mirror of
https://github.com/marzer/tomlplusplus.git
synced 2025-02-23 09:41:12 +00:00
new file: .circleci/config.yml
new file: .editorconfig new file: .gitattributes new file: .gitignore new file: .gitmodules new file: LICENSE new file: README.md new file: examples/example.cpp new file: examples/example.toml new file: examples/meson.build new file: include/toml++/toml.h new file: include/toml++/toml_array.h new file: include/toml++/toml_common.h new file: include/toml++/toml_formatter.h new file: include/toml++/toml_node.h new file: include/toml++/toml_node_view.h new file: include/toml++/toml_parser.h new file: include/toml++/toml_table.h new file: include/toml++/toml_utf8.h new file: include/toml++/toml_utf8_generated.h new file: include/toml++/toml_value.h new file: meson.build new file: python/ci_single_header_check.py new file: python/generate_single_header.py new file: python/generate_unicode_functions.py new file: tests/catch2 new file: tests/catch2.h new file: tests/lifetimes.cpp new file: tests/main.cpp new file: tests/meson.build new file: tests/parsing_arrays.cpp new file: tests/parsing_booleans.cpp new file: tests/parsing_comments.cpp new file: tests/parsing_dates_and_times.cpp new file: tests/parsing_floats.cpp new file: tests/parsing_integers.cpp new file: tests/parsing_key_value_pairs.cpp new file: tests/parsing_spec_example.cpp new file: tests/parsing_strings.cpp new file: tests/parsing_tables.cpp new file: tests/tests.cpp new file: tests/tests.h new file: toml.hpp new file: vs/.runsettings new file: vs/example.vcxproj new file: vs/test_char.vcxproj new file: vs/test_char8.vcxproj new file: vs/test_char8_noexcept.vcxproj new file: vs/test_char_noexcept.vcxproj new file: vs/test_strict_char.vcxproj new file: vs/test_strict_char8.vcxproj new file: vs/test_strict_char8_noexcept.vcxproj new file: vs/test_strict_char_noexcept.vcxproj new file: vs/toml++.natvis new file: vs/toml++.props new file: vs/toml++.sln new file: vs/toml++.vcxproj new file: vs/toml++.vcxproj.filters
This commit is contained in:
commit
930bf0ad58
45
.circleci/config.yml
Normal file
45
.circleci/config.yml
Normal file
@ -0,0 +1,45 @@
|
||||
version: 2.1
|
||||
|
||||
jobs:
|
||||
linux_build:
|
||||
docker:
|
||||
- image: "debian:bullseye"
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
name: Installing python
|
||||
command: |
|
||||
apt-get -qq update && apt-get install -y python3
|
||||
- run:
|
||||
name: Checking toml.hpp
|
||||
command: |
|
||||
cd python && python3 ci_single_header_check.py
|
||||
- run:
|
||||
name: Installing applications
|
||||
command: |
|
||||
apt-get -qq update && apt-get install -y git clang-9 g++-9 python3-pip ninja-build
|
||||
pip3 install meson
|
||||
- run:
|
||||
name: Pulling submodules
|
||||
command: |
|
||||
git submodule update --init --recursive
|
||||
- run:
|
||||
name: Building with clang
|
||||
command: |
|
||||
CXX=clang++-9 meson build-clang
|
||||
cd build-clang && ninja -v -j 4
|
||||
- run:
|
||||
name: Building with gcc
|
||||
command: |
|
||||
CXX=g++-9 meson build-gcc
|
||||
cd build-gcc && ninja -v -j 4
|
||||
- run:
|
||||
name: Running tests
|
||||
command: |
|
||||
cd build-clang && ninja test && cd ../build-gcc && ninja test
|
||||
|
||||
workflows:
|
||||
version: 2
|
||||
build:
|
||||
jobs:
|
||||
- linux_build
|
17
.editorconfig
Normal file
17
.editorconfig
Normal file
@ -0,0 +1,17 @@
|
||||
root = true
|
||||
|
||||
[*]
|
||||
insert_final_newline = true
|
||||
indent_style = tab
|
||||
indent_size = 4
|
||||
tab_width = 4
|
||||
|
||||
[*.{gitattributes, yml}]
|
||||
indent_style = space
|
||||
|
||||
[*.{c, cpp, cxx, h, hpp, hxx, inl, toml, xml, py, natvis, props, build, yml}]
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.{c, cpp, cxx, h, hpp, hxx, inl, py, md}]
|
||||
end_of_line = lf
|
17
.gitattributes
vendored
Normal file
17
.gitattributes
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
* text=auto encoding=UTF-8
|
||||
*.c text encoding=UTF-8 eol=lf
|
||||
*.cpp text encoding=UTF-8 eol=lf
|
||||
*.cxx text encoding=UTF-8 eol=lf
|
||||
*.h text encoding=UTF-8 eol=lf
|
||||
*.hpp text encoding=UTF-8 eol=lf
|
||||
*.hxx text encoding=UTF-8 eol=lf
|
||||
*.inl text encoding=UTF-8 eol=lf
|
||||
*.toml text=auto encoding=UTF-8
|
||||
*.xml text=auto encoding=UTF-8
|
||||
*.py text encoding=UTF-8 eol=lf
|
||||
*.natvis text encoding=UTF-8 eol=crlf
|
||||
*.props text encoding=UTF-8 eol=crlf
|
||||
*.vcxproj text encoding=UTF-8 eol=crlf
|
||||
*.sln text encoding=UTF-8-BOM eol=crlf
|
||||
*.runsettings text encoding=UTF-8 eol=crlf
|
||||
*.md text encoding=UTF-8 eol=lf
|
359
.gitignore
vendored
Normal file
359
.gitignore
vendored
Normal file
@ -0,0 +1,359 @@
|
||||
UnicodeData.txt
|
||||
meson-info/
|
||||
meson-logs/
|
||||
meson-private/
|
||||
*.o
|
||||
.ninja_*
|
||||
build.ninja
|
||||
compile_commands.json
|
||||
[Bb]uild*/
|
||||
|
||||
## Ignore Visual Studio temporary files, build results, and
|
||||
## files generated by popular Visual Studio add-ons.
|
||||
##
|
||||
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
|
||||
|
||||
# User-specific files
|
||||
*.suo
|
||||
*.user
|
||||
*.userosscache
|
||||
*.sln.docstates
|
||||
|
||||
# User-specific files (MonoDevelop/Xamarin Studio)
|
||||
*.userprefs
|
||||
|
||||
# Build results
|
||||
[Dd]ebug/
|
||||
[Dd]ebugPublic/
|
||||
[Rr]elease/
|
||||
[Rr]eleases/
|
||||
x64/
|
||||
x86/
|
||||
bld/
|
||||
[Bb]in/
|
||||
[Oo]bj/
|
||||
[Ll]og/
|
||||
|
||||
# Visual Studio 2015/2017 cache/options directory
|
||||
.vs/
|
||||
.vscode/
|
||||
# Uncomment if you have tasks that create the project's static files in wwwroot
|
||||
#wwwroot/
|
||||
|
||||
# Visual Studio 2017 auto generated files
|
||||
Generated\ Files/
|
||||
|
||||
# MSTest test Results
|
||||
[Tt]est[Rr]esult*/
|
||||
[Bb]uild[Ll]og.*
|
||||
|
||||
# NUNIT
|
||||
*.VisualState.xml
|
||||
TestResult.xml
|
||||
|
||||
# Build Results of an ATL Project
|
||||
[Dd]ebugPS/
|
||||
[Rr]eleasePS/
|
||||
dlldata.c
|
||||
|
||||
# Benchmark Results
|
||||
BenchmarkDotNet.Artifacts/
|
||||
|
||||
# .NET Core
|
||||
project.lock.json
|
||||
project.fragment.lock.json
|
||||
artifacts/
|
||||
**/Properties/launchSettings.json
|
||||
|
||||
# StyleCop
|
||||
StyleCopReport.xml
|
||||
|
||||
# Files built by Visual Studio
|
||||
*_i.c
|
||||
*_p.c
|
||||
*_i.h
|
||||
*.ilk
|
||||
*.meta
|
||||
*.obj
|
||||
*.iobj
|
||||
*.pch
|
||||
*.pdb
|
||||
*.ipdb
|
||||
*.pgc
|
||||
*.pgd
|
||||
*.rsp
|
||||
*.sbr
|
||||
*.tlb
|
||||
*.tli
|
||||
*.tlh
|
||||
*.tmp
|
||||
*.tmp_proj
|
||||
*.log
|
||||
*.vspscc
|
||||
*.vssscc
|
||||
.builds
|
||||
*.pidb
|
||||
*.svclog
|
||||
*.scc
|
||||
*.Designer.cs.dll
|
||||
unsuccessfulbuild
|
||||
*.lastbuildstate
|
||||
*.psess
|
||||
*.vsp
|
||||
*.vspx
|
||||
*.tlog
|
||||
|
||||
# Chutzpah Test files
|
||||
_Chutzpah*
|
||||
|
||||
# Visual C++ cache files
|
||||
ipch/
|
||||
*.aps
|
||||
*.ncb
|
||||
*.opendb
|
||||
*.opensdf
|
||||
*.sdf
|
||||
*.cachefile
|
||||
*.VC.db
|
||||
*.VC.VC.opendb
|
||||
|
||||
# Visual Studio profiler
|
||||
*.psess
|
||||
*.vsp
|
||||
*.vspx
|
||||
*.sap
|
||||
|
||||
# Visual Studio Trace Files
|
||||
*.e2e
|
||||
|
||||
# TFS 2012 Local Workspace
|
||||
$tf/
|
||||
|
||||
# Guidance Automation Toolkit
|
||||
*.gpState
|
||||
|
||||
# ReSharper is a .NET coding add-in
|
||||
_ReSharper*/
|
||||
*.[Rr]e[Ss]harper
|
||||
*.DotSettings.user
|
||||
|
||||
# JustCode is a .NET coding add-in
|
||||
.JustCode
|
||||
|
||||
# TeamCity is a build add-in
|
||||
_TeamCity*
|
||||
|
||||
# DotCover is a Code Coverage Tool
|
||||
*.dotCover
|
||||
|
||||
# AxoCover is a Code Coverage Tool
|
||||
.axoCover/*
|
||||
!.axoCover/settings.json
|
||||
|
||||
# Visual Studio code coverage results
|
||||
*.coverage
|
||||
*.coveragexml
|
||||
|
||||
# NCrunch
|
||||
_NCrunch_*
|
||||
.*crunch*.local.xml
|
||||
nCrunchTemp_*
|
||||
|
||||
# MightyMoose
|
||||
*.mm.*
|
||||
AutoTest.Net/
|
||||
|
||||
# Web workbench (sass)
|
||||
.sass-cache/
|
||||
|
||||
# Installshield output folder
|
||||
[Ee]xpress/
|
||||
|
||||
# DocProject is a documentation generator add-in
|
||||
DocProject/buildhelp/
|
||||
DocProject/Help/*.HxT
|
||||
DocProject/Help/*.HxC
|
||||
DocProject/Help/*.hhc
|
||||
DocProject/Help/*.hhk
|
||||
DocProject/Help/*.hhp
|
||||
DocProject/Help/Html2
|
||||
DocProject/Help/html
|
||||
|
||||
# Click-Once directory
|
||||
publish/
|
||||
|
||||
# Publish Web Output
|
||||
*.[Pp]ublish.xml
|
||||
*.azurePubxml
|
||||
# Note: Comment the next line if you want to checkin your web deploy settings,
|
||||
# but database connection strings (with potential passwords) will be unencrypted
|
||||
*.pubxml
|
||||
*.publishproj
|
||||
|
||||
# Microsoft Azure Web App publish settings. Comment the next line if you want to
|
||||
# checkin your Azure Web App publish settings, but sensitive information contained
|
||||
# in these scripts will be unencrypted
|
||||
PublishScripts/
|
||||
|
||||
# NuGet Packages
|
||||
*.nupkg
|
||||
# The packages folder can be ignored because of Package Restore
|
||||
**/[Pp]ackages/*
|
||||
# except build/, which is used as an MSBuild target.
|
||||
!**/[Pp]ackages/build/
|
||||
# Uncomment if necessary however generally it will be regenerated when needed
|
||||
#!**/[Pp]ackages/repositories.config
|
||||
# NuGet v3's project.json files produces more ignorable files
|
||||
*.nuget.props
|
||||
*.nuget.targets
|
||||
|
||||
# Microsoft Azure Build Output
|
||||
csx/
|
||||
*.build.csdef
|
||||
|
||||
# Microsoft Azure Emulator
|
||||
ecf/
|
||||
rcf/
|
||||
|
||||
# Windows Store app package directories and files
|
||||
AppPackages/
|
||||
BundleArtifacts/
|
||||
Package.StoreAssociation.xml
|
||||
_pkginfo.txt
|
||||
*.appx
|
||||
|
||||
# Visual Studio cache files
|
||||
# files ending in .cache can be ignored
|
||||
*.[Cc]ache
|
||||
# but keep track of directories ending in .cache
|
||||
!*.[Cc]ache/
|
||||
|
||||
# Others
|
||||
ClientBin/
|
||||
~$*
|
||||
*~
|
||||
*.dbmdl
|
||||
*.dbproj.schemaview
|
||||
*.jfm
|
||||
*.pfx
|
||||
*.publishsettings
|
||||
orleans.codegen.cs
|
||||
|
||||
# Including strong name files can present a security risk
|
||||
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
|
||||
#*.snk
|
||||
|
||||
# Since there are multiple workflows, uncomment next line to ignore bower_components
|
||||
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
|
||||
#bower_components/
|
||||
|
||||
# RIA/Silverlight projects
|
||||
Generated_Code/
|
||||
|
||||
# Backup & report files from converting an old project file
|
||||
# to a newer Visual Studio version. Backup files are not needed,
|
||||
# because we have git ;-)
|
||||
_UpgradeReport_Files/
|
||||
Backup*/
|
||||
UpgradeLog*.XML
|
||||
UpgradeLog*.htm
|
||||
ServiceFabricBackup/
|
||||
*.rptproj.bak
|
||||
|
||||
# SQL Server files
|
||||
*.mdf
|
||||
*.ldf
|
||||
*.ndf
|
||||
|
||||
# Business Intelligence projects
|
||||
*.rdl.data
|
||||
*.bim.layout
|
||||
*.bim_*.settings
|
||||
*.rptproj.rsuser
|
||||
|
||||
# Microsoft Fakes
|
||||
FakesAssemblies/
|
||||
|
||||
# GhostDoc plugin setting file
|
||||
*.GhostDoc.xml
|
||||
|
||||
# Node.js Tools for Visual Studio
|
||||
.ntvs_analysis.dat
|
||||
node_modules/
|
||||
|
||||
# Visual Studio 6 build log
|
||||
*.plg
|
||||
|
||||
# Visual Studio 6 workspace options file
|
||||
*.opt
|
||||
|
||||
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
|
||||
*.vbw
|
||||
|
||||
# Visual Studio LightSwitch build output
|
||||
**/*.HTMLClient/GeneratedArtifacts
|
||||
**/*.DesktopClient/GeneratedArtifacts
|
||||
**/*.DesktopClient/ModelManifest.xml
|
||||
**/*.Server/GeneratedArtifacts
|
||||
**/*.Server/ModelManifest.xml
|
||||
_Pvt_Extensions
|
||||
|
||||
# Paket dependency manager
|
||||
.paket/paket.exe
|
||||
paket-files/
|
||||
|
||||
# FAKE - F# Make
|
||||
.fake/
|
||||
|
||||
# JetBrains Rider
|
||||
.idea/
|
||||
*.sln.iml
|
||||
|
||||
# CodeRush
|
||||
.cr/
|
||||
|
||||
# Python Tools for Visual Studio (PTVS)
|
||||
__pycache__/
|
||||
*.pyc
|
||||
|
||||
# Cake - Uncomment if you are using it
|
||||
# tools/**
|
||||
# !tools/packages.config
|
||||
|
||||
# Tabs Studio
|
||||
*.tss
|
||||
|
||||
# Telerik's JustMock configuration file
|
||||
*.jmconfig
|
||||
|
||||
# BizTalk build output
|
||||
*.btp.cs
|
||||
*.btm.cs
|
||||
*.odx.cs
|
||||
*.xsd.cs
|
||||
|
||||
# OpenCover UI analysis results
|
||||
OpenCover/
|
||||
|
||||
# Azure Stream Analytics local run output
|
||||
ASALocalRun/
|
||||
|
||||
# MSBuild Binary and Structured Log
|
||||
*.binlog
|
||||
|
||||
# NVidia Nsight GPU debugger configuration file
|
||||
*.nvuser
|
||||
|
||||
# MFractors (Xamarin productivity tool) working folder
|
||||
.mfractor/
|
||||
|
||||
# Windows
|
||||
Thumbs.db
|
||||
ehthumbs.db
|
||||
Desktop.ini
|
||||
$RECYCLE.BIN/
|
||||
*.cab
|
||||
*.msi
|
||||
*.msm
|
||||
*.msp
|
||||
*.lnk
|
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
[submodule "tests/catch2"]
|
||||
path = tests/catch2
|
||||
url = https://github.com/catchorg/Catch2.git
|
18
LICENSE
Normal file
18
LICENSE
Normal file
@ -0,0 +1,18 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 Mark Gillard
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
|
||||
associated documentation files (the "Software"), to deal in the Software without restriction,
|
||||
including without limitation the rights to use, copy, modify, merge, publish, distribute,
|
||||
sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or
|
||||
substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
|
||||
NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
142
README.md
Normal file
142
README.md
Normal file
@ -0,0 +1,142 @@
|
||||
# toml++ (tomlplusplus)
|
||||
Header-only [TOML v0.5.0] parsing lib for C++17 and later.
|
||||
|
||||
[](https://circleci.com/gh/marzer/tomlplusplus)
|
||||
|
||||
<br>
|
||||
|
||||
# Usage
|
||||
`toml++` comes in two flavours: Regular and Single-header.
|
||||
|
||||
### Regular mode
|
||||
1. Add `tomlplusplus/include` to your include paths
|
||||
2. `#include <toml++/toml.h>`
|
||||
|
||||
### Single-header mode
|
||||
1. Drop `toml.hpp` somewhere in your source tree
|
||||
2. There is no step two
|
||||
|
||||
The API is the same regardless of how you consume the library. You'll find code examples in
|
||||
the `examples` directory.
|
||||
|
||||
<br>
|
||||
|
||||
# Configuration
|
||||
A number of configurable options are exposed in the form of preprocessor macros. Most likely you
|
||||
won't need to mess with these at all, but in the event you do, set your overrides prior to including
|
||||
toml++.
|
||||
|
||||
| Option | Type | Default | Description |
|
||||
|----------------------------|:--------------:|-----------------------------------|-----------------------------------------------------------------------------------------------|
|
||||
| `TOML_ASSERT(expr)` | function macro | `assert(expr)`<br>(or undefined) | Sets the assert function used by the library. |
|
||||
| `TOML_CHAR_8_STRINGS` | boolean | `0` | Uses C++20 [char8_t]-based strings as the toml string data type. |
|
||||
| `TOML_CONFIG_HEADER` | string literal | undefined | Includes the given header file before the rest of the library. |
|
||||
| `TOML_UNDEF_MACROS` | boolean | `1` | `#undefs` the library's internal macros at the end of the header. |
|
||||
| `TOML_UNRELEASED_FEATURES` | boolean | `1` | Enables support for [unreleased TOML language features] not yet part of a [numbered version]. |
|
||||
|
||||
<br>
|
||||
|
||||
# TOML Language Support
|
||||
At any given time `toml++` aims to implement whatever the [numbered version] of TOML is, with the
|
||||
addition of unreleased features from the [TOML master] and some sane cherry-picks from the
|
||||
[TOML issues list] where the discussion strongly indicates inclusion in a near-future release.
|
||||
|
||||
The library advertises the most recent numbered language version it fully supports via the preprocessor
|
||||
defines `TOML_LANG_MAJOR`, `TOML_LANG_MINOR` and `TOML_LANG_REVISION`.
|
||||
|
||||
### **🔸Unreleased features:**
|
||||
- [#356]: Allow leading zeros in the exponent part of a float
|
||||
- [#516]: Allow newlines and trailing commas in inline tables
|
||||
- [#562]: Allow hex floatingpoint values
|
||||
- [#567]: Clarify that control characters are not permitted in comments
|
||||
- [#571]: Allow raw tabs inside strings
|
||||
- [#622]: Add short escaping alias `\s` for space (`\u0020`)
|
||||
- [#644]: Support `+` in key names
|
||||
- [#665]: Make arrays heterogeneous
|
||||
- [#671]: Local time of day format should support `09:30` as opposed to `09:30:00`
|
||||
- [#687]: Relax bare key restrictions to allow additional unicode characters
|
||||
|
||||
_These can be disabled (and thus strict [TOML v0.5.0] compliance enforced) by specifying
|
||||
`TOML_UNRELEASED_FEATURES = 0` (see [Configuration](#Configuration))._
|
||||
|
||||
### **🔹[v0.5.0](https://github.com/toml-lang/toml/releases/tag/v0.5.0) and earlier:**
|
||||
- All features as of `<< release date >>`.
|
||||
|
||||
<br>
|
||||
|
||||
# Contributing
|
||||
Contributions are welcome, either by [reporting issues](https://github.com/marzer/tomlplusplus/issues)
|
||||
or submitting pull requests. If you wish to submit a PR, please be aware that:
|
||||
- The single-header file `toml.hpp` is generated by a script; make your changes in the files in
|
||||
`include`, **not** in `toml.hpp`.
|
||||
- Your changes should compile warning-free on at least gcc 8.3.0, clang 8.0, and MSVC 19.2X
|
||||
(Visual Studio 2019).
|
||||
- You should regenerate the single-header file as part of your PR (a CI check will fail if you don't).
|
||||
|
||||
### Regenerating toml.hpp
|
||||
1. Make your changes as necessary
|
||||
2. If you've added a new header file that isn't going to be transitively included by one of the
|
||||
others, add an include directive to `include/toml++/toml.h`
|
||||
3. Run `python/generate_single_header.py`
|
||||
|
||||
### Building and testing
|
||||
Testing is done using [catch2], included in the respository as a submodule under `tests/catch2`.
|
||||
The first time you want to begin testing you'll need to ensure submodules have been fetched:
|
||||
```bash
|
||||
git submodule update --init --recursive
|
||||
```
|
||||
|
||||
#### Windows
|
||||
|
||||
Install [Visual Studio 2019] and [Test Adapter for Catch2], then open `vs/toml++.sln` and build the
|
||||
projects in the `tests` solution folder. Visual Studio's Test Explorer should pick these up and
|
||||
allow you to run the tests directly.
|
||||
|
||||
If test discovery fails, you can usually fix it by clicking enabling
|
||||
`Auto Detect runsettings Files` (settings gear icon > `Configure Run Settings`).
|
||||
|
||||
#### Linux
|
||||
Install [meson] and [ninja] if necessary, then test with both gcc and clang:
|
||||
```bash
|
||||
CXX=g++ meson build-gcc
|
||||
CXX=clang++ meson build-clang
|
||||
cd build-gcc
|
||||
ninja && ninja test
|
||||
cd ../build-clang
|
||||
ninja && ninja test
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
# License and Attribution
|
||||
|
||||
`toml++` is licensed under the terms of the MIT license - See [LICENSE].
|
||||
|
||||
UTF-8 decoding is performed using a state machine based on Bjoern Hoehrmann's '[Flexible and Economical UTF-8 Decoder]',
|
||||
which is itself subject to the terms of the MIT license. The license text is included in the
|
||||
[relevant part](https://github.com/marzer/tomlplusplus/blob/master/include/toml%2B%2B/toml_utf8.h)
|
||||
of the toml++ source.
|
||||
|
||||
[unreleased TOML language features]: https://github.com/marzer/tomlplusplus#unreleased-features
|
||||
[numbered version]: https://github.com/toml-lang/toml/releases
|
||||
[char8_t]: https://en.cppreference.com/w/cpp/keyword/char8_t
|
||||
[TOML master]: https://github.com/toml-lang/toml/blob/master/README.md
|
||||
[TOML issues list]: https://github.com/toml-lang/toml/issues
|
||||
[TOML v0.5.0]: https://github.com/toml-lang/toml/blob/master/versions/en/toml-v0.5.0.md
|
||||
[LICENSE]: https://github.com/marzer/tomlplusplus/blob/master/LICENSE
|
||||
[Flexible and Economical UTF-8 Decoder]: http://bjoern.hoehrmann.de/utf-8/decoder/dfa/
|
||||
[meson]: https://mesonbuild.com/Getting-meson.html
|
||||
[ninja]: https://github.com/ninja-build/ninja/wiki/Pre-built-Ninja-packages
|
||||
[catch2]: https://github.com/catchorg/Catch2
|
||||
[Test Adapter for Catch2]: https://marketplace.visualstudio.com/items?itemName=JohnnyHendriks.ext01
|
||||
[Visual Studio 2019]: https://visualstudio.microsoft.com/vs/
|
||||
[#356]: https://github.com/toml-lang/toml/issues/356
|
||||
[#516]: https://github.com/toml-lang/toml/issues/516
|
||||
[#562]: https://github.com/toml-lang/toml/issues/562
|
||||
[#567]: https://github.com/toml-lang/toml/issues/567
|
||||
[#571]: https://github.com/toml-lang/toml/issues/571
|
||||
[#622]: https://github.com/toml-lang/toml/issues/622
|
||||
[#644]: https://github.com/toml-lang/toml/issues/644
|
||||
[#665]: https://github.com/toml-lang/toml/issues/665
|
||||
[#671]: https://github.com/toml-lang/toml/issues/671
|
||||
[#687]: https://github.com/toml-lang/toml/issues/687
|
45
examples/example.cpp
Normal file
45
examples/example.cpp
Normal file
@ -0,0 +1,45 @@
|
||||
#include <toml++/toml.h>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#ifdef _WIN32
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <Windows.h>
|
||||
#endif
|
||||
using namespace std::string_view_literals;
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
SetConsoleOutputCP(65001);
|
||||
#endif
|
||||
|
||||
auto path = std::string{ argc > 1 ? argv[1] : "example.toml" };
|
||||
|
||||
auto file = std::ifstream{ path };
|
||||
if (!file)
|
||||
{
|
||||
std::cerr << "The file '"sv << path << "' could not be opened for reading."sv << std::endl;
|
||||
return 1;
|
||||
}
|
||||
try
|
||||
{
|
||||
//const auto table = toml::parse(file); //works but parse_errors would not include the source path
|
||||
|
||||
const auto table = toml::parse(file, std::move(path));
|
||||
|
||||
std::cout << table << std::endl;
|
||||
}
|
||||
catch (const toml::parse_error& err)
|
||||
{
|
||||
std::cerr
|
||||
<< "Error parsing file '"sv << *err.where().path
|
||||
<< "' at line "sv << err.where().begin.line
|
||||
<< ", column "sv << err.where().begin.column
|
||||
<< ":\n"sv << err.what()
|
||||
<< std::endl;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
94
examples/example.toml
Normal file
94
examples/example.toml
Normal file
@ -0,0 +1,94 @@
|
||||
# This is a TOML document. Boom.
|
||||
|
||||
title = "TOML Example"
|
||||
|
||||
# plain signed integers
|
||||
int1 = -9223372036854775808
|
||||
int2 = 9223372036854775807
|
||||
|
||||
# floats
|
||||
flt1 = 0.00000000001
|
||||
flt2 = 1e-11
|
||||
flt3 = 11.0
|
||||
|
||||
# hexadecimal with prefix `0x`
|
||||
hex1 = 0xDEADBEEF
|
||||
hex2 = 0xdeadbeef
|
||||
hex3 = 0xdead_beef
|
||||
|
||||
# octal with prefix `0o`
|
||||
oct1 = 0o01234567
|
||||
oct2 = 0o755 # useful for Unix file permissions
|
||||
|
||||
# binary with prefix `0b`
|
||||
bin1 = 0b11010110 # 214
|
||||
|
||||
# local dates and times
|
||||
tim1 = 07:32:00
|
||||
tim2 = 00:32:00.100000000
|
||||
dat1 = 1979-05-27
|
||||
|
||||
# offset date-times
|
||||
odt1 = 1979-05-27T07:32:00Z
|
||||
odt2 = 1979-05-27T00:32:00-07:00
|
||||
odt3 = 1979-05-27T00:32:00.999999-07:00
|
||||
|
||||
# unicode
|
||||
kosme = "κόσμε"
|
||||
|
||||
arr = [ 'this', 'is', 'a', 'long', 'array', 'with', 16, 'elements.', 'it', 'should', 'be', 'printed', 'as', 'a', 'multiline', 'array.']
|
||||
|
||||
tab = { this = 'is', an = 'inline', table = 'yay'}
|
||||
|
||||
dotted.keys.are = "supported"
|
||||
dotted.and = "implemented as tables"
|
||||
|
||||
[owner]
|
||||
name = "Mark Gillard"
|
||||
dob = 1987-03-16 10:20:00+09:30
|
||||
|
||||
[[owner.pets]]
|
||||
name = "Brian"
|
||||
species = "cat"
|
||||
|
||||
[[owner.pets]]
|
||||
name = "Skippy"
|
||||
species = "kangaroo"
|
||||
|
||||
[database]
|
||||
server = "192.168.1.1"
|
||||
ports = [ 8001, 8001, 8002 ]
|
||||
connection_max = 5000
|
||||
enabled = true
|
||||
|
||||
[servers]
|
||||
|
||||
# You can indent as you please. Tabs or spaces. TOML don't care.
|
||||
[servers.alpha]
|
||||
ip = "10.0.0.1"
|
||||
dc = "eqdc10"
|
||||
|
||||
[servers.beta]
|
||||
ip = "10.0.0.2"
|
||||
dc = "eqdc10"
|
||||
country = "中国" # This should be parsed as UTF-8
|
||||
|
||||
[clients]
|
||||
data = [ ["gamma", "delta"], [1, 2] ] # just an update to make sure parsers support it
|
||||
|
||||
# Line breaks are OK when inside arrays
|
||||
hosts = [
|
||||
"alpha",
|
||||
"omega"
|
||||
]
|
||||
|
||||
# Products
|
||||
|
||||
[[products]]
|
||||
name = "Hammer"
|
||||
sku = 738594937
|
||||
|
||||
[[products]]
|
||||
name = "Nail"
|
||||
sku = 284758393
|
||||
color = "gray"
|
5
examples/meson.build
Normal file
5
examples/meson.build
Normal file
@ -0,0 +1,5 @@
|
||||
example = executable(
|
||||
'example',
|
||||
[ 'example.cpp' ],
|
||||
include_directories : inc
|
||||
)
|
49
include/toml++/toml.h
Normal file
49
include/toml++/toml.h
Normal file
@ -0,0 +1,49 @@
|
||||
#pragma once
|
||||
|
||||
//# Note: most of these would be included transitively but
|
||||
//# they're listed explicitly here because this file
|
||||
//# is used as the source for generate_single_header.py.
|
||||
|
||||
#include "toml_common.h"
|
||||
#include "toml_node.h"
|
||||
#include "toml_table.h"
|
||||
#include "toml_array.h"
|
||||
#include "toml_value.h"
|
||||
#include "toml_utf8.h"
|
||||
#include "toml_node_view.h"
|
||||
#include "toml_parser.h"
|
||||
#include "toml_formatter.h"
|
||||
|
||||
//macro hygiene
|
||||
#if TOML_UNDEF_MACROS
|
||||
#undef TOML_EXCEPTIONS
|
||||
#undef TOML_USE_STREAMS_FOR_FLOATS
|
||||
#undef TOML_PUSH_WARNINGS
|
||||
#undef TOML_DISABLE_SWITCH_WARNING
|
||||
#undef TOML_DISABLE_FIELD_INIT_WARNING
|
||||
#undef TOML_DISABLE_VAR_INIT_WARNING
|
||||
#undef TOML_DISABLE_ALL_WARNINGS
|
||||
#undef TOML_POP_WARNINGS
|
||||
#undef TOML_ALWAYS_INLINE
|
||||
#undef TOML_ASSUME
|
||||
#undef TOML_UNREACHABLE
|
||||
#undef TOML_INTERFACE
|
||||
#undef TOML_EMPTY_BASES
|
||||
#undef TOML_CPP
|
||||
#undef TOML_CONDITIONAL_NOEXCEPT
|
||||
#undef TOML_MAY_THROW
|
||||
#undef TOML_NO_DEFAULT_CASE
|
||||
#undef TOML_CONSTEVAL
|
||||
#undef TOML_LIKELY
|
||||
#undef TOML_UNLIKELY
|
||||
#undef TOML_NO_UNIQUE_ADDRESS
|
||||
#undef TOML_NODISCARD_CTOR
|
||||
#undef TOML_LANG_MAKE_VERSION
|
||||
#undef TOML_LANG_EFFECTIVE_VERSION
|
||||
#undef TOML_LANG_HIGHER_THAN
|
||||
#undef TOML_LANG_AT_LEAST
|
||||
#undef TOML_LANG_EXACTLY
|
||||
#undef TOML_STRING_PREFIX_1
|
||||
#undef TOML_STRING_PREFIX
|
||||
#undef TOML_UNDEF_MACROS
|
||||
#endif
|
83
include/toml++/toml_array.h
Normal file
83
include/toml++/toml_array.h
Normal file
@ -0,0 +1,83 @@
|
||||
#pragma once
|
||||
#include "toml_node.h"
|
||||
|
||||
namespace toml
|
||||
{
|
||||
class array final
|
||||
: public node
|
||||
{
|
||||
private:
|
||||
friend class impl::parser;
|
||||
friend class default_formatter;
|
||||
std::vector<std::unique_ptr<node>> values;
|
||||
|
||||
public:
|
||||
|
||||
TOML_NODISCARD_CTOR
|
||||
array() noexcept = default;
|
||||
|
||||
TOML_NODISCARD_CTOR
|
||||
array(array&& other) noexcept
|
||||
: node{ std::move(other) },
|
||||
values{ std::move(other.values) }
|
||||
{}
|
||||
|
||||
array& operator= (array&& rhs) noexcept
|
||||
{
|
||||
node::operator=(std::move(rhs));
|
||||
values = std::move(rhs.values);
|
||||
return *this;
|
||||
}
|
||||
|
||||
[[nodiscard]] bool is_array() const noexcept override { return true; }
|
||||
|
||||
[[nodiscard]] bool is_array_of_tables() const noexcept override
|
||||
{
|
||||
if (values.empty())
|
||||
return false;
|
||||
|
||||
for (auto& val : values)
|
||||
if (!val->is_table())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
bool is_homogeneous() const noexcept
|
||||
{
|
||||
if (values.size() <= 1_sz)
|
||||
return true;
|
||||
|
||||
const auto type = values[0]->type();
|
||||
for (size_t i = 1; i < values.size(); i++)
|
||||
if (values[i]->type() != type)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
[[nodiscard]] array* as_array() noexcept override { return this; }
|
||||
[[nodiscard]] const array* as_array() const noexcept override { return this; }
|
||||
|
||||
[[nodiscard]] node_type type() const noexcept override { return node_type::array; }
|
||||
|
||||
[[nodiscard]] size_t size() const noexcept { return values.size(); }
|
||||
|
||||
[[nodiscard]] node* get(size_t index) noexcept { return values[index].get(); }
|
||||
[[nodiscard]] const node* get(size_t index) const noexcept { return values[index].get(); }
|
||||
|
||||
template <typename T>
|
||||
[[nodiscard]]
|
||||
node_of<T>* get_as(size_t index) noexcept
|
||||
{
|
||||
return get(index)->as<T>();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
[[nodiscard]]
|
||||
const node_of<T>* get_as(size_t index) const noexcept
|
||||
{
|
||||
return get(index)->as<T>();
|
||||
}
|
||||
};
|
||||
}
|
623
include/toml++/toml_common.h
Normal file
623
include/toml++/toml_common.h
Normal file
@ -0,0 +1,623 @@
|
||||
#pragma once
|
||||
|
||||
////////// CONFIGURATION
|
||||
// clang-format off
|
||||
|
||||
#ifdef TOML_CONFIG_HEADER
|
||||
#include TOML_CONFIG_HEADER
|
||||
#undef TOML_CONFIG_HEADER
|
||||
#endif
|
||||
|
||||
#ifndef TOML_CHAR_8_STRINGS
|
||||
#define TOML_CHAR_8_STRINGS 0
|
||||
#endif
|
||||
|
||||
#ifndef TOML_UNRELEASED_FEATURES
|
||||
#define TOML_UNRELEASED_FEATURES 1
|
||||
#endif
|
||||
|
||||
#ifndef TOML_ASSERT
|
||||
#ifdef assert
|
||||
#define TOML_ASSERT(expr) assert(expr)
|
||||
#else
|
||||
#define TOML_ASSERT(expr) (void)0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef TOML_UNDEF_MACROS
|
||||
#define TOML_UNDEF_MACROS 1
|
||||
#endif
|
||||
|
||||
////////// COMPILER & ENVIRONMENT STUFF
|
||||
|
||||
#ifndef __cplusplus
|
||||
#error toml++ is a C++ library.
|
||||
#endif
|
||||
|
||||
#ifdef __clang__
|
||||
|
||||
#ifndef __cpp_exceptions
|
||||
#define TOML_EXCEPTIONS 0
|
||||
#endif
|
||||
|
||||
#define TOML_PUSH_WARNINGS _Pragma("clang diagnostic push")
|
||||
#define TOML_DISABLE_SWITCH_WARNING _Pragma("clang diagnostic ignored \"-Wswitch\"")
|
||||
#define TOML_DISABLE_FIELD_INIT_WARNING _Pragma("clang diagnostic ignored \"-Wmissing-field-initializers\"")
|
||||
#define TOML_DISABLE_ALL_WARNINGS _Pragma("clang diagnostic ignored \"-Weverything\"")
|
||||
#define TOML_POP_WARNINGS _Pragma("clang diagnostic pop")
|
||||
#define TOML_ALWAYS_INLINE __attribute__((__always_inline__)) inline
|
||||
#define TOML_ASSUME(cond) __builtin_assume(cond)
|
||||
#define TOML_UNREACHABLE __builtin_unreachable()
|
||||
|
||||
#if __has_declspec_attribute(novtable)
|
||||
#define TOML_INTERFACE __declspec(novtable)
|
||||
#endif
|
||||
|
||||
#if __has_declspec_attribute(empty_bases)
|
||||
#define TOML_EMPTY_BASES __declspec(empty_bases)
|
||||
#endif
|
||||
|
||||
//floating-point from_chars and to_chars are not implemented in any version of clang as of 1/1/2020
|
||||
#ifndef TOML_USE_STREAMS_FOR_FLOATS
|
||||
#define TOML_USE_STREAMS_FOR_FLOATS 1
|
||||
#endif
|
||||
|
||||
#elif defined(_MSC_VER)
|
||||
|
||||
#ifndef _CPPUNWIND
|
||||
#define TOML_EXCEPTIONS 0
|
||||
#endif
|
||||
|
||||
#define TOML_CPP_VERSION _MSVC_LANG
|
||||
#define TOML_PUSH_WARNINGS __pragma(warning(push))
|
||||
#define TOML_DISABLE_SWITCH_WARNING __pragma(warning(disable: 4063))
|
||||
#define TOML_DISABLE_ALL_WARNINGS __pragma(warning(pop)) \
|
||||
__pragma(warning(push, 0))
|
||||
#define TOML_POP_WARNINGS __pragma(warning(pop))
|
||||
#define TOML_ALWAYS_INLINE __forceinline
|
||||
#define TOML_ASSUME(cond) __assume(cond)
|
||||
#define TOML_UNREACHABLE __assume(0)
|
||||
#define TOML_INTERFACE __declspec(novtable)
|
||||
#define TOML_EMPTY_BASES __declspec(empty_bases)
|
||||
|
||||
#elif defined(__GNUC__)
|
||||
|
||||
#ifndef __cpp_exceptions
|
||||
#define TOML_EXCEPTIONS 0
|
||||
#endif
|
||||
|
||||
#define TOML_PUSH_WARNINGS _Pragma("GCC diagnostic push")
|
||||
#define TOML_DISABLE_SWITCH_WARNING _Pragma("GCC diagnostic ignored \"-Wswitch\"")
|
||||
#define TOML_DISABLE_FIELD_INIT_WARNING _Pragma("GCC diagnostic ignored \"-Wmissing-field-initializers\"")
|
||||
#define TOML_DISABLE_VAR_INIT_WARNING _Pragma("GCC diagnostic ignored \"-Wmaybe-uninitialized\"")
|
||||
#define TOML_DISABLE_ALL_WARNINGS _Pragma("GCC diagnostic ignored \"-Wall\"")
|
||||
#define TOML_POP_WARNINGS _Pragma("GCC diagnostic pop")
|
||||
#define TOML_ALWAYS_INLINE __attribute__((__always_inline__)) inline
|
||||
#define TOML_UNREACHABLE __builtin_unreachable()
|
||||
|
||||
//floating-point from_chars and to_chars are not implemented in any version of gcc as of 1/1/2020
|
||||
#ifndef TOML_USE_STREAMS_FOR_FLOATS
|
||||
#define TOML_USE_STREAMS_FOR_FLOATS 1
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef TOML_CPP_VERSION
|
||||
#define TOML_CPP_VERSION __cplusplus
|
||||
#endif
|
||||
#if TOML_CPP_VERSION >= 202600L
|
||||
#define TOML_CPP 26
|
||||
#elif TOML_CPP_VERSION >= 202300L
|
||||
#define TOML_CPP 23
|
||||
#elif TOML_CPP_VERSION >= 202000L
|
||||
#define TOML_CPP 20
|
||||
#elif TOML_CPP_VERSION >= 201703L
|
||||
#define TOML_CPP 17
|
||||
#elif TOML_CPP_VERSION >= 201100L
|
||||
#error toml++ requires C++17 or higher. For a TOML parser that supports C++11 see https://github.com/skystrife/cpptoml
|
||||
#else
|
||||
#error toml++ requires C++17 or higher. For a TOML parser that supports pre-C++11 see https://github.com/ToruNiina/Boost.toml
|
||||
#endif
|
||||
#undef TOML_CPP_VERSION
|
||||
|
||||
#ifndef TOML_EXCEPTIONS
|
||||
#define TOML_EXCEPTIONS 1
|
||||
#endif
|
||||
#if TOML_EXCEPTIONS
|
||||
#define TOML_CONDITIONAL_NOEXCEPT(...) noexcept(__VA_ARGS__)
|
||||
#define TOML_MAY_THROW
|
||||
#else
|
||||
#define TOML_CONDITIONAL_NOEXCEPT(...) noexcept
|
||||
#define TOML_MAY_THROW noexcept
|
||||
#endif
|
||||
|
||||
#ifndef TOML_DISABLE_FIELD_INIT_WARNING
|
||||
#define TOML_DISABLE_FIELD_INIT_WARNING
|
||||
#endif
|
||||
#ifndef TOML_DISABLE_VAR_INIT_WARNING
|
||||
#define TOML_DISABLE_VAR_INIT_WARNING
|
||||
#endif
|
||||
#ifndef TOML_USE_STREAMS_FOR_FLOATS
|
||||
#define TOML_USE_STREAMS_FOR_FLOATS 0
|
||||
#endif
|
||||
#ifndef TOML_PUSH_WARNINGS
|
||||
#define TOML_PUSH_WARNINGS
|
||||
#endif
|
||||
#ifndef TOML_DISABLE_ALL_WARNINGS
|
||||
#define TOML_DISABLE_ALL_WARNINGS
|
||||
#endif
|
||||
#ifndef TOML_POP_WARNINGS
|
||||
#define TOML_POP_WARNINGS
|
||||
#endif
|
||||
#ifndef TOML_INTERFACE
|
||||
#define TOML_INTERFACE
|
||||
#endif
|
||||
#ifndef TOML_EMPTY_BASES
|
||||
#define TOML_EMPTY_BASES
|
||||
#endif
|
||||
#ifndef TOML_ALWAYS_INLINE
|
||||
#define TOML_ALWAYS_INLINE inline
|
||||
#endif
|
||||
#ifndef TOML_ASSUME
|
||||
#define TOML_ASSUME(cond) (void)0
|
||||
#endif
|
||||
#ifndef TOML_UNREACHABLE
|
||||
#define TOML_UNREACHABLE (void)0
|
||||
#endif
|
||||
#define TOML_NO_DEFAULT_CASE default: TOML_UNREACHABLE
|
||||
#ifdef __cpp_consteval
|
||||
#define TOML_CONSTEVAL consteval
|
||||
#else
|
||||
#define TOML_CONSTEVAL constexpr
|
||||
#endif
|
||||
#ifndef __INTELLISENSE__
|
||||
#if __has_cpp_attribute(likely)
|
||||
#define TOML_LIKELY [[likely]]
|
||||
#endif
|
||||
#if __has_cpp_attribute(unlikely)
|
||||
#define TOML_UNLIKELY [[unlikely]]
|
||||
#endif
|
||||
#if __has_cpp_attribute(no_unique_address)
|
||||
#define TOML_NO_UNIQUE_ADDRESS [[no_unique_address]]
|
||||
#endif
|
||||
#if __has_cpp_attribute(nodiscard) >= 201907L
|
||||
#define TOML_NODISCARD_CTOR [[nodiscard]]
|
||||
#endif
|
||||
#endif //__INTELLISENSE__
|
||||
#ifndef TOML_LIKELY
|
||||
#define TOML_LIKELY
|
||||
#endif
|
||||
#ifndef TOML_UNLIKELY
|
||||
#define TOML_UNLIKELY
|
||||
#endif
|
||||
#ifndef TOML_NO_UNIQUE_ADDRESS
|
||||
#define TOML_NO_UNIQUE_ADDRESS
|
||||
#endif
|
||||
#ifndef TOML_NODISCARD_CTOR
|
||||
#define TOML_NODISCARD_CTOR
|
||||
#endif
|
||||
|
||||
#define TOML_LANG_MAJOR 0
|
||||
#define TOML_LANG_MINOR 5
|
||||
#define TOML_LANG_REVISION 0
|
||||
|
||||
#define TOML_LANG_MAKE_VERSION(maj, min, rev) \
|
||||
((maj) * 1000 + (min) * 25 + (rev))
|
||||
|
||||
#if TOML_UNRELEASED_FEATURES
|
||||
#define TOML_LANG_EFFECTIVE_VERSION \
|
||||
TOML_LANG_MAKE_VERSION(TOML_LANG_MAJOR, TOML_LANG_MINOR, TOML_LANG_REVISION+1)
|
||||
#else
|
||||
#define TOML_LANG_EFFECTIVE_VERSION \
|
||||
TOML_LANG_MAKE_VERSION(TOML_LANG_MAJOR, TOML_LANG_MINOR, TOML_LANG_REVISION)
|
||||
#endif
|
||||
|
||||
#define TOML_LANG_HIGHER_THAN(maj, min, rev) \
|
||||
(TOML_LANG_EFFECTIVE_VERSION > TOML_LANG_MAKE_VERSION(maj, min, rev))
|
||||
|
||||
#define TOML_LANG_AT_LEAST(maj, min, rev) \
|
||||
(TOML_LANG_EFFECTIVE_VERSION >= TOML_LANG_MAKE_VERSION(maj, min, rev))
|
||||
|
||||
#define TOML_LANG_EXACTLY(maj, min, rev) \
|
||||
(TOML_LANG_EFFECTIVE_VERSION == TOML_LANG_MAKE_VERSION(maj, min, rev))
|
||||
|
||||
////////// INCLUDES
|
||||
|
||||
TOML_PUSH_WARNINGS
|
||||
TOML_DISABLE_ALL_WARNINGS
|
||||
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstring> //memcpy, memset
|
||||
#include <cmath> //log10
|
||||
#include <optional>
|
||||
#include <memory>
|
||||
#include <string_view>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <iosfwd>
|
||||
#include <charconv>
|
||||
#if TOML_USE_STREAMS_FOR_FLOATS
|
||||
#include <sstream>
|
||||
#endif
|
||||
#if TOML_EXCEPTIONS
|
||||
#include <stdexcept>
|
||||
#endif
|
||||
|
||||
TOML_POP_WARNINGS
|
||||
|
||||
#if TOML_CHAR_8_STRINGS
|
||||
#if !defined(__cpp_lib_char8_t)
|
||||
#error toml++ requires implementation support to use char8_t strings, but yours does not provide it.
|
||||
#endif
|
||||
|
||||
#define TOML_STRING_PREFIX_1(S) u8##S
|
||||
#define TOML_STRING_PREFIX(S) TOML_STRING_PREFIX_1(S)
|
||||
#else
|
||||
#define TOML_STRING_PREFIX(S) S
|
||||
#endif
|
||||
|
||||
////////// FORWARD DECLARATIONS & TYPEDEFS
|
||||
// clang-format on
|
||||
|
||||
namespace toml
|
||||
{
|
||||
inline namespace literals
|
||||
{
|
||||
using namespace std::string_literals;
|
||||
using namespace std::string_view_literals;
|
||||
|
||||
[[nodiscard]] TOML_ALWAYS_INLINE
|
||||
TOML_CONSTEVAL uint8_t operator"" _u8(unsigned long long n) noexcept
|
||||
{
|
||||
return static_cast<uint8_t>(n);
|
||||
}
|
||||
|
||||
[[nodiscard]] TOML_ALWAYS_INLINE
|
||||
TOML_CONSTEVAL size_t operator"" _sz(unsigned long long n) noexcept
|
||||
{
|
||||
return static_cast<size_t>(n);
|
||||
}
|
||||
}
|
||||
|
||||
struct date final
|
||||
{
|
||||
uint16_t year;
|
||||
uint8_t month;
|
||||
uint8_t day;
|
||||
|
||||
[[nodiscard]]
|
||||
friend bool operator == (date lhs, date rhs) noexcept
|
||||
{
|
||||
return lhs.year == rhs.year
|
||||
&& lhs.month == rhs.month
|
||||
&& lhs.day == rhs.day;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
friend bool operator != (date lhs, date rhs) noexcept
|
||||
{
|
||||
return lhs.year != rhs.year
|
||||
|| lhs.month != rhs.month
|
||||
|| lhs.day != rhs.day;
|
||||
}
|
||||
};
|
||||
|
||||
struct time final
|
||||
{
|
||||
uint8_t hour;
|
||||
uint8_t minute;
|
||||
uint8_t second;
|
||||
uint32_t nanosecond;
|
||||
|
||||
[[nodiscard]]
|
||||
friend bool operator == (time lhs, time rhs) noexcept
|
||||
{
|
||||
return lhs.hour == rhs.hour
|
||||
&& lhs.minute == rhs.minute
|
||||
&& lhs.second == rhs.second
|
||||
&& lhs.nanosecond == rhs.nanosecond;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
friend bool operator != (time lhs, time rhs) noexcept
|
||||
{
|
||||
return lhs.hour != rhs.hour
|
||||
|| lhs.minute != rhs.minute
|
||||
|| lhs.second != rhs.second
|
||||
|| lhs.nanosecond != rhs.nanosecond;
|
||||
}
|
||||
};
|
||||
|
||||
struct time_offset final
|
||||
{
|
||||
int8_t hours;
|
||||
int8_t minutes;
|
||||
|
||||
[[nodiscard]]
|
||||
friend bool operator == (time_offset lhs, time_offset rhs) noexcept
|
||||
{
|
||||
return lhs.hours == rhs.hours
|
||||
&& lhs.minutes == rhs.minutes;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
friend bool operator != (time_offset lhs, time_offset rhs) noexcept
|
||||
{
|
||||
return lhs.hours != rhs.hours
|
||||
|| lhs.minutes != rhs.minutes;
|
||||
}
|
||||
};
|
||||
|
||||
struct date_time final
|
||||
{
|
||||
toml::date date;
|
||||
toml::time time;
|
||||
std::optional<toml::time_offset> time_offset;
|
||||
|
||||
[[nodiscard]]
|
||||
friend bool operator == (const date_time& lhs, const date_time& rhs) noexcept
|
||||
{
|
||||
return lhs.date == rhs.date
|
||||
&& lhs.time == rhs.time
|
||||
&& lhs.time_offset == rhs.time_offset;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
friend bool operator != (const date_time& lhs, const date_time& rhs) noexcept
|
||||
{
|
||||
return lhs.date != rhs.date
|
||||
|| lhs.time != rhs.time
|
||||
|| lhs.time_offset != rhs.time_offset;
|
||||
}
|
||||
};
|
||||
|
||||
#if TOML_CHAR_8_STRINGS
|
||||
|
||||
using string_char = char8_t;
|
||||
using string = std::u8string;
|
||||
using string_view = std::u8string_view;
|
||||
|
||||
#else
|
||||
|
||||
using string_char = char;
|
||||
using string = std::string;
|
||||
using string_view = std::string_view;
|
||||
|
||||
#endif
|
||||
|
||||
template <typename T>
|
||||
using string_map = std::map<string, T, std::less<>>; //heterogeneous lookup
|
||||
|
||||
class node;
|
||||
template <typename T>
|
||||
class node_view;
|
||||
template <typename T>
|
||||
class value;
|
||||
class array;
|
||||
class table;
|
||||
|
||||
class default_formatter;
|
||||
|
||||
namespace impl
|
||||
{
|
||||
#if defined(__cpp_lib_remove_cvref) || (defined(_MSC_VER) && defined(_HAS_CXX20))
|
||||
|
||||
template <typename T>
|
||||
using remove_cvref_t = std::remove_cvref_t<T>;
|
||||
|
||||
#else
|
||||
|
||||
template <typename T>
|
||||
using remove_cvref_t = std::remove_cv_t<std::remove_reference_t<T>>;
|
||||
|
||||
#endif
|
||||
|
||||
class parser;
|
||||
|
||||
template <typename T>
|
||||
inline constexpr bool is_value =
|
||||
std::is_same_v<T, string>
|
||||
|| std::is_same_v<T, int64_t>
|
||||
|| std::is_same_v<T, double>
|
||||
|| std::is_same_v<T, bool>
|
||||
|| std::is_same_v<T, date>
|
||||
|| std::is_same_v<T, time>
|
||||
|| std::is_same_v<T, date_time>;
|
||||
|
||||
template <typename T>
|
||||
inline constexpr bool is_value_or_promotable =
|
||||
is_value<T>
|
||||
|| std::is_same_v<T, string_view>
|
||||
|| std::is_same_v<T, int32_t>
|
||||
|| std::is_same_v<T, int16_t>
|
||||
|| std::is_same_v<T, int8_t>
|
||||
|| std::is_same_v<T, uint32_t>
|
||||
|| std::is_same_v<T, uint16_t>
|
||||
|| std::is_same_v<T, uint8_t>
|
||||
|| std::is_same_v<T, float>;
|
||||
|
||||
template <typename T>
|
||||
inline constexpr bool is_value_or_node =
|
||||
is_value<T>
|
||||
|| std::is_same_v<T, array>
|
||||
|| std::is_same_v<T, table>;
|
||||
|
||||
template <typename T> struct node_wrapper { using type = T; };
|
||||
template <> struct node_wrapper<string> { using type = value<string>; };
|
||||
template <> struct node_wrapper<int64_t> { using type = value<int64_t>; };
|
||||
template <> struct node_wrapper<double> { using type = value<double>; };
|
||||
template <> struct node_wrapper<bool> { using type = value<bool>; };
|
||||
template <> struct node_wrapper<date> { using type = value<date>; };
|
||||
template <> struct node_wrapper<time> { using type = value<time>; };
|
||||
template <> struct node_wrapper<date_time> { using type = value<date_time>; };
|
||||
|
||||
template <typename T> struct value_promoter { using type = T; };
|
||||
template <> struct value_promoter<string_view> { using type = string; };
|
||||
template <> struct value_promoter<int32_t> { using type = int64_t; };
|
||||
template <> struct value_promoter<int16_t> { using type = int64_t; };
|
||||
template <> struct value_promoter<int8_t> { using type = int64_t; };
|
||||
template <> struct value_promoter<uint32_t> { using type = int64_t; };
|
||||
template <> struct value_promoter<uint16_t> { using type = int64_t; };
|
||||
template <> struct value_promoter<uint8_t> { using type = int64_t; };
|
||||
template <> struct value_promoter<float> { using type = double; };
|
||||
|
||||
template <typename T>
|
||||
std::optional<size_t> find(const std::vector<T>& haystack, const T& needle) noexcept
|
||||
{
|
||||
// Q: "why not use std::find??"
|
||||
// A: Because <algorithm> is _huge_ and std::find would be the only thing I used from it.
|
||||
// I don't want to impose such a heavy burden on users.
|
||||
|
||||
const auto end = haystack.size();
|
||||
for (size_t i = 0; i < end; i++)
|
||||
if (haystack[i] == needle)
|
||||
return i;
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
using node_of = typename impl::node_wrapper<T>::type;
|
||||
|
||||
template <typename T>
|
||||
using value_of = typename impl::value_promoter<T>::type;
|
||||
|
||||
struct source_position
|
||||
{
|
||||
uint32_t line; //begins at 1
|
||||
uint32_t column; //begins at 1
|
||||
|
||||
[[nodiscard]]
|
||||
friend bool operator == (const source_position& lhs, const source_position& rhs) noexcept
|
||||
{
|
||||
return lhs.line == rhs.line
|
||||
&& lhs.column == rhs.column;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
friend bool operator != (const source_position& lhs, const source_position& rhs) noexcept
|
||||
{
|
||||
return lhs.line != rhs.line
|
||||
|| lhs.column != rhs.column;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
friend bool operator < (const source_position& lhs, const source_position& rhs) noexcept
|
||||
{
|
||||
return lhs.line < rhs.line
|
||||
|| (lhs.line == rhs.line && lhs.column < rhs.column);
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
friend bool operator <= (const source_position& lhs, const source_position& rhs) noexcept
|
||||
{
|
||||
return lhs.line < rhs.line
|
||||
|| (lhs.line == rhs.line && lhs.column <= rhs.column);
|
||||
}
|
||||
};
|
||||
|
||||
struct source_region
|
||||
{
|
||||
source_position begin;
|
||||
source_position end;
|
||||
std::shared_ptr<const std::string> path;
|
||||
};
|
||||
|
||||
enum class node_type : uint8_t
|
||||
{
|
||||
table,
|
||||
array,
|
||||
string,
|
||||
integer,
|
||||
floating_point,
|
||||
boolean,
|
||||
date,
|
||||
time,
|
||||
date_time
|
||||
};
|
||||
|
||||
TOML_PUSH_WARNINGS
|
||||
TOML_DISABLE_FIELD_INIT_WARNING
|
||||
|
||||
#if TOML_EXCEPTIONS
|
||||
|
||||
class parse_error final
|
||||
: public std::runtime_error
|
||||
{
|
||||
private:
|
||||
source_region rgn;
|
||||
|
||||
public:
|
||||
|
||||
TOML_NODISCARD_CTOR
|
||||
parse_error(const char* description, source_region&& region) noexcept
|
||||
: std::runtime_error{ description },
|
||||
rgn{ std::move(region) }
|
||||
{}
|
||||
|
||||
TOML_NODISCARD_CTOR
|
||||
parse_error(const char* description, const source_region& region) noexcept
|
||||
: std::runtime_error{ description },
|
||||
rgn{ region }
|
||||
{}
|
||||
|
||||
TOML_NODISCARD_CTOR
|
||||
parse_error(const char* description, const source_position& position, const std::shared_ptr<const std::string>& source_path) noexcept
|
||||
: std::runtime_error{ description },
|
||||
rgn{ position, position, source_path }
|
||||
{}
|
||||
|
||||
TOML_NODISCARD_CTOR
|
||||
parse_error(const char* description, const source_position& position) noexcept
|
||||
: std::runtime_error{ description },
|
||||
rgn{ position, position }
|
||||
{}
|
||||
|
||||
[[nodiscard]]
|
||||
const source_region& where() const noexcept
|
||||
{
|
||||
return rgn;
|
||||
}
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
struct parse_error final
|
||||
{
|
||||
std::string what;
|
||||
source_region where;
|
||||
|
||||
TOML_NODISCARD_CTOR
|
||||
parse_error() noexcept = default;
|
||||
|
||||
TOML_NODISCARD_CTOR
|
||||
parse_error(const char* description, source_region&& region) noexcept
|
||||
: what{ description },
|
||||
where{ std::move(region) }
|
||||
{}
|
||||
|
||||
TOML_NODISCARD_CTOR
|
||||
parse_error(const char* description, const source_region& region) noexcept
|
||||
: what{ description },
|
||||
where{ region }
|
||||
{}
|
||||
|
||||
TOML_NODISCARD_CTOR
|
||||
parse_error(const char* description, const source_position& position, const std::shared_ptr<const std::string>& source_path) noexcept
|
||||
: what{ description },
|
||||
where{ position, position, source_path }
|
||||
{}
|
||||
|
||||
TOML_NODISCARD_CTOR
|
||||
parse_error(const char* description, const source_position& position) noexcept
|
||||
: what{ description },
|
||||
where{ position, position }
|
||||
{}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
TOML_POP_WARNINGS
|
||||
}
|
717
include/toml++/toml_formatter.h
Normal file
717
include/toml++/toml_formatter.h
Normal file
@ -0,0 +1,717 @@
|
||||
#pragma once
|
||||
#include "toml_utf8.h"
|
||||
#include "toml_value.h"
|
||||
#include "toml_array.h"
|
||||
|
||||
namespace toml::impl
|
||||
{
|
||||
struct TOML_INTERFACE formatter_writer_interface
|
||||
{
|
||||
virtual void operator() (const void*, size_t) const TOML_MAY_THROW = 0;
|
||||
virtual void operator() (char) const TOML_MAY_THROW = 0;
|
||||
|
||||
virtual ~formatter_writer_interface() noexcept = default;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class formatter_writer;
|
||||
|
||||
template <typename CHAR>
|
||||
class TOML_EMPTY_BASES formatter_writer<std::basic_ostream<CHAR>> : public formatter_writer_interface
|
||||
{
|
||||
private:
|
||||
std::basic_ostream<CHAR>& target;
|
||||
|
||||
public:
|
||||
|
||||
void operator() (const void* data, size_t size) const TOML_MAY_THROW override
|
||||
{
|
||||
TOML_ASSERT(data && size);
|
||||
target.write(reinterpret_cast<const CHAR*>(data), static_cast<std::streamsize>(size));
|
||||
}
|
||||
|
||||
void operator() (char character) const TOML_MAY_THROW override
|
||||
{
|
||||
target.put(static_cast<CHAR>(character));
|
||||
}
|
||||
|
||||
formatter_writer(std::basic_ostream<CHAR>& target_) noexcept
|
||||
: target{ target_ }
|
||||
{}
|
||||
};
|
||||
|
||||
template <typename CHAR>
|
||||
formatter_writer(std::basic_ostream<CHAR>&) -> formatter_writer<std::basic_ostream<CHAR>>;
|
||||
}
|
||||
|
||||
namespace toml
|
||||
{
|
||||
class default_formatter final
|
||||
{
|
||||
private:
|
||||
const toml::table& source;
|
||||
std::string_view indent_string;
|
||||
size_t indent_string_columns = {};
|
||||
|
||||
mutable int indent_level;
|
||||
mutable bool naked_newline;
|
||||
mutable std::vector<toml::string> key_path;
|
||||
mutable const impl::formatter_writer_interface* writer = nullptr;
|
||||
|
||||
TOML_ALWAYS_INLINE
|
||||
void write(char character) const TOML_MAY_THROW
|
||||
{
|
||||
(*writer)(character);
|
||||
}
|
||||
|
||||
template <typename CHAR>
|
||||
TOML_ALWAYS_INLINE
|
||||
void write(std::basic_string_view<CHAR> strv) const TOML_MAY_THROW
|
||||
{
|
||||
static_assert(sizeof(CHAR) == 1_sz);
|
||||
|
||||
(*writer)(reinterpret_cast<const uint8_t*>(strv.data()), strv.length());
|
||||
}
|
||||
|
||||
template <typename CHAR>
|
||||
TOML_ALWAYS_INLINE
|
||||
void write(const std::basic_string<CHAR>& str) const TOML_MAY_THROW
|
||||
{
|
||||
static_assert(sizeof(CHAR) == 1_sz);
|
||||
|
||||
(*writer)(reinterpret_cast<const uint8_t*>(str.data()), str.length());
|
||||
}
|
||||
|
||||
void write_newline(bool force = false) const TOML_MAY_THROW
|
||||
{
|
||||
if (!naked_newline || force)
|
||||
{
|
||||
write('\n');
|
||||
naked_newline = true;
|
||||
}
|
||||
}
|
||||
|
||||
void write_indent() const TOML_MAY_THROW
|
||||
{
|
||||
for (int i = 0; i < indent_level; i++)
|
||||
{
|
||||
write(indent_string);
|
||||
naked_newline = false;
|
||||
}
|
||||
}
|
||||
|
||||
TOML_PUSH_WARNINGS
|
||||
TOML_DISABLE_ALL_WARNINGS // some compilers will complain about a tautological unsigned >= 0.
|
||||
// TINAE - char can have signed _or_ unsigned semantics and I can't
|
||||
// be arsed handling this differently
|
||||
|
||||
static toml::string_view escape_string_character(const toml::string_char& c) noexcept
|
||||
{
|
||||
if (c >= toml::string_char{} && c <= TOML_STRING_PREFIX('\x1F')) TOML_UNLIKELY
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case TOML_STRING_PREFIX('\x00'): return TOML_STRING_PREFIX("\\u0000"sv);
|
||||
case TOML_STRING_PREFIX('\x01'): return TOML_STRING_PREFIX("\\u0001"sv);
|
||||
case TOML_STRING_PREFIX('\x02'): return TOML_STRING_PREFIX("\\u0002"sv);
|
||||
case TOML_STRING_PREFIX('\x03'): return TOML_STRING_PREFIX("\\u0003"sv);
|
||||
case TOML_STRING_PREFIX('\x04'): return TOML_STRING_PREFIX("\\u0004"sv);
|
||||
case TOML_STRING_PREFIX('\x05'): return TOML_STRING_PREFIX("\\u0005"sv);
|
||||
case TOML_STRING_PREFIX('\x06'): return TOML_STRING_PREFIX("\\u0006"sv);
|
||||
case TOML_STRING_PREFIX('\x07'): return TOML_STRING_PREFIX("\\u0007"sv);
|
||||
case TOML_STRING_PREFIX('\x08'): return TOML_STRING_PREFIX("\\b"sv);
|
||||
case TOML_STRING_PREFIX('\x09'): return TOML_STRING_PREFIX("\\t"sv);
|
||||
case TOML_STRING_PREFIX('\x0A'): return TOML_STRING_PREFIX("\\n"sv);
|
||||
case TOML_STRING_PREFIX('\x0B'): return TOML_STRING_PREFIX("\\u000B"sv);
|
||||
case TOML_STRING_PREFIX('\x0C'): return TOML_STRING_PREFIX("\\f"sv);
|
||||
case TOML_STRING_PREFIX('\x0D'): return TOML_STRING_PREFIX("\\r"sv);
|
||||
case TOML_STRING_PREFIX('\x0E'): return TOML_STRING_PREFIX("\\u000E"sv);
|
||||
case TOML_STRING_PREFIX('\x0F'): return TOML_STRING_PREFIX("\\u000F"sv);
|
||||
case TOML_STRING_PREFIX('\x10'): return TOML_STRING_PREFIX("\\u0010"sv);
|
||||
case TOML_STRING_PREFIX('\x11'): return TOML_STRING_PREFIX("\\u0011"sv);
|
||||
case TOML_STRING_PREFIX('\x12'): return TOML_STRING_PREFIX("\\u0012"sv);
|
||||
case TOML_STRING_PREFIX('\x13'): return TOML_STRING_PREFIX("\\u0013"sv);
|
||||
case TOML_STRING_PREFIX('\x14'): return TOML_STRING_PREFIX("\\u0014"sv);
|
||||
case TOML_STRING_PREFIX('\x15'): return TOML_STRING_PREFIX("\\u0015"sv);
|
||||
case TOML_STRING_PREFIX('\x16'): return TOML_STRING_PREFIX("\\u0016"sv);
|
||||
case TOML_STRING_PREFIX('\x17'): return TOML_STRING_PREFIX("\\u0017"sv);
|
||||
case TOML_STRING_PREFIX('\x18'): return TOML_STRING_PREFIX("\\u0018"sv);
|
||||
case TOML_STRING_PREFIX('\x19'): return TOML_STRING_PREFIX("\\u0019"sv);
|
||||
case TOML_STRING_PREFIX('\x1A'): return TOML_STRING_PREFIX("\\u001A"sv);
|
||||
case TOML_STRING_PREFIX('\x1B'): return TOML_STRING_PREFIX("\\u001B"sv);
|
||||
case TOML_STRING_PREFIX('\x1C'): return TOML_STRING_PREFIX("\\u001C"sv);
|
||||
case TOML_STRING_PREFIX('\x1D'): return TOML_STRING_PREFIX("\\u001D"sv);
|
||||
case TOML_STRING_PREFIX('\x1E'): return TOML_STRING_PREFIX("\\u001E"sv);
|
||||
case TOML_STRING_PREFIX('\x1F'): return TOML_STRING_PREFIX("\\u001F"sv);
|
||||
TOML_NO_DEFAULT_CASE;
|
||||
}
|
||||
}
|
||||
else if (c == TOML_STRING_PREFIX('\x7F')) TOML_UNLIKELY
|
||||
return TOML_STRING_PREFIX("\\u007F"sv);
|
||||
else if (c == TOML_STRING_PREFIX('"')) TOML_UNLIKELY
|
||||
return TOML_STRING_PREFIX("\\\""sv);
|
||||
else
|
||||
return toml::string_view{ &c, 1_sz };
|
||||
}
|
||||
|
||||
TOML_POP_WARNINGS
|
||||
|
||||
static toml::string make_key_segment(const toml::string& str) noexcept
|
||||
{
|
||||
if (str.empty())
|
||||
return TOML_STRING_PREFIX("''"s);
|
||||
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)
|
||||
{
|
||||
toml::string s;
|
||||
s.reserve(str.length() + 2_sz);
|
||||
s += TOML_STRING_PREFIX('"');
|
||||
for (auto c : str)
|
||||
s.append(escape_string_character(c));
|
||||
s += TOML_STRING_PREFIX('"');
|
||||
return s;
|
||||
}
|
||||
else
|
||||
return str;
|
||||
}
|
||||
}
|
||||
|
||||
void write_key_segment(const toml::string& str) const TOML_MAY_THROW
|
||||
{
|
||||
if (str.empty())
|
||||
write("''"sv);
|
||||
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)
|
||||
{
|
||||
write('"');
|
||||
for (auto c : str)
|
||||
write(escape_string_character(c));
|
||||
write('"');
|
||||
}
|
||||
else
|
||||
write(str);
|
||||
}
|
||||
}
|
||||
|
||||
void write_key_path() const TOML_MAY_THROW
|
||||
{
|
||||
for (const auto& segment : key_path)
|
||||
{
|
||||
if (std::addressof(segment) > key_path.data())
|
||||
write('.');
|
||||
write(segment);
|
||||
}
|
||||
naked_newline = false;
|
||||
}
|
||||
|
||||
void write(const value<toml::string>& val) const TOML_MAY_THROW
|
||||
{
|
||||
const auto& str = val.get();
|
||||
if (str.empty())
|
||||
write("''"sv);
|
||||
else
|
||||
{
|
||||
write('"');
|
||||
for (auto c : str)
|
||||
write(escape_string_character(c));
|
||||
write('"');
|
||||
}
|
||||
naked_newline = false;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void write_integer(T val) const TOML_MAY_THROW
|
||||
{
|
||||
char buf[20_sz]; //strlen("-9223372036854775808")
|
||||
const auto res = std::to_chars(buf, buf + sizeof(buf), val);
|
||||
(*writer)(buf, static_cast<size_t>(res.ptr - buf));
|
||||
naked_newline = false;
|
||||
}
|
||||
|
||||
void write(const value<int64_t>& val) const TOML_MAY_THROW
|
||||
{
|
||||
write_integer(val.get());
|
||||
}
|
||||
|
||||
void write(const value<double>& val) const TOML_MAY_THROW
|
||||
{
|
||||
#if TOML_USE_STREAMS_FOR_FLOATS
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << val.get();
|
||||
write(oss.str());
|
||||
if (val.get() == 0.0)
|
||||
write(".0"sv);
|
||||
}
|
||||
#else
|
||||
{
|
||||
char buf[32_sz];
|
||||
const auto res = std::to_chars(buf, buf + sizeof(buf), val.get());
|
||||
const auto sv = std::string_view{ buf, static_cast<size_t>(res.ptr - buf) };
|
||||
write(sv);
|
||||
bool needs_decimal_point = true;
|
||||
for (auto ch : sv)
|
||||
{
|
||||
if (ch == 'e' || ch == 'E' || ch == '.')
|
||||
{
|
||||
needs_decimal_point = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (needs_decimal_point)
|
||||
write(".0"sv);
|
||||
}
|
||||
#endif
|
||||
naked_newline = false;
|
||||
}
|
||||
|
||||
void write(const value<bool>& val) const TOML_MAY_THROW
|
||||
{
|
||||
write(val.get() ? "true"sv : "false"sv);
|
||||
naked_newline = false;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void write_zero_padded_integer(T intval, size_t digits) const TOML_MAY_THROW
|
||||
{
|
||||
static_assert(std::is_unsigned_v<T>);
|
||||
|
||||
char buf[17_sz]; //strlen("9223372036854775807")
|
||||
const auto res = std::to_chars(buf, buf + sizeof(buf), intval);
|
||||
const auto len = static_cast<size_t>(res.ptr - buf);
|
||||
for (size_t i = len; i < digits; i++)
|
||||
write('0');
|
||||
(*writer)(buf, len);
|
||||
naked_newline = false;
|
||||
}
|
||||
|
||||
void write(const time& tm) const TOML_MAY_THROW
|
||||
{
|
||||
write_zero_padded_integer(tm.hour, 2_sz);
|
||||
write(':');
|
||||
write_zero_padded_integer(tm.minute, 2_sz);
|
||||
write(':');
|
||||
write_zero_padded_integer(tm.second, 2_sz);
|
||||
|
||||
if (tm.nanosecond && tm.nanosecond <= 999999999u)
|
||||
{
|
||||
write('.');
|
||||
auto ns = tm.nanosecond;
|
||||
size_t digits = 9_sz;
|
||||
while (ns % 10u == 0u)
|
||||
{
|
||||
ns /= 10u;
|
||||
digits--;
|
||||
}
|
||||
write_integer(ns);
|
||||
}
|
||||
}
|
||||
|
||||
void write(const date& dt) const TOML_MAY_THROW
|
||||
{
|
||||
write_zero_padded_integer(dt.year, 4_sz);
|
||||
write('-');
|
||||
write_zero_padded_integer(dt.month, 2_sz);
|
||||
write('-');
|
||||
write_zero_padded_integer(dt.day, 2_sz);
|
||||
}
|
||||
|
||||
void write(const date_time& dt) const TOML_MAY_THROW
|
||||
{
|
||||
write(dt.date);
|
||||
write('T');
|
||||
write(dt.time);
|
||||
if (dt.time_offset)
|
||||
{
|
||||
const auto& to = *dt.time_offset;
|
||||
if (!to.hours && !to.minutes)
|
||||
write('Z');
|
||||
else
|
||||
{
|
||||
write(to.hours < 0 || to.minutes < 0 ? '-' : '+');
|
||||
write_zero_padded_integer(static_cast<uint8_t>(to.hours < 0 ? -to.hours : to.hours), 2_sz);
|
||||
write(':');
|
||||
write_zero_padded_integer(static_cast<uint8_t>(to.minutes < 0 ? -to.minutes : to.minutes), 2_sz);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void write(const value<time>& val) const TOML_MAY_THROW
|
||||
{
|
||||
write(val.get());
|
||||
}
|
||||
|
||||
void write(const value<date>& val) const TOML_MAY_THROW
|
||||
{
|
||||
write(val.get());
|
||||
}
|
||||
|
||||
void write(const value<date_time>& val) const TOML_MAY_THROW
|
||||
{
|
||||
write(val.get());
|
||||
}
|
||||
|
||||
inline void write_inline(const table& /*tab*/) const TOML_MAY_THROW;
|
||||
|
||||
static size_t inline_columns(const node& node) noexcept
|
||||
{
|
||||
switch (node.type())
|
||||
{
|
||||
case node_type::table: //assumed to be inline
|
||||
{
|
||||
auto& values = reinterpret_cast<const table*>(&node)->values;
|
||||
if (values.empty())
|
||||
return 2_sz; // "{}"
|
||||
size_t weight = 3_sz; // "{ }"
|
||||
for (auto& [k, v] : values)
|
||||
weight += k.length() + inline_columns(*v) + 2_sz; // + ", "
|
||||
return weight;
|
||||
}
|
||||
case node_type::array:
|
||||
{
|
||||
auto& values = reinterpret_cast<const array*>(&node)->values;
|
||||
if (values.empty())
|
||||
return 2_sz; // "[]"
|
||||
size_t weight = 3_sz; // "[ ]"
|
||||
for (auto& v : values)
|
||||
weight += inline_columns(*v) + 2_sz; // + ", "
|
||||
return weight;
|
||||
}
|
||||
case node_type::string:
|
||||
return reinterpret_cast<const value<string>*>(&node)->get().length() + 2_sz; // + ""
|
||||
|
||||
case node_type::integer:
|
||||
{
|
||||
auto v = reinterpret_cast<const value<int64_t>*>(&node)->get();
|
||||
if (!v)
|
||||
return 1_sz;
|
||||
size_t weight = {};
|
||||
if (v < 0)
|
||||
{
|
||||
weight += 1;
|
||||
v *= -1;
|
||||
}
|
||||
return weight + static_cast<size_t>(std::log10(static_cast<double>(v)));
|
||||
}
|
||||
|
||||
case node_type::floating_point:
|
||||
{
|
||||
auto v = reinterpret_cast<const value<double>*>(&node)->get();
|
||||
if (v == 0.0)
|
||||
return 3_sz;
|
||||
size_t weight = 2_sz; // ".0"
|
||||
if (v < 0.0)
|
||||
{
|
||||
weight += 1;
|
||||
v *= -1.0;
|
||||
}
|
||||
return weight + static_cast<size_t>(std::log10(v));
|
||||
}
|
||||
|
||||
case node_type::boolean: return 5_sz;
|
||||
case node_type::date: [[fallthrough]];
|
||||
case node_type::time: return 10_sz;
|
||||
case node_type::date_time: return 30_sz;
|
||||
TOML_NO_DEFAULT_CASE;
|
||||
}
|
||||
}
|
||||
|
||||
static bool forces_multiline(const node& node, size_t starting_column_bias = 0) noexcept
|
||||
{
|
||||
return (inline_columns(node) + starting_column_bias) > 100_sz;
|
||||
}
|
||||
|
||||
void write(const array& arr) const TOML_MAY_THROW
|
||||
{
|
||||
if (arr.values.empty())
|
||||
write("[]"sv);
|
||||
else
|
||||
{
|
||||
const auto multiline = forces_multiline(
|
||||
arr,
|
||||
indent_string_columns * static_cast<size_t>(indent_level < 0 ? 0 : indent_level)
|
||||
);
|
||||
const auto original_indent = indent_level;
|
||||
write("["sv);
|
||||
if (multiline)
|
||||
{
|
||||
if (indent_level < 0)
|
||||
indent_level++;
|
||||
indent_level++;
|
||||
}
|
||||
else
|
||||
write(' ');
|
||||
|
||||
for (auto& v : arr.values)
|
||||
{
|
||||
if (std::addressof(v) > arr.values.data())
|
||||
{
|
||||
write(',');
|
||||
if (!multiline)
|
||||
write(' ');
|
||||
}
|
||||
|
||||
if (multiline)
|
||||
{
|
||||
write_newline(true);
|
||||
write_indent();
|
||||
}
|
||||
|
||||
const auto type = v->type();
|
||||
switch (type)
|
||||
{
|
||||
case node_type::table: write_inline(*reinterpret_cast<const table*>(v.get())); break;
|
||||
case node_type::array: write(*reinterpret_cast<const array*>(v.get())); break;
|
||||
case node_type::string: write(*reinterpret_cast<const value<string>*>(v.get())); break;
|
||||
case node_type::integer: write(*reinterpret_cast<const value<int64_t>*>(v.get())); break;
|
||||
case node_type::floating_point: write(*reinterpret_cast<const value<double>*>(v.get())); break;
|
||||
case node_type::boolean: write(*reinterpret_cast<const value<bool>*>(v.get())); break;
|
||||
case node_type::date: write(*reinterpret_cast<const value<date>*>(v.get())); break;
|
||||
case node_type::time: write(*reinterpret_cast<const value<time>*>(v.get())); break;
|
||||
case node_type::date_time: write(*reinterpret_cast<const value<date_time>*>(v.get())); break;
|
||||
TOML_NO_DEFAULT_CASE;
|
||||
}
|
||||
|
||||
}
|
||||
if (multiline)
|
||||
{
|
||||
indent_level = original_indent;
|
||||
write_newline(true);
|
||||
write_indent();
|
||||
}
|
||||
else
|
||||
write(' ');
|
||||
write("]"sv);
|
||||
}
|
||||
naked_newline = false;
|
||||
}
|
||||
|
||||
void write(const table& tab) const TOML_MAY_THROW
|
||||
{
|
||||
//values, arrays, and inline tables
|
||||
for (auto& [k, v] : tab.values)
|
||||
{
|
||||
const auto type = v->type();
|
||||
if ((type == node_type::table && !reinterpret_cast<const table*>(v.get())->is_inline())
|
||||
|| (type == node_type::array && reinterpret_cast<const array*>(v.get())->is_array_of_tables()))
|
||||
continue;
|
||||
|
||||
write_newline();
|
||||
write_indent();
|
||||
write_key_segment(k);
|
||||
write(" = "sv);
|
||||
switch (type)
|
||||
{
|
||||
case node_type::table: write_inline(*reinterpret_cast<const table*>(v.get())); break;
|
||||
case node_type::array: write(*reinterpret_cast<const array*>(v.get())); break;
|
||||
case node_type::string: write(*reinterpret_cast<const value<string>*>(v.get())); break;
|
||||
case node_type::integer: write(*reinterpret_cast<const value<int64_t>*>(v.get())); break;
|
||||
case node_type::floating_point: write(*reinterpret_cast<const value<double>*>(v.get())); break;
|
||||
case node_type::boolean: write(*reinterpret_cast<const value<bool>*>(v.get())); break;
|
||||
case node_type::date: write(*reinterpret_cast<const value<date>*>(v.get())); break;
|
||||
case node_type::time: write(*reinterpret_cast<const value<time>*>(v.get())); break;
|
||||
case node_type::date_time: write(*reinterpret_cast<const value<date_time>*>(v.get())); break;
|
||||
TOML_NO_DEFAULT_CASE;
|
||||
}
|
||||
}
|
||||
|
||||
//non-inline tables
|
||||
for (auto& [k, v] : tab.values)
|
||||
{
|
||||
const auto type = v->type();
|
||||
if (type != node_type::table || reinterpret_cast<const table*>(v.get())->is_inline())
|
||||
continue;
|
||||
auto& child_tab = *reinterpret_cast<const table*>(v.get());
|
||||
|
||||
//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_tab.values)
|
||||
{
|
||||
const auto child_type = child_v->type();
|
||||
switch (child_type)
|
||||
{
|
||||
case node_type::table:
|
||||
if (reinterpret_cast<const table*>(child_v.get())->is_inline())
|
||||
child_value_count++;
|
||||
else
|
||||
child_table_count++;
|
||||
break;
|
||||
|
||||
case node_type::array:
|
||||
if (reinterpret_cast<const array*>(child_v.get())->is_array_of_tables())
|
||||
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;
|
||||
|
||||
if (!skip_self)
|
||||
indent_level++;
|
||||
key_path.push_back(make_key_segment(k));
|
||||
|
||||
if (!skip_self)
|
||||
{
|
||||
write_newline();
|
||||
write_newline(true);
|
||||
write_indent();
|
||||
write("["sv);
|
||||
write_key_path();
|
||||
write("]"sv);
|
||||
write_newline(true);
|
||||
}
|
||||
|
||||
write(child_tab);
|
||||
|
||||
key_path.pop_back();
|
||||
if (!skip_self)
|
||||
indent_level--;
|
||||
}
|
||||
|
||||
//table arrays
|
||||
for (auto& [k, v] : tab.values)
|
||||
{
|
||||
const auto type = v->type();
|
||||
if (type != node_type::array || !reinterpret_cast<const array*>(v.get())->is_array_of_tables())
|
||||
continue;
|
||||
auto& node = *reinterpret_cast<const array*>(v.get());
|
||||
|
||||
indent_level++;
|
||||
key_path.push_back(make_key_segment(k));
|
||||
|
||||
for (auto& t : node.values)
|
||||
{
|
||||
write_newline();
|
||||
write_newline(true);
|
||||
write_indent();
|
||||
write("[["sv);
|
||||
write_key_path();
|
||||
write("]]"sv);
|
||||
write_newline(true);
|
||||
write(*reinterpret_cast<const table*>(t.get()));
|
||||
}
|
||||
|
||||
key_path.pop_back();
|
||||
indent_level--;
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
explicit default_formatter(const toml::table& source_, std::string_view indent_string_ = " "sv) noexcept
|
||||
: source{ source_ },
|
||||
indent_string{ indent_string_ }
|
||||
{
|
||||
for (auto c : indent_string)
|
||||
indent_string_columns += c == '\t' ? 4_sz : 1_sz;
|
||||
}
|
||||
|
||||
template <typename CHAR>
|
||||
friend std::basic_ostream<CHAR>& operator << (std::basic_ostream<CHAR>& lhs, const default_formatter& rhs) TOML_MAY_THROW
|
||||
{
|
||||
static_assert(
|
||||
sizeof(CHAR) == 1,
|
||||
"The stream's underlying character type must be 1 byte in size."
|
||||
);
|
||||
|
||||
rhs.indent_level = -1;
|
||||
rhs.naked_newline = true;
|
||||
rhs.key_path.clear();
|
||||
auto fw = impl::formatter_writer{ lhs };
|
||||
rhs.writer = &fw;
|
||||
rhs.write(rhs.source);
|
||||
|
||||
return lhs;
|
||||
}
|
||||
};
|
||||
|
||||
inline void default_formatter::write_inline(const toml::table& tab) const TOML_MAY_THROW
|
||||
{
|
||||
if (tab.values.empty())
|
||||
write("{}"sv);
|
||||
else
|
||||
{
|
||||
write("{ "sv);
|
||||
|
||||
bool first = false;
|
||||
for (auto& [k, v] : tab.values)
|
||||
{
|
||||
if (first)
|
||||
{
|
||||
write(", "sv);
|
||||
}
|
||||
first = true;
|
||||
|
||||
write_key_segment(k);
|
||||
write(" = "sv);
|
||||
|
||||
const auto type = v->type();
|
||||
switch (type)
|
||||
{
|
||||
case node_type::table: write_inline(*reinterpret_cast<const table*>(v.get())); break;
|
||||
case node_type::array: write(*reinterpret_cast<const array*>(v.get())); break;
|
||||
case node_type::string: write(*reinterpret_cast<const value<string>*>(v.get())); break;
|
||||
case node_type::integer: write(*reinterpret_cast<const value<int64_t>*>(v.get())); break;
|
||||
case node_type::floating_point: write(*reinterpret_cast<const value<double>*>(v.get())); break;
|
||||
case node_type::boolean: write(*reinterpret_cast<const value<bool>*>(v.get())); break;
|
||||
case node_type::date: write(*reinterpret_cast<const value<date>*>(v.get())); break;
|
||||
case node_type::time: write(*reinterpret_cast<const value<time>*>(v.get())); break;
|
||||
case node_type::date_time: write(*reinterpret_cast<const value<date_time>*>(v.get())); break;
|
||||
TOML_NO_DEFAULT_CASE;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
write(" }"sv);
|
||||
}
|
||||
naked_newline = false;
|
||||
}
|
||||
|
||||
template <typename CHAR>
|
||||
inline std::basic_ostream<CHAR>& operator << (std::basic_ostream<CHAR>& lhs, const table& rhs) TOML_MAY_THROW
|
||||
{
|
||||
static_assert(
|
||||
sizeof(CHAR) == 1,
|
||||
"The stream's underlying character type must be 1 byte in size."
|
||||
);
|
||||
|
||||
return lhs << default_formatter{ rhs };
|
||||
}
|
||||
}
|
132
include/toml++/toml_node.h
Normal file
132
include/toml++/toml_node.h
Normal file
@ -0,0 +1,132 @@
|
||||
#pragma once
|
||||
#include "toml_common.h"
|
||||
|
||||
namespace toml
|
||||
{
|
||||
class TOML_INTERFACE node
|
||||
{
|
||||
private:
|
||||
friend class impl::parser;
|
||||
source_region rgn{};
|
||||
|
||||
protected:
|
||||
|
||||
node(node&& other) noexcept
|
||||
: rgn{ std::move(other.rgn) }
|
||||
{}
|
||||
|
||||
node& operator= (node&& rhs) noexcept
|
||||
{
|
||||
rgn = std::move(rhs.rgn);
|
||||
return *this;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
node() noexcept = default;
|
||||
node(const node&) = delete;
|
||||
node& operator= (const node&) = delete;
|
||||
virtual ~node() noexcept = default;
|
||||
|
||||
[[nodiscard]] virtual bool is_value() const noexcept { return false; }
|
||||
[[nodiscard]] virtual bool is_string() const noexcept { return false; }
|
||||
[[nodiscard]] virtual bool is_integer() const noexcept { return false; }
|
||||
[[nodiscard]] virtual bool is_floating_point() const noexcept { return false; }
|
||||
[[nodiscard]] virtual bool is_boolean() const noexcept { return false; }
|
||||
[[nodiscard]] virtual bool is_date() const noexcept { return false; }
|
||||
[[nodiscard]] virtual bool is_time() const noexcept { return false; }
|
||||
[[nodiscard]] virtual bool is_date_time() const noexcept { return false; }
|
||||
[[nodiscard]] virtual bool is_array() const noexcept { return false; }
|
||||
[[nodiscard]] virtual bool is_table() const noexcept { return false; }
|
||||
[[nodiscard]] virtual bool is_array_of_tables() const noexcept { return false; }
|
||||
|
||||
template <typename T>
|
||||
[[nodiscard]] bool is() const noexcept
|
||||
{
|
||||
using type = T;
|
||||
static_assert(
|
||||
impl::is_value_or_node<type>,
|
||||
"Template type parameter must be one of the basic value types, a toml::table, or a toml::array"
|
||||
);
|
||||
|
||||
if constexpr (std::is_same_v<type, 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();
|
||||
else if constexpr (std::is_same_v<type, array>) return is_array();
|
||||
else if constexpr (std::is_same_v<type, table>) return is_table();
|
||||
}
|
||||
|
||||
[[nodiscard]] virtual value<string>* as_string() noexcept { return nullptr; }
|
||||
[[nodiscard]] virtual value<int64_t>* as_integer() noexcept { return nullptr; }
|
||||
[[nodiscard]] virtual value<double>* as_floating_point() noexcept { return nullptr; }
|
||||
[[nodiscard]] virtual value<bool>* as_boolean() noexcept { return nullptr; }
|
||||
[[nodiscard]] virtual value<date>* as_date() noexcept { return nullptr; }
|
||||
[[nodiscard]] virtual value<time>* as_time() noexcept { return nullptr; }
|
||||
[[nodiscard]] virtual value<date_time>* as_date_time() noexcept { return nullptr; }
|
||||
[[nodiscard]] virtual array* as_array() noexcept { return nullptr; }
|
||||
[[nodiscard]] virtual table* as_table() noexcept { return nullptr; }
|
||||
|
||||
|
||||
[[nodiscard]] virtual const value<string>* as_string() const noexcept { return nullptr; }
|
||||
[[nodiscard]] virtual const value<int64_t>* as_integer() const noexcept { return nullptr; }
|
||||
[[nodiscard]] virtual const value<double>* as_floating_point() const noexcept { return nullptr; }
|
||||
[[nodiscard]] virtual const value<bool>* as_boolean() const noexcept { return nullptr; }
|
||||
[[nodiscard]] virtual const value<date>* as_date() const noexcept { return nullptr; }
|
||||
[[nodiscard]] virtual const value<time>* as_time() const noexcept { return nullptr; }
|
||||
[[nodiscard]] virtual const value<date_time>* as_date_time() const noexcept { return nullptr; }
|
||||
[[nodiscard]] virtual const array* as_array() const noexcept { return nullptr; }
|
||||
[[nodiscard]] virtual const table* as_table() const noexcept { return nullptr; }
|
||||
|
||||
template <typename T>
|
||||
[[nodiscard]] node_of<T>* as() noexcept
|
||||
{
|
||||
using type = T;
|
||||
static_assert(
|
||||
impl::is_value_or_node<type>,
|
||||
"Template type parameter must be one of the basic value types, a toml::table, or a toml::array"
|
||||
);
|
||||
|
||||
if constexpr (std::is_same_v<type, 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();
|
||||
else if constexpr (std::is_same_v<type, array>) return as_array();
|
||||
else if constexpr (std::is_same_v<type, table>) return as_table();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
[[nodiscard]] const node_of<T>* as() const noexcept
|
||||
{
|
||||
using type = T;
|
||||
static_assert(
|
||||
impl::is_value_or_node<type>,
|
||||
"Template type parameter must be one of the basic value types, a toml::table, or a toml::array"
|
||||
);
|
||||
|
||||
if constexpr (std::is_same_v<type, 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();
|
||||
else if constexpr (std::is_same_v<type, array>) return as_array();
|
||||
else if constexpr (std::is_same_v<type, table>) return as_table();
|
||||
}
|
||||
|
||||
[[nodiscard]] virtual node_type type() const noexcept = 0;
|
||||
|
||||
[[nodiscard]]
|
||||
const source_region& region() const noexcept
|
||||
{
|
||||
return rgn;
|
||||
}
|
||||
};
|
||||
}
|
312
include/toml++/toml_node_view.h
Normal file
312
include/toml++/toml_node_view.h
Normal file
@ -0,0 +1,312 @@
|
||||
#pragma once
|
||||
#include "toml_table.h"
|
||||
#include "toml_array.h"
|
||||
#include "toml_value.h"
|
||||
|
||||
namespace toml::impl
|
||||
{
|
||||
template <typename T>
|
||||
struct node_view_traits;
|
||||
|
||||
template <>
|
||||
struct node_view_traits<const table>
|
||||
{
|
||||
using member_type = const table*;
|
||||
using key_type = string_view;
|
||||
|
||||
[[nodiscard]]
|
||||
static const node* get(const table* tbl, key_type key) noexcept
|
||||
{
|
||||
return tbl->get(key);
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
[[nodiscard]]
|
||||
static const node_of<U>* as(const table* tbl, key_type key) noexcept
|
||||
{
|
||||
return tbl->get_as<U>(key);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct node_view_traits<table>
|
||||
{
|
||||
using member_type = table*;
|
||||
using key_type = string_view;
|
||||
|
||||
[[nodiscard]]
|
||||
static node* get(table* tbl, key_type key) noexcept
|
||||
{
|
||||
return tbl->get(key);
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
static const node* get(const table* tbl, key_type key) noexcept
|
||||
{
|
||||
return tbl->get(key);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
[[nodiscard]]
|
||||
static node_of<T>* as(table* tbl, key_type key) noexcept
|
||||
{
|
||||
return tbl->get_as<T>(key);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
[[nodiscard]]
|
||||
static const node_of<T>* as(const table* tbl, key_type key) noexcept
|
||||
{
|
||||
return tbl->get_as<T>(key);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, typename K>
|
||||
struct sub_view final { };
|
||||
|
||||
template <typename T>
|
||||
struct node_view_traits<sub_view<T, string_view>>
|
||||
{
|
||||
using member_type = T;
|
||||
using key_type = string_view;
|
||||
|
||||
[[nodiscard]]
|
||||
static auto get(member_type& view, string_view key) noexcept
|
||||
{
|
||||
auto parent = view.as_table();
|
||||
return parent ? parent->get(key) : nullptr;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
static const node* get(const member_type& view, string_view key) noexcept
|
||||
{
|
||||
auto parent = view.as_table();
|
||||
return parent ? parent->get(key) : nullptr;
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
[[nodiscard]]
|
||||
static auto as(member_type& view, string_view key) noexcept
|
||||
{
|
||||
auto parent = view.as_table();
|
||||
return parent ? parent->template get_as<U>(key) : nullptr;
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
[[nodiscard]]
|
||||
static const node_of<U>* as(const member_type& view, string_view key) noexcept
|
||||
{
|
||||
auto parent = view.as_table();
|
||||
return parent ? parent->template get_as<U>(key) : nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct node_view_traits<sub_view<T, size_t>>
|
||||
{
|
||||
using member_type = T;
|
||||
using key_type = size_t;
|
||||
|
||||
[[nodiscard]]
|
||||
static auto get(member_type& view, size_t index) noexcept
|
||||
{
|
||||
auto parent = view.as_array();
|
||||
return parent ? parent->get(index) : nullptr;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
static const node* get(const member_type& view, size_t index) noexcept
|
||||
{
|
||||
auto parent = view.as_array();
|
||||
return parent ? parent->get(index) : nullptr;
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
[[nodiscard]]
|
||||
static auto as(member_type& view, size_t index) noexcept
|
||||
{
|
||||
auto parent = view.as_array();
|
||||
return parent ? parent->template get_as<U>(index) : nullptr;
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
[[nodiscard]]
|
||||
static const node_of<U>* as(const member_type& view, size_t index) noexcept
|
||||
{
|
||||
auto parent = view.as_array();
|
||||
return parent ? parent->template get_as<U>(index) : nullptr;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
namespace toml
|
||||
{
|
||||
template <typename T>
|
||||
class node_view final
|
||||
{
|
||||
public:
|
||||
using traits = impl::node_view_traits<T>;
|
||||
using key_type = typename traits::key_type;
|
||||
|
||||
private:
|
||||
using member_type = typename traits::member_type;
|
||||
member_type obj_;
|
||||
key_type key_;
|
||||
|
||||
public:
|
||||
|
||||
TOML_NODISCARD_CTOR
|
||||
node_view(member_type obj, key_type key) noexcept
|
||||
: obj_{ obj },
|
||||
key_{ key }
|
||||
{}
|
||||
|
||||
[[nodiscard]] auto get() noexcept { return traits::get(obj_, key_); }
|
||||
[[nodiscard]] const node* get() const noexcept { return traits::get(obj_, key_); }
|
||||
|
||||
[[nodiscard]] explicit operator bool() const noexcept { return !!get(); }
|
||||
|
||||
template <typename U>
|
||||
[[nodiscard]]
|
||||
auto as() noexcept
|
||||
{
|
||||
static_assert(
|
||||
impl::is_value_or_node<U>,
|
||||
"Template type parameter must be one of the basic value types, a toml::table, or a toml::array"
|
||||
);
|
||||
|
||||
return traits::template as<U>(obj_, key_);
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
[[nodiscard]]
|
||||
const node_of<U>* as() const noexcept
|
||||
{
|
||||
static_assert(
|
||||
impl::is_value_or_node<U>,
|
||||
"Template type parameter must be one of the basic value types, a toml::table, or a toml::array"
|
||||
);
|
||||
|
||||
return traits::template as<U>(obj_, key_);
|
||||
}
|
||||
|
||||
[[nodiscard]] auto as_string() noexcept { return as<string>(); }
|
||||
[[nodiscard]] auto as_integer() noexcept { return as<int64_t>(); }
|
||||
[[nodiscard]] auto as_floating_point() noexcept { return as<double>(); }
|
||||
[[nodiscard]] auto as_boolean() noexcept { return as<bool>(); }
|
||||
[[nodiscard]] auto as_date() noexcept { return as<date>(); }
|
||||
[[nodiscard]] auto as_time() noexcept { return as<time>(); }
|
||||
[[nodiscard]] auto as_date_time() noexcept { return as<date_time>(); }
|
||||
[[nodiscard]] auto as_array() noexcept { return as<array>(); }
|
||||
[[nodiscard]] auto as_table() noexcept { return as<table>(); }
|
||||
|
||||
[[nodiscard]] const value<string>* as_string() const noexcept { return as<string>(); }
|
||||
[[nodiscard]] const value<int64_t>* as_integer() const noexcept { return as<int64_t>(); }
|
||||
[[nodiscard]] const value<double>* as_floating_point() const noexcept { return as<double>(); }
|
||||
[[nodiscard]] const value<bool>* as_boolean() const noexcept { return as<bool>(); }
|
||||
[[nodiscard]] const value<date>* as_date() const noexcept { return as<date>(); }
|
||||
[[nodiscard]] const value<time>* as_time() const noexcept { return as<time>(); }
|
||||
[[nodiscard]] const value<date_time>* as_date_time() const noexcept { return as<date_time>(); }
|
||||
[[nodiscard]] const array* as_array() const noexcept { return as<array>(); }
|
||||
[[nodiscard]] const table* as_table() const noexcept { return as<table>(); }
|
||||
|
||||
private:
|
||||
|
||||
template <typename U>
|
||||
[[nodiscard]]
|
||||
static bool value_equality(const node_view& lhs, const U& rhs) noexcept
|
||||
{
|
||||
const auto val = lhs.as<value_of<U>>();
|
||||
return val && val->get() == rhs;
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
[[nodiscard]]
|
||||
static bool container_equality(const node_view& lhs, const U& rhs) noexcept
|
||||
{
|
||||
using elem_t = std::remove_const_t<typename U::value_type>;
|
||||
|
||||
static_assert(
|
||||
impl::is_value_or_promotable<elem_t>,
|
||||
"Container element type must be (or be convertible to) one of the basic value types"
|
||||
);
|
||||
|
||||
const array* arr = lhs.as<array>();
|
||||
if (!arr || arr->size() != rhs.size())
|
||||
return false;
|
||||
if (rhs.size() == 0_sz)
|
||||
return true;
|
||||
|
||||
size_t i{};
|
||||
for (auto& list_elem : rhs)
|
||||
{
|
||||
const auto elem = arr->get_as<value_of<elem_t>>(i++);
|
||||
if (!elem || elem->get() != list_elem)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
[[nodiscard]] bool operator == (const string& rhs) const noexcept { return value_equality(*this, rhs); }
|
||||
[[nodiscard]] bool operator == (string_view rhs) const noexcept { return value_equality(*this, rhs); }
|
||||
[[nodiscard]] bool operator == (int64_t rhs) const noexcept { return value_equality(*this, rhs); }
|
||||
[[nodiscard]] bool operator == (int32_t rhs) const noexcept { return value_equality(*this, rhs); }
|
||||
[[nodiscard]] bool operator == (int16_t rhs) const noexcept { return value_equality(*this, rhs); }
|
||||
[[nodiscard]] bool operator == (int8_t rhs) const noexcept { return value_equality(*this, rhs); }
|
||||
[[nodiscard]] bool operator == (uint32_t rhs) const noexcept { return value_equality(*this, rhs); }
|
||||
[[nodiscard]] bool operator == (uint16_t rhs) const noexcept { return value_equality(*this, rhs); }
|
||||
[[nodiscard]] bool operator == (uint8_t rhs) const noexcept { return value_equality(*this, rhs); }
|
||||
[[nodiscard]] bool operator == (double rhs) const noexcept { return value_equality(*this, rhs); }
|
||||
[[nodiscard]] bool operator == (float rhs) const noexcept { return value_equality(*this, rhs); }
|
||||
[[nodiscard]] bool operator == (bool rhs) const noexcept { return value_equality(*this, rhs); }
|
||||
[[nodiscard]] bool operator == (const date& rhs) const noexcept { return value_equality(*this, rhs); }
|
||||
[[nodiscard]] bool operator == (const time& rhs) const noexcept { return value_equality(*this, rhs); }
|
||||
[[nodiscard]] bool operator == (const date_time& rhs) const noexcept { return value_equality(*this, rhs); }
|
||||
|
||||
template <typename U>
|
||||
[[nodiscard]]
|
||||
bool operator == (const std::initializer_list<U>& rhs) const noexcept
|
||||
{
|
||||
return container_equality(*this, rhs);
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
[[nodiscard]]
|
||||
bool operator == (const std::vector<U>& rhs) const noexcept
|
||||
{
|
||||
return container_equality(*this, rhs);
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
[[nodiscard]]
|
||||
friend bool operator == (const U& lhs, const node_view& rhs) noexcept
|
||||
{
|
||||
return rhs == lhs;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
node_view<impl::sub_view<node_view<T>, string_view>> operator[] (string_view key) noexcept
|
||||
{
|
||||
return { *this, key };
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
node_view<impl::sub_view<node_view<T>, size_t>> operator[] (size_t index) noexcept
|
||||
{
|
||||
return { *this, index };
|
||||
}
|
||||
};
|
||||
|
||||
inline node_view<table> table::operator[] (string_view key) noexcept
|
||||
{
|
||||
return { this, key };
|
||||
}
|
||||
|
||||
inline node_view<const table> table::operator[] (string_view key) const noexcept
|
||||
{
|
||||
return { this, key };
|
||||
}
|
||||
}
|
2801
include/toml++/toml_parser.h
Normal file
2801
include/toml++/toml_parser.h
Normal file
File diff suppressed because it is too large
Load Diff
82
include/toml++/toml_table.h
Normal file
82
include/toml++/toml_table.h
Normal file
@ -0,0 +1,82 @@
|
||||
#pragma once
|
||||
#include "toml_node.h"
|
||||
|
||||
namespace toml
|
||||
{
|
||||
class table final
|
||||
: public node
|
||||
{
|
||||
private:
|
||||
friend class impl::parser;
|
||||
friend class default_formatter;
|
||||
friend class node_view<table>;
|
||||
|
||||
string_map<std::unique_ptr<node>> values;
|
||||
bool inline_ = false;
|
||||
|
||||
public:
|
||||
|
||||
TOML_NODISCARD_CTOR
|
||||
table() noexcept {}
|
||||
|
||||
TOML_NODISCARD_CTOR
|
||||
table(table&& other) noexcept
|
||||
: node{ std::move(other) },
|
||||
values{ std::move(other.values) },
|
||||
inline_ { other.inline_ }
|
||||
{}
|
||||
|
||||
table& operator= (table&& rhs) noexcept
|
||||
{
|
||||
node::operator=(std::move(rhs));
|
||||
values = std::move(rhs.values);
|
||||
inline_ = rhs.inline_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
[[nodiscard]] bool is_table() const noexcept override { return true; }
|
||||
[[nodiscard]] bool is_inline() const noexcept { return inline_; }
|
||||
|
||||
[[nodiscard]] table* as_table() noexcept override { return this; }
|
||||
[[nodiscard]] const table* as_table() const noexcept override { return this; }
|
||||
|
||||
[[nodiscard]] node_type type() const noexcept override { return node_type::table; }
|
||||
|
||||
[[nodiscard]] size_t size() const noexcept { return values.size(); }
|
||||
|
||||
[[nodiscard]]
|
||||
node* get(string_view key) noexcept
|
||||
{
|
||||
if (auto it = values.find(key); it != values.end())
|
||||
return it->second.get();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
const node* get(string_view key) const noexcept
|
||||
{
|
||||
if (auto it = values.find(key); it != values.end())
|
||||
return it->second.get();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
[[nodiscard]]
|
||||
node_of<T>* get_as(string_view key) noexcept
|
||||
{
|
||||
const auto node = get(key);
|
||||
return node ? node->as<T>() : nullptr;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
[[nodiscard]]
|
||||
const node_of<T>* get_as(string_view key) const noexcept
|
||||
{
|
||||
const auto node = get(key);
|
||||
return node ? node->as<T>() : nullptr;
|
||||
}
|
||||
|
||||
[[nodiscard]] inline node_view<table> operator[] (string_view) noexcept;
|
||||
[[nodiscard]] inline node_view<const table> operator[] (string_view) const noexcept;
|
||||
};
|
||||
}
|
600
include/toml++/toml_utf8.h
Normal file
600
include/toml++/toml_utf8.h
Normal file
@ -0,0 +1,600 @@
|
||||
#pragma once
|
||||
#include "toml_common.h"
|
||||
#if TOML_LANG_HIGHER_THAN(0, 5, 0) // toml/issues/687
|
||||
#include "toml_utf8_generated.h"
|
||||
#endif // TOML_LANG_HIGHER_THAN(0, 5, 0)
|
||||
|
||||
namespace toml::impl
|
||||
{
|
||||
[[nodiscard]]
|
||||
constexpr bool is_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'\t'
|
||||
|| codepoint == U' '
|
||||
|| 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
|
||||
;
|
||||
}
|
||||
|
||||
template <bool CR = true>
|
||||
[[nodiscard]]
|
||||
constexpr bool is_line_break(char32_t codepoint) noexcept
|
||||
{
|
||||
// see https://en.wikipedia.org/wiki/Whitespace_character#Unicode
|
||||
// (characters that say "is a line-break")
|
||||
|
||||
constexpr auto low_range_end = CR ? U'\r' : U'\f';
|
||||
|
||||
return (codepoint >= U'\n' && codepoint <= low_range_end)
|
||||
|| codepoint == U'\u0085' // next line
|
||||
|| codepoint == U'\u2028' // line separator
|
||||
|| codepoint == U'\u2029' // paragraph separator
|
||||
;
|
||||
}
|
||||
|
||||
[[nodiscard]] TOML_ALWAYS_INLINE
|
||||
constexpr bool is_string_delimiter(char32_t codepoint) noexcept
|
||||
{
|
||||
return codepoint == U'"'
|
||||
|| codepoint == U'\'';
|
||||
}
|
||||
|
||||
[[nodiscard]] TOML_ALWAYS_INLINE
|
||||
constexpr bool is_ascii_letter(char32_t codepoint) noexcept
|
||||
{
|
||||
return (codepoint >= U'a' && codepoint <= U'z')
|
||||
|| (codepoint >= U'A' && codepoint <= U'Z');
|
||||
}
|
||||
|
||||
[[nodiscard]] TOML_ALWAYS_INLINE
|
||||
constexpr bool is_binary_digit(char32_t codepoint) noexcept
|
||||
{
|
||||
return codepoint == U'0' || codepoint == U'1';
|
||||
}
|
||||
|
||||
[[nodiscard]] TOML_ALWAYS_INLINE
|
||||
constexpr bool is_octal_digit(char32_t codepoint) noexcept
|
||||
{
|
||||
return (codepoint >= U'0' && codepoint <= U'7');
|
||||
}
|
||||
|
||||
[[nodiscard]] TOML_ALWAYS_INLINE
|
||||
constexpr bool is_decimal_digit(char32_t codepoint) noexcept
|
||||
{
|
||||
return (codepoint >= U'0' && codepoint <= U'9');
|
||||
}
|
||||
|
||||
[[nodiscard]] TOML_ALWAYS_INLINE
|
||||
constexpr bool is_hex_digit(char32_t codepoint) noexcept
|
||||
{
|
||||
return (codepoint >= U'a' && codepoint <= U'f')
|
||||
|| (codepoint >= U'A' && codepoint <= U'F')
|
||||
|| is_decimal_digit(codepoint);
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr bool is_bare_key_start_character(char32_t codepoint) noexcept
|
||||
{
|
||||
return is_ascii_letter(codepoint)
|
||||
|| is_decimal_digit(codepoint)
|
||||
|| codepoint == U'-'
|
||||
|| codepoint == U'_'
|
||||
#if TOML_LANG_HIGHER_THAN(0, 5, 0) // toml/issues/644 & toml/issues/687
|
||||
|| codepoint == U'+'
|
||||
|| is_unicode_letter(codepoint)
|
||||
|| is_unicode_number(codepoint)
|
||||
#endif
|
||||
;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr bool is_bare_key_character(char32_t codepoint) noexcept
|
||||
{
|
||||
return is_bare_key_start_character(codepoint)
|
||||
#if TOML_LANG_HIGHER_THAN(0, 5, 0) // toml/issues/687
|
||||
|| is_unicode_combining_mark(codepoint)
|
||||
#endif
|
||||
;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr bool is_value_terminator(char32_t codepoint) noexcept
|
||||
{
|
||||
return is_line_break(codepoint)
|
||||
|| is_whitespace(codepoint)
|
||||
|| codepoint == U']'
|
||||
|| codepoint == U'}'
|
||||
|| codepoint == U','
|
||||
|| codepoint == U'#'
|
||||
;
|
||||
}
|
||||
|
||||
struct utf8_decoder final
|
||||
{
|
||||
// This decoder is based on code from here: http://bjoern.hoehrmann.de/utf-8/decoder/dfa/
|
||||
//
|
||||
// License:
|
||||
//
|
||||
// Copyright (c) 2008-2009 Bjoern Hoehrmann <bjoern@hoehrmann.de>
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
|
||||
// software and associated documentation files (the "Software"), to deal in the Software
|
||||
// without restriction, including without limitation the rights to use, copy, modify, merge,
|
||||
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
// persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all copies
|
||||
// or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
|
||||
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
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]] TOML_ALWAYS_INLINE
|
||||
constexpr bool error() const noexcept
|
||||
{
|
||||
return state == uint_least32_t{ 12u };
|
||||
}
|
||||
|
||||
[[nodiscard]] TOML_ALWAYS_INLINE
|
||||
constexpr bool has_code_point() const noexcept
|
||||
{
|
||||
return state == uint_least32_t{};
|
||||
}
|
||||
|
||||
[[nodiscard]] TOML_ALWAYS_INLINE
|
||||
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];
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class utf8_byte_stream;
|
||||
|
||||
template <typename CHAR>
|
||||
class 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 }
|
||||
{
|
||||
if (source.length() >= 3_sz
|
||||
&& static_cast<uint8_t>(source[0]) == 0xEF_u8
|
||||
&& static_cast<uint8_t>(source[1]) == 0xBB_u8
|
||||
&& static_cast<uint8_t>(source[2]) == 0xBF_u8)
|
||||
{
|
||||
position += 3_sz;
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr bool eof() const noexcept
|
||||
{
|
||||
return position >= source.length();
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr bool error() const noexcept
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr std::optional<uint8_t> operator() () noexcept
|
||||
{
|
||||
if (position >= source.length())
|
||||
return {};
|
||||
return static_cast<uint8_t>(source[position++]);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename CHAR>
|
||||
class 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) TOML_MAY_THROW
|
||||
: source{ &stream }
|
||||
{
|
||||
if (*source)
|
||||
{
|
||||
static constexpr uint8_t bom[] {
|
||||
0xEF_u8,
|
||||
0xBB_u8,
|
||||
0xBF_u8
|
||||
};
|
||||
|
||||
using stream_traits = typename std::remove_pointer_t<decltype(source)>::traits_type;
|
||||
const auto initial_pos = source->tellg();
|
||||
size_t bom_pos{};
|
||||
auto bom_char = source->get();
|
||||
while (*source && bom_char != stream_traits::eof() && bom_char == bom[bom_pos])
|
||||
{
|
||||
bom_pos++;
|
||||
bom_char = source->get();
|
||||
}
|
||||
if (!(*source) || bom_pos < 3_sz)
|
||||
source->seekg(initial_pos);
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
bool eof() const noexcept
|
||||
{
|
||||
return source->eof();
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
bool error() const noexcept
|
||||
{
|
||||
return !(*source);
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
std::optional<uint8_t> operator() () TOML_MAY_THROW
|
||||
{
|
||||
auto val = source->get();
|
||||
if (val == std::basic_istream<CHAR>::traits_type::eof())
|
||||
return {};
|
||||
return static_cast<uint8_t>(val);
|
||||
}
|
||||
};
|
||||
|
||||
struct utf8_codepoint final
|
||||
{
|
||||
char32_t value;
|
||||
uint8_t bytes[4];
|
||||
toml::source_position position;
|
||||
|
||||
template <typename CHAR = toml::string_char>
|
||||
[[nodiscard]] TOML_ALWAYS_INLINE
|
||||
std::basic_string_view<CHAR> as_view() const noexcept
|
||||
{
|
||||
static_assert(
|
||||
sizeof(CHAR) == 1,
|
||||
"The string view's underlying character type must be 1 byte in size."
|
||||
);
|
||||
|
||||
return bytes[3]
|
||||
? std::basic_string_view<CHAR>{ reinterpret_cast<const CHAR* const>(bytes), 4_sz }
|
||||
: std::basic_string_view<CHAR>{ reinterpret_cast<const CHAR* const>(bytes) };
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr operator char32_t& () noexcept
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr operator const char32_t& () const noexcept
|
||||
{
|
||||
return value;
|
||||
}
|
||||
};
|
||||
static_assert(std::is_trivial_v<utf8_codepoint>);
|
||||
static_assert(std::is_standard_layout_v<utf8_codepoint>);
|
||||
|
||||
#if TOML_EXCEPTIONS
|
||||
#define TOML_ERROR_CHECK (void)0
|
||||
#define TOML_ERROR(...) throw toml::parse_error( __VA_ARGS__ )
|
||||
#else
|
||||
#define TOML_ERROR_CHECK if (err) return nullptr
|
||||
#define TOML_ERROR(...) err.emplace( __VA_ARGS__ )
|
||||
#endif
|
||||
|
||||
struct TOML_INTERFACE utf8_reader_interface
|
||||
{
|
||||
[[nodiscard]]
|
||||
virtual const std::shared_ptr<const std::string>& source_path() const noexcept = 0;
|
||||
|
||||
[[nodiscard]]
|
||||
virtual const utf8_codepoint* read_next() TOML_MAY_THROW = 0;
|
||||
|
||||
#if !TOML_EXCEPTIONS
|
||||
|
||||
[[nodiscard]]
|
||||
virtual std::optional<toml::parse_error>&& error() noexcept = 0;
|
||||
|
||||
#endif
|
||||
|
||||
virtual ~utf8_reader_interface() noexcept = default;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class TOML_EMPTY_BASES utf8_reader final
|
||||
: public utf8_reader_interface
|
||||
{
|
||||
private:
|
||||
utf8_byte_stream<T> stream;
|
||||
utf8_decoder decoder;
|
||||
utf8_codepoint prev{}, current{};
|
||||
uint8_t current_byte_count{};
|
||||
std::shared_ptr<const std::string> source_path_;
|
||||
#if !TOML_EXCEPTIONS
|
||||
std::optional<toml::parse_error> err;
|
||||
#endif
|
||||
|
||||
public:
|
||||
|
||||
template <typename U, typename STR = std::string_view>
|
||||
explicit utf8_reader(U && source, STR&& source_path = {})
|
||||
TOML_CONDITIONAL_NOEXCEPT(std::is_nothrow_constructible_v<utf8_byte_stream<T>, U&&>)
|
||||
: stream{ std::forward<U>(source) }
|
||||
{
|
||||
current.position = { 1u, 1u };
|
||||
|
||||
if (!source_path.empty())
|
||||
source_path_ = std::make_shared<const std::string>(std::forward<STR>(source_path));
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
const std::shared_ptr<const std::string>& source_path() const noexcept override
|
||||
{
|
||||
return source_path_;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
const utf8_codepoint* read_next() TOML_MAY_THROW override
|
||||
{
|
||||
TOML_ERROR_CHECK;
|
||||
|
||||
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)
|
||||
{
|
||||
std::optional<uint8_t> nextByte;
|
||||
if constexpr (!TOML_EXCEPTIONS || noexcept(stream()))
|
||||
{
|
||||
nextByte = stream();
|
||||
}
|
||||
#if TOML_EXCEPTIONS
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
nextByte = stream();
|
||||
}
|
||||
catch (const std::exception& exc)
|
||||
{
|
||||
throw toml::parse_error{ exc.what(), prev.position, source_path_ };
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
throw toml::parse_error{ "An unspecified error occurred", prev.position, source_path_ };
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!nextByte)
|
||||
{
|
||||
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;
|
||||
|
||||
decoder(*nextByte);
|
||||
if (decoder.error())
|
||||
TOML_ERROR( "Encountered invalid utf-8 sequence", prev.position, source_path_ );
|
||||
|
||||
TOML_ERROR_CHECK;
|
||||
|
||||
current.bytes[current_byte_count++] = *nextByte;
|
||||
if (decoder.has_code_point())
|
||||
{
|
||||
current.value = decoder.codepoint;
|
||||
prev = current;
|
||||
std::memset(current.bytes, 0, sizeof(current.bytes));
|
||||
current_byte_count = {};
|
||||
|
||||
if (is_line_break<false>(prev.value))
|
||||
{
|
||||
current.position.line++;
|
||||
current.position.column = 1u;
|
||||
}
|
||||
else
|
||||
current.position.column++;
|
||||
|
||||
return &prev;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if !TOML_EXCEPTIONS
|
||||
|
||||
[[nodiscard]]
|
||||
std::optional<toml::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_istream<CHAR>&, std::string_view) -> utf8_reader<std::basic_istream<CHAR>>;
|
||||
|
||||
template <typename CHAR>
|
||||
utf8_reader(std::basic_string_view<CHAR>, std::string&&) -> utf8_reader<std::basic_string_view<CHAR>>;
|
||||
|
||||
template <typename CHAR>
|
||||
utf8_reader(std::basic_istream<CHAR>&, std::string&&) -> utf8_reader<std::basic_istream<CHAR>>;
|
||||
|
||||
#if !TOML_EXCEPTIONS
|
||||
#undef TOML_ERROR_CHECK
|
||||
#define TOML_ERROR_CHECK if (reader.error()) return nullptr
|
||||
#endif
|
||||
|
||||
class TOML_EMPTY_BASES utf8_buffered_reader final
|
||||
: public utf8_reader_interface
|
||||
{
|
||||
public:
|
||||
static constexpr auto max_history_length = 64_sz;
|
||||
|
||||
private:
|
||||
static constexpr auto history_buffer_size = max_history_length - 1_sz; //the 'head' is stored in the underlying 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
|
||||
: reader{ reader_ }
|
||||
{}
|
||||
|
||||
[[nodiscard]]
|
||||
const std::shared_ptr<const std::string>& source_path() const noexcept override
|
||||
{
|
||||
return reader.source_path();
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
const utf8_codepoint* read_next() TOML_MAY_THROW override
|
||||
{
|
||||
TOML_ERROR_CHECK;
|
||||
|
||||
if (negative_offset)
|
||||
{
|
||||
negative_offset--;
|
||||
|
||||
// an entry negative offset of 1 just means "replay the current head"
|
||||
if (!negative_offset)
|
||||
return head;
|
||||
|
||||
// otherwise step back into the history buffer
|
||||
else
|
||||
return history.buffer + ((history.first + history.count - negative_offset) % history_buffer_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
// first character read from stream
|
||||
if (!history.count && !head) TOML_UNLIKELY
|
||||
head = reader.read_next();
|
||||
|
||||
// subsequent characters and not eof
|
||||
else if (head)
|
||||
{
|
||||
if (history.count < history_buffer_size) TOML_UNLIKELY
|
||||
history.buffer[history.count++] = *head;
|
||||
else
|
||||
history.buffer[(history.first++ + history_buffer_size) % history_buffer_size] = *head;
|
||||
|
||||
head = reader.read_next();
|
||||
}
|
||||
|
||||
return head;
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
const utf8_codepoint* step_back(size_t count) noexcept
|
||||
{
|
||||
TOML_ERROR_CHECK;
|
||||
TOML_ASSERT(history.count);
|
||||
TOML_ASSERT(negative_offset + count <= history.count);
|
||||
|
||||
negative_offset += count;
|
||||
|
||||
return negative_offset
|
||||
? history.buffer + ((history.first + history.count - negative_offset) % history_buffer_size)
|
||||
: head;
|
||||
}
|
||||
|
||||
#if !TOML_EXCEPTIONS
|
||||
|
||||
[[nodiscard]]
|
||||
std::optional<toml::parse_error>&& error() noexcept override
|
||||
{
|
||||
return reader.error();
|
||||
}
|
||||
|
||||
#endif
|
||||
};
|
||||
|
||||
#undef TOML_ERROR_CHECK
|
||||
#undef TOML_ERROR
|
||||
}
|
||||
|
985
include/toml++/toml_utf8_generated.h
Normal file
985
include/toml++/toml_utf8_generated.h
Normal file
@ -0,0 +1,985 @@
|
||||
//# this file was generated by generate_unicode_functions.py
|
||||
#pragma once
|
||||
#include "toml_common.h"
|
||||
|
||||
#define TOML_ASSUME_CODEPOINT_BETWEEN(first, last) \
|
||||
TOML_ASSUME(codepoint >= first); \
|
||||
TOML_ASSUME(codepoint <= last)
|
||||
|
||||
namespace toml::impl
|
||||
{
|
||||
/// \brief Returns true if a codepoint belongs to any of these categories: Ll, Lm, Lo, Lt, Lu
|
||||
[[nodiscard]]
|
||||
constexpr bool is_unicode_letter(char32_t codepoint) noexcept
|
||||
{
|
||||
if (codepoint < U'\u00AA' || codepoint > U'\U0002FA1D')
|
||||
return false;
|
||||
|
||||
TOML_ASSUME_CODEPOINT_BETWEEN(U'\u00AA', U'\U0002FA1D');
|
||||
switch ((static_cast<uint_least32_t>(codepoint) - 0xAAu) / 3046u)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
if (codepoint > U'\u0C8F')
|
||||
return false;
|
||||
|
||||
TOML_ASSUME_CODEPOINT_BETWEEN(U'\u00AA', U'\u0C8F');
|
||||
switch ((static_cast<uint_least32_t>(codepoint) - 0xAAu) / 64u)
|
||||
{
|
||||
case 0: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0xAAull)) & 0xFFFFDFFFFFC10801ull;
|
||||
case 1: return codepoint != U'\u00F7';
|
||||
case 8: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0x2AAull)) & 0x7C000FFF0FFFFFFull;
|
||||
case 9: return codepoint != U'\u02EA';
|
||||
case 10: return false;
|
||||
case 11: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0x370ull)) & 0x3FBFFFFD740BCDFull;
|
||||
case 13: return codepoint != U'\u03F6';
|
||||
case 15: return codepoint <= U'\u0481' || codepoint >= U'\u048A';
|
||||
case 18: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0x52Aull)) & 0xFFC09FFFFFFFFFBFull;
|
||||
case 21: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0x5EAull)) & 0xFFC00000000001E1ull;
|
||||
case 23: return codepoint != U'\u066A';
|
||||
case 24: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0x6AAull)) & 0x18000BFFFFFFFFFFull;
|
||||
case 25: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0x6EEull)) & 0xFFFFFF400027003ull;
|
||||
case 26: return codepoint <= U'\u072F' || codepoint >= U'\u074D';
|
||||
case 28: return codepoint <= U'\u07B1' || codepoint >= U'\u07CA';
|
||||
case 29: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0x7EAull)) & 0x44010FFFFFC10C01ull;
|
||||
case 30: return codepoint <= U'\u0858' || codepoint >= U'\u0860';
|
||||
case 31: return codepoint <= U'\u086A' || codepoint >= U'\u08A0';
|
||||
case 32: return codepoint != U'\u08B5';
|
||||
case 34: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0x92Aull)) & 0xFFC0400008FFFFull;
|
||||
case 35: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0x971ull)) & 0xFFFFFCCFF0FFFFull;
|
||||
case 36: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0x9AAull)) & 0xEC00100008F17Full;
|
||||
case 37: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0x9F0ull)) & 0x1FFFFF987E01003ull;
|
||||
case 38: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0xA2Aull)) & 0x1780000000DB7Full;
|
||||
case 39: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0xA72ull)) & 0x7FFFFEEFF80007ull;
|
||||
case 40: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0xAAAull)) & 0xC000400008FB7Full;
|
||||
case 41: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0xAF9ull)) & 0xFFFFFCCFF001ull;
|
||||
case 42: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0xB2Aull)) & 0xEC00000008FB7Full;
|
||||
case 43: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0xB71ull)) & 0x18C6B1EE3F40001ull;
|
||||
case 44: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0xBAAull)) & 0x400000FFF1ull;
|
||||
case 45: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0xC05ull)) & 0xFFFFFEEFFull;
|
||||
case 46: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0xC2Aull)) & 0xC1C0000008FFFFull;
|
||||
case 47: return (1u << (static_cast<uint_least32_t>(codepoint) - 0xC80u)) & 0xDFE1u;
|
||||
default: return true;
|
||||
}
|
||||
// chunk summary: 1867 codepoints from 117 ranges (spanning a search area of 3046)
|
||||
}
|
||||
case 1:
|
||||
{
|
||||
if (codepoint < U'\u0C90' || codepoint > U'\u1875')
|
||||
return false;
|
||||
|
||||
TOML_ASSUME_CODEPOINT_BETWEEN(U'\u0C90', U'\u1875');
|
||||
switch ((static_cast<uint_least32_t>(codepoint) - 0xC90u) / 64u)
|
||||
{
|
||||
case 0: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0xC90ull)) & 0x23EFFDFFFFFDull;
|
||||
case 1: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0xCDEull)) & 0x37F800018000Dull;
|
||||
case 2: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0xD10ull)) & 0x400027FFFFFFFFFDull;
|
||||
case 3: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0xD54ull)) & 0xFFE0FC000003807ull;
|
||||
case 4: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0xD90ull)) & 0x7F2FFBFFFFFC7Full;
|
||||
case 6: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0xE10ull)) & 0x7F000DFFFFFFFFull;
|
||||
case 7: return (1u << (static_cast<uint_least32_t>(codepoint) - 0xE81u)) & 0x7BEBu;
|
||||
case 8: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0xE90ull)) & 0x5F200DFFAFFFFFull;
|
||||
case 9: return codepoint <= U'\u0EDF' || codepoint >= U'\u0F00';
|
||||
case 10: return codepoint != U'\u0F10';
|
||||
case 11: return codepoint <= U'\u0F6C' || codepoint >= U'\u0F88';
|
||||
case 12: return false;
|
||||
case 14: return codepoint <= U'\u102A' || codepoint >= U'\u103F';
|
||||
case 15: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0x1050ull)) & 0x4003FFE1C0623C3Full;
|
||||
case 16: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0x10A0ull)) & 0x20BFFFFFFFFFull;
|
||||
case 17: return codepoint != U'\u10FB';
|
||||
case 22: return codepoint != U'\u1249';
|
||||
case 23: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0x1250ull)) & 0x3DFFFFFFFFFF3D7Full;
|
||||
case 24: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0x1290ull)) & 0xFF3D7F3DFFFFFFFFull;
|
||||
case 25: return codepoint != U'\u12D7';
|
||||
case 26: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0x1310ull)) & 0xFFFFFFFFFFFFFF3Dull;
|
||||
case 27: return codepoint <= U'\u135A' || codepoint >= U'\u1380';
|
||||
case 29: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0x13D0ull)) & 0xFFFE3F3FFFFFFFFFull;
|
||||
case 39: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0x1650ull)) & 0xFFFEFFFF9FFFFFFFull;
|
||||
case 40: return codepoint <= U'\u169A' || codepoint >= U'\u16A0';
|
||||
case 41: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0x16D0ull)) & 0xDFFF01FE07FFFFFFull;
|
||||
case 42: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0x1710ull)) & 0xFFFF0003FFFF0003ull;
|
||||
case 43: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0x1750ull)) & 0xFFFF0001DFFF0003ull;
|
||||
case 45: return codepoint <= U'\u17D7' || codepoint >= U'\u17DC';
|
||||
default: return true;
|
||||
}
|
||||
// chunk summary: 2139 codepoints from 86 ranges (spanning a search area of 3046)
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
if (codepoint < U'\u1876' || codepoint > U'\u2184')
|
||||
return false;
|
||||
|
||||
TOML_ASSUME_CODEPOINT_BETWEEN(U'\u1876', U'\u2184');
|
||||
switch ((static_cast<uint_least32_t>(codepoint) - 0x1876u) / 63u)
|
||||
{
|
||||
case 0: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0x1876ull)) & 0x7C17FFFFFFFE7C07ull;
|
||||
case 2: return codepoint <= U'\u18F5' || codepoint >= U'\u1900';
|
||||
case 3: return codepoint <= U'\u196D' || codepoint >= U'\u1970';
|
||||
case 4: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0x1972ull)) & 0x43FFFFFFFFFFC007ull;
|
||||
case 6: return codepoint <= U'\u1A16' || codepoint >= U'\u1A20';
|
||||
case 9: return false;
|
||||
case 11: return codepoint <= U'\u1B33' || codepoint >= U'\u1B45';
|
||||
case 13: return codepoint <= U'\u1BAF' || codepoint >= U'\u1BBA';
|
||||
case 15: return codepoint <= U'\u1C4F' || codepoint >= U'\u1C5A';
|
||||
case 16: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0x1C66ull)) & 0x7FFFFC07FCFFFFFFull;
|
||||
case 17: return codepoint <= U'\u1CBA' || codepoint >= U'\u1CBD';
|
||||
case 18: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0x1CE9ull)) & 0x3FFFFFFFF8237EFull;
|
||||
case 26: return codepoint <= U'\u1F15' || codepoint >= U'\u1F18';
|
||||
case 27: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0x1F1Bull)) & 0x5FE7E7FFFFFFFFE7ull;
|
||||
case 28: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0x1F5Bull)) & 0x3FFFFFE7FFFFFFF5ull;
|
||||
case 29: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0x1F99ull)) & 0x678FEE2FEFFFFFFFull;
|
||||
case 30: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0x1FD8ull)) & 0x1FDC1FFF0Full;
|
||||
case 31: return false;
|
||||
case 32: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0x2071ull)) & 0xF80004001ull;
|
||||
case 34: return (1u << (static_cast<uint_least32_t>(codepoint) - 0x2102u)) & 0x1FF21u;
|
||||
case 35: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0x2113ull)) & 0x87C1E7FF7AA07C5ull;
|
||||
default: return true;
|
||||
}
|
||||
// chunk summary: 1328 codepoints from 65 ranges (spanning a search area of 2319)
|
||||
}
|
||||
case 3:
|
||||
{
|
||||
if (codepoint < U'\u2C00' || codepoint > U'\u3041')
|
||||
return false;
|
||||
|
||||
TOML_ASSUME_CODEPOINT_BETWEEN(U'\u2C00', U'\u3041');
|
||||
switch ((static_cast<uint_least32_t>(codepoint) - 0x2C00u) / 61u)
|
||||
{
|
||||
case 0: return codepoint != U'\u2C2F';
|
||||
case 1: return codepoint != U'\u2C5F';
|
||||
case 2: return true;
|
||||
case 3: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0x2CB7ull)) & 0x18F03FFFFFFFFFFFull;
|
||||
case 4: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0x2D00ull)) & 0x120BFFFFFFFFFull;
|
||||
case 5: return true;
|
||||
case 6: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0x2D6Full)) & 0xEFE00FFFFFE0001ull;
|
||||
case 7: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0x2DABull)) & 0xFEFEFEFEFEFEFull;
|
||||
case 9: return true;
|
||||
case 16: return true;
|
||||
case 17: return (1u << (static_cast<uint_least32_t>(codepoint) - 0x3031u)) & 0x10C1Fu;
|
||||
default: return false;
|
||||
}
|
||||
// chunk summary: 420 codepoints from 24 ranges (spanning a search area of 1090)
|
||||
}
|
||||
case 4:
|
||||
{
|
||||
if (codepoint < U'\u3042' || codepoint > U'\u3C27')
|
||||
return false;
|
||||
|
||||
TOML_ASSUME_CODEPOINT_BETWEEN(U'\u3042', U'\u3C27');
|
||||
switch ((static_cast<uint_least32_t>(codepoint) - 0x3042u) / 64u)
|
||||
{
|
||||
case 1: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0x3082ull)) & 0xFFFFFFFFB81FFFFFull;
|
||||
case 2: return codepoint != U'\u30FB';
|
||||
case 3: return codepoint != U'\u3102';
|
||||
case 5: return codepoint <= U'\u318E' || codepoint >= U'\u31A0';
|
||||
case 7: return false;
|
||||
case 8: return false;
|
||||
case 9: return false;
|
||||
case 10: return false;
|
||||
case 11: return false;
|
||||
case 12: return false;
|
||||
case 13: return false;
|
||||
default: return true;
|
||||
}
|
||||
// chunk summary: 2450 codepoints from 9 ranges (spanning a search area of 3046)
|
||||
}
|
||||
case 6: return codepoint <= U'\u4DB4' || codepoint >= U'\u4E00';
|
||||
case 13:
|
||||
{
|
||||
if (codepoint < U'\u9B58' || codepoint > U'\uA73D')
|
||||
return false;
|
||||
|
||||
TOML_ASSUME_CODEPOINT_BETWEEN(U'\u9B58', U'\uA73D');
|
||||
switch ((static_cast<uint_least32_t>(codepoint) - 0x9B58u) / 64u)
|
||||
{
|
||||
case 18: return codepoint <= U'\u9FEE' || codepoint >= U'\uA000';
|
||||
case 38: return codepoint <= U'\uA4FD' || codepoint >= U'\uA500';
|
||||
case 42: return codepoint <= U'\uA60C' || codepoint >= U'\uA610';
|
||||
case 43: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0xA618ull)) & 0xFFFFFF00000C00FFull;
|
||||
case 44: return codepoint <= U'\uA66E' || codepoint >= U'\uA67F';
|
||||
case 45: return codepoint <= U'\uA69D' || codepoint >= U'\uA6A0';
|
||||
case 46: return codepoint <= U'\uA6E5' || codepoint >= U'\uA717';
|
||||
case 47: return codepoint <= U'\uA71F' || codepoint >= U'\uA722';
|
||||
default: return true;
|
||||
}
|
||||
// chunk summary: 2858 codepoints from 11 ranges (spanning a search area of 3046)
|
||||
}
|
||||
case 14:
|
||||
{
|
||||
if (codepoint < U'\uA73E' || codepoint > U'\uB323')
|
||||
return false;
|
||||
|
||||
TOML_ASSUME_CODEPOINT_BETWEEN(U'\uA73E', U'\uB323');
|
||||
switch ((static_cast<uint_least32_t>(codepoint) - 0xA73Eu) / 64u)
|
||||
{
|
||||
case 1: return codepoint <= U'\uA788' || codepoint >= U'\uA78B';
|
||||
case 2: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0xA7BEull)) & 0xFE000000000001F3ull;
|
||||
case 3: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0xA7FEull)) & 0x1FFFFFDEEFull;
|
||||
case 6: return (1u << (static_cast<uint_least32_t>(codepoint) - 0xA8F2u)) & 0xA3Fu;
|
||||
case 7: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0xA8FEull)) & 0xFFFC00FFFFFFF001ull;
|
||||
case 8: return codepoint <= U'\uA946' || codepoint >= U'\uA960';
|
||||
case 10: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0xA9CFull)) & 0x7801FFBE0001ull;
|
||||
case 11: return codepoint != U'\uA9FF';
|
||||
case 12: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0xAA40ull)) & 0x47FFFFF00000FF7ull;
|
||||
case 13: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0xAA7Eull)) & 0xF98BFFFFFFFFFFFFull;
|
||||
case 14: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0xAAC0ull)) & 0x1C07FF38000005ull;
|
||||
case 15: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0xAB01ull)) & 0x1FFFBFBF803F3F3Full;
|
||||
case 16: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0xAB3Eull)) & 0xFFFC03FFDFFFFFFFull;
|
||||
default: return true;
|
||||
}
|
||||
// chunk summary: 2616 codepoints from 43 ranges (spanning a search area of 3046)
|
||||
}
|
||||
case 18: return codepoint <= U'\uD7A2' || (codepoint >= U'\uD7B0' && codepoint <= U'\uD7C6')
|
||||
|| codepoint >= U'\uD7CB';
|
||||
case 19: return false;
|
||||
case 20: return codepoint <= U'\uFA6D' || codepoint >= U'\uFA70';
|
||||
case 21:
|
||||
{
|
||||
if (codepoint < U'\uFA88' || codepoint > U'\U0001066D')
|
||||
return false;
|
||||
|
||||
TOML_ASSUME_CODEPOINT_BETWEEN(U'\uFA88', U'\U0001066D');
|
||||
switch ((static_cast<uint_least32_t>(codepoint) - 0xFA88u) / 64u)
|
||||
{
|
||||
case 1: return codepoint <= U'\uFAD9' || codepoint >= U'\uFB00';
|
||||
case 2: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0xFB13ull)) & 0x1B6BEFFFBFF41Full;
|
||||
case 12: return codepoint <= U'\uFD8F' || codepoint >= U'\uFD92';
|
||||
case 14: return false;
|
||||
case 15: return codepoint != U'\uFE48';
|
||||
case 18: return codepoint <= U'\uFF3A' || codepoint >= U'\uFF41';
|
||||
case 19: return codepoint <= U'\uFF5A' || codepoint >= U'\uFF66';
|
||||
case 20: return codepoint <= U'\uFFBE' || codepoint >= U'\uFFC2';
|
||||
case 21: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0xFFCAull)) & 0x3FC0000000073F3Full;
|
||||
case 22: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0x10008ull)) & 0xFFB7FFFF7FFFFFEFull;
|
||||
case 23: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0x10048ull)) & 0xFF000000003FFF3Full;
|
||||
case 26: return false;
|
||||
case 27: return false;
|
||||
case 28: return false;
|
||||
case 29: return false;
|
||||
case 30: return false;
|
||||
case 32: return codepoint <= U'\U0001029C' || codepoint >= U'\U000102A0';
|
||||
case 33: return codepoint <= U'\U000102D0' || codepoint >= U'\U00010300';
|
||||
case 34: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0x10308ull)) & 0xFDFFFFE000FFFFFFull;
|
||||
case 35: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0x10348ull)) & 0xFF003FFFFFFFFF03ull;
|
||||
case 36: return codepoint <= U'\U0001039D' || codepoint >= U'\U000103A0';
|
||||
case 37: return codepoint <= U'\U000103CF' || codepoint >= U'\U00010400';
|
||||
case 40: return codepoint <= U'\U0001049D' || codepoint >= U'\U000104B0';
|
||||
case 41: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0x104C8ull)) & 0xFF0FFFFFFFFF0FFFull;
|
||||
case 42: return codepoint <= U'\U00010527' || codepoint >= U'\U00010530';
|
||||
case 44: return false;
|
||||
default: return true;
|
||||
}
|
||||
// chunk summary: 1924 codepoints from 46 ranges (spanning a search area of 3046)
|
||||
}
|
||||
case 22:
|
||||
{
|
||||
if (codepoint < U'\U0001066E' || codepoint > U'\U0001122B')
|
||||
return false;
|
||||
|
||||
TOML_ASSUME_CODEPOINT_BETWEEN(U'\U0001066E', U'\U0001122B');
|
||||
switch ((static_cast<uint_least32_t>(codepoint) - 0x1066Eu) / 64u)
|
||||
{
|
||||
case 3: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0x1072Eull)) & 0x3FC00FFFFFC01FFull;
|
||||
case 4: return false;
|
||||
case 5: return false;
|
||||
case 6: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0x10800ull)) & 0x3FFFFFFFFD3Full;
|
||||
case 7: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0x1082Eull)) & 0xFFFC00FFFFFE46FFull;
|
||||
case 8: return codepoint <= U'\U00010876' || codepoint >= U'\U00010880';
|
||||
case 10: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0x108EEull)) & 0xFFFC00FFFFFC00DFull;
|
||||
case 13: return codepoint <= U'\U000109B7' || codepoint >= U'\U000109BE';
|
||||
case 14: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0x10A00ull)) & 0x3FFFFEEF0001ull;
|
||||
case 15: return codepoint <= U'\U00010A35' || codepoint >= U'\U00010A60';
|
||||
case 16: return codepoint <= U'\U00010A7C' || codepoint >= U'\U00010A80';
|
||||
case 17: return codepoint != U'\U00010AAE';
|
||||
case 19: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0x10B2Eull)) & 0xFFFC00FFFFFC00FFull;
|
||||
case 20: return codepoint <= U'\U00010B72' || codepoint >= U'\U00010B80';
|
||||
case 21: return false;
|
||||
case 25: return codepoint <= U'\U00010CB2' || codepoint >= U'\U00010CC0';
|
||||
case 26: return codepoint <= U'\U00010CF2' || codepoint >= U'\U00010D00';
|
||||
case 27: return false;
|
||||
case 28: return false;
|
||||
case 29: return false;
|
||||
case 30: return false;
|
||||
case 31: return false;
|
||||
case 32: return false;
|
||||
case 33: return false;
|
||||
case 34: return codepoint <= U'\U00010F1C' || codepoint >= U'\U00010F27';
|
||||
case 36: return false;
|
||||
case 38: return codepoint <= U'\U00010FF6' || codepoint >= U'\U00011003';
|
||||
case 41: return codepoint <= U'\U000110AF' || codepoint >= U'\U000110D0';
|
||||
case 43: return codepoint <= U'\U00011144' || codepoint >= U'\U00011150';
|
||||
case 44: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0x1116Eull)) & 0xFFFFFFFFFFE0011Full;
|
||||
case 45: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0x111AEull)) & 0x50000078001Full;
|
||||
case 46: return codepoint != U'\U000111EE';
|
||||
default: return true;
|
||||
}
|
||||
// chunk summary: 1312 codepoints from 50 ranges (spanning a search area of 3006)
|
||||
}
|
||||
case 23:
|
||||
{
|
||||
if (codepoint < U'\U00011280' || codepoint > U'\U00011D98')
|
||||
return false;
|
||||
|
||||
TOML_ASSUME_CODEPOINT_BETWEEN(U'\U00011280', U'\U00011D98');
|
||||
switch ((static_cast<uint_least32_t>(codepoint) - 0x11280u) / 64u)
|
||||
{
|
||||
case 0: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0x11280ull)) & 0xFFFF01FFBFFFBD7Full;
|
||||
case 1: return true;
|
||||
case 2: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0x11305ull)) & 0x11F6FEFFFFFCCFFull;
|
||||
case 3: return codepoint <= U'\U00011350' || codepoint >= U'\U0001135D';
|
||||
case 6: return true;
|
||||
case 7: return codepoint <= U'\U0001144A' || codepoint >= U'\U0001145F';
|
||||
case 8: return true;
|
||||
case 9: return codepoint != U'\U000114C0';
|
||||
case 12: return true;
|
||||
case 13: return true;
|
||||
case 14: return true;
|
||||
case 15: return true;
|
||||
case 16: return codepoint <= U'\U000116AA' || codepoint >= U'\U000116B8';
|
||||
case 18: return true;
|
||||
case 22: return true;
|
||||
case 24: return true;
|
||||
case 25: return codepoint <= U'\U000118DF' || codepoint >= U'\U000118FF';
|
||||
case 28: return codepoint <= U'\U000119A7' || codepoint >= U'\U000119AA';
|
||||
case 29: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0x119C0ull)) & 0xA0001FFFFull;
|
||||
case 30: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0x11A00ull)) & 0x407FFFFFFFFF801ull;
|
||||
case 31: return codepoint <= U'\U00011A50' || codepoint >= U'\U00011A5C';
|
||||
case 32: return codepoint <= U'\U00011A89' || codepoint >= U'\U00011A9D';
|
||||
case 33: return true;
|
||||
case 38: return codepoint != U'\U00011C09';
|
||||
case 39: return codepoint <= U'\U00011C40' || codepoint >= U'\U00011C72';
|
||||
case 40: return true;
|
||||
case 42: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0x11D00ull)) & 0x1FFFFFFFFFB7Full;
|
||||
case 43: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0x11D46ull)) & 0x3FFFFF6FC000001ull;
|
||||
case 44: return codepoint <= U'\U00011D89' || codepoint >= U'\U00011D98';
|
||||
default: return false;
|
||||
}
|
||||
// chunk summary: 888 codepoints from 54 ranges (spanning a search area of 2841)
|
||||
}
|
||||
case 24: return codepoint <= U'\U00011EF2' || (codepoint >= U'\U00012000' && codepoint <= U'\U00012399')
|
||||
|| codepoint >= U'\U00012480';
|
||||
case 26: return false;
|
||||
case 28: return false;
|
||||
case 29: return false;
|
||||
case 30:
|
||||
{
|
||||
if (codepoint < U'\U00016800' || codepoint > U'\U00017183')
|
||||
return false;
|
||||
|
||||
TOML_ASSUME_CODEPOINT_BETWEEN(U'\U00016800', U'\U00017183');
|
||||
switch ((static_cast<uint_least32_t>(codepoint) - 0x16800u) / 63u)
|
||||
{
|
||||
case 9: return codepoint <= U'\U00016A38' || codepoint >= U'\U00016A40';
|
||||
case 10: return false;
|
||||
case 13: return codepoint <= U'\U00016B43' || codepoint >= U'\U00016B63';
|
||||
case 14: return codepoint <= U'\U00016B77' || codepoint >= U'\U00016B7D';
|
||||
case 15: return false;
|
||||
case 16: return false;
|
||||
case 17: return false;
|
||||
case 18: return false;
|
||||
case 19: return false;
|
||||
case 20: return false;
|
||||
case 21: return false;
|
||||
case 22: return false;
|
||||
case 23: return false;
|
||||
case 24: return false;
|
||||
case 27: return false;
|
||||
case 29: return codepoint <= U'\U00016F4A' || codepoint >= U'\U00016F50';
|
||||
case 31: return false;
|
||||
case 32: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0x16FE0ull)) & 0x7FFFFFFF0000000Bull;
|
||||
default: return true;
|
||||
}
|
||||
// chunk summary: 1266 codepoints from 14 ranges (spanning a search area of 2436)
|
||||
}
|
||||
case 32: return codepoint <= U'\U000187F6' || codepoint >= U'\U00018800';
|
||||
case 34: return false;
|
||||
case 35: return false;
|
||||
case 36: return codepoint <= U'\U0001B11E' || (codepoint >= U'\U0001B150' && codepoint <= U'\U0001B152')
|
||||
|| (codepoint >= U'\U0001B164' && codepoint <= U'\U0001B167') || codepoint >= U'\U0001B170';
|
||||
case 37: return codepoint <= U'\U0001BC6A' || (codepoint >= U'\U0001BC70' && codepoint <= U'\U0001BC7C')
|
||||
|| (codepoint >= U'\U0001BC80' && codepoint <= U'\U0001BC88') || codepoint >= U'\U0001BC90';
|
||||
case 38: return false;
|
||||
case 39:
|
||||
{
|
||||
if (codepoint < U'\U0001D400' || codepoint > U'\U0001D7CB')
|
||||
return false;
|
||||
|
||||
TOML_ASSUME_CODEPOINT_BETWEEN(U'\U0001D400', U'\U0001D7CB');
|
||||
switch ((static_cast<uint_least32_t>(codepoint) - 0x1D400u) / 61u)
|
||||
{
|
||||
case 1: return codepoint != U'\U0001D455';
|
||||
case 2: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0x1D47Aull)) & 0x1FF79937FFFFFFFFull;
|
||||
case 3: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0x1D4B7ull)) & 0x1FFFFFFFFFFFDFD7ull;
|
||||
case 4: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0x1D4F4ull)) & 0x1FFFFDFDFE7BFFFFull;
|
||||
case 5: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0x1D531ull)) & 0x1FFFFFFEFE2FBDFFull;
|
||||
case 11: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0x1D69Full)) & 0xFFFFFFBFFFFFE7Full;
|
||||
case 12: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0x1D6DCull)) & 0x1DFFFFFF7FFFFFFFull;
|
||||
case 13: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0x1D719ull)) & 0x1FBFFFFFEFFFFFFFull;
|
||||
case 14: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0x1D756ull)) & 0x1FF7FFFFFDFFFFFFull;
|
||||
case 15: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0x1D793ull)) & 0x1FEFFFFFFBFFFFFull;
|
||||
default: return true;
|
||||
}
|
||||
// chunk summary: 936 codepoints from 30 ranges (spanning a search area of 972)
|
||||
}
|
||||
case 40:
|
||||
{
|
||||
if (codepoint < U'\U0001E100' || codepoint > U'\U0001E87F')
|
||||
return false;
|
||||
|
||||
TOML_ASSUME_CODEPOINT_BETWEEN(U'\U0001E100', U'\U0001E87F');
|
||||
switch ((static_cast<uint_least32_t>(codepoint) - 0x1E100u) / 64u)
|
||||
{
|
||||
case 0: return codepoint <= U'\U0001E12C' || codepoint >= U'\U0001E137';
|
||||
case 1: return true;
|
||||
case 7: return true;
|
||||
case 28: return true;
|
||||
case 29: return true;
|
||||
default: return false;
|
||||
}
|
||||
// chunk summary: 225 codepoints from 5 ranges (spanning a search area of 1920)
|
||||
}
|
||||
case 41:
|
||||
{
|
||||
if (codepoint < U'\U0001E880' || codepoint > U'\U0001EEBB')
|
||||
return false;
|
||||
|
||||
TOML_ASSUME_CODEPOINT_BETWEEN(U'\U0001E880', U'\U0001EEBB');
|
||||
switch ((static_cast<uint_least32_t>(codepoint) - 0x1E880u) / 64u)
|
||||
{
|
||||
case 0: return true;
|
||||
case 1: return true;
|
||||
case 2: return true;
|
||||
case 3: return codepoint <= U'\U0001E943' || codepoint >= U'\U0001E94B';
|
||||
case 22: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0x1EE00ull)) & 0xAF7FE96FFFFFFEFull;
|
||||
case 23: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0x1EE42ull)) & 0x17BDFDE5AAA5BAA1ull;
|
||||
case 24: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0x1EE80ull)) & 0xFFFFBEE0FFFFBFFull;
|
||||
default: return false;
|
||||
}
|
||||
// chunk summary: 279 codepoints from 36 ranges (spanning a search area of 1596)
|
||||
}
|
||||
case 58: return codepoint <= U'\U0002B733' || (codepoint >= U'\U0002B740' && codepoint <= U'\U0002B81C')
|
||||
|| codepoint >= U'\U0002B820';
|
||||
case 60: return codepoint <= U'\U0002CEA0' || codepoint >= U'\U0002CEB0';
|
||||
default: return true;
|
||||
}
|
||||
// chunk summary: 125582 codepoints from 607 ranges (spanning a search area of 194932)
|
||||
}
|
||||
|
||||
/// \brief Returns true if a codepoint belongs to any of these categories: Nd, Nl
|
||||
[[nodiscard]]
|
||||
constexpr bool is_unicode_number(char32_t codepoint) noexcept
|
||||
{
|
||||
if (codepoint < U'\u0660' || codepoint > U'\U0001E959')
|
||||
return false;
|
||||
|
||||
TOML_ASSUME_CODEPOINT_BETWEEN(U'\u0660', U'\U0001E959');
|
||||
switch ((static_cast<uint_least32_t>(codepoint) - 0x660u) / 1932u)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
if (codepoint > U'\u0DEB')
|
||||
return false;
|
||||
|
||||
return ((static_cast<uint_least32_t>(codepoint) - 0x660u) / 63u) & 0x55555025ull;
|
||||
// chunk summary: 126 codepoints from 13 ranges (spanning a search area of 1932)
|
||||
}
|
||||
case 1:
|
||||
{
|
||||
if (codepoint < U'\u0DEC' || codepoint > U'\u1099')
|
||||
return false;
|
||||
|
||||
return ((static_cast<uint_least32_t>(codepoint) - 0xDECu) / 63u) & 0x63Bull;
|
||||
// chunk summary: 54 codepoints from 6 ranges (spanning a search area of 686)
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
if (codepoint < U'\u16EE' || codepoint > U'\u1C59')
|
||||
return false;
|
||||
|
||||
TOML_ASSUME_CODEPOINT_BETWEEN(U'\u16EE', U'\u1C59');
|
||||
switch ((static_cast<uint_least32_t>(codepoint) - 0x16EEu) / 64u)
|
||||
{
|
||||
case 0: return true;
|
||||
case 3: return true;
|
||||
case 4: return true;
|
||||
case 9: return true;
|
||||
case 11: return true;
|
||||
case 14: return codepoint <= U'\u1A89' || codepoint >= U'\u1A90';
|
||||
case 17: return true;
|
||||
case 19: return true;
|
||||
case 21: return codepoint <= U'\u1C49' || codepoint >= U'\u1C50';
|
||||
default: return false;
|
||||
}
|
||||
// chunk summary: 103 codepoints from 11 ranges (spanning a search area of 1388)
|
||||
}
|
||||
case 3: return codepoint <= U'\u2182' || codepoint >= U'\u2185';
|
||||
case 5: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0x3007ull)) & 0xE0007FC000001ull;
|
||||
case 21:
|
||||
{
|
||||
if (codepoint < U'\uA620' || codepoint > U'\uABF9')
|
||||
return false;
|
||||
|
||||
TOML_ASSUME_CODEPOINT_BETWEEN(U'\uA620', U'\uABF9');
|
||||
switch ((static_cast<uint_least32_t>(codepoint) - 0xA620u) / 63u)
|
||||
{
|
||||
case 0: return true;
|
||||
case 3: return true;
|
||||
case 10: return true;
|
||||
case 11: return codepoint <= U'\uA8D9' || codepoint >= U'\uA900';
|
||||
case 14: return true;
|
||||
case 15: return codepoint <= U'\uA9D9' || codepoint >= U'\uA9F0';
|
||||
case 17: return true;
|
||||
case 23: return true;
|
||||
default: return false;
|
||||
}
|
||||
// chunk summary: 80 codepoints from 8 ranges (spanning a search area of 1498)
|
||||
}
|
||||
case 32: return true;
|
||||
case 33:
|
||||
{
|
||||
if (codepoint < U'\U00010140' || codepoint > U'\U000104A9')
|
||||
return false;
|
||||
|
||||
TOML_ASSUME_CODEPOINT_BETWEEN(U'\U00010140', U'\U000104A9');
|
||||
switch ((static_cast<uint_least32_t>(codepoint) - 0x10140u) / 63u)
|
||||
{
|
||||
case 0: return true;
|
||||
case 8: return codepoint <= U'\U00010341' || codepoint >= U'\U0001034A';
|
||||
case 10: return true;
|
||||
case 13: return true;
|
||||
default: return false;
|
||||
}
|
||||
// chunk summary: 70 codepoints from 5 ranges (spanning a search area of 874)
|
||||
}
|
||||
case 34: return true;
|
||||
case 35:
|
||||
{
|
||||
if (codepoint < U'\U00011066' || codepoint > U'\U000114D9')
|
||||
return false;
|
||||
|
||||
return ((static_cast<uint_least32_t>(codepoint) - 0x11066u) / 64u) & 0x2842Dull;
|
||||
// chunk summary: 70 codepoints from 7 ranges (spanning a search area of 1140)
|
||||
}
|
||||
case 36:
|
||||
{
|
||||
if (codepoint < U'\U00011650' || codepoint > U'\U00011D59')
|
||||
return false;
|
||||
|
||||
return ((static_cast<uint_least32_t>(codepoint) - 0x11650u) / 63u) & 0x1100040Bull;
|
||||
// chunk summary: 60 codepoints from 6 ranges (spanning a search area of 1802)
|
||||
}
|
||||
case 37: return codepoint <= U'\U00011DA9' || codepoint >= U'\U00012400';
|
||||
case 47: return codepoint <= U'\U00016A69' || codepoint >= U'\U00016B50';
|
||||
case 61: return true;
|
||||
case 62: return true;
|
||||
case 63: return codepoint <= U'\U0001E2F9' || codepoint >= U'\U0001E950';
|
||||
default: return false;
|
||||
}
|
||||
// chunk summary: 856 codepoints from 70 ranges (spanning a search area of 123642)
|
||||
}
|
||||
|
||||
/// \brief Returns true if a codepoint belongs to any of these categories: Mn, Mc
|
||||
[[nodiscard]]
|
||||
constexpr bool is_unicode_combining_mark(char32_t codepoint) noexcept
|
||||
{
|
||||
if (codepoint < U'\u0300' || codepoint > U'\U000E01EF')
|
||||
return false;
|
||||
|
||||
TOML_ASSUME_CODEPOINT_BETWEEN(U'\u0300', U'\U000E01EF');
|
||||
switch ((static_cast<uint_least32_t>(codepoint) - 0x300u) / 14332u)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
if (codepoint > U'\u309A')
|
||||
return false;
|
||||
|
||||
TOML_ASSUME_CODEPOINT_BETWEEN(U'\u0300', U'\u309A');
|
||||
switch ((static_cast<uint_least32_t>(codepoint) - 0x300u) / 183u)
|
||||
{
|
||||
case 0: return true;
|
||||
case 2: return true;
|
||||
case 3: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0x591ull)) & 0x5B5FFFFFFFFFFFull;
|
||||
case 4: return codepoint <= U'\u061A' || (codepoint >= U'\u064B' && codepoint <= U'\u065F')
|
||||
|| codepoint == U'\u0670';
|
||||
case 5:
|
||||
{
|
||||
if (codepoint < U'\u06D6' || codepoint > U'\u0749')
|
||||
return false;
|
||||
|
||||
TOML_ASSUME_CODEPOINT_BETWEEN(U'\u06D6', U'\u0749');
|
||||
switch ((static_cast<uint_least32_t>(codepoint) - 0x6D6u) / 58u)
|
||||
{
|
||||
case 0: return (1u << (static_cast<uint_least32_t>(codepoint) - 0x6D6u)) & 0xF67E7Fu;
|
||||
case 1: return codepoint <= U'\u0711' || codepoint >= U'\u0730';
|
||||
TOML_NO_DEFAULT_CASE;
|
||||
}
|
||||
// chunk summary: 46 codepoints from 6 ranges (spanning a search area of 116)
|
||||
}
|
||||
case 6: return codepoint == U'\u074A' || (codepoint >= U'\u07A6' && codepoint <= U'\u07B0')
|
||||
|| (codepoint >= U'\u07EB' && codepoint <= U'\u07F3') || codepoint == U'\u07FD';
|
||||
case 7:
|
||||
{
|
||||
if (codepoint < U'\u0816' || codepoint > U'\u085B')
|
||||
return false;
|
||||
|
||||
TOML_ASSUME_CODEPOINT_BETWEEN(U'\u0816', U'\u085B');
|
||||
switch ((static_cast<uint_least32_t>(codepoint) - 0x816u) / 35u)
|
||||
{
|
||||
case 0: return (1u << (static_cast<uint_least32_t>(codepoint) - 0x816u)) & 0xFBBFEFu;
|
||||
default: return true;
|
||||
}
|
||||
// chunk summary: 24 codepoints from 5 ranges (spanning a search area of 70)
|
||||
}
|
||||
case 8:
|
||||
{
|
||||
if (codepoint < U'\u08D3' || codepoint > U'\u0963')
|
||||
return false;
|
||||
|
||||
TOML_ASSUME_CODEPOINT_BETWEEN(U'\u08D3', U'\u0963');
|
||||
switch ((static_cast<uint_least32_t>(codepoint) - 0x8D3u) / 49u)
|
||||
{
|
||||
case 0: return codepoint != U'\u08E2';
|
||||
case 2: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0x93Aull)) & 0x3003FBFFFF7ull;
|
||||
default: return false;
|
||||
}
|
||||
// chunk summary: 78 codepoints from 6 ranges (spanning a search area of 145)
|
||||
}
|
||||
case 9:
|
||||
{
|
||||
if (codepoint < U'\u0981' || codepoint > U'\u0A03')
|
||||
return false;
|
||||
|
||||
TOML_ASSUME_CODEPOINT_BETWEEN(U'\u0981', U'\u0A03');
|
||||
switch ((static_cast<uint_least32_t>(codepoint) - 0x981u) / 44u)
|
||||
{
|
||||
case 1: return (1u << (static_cast<uint_least32_t>(codepoint) - 0x9BCu)) & 0x80399FDu;
|
||||
case 2: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0x9E2ull)) & 0x390000003ull;
|
||||
default: return true;
|
||||
}
|
||||
// chunk summary: 23 codepoints from 9 ranges (spanning a search area of 131)
|
||||
}
|
||||
case 10:
|
||||
{
|
||||
if (codepoint < U'\u0A3C' || codepoint > U'\u0ACD')
|
||||
return false;
|
||||
|
||||
TOML_ASSUME_CODEPOINT_BETWEEN(U'\u0A3C', U'\u0ACD');
|
||||
switch ((static_cast<uint_least32_t>(codepoint) - 0xA3Cu) / 49u)
|
||||
{
|
||||
case 0: return (1u << (static_cast<uint_least32_t>(codepoint) - 0xA3Cu)) & 0x23987Du;
|
||||
case 1: return (1u << (static_cast<uint_least32_t>(codepoint) - 0xA70u)) & 0xE0023u;
|
||||
case 2: return (1u << (static_cast<uint_least32_t>(codepoint) - 0xABCu)) & 0x3BBFDu;
|
||||
TOML_NO_DEFAULT_CASE;
|
||||
}
|
||||
// chunk summary: 33 codepoints from 12 ranges (spanning a search area of 146)
|
||||
}
|
||||
case 11:
|
||||
{
|
||||
if (codepoint < U'\u0AE2' || codepoint > U'\u0B82')
|
||||
return false;
|
||||
|
||||
TOML_ASSUME_CODEPOINT_BETWEEN(U'\u0AE2', U'\u0B82');
|
||||
switch ((static_cast<uint_least32_t>(codepoint) - 0xAE2u) / 54u)
|
||||
{
|
||||
case 0: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0xAE2ull)) & 0x3BF000003ull;
|
||||
case 1: return (1u << (static_cast<uint_least32_t>(codepoint) - 0xB3Cu)) & 0x399FDu;
|
||||
case 2: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0xB56ull)) & 0x100000003003ull;
|
||||
TOML_NO_DEFAULT_CASE;
|
||||
}
|
||||
// chunk summary: 29 codepoints from 10 ranges (spanning a search area of 161)
|
||||
}
|
||||
case 12:
|
||||
{
|
||||
if (codepoint < U'\u0BBE' || codepoint > U'\u0C4A')
|
||||
return false;
|
||||
|
||||
TOML_ASSUME_CODEPOINT_BETWEEN(U'\u0BBE', U'\u0C4A');
|
||||
switch ((static_cast<uint_least32_t>(codepoint) - 0xBBEu) / 47u)
|
||||
{
|
||||
case 0: return (1u << (static_cast<uint_least32_t>(codepoint) - 0xBBEu)) & 0x200F71Fu;
|
||||
case 2: return (1u << (static_cast<uint_least32_t>(codepoint) - 0xC3Eu)) & 0x177Fu;
|
||||
default: return true;
|
||||
}
|
||||
// chunk summary: 29 codepoints from 8 ranges (spanning a search area of 141)
|
||||
}
|
||||
case 13:
|
||||
{
|
||||
if (codepoint < U'\u0C4B' || codepoint > U'\u0D01')
|
||||
return false;
|
||||
|
||||
TOML_ASSUME_CODEPOINT_BETWEEN(U'\u0C4B', U'\u0D01');
|
||||
switch ((static_cast<uint_least32_t>(codepoint) - 0xC4Bu) / 61u)
|
||||
{
|
||||
case 0: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0xC4Bull)) & 0x1C0000001800C07ull;
|
||||
case 1: return codepoint != U'\u0C88';
|
||||
case 2: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0xCC6ull)) & 0xC000000300180F7ull;
|
||||
TOML_NO_DEFAULT_CASE;
|
||||
}
|
||||
// chunk summary: 31 codepoints from 11 ranges (spanning a search area of 183)
|
||||
}
|
||||
case 14:
|
||||
{
|
||||
if (codepoint < U'\u0D02' || codepoint > U'\u0D83')
|
||||
return false;
|
||||
|
||||
TOML_ASSUME_CODEPOINT_BETWEEN(U'\u0D02', U'\u0D83');
|
||||
switch ((static_cast<uint_least32_t>(codepoint) - 0xD02u) / 44u)
|
||||
{
|
||||
case 1: return (1u << (static_cast<uint_least32_t>(codepoint) - 0xD3Bu)) & 0x1007BBFBu;
|
||||
case 2: return codepoint <= U'\u0D63' || codepoint >= U'\u0D82';
|
||||
default: return true;
|
||||
}
|
||||
// chunk summary: 23 codepoints from 8 ranges (spanning a search area of 130)
|
||||
}
|
||||
case 15:
|
||||
{
|
||||
if (codepoint < U'\u0DCA' || codepoint > U'\u0E4E')
|
||||
return false;
|
||||
|
||||
TOML_ASSUME_CODEPOINT_BETWEEN(U'\u0DCA', U'\u0E4E');
|
||||
switch ((static_cast<uint_least32_t>(codepoint) - 0xDCAu) / 45u)
|
||||
{
|
||||
case 0: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0xDCAull)) & 0x300003FD7E1ull;
|
||||
case 2: return (1u << (static_cast<uint_least32_t>(codepoint) - 0xE31u)) & 0x3FC003F9u;
|
||||
default: return false;
|
||||
}
|
||||
// chunk summary: 34 codepoints from 8 ranges (spanning a search area of 133)
|
||||
}
|
||||
case 16: return codepoint == U'\u0EB1' || (codepoint >= U'\u0EB4' && codepoint <= U'\u0EBC')
|
||||
|| (codepoint >= U'\u0EC8' && codepoint <= U'\u0ECD') || codepoint >= U'\u0F18';
|
||||
case 17:
|
||||
{
|
||||
if (codepoint < U'\u0F35' || codepoint > U'\u0FC6')
|
||||
return false;
|
||||
|
||||
TOML_ASSUME_CODEPOINT_BETWEEN(U'\u0F35', U'\u0FC6');
|
||||
switch ((static_cast<uint_least32_t>(codepoint) - 0xF35u) / 49u)
|
||||
{
|
||||
case 0: return (1u << (static_cast<uint_least32_t>(codepoint) - 0xF35u)) & 0x615u;
|
||||
case 1: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0xF71ull)) & 0x3FF06FFFFFull;
|
||||
case 2: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0xF97ull)) & 0x803FFFFFFFFDull;
|
||||
TOML_NO_DEFAULT_CASE;
|
||||
}
|
||||
// chunk summary: 75 codepoints from 9 ranges (spanning a search area of 146)
|
||||
}
|
||||
case 18:
|
||||
{
|
||||
if (codepoint < U'\u102B' || codepoint > U'\u108F')
|
||||
return false;
|
||||
|
||||
TOML_ASSUME_CODEPOINT_BETWEEN(U'\u102B', U'\u108F');
|
||||
switch ((static_cast<uint_least32_t>(codepoint) - 0x102Bu) / 51u)
|
||||
{
|
||||
case 0: return codepoint <= U'\u103E' || codepoint >= U'\u1056';
|
||||
case 1: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0x105Eull)) & 0x2FFF00078FE77ull;
|
||||
TOML_NO_DEFAULT_CASE;
|
||||
}
|
||||
// chunk summary: 54 codepoints from 8 ranges (spanning a search area of 101)
|
||||
}
|
||||
case 19: return true;
|
||||
case 22: return true;
|
||||
case 28:
|
||||
{
|
||||
if (codepoint < U'\u1712' || codepoint > U'\u17BA')
|
||||
return false;
|
||||
|
||||
TOML_ASSUME_CODEPOINT_BETWEEN(U'\u1712', U'\u17BA');
|
||||
switch ((static_cast<uint_least32_t>(codepoint) - 0x1712u) / 57u)
|
||||
{
|
||||
case 0: return codepoint <= U'\u1714' || codepoint >= U'\u1732';
|
||||
case 1: return codepoint <= U'\u1753' || codepoint >= U'\u1772';
|
||||
default: return true;
|
||||
}
|
||||
// chunk summary: 17 codepoints from 5 ranges (spanning a search area of 169)
|
||||
}
|
||||
case 29: return codepoint <= U'\u17D3' || codepoint == U'\u17DD' || codepoint >= U'\u180B';
|
||||
case 30: return codepoint <= U'\u1886' || codepoint == U'\u18A9' || codepoint >= U'\u1920';
|
||||
case 31: return codepoint <= U'\u192B' || codepoint >= U'\u1930';
|
||||
case 32: return codepoint <= U'\u1A1B' || (codepoint >= U'\u1A55' && codepoint <= U'\u1A5E')
|
||||
|| (codepoint >= U'\u1A60' && codepoint <= U'\u1A7C') || codepoint == U'\u1A7F';
|
||||
case 33: return codepoint <= U'\u1ABD' || (codepoint >= U'\u1B00' && codepoint <= U'\u1B04')
|
||||
|| codepoint >= U'\u1B34';
|
||||
case 34: return codepoint <= U'\u1B73' || (codepoint >= U'\u1B80' && codepoint <= U'\u1B82')
|
||||
|| (codepoint >= U'\u1BA1' && codepoint <= U'\u1BAD') || codepoint >= U'\u1BE6';
|
||||
case 35: return true;
|
||||
case 36: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0x1CD0ull)) & 0x39021FFFFF7ull;
|
||||
case 37: return codepoint != U'\u1D73';
|
||||
case 41: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0x20D0ull)) & 0x1FFE21FFFull;
|
||||
case 58: return true;
|
||||
case 59: return codepoint <= U'\u2D7F' || codepoint >= U'\u2DE0';
|
||||
case 60: return true;
|
||||
case 63: return codepoint <= U'\u302F' || codepoint >= U'\u3099';
|
||||
default: return false;
|
||||
}
|
||||
// chunk summary: 1102 codepoints from 155 ranges (spanning a search area of 11675)
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
if (codepoint < U'\uA66F' || codepoint > U'\uAAEF')
|
||||
return false;
|
||||
|
||||
TOML_ASSUME_CODEPOINT_BETWEEN(U'\uA66F', U'\uAAEF');
|
||||
switch ((static_cast<uint_least32_t>(codepoint) - 0xA66Fu) / 61u)
|
||||
{
|
||||
case 0: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0xA66Full)) & 0x1800000007FE1ull;
|
||||
case 1: return false;
|
||||
case 3: return false;
|
||||
case 4: return false;
|
||||
case 5: return false;
|
||||
case 6: return (1u << (static_cast<uint_least32_t>(codepoint) - 0xA802u)) & 0x211u;
|
||||
case 10: return codepoint <= U'\uA8F1' || codepoint >= U'\uA8FF';
|
||||
case 11: return codepoint <= U'\uA92D' || codepoint >= U'\uA947';
|
||||
case 12: return codepoint <= U'\uA953' || codepoint >= U'\uA980';
|
||||
case 16: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0xAA43ull)) & 0x100000000000601ull;
|
||||
case 17: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0xAA7Cull)) & 0x19D0000000000003ull;
|
||||
case 18: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0xAABEull)) & 0x3E0000000000Bull;
|
||||
default: return true;
|
||||
}
|
||||
// chunk summary: 136 codepoints from 27 ranges (spanning a search area of 1153)
|
||||
}
|
||||
case 3: return codepoint <= U'\uAAF6' || (codepoint >= U'\uABE3' && codepoint <= U'\uABEA')
|
||||
|| codepoint >= U'\uABEC';
|
||||
case 4:
|
||||
{
|
||||
if (codepoint < U'\uFB1E' || codepoint > U'\U00011A99')
|
||||
return false;
|
||||
|
||||
TOML_ASSUME_CODEPOINT_BETWEEN(U'\uFB1E', U'\U00011A99');
|
||||
switch ((static_cast<uint_least32_t>(codepoint) - 0xFB1Eu) / 128u)
|
||||
{
|
||||
case 0: return true;
|
||||
case 5: return true;
|
||||
case 6: return true;
|
||||
case 13: return true;
|
||||
case 15: return true;
|
||||
case 16: return true;
|
||||
case 29: return (1u << (static_cast<uint_least32_t>(codepoint) - 0x10A01u)) & 0x7837u;
|
||||
case 30: return codepoint <= U'\U00010A3A' || codepoint >= U'\U00010A3F';
|
||||
case 31: return true;
|
||||
case 36: return true;
|
||||
case 40: return true;
|
||||
case 41: return true;
|
||||
case 42: return codepoint <= U'\U00011046' || codepoint >= U'\U0001107F';
|
||||
case 43: return codepoint <= U'\U000110BA' || codepoint >= U'\U00011100';
|
||||
case 44: return codepoint <= U'\U00011134' || (codepoint >= U'\U00011145' && codepoint <= U'\U00011146')
|
||||
|| codepoint == U'\U00011173' || codepoint >= U'\U00011180';
|
||||
case 45: return codepoint <= U'\U000111C0' || codepoint >= U'\U000111C9';
|
||||
case 46: return codepoint <= U'\U00011237' || codepoint >= U'\U0001123E';
|
||||
case 47: return codepoint <= U'\U000112EA' || codepoint >= U'\U00011300';
|
||||
case 48: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0x1133Bull)) & 0x3E3F980100733FBull;
|
||||
case 50: return codepoint <= U'\U00011446' || codepoint >= U'\U0001145E';
|
||||
case 51: return true;
|
||||
case 53: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0x115AFull)) & 0x60000003FE7Full;
|
||||
case 54: return true;
|
||||
case 55: return codepoint <= U'\U000116B7' || codepoint >= U'\U0001171D';
|
||||
case 56: return true;
|
||||
case 58: return true;
|
||||
case 61: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0x119D1ull)) & 0x3FF00000008FE7Full;
|
||||
case 62:
|
||||
{
|
||||
if (codepoint < U'\U00011A33')
|
||||
return false;
|
||||
|
||||
TOML_ASSUME_CODEPOINT_BETWEEN(U'\U00011A33', U'\U00011A99');
|
||||
switch ((static_cast<uint_least32_t>(codepoint) - 0x11A33u) / 52u)
|
||||
{
|
||||
case 0: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0x11A33ull)) & 0x1FFC0100F7Full;
|
||||
default: return true;
|
||||
}
|
||||
// chunk summary: 39 codepoints from 5 ranges (spanning a search area of 103)
|
||||
}
|
||||
default: return false;
|
||||
}
|
||||
// chunk summary: 383 codepoints from 56 ranges (spanning a search area of 8060)
|
||||
}
|
||||
case 5:
|
||||
{
|
||||
if (codepoint < U'\U00011C2F' || codepoint > U'\U00011EF6')
|
||||
return false;
|
||||
|
||||
TOML_ASSUME_CODEPOINT_BETWEEN(U'\U00011C2F', U'\U00011EF6');
|
||||
switch ((static_cast<uint_least32_t>(codepoint) - 0x11C2Fu) / 60u)
|
||||
{
|
||||
case 0: return codepoint != U'\U00011C37';
|
||||
case 1: return true;
|
||||
case 2: return codepoint != U'\U00011CA8';
|
||||
case 4: return (1u << (static_cast<uint_least32_t>(codepoint) - 0x11D31u)) & 0x5FDA3Fu;
|
||||
case 5: return (1u << (static_cast<uint_least32_t>(codepoint) - 0x11D8Au)) & 0x1EDFu;
|
||||
case 6: return true;
|
||||
case 11: return true;
|
||||
default: return false;
|
||||
}
|
||||
// chunk summary: 85 codepoints from 13 ranges (spanning a search area of 712)
|
||||
}
|
||||
case 6:
|
||||
{
|
||||
if (codepoint < U'\U00016AF0' || codepoint > U'\U00016F92')
|
||||
return false;
|
||||
|
||||
TOML_ASSUME_CODEPOINT_BETWEEN(U'\U00016AF0', U'\U00016F92');
|
||||
switch ((static_cast<uint_least32_t>(codepoint) - 0x16AF0u) / 63u)
|
||||
{
|
||||
case 0: return true;
|
||||
case 1: return true;
|
||||
case 17: return codepoint != U'\U00016F1F';
|
||||
case 18: return codepoint <= U'\U00016F87' || codepoint >= U'\U00016F8F';
|
||||
default: return false;
|
||||
}
|
||||
// chunk summary: 72 codepoints from 5 ranges (spanning a search area of 1187)
|
||||
}
|
||||
case 7: return true;
|
||||
case 8:
|
||||
{
|
||||
if (codepoint < U'\U0001D165' || codepoint > U'\U0001E94A')
|
||||
return false;
|
||||
|
||||
TOML_ASSUME_CODEPOINT_BETWEEN(U'\U0001D165', U'\U0001E94A');
|
||||
switch ((static_cast<uint_least32_t>(codepoint) - 0x1D165u) / 128u)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
if (codepoint > U'\U0001D1AD')
|
||||
return false;
|
||||
|
||||
TOML_ASSUME_CODEPOINT_BETWEEN(U'\U0001D165', U'\U0001D1AD');
|
||||
switch ((static_cast<uint_least32_t>(codepoint) - 0x1D165u) / 37u)
|
||||
{
|
||||
case 0: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0x1D165ull)) & 0x1F3FC03F1Full;
|
||||
case 1: return codepoint <= U'\U0001D18B' || codepoint >= U'\U0001D1AA';
|
||||
TOML_NO_DEFAULT_CASE;
|
||||
}
|
||||
// chunk summary: 30 codepoints from 5 ranges (spanning a search area of 73)
|
||||
}
|
||||
case 1: return true;
|
||||
case 17: return codepoint <= U'\U0001DA36' || codepoint >= U'\U0001DA3B';
|
||||
case 18:
|
||||
{
|
||||
if (codepoint < U'\U0001DA65' || codepoint > U'\U0001DAAF')
|
||||
return false;
|
||||
|
||||
TOML_ASSUME_CODEPOINT_BETWEEN(U'\U0001DA65', U'\U0001DAAF');
|
||||
switch ((static_cast<uint_least32_t>(codepoint) - 0x1DA65u) / 38u)
|
||||
{
|
||||
case 0: return (1u << (static_cast<uint_least32_t>(codepoint) - 0x1DA65u)) & 0x800100FFu;
|
||||
case 1: return codepoint != U'\U0001DA8B';
|
||||
TOML_NO_DEFAULT_CASE;
|
||||
}
|
||||
// chunk summary: 30 codepoints from 5 ranges (spanning a search area of 75)
|
||||
}
|
||||
case 29: return (1ull << (static_cast<uint_least64_t>(codepoint) - 0x1E000ull)) & 0x7DBF9FFFF7Full;
|
||||
case 31: return true;
|
||||
case 35: return true;
|
||||
case 46: return true;
|
||||
case 47: return true;
|
||||
default: return false;
|
||||
}
|
||||
// chunk summary: 223 codepoints from 21 ranges (spanning a search area of 6118)
|
||||
}
|
||||
case 63: return true;
|
||||
default: return false;
|
||||
}
|
||||
// chunk summary: 2255 codepoints from 282 ranges (spanning a search area of 917232)
|
||||
}
|
||||
}
|
||||
|
||||
#undef TOML_ASSUME_CODEPOINT_BETWEEN
|
113
include/toml++/toml_value.h
Normal file
113
include/toml++/toml_value.h
Normal file
@ -0,0 +1,113 @@
|
||||
#pragma once
|
||||
#include "toml_node.h"
|
||||
|
||||
namespace toml
|
||||
{
|
||||
template <typename T>
|
||||
class value final
|
||||
: public node
|
||||
{
|
||||
static_assert(
|
||||
impl::is_value<T>,
|
||||
"Template type parameter must be one of the basic value types"
|
||||
);
|
||||
|
||||
private:
|
||||
friend class impl::parser;
|
||||
|
||||
template <typename U>
|
||||
[[nodiscard]] TOML_ALWAYS_INLINE
|
||||
toml::value<U>* as_value() noexcept
|
||||
{
|
||||
if constexpr (std::is_same_v<T, U>)
|
||||
return this;
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
[[nodiscard]] TOML_ALWAYS_INLINE
|
||||
const toml::value<U>* as_value() const noexcept
|
||||
{
|
||||
if constexpr (std::is_same_v<T, U>)
|
||||
return this;
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
T val_;
|
||||
|
||||
public:
|
||||
|
||||
template <typename... U>
|
||||
TOML_NODISCARD_CTOR
|
||||
explicit value(U&&... args) TOML_CONDITIONAL_NOEXCEPT(std::is_nothrow_constructible_v<T, U &&...>)
|
||||
: val_{ std::forward<U>(args)... }
|
||||
{}
|
||||
|
||||
TOML_NODISCARD_CTOR
|
||||
value(value&& other) noexcept
|
||||
: node{ std::move(other) },
|
||||
val_{ std::move(other.val_) }
|
||||
{}
|
||||
|
||||
value& operator= (value&& rhs) noexcept
|
||||
{
|
||||
node::operator=(std::move(rhs));
|
||||
val_ = std::move(rhs.val_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
[[nodiscard]] bool is_string() const noexcept override { return std::is_same_v<T, string>; }
|
||||
[[nodiscard]] bool is_integer() const noexcept override { return std::is_same_v<T, int64_t>; }
|
||||
[[nodiscard]] bool is_floating_point() const noexcept override { return std::is_same_v<T, double>; }
|
||||
[[nodiscard]] bool is_boolean() const noexcept override { return std::is_same_v<T, bool>; }
|
||||
[[nodiscard]] bool is_date() const noexcept override { return std::is_same_v<T, date>; }
|
||||
[[nodiscard]] bool is_time() const noexcept override { return std::is_same_v<T, time>; }
|
||||
[[nodiscard]] bool is_date_time() const noexcept override { return std::is_same_v<T, date_time>; }
|
||||
|
||||
[[nodiscard]] value<string>* as_string() noexcept override { return as_value<string>(); }
|
||||
[[nodiscard]] value<int64_t>* as_integer() noexcept override { return as_value<int64_t>(); }
|
||||
[[nodiscard]] value<double>* as_floating_point() noexcept override { return as_value<double>(); }
|
||||
[[nodiscard]] value<bool>* as_boolean() noexcept override { return as_value<bool>(); }
|
||||
[[nodiscard]] value<date>* as_date() noexcept override { return as_value<date>(); }
|
||||
[[nodiscard]] value<time>* as_time() noexcept override { return as_value<time>(); }
|
||||
[[nodiscard]] value<date_time>* as_date_time() noexcept override { return as_value<date_time>(); }
|
||||
|
||||
[[nodiscard]] const value<string>* as_string() const noexcept override { return as_value<string>(); }
|
||||
[[nodiscard]] const value<int64_t>* as_integer() const noexcept override { return as_value<int64_t>(); }
|
||||
[[nodiscard]] const value<double>* as_floating_point() const noexcept override { return as_value<double>(); }
|
||||
[[nodiscard]] const value<bool>* as_boolean() const noexcept override { return as_value<bool>(); }
|
||||
[[nodiscard]] const value<date>* as_date() const noexcept override { return as_value<date>(); }
|
||||
[[nodiscard]] const value<time>* as_time() const noexcept override { return as_value<time>(); }
|
||||
[[nodiscard]] const value<date_time>* as_date_time() const noexcept override { return as_value<date_time>(); }
|
||||
|
||||
[[nodiscard]] node_type type() const noexcept override
|
||||
{
|
||||
if constexpr (std::is_same_v<T, string>) return node_type::string;
|
||||
else if constexpr (std::is_same_v<T, int64_t>) return node_type::integer;
|
||||
else if constexpr (std::is_same_v<T, double>) return node_type::floating_point;
|
||||
else if constexpr (std::is_same_v<T, bool>) return node_type::boolean;
|
||||
else if constexpr (std::is_same_v<T, date>) return node_type::date;
|
||||
else if constexpr (std::is_same_v<T, time>) return node_type::time;
|
||||
else if constexpr (std::is_same_v<T, date_time>) return node_type::date_time;
|
||||
}
|
||||
|
||||
[[nodiscard]] T& get() noexcept { return val_; }
|
||||
[[nodiscard]] const T& get() const noexcept { return val_; }
|
||||
};
|
||||
|
||||
value(const string_char*) -> value<string>;
|
||||
value(string_view) -> value<string>;
|
||||
value(string) -> value<string>;
|
||||
value(bool) -> value<bool>;
|
||||
value(float) -> value<double>;
|
||||
value(double) -> value<double>;
|
||||
value(int8_t) -> value<int64_t>;
|
||||
value(int16_t) -> value<int64_t>;
|
||||
value(int32_t) -> value<int64_t>;
|
||||
value(int64_t) -> value<int64_t>;
|
||||
value(uint8_t) -> value<int64_t>;
|
||||
value(uint16_t) -> value<int64_t>;
|
||||
value(uint32_t) -> value<int64_t>;
|
||||
}
|
28
meson.build
Normal file
28
meson.build
Normal file
@ -0,0 +1,28 @@
|
||||
project(
|
||||
'tomlplusplus', 'cpp',
|
||||
version : '0.1.0',
|
||||
license : 'MIT',
|
||||
default_options : [
|
||||
'cpp_std=c++17',
|
||||
'warning_level=3',
|
||||
'cpp_eh=default'
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
if meson.get_compiler('cpp').get_id() == 'gcc'
|
||||
add_project_arguments(['-fmax-errors=5', '-Wno-attributes'], language : 'cpp')
|
||||
endif
|
||||
|
||||
if meson.get_compiler('cpp').get_id() == 'clang'
|
||||
add_project_arguments('-ferror-limit=5', language : 'cpp')
|
||||
endif
|
||||
|
||||
#pymod = import('python')
|
||||
#python = pymod.find_installation('python3')
|
||||
|
||||
inc = include_directories('include')
|
||||
|
||||
subdir('tests')
|
||||
#subdir('examples')
|
||||
|
64
python/ci_single_header_check.py
Normal file
64
python/ci_single_header_check.py
Normal file
@ -0,0 +1,64 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import sys
|
||||
import os
|
||||
import os.path
|
||||
import traceback
|
||||
import hashlib
|
||||
import subprocess
|
||||
from shutil import which
|
||||
|
||||
|
||||
|
||||
def is_tool(name):
|
||||
return which(name) is not None
|
||||
|
||||
|
||||
|
||||
def get_script_folder():
|
||||
return os.path.dirname(os.path.realpath(sys.argv[0]))
|
||||
|
||||
|
||||
|
||||
def read_all_text_from_file(path):
|
||||
print("Reading {}".format(path))
|
||||
file = open(path, 'r')
|
||||
text = file.read()
|
||||
file.close()
|
||||
return text
|
||||
|
||||
|
||||
|
||||
def main():
|
||||
hpp_path = os.path.join(get_script_folder(), '..', 'toml.hpp')
|
||||
hash1 = hashlib.sha1(read_all_text_from_file(hpp_path).encode('utf-8')).hexdigest()
|
||||
print("Hash 1: {}".format(hash1))
|
||||
subprocess.check_call(
|
||||
['py' if is_tool('py') else 'python3', 'generate_single_header.py']
|
||||
)
|
||||
hash2 = hashlib.sha1(read_all_text_from_file(hpp_path).encode('utf-8')).hexdigest()
|
||||
print("Hash 2: {}".format(hash2))
|
||||
if (hash1 != hash2):
|
||||
print(
|
||||
"toml.hpp wasn't up-to-date!\nRun generate_single_header.py before your commit to prevent this error.",
|
||||
file=sys.stderr
|
||||
)
|
||||
return 1
|
||||
print("toml.hpp was up-to-date")
|
||||
return 0
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
try:
|
||||
sys.exit(main())
|
||||
except Exception as err:
|
||||
print(
|
||||
'Fatal error: [{}] {}'.format(
|
||||
type(err).__name__,
|
||||
str(err)
|
||||
),
|
||||
file=sys.stderr
|
||||
)
|
||||
traceback.print_exc(file=sys.stderr)
|
||||
sys.exit(-1)
|
137
python/generate_single_header.py
Normal file
137
python/generate_single_header.py
Normal file
@ -0,0 +1,137 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import sys
|
||||
import re
|
||||
import os
|
||||
import os.path
|
||||
import traceback
|
||||
|
||||
|
||||
|
||||
|
||||
def get_script_folder():
|
||||
return os.path.dirname(os.path.realpath(sys.argv[0]))
|
||||
|
||||
|
||||
|
||||
def read_all_text_from_file(path):
|
||||
print("Reading {}".format(path))
|
||||
file = open(path, 'r')
|
||||
text = file.read()
|
||||
file.close()
|
||||
return text
|
||||
|
||||
|
||||
|
||||
def make_divider(text = None, text_col = 40):
|
||||
if (text is None):
|
||||
return "//" + ('-' * 98)
|
||||
else:
|
||||
text = "//{} {} ".format('-' * (text_col - 2),text);
|
||||
if (len(text) < 100):
|
||||
return text + ('-' * (100 - len(text)))
|
||||
else:
|
||||
return text
|
||||
|
||||
|
||||
|
||||
preprocessed_include_headers = 0
|
||||
preprocessed_includes = []
|
||||
preprocess_include_level = -1
|
||||
def preprocess(match):
|
||||
global preprocessed_includes
|
||||
global preprocess_include_level
|
||||
global preprocessed_include_headers
|
||||
|
||||
raw_incl = match if isinstance(match, str) else match.group(1)
|
||||
incl = raw_incl.strip().lower()
|
||||
if incl in preprocessed_includes:
|
||||
return ''
|
||||
|
||||
preprocessed_includes.append(incl)
|
||||
text = read_all_text_from_file(os.path.join(get_script_folder(), '..', 'include', 'toml++', incl))
|
||||
|
||||
if preprocess_include_level >= 0:
|
||||
text = re.sub(r'^\s*#\s*pragma\s*once\s*$', '', text, 0, re.I | re.M)
|
||||
|
||||
preprocess_include_level += 1
|
||||
text = re.sub(r'^\s*#\s*include\s+"(.+?)"', preprocess, text, 0, re.I | re.M)
|
||||
preprocess_include_level -= 1
|
||||
|
||||
if (preprocess_include_level == 0):
|
||||
lpad = 35 + (preprocessed_include_headers % 3) * 20
|
||||
preprocessed_include_headers += 1
|
||||
return '''
|
||||
{}
|
||||
#pragma region {}
|
||||
|
||||
{}
|
||||
|
||||
#pragma endregion {}
|
||||
{}'''.format(make_divider('↓ ' + raw_incl, lpad), raw_incl, text, raw_incl, make_divider('↑ ' + raw_incl, lpad))
|
||||
else:
|
||||
return text
|
||||
|
||||
|
||||
|
||||
def main():
|
||||
|
||||
# build the preamble (license etc)
|
||||
preamble = []
|
||||
preamble.append('''toml++
|
||||
https://github.com/marzer/tomlplusplus''')
|
||||
preamble.append('''*** THIS FILE WAS ASSEMBLED FROM MULTIPLE FILES PROGRAMMATICALLY - DON'T CHANGE IT DIRECTLY ***
|
||||
|
||||
If you wish to submit a change to toml++, hooray and thanks! But please be aware that this file
|
||||
is assembled programmatically by a script and should not be edited directly. You should instead
|
||||
make your changes in the relevant source file. The filenames of the source files are indicated at
|
||||
the beginning and end of the relevant subregions.''')
|
||||
preamble.append('''TOML language documentation:
|
||||
Latest: https://github.com/toml-lang/toml
|
||||
v0.5.0: https://github.com/toml-lang/toml/tree/v0.5.0''')
|
||||
preamble.append(read_all_text_from_file(os.path.join(get_script_folder(), '..', 'LICENSE')))
|
||||
|
||||
# preprocess header(s)
|
||||
source_text = preprocess('toml.h')
|
||||
source_text = re.sub('\r\n', '\n', source_text, 0, re.I | re.M)
|
||||
source_text = re.sub(r'^[ \t]*//[/#!].+?$', '', source_text, 0, re.I | re.M)
|
||||
source_text = re.sub('\n([ \t]*\n[ \t]*)+\n', '\n\n', source_text, 0, re.I | re.M)
|
||||
source_text = re.sub('([^ \t])[ \t]+\n', '\\1\n', source_text, 0, re.I | re.M)
|
||||
source_text = source_text.strip()
|
||||
|
||||
# write the output file
|
||||
output_file_path = os.path.join(get_script_folder(), '..', 'toml.hpp')
|
||||
print("Writing to {}".format(output_file_path))
|
||||
output_file = open(output_file_path,'w', encoding='utf-8', newline='\n')
|
||||
if (len(preamble) > 0):
|
||||
print(make_divider(), file=output_file)
|
||||
for pre in preamble:
|
||||
print('//', file=output_file)
|
||||
for line in pre.splitlines():
|
||||
print('//', file=output_file, end = '')
|
||||
if (len(line) > 0):
|
||||
print(' ', file=output_file, end = '')
|
||||
print(line, file=output_file)
|
||||
else:
|
||||
print('\n', file=output_file, end = '')
|
||||
print('//', file=output_file)
|
||||
print(make_divider(), file=output_file)
|
||||
print(source_text, file=output_file)
|
||||
output_file.close()
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
try:
|
||||
main()
|
||||
except Exception as err:
|
||||
print(
|
||||
'Fatal error: [{}] {}'.format(
|
||||
type(err).__name__,
|
||||
str(err)
|
||||
),
|
||||
file=sys.stderr
|
||||
)
|
||||
traceback.print_exc(file=sys.stderr)
|
||||
sys.exit(1)
|
||||
sys.exit()
|
528
python/generate_unicode_functions.py
Normal file
528
python/generate_unicode_functions.py
Normal file
@ -0,0 +1,528 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import sys
|
||||
import re
|
||||
import os
|
||||
import os.path
|
||||
import math
|
||||
import requests
|
||||
import traceback
|
||||
|
||||
|
||||
#### SETTINGS / MISC #########################################
|
||||
|
||||
|
||||
class Settings:
|
||||
binary_bitmasks = False
|
||||
switch_case_limit = 64
|
||||
|
||||
|
||||
|
||||
def make_literal(codepoint):
|
||||
if (codepoint > 0xFFFF):
|
||||
return "U'\\U{:08X}'".format(codepoint)
|
||||
else:
|
||||
return "U'\\u{:04X}'".format(codepoint)
|
||||
|
||||
|
||||
|
||||
def make_bitmask(codepoint, size=64):
|
||||
if (Settings.binary_bitmasks):
|
||||
if (size==64):
|
||||
return "0b{:064b}ull".format(codepoint)
|
||||
else:
|
||||
return "0b{:032b}u".format(codepoint)
|
||||
else:
|
||||
if (size==64):
|
||||
return "0x{:X}ull".format(codepoint)
|
||||
else:
|
||||
return "0x{:X}u".format(codepoint)
|
||||
|
||||
|
||||
def make_mask_from_indices(indices):
|
||||
mask = 0
|
||||
for i in indices:
|
||||
mask = mask | (1 << i)
|
||||
return mask;
|
||||
|
||||
|
||||
|
||||
def range_first(r):
|
||||
if isinstance(r, int):
|
||||
return r
|
||||
else:
|
||||
return r[0]
|
||||
|
||||
|
||||
|
||||
def range_last(r):
|
||||
if isinstance(r, int):
|
||||
return r
|
||||
else:
|
||||
return r[1]
|
||||
|
||||
|
||||
|
||||
def calculate_subdivisions(span_size):
|
||||
|
||||
# if it's a relatively small span, divide it such the effective size of each subchunk
|
||||
# would be less than or equal to 64 so we'll generate bitmask ops
|
||||
if (64 < span_size <= 4096):
|
||||
subdiv_count = int(math.ceil(span_size / 64))
|
||||
return subdiv_count
|
||||
|
||||
# try to find a divisor that will yield a power-of-2 size
|
||||
subdiv_count = 2
|
||||
subdiv_size = int(math.ceil(span_size / float(subdiv_count)))
|
||||
while (subdiv_count <= Settings.switch_case_limit):
|
||||
if (subdiv_size > 0 and subdiv_size < span_size and (subdiv_size & (subdiv_size-1) == 0)):
|
||||
return subdiv_count
|
||||
subdiv_count += 1
|
||||
subdiv_size = int(math.ceil(span_size / float(subdiv_count)))
|
||||
|
||||
# couldn't find divisor that would yield a power-of-2 size
|
||||
subdiv_count = Settings.switch_case_limit
|
||||
subdiv_size = int(math.ceil(span_size / float(subdiv_count)))
|
||||
while (subdiv_count > 1):
|
||||
if (subdiv_size > 0 and subdiv_size < span_size):
|
||||
return subdiv_count
|
||||
subdiv_count -= 1
|
||||
subdiv_size = int(math.ceil(span_size / float(subdiv_count)))
|
||||
|
||||
return subdiv_count
|
||||
|
||||
|
||||
|
||||
#### CHUNK ###################################################
|
||||
|
||||
|
||||
class Chunk:
|
||||
|
||||
def __init__(self, first, last):
|
||||
self.first = int(first)
|
||||
self.last = int(last)
|
||||
self.span_size = (self.last - self.first) + 1
|
||||
self.count = 0
|
||||
self.ranges = []
|
||||
self.subchunks = None
|
||||
self.subchunk_size = 0
|
||||
self.first_set = self.last + 1
|
||||
self.last_set = -1
|
||||
self.first_unset = self.first
|
||||
|
||||
|
||||
def low_range_mask(self):
|
||||
if self.count == 0:
|
||||
return 0;
|
||||
mask = 0
|
||||
bits = 0
|
||||
prev_last_unset = -1
|
||||
for r in self.ranges:
|
||||
first = range_first(r)
|
||||
last = range_last(r)
|
||||
count = (last - first) + 1
|
||||
while (prev_last_unset >= 0 and prev_last_unset < first and bits < 64):
|
||||
prev_last_unset += 1
|
||||
bits += 1
|
||||
if (bits >= 64):
|
||||
break;
|
||||
while (count > 0 and bits < 64):
|
||||
mask |= (1 << bits)
|
||||
bits += 1
|
||||
count -= 1
|
||||
if (bits >= 64):
|
||||
break;
|
||||
|
||||
prev_last_unset = last + 1
|
||||
return mask
|
||||
|
||||
|
||||
def add(self, first, last = None):
|
||||
f = int(first)
|
||||
num_added = 0
|
||||
if (last is None or first == last):
|
||||
self.ranges.append(f)
|
||||
self.count += 1
|
||||
self.last_set = max(self.last_set, f)
|
||||
if (self.first_unset == f):
|
||||
self.first_unset = f + 1
|
||||
else:
|
||||
l = int(last)
|
||||
self.ranges.append((f, l))
|
||||
self.count += (l - f) + 1
|
||||
self.last_set = max(self.last_set, l)
|
||||
if (self.first_unset == f):
|
||||
self.first_unset = l + 1
|
||||
self.first_set = min(self.first_set, f)
|
||||
|
||||
|
||||
def trim(self):
|
||||
if (self.subchunks is not None
|
||||
or self.count == 0
|
||||
or (self.first_set == self.first and self.last_set == self.last)):
|
||||
return
|
||||
|
||||
self.first = self.first_set
|
||||
self.last = self.last_set
|
||||
self.span_size = (self.last - self.first) + 1
|
||||
|
||||
|
||||
def subdivide(self):
|
||||
if (self.subchunks is not None
|
||||
or self.count >= self.span_size - 1
|
||||
or self.count <= 1
|
||||
or (self.last_set - self.first_set) + 1 <= 64
|
||||
or self.count == (self.last - self.first_set) + 1
|
||||
or self.count == (self.first_unset - self.first)
|
||||
or self.count == (self.last_set - self.first_set) + 1
|
||||
or (len(self.ranges) == 2 and range_first(self.ranges[0]) == self.first and range_last(self.ranges[1]) == self.last)
|
||||
or len(self.ranges) <= 4
|
||||
):
|
||||
return
|
||||
subchunk_count = calculate_subdivisions(self.span_size)
|
||||
if (subchunk_count <= 1):
|
||||
return
|
||||
subchunk_size = int(math.ceil(self.span_size / float(subchunk_count)))
|
||||
if (subchunk_size <= 4):
|
||||
return
|
||||
|
||||
self.subchunks = []
|
||||
self.subchunk_size = subchunk_size
|
||||
for subchunk in range(subchunk_count):
|
||||
self.subchunks.append(
|
||||
Chunk(
|
||||
self.first + (subchunk * self.subchunk_size),
|
||||
min(self.first + (((subchunk + 1) * self.subchunk_size) - 1), self.last)
|
||||
)
|
||||
)
|
||||
for r in self.ranges:
|
||||
if (isinstance(r, int)):
|
||||
subchunk = int((r - self.first) / self.subchunk_size)
|
||||
self.subchunks[subchunk].add(r)
|
||||
else:
|
||||
start_chunk = int((r[0] - self.first) / self.subchunk_size)
|
||||
end_chunk = int((r[1] - self.first) / self.subchunk_size)
|
||||
for subchunk in range(start_chunk, end_chunk+1):
|
||||
self.subchunks[subchunk].add(
|
||||
max(r[0], self.subchunks[subchunk].first),
|
||||
min(r[1], self.subchunks[subchunk].last),
|
||||
)
|
||||
#self.ranges = None
|
||||
for subchunk in self.subchunks:
|
||||
subchunk.trim()
|
||||
subchunk.subdivide()
|
||||
|
||||
|
||||
def always_returns_true(self):
|
||||
return self.count == self.span_size;
|
||||
|
||||
|
||||
def always_returns_false(self):
|
||||
return self.count == 0;
|
||||
|
||||
|
||||
def print_subchunk_case(self, subchunk_index, output_file, level, indent):
|
||||
print("{}\tcase {}: ".format(indent, subchunk_index), end='', file=output_file)
|
||||
if (self.subchunks[subchunk_index].count == self.subchunks[subchunk_index].span_size):
|
||||
self.subchunks[subchunk_index].print(output_file, level + 1, (self.first, self.last))
|
||||
else:
|
||||
if (self.subchunks[subchunk_index].subchunks is not None and self.subchunks[subchunk_index].span_size > 64):
|
||||
print("\n{}\t{{".format(indent), file=output_file)
|
||||
self.subchunks[subchunk_index].print(output_file, level + 1, (self.first, self.last))
|
||||
if (self.subchunks[subchunk_index].subchunks is not None and self.subchunks[subchunk_index].span_size > 64):
|
||||
print("{}\t}}".format(indent), file=output_file)
|
||||
|
||||
|
||||
def return_value_string(self):
|
||||
|
||||
# return true; (completely full range)
|
||||
if (self.always_returns_true()):
|
||||
return 'true';
|
||||
|
||||
# return false; (completely empty range)
|
||||
elif (self.always_returns_false()):
|
||||
return 'false';
|
||||
|
||||
# return cp == A
|
||||
elif (self.count == 1):
|
||||
return 'codepoint == {}'.format(make_literal(self.ranges[0]))
|
||||
|
||||
# return cp != A
|
||||
elif (self.count == self.span_size - 1):
|
||||
return 'codepoint != {}'.format(make_literal(self.first_unset))
|
||||
|
||||
# return cp < A
|
||||
elif (self.count == (self.first_unset - self.first)):
|
||||
return 'codepoint < {}'.format(make_literal(self.first_unset))
|
||||
|
||||
# return cp >= A
|
||||
elif (self.count == (self.last - self.first_set) + 1):
|
||||
return 'codepoint >= {}'.format(make_literal(self.first_set))
|
||||
|
||||
# return cp >= A && cp <= B
|
||||
elif (self.count == (self.last_set - self.first_set) + 1):
|
||||
return 'codepoint >= {} && codepoint <= {}'.format(make_literal(self.first_set), make_literal(self.last_set))
|
||||
|
||||
# return cp <= A || cp >= B
|
||||
elif (len(self.ranges) == 2 and range_first(self.ranges[0]) == self.first and range_last(self.ranges[1]) == self.last):
|
||||
return 'codepoint <= {} || codepoint >= {}'.format(make_literal(range_last(self.ranges[0])), make_literal(range_first(self.ranges[1])))
|
||||
|
||||
# return cp & A (32-bit)
|
||||
elif ((self.last_set - self.first_set) + 1 <= 32):
|
||||
if (self.first_set == self.first):
|
||||
return '(1u << (static_cast<uint_least32_t>(codepoint) - 0x{:X}u)) & {}'.format(self.first_set, make_bitmask(self.low_range_mask(), 32))
|
||||
else:
|
||||
return 'codepoint >= {} && ((1u << (static_cast<uint_least32_t>(codepoint) - 0x{:X}u)) & {})'.format(
|
||||
make_literal(self.first_set), self.first_set, make_bitmask(self.low_range_mask(), 32))
|
||||
|
||||
# return cp & A (64-bit)
|
||||
elif ((self.last_set - self.first_set) + 1 <= 64):
|
||||
if (self.first_set == self.first):
|
||||
return '(1ull << (static_cast<uint_least64_t>(codepoint) - 0x{:X}ull)) & {}'.format(self.first_set, make_bitmask(self.low_range_mask()))
|
||||
else:
|
||||
return 'codepoint >= {} && ((1ull << (static_cast<uint_least64_t>(codepoint) - 0x{:X}ull)) & {})'.format(
|
||||
make_literal(self.first_set), self.first_set, make_bitmask(self.low_range_mask()))
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def print(self, output_file, level = 0, parent_range = None):
|
||||
indent = '\t\t' + ('\t' * (2 * level))
|
||||
if (parent_range is None):
|
||||
parent_range = (0, 0x7FFFFFFF)
|
||||
|
||||
rvs = self.return_value_string()
|
||||
|
||||
# return ______;
|
||||
if (rvs is not None):
|
||||
print("return {};".format(rvs), file=output_file)
|
||||
|
||||
# switch (cp)
|
||||
elif (self.subchunks is not None):
|
||||
|
||||
# guard against non-exhaustive ranges (we may have been trimmed)
|
||||
if (self.first > parent_range[0] and self.last < parent_range[1]):
|
||||
print("{}if (codepoint < {} || codepoint > {})\n{}\treturn false;\n".format(indent, make_literal(self.first), make_literal(self.last), indent), file=output_file)
|
||||
elif (self.first > parent_range[0]):
|
||||
print("{}if (codepoint < {})\n{}\treturn false;\n".format(indent, make_literal(self.first), indent), file=output_file)
|
||||
elif (self.last < parent_range[1]):
|
||||
print("{}if (codepoint > {})\n{}\treturn false;\n".format(indent, make_literal(self.last), indent), file=output_file)
|
||||
|
||||
# see if we can avoid emitting a switch altogether, or reduce its scope
|
||||
always_true = []
|
||||
always_false = []
|
||||
not_always_true_or_false = []
|
||||
for subchunk_index in range(len(self.subchunks)):
|
||||
even = (subchunk_index % 2) == 0
|
||||
if self.subchunks[subchunk_index].always_returns_true():
|
||||
always_true.append(subchunk_index)
|
||||
elif self.subchunks[subchunk_index].always_returns_false():
|
||||
always_false.append(subchunk_index)
|
||||
else:
|
||||
not_always_true_or_false.append(subchunk_index)
|
||||
|
||||
selector = '(static_cast<uint_least32_t>(codepoint) - 0x{:X}u) / {}u'.format(self.first, self.subchunk_size)
|
||||
|
||||
# return selector & mask
|
||||
if (len(always_true) + len(always_false) == len(self.subchunks) and len(self.subchunks) <= 64):
|
||||
print("{}return ({}) & {};".format(indent, selector, make_bitmask(make_mask_from_indices(always_true))), file=output_file)
|
||||
|
||||
# return selector == A ? true : selector & mask
|
||||
#elif (len(not_always_true_or_false) == 1
|
||||
# and (len(always_true) + len(always_false)) == len(self.subchunks)-1
|
||||
# and len(self.subchunks) <= 64):
|
||||
# print('{}const auto selector = {}; //kek'.format(indent, selector), file=output_file)
|
||||
# print('{}return selector == {}u ? true : selector & {};'.format(
|
||||
# indent,
|
||||
# not_always_true_or_false[0],
|
||||
# make_bitmask(make_mask_from_indices(always_true))
|
||||
# ),
|
||||
# file=output_file
|
||||
# )
|
||||
|
||||
# switch(selector)
|
||||
else:
|
||||
print("{}TOML_ASSUME_CODEPOINT_BETWEEN({}, {});".format(indent, make_literal(self.first), make_literal(self.last)), file=output_file)
|
||||
print("{}switch ({})\n{}{{".format(indent, selector, indent), file=output_file)
|
||||
if (len(always_true) == 0 and len(always_false) == 0):
|
||||
for subchunk_index in range(len(self.subchunks)):
|
||||
self.print_subchunk_case(subchunk_index, output_file, level, indent)
|
||||
print("{}\tTOML_NO_DEFAULT_CASE;".format(indent), file=output_file)
|
||||
elif (len(always_true) > len(always_false)):
|
||||
for subchunk_index in range(len(self.subchunks)):
|
||||
if not self.subchunks[subchunk_index].always_returns_true():
|
||||
self.print_subchunk_case(subchunk_index, output_file, level, indent)
|
||||
print("{}\tdefault: return true;".format(indent), file=output_file)
|
||||
else:
|
||||
for subchunk_index in range(len(self.subchunks)):
|
||||
if not self.subchunks[subchunk_index].always_returns_false():
|
||||
self.print_subchunk_case(subchunk_index, output_file, level, indent)
|
||||
print("{}\tdefault: return false;".format(indent), file=output_file)
|
||||
print("{}}}".format(indent), file=output_file)
|
||||
print("{}// chunk summary: {} codepoints from {} ranges (spanning a search area of {})".format(indent, self.count, len(self.ranges), self.span_size), file=output_file)
|
||||
|
||||
# return cp == A || cp == B ...
|
||||
else:
|
||||
print("return", end='', file=output_file)
|
||||
line_weight = 0
|
||||
first_line = True
|
||||
for range_idx in range(0, len(self.ranges)):
|
||||
r = self.ranges[range_idx]
|
||||
range_weight = (1 if (
|
||||
isinstance(r, int)
|
||||
or (range_idx == 0 and r[0] == self.first)
|
||||
or (range_idx == (len(self.ranges)-1) and r[1] == self.last))
|
||||
else 2
|
||||
)
|
||||
needs_space = True
|
||||
if ((line_weight + range_weight) > (4 - (1 if first_line else 0))):
|
||||
print("\n\t{}".format(indent), end='', file=output_file)
|
||||
line_weight = range_weight
|
||||
needs_space = False
|
||||
first_line = False
|
||||
else:
|
||||
line_weight += range_weight
|
||||
if (needs_space):
|
||||
print(" ", end='', file=output_file)
|
||||
if (range_idx > 0):
|
||||
print("|| ", end='', file=output_file)
|
||||
if (isinstance(r, int)):
|
||||
print("codepoint == {}".format(make_literal(r)), end='', file=output_file)
|
||||
elif (range_idx == 0 and r[0] == self.first):
|
||||
print("codepoint <= {}".format(make_literal(r[1])), end='', file=output_file)
|
||||
elif (range_idx == (len(self.ranges)-1) and r[1] == self.last):
|
||||
print("codepoint >= {}".format(make_literal(r[0])), end='', file=output_file)
|
||||
else:
|
||||
print("{}codepoint >= {} && codepoint <= {}{}".format(
|
||||
'(' if len(self.ranges) > 1 else '',
|
||||
make_literal(r[0]),
|
||||
make_literal(r[1]),
|
||||
')' if len(self.ranges) > 1 else ''
|
||||
),
|
||||
end='',
|
||||
file=output_file
|
||||
)
|
||||
print(";", file=output_file)
|
||||
|
||||
|
||||
|
||||
#### FUNCTION GENERATOR #####################################
|
||||
|
||||
|
||||
|
||||
def emit_function(name, categories, file, codepoints):
|
||||
|
||||
# divide the codepoints up into chunks of ranges
|
||||
root_chunk = Chunk(codepoints[0][0], codepoints[-1][0])
|
||||
first_codepoint = -1
|
||||
last_codepoint = -1
|
||||
for codepoint, category in codepoints:
|
||||
if (category in categories):
|
||||
if (first_codepoint == -1):
|
||||
first_codepoint = codepoint
|
||||
last_codepoint = codepoint
|
||||
elif (last_codepoint == codepoint-1):
|
||||
last_codepoint = codepoint
|
||||
else:
|
||||
root_chunk.add(first_codepoint, last_codepoint)
|
||||
first_codepoint = codepoint
|
||||
last_codepoint = codepoint
|
||||
if (first_codepoint != -1):
|
||||
root_chunk.add(first_codepoint, last_codepoint)
|
||||
root_chunk.trim()
|
||||
root_chunk.subdivide()
|
||||
|
||||
# write the function
|
||||
|
||||
print('\n\t/// \\brief Returns true if a codepoint belongs to any of these categories: {}'.format(', '.join(categories)), file=file)
|
||||
print('\t[[nodiscard]]', file=file)
|
||||
print('\tconstexpr bool {}(char32_t codepoint) noexcept\n\t{{'.format(name), file=file)
|
||||
root_chunk.print(file)
|
||||
print('\t}', file=file)
|
||||
|
||||
|
||||
|
||||
#### MAIN ####################################################
|
||||
|
||||
|
||||
|
||||
def get_script_folder():
|
||||
return os.path.dirname(os.path.realpath(sys.argv[0]))
|
||||
|
||||
|
||||
|
||||
def main():
|
||||
|
||||
# get unicode character database
|
||||
codepoint_list = ''
|
||||
codepoint_file_path = os.path.join(get_script_folder(), 'UnicodeData.txt')
|
||||
if (not os.path.exists(codepoint_file_path)):
|
||||
print("Couldn't find unicode database file, will download")
|
||||
response = requests.get(
|
||||
'https://www.unicode.org/Public/UCD/latest/ucd/UnicodeData.txt',
|
||||
timeout=1
|
||||
)
|
||||
codepoint_list = response.text
|
||||
codepoint_file = open(codepoint_file_path, 'w', newline='\n')
|
||||
print(codepoint_list, end='', file=codepoint_file)
|
||||
codepoint_file.close()
|
||||
else:
|
||||
print("Reading unicode database file into memory")
|
||||
codepoint_file = open(codepoint_file_path, 'r')
|
||||
codepoint_list = codepoint_file.read()
|
||||
codepoint_file.close()
|
||||
|
||||
# parse the database file into codepoints
|
||||
re_codepoint = re.compile(r'^([0-9a-fA-F]+);(.+?);([a-zA-Z]+);')
|
||||
current_range_start = -1
|
||||
codepoints = []
|
||||
for codepoint_entry in codepoint_list.split('\n'):
|
||||
match = re_codepoint.search(codepoint_entry)
|
||||
if (match is None):
|
||||
if (current_range_start > -1):
|
||||
raise Exception('Previous codepoint indicated the start of a range but the next one was null')
|
||||
continue
|
||||
codepoint = int('0x{}'.format(match.group(1)), 16)
|
||||
if (codepoint <= 128): # ASCII range is handled separately
|
||||
continue
|
||||
if (current_range_start > -1):
|
||||
for cp in range(current_range_start, codepoint):
|
||||
codepoints.append((cp, match.group(3)))
|
||||
current_range_start = -1
|
||||
else:
|
||||
if (match.group(2).endswith(', First>')):
|
||||
current_range_start = codepoint
|
||||
else:
|
||||
codepoints.append((codepoint, match.group(3)))
|
||||
print("Parsed {} codepoints from unicode database file.".format(len(codepoints)))
|
||||
codepoints.sort(key=lambda r:r[0])
|
||||
|
||||
# write the output file
|
||||
output_file_path = os.path.join(get_script_folder(), '..', 'include', 'toml++', 'toml_utf8_generated.h')
|
||||
print("Writing to {}".format(output_file_path))
|
||||
output_file = open(output_file_path, 'w', newline='\n')
|
||||
print('//# this file was generated by generate_unicode_functions.py', file=output_file)
|
||||
print('#pragma once', file=output_file)
|
||||
print('#include "toml_common.h"', file=output_file)
|
||||
print('\n#define TOML_ASSUME_CODEPOINT_BETWEEN(first, last)\t\\\n\tTOML_ASSUME(codepoint >= first);\t\t\t\t\\\n\tTOML_ASSUME(codepoint <= last)', file=output_file)
|
||||
print('\nnamespace toml::impl\n{', file=output_file, end='')
|
||||
emit_function('is_unicode_letter', ('Ll', 'Lm', 'Lo', 'Lt', 'Lu'), output_file, codepoints)
|
||||
emit_function('is_unicode_number', ('Nd', 'Nl'), output_file, codepoints)
|
||||
emit_function('is_unicode_combining_mark', ('Mn', 'Mc'), output_file, codepoints)
|
||||
print('}\n\n#undef TOML_ASSUME_CODEPOINT_BETWEEN', file=output_file)
|
||||
output_file.close()
|
||||
|
||||
if __name__ == '__main__':
|
||||
try:
|
||||
main()
|
||||
except Exception as err:
|
||||
print(
|
||||
'Fatal error: [{}] {}'.format(
|
||||
type(err).__name__,
|
||||
str(err)
|
||||
),
|
||||
file=sys.stderr
|
||||
)
|
||||
traceback.print_exc(file=sys.stderr)
|
||||
sys.exit(1)
|
||||
sys.exit()
|
1
tests/catch2
Submodule
1
tests/catch2
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit d10b9bd02e098476670f5eb0527d2c7281476e8a
|
55
tests/catch2.h
Normal file
55
tests/catch2.h
Normal file
@ -0,0 +1,55 @@
|
||||
#pragma once
|
||||
|
||||
//catch config
|
||||
#define CATCH_CONFIG_CPP11_TO_STRING
|
||||
#define CATCH_CONFIG_CPP17_OPTIONAL
|
||||
#define CATCH_CONFIG_CPP17_STRING_VIEW
|
||||
#define CATCH_CONFIG_FAST_COMPILE
|
||||
#define CATCH_CONFIG_CONSOLE_WIDTH 100
|
||||
|
||||
//windows.h config
|
||||
#ifdef _WIN32
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#define VC_EXTRALEAN
|
||||
#define NOATOM // - Atom Manager routines
|
||||
#define NOBITMAP
|
||||
#define NOCLIPBOARD // - Clipboard routines
|
||||
#define NOCOLOR // - Screen colors
|
||||
#define NOCOMM // - COMM driver routines
|
||||
#define NOCTLMGR // - Control and Dialog routines
|
||||
#define NODEFERWINDOWPOS // - DeferWindowPos routines
|
||||
#define NODRAWTEXT // - DrawText() and DT_*
|
||||
#define NOGDI // - All GDI defines and routines
|
||||
#define NOGDICAPMASKS // - CC_*, LC_*, PC_*, CP_*, TC_*, RC_
|
||||
#define NOHELP // - Help engine interface.
|
||||
#define NOICONS // - IDI_*
|
||||
#define NOKANJI // - Kanji support stuff.
|
||||
#define NOKEYSTATES // - MK_*
|
||||
#define NOKERNEL // - All KERNEL defines and routines
|
||||
#define NOMB // - MB_* and MessageBox()
|
||||
#define NOMCX // - Modem Configuration Extensions
|
||||
#define NOMENUS // - MF_*
|
||||
#define NOMEMMGR // - GMEM_*, LMEM_*, GHND, LHND, associated routines
|
||||
#define NOMETAFILE // - typedef METAFILEPICT
|
||||
#define NOMINMAX // - Macros min(a,b) and max(a,b)
|
||||
#define NOMSG // - typedef MSG and associated routines
|
||||
#define NONLS // - All NLS defines and routines
|
||||
#define NOOPENFILE // - OpenFile(), OemToAnsi, AnsiToOem, and OF_*
|
||||
#define NOPROFILER // - Profiler interface.
|
||||
#define NORASTEROPS // - Binary and Tertiary raster ops
|
||||
#define NOSCROLL // - SB_* and scrolling routines
|
||||
#define NOSERVICE // - All Service Controller routines, SERVICE_ equates, etc.
|
||||
#define NOSHOWWINDOW // - SW_*
|
||||
#define NOSOUND // - Sound driver routines
|
||||
#define NOSYSCOMMANDS // - SC_*
|
||||
#define NOSYSMETRICS // - SM_*
|
||||
#define NOTEXTMETRIC // - typedef TEXTMETRIC and associated routines
|
||||
#define NOUSER // - All USER defines and routines
|
||||
#define NOVIRTUALKEYCODES // - VK_*
|
||||
#define NOWH // - SetWindowsHook and WH_*
|
||||
#define NOWINOFFSETS // - GWL_*, GCL_*, associated routines
|
||||
#define NOWINMESSAGES // - WM_*, EM_*, LB_*, CB_*
|
||||
#define NOWINSTYLES // - WS_*, CS_*, ES_*, LBS_*, SBS_*, CBS_*
|
||||
#endif
|
||||
|
||||
#include <catch2/single_include/catch2/catch.hpp>
|
40
tests/lifetimes.cpp
Normal file
40
tests/lifetimes.cpp
Normal file
@ -0,0 +1,40 @@
|
||||
#include "tests.h"
|
||||
|
||||
TEST_CASE("lifetime - tables")
|
||||
{
|
||||
static constexpr auto filename = "foo.toml"sv;
|
||||
|
||||
parsing_should_succeed(
|
||||
S(R"(test = { val1 = "foo" })"sv),
|
||||
[&](table&& tbl) noexcept
|
||||
{
|
||||
CHECK(tbl.region().begin == source_position{ 1, 1 });
|
||||
CHECK(tbl.region().end == source_position{ 1, 25 });
|
||||
CHECK(tbl.region().path);
|
||||
CHECK(*tbl.region().path == filename);
|
||||
CHECK(tbl.size() == 1_sz);
|
||||
REQUIRE(tbl[S("test")].as<table>());
|
||||
CHECK(tbl[S("test")].as<table>()->size() == 1_sz);
|
||||
CHECK(tbl[S("test")][S("val1")] == S("foo"sv));
|
||||
|
||||
table test_table;
|
||||
CHECK(test_table.region().begin == source_position{});
|
||||
CHECK(test_table.region().end == source_position{});
|
||||
CHECK(!test_table.region().path);
|
||||
CHECK(test_table.size() == 0_sz);
|
||||
CHECK(!test_table[S("test")].as<table>());
|
||||
|
||||
test_table = std::move(tbl);
|
||||
CHECK(test_table.region().begin == source_position{ 1, 1 });
|
||||
CHECK(test_table.region().end == source_position{ 1, 25 });
|
||||
CHECK(test_table.region().path);
|
||||
CHECK(*test_table.region().path == filename);
|
||||
CHECK(test_table.size() == 1_sz);
|
||||
REQUIRE(test_table[S("test")].as<table>());
|
||||
CHECK(test_table[S("test")].as<table>()->size() == 1_sz);
|
||||
CHECK(test_table[S("test")][S("val1")] == S("foo"sv));
|
||||
},
|
||||
filename
|
||||
);
|
||||
|
||||
}
|
11
tests/main.cpp
Normal file
11
tests/main.cpp
Normal file
@ -0,0 +1,11 @@
|
||||
#define CATCH_CONFIG_RUNNER
|
||||
#include "catch2.h"
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
#ifdef _WIN32
|
||||
SetConsoleOutputCP(65001);
|
||||
#endif
|
||||
|
||||
return Catch::Session().run(argc, argv);;
|
||||
}
|
73
tests/meson.build
Normal file
73
tests/meson.build
Normal file
@ -0,0 +1,73 @@
|
||||
test_sources = [
|
||||
'lifetimes.cpp',
|
||||
'main.cpp',
|
||||
'parsing_arrays.cpp',
|
||||
'parsing_booleans.cpp',
|
||||
'parsing_comments.cpp',
|
||||
'parsing_dates_and_times.cpp',
|
||||
'parsing_floats.cpp',
|
||||
'parsing_integers.cpp',
|
||||
'parsing_key_value_pairs.cpp',
|
||||
'parsing_spec_example.cpp',
|
||||
'parsing_strings.cpp',
|
||||
'parsing_tables.cpp'
|
||||
]
|
||||
|
||||
disable_exceptions = 'cpp_eh=none'
|
||||
no_unreleased_features = '-DTOML_UNRELEASED_FEATURES=0'
|
||||
|
||||
|
||||
test_char = executable(
|
||||
'test_char',
|
||||
test_sources,
|
||||
include_directories : inc
|
||||
)
|
||||
test('test_char', test_char)
|
||||
|
||||
|
||||
test_char_noexcept = executable(
|
||||
'test_char_noexcept',
|
||||
test_sources,
|
||||
include_directories : inc,
|
||||
override_options : [ disable_exceptions ]
|
||||
)
|
||||
test('test_char_noexcept', test_char_noexcept)
|
||||
|
||||
|
||||
test_strict_char = executable(
|
||||
'test_strict_char',
|
||||
test_sources,
|
||||
include_directories : inc,
|
||||
cpp_args : [ no_unreleased_features ]
|
||||
)
|
||||
test('test_strict_char', test_strict_char)
|
||||
|
||||
|
||||
test_strict_char_noexcept = executable(
|
||||
'test_strict_char_noexcept',
|
||||
test_sources,
|
||||
include_directories : inc,
|
||||
override_options : [ disable_exceptions ],
|
||||
cpp_args : [ no_unreleased_features ]
|
||||
)
|
||||
test('test_strict_char_noexcept', test_strict_char_noexcept)
|
||||
|
||||
|
||||
|
||||
# char8_t is not supported until gcc9, yo.
|
||||
# test_char8 = executable(
|
||||
# 'test_char8',
|
||||
# test_sources,
|
||||
# include_directories : inc,
|
||||
# cpp_args : ['-DTOML_CHAR_8_STRINGS=1', '-fchar8_t']
|
||||
#)
|
||||
#
|
||||
# test_char8_noexcept = executable(
|
||||
# 'test_char8_noexcept',
|
||||
# test_sources,
|
||||
# include_directories : inc,
|
||||
# override_options : [ disable_exceptions ],
|
||||
# cpp_args : ['-DTOML_CHAR_8_STRINGS=1', '-fchar8_t']
|
||||
#)
|
||||
|
||||
|
140
tests/parsing_arrays.cpp
Normal file
140
tests/parsing_arrays.cpp
Normal file
@ -0,0 +1,140 @@
|
||||
#include "tests.h"
|
||||
|
||||
TEST_CASE("parsing arrays")
|
||||
{
|
||||
parsing_should_succeed(S(R"(
|
||||
integers = [ 1, 2, 3 ]
|
||||
integers2 = [
|
||||
1, 2, 3
|
||||
]
|
||||
integers3 = [
|
||||
1,
|
||||
2, # this is ok
|
||||
]
|
||||
colors = [ "red", "yellow", "green" ]
|
||||
nested_array_of_int = [ [ 1, 2 ], [3, 4, 5] ]
|
||||
nested_mixed_array = [ [ 1, 2 ], ["a", "b", "c"] ]
|
||||
string_array = [ "all", 'strings', """are the same""", '''type''' ]
|
||||
)"sv),
|
||||
[](table&& tbl) noexcept
|
||||
{
|
||||
REQUIRE(tbl[S("integers")].as<array>());
|
||||
CHECK(tbl[S("integers")].as<array>()->is_homogeneous());
|
||||
CHECK(tbl[S("integers")].as<array>()->size() == 3);
|
||||
CHECK(tbl[S("integers")][0] == 1);
|
||||
CHECK(tbl[S("integers")][1] == 2);
|
||||
CHECK(tbl[S("integers")][2] == 3);
|
||||
|
||||
REQUIRE(tbl[S("integers2")].as<array>());
|
||||
CHECK(tbl[S("integers2")].as<array>()->is_homogeneous());
|
||||
CHECK(tbl[S("integers2")].as<array>()->size() == 3);
|
||||
CHECK(tbl[S("integers2")][0] == 1);
|
||||
CHECK(tbl[S("integers2")][1] == 2);
|
||||
CHECK(tbl[S("integers2")][2] == 3);
|
||||
|
||||
REQUIRE(tbl[S("integers3")].as<array>());
|
||||
CHECK(tbl[S("integers3")].as<array>()->is_homogeneous());
|
||||
CHECK(tbl[S("integers3")].as<array>()->size() == 2);
|
||||
CHECK(tbl[S("integers3")][0] == 1);
|
||||
CHECK(tbl[S("integers3")][1] == 2);
|
||||
|
||||
REQUIRE(tbl[S("colors")].as<array>());
|
||||
CHECK(tbl[S("colors")].as<array>()->is_homogeneous());
|
||||
CHECK(tbl[S("colors")].as<array>()->size() == 3);
|
||||
CHECK(tbl[S("colors")][0] == S("red"sv));
|
||||
CHECK(tbl[S("colors")][1] == S("yellow"sv));
|
||||
CHECK(tbl[S("colors")][2] == S("green"sv));
|
||||
|
||||
REQUIRE(tbl[S("nested_array_of_int")].as<array>());
|
||||
CHECK(tbl[S("nested_array_of_int")].as<array>()->is_homogeneous());
|
||||
CHECK(tbl[S("nested_array_of_int")].as<array>()->size() == 2);
|
||||
REQUIRE(tbl[S("nested_array_of_int")][0].as<array>());
|
||||
CHECK(tbl[S("nested_array_of_int")][0].as<array>()->is_homogeneous());
|
||||
CHECK(tbl[S("nested_array_of_int")][0].as<array>()->size() == 2);
|
||||
CHECK(tbl[S("nested_array_of_int")][0][0] == 1);
|
||||
CHECK(tbl[S("nested_array_of_int")][0][1] == 2);
|
||||
REQUIRE(tbl[S("nested_array_of_int")][1].as<array>());
|
||||
CHECK(tbl[S("nested_array_of_int")][1].as<array>()->is_homogeneous());
|
||||
CHECK(tbl[S("nested_array_of_int")][1].as<array>()->size() == 3);
|
||||
CHECK(tbl[S("nested_array_of_int")][1][0] == 3);
|
||||
CHECK(tbl[S("nested_array_of_int")][1][1] == 4);
|
||||
CHECK(tbl[S("nested_array_of_int")][1][2] == 5);
|
||||
|
||||
REQUIRE(tbl[S("nested_mixed_array")].as<array>());
|
||||
CHECK(tbl[S("nested_mixed_array")].as<array>()->is_homogeneous());
|
||||
CHECK(tbl[S("nested_mixed_array")].as<array>()->size() == 2);
|
||||
REQUIRE(tbl[S("nested_mixed_array")][0].as<array>());
|
||||
CHECK(tbl[S("nested_mixed_array")][0].as<array>()->is_homogeneous());
|
||||
CHECK(tbl[S("nested_mixed_array")][0].as<array>()->size() == 2);
|
||||
CHECK(tbl[S("nested_mixed_array")][0][0] == 1);
|
||||
CHECK(tbl[S("nested_mixed_array")][0][1] == 2);
|
||||
REQUIRE(tbl[S("nested_mixed_array")][1].as<array>());
|
||||
CHECK(tbl[S("nested_mixed_array")][1].as<array>()->is_homogeneous());
|
||||
CHECK(tbl[S("nested_mixed_array")][1].as<array>()->size() == 3);
|
||||
CHECK(tbl[S("nested_mixed_array")][1][0] == S("a"sv));
|
||||
CHECK(tbl[S("nested_mixed_array")][1][1] == S("b"sv));
|
||||
CHECK(tbl[S("nested_mixed_array")][1][2] == S("c"sv));
|
||||
|
||||
REQUIRE(tbl[S("string_array")].as<array>());
|
||||
CHECK(tbl[S("string_array")].as<array>()->is_homogeneous());
|
||||
CHECK(tbl[S("string_array")].as<array>()->size() == 4);
|
||||
CHECK(tbl[S("string_array")][0] == S("all"sv));
|
||||
CHECK(tbl[S("string_array")][1] == S("strings"sv));
|
||||
CHECK(tbl[S("string_array")][2] == S("are the same"sv));
|
||||
CHECK(tbl[S("string_array")][3] == S("type"sv));
|
||||
REQUIRE(tbl[S("integers")].as<array>());
|
||||
CHECK(tbl[S("integers")].as<array>()->is_homogeneous());
|
||||
CHECK(tbl[S("integers")].as<array>()->size() == 3);
|
||||
CHECK(tbl[S("integers")][0] == 1);
|
||||
CHECK(tbl[S("integers")][1] == 2);
|
||||
CHECK(tbl[S("integers")][2] == 3);
|
||||
}
|
||||
);
|
||||
|
||||
// heterogeneous arrays are allowed after 0.5.0
|
||||
#if TOML_LANG_HIGHER_THAN(0, 5, 0)
|
||||
|
||||
parsing_should_succeed(S(R"(
|
||||
# Mixed-type arrays are allowed
|
||||
numbers = [ 0.1, 0.2, 0.5, 1, 2, 5 ]
|
||||
contributors = [
|
||||
"Foo Bar <foo@example.com>",
|
||||
{ name = "Baz Qux", email = "bazqux@example.com", url = "https://example.com/bazqux" }
|
||||
]
|
||||
)"sv),
|
||||
[](table&& tbl) noexcept
|
||||
{
|
||||
REQUIRE(tbl[S("numbers")].as<array>());
|
||||
CHECK(!tbl[S("numbers")].as<array>()->is_homogeneous());
|
||||
CHECK(tbl[S("numbers")].as<array>()->size() == 6);
|
||||
CHECK(tbl[S("numbers")][0].as<double>());
|
||||
CHECK(tbl[S("numbers")][1].as<double>());
|
||||
CHECK(tbl[S("numbers")][2].as<double>());
|
||||
CHECK(tbl[S("numbers")][3].as<int64_t>());
|
||||
CHECK(tbl[S("numbers")][4].as<int64_t>());
|
||||
CHECK(tbl[S("numbers")][5].as<int64_t>());
|
||||
CHECK(tbl[S("numbers")][0] == 0.1);
|
||||
CHECK(tbl[S("numbers")][1] == 0.2);
|
||||
CHECK(tbl[S("numbers")][2] == 0.5);
|
||||
CHECK(tbl[S("numbers")][3] == 1);
|
||||
CHECK(tbl[S("numbers")][4] == 2);
|
||||
CHECK(tbl[S("numbers")][5] == 5);
|
||||
|
||||
REQUIRE(tbl[S("contributors")].as<array>());
|
||||
CHECK(!tbl[S("contributors")].as<array>()->is_homogeneous());
|
||||
CHECK(tbl[S("contributors")].as<array>()->size() == 2);
|
||||
CHECK(tbl[S("contributors")][0].as<string>());
|
||||
CHECK(tbl[S("contributors")][1].as<table>());
|
||||
CHECK(tbl[S("contributors")][0] == S("Foo Bar <foo@example.com>"sv));
|
||||
CHECK(tbl[S("contributors")][1][S("name")] == S("Baz Qux"sv));
|
||||
CHECK(tbl[S("contributors")][1][S("email")] == S("bazqux@example.com"sv));
|
||||
CHECK(tbl[S("contributors")][1][S("url")] == S("https://example.com/bazqux"sv));
|
||||
}
|
||||
);
|
||||
|
||||
#else
|
||||
|
||||
parsing_should_fail(S("numbers = [ 0.1, 0.2, 0.5, 1, 2, 5 ]"sv));
|
||||
|
||||
#endif
|
||||
}
|
27
tests/parsing_booleans.cpp
Normal file
27
tests/parsing_booleans.cpp
Normal file
@ -0,0 +1,27 @@
|
||||
#include "tests.h"
|
||||
|
||||
TEST_CASE("parsing booleans")
|
||||
{
|
||||
parsing_should_succeed(S(R"(
|
||||
bool1 = true
|
||||
bool2 = false
|
||||
)"sv),
|
||||
[](table&& tbl) noexcept
|
||||
{
|
||||
CHECK(tbl[S("bool1")] == true);
|
||||
CHECK(tbl[S("bool2")] == false);
|
||||
}
|
||||
);
|
||||
|
||||
// "Always lowercase."
|
||||
parsing_should_fail(S("bool = True"sv));
|
||||
parsing_should_fail(S("bool = TRUE"sv));
|
||||
parsing_should_fail(S("bool = tRUE"sv));
|
||||
parsing_should_fail(S("bool = False"sv));
|
||||
parsing_should_fail(S("bool = FALSE"sv));
|
||||
parsing_should_fail(S("bool = fALSE"sv));
|
||||
|
||||
// value tests
|
||||
parse_expected_value(" true", true);
|
||||
parse_expected_value("false", false);
|
||||
}
|
17
tests/parsing_comments.cpp
Normal file
17
tests/parsing_comments.cpp
Normal file
@ -0,0 +1,17 @@
|
||||
#include "tests.h"
|
||||
|
||||
TEST_CASE("parsing comments")
|
||||
{
|
||||
parsing_should_succeed(S(R"(
|
||||
# This is a full-line comment
|
||||
key = "value" # This is a comment at the end of a line
|
||||
another = "# This is not a comment"
|
||||
)"sv),
|
||||
[](table&& tbl) noexcept
|
||||
{
|
||||
CHECK(tbl.size() == 2);
|
||||
CHECK(tbl[S("key")] == S("value"sv));
|
||||
CHECK(tbl[S("another")] == S("# This is not a comment"sv));
|
||||
}
|
||||
);
|
||||
}
|
43
tests/parsing_dates_and_times.cpp
Normal file
43
tests/parsing_dates_and_times.cpp
Normal file
@ -0,0 +1,43 @@
|
||||
#include "tests.h"
|
||||
|
||||
TOML_PUSH_WARNINGS
|
||||
TOML_DISABLE_FIELD_INIT_WARNING
|
||||
|
||||
TEST_CASE("parsing dates and times")
|
||||
{
|
||||
parsing_should_succeed(S(R"(
|
||||
odt1 = 1979-05-27T07:32:00Z
|
||||
odt2 = 1979-05-27T00:32:00-07:00
|
||||
odt3 = 1979-05-27T00:32:00.999999-07:00
|
||||
odt4 = 1979-05-27 07:32:00Z
|
||||
ldt1 = 1979-05-27T07:32:00
|
||||
ldt2 = 1979-05-27T00:32:00.999999
|
||||
ld1 = 1979-05-27
|
||||
lt1 = 07:32:00
|
||||
lt2 = 00:32:00.999999
|
||||
)"sv),
|
||||
[](table&& tbl) noexcept
|
||||
{
|
||||
static constexpr auto odt1 = date_time{ { 1979, 5, 27 }, { 7, 32 }, time_offset{} };
|
||||
CHECK(tbl[S("odt1")] == odt1);
|
||||
static constexpr auto odt2 = date_time{ { 1979, 5, 27 }, { 0, 32 }, time_offset{ -7 } };
|
||||
CHECK(tbl[S("odt2")] == odt2);
|
||||
static constexpr auto odt3 = date_time{ { 1979, 5, 27 }, { 0, 32, 0, 999999000u }, time_offset{ -7 } };
|
||||
CHECK(tbl[S("odt3")] == odt3);
|
||||
static constexpr auto odt4 = date_time{ { 1979, 5, 27 }, { 7, 32 }, time_offset{} };
|
||||
CHECK(tbl[S("odt4")] == odt4);
|
||||
static constexpr auto ldt1 = date_time{ { 1979, 5, 27 }, { 7, 32 } };
|
||||
CHECK(tbl[S("ldt1")] == ldt1);
|
||||
static constexpr auto ldt2 = date_time{ { 1979, 5, 27 }, { 0, 32, 0, 999999000u } };
|
||||
CHECK(tbl[S("ldt2")] == ldt2);
|
||||
static constexpr auto ld1 = date{ 1979, 5, 27 };
|
||||
CHECK(tbl[S("ld1")] == ld1);
|
||||
static constexpr auto lt1 = toml::time{ 7, 32 };
|
||||
CHECK(tbl[S("lt1")] == lt1);
|
||||
static constexpr auto lt2 = toml::time{ 0, 32, 0, 999999000u };
|
||||
CHECK(tbl[S("lt2")] == lt2);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
TOML_POP_WARNINGS
|
112
tests/parsing_floats.cpp
Normal file
112
tests/parsing_floats.cpp
Normal file
@ -0,0 +1,112 @@
|
||||
#include "tests.h"
|
||||
|
||||
TEST_CASE("parsing floats - normal")
|
||||
{
|
||||
parsing_should_succeed(S(R"(
|
||||
# fractional
|
||||
flt1 = +1.0
|
||||
flt2 = 3.1415
|
||||
flt3 = -0.01
|
||||
|
||||
# exponent
|
||||
flt4 = 5e+22
|
||||
flt5 = 1e06
|
||||
flt6 = -2E-2
|
||||
|
||||
# both
|
||||
flt7 = 6.626e-34
|
||||
|
||||
flt8 = 224_617.445_991_228
|
||||
)"sv),
|
||||
[](table&& tbl) noexcept
|
||||
{
|
||||
CHECK(tbl[S("flt1")] == 1.0);
|
||||
CHECK(tbl[S("flt2")] == 3.1415);
|
||||
CHECK(tbl[S("flt3")] == -0.01);
|
||||
CHECK(tbl[S("flt4")].as<double>()->get() == 5e+22_a);
|
||||
CHECK(tbl[S("flt5")].as<double>()->get() == 1e6_a);
|
||||
CHECK(tbl[S("flt6")] == -2E-2);
|
||||
CHECK(tbl[S("flt7")].as<double>()->get() == 6.626e-34_a);
|
||||
CHECK(tbl[S("flt8")].as<double>()->get() == 224617.445991228_a);
|
||||
}
|
||||
);
|
||||
|
||||
// "Each underscore must be surrounded by at least one digit on each side."
|
||||
parsing_should_fail(S("flt8 = 224_617.445_991_228_"sv));
|
||||
parsing_should_fail(S("flt8 = _224_617.445_991_228"sv));
|
||||
parsing_should_fail(S("flt8 = 224__617.445_991_228"sv));
|
||||
|
||||
// "Float values -0.0 and +0.0 are valid and should map according to IEEE 754."
|
||||
parsing_should_succeed(
|
||||
S(R"(zeroes = [-0.0, +0.0])"sv),
|
||||
[](table&& tbl) noexcept
|
||||
{
|
||||
CHECK(tbl[S("zeroes")][0] == -0.0);
|
||||
CHECK(tbl[S("zeroes")][1] == +0.0);
|
||||
}
|
||||
);
|
||||
|
||||
//value tests
|
||||
parse_expected_value( "1.0"sv, 1.0 );
|
||||
parse_expected_value( "0.1"sv, 0.1 );
|
||||
parse_expected_value( "0.001"sv, 0.001 );
|
||||
parse_expected_value( "0.100"sv, 0.1 );
|
||||
parse_expected_value( "+3.14"sv, 3.14 );
|
||||
parse_expected_value( "-3.14"sv, -3.14 );
|
||||
parse_expected_value( "3.1415_9265_3589"sv, 3.141592653589 );
|
||||
parse_expected_value( "+3.1415_9265_3589"sv, 3.141592653589 );
|
||||
parse_expected_value( "-3.1415_9265_3589"sv, -3.141592653589 );
|
||||
parse_expected_value( "123_456.789"sv, 123456.789 );
|
||||
parse_expected_value( "+123_456.789"sv, 123456.789 );
|
||||
parse_expected_value( "-123_456.789"sv, -123456.789 );
|
||||
parse_expected_value( "+0.0"sv, 0.0 );
|
||||
parse_expected_value( "-0.0"sv, -0.0 );
|
||||
parse_expected_value( "1e10"sv, 1e10 );
|
||||
parse_expected_value( "1e+10"sv, 1e10 );
|
||||
parse_expected_value( "1e-10"sv, 1e-10 );
|
||||
parse_expected_value( "+1e10"sv, 1e10 );
|
||||
parse_expected_value( "+1e+10"sv, 1e10 );
|
||||
parse_expected_value( "+1e-10"sv, 1e-10 );
|
||||
parse_expected_value( "-1e10"sv, -1e10 );
|
||||
parse_expected_value( "-1e+10"sv, -1e10 );
|
||||
parse_expected_value( "-1e-10"sv, -1e-10 );
|
||||
parse_expected_value( "123e-10"sv, 123e-10 );
|
||||
parse_expected_value( "1E10"sv, 1e10 );
|
||||
parse_expected_value( "1E+10"sv, 1e10 );
|
||||
parse_expected_value( "1E-10"sv, 1e-10 );
|
||||
parse_expected_value( "123E-10"sv, 123e-10 );
|
||||
parse_expected_value( "1_2_3E-10"sv, 123e-10 );
|
||||
parse_expected_value( "1_2_3E-1_0"sv, 123e-10 );
|
||||
parse_expected_value( "+0e0"sv, 0.0 );
|
||||
parse_expected_value( "-0e0"sv, -0.0 );
|
||||
parse_expected_value( "1_2_3E-01"sv, 123e-1 );
|
||||
parse_expected_value( "1_2_3E-0_1"sv, 123e-1 );
|
||||
parse_expected_value( "6.02e23"sv, 6.02e23 );
|
||||
parse_expected_value( "6.02e+23"sv, 6.02e23 );
|
||||
parse_expected_value( "1.112_650_06e-17"sv, 1.11265006e-17 );
|
||||
}
|
||||
|
||||
TEST_CASE("parsing floats - inf and nan")
|
||||
{
|
||||
parsing_should_succeed(S(R"(
|
||||
# infinity
|
||||
sf1 = inf # positive infinity
|
||||
sf2 = +inf # positive infinity
|
||||
sf3 = -inf # negative infinity
|
||||
|
||||
# not a number
|
||||
sf4 = nan # actual sNaN/qNaN encoding is implementation specific
|
||||
sf5 = +nan # same as `nan`
|
||||
sf6 = -nan # valid, actual encoding is implementation specific
|
||||
)"sv),
|
||||
[](table&& tbl) noexcept
|
||||
{
|
||||
CHECK(tbl[S("sf1")] == std::numeric_limits<double>::infinity());
|
||||
CHECK(tbl[S("sf2")] == std::numeric_limits<double>::infinity());
|
||||
CHECK(tbl[S("sf3")] == -std::numeric_limits<double>::infinity());
|
||||
CHECK(std::isnan(tbl[S("sf4")].as<double>()->get()));
|
||||
CHECK(std::isnan(tbl[S("sf5")].as<double>()->get()));
|
||||
CHECK(std::isnan(tbl[S("sf6")].as<double>()->get()));
|
||||
}
|
||||
);
|
||||
}
|
151
tests/parsing_integers.cpp
Normal file
151
tests/parsing_integers.cpp
Normal file
@ -0,0 +1,151 @@
|
||||
#include "tests.h"
|
||||
|
||||
TEST_CASE("parsing integers - decimal")
|
||||
{
|
||||
parsing_should_succeed(S(R"(
|
||||
int1 = +99
|
||||
int2 = 42
|
||||
int3 = 0
|
||||
int4 = -17
|
||||
int5 = 1_000
|
||||
int6 = 5_349_221
|
||||
int7 = 1_2_3_4_5 # VALID but discouraged
|
||||
)"sv),
|
||||
[](table&& tbl) noexcept
|
||||
{
|
||||
CHECK(tbl[S("int1")] == 99);
|
||||
CHECK(tbl[S("int2")] == 42);
|
||||
CHECK(tbl[S("int3")] == 0);
|
||||
CHECK(tbl[S("int4")] == -17);
|
||||
CHECK(tbl[S("int5")] == 1000);
|
||||
CHECK(tbl[S("int6")] == 5349221);
|
||||
CHECK(tbl[S("int7")] == 12345);
|
||||
}
|
||||
);
|
||||
|
||||
// "Each underscore must be surrounded by at least one digit on each side."
|
||||
parsing_should_fail(S("int5 = 1__000"sv));
|
||||
parsing_should_fail(S("int5 = _1_000"sv));
|
||||
parsing_should_fail(S("int5 = 1_000_"sv));
|
||||
|
||||
// "Leading zeroes are not allowed."
|
||||
parsing_should_fail(S("int1 = +099"sv));
|
||||
parsing_should_fail(S("int2 = 042"sv));
|
||||
parsing_should_fail(S("int3 = 00"sv));
|
||||
parsing_should_fail(S("int4 = -017"sv));
|
||||
parsing_should_fail(S("int5 = 01_000"sv));
|
||||
parsing_should_fail(S("int6 = 05_349_221"sv));
|
||||
parsing_should_fail(S("int7 = 01_2_3_4_5"sv));
|
||||
|
||||
// "Integer values -0 and +0 are valid and identical to an unprefixed zero."
|
||||
parsing_should_succeed(
|
||||
S("zeroes = [-0, +0]"sv),
|
||||
[](table&& tbl) noexcept
|
||||
{
|
||||
CHECK(tbl[S("zeroes")][0] == 0);
|
||||
CHECK(tbl[S("zeroes")][1] == 0);
|
||||
}
|
||||
);
|
||||
|
||||
parsing_should_fail(S("val = +-1"sv));
|
||||
parsing_should_fail(S("val = -+1"sv));
|
||||
parsing_should_fail(S("val = ++1"sv));
|
||||
parsing_should_fail(S("val = --1"sv));
|
||||
parsing_should_fail(S("val = 1-"sv));
|
||||
parsing_should_fail(S("val = 1+"sv));
|
||||
parsing_should_fail(S("val = -1+"sv));
|
||||
parsing_should_fail(S("val = +1-"sv));
|
||||
|
||||
// value tests
|
||||
parse_expected_value( "1234"sv, 1234 );
|
||||
parse_expected_value( "+1234"sv, 1234 );
|
||||
parse_expected_value( "-1234"sv, -1234 );
|
||||
parse_expected_value( "0"sv, 0 );
|
||||
parse_expected_value( "1_2_3_4"sv, 1234 );
|
||||
parse_expected_value( "+1_2_3_4"sv, 1234 );
|
||||
parse_expected_value( "-1_2_3_4"sv, -1234 );
|
||||
parse_expected_value( "123_456_789"sv, 123456789 );
|
||||
}
|
||||
|
||||
TEST_CASE("parsing integers - hex, bin, oct")
|
||||
{
|
||||
parsing_should_succeed(S(R"(
|
||||
# hexadecimal with prefix `0x`
|
||||
hex1 = 0xDEADBEEF
|
||||
hex2 = 0xdeadbeef
|
||||
hex3 = 0xdead_beef
|
||||
|
||||
# octal with prefix `0o`
|
||||
oct1 = 0o01234567
|
||||
oct2 = 0o755 # useful for Unix file permissions
|
||||
|
||||
# binary with prefix `0b`
|
||||
bin1 = 0b11010110
|
||||
)"sv),
|
||||
[](table&& tbl) noexcept
|
||||
{
|
||||
CHECK(tbl[S("hex1")] == 0xDEADBEEF);
|
||||
CHECK(tbl[S("hex2")] == 0xDEADBEEF);
|
||||
CHECK(tbl[S("hex3")] == 0xDEADBEEF);
|
||||
CHECK(tbl[S("oct1")] == 01234567);
|
||||
CHECK(tbl[S("oct2")] == 0755);
|
||||
CHECK(tbl[S("bin1")] == 0b11010110);
|
||||
}
|
||||
);
|
||||
|
||||
// "leading + is not allowed"
|
||||
parsing_should_fail(S("hex1 = +0xDEADBEEF"sv));
|
||||
parsing_should_fail(S("hex2 = +0xdeadbeef"sv));
|
||||
parsing_should_fail(S("hex3 = +0xdead_beef"sv));
|
||||
parsing_should_fail(S("oct1 = +0o01234567"sv));
|
||||
parsing_should_fail(S("oct2 = +0o7550"sv));
|
||||
parsing_should_fail(S("int6 = +05_349_221"sv));
|
||||
parsing_should_fail(S("bin1 = +0b11010110"sv));
|
||||
|
||||
// "leading zeros are allowed (after the prefix)"
|
||||
parsing_should_succeed(S(R"(
|
||||
hex1 = 0x000DEADBEEF
|
||||
hex2 = 0x00000deadbeef
|
||||
hex3 = 0x0dead_beef
|
||||
oct1 = 0o0001234567
|
||||
oct2 = 0o000755
|
||||
bin1 = 0b0000011010110
|
||||
)"sv),
|
||||
[](table&& tbl) noexcept
|
||||
{
|
||||
CHECK(tbl[S("hex1")] == 0xDEADBEEF);
|
||||
CHECK(tbl[S("hex2")] == 0xDEADBEEF);
|
||||
CHECK(tbl[S("hex3")] == 0xDEADBEEF);
|
||||
CHECK(tbl[S("oct1")] == 01234567);
|
||||
CHECK(tbl[S("oct2")] == 0755);
|
||||
CHECK(tbl[S("bin1")] == 0b11010110);
|
||||
}
|
||||
);
|
||||
|
||||
// "64 bit (signed long) range expected (−9,223,372,036,854,775,808 to 9,223,372,036,854,775,807)."
|
||||
parsing_should_fail(S("val = −9223372036854775809"sv));
|
||||
parsing_should_fail(S("val = 9223372036854775808"sv));
|
||||
|
||||
// "***Non-negative*** integer values may also be expressed in hexadecimal, octal, or binary"
|
||||
parsing_should_fail(S("val = -0o1"sv));
|
||||
parsing_should_fail(S("val = -0b1"sv));
|
||||
parsing_should_fail(S("val = -0x1"sv));
|
||||
|
||||
// value tests
|
||||
parse_expected_value( "0xDEADBEEF"sv, 0xDEADBEEF );
|
||||
parse_expected_value( "0xdeadbeef"sv, 0xDEADBEEF );
|
||||
parse_expected_value( "0xDEADbeef"sv, 0xDEADBEEF );
|
||||
parse_expected_value( "0xDEAD_BEEF"sv, 0xDEADBEEF );
|
||||
parse_expected_value( "0xdead_beef"sv, 0xDEADBEEF );
|
||||
parse_expected_value( "0xdead_BEEF"sv, 0xDEADBEEF );
|
||||
parse_expected_value( "0xFF"sv, 0xFF );
|
||||
parse_expected_value( "0x00FF"sv, 0xFF );
|
||||
parse_expected_value( "0x0000FF"sv, 0xFF );
|
||||
parse_expected_value( "0o777"sv, 0777 );
|
||||
parse_expected_value( "0o7_7_7"sv, 0777 );
|
||||
parse_expected_value( "0o007"sv, 0007 );
|
||||
parse_expected_value( "0b10000"sv, 0b10000 );
|
||||
parse_expected_value( "0b010000"sv, 0b10000 );
|
||||
parse_expected_value( "0b01_00_00"sv, 0b10000 );
|
||||
parse_expected_value( "0b111111"sv, 0b111111 );
|
||||
}
|
132
tests/parsing_key_value_pairs.cpp
Normal file
132
tests/parsing_key_value_pairs.cpp
Normal file
@ -0,0 +1,132 @@
|
||||
#include "tests.h"
|
||||
|
||||
TEST_CASE("parsing key-value pairs")
|
||||
{
|
||||
parsing_should_succeed(S(R"(
|
||||
key = "value"
|
||||
bare_key = "value"
|
||||
bare-key = "value"
|
||||
1234 = "value"
|
||||
)"sv),
|
||||
[](table&& tbl) noexcept
|
||||
{
|
||||
CHECK(tbl.size() == 4);
|
||||
CHECK(tbl[S("key")] == S("value"sv));
|
||||
CHECK(tbl[S("bare_key")] == S("value"sv));
|
||||
CHECK(tbl[S("bare-key")] == S("value"sv));
|
||||
CHECK(tbl[S("1234")] == S("value"sv));
|
||||
}
|
||||
);
|
||||
|
||||
parsing_should_fail(S(R"(key = # INVALID)"sv));
|
||||
|
||||
parsing_should_succeed(S(R"(
|
||||
"127.0.0.1" = "value"
|
||||
"character encoding" = "value"
|
||||
"ʎǝʞ" = "value"
|
||||
'key2' = "value"
|
||||
'quoted "value"' = "value"
|
||||
)"sv),
|
||||
[](table&& tbl) noexcept
|
||||
{
|
||||
CHECK(tbl[S("127.0.0.1")] == S("value"sv));
|
||||
CHECK(tbl[S("character encoding")] == S("value"sv));
|
||||
CHECK(tbl[S("ʎǝʞ")] == S("value"sv));
|
||||
CHECK(tbl[S("key2")] == S("value"sv));
|
||||
CHECK(tbl[S("quoted \"value\"")] == S("value"sv));
|
||||
}
|
||||
);
|
||||
|
||||
parsing_should_fail(S(R"(= "no key name")"sv));
|
||||
|
||||
parsing_should_fail(S(R"(
|
||||
# DO NOT DO THIS
|
||||
name = "Tom"
|
||||
name = "Pradyun"
|
||||
)"sv)
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
TEST_CASE("parsing key-value pairs - dotted")
|
||||
{
|
||||
parsing_should_succeed(S(R"(
|
||||
name = "Orange"
|
||||
physical.color = "orange"
|
||||
physical.shape = "round"
|
||||
site."google.com" = true
|
||||
)"sv),
|
||||
[](table&& tbl) noexcept
|
||||
{
|
||||
CHECK(tbl.size() == 3);
|
||||
CHECK(tbl[S("name")] == S("Orange"sv));
|
||||
CHECK(tbl[S("physical")][S("color")] == S("orange"sv));
|
||||
CHECK(tbl[S("physical")][S("shape")] == S("round"sv));
|
||||
CHECK(tbl[S("site")][S("google.com")] == true);
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
parsing_should_succeed(S(R"(
|
||||
fruit.apple.smooth = true
|
||||
fruit.orange = 2
|
||||
)"sv),
|
||||
[](table&& tbl) noexcept
|
||||
{
|
||||
CHECK(tbl[S("fruit")][S("apple")][S("smooth")] == true);
|
||||
CHECK(tbl[S("fruit")][S("orange")] == 2);
|
||||
}
|
||||
);
|
||||
|
||||
parsing_should_fail(S(R"(
|
||||
# THIS IS INVALID
|
||||
fruit.apple = 1
|
||||
fruit.apple.smooth = true
|
||||
)"sv)
|
||||
);
|
||||
|
||||
parsing_should_succeed(S(R"(
|
||||
# VALID BUT DISCOURAGED
|
||||
|
||||
apple.type = "fruit"
|
||||
orange.type = "fruit"
|
||||
|
||||
apple.skin = "thin"
|
||||
orange.skin = "thick"
|
||||
|
||||
apple.color = "red"
|
||||
orange.color = "orange"
|
||||
)"sv),
|
||||
[](table&& tbl) noexcept
|
||||
{
|
||||
CHECK(tbl[S("apple")][S("type")] == S("fruit"sv));
|
||||
CHECK(tbl[S("apple")][S("skin")] == S("thin"sv));
|
||||
CHECK(tbl[S("apple")][S("color")] == S("red"sv));
|
||||
CHECK(tbl[S("orange")][S("type")] == S("fruit"sv));
|
||||
CHECK(tbl[S("orange")][S("skin")] == S("thick"sv));
|
||||
CHECK(tbl[S("orange")][S("color")] == S("orange"sv));
|
||||
}
|
||||
);
|
||||
|
||||
parsing_should_succeed(S(R"(
|
||||
# RECOMMENDED
|
||||
|
||||
apple.type = "fruit"
|
||||
apple.skin = "thin"
|
||||
apple.color = "red"
|
||||
|
||||
orange.type = "fruit"
|
||||
orange.skin = "thick"
|
||||
orange.color = "orange"
|
||||
)"sv),
|
||||
[](table&& tbl) noexcept
|
||||
{
|
||||
CHECK(tbl[S("apple")][S("type")] == S("fruit"sv));
|
||||
CHECK(tbl[S("apple")][S("skin")] == S("thin"sv));
|
||||
CHECK(tbl[S("apple")][S("color")] == S("red"sv));
|
||||
CHECK(tbl[S("orange")][S("type")] == S("fruit"sv));
|
||||
CHECK(tbl[S("orange")][S("skin")] == S("thick"sv));
|
||||
CHECK(tbl[S("orange")][S("color")] == S("orange"sv));
|
||||
}
|
||||
);
|
||||
}
|
88
tests/parsing_spec_example.cpp
Normal file
88
tests/parsing_spec_example.cpp
Normal file
@ -0,0 +1,88 @@
|
||||
#include "tests.h"
|
||||
|
||||
TOML_PUSH_WARNINGS
|
||||
TOML_DISABLE_FIELD_INIT_WARNING
|
||||
|
||||
TEST_CASE("parsing TOML spec example")
|
||||
{
|
||||
static constexpr auto toml_text =
|
||||
S(R"(# This is a TOML document.
|
||||
|
||||
title = "TOML Example"
|
||||
|
||||
[owner]
|
||||
name = "Tom Preston-Werner"
|
||||
dob = 1979-05-27T07:32:00-08:00 # First class dates
|
||||
|
||||
[database]
|
||||
server = "192.168.1.1"
|
||||
ports = [ 8001, 8001, 8002 ]
|
||||
connection_max = 5000
|
||||
enabled = true
|
||||
|
||||
[servers]
|
||||
|
||||
# Indentation (tabs and/or spaces) is allowed but not required
|
||||
[servers.alpha]
|
||||
ip = "10.0.0.1"
|
||||
dc = "eqdc10"
|
||||
|
||||
[servers.beta]
|
||||
ip = "10.0.0.2"
|
||||
dc = "eqdc10"
|
||||
|
||||
[clients]
|
||||
data = [ ["gamma", "delta"], [1, 2] ]
|
||||
|
||||
# Line breaks are OK when inside arrays
|
||||
hosts = [
|
||||
"alpha",
|
||||
"omega"
|
||||
])"sv);
|
||||
|
||||
parsing_should_succeed(toml_text, [](table&& tbl) noexcept
|
||||
{
|
||||
CHECK(tbl.size() == 5);
|
||||
|
||||
CHECK(tbl[S("title")] == S("TOML Example"sv));
|
||||
|
||||
CHECK(tbl[S("owner")]);
|
||||
CHECK(tbl[S("owner")].as<table>());
|
||||
CHECK(tbl[S("owner")][S("name")] == S("Tom Preston-Werner"sv));
|
||||
const auto dob = date_time{ { 1979, 5, 27 }, { 7, 32 }, time_offset{ -8 } };
|
||||
CHECK(tbl[S("owner")][S("dob")] == dob);
|
||||
|
||||
CHECK(tbl[S("database")].as<table>());
|
||||
CHECK(tbl[S("database")][S("server")] == S("192.168.1.1"sv));
|
||||
const auto ports = { 8001, 8001, 8002 };
|
||||
CHECK(tbl[S("database")][S("ports")] == ports);
|
||||
CHECK(tbl[S("database")][S("connection_max")] == 5000);
|
||||
CHECK(tbl[S("database")][S("enabled")] == true);
|
||||
|
||||
CHECK(tbl[S("servers")].as<table>());
|
||||
CHECK(tbl[S("servers")][S("alpha")].as<table>());
|
||||
CHECK(tbl[S("servers")][S("alpha")][S("ip")] == S("10.0.0.1"sv));
|
||||
CHECK(tbl[S("servers")][S("alpha")][S("dc")] == S("eqdc10"sv));
|
||||
CHECK(tbl[S("servers")][S("beta")].as<table>());
|
||||
CHECK(tbl[S("servers")][S("beta")][S("ip")] == S("10.0.0.2"sv));
|
||||
CHECK(tbl[S("servers")][S("beta")][S("dc")] == S("eqdc10"sv));
|
||||
|
||||
CHECK(tbl[S("clients")].as<table>());
|
||||
REQUIRE(tbl[S("clients")][S("data")].as<array>());
|
||||
CHECK(tbl[S("clients")][S("data")].as<array>()->size() == 2);
|
||||
REQUIRE(tbl[S("clients")][S("data")][0].as<array>());
|
||||
CHECK(tbl[S("clients")][S("data")][0].as<array>()->size() == 2);
|
||||
CHECK(tbl[S("clients")][S("data")][0][0] == S("gamma"sv));
|
||||
CHECK(tbl[S("clients")][S("data")][0][1] == S("delta"sv));
|
||||
REQUIRE(tbl[S("clients")][S("data")][1].as<array>());
|
||||
CHECK(tbl[S("clients")][S("data")][1].as<array>()->size() == 2);
|
||||
CHECK(tbl[S("clients")][S("data")][1][0] == 1);
|
||||
CHECK(tbl[S("clients")][S("data")][1][1] == 2);
|
||||
REQUIRE(tbl[S("clients")][S("hosts")].as<array>());
|
||||
CHECK(tbl[S("clients")][S("hosts")].as<array>()->size() == 2);
|
||||
CHECK(tbl[S("clients")][S("hosts")][0] == S("alpha"sv));
|
||||
CHECK(tbl[S("clients")][S("hosts")][1] == S("omega"sv));
|
||||
});
|
||||
}
|
||||
|
||||
TOML_POP_WARNINGS
|
120
tests/parsing_strings.cpp
Normal file
120
tests/parsing_strings.cpp
Normal file
@ -0,0 +1,120 @@
|
||||
#include "tests.h"
|
||||
|
||||
TEST_CASE("parsing strings")
|
||||
{
|
||||
parsing_should_succeed(S(R"(
|
||||
str = "I'm a string. \"You can quote me\". Name\tJos\u00E9\nLocation\tSF."
|
||||
|
||||
str1 = """
|
||||
Roses are red
|
||||
Violets are blue"""
|
||||
)"sv),
|
||||
[](table&& tbl) noexcept
|
||||
{
|
||||
CHECK(tbl[S("str")] == S("I'm a string. \"You can quote me\". Name\tJos\u00E9\nLocation\tSF."sv));
|
||||
CHECK(tbl[S("str1")] == S("Roses are red\nViolets are blue"sv));
|
||||
}
|
||||
);
|
||||
|
||||
parsing_should_succeed(S(R"(
|
||||
# The following strings are byte-for-byte equivalent:
|
||||
str1 = "The quick brown fox jumps over the lazy dog."
|
||||
|
||||
str2 = """
|
||||
The quick brown \
|
||||
|
||||
|
||||
fox jumps over \
|
||||
the lazy dog."""
|
||||
|
||||
str3 = """\
|
||||
The quick brown \
|
||||
fox jumps over \
|
||||
the lazy dog.\
|
||||
"""
|
||||
|
||||
str4 = """Here are two quotation marks: "". Simple enough."""
|
||||
# str5 = """Here are three quotation marks: """.""" # INVALID
|
||||
str5 = """Here are three quotation marks: ""\"."""
|
||||
str6 = """Here are fifteen quotation marks: ""\"""\"""\"""\"""\"."""
|
||||
|
||||
# "This," she said, "is just a pointless statement."
|
||||
str7 = """"This," she said, "is just a pointless statement.""""
|
||||
)"sv),
|
||||
[](table&& tbl) noexcept
|
||||
{
|
||||
static constexpr auto quick_brown_fox = S("The quick brown fox jumps over the lazy dog."sv);
|
||||
CHECK(tbl[S("str1")] == quick_brown_fox);
|
||||
CHECK(tbl[S("str2")] == quick_brown_fox);
|
||||
CHECK(tbl[S("str3")] == quick_brown_fox);
|
||||
CHECK(tbl[S("str4")] == S(R"(Here are two quotation marks: "". Simple enough.)"sv));
|
||||
CHECK(tbl[S("str5")] == S(R"(Here are three quotation marks: """.)"sv));
|
||||
CHECK(tbl[S("str6")] == S(R"(Here are fifteen quotation marks: """"""""""""""".)"sv));
|
||||
CHECK(tbl[S("str7")] == S(R"("This," she said, "is just a pointless statement.")"sv));
|
||||
}
|
||||
);
|
||||
|
||||
parsing_should_fail(S(R"(str5 = """Here are three quotation marks: """.""")"sv));
|
||||
|
||||
parsing_should_succeed(S(R"(
|
||||
# What you see is what you get.
|
||||
winpath = 'C:\Users\nodejs\templates'
|
||||
winpath2 = '\\ServerX\admin$\system32\'
|
||||
quoted = 'Tom "Dubs" Preston-Werner'
|
||||
regex = '<\i\c*\s*>'
|
||||
regex2 = '''I [dw]on't need \d{2} apples'''
|
||||
lines = '''
|
||||
The first newline is
|
||||
trimmed in raw strings.
|
||||
All other whitespace
|
||||
is preserved.
|
||||
'''
|
||||
)"sv),
|
||||
[](table&& tbl) noexcept
|
||||
{
|
||||
CHECK(tbl[S("winpath")] == S(R"(C:\Users\nodejs\templates)"sv));
|
||||
CHECK(tbl[S("winpath2")] == S(R"(\\ServerX\admin$\system32\)"sv));
|
||||
CHECK(tbl[S("quoted")] == S(R"(Tom "Dubs" Preston-Werner)"sv));
|
||||
CHECK(tbl[S("regex")] == S(R"(<\i\c*\s*>)"sv));
|
||||
CHECK(tbl[S("regex2")] == S(R"(I [dw]on't need \d{2} apples)"sv));
|
||||
CHECK(tbl[S("lines")] == S(R"(The first newline is
|
||||
trimmed in raw strings.
|
||||
All other whitespace
|
||||
is preserved.
|
||||
)"sv));
|
||||
}
|
||||
);
|
||||
|
||||
parsing_should_succeed(S(R"(
|
||||
quot15 = '''Here are fifteen quotation marks: """""""""""""""'''
|
||||
|
||||
# apos15 = '''Here are fifteen apostrophes: '''''''''''''''''' # INVALID
|
||||
apos15 = "Here are fifteen apostrophes: '''''''''''''''"
|
||||
|
||||
# 'That's still pointless', she said.
|
||||
str = ''''That's still pointless', she said.'''
|
||||
)"sv),
|
||||
[](table&& tbl) noexcept
|
||||
{
|
||||
CHECK(tbl[S("quot15")] == S(R"(Here are fifteen quotation marks: """"""""""""""")"sv));
|
||||
CHECK(tbl[S("apos15")] == S(R"(Here are fifteen apostrophes: ''''''''''''''')"sv));
|
||||
CHECK(tbl[S("str")] == S(R"('That's still pointless', she said.)"sv));
|
||||
}
|
||||
);
|
||||
|
||||
parsing_should_fail(S(R"(apos15 = '''Here are fifteen apostrophes: '''''''''''''''''' # INVALID)"sv));
|
||||
|
||||
//value tests
|
||||
parse_expected_value(
|
||||
R"("The quick brown fox jumps over the lazy dog")"sv,
|
||||
S("The quick brown fox jumps over the lazy dog"sv));
|
||||
parse_expected_value(
|
||||
R"('The quick brown fox jumps over the lazy dog')"sv,
|
||||
S("The quick brown fox jumps over the lazy dog"sv));
|
||||
parse_expected_value(
|
||||
R"("""The quick brown fox jumps over the lazy dog""")"sv,
|
||||
S("The quick brown fox jumps over the lazy dog"sv));
|
||||
parse_expected_value(
|
||||
R"('''The quick brown fox jumps over the lazy dog''')"sv,
|
||||
S("The quick brown fox jumps over the lazy dog"sv));
|
||||
}
|
420
tests/parsing_tables.cpp
Normal file
420
tests/parsing_tables.cpp
Normal file
@ -0,0 +1,420 @@
|
||||
#include "tests.h"
|
||||
|
||||
TEST_CASE("parsing tables")
|
||||
{
|
||||
parsing_should_succeed(S(R"(
|
||||
[table]
|
||||
|
||||
[table-1]
|
||||
key1 = "some string"
|
||||
key2 = 123
|
||||
|
||||
[table-2]
|
||||
key1 = "another string"
|
||||
key2 = 456
|
||||
|
||||
[dog."tater.man"]
|
||||
type.name = "pug"
|
||||
|
||||
[a.b.c] # this is best practice
|
||||
[ d.e.f ] # same as [d.e.f]
|
||||
[ g . h . i ] # same as [g.h.i]
|
||||
[ j . "ʞ" . 'l' ] # same as [j."ʞ".'l']
|
||||
|
||||
# [x] you
|
||||
# [x.y] don't
|
||||
# [x.y.z] need these
|
||||
[x.y.z.w] # for this to work
|
||||
|
||||
[x] # defining a super-table afterwards is ok
|
||||
|
||||
[fruit]
|
||||
apple.color = "red"
|
||||
apple.taste.sweet = true
|
||||
|
||||
[fruit.apple.texture] # you can add sub-tables
|
||||
smooth = true
|
||||
|
||||
)"sv),
|
||||
[](table&& tbl) noexcept
|
||||
{
|
||||
REQUIRE(tbl[S("table")].as<table>());
|
||||
CHECK(tbl[S("table")].as<table>()->size() == 0_sz);
|
||||
|
||||
REQUIRE(tbl[S("table-1")].as<table>());
|
||||
CHECK(tbl[S("table-1")].as<table>()->size() == 2_sz);
|
||||
CHECK(tbl[S("table-1")][S("key1")] == S("some string"sv));
|
||||
CHECK(tbl[S("table-1")][S("key2")] == 123);
|
||||
|
||||
REQUIRE(tbl[S("table-2")].as<table>());
|
||||
CHECK(tbl[S("table-2")].as<table>()->size() == 2_sz);
|
||||
CHECK(tbl[S("table-2")][S("key1")] == S("another string"sv));
|
||||
CHECK(tbl[S("table-2")][S("key2")] == 456);
|
||||
|
||||
REQUIRE(tbl[S("dog")].as<table>());
|
||||
CHECK(tbl[S("dog")].as<table>()->size() == 1_sz);
|
||||
|
||||
REQUIRE(tbl[S("dog")][S("tater.man")].as<table>());
|
||||
CHECK(tbl[S("dog")][S("tater.man")].as<table>()->size() == 1_sz);
|
||||
CHECK(tbl[S("dog")][S("tater.man")][S("type")][S("name")] == S("pug"sv));
|
||||
|
||||
CHECK(tbl[S("a")].as<table>());
|
||||
CHECK(tbl[S("a")][S("b")].as<table>());
|
||||
CHECK(tbl[S("a")][S("b")][S("c")].as<table>());
|
||||
|
||||
CHECK(tbl[S("d")].as<table>());
|
||||
CHECK(tbl[S("d")][S("e")].as<table>());
|
||||
CHECK(tbl[S("d")][S("e")][S("f")].as<table>());
|
||||
|
||||
CHECK(tbl[S("g")].as<table>());
|
||||
CHECK(tbl[S("g")][S("h")].as<table>());
|
||||
CHECK(tbl[S("g")][S("h")][S("i")].as<table>());
|
||||
|
||||
CHECK(tbl[S("j")].as<table>());
|
||||
CHECK(tbl[S("j")][S("ʞ")].as<table>());
|
||||
CHECK(tbl[S("j")][S("ʞ")][S("l")].as<table>());
|
||||
|
||||
REQUIRE(tbl[S("fruit")].as<table>());
|
||||
CHECK(tbl[S("fruit")][S("apple")][S("color")] == S("red"sv));
|
||||
CHECK(tbl[S("fruit")][S("apple")][S("taste")][S("sweet")] == true);
|
||||
CHECK(tbl[S("fruit")][S("apple")][S("texture")][S("smooth")] == true);
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
parsing_should_fail(S(R"(
|
||||
# DO NOT DO THIS
|
||||
|
||||
[fruit]
|
||||
apple = "red"
|
||||
|
||||
[fruit]
|
||||
orange = "orange"
|
||||
)"sv));
|
||||
|
||||
parsing_should_fail(S(R"(
|
||||
# DO NOT DO THIS EITHER
|
||||
|
||||
[fruit]
|
||||
apple = "red"
|
||||
|
||||
[fruit.apple]
|
||||
texture = "smooth"
|
||||
)"sv));
|
||||
|
||||
parsing_should_fail(S(R"(
|
||||
[fruit]
|
||||
apple.color = "red"
|
||||
apple.taste.sweet = true
|
||||
|
||||
[fruit.apple]
|
||||
)"sv));
|
||||
|
||||
parsing_should_fail(S(R"(
|
||||
[fruit]
|
||||
apple.color = "red"
|
||||
apple.taste.sweet = true
|
||||
|
||||
[fruit.apple.taste]
|
||||
)"sv));
|
||||
|
||||
parsing_should_succeed(S(R"(
|
||||
# VALID BUT DISCOURAGED
|
||||
[fruit.apple]
|
||||
[animal]
|
||||
[fruit.orange]
|
||||
)"sv),
|
||||
[](table&& tbl) noexcept
|
||||
{
|
||||
REQUIRE(tbl[S("animal")].as<table>());
|
||||
CHECK(tbl[S("animal")].as<table>()->size() == 0_sz);
|
||||
|
||||
REQUIRE(tbl[S("fruit")].as<table>());
|
||||
CHECK(tbl[S("fruit")].as<table>()->size() == 2_sz);
|
||||
|
||||
REQUIRE(tbl[S("fruit")][S("apple")].as<table>());
|
||||
REQUIRE(tbl[S("fruit")][S("orange")].as<table>());
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
parsing_should_succeed(S(R"(
|
||||
# RECOMMENDED
|
||||
[fruit.apple]
|
||||
[fruit.orange]
|
||||
[animal]
|
||||
)"sv),
|
||||
[](table&& tbl) noexcept
|
||||
{
|
||||
REQUIRE(tbl[S("animal")].as<table>());
|
||||
CHECK(tbl[S("animal")].as<table>()->size() == 0_sz);
|
||||
|
||||
REQUIRE(tbl[S("fruit")].as<table>());
|
||||
CHECK(tbl[S("fruit")].as<table>()->size() == 2_sz);
|
||||
|
||||
REQUIRE(tbl[S("fruit")][S("apple")].as<table>());
|
||||
REQUIRE(tbl[S("fruit")][S("orange")].as<table>());
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
TEST_CASE("parsing inline tables")
|
||||
{
|
||||
parsing_should_succeed(S(R"(
|
||||
name = { first = "Tom", last = "Preston-Werner" }
|
||||
point = { x = 1, y = 2 }
|
||||
animal = { type.name = "pug" }
|
||||
|
||||
[product]
|
||||
type = { name = "Nail" }
|
||||
)"sv),
|
||||
[](table&& tbl) noexcept
|
||||
{
|
||||
REQUIRE(tbl[S("name")].as<table>());
|
||||
CHECK(tbl[S("name")].as<table>()->size() == 2_sz);
|
||||
CHECK(tbl[S("name")][S("first")] == S("Tom"sv));
|
||||
CHECK(tbl[S("name")][S("last")] == S("Preston-Werner"sv));
|
||||
|
||||
REQUIRE(tbl[S("point")].as<table>());
|
||||
CHECK(tbl[S("point")].as<table>()->size() == 2_sz);
|
||||
CHECK(tbl[S("point")][S("x")] == 1);
|
||||
CHECK(tbl[S("point")][S("y")] == 2);
|
||||
|
||||
REQUIRE(tbl[S("animal")].as<table>());
|
||||
CHECK(tbl[S("animal")].as<table>()->size() == 1_sz);
|
||||
REQUIRE(tbl[S("animal")][S("type")].as<table>());
|
||||
CHECK(tbl[S("animal")][S("type")].as<table>()->size() == 1_sz);
|
||||
CHECK(tbl[S("animal")][S("type")][S("name")] == S("pug"sv));
|
||||
|
||||
REQUIRE(tbl[S("product")].as<table>());
|
||||
CHECK(tbl[S("product")].as<table>()->size() == 1_sz);
|
||||
REQUIRE(tbl[S("product")][S("type")].as<table>());
|
||||
CHECK(tbl[S("product")][S("type")].as<table>()->size() == 1_sz);
|
||||
CHECK(tbl[S("product")][S("type")][S("name")] == S("Nail"sv));
|
||||
}
|
||||
);
|
||||
|
||||
parsing_should_fail(S(R"(
|
||||
[product]
|
||||
type = { name = "Nail" }
|
||||
type.edible = false # INVALID
|
||||
)"sv));
|
||||
|
||||
parsing_should_fail(S(R"(
|
||||
[product]
|
||||
type.name = "Nail"
|
||||
type = { edible = false } # INVALID
|
||||
)"sv));
|
||||
|
||||
// "newlines are allowed between the curly braces [if] they are valid within a value."
|
||||
parsing_should_succeed(S(R"(
|
||||
test = { val1 = "foo", val2 = [
|
||||
1, 2,
|
||||
3
|
||||
], val3 = "bar" }
|
||||
)"sv),
|
||||
[](table&& tbl) noexcept
|
||||
{
|
||||
REQUIRE(tbl[S("test")].as<table>());
|
||||
CHECK(tbl[S("test")].as<table>()->size() == 3_sz);
|
||||
CHECK(tbl[S("test")][S("val1")] == S("foo"sv));
|
||||
REQUIRE(tbl[S("test")][S("val2")].as<array>());
|
||||
CHECK(tbl[S("test")][S("val2")].as<array>()->size() == 3_sz);
|
||||
CHECK(tbl[S("test")][S("val2")][0] == 1);
|
||||
CHECK(tbl[S("test")][S("val2")][1] == 2);
|
||||
CHECK(tbl[S("test")][S("val2")][2] == 3);
|
||||
CHECK(tbl[S("test")][S("val3")] == S("bar"sv));
|
||||
}
|
||||
);
|
||||
|
||||
#if TOML_LANG_HIGHER_THAN(0, 5, 0)
|
||||
{
|
||||
// toml/issues/516 - allow newlines and trailing commas in inline tables
|
||||
parsing_should_succeed(S(R"(
|
||||
name = {
|
||||
first = "Tom",
|
||||
last = "Preston-Werner",
|
||||
}
|
||||
)"sv),
|
||||
[](table&& tbl) noexcept
|
||||
{
|
||||
REQUIRE(tbl[S("name")].as<table>());
|
||||
CHECK(tbl[S("name")].as<table>()->size() == 2_sz);
|
||||
CHECK(tbl[S("name")][S("first")] == S("Tom"sv));
|
||||
CHECK(tbl[S("name")][S("last")] == S("Preston-Werner"sv));
|
||||
}
|
||||
);
|
||||
|
||||
}
|
||||
#else
|
||||
{
|
||||
// "A terminating comma (also called trailing comma) is not permitted after the last key/value pair in an inline table."
|
||||
parsing_should_fail(S(R"(name = { first = "Tom", last = "Preston-Werner", })"sv));
|
||||
|
||||
// "No newlines are allowed between the curly braces unless they are valid within a value."
|
||||
parsing_should_fail(S(R"(
|
||||
name = {
|
||||
first = "Tom",
|
||||
last = "Preston-Werner"
|
||||
}
|
||||
)"sv));
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
TEST_CASE("parsing arrays-of-tables")
|
||||
{
|
||||
parsing_should_succeed(S(R"(
|
||||
points = [ { x = 1, y = 2, z = 3 },
|
||||
{ x = 7, y = 8, z = 9 },
|
||||
{ x = 2, y = 4, z = 8 } ]
|
||||
|
||||
[[products]]
|
||||
name = "Hammer"
|
||||
sku = 738594937
|
||||
|
||||
[[products]]
|
||||
|
||||
[[products]]
|
||||
name = "Nail"
|
||||
sku = 284758393
|
||||
|
||||
color = "gray"
|
||||
|
||||
[[fruit]]
|
||||
name = "apple"
|
||||
|
||||
[fruit.physical] # subtable
|
||||
color = "red"
|
||||
shape = "round"
|
||||
|
||||
[[fruit.variety]] # nested array of tables
|
||||
name = "red delicious"
|
||||
|
||||
[[fruit.variety]]
|
||||
name = "granny smith"
|
||||
|
||||
[[fruit]]
|
||||
name = "banana"
|
||||
|
||||
[[fruit.variety]]
|
||||
name = "plantain"
|
||||
|
||||
)"sv),
|
||||
[](table&& tbl) noexcept
|
||||
{
|
||||
REQUIRE(tbl[S("points")].as<array>());
|
||||
CHECK(tbl[S("points")].as<array>()->size() == 3_sz);
|
||||
CHECK(tbl[S("points")].as<array>()->is_homogeneous());
|
||||
CHECK(tbl[S("points")].as<array>()->is_array_of_tables());
|
||||
CHECK(tbl[S("points")][0][S("x")] == 1);
|
||||
CHECK(tbl[S("points")][0][S("y")] == 2);
|
||||
CHECK(tbl[S("points")][0][S("z")] == 3);
|
||||
CHECK(tbl[S("points")][1][S("x")] == 7);
|
||||
CHECK(tbl[S("points")][1][S("y")] == 8);
|
||||
CHECK(tbl[S("points")][1][S("z")] == 9);
|
||||
CHECK(tbl[S("points")][2][S("x")] == 2);
|
||||
CHECK(tbl[S("points")][2][S("y")] == 4);
|
||||
CHECK(tbl[S("points")][2][S("z")] == 8);
|
||||
|
||||
REQUIRE(tbl[S("products")].as<array>());
|
||||
CHECK(tbl[S("products")].as<array>()->size() == 3_sz);
|
||||
CHECK(tbl[S("products")].as<array>()->is_homogeneous());
|
||||
CHECK(tbl[S("products")].as<array>()->is_array_of_tables());
|
||||
|
||||
REQUIRE(tbl[S("products")][0].as<table>());
|
||||
CHECK(tbl[S("products")][0].as<table>()->size() == 2_sz);
|
||||
CHECK(tbl[S("products")][0][S("name")] == S("Hammer"sv));
|
||||
CHECK(tbl[S("products")][0][S("sku")] == 738594937);
|
||||
|
||||
REQUIRE(tbl[S("products")][1].as<table>());
|
||||
CHECK(tbl[S("products")][1].as<table>()->size() == 0_sz);
|
||||
|
||||
REQUIRE(tbl[S("products")][2].as<table>());
|
||||
CHECK(tbl[S("products")][2].as<table>()->size() == 3_sz);
|
||||
CHECK(tbl[S("products")][2][S("name")] == S("Nail"sv));
|
||||
CHECK(tbl[S("products")][2][S("sku")] == 284758393);
|
||||
CHECK(tbl[S("products")][2][S("color")] == S("gray"sv));
|
||||
|
||||
|
||||
REQUIRE(tbl[S("fruit")].as<array>());
|
||||
CHECK(tbl[S("fruit")].as<array>()->size() == 2_sz);
|
||||
CHECK(tbl[S("fruit")].as<array>()->is_homogeneous());
|
||||
CHECK(tbl[S("fruit")].as<array>()->is_array_of_tables());
|
||||
|
||||
REQUIRE(tbl[S("fruit")][0].as<table>());
|
||||
CHECK(tbl[S("fruit")][0].as<table>()->size() == 3_sz);
|
||||
CHECK(tbl[S("fruit")][0][S("name")] == S("apple"sv));
|
||||
|
||||
REQUIRE(tbl[S("fruit")][0][S("physical")].as<table>());
|
||||
CHECK(tbl[S("fruit")][0][S("physical")].as<table>()->size() == 2_sz);
|
||||
CHECK(tbl[S("fruit")][0][S("physical")][S("color")] == S("red"sv));
|
||||
CHECK(tbl[S("fruit")][0][S("physical")][S("shape")] == S("round"sv));
|
||||
|
||||
REQUIRE(tbl[S("fruit")][0][S("variety")].as<array>());
|
||||
CHECK(tbl[S("fruit")][0][S("variety")].as<array>()->size() == 2_sz);
|
||||
CHECK(tbl[S("fruit")][0][S("variety")].as<array>()->is_homogeneous());
|
||||
CHECK(tbl[S("fruit")][0][S("variety")].as<array>()->is_array_of_tables());
|
||||
CHECK(tbl[S("fruit")][0][S("variety")][0][S("name")] == S("red delicious"sv));
|
||||
CHECK(tbl[S("fruit")][0][S("variety")][1][S("name")] == S("granny smith"sv));
|
||||
|
||||
REQUIRE(tbl[S("fruit")][1].as<table>());
|
||||
CHECK(tbl[S("fruit")][1].as<table>()->size() == 2_sz);
|
||||
CHECK(tbl[S("fruit")][1][S("name")] == S("banana"sv));
|
||||
|
||||
REQUIRE(tbl[S("fruit")][1][S("variety")].as<array>());
|
||||
CHECK(tbl[S("fruit")][1][S("variety")].as<array>()->size() == 1_sz);
|
||||
CHECK(tbl[S("fruit")][1][S("variety")].as<array>()->is_homogeneous());
|
||||
CHECK(tbl[S("fruit")][1][S("variety")].as<array>()->is_array_of_tables());
|
||||
CHECK(tbl[S("fruit")][1][S("variety")][0][S("name")] == S("plantain"sv));
|
||||
}
|
||||
);
|
||||
|
||||
parsing_should_fail(S(R"(
|
||||
# INVALID TOML DOC
|
||||
[fruit.physical] # subtable, but to which parent element should it belong?
|
||||
color = "red"
|
||||
shape = "round"
|
||||
|
||||
[[fruit]] # parser must throw an error upon discovering that "fruit" is
|
||||
# an array rather than a table
|
||||
name = "apple"
|
||||
)"sv));
|
||||
|
||||
parsing_should_fail(S(R"(
|
||||
# INVALID TOML DOC
|
||||
fruit = []
|
||||
|
||||
[[fruit]] # Not allowed
|
||||
)"sv));
|
||||
|
||||
parsing_should_fail(S(R"(
|
||||
# INVALID TOML DOC
|
||||
[[fruit]]
|
||||
name = "apple"
|
||||
|
||||
[[fruit.variety]]
|
||||
name = "red delicious"
|
||||
|
||||
# INVALID: This table conflicts with the previous array of tables
|
||||
[fruit.variety]
|
||||
name = "granny smith"
|
||||
)"sv));
|
||||
|
||||
parsing_should_fail(S(R"(
|
||||
# INVALID TOML DOC
|
||||
[[fruit]]
|
||||
name = "apple"
|
||||
|
||||
[fruit.physical]
|
||||
color = "red"
|
||||
shape = "round"
|
||||
|
||||
# INVALID: This array of tables conflicts with the previous table
|
||||
[[fruit.physical]]
|
||||
color = "green"
|
||||
)"sv));
|
||||
|
||||
}
|
3
tests/tests.cpp
Normal file
3
tests/tests.cpp
Normal file
@ -0,0 +1,3 @@
|
||||
#include "tests.h"
|
||||
|
||||
// this file is a no-op. it's only here for PCH on MSVC.
|
187
tests/tests.h
Normal file
187
tests/tests.h
Normal file
@ -0,0 +1,187 @@
|
||||
#pragma once
|
||||
#define TOML_UNDEF_MACROS 0
|
||||
#include "../include/toml++/toml.h"
|
||||
TOML_PUSH_WARNINGS
|
||||
TOML_DISABLE_ALL_WARNINGS
|
||||
#include "catch2.h"
|
||||
#include <sstream>
|
||||
using namespace toml;
|
||||
using namespace Catch::literals;
|
||||
TOML_POP_WARNINGS
|
||||
|
||||
#define S(str) TOML_STRING_PREFIX(str)
|
||||
|
||||
template <typename CHAR, typename FUNC>
|
||||
void parsing_should_succeed(std::basic_string_view<CHAR> toml_str, FUNC&& func, std::string_view source_path = {}) noexcept
|
||||
{
|
||||
constexpr auto validate_table = [](table&& tabl, std::string_view path) noexcept -> table&&
|
||||
{
|
||||
CHECK(tabl.region().begin != source_position{});
|
||||
CHECK(tabl.region().end != source_position{});
|
||||
if (path.empty())
|
||||
CHECK(tabl.region().path == nullptr);
|
||||
else
|
||||
{
|
||||
REQUIRE(tabl.region().path != nullptr);
|
||||
CHECK(*tabl.region().path == path);
|
||||
}
|
||||
|
||||
return std::move(tabl);
|
||||
};
|
||||
|
||||
#if TOML_EXCEPTIONS
|
||||
|
||||
try
|
||||
{
|
||||
std::forward<FUNC>(func)(validate_table(toml::parse(toml_str, source_path), source_path));
|
||||
{
|
||||
std::basic_stringstream<CHAR, std::char_traits<CHAR>, std::allocator<CHAR>> ss;
|
||||
ss.write(toml_str.data(), toml_str.length());
|
||||
std::forward<FUNC>(func)(validate_table(toml::parse(ss, source_path), source_path));
|
||||
}
|
||||
}
|
||||
catch (const toml::parse_error& err)
|
||||
{
|
||||
FAIL(
|
||||
"Parse error on line "sv << err.where().begin.line
|
||||
<< ", column "sv << err.where().begin.column
|
||||
<< ":\n"sv << err.what()
|
||||
);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
{
|
||||
toml::parse_result result = toml::parse(toml_str, source_path);
|
||||
if (result)
|
||||
std::forward<FUNC>(func)(validate_table(*std::move(result.root), source_path));
|
||||
else
|
||||
{
|
||||
FAIL(
|
||||
"Parse error on line "sv << result.error.where.begin.line
|
||||
<< ", column "sv << result.error.where.begin.column
|
||||
<< ":\n"sv << result.error.what
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
std::basic_stringstream<CHAR, std::char_traits<CHAR>, std::allocator<CHAR>> ss;
|
||||
ss.write(toml_str.data(), toml_str.length());
|
||||
toml::parse_result result = toml::parse(ss, source_path);
|
||||
if (result)
|
||||
std::forward<FUNC>(func)(validate_table(*std::move(result.root), source_path));
|
||||
else
|
||||
{
|
||||
FAIL(
|
||||
"Parse error on line "sv << result.error.where.begin.line
|
||||
<< ", column "sv << result.error.where.begin.column
|
||||
<< ":\n"sv << result.error.what
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
template <typename CHAR>
|
||||
void parsing_should_fail(std::basic_string_view<CHAR> toml_str) noexcept
|
||||
{
|
||||
#if TOML_EXCEPTIONS
|
||||
|
||||
static constexpr auto run_tests = [](auto&& fn) noexcept
|
||||
{
|
||||
try
|
||||
{
|
||||
fn();
|
||||
}
|
||||
catch (const toml::parse_error&)
|
||||
{
|
||||
SUCCEED("toml::parse_error thrown OK"sv);
|
||||
return true;
|
||||
}
|
||||
catch (const std::exception& exc)
|
||||
{
|
||||
FAIL("Expected parsing failure, saw exception: "sv << exc.what());
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
FAIL("Expected parsing failure, saw unspecified error"sv);
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
if (run_tests([=]() { (void)toml::parse(toml_str); }))
|
||||
run_tests([=]()
|
||||
{
|
||||
std::basic_stringstream<CHAR, std::char_traits<CHAR>, std::allocator<CHAR>> ss;
|
||||
ss.write(toml_str.data(), toml_str.length());
|
||||
(void)toml::parse(ss);
|
||||
});
|
||||
|
||||
#else
|
||||
|
||||
static constexpr auto run_tests = [](auto&& fn) noexcept
|
||||
{
|
||||
toml::parse_result result = fn();
|
||||
if (result)
|
||||
{
|
||||
FAIL("Expected parsing failure"sv);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
SUCCEED("toml::parse_error returned OK"sv);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
if (run_tests([=]() noexcept { return toml::parse(toml_str); }))
|
||||
run_tests([=]() noexcept
|
||||
{
|
||||
std::basic_stringstream<CHAR, std::char_traits<CHAR>, std::allocator<CHAR>> ss;
|
||||
ss.write(toml_str.data(), toml_str.length());
|
||||
return toml::parse(ss);
|
||||
});
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void parse_expected_value(std::string_view value_str, const T& expected) noexcept
|
||||
{
|
||||
std::string value;
|
||||
value.reserve(value_str.length() + 6_sz);
|
||||
value.append("val = "sv);
|
||||
value.append(value_str);
|
||||
|
||||
static constexpr auto is_val = [](char c) noexcept
|
||||
{
|
||||
if constexpr (std::is_same_v<string, value_of<T>>)
|
||||
return c == '"' || c == '\'';
|
||||
else
|
||||
return c != ' ' && c != '\t';
|
||||
};
|
||||
|
||||
size_t begin = 5_sz;
|
||||
for (; begin < value.length(); begin++)
|
||||
if (is_val(value[begin]))
|
||||
break;
|
||||
begin++;
|
||||
size_t end = value.length();
|
||||
for (; end --> 0_sz; )
|
||||
if (is_val(value[end]))
|
||||
break;
|
||||
end += 2_sz;
|
||||
|
||||
parsing_should_succeed(std::string_view{ value }, [&](table&& tbl) noexcept
|
||||
{
|
||||
CHECK(tbl.size() == 1);
|
||||
REQUIRE(tbl[S("val"sv)].as<value_of<T>>());
|
||||
CHECK(tbl[S("val"sv)].as<value_of<T>>()->get() == expected);
|
||||
CHECK(tbl[S("val"sv)].get()->region().begin == source_position{ 1, static_cast<uint32_t>(begin) });
|
||||
CHECK(tbl[S("val"sv)].get()->region().end == source_position{ 1, static_cast<uint32_t>(end) });
|
||||
});
|
||||
}
|
21
vs/.runsettings
Normal file
21
vs/.runsettings
Normal file
@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RunSettings>
|
||||
<!-- Configurations that affect the Test Framework -->
|
||||
<RunConfiguration>
|
||||
<MaxCpuCount>1</MaxCpuCount>
|
||||
<ResultsDirectory>..\build\TestResults</ResultsDirectory><!-- Path relative to solution directory -->
|
||||
<TestSessionTimeout>60000</TestSessionTimeout><!-- Milliseconds -->
|
||||
</RunConfiguration>
|
||||
|
||||
<!-- Adapter Specific sections -->
|
||||
<Catch2Adapter>
|
||||
<DebugBreak>on</DebugBreak><!-- Introduced in v1.1.0 -->
|
||||
<DiscoverCommandLine>--verbosity high --list-test-names-only</DiscoverCommandLine>
|
||||
<DiscoverTimeout>500</DiscoverTimeout><!-- Milliseconds -->
|
||||
<FilenameFilter>(?i:test)</FilenameFilter>
|
||||
<Logging>debug</Logging>
|
||||
<WorkingDirectoryRoot>Solution</WorkingDirectoryRoot>
|
||||
<WorkingDirectory>..\tests\</WorkingDirectory>
|
||||
</Catch2Adapter>
|
||||
|
||||
</RunSettings>
|
71
vs/example.vcxproj
Normal file
71
vs/example.vcxproj
Normal file
@ -0,0 +1,71 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>16.0</VCProjectVersion>
|
||||
<ProjectGuid>{259FCEE5-3442-4076-9547-2BA793ECA1CB}</ProjectGuid>
|
||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<Import Project="toml++.props" />
|
||||
<PropertyGroup>
|
||||
<LocalDebuggerWorkingDirectory>$(SolutionDir)..\examples\</LocalDebuggerWorkingDirectory>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\examples\example.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\examples\example.toml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Natvis Include="toml++.natvis" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
</Project>
|
96
vs/test_char.vcxproj
Normal file
96
vs/test_char.vcxproj
Normal file
@ -0,0 +1,96 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>16.0</VCProjectVersion>
|
||||
<ProjectGuid>{54532B93-A2F9-49AC-886E-767A6D78E2F2}</ProjectGuid>
|
||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<Import Project="toml++.props" />
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>..\tests;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>TOML_CHAR_8_STRINGS=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>tests.h</PrecompiledHeaderFile>
|
||||
<PreprocessorDefinitions Condition="'%(PrecompiledHeader)'=='Use'">USING_PCH=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<PropertyGroup>
|
||||
<LocalDebuggerWorkingDirectory>..\tests\</LocalDebuggerWorkingDirectory>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\tests\lifetimes.cpp" />
|
||||
<ClCompile Include="..\tests\main.cpp">
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\tests\parsing_arrays.cpp" />
|
||||
<ClCompile Include="..\tests\parsing_booleans.cpp" />
|
||||
<ClCompile Include="..\tests\parsing_comments.cpp" />
|
||||
<ClCompile Include="..\tests\parsing_dates_and_times.cpp" />
|
||||
<ClCompile Include="..\tests\parsing_floats.cpp" />
|
||||
<ClCompile Include="..\tests\parsing_integers.cpp" />
|
||||
<ClCompile Include="..\tests\parsing_key_value_pairs.cpp" />
|
||||
<ClCompile Include="..\tests\parsing_spec_example.cpp" />
|
||||
<ClCompile Include="..\tests\parsing_strings.cpp" />
|
||||
<ClCompile Include="..\tests\parsing_tables.cpp" />
|
||||
<ClCompile Include="..\tests\tests.cpp">
|
||||
<PrecompiledHeader>Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Natvis Include="toml++.natvis" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\tests\tests.h" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
</Project>
|
96
vs/test_char8.vcxproj
Normal file
96
vs/test_char8.vcxproj
Normal file
@ -0,0 +1,96 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>16.0</VCProjectVersion>
|
||||
<ProjectGuid>{3E4018CE-CCA2-48E6-B11E-732A1B59C672}</ProjectGuid>
|
||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<Import Project="toml++.props" />
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>..\tests;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>TOML_CHAR_8_STRINGS=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>tests.h</PrecompiledHeaderFile>
|
||||
<PreprocessorDefinitions Condition="'%(PrecompiledHeader)'=='Use'">USING_PCH=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<PropertyGroup>
|
||||
<LocalDebuggerWorkingDirectory>..\tests\</LocalDebuggerWorkingDirectory>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\tests\lifetimes.cpp" />
|
||||
<ClCompile Include="..\tests\main.cpp">
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\tests\parsing_arrays.cpp" />
|
||||
<ClCompile Include="..\tests\parsing_booleans.cpp" />
|
||||
<ClCompile Include="..\tests\parsing_comments.cpp" />
|
||||
<ClCompile Include="..\tests\parsing_dates_and_times.cpp" />
|
||||
<ClCompile Include="..\tests\parsing_floats.cpp" />
|
||||
<ClCompile Include="..\tests\parsing_integers.cpp" />
|
||||
<ClCompile Include="..\tests\parsing_key_value_pairs.cpp" />
|
||||
<ClCompile Include="..\tests\parsing_spec_example.cpp" />
|
||||
<ClCompile Include="..\tests\parsing_strings.cpp" />
|
||||
<ClCompile Include="..\tests\parsing_tables.cpp" />
|
||||
<ClCompile Include="..\tests\tests.cpp">
|
||||
<PrecompiledHeader>Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Natvis Include="toml++.natvis" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\tests\tests.h" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
</Project>
|
98
vs/test_char8_noexcept.vcxproj
Normal file
98
vs/test_char8_noexcept.vcxproj
Normal file
@ -0,0 +1,98 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>16.0</VCProjectVersion>
|
||||
<ProjectGuid>{F094F967-42B5-4AD7-AB44-EA044CD9837E}</ProjectGuid>
|
||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<Import Project="toml++.props" />
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>..\tests;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>TOML_CHAR_8_STRINGS=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>_HAS_EXCEPTIONS=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ExceptionHandling>false</ExceptionHandling>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>tests.h</PrecompiledHeaderFile>
|
||||
<PreprocessorDefinitions Condition="'%(PrecompiledHeader)'=='Use'">USING_PCH=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<PropertyGroup>
|
||||
<LocalDebuggerWorkingDirectory>..\tests\</LocalDebuggerWorkingDirectory>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\tests\lifetimes.cpp" />
|
||||
<ClCompile Include="..\tests\main.cpp">
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\tests\parsing_arrays.cpp" />
|
||||
<ClCompile Include="..\tests\parsing_booleans.cpp" />
|
||||
<ClCompile Include="..\tests\parsing_comments.cpp" />
|
||||
<ClCompile Include="..\tests\parsing_dates_and_times.cpp" />
|
||||
<ClCompile Include="..\tests\parsing_floats.cpp" />
|
||||
<ClCompile Include="..\tests\parsing_integers.cpp" />
|
||||
<ClCompile Include="..\tests\parsing_key_value_pairs.cpp" />
|
||||
<ClCompile Include="..\tests\parsing_spec_example.cpp" />
|
||||
<ClCompile Include="..\tests\parsing_strings.cpp" />
|
||||
<ClCompile Include="..\tests\parsing_tables.cpp" />
|
||||
<ClCompile Include="..\tests\tests.cpp">
|
||||
<PrecompiledHeader>Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Natvis Include="toml++.natvis" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\tests\tests.h" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
</Project>
|
98
vs/test_char_noexcept.vcxproj
Normal file
98
vs/test_char_noexcept.vcxproj
Normal file
@ -0,0 +1,98 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>16.0</VCProjectVersion>
|
||||
<ProjectGuid>{E888E99C-734D-44C4-B917-0AC8D3E2F48F}</ProjectGuid>
|
||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<Import Project="toml++.props" />
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>..\tests;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>TOML_CHAR_8_STRINGS=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>_HAS_EXCEPTIONS=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ExceptionHandling>false</ExceptionHandling>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>tests.h</PrecompiledHeaderFile>
|
||||
<PreprocessorDefinitions Condition="'%(PrecompiledHeader)'=='Use'">USING_PCH=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<PropertyGroup>
|
||||
<LocalDebuggerWorkingDirectory>..\tests\</LocalDebuggerWorkingDirectory>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\tests\lifetimes.cpp" />
|
||||
<ClCompile Include="..\tests\main.cpp">
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\tests\parsing_arrays.cpp" />
|
||||
<ClCompile Include="..\tests\parsing_booleans.cpp" />
|
||||
<ClCompile Include="..\tests\parsing_comments.cpp" />
|
||||
<ClCompile Include="..\tests\parsing_dates_and_times.cpp" />
|
||||
<ClCompile Include="..\tests\parsing_floats.cpp" />
|
||||
<ClCompile Include="..\tests\parsing_integers.cpp" />
|
||||
<ClCompile Include="..\tests\parsing_key_value_pairs.cpp" />
|
||||
<ClCompile Include="..\tests\parsing_spec_example.cpp" />
|
||||
<ClCompile Include="..\tests\parsing_strings.cpp" />
|
||||
<ClCompile Include="..\tests\parsing_tables.cpp" />
|
||||
<ClCompile Include="..\tests\tests.cpp">
|
||||
<PrecompiledHeader>Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Natvis Include="toml++.natvis" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\tests\tests.h" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
</Project>
|
97
vs/test_strict_char.vcxproj
Normal file
97
vs/test_strict_char.vcxproj
Normal file
@ -0,0 +1,97 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>16.0</VCProjectVersion>
|
||||
<ProjectGuid>{89FF67C6-94C0-4C46-8411-7549A36584FB}</ProjectGuid>
|
||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<Import Project="toml++.props" />
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>..\tests;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>TOML_CHAR_8_STRINGS=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>TOML_UNRELEASED_FEATURES=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>tests.h</PrecompiledHeaderFile>
|
||||
<PreprocessorDefinitions Condition="'%(PrecompiledHeader)'=='Use'">USING_PCH=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<PropertyGroup>
|
||||
<LocalDebuggerWorkingDirectory>..\tests\</LocalDebuggerWorkingDirectory>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\tests\lifetimes.cpp" />
|
||||
<ClCompile Include="..\tests\main.cpp">
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\tests\parsing_arrays.cpp" />
|
||||
<ClCompile Include="..\tests\parsing_booleans.cpp" />
|
||||
<ClCompile Include="..\tests\parsing_comments.cpp" />
|
||||
<ClCompile Include="..\tests\parsing_dates_and_times.cpp" />
|
||||
<ClCompile Include="..\tests\parsing_floats.cpp" />
|
||||
<ClCompile Include="..\tests\parsing_integers.cpp" />
|
||||
<ClCompile Include="..\tests\parsing_key_value_pairs.cpp" />
|
||||
<ClCompile Include="..\tests\parsing_spec_example.cpp" />
|
||||
<ClCompile Include="..\tests\parsing_strings.cpp" />
|
||||
<ClCompile Include="..\tests\parsing_tables.cpp" />
|
||||
<ClCompile Include="..\tests\tests.cpp">
|
||||
<PrecompiledHeader>Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Natvis Include="toml++.natvis" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\tests\tests.h" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
</Project>
|
97
vs/test_strict_char8.vcxproj
Normal file
97
vs/test_strict_char8.vcxproj
Normal file
@ -0,0 +1,97 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>16.0</VCProjectVersion>
|
||||
<ProjectGuid>{EAC419E9-0C72-4625-B2B9-E879F697021A}</ProjectGuid>
|
||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<Import Project="toml++.props" />
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>..\tests;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>TOML_CHAR_8_STRINGS=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>TOML_UNRELEASED_FEATURES=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>tests.h</PrecompiledHeaderFile>
|
||||
<PreprocessorDefinitions Condition="'%(PrecompiledHeader)'=='Use'">USING_PCH=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<PropertyGroup>
|
||||
<LocalDebuggerWorkingDirectory>..\tests\</LocalDebuggerWorkingDirectory>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\tests\lifetimes.cpp" />
|
||||
<ClCompile Include="..\tests\main.cpp">
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\tests\parsing_arrays.cpp" />
|
||||
<ClCompile Include="..\tests\parsing_booleans.cpp" />
|
||||
<ClCompile Include="..\tests\parsing_comments.cpp" />
|
||||
<ClCompile Include="..\tests\parsing_dates_and_times.cpp" />
|
||||
<ClCompile Include="..\tests\parsing_floats.cpp" />
|
||||
<ClCompile Include="..\tests\parsing_integers.cpp" />
|
||||
<ClCompile Include="..\tests\parsing_key_value_pairs.cpp" />
|
||||
<ClCompile Include="..\tests\parsing_spec_example.cpp" />
|
||||
<ClCompile Include="..\tests\parsing_strings.cpp" />
|
||||
<ClCompile Include="..\tests\parsing_tables.cpp" />
|
||||
<ClCompile Include="..\tests\tests.cpp">
|
||||
<PrecompiledHeader>Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Natvis Include="toml++.natvis" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\tests\tests.h" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
</Project>
|
99
vs/test_strict_char8_noexcept.vcxproj
Normal file
99
vs/test_strict_char8_noexcept.vcxproj
Normal file
@ -0,0 +1,99 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>16.0</VCProjectVersion>
|
||||
<ProjectGuid>{9ADB61D3-FDFA-4A9C-A34F-663007BB70F6}</ProjectGuid>
|
||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<Import Project="toml++.props" />
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>..\tests;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>TOML_CHAR_8_STRINGS=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>_HAS_EXCEPTIONS=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>TOML_UNRELEASED_FEATURES=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ExceptionHandling>false</ExceptionHandling>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>tests.h</PrecompiledHeaderFile>
|
||||
<PreprocessorDefinitions Condition="'%(PrecompiledHeader)'=='Use'">USING_PCH=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<PropertyGroup>
|
||||
<LocalDebuggerWorkingDirectory>..\tests\</LocalDebuggerWorkingDirectory>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\tests\lifetimes.cpp" />
|
||||
<ClCompile Include="..\tests\main.cpp">
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\tests\parsing_arrays.cpp" />
|
||||
<ClCompile Include="..\tests\parsing_booleans.cpp" />
|
||||
<ClCompile Include="..\tests\parsing_comments.cpp" />
|
||||
<ClCompile Include="..\tests\parsing_dates_and_times.cpp" />
|
||||
<ClCompile Include="..\tests\parsing_floats.cpp" />
|
||||
<ClCompile Include="..\tests\parsing_integers.cpp" />
|
||||
<ClCompile Include="..\tests\parsing_key_value_pairs.cpp" />
|
||||
<ClCompile Include="..\tests\parsing_spec_example.cpp" />
|
||||
<ClCompile Include="..\tests\parsing_strings.cpp" />
|
||||
<ClCompile Include="..\tests\parsing_tables.cpp" />
|
||||
<ClCompile Include="..\tests\tests.cpp">
|
||||
<PrecompiledHeader>Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Natvis Include="toml++.natvis" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\tests\tests.h" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
</Project>
|
99
vs/test_strict_char_noexcept.vcxproj
Normal file
99
vs/test_strict_char_noexcept.vcxproj
Normal file
@ -0,0 +1,99 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>16.0</VCProjectVersion>
|
||||
<ProjectGuid>{F05F8C1B-7E23-4147-901E-AD91092E5752}</ProjectGuid>
|
||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<Import Project="toml++.props" />
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>..\tests;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>TOML_CHAR_8_STRINGS=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>_HAS_EXCEPTIONS=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>TOML_UNRELEASED_FEATURES=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ExceptionHandling>false</ExceptionHandling>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>tests.h</PrecompiledHeaderFile>
|
||||
<PreprocessorDefinitions Condition="'%(PrecompiledHeader)'=='Use'">USING_PCH=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<PropertyGroup>
|
||||
<LocalDebuggerWorkingDirectory>..\tests\</LocalDebuggerWorkingDirectory>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\tests\lifetimes.cpp" />
|
||||
<ClCompile Include="..\tests\main.cpp">
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\tests\parsing_arrays.cpp" />
|
||||
<ClCompile Include="..\tests\parsing_booleans.cpp" />
|
||||
<ClCompile Include="..\tests\parsing_comments.cpp" />
|
||||
<ClCompile Include="..\tests\parsing_dates_and_times.cpp" />
|
||||
<ClCompile Include="..\tests\parsing_floats.cpp" />
|
||||
<ClCompile Include="..\tests\parsing_integers.cpp" />
|
||||
<ClCompile Include="..\tests\parsing_key_value_pairs.cpp" />
|
||||
<ClCompile Include="..\tests\parsing_spec_example.cpp" />
|
||||
<ClCompile Include="..\tests\parsing_strings.cpp" />
|
||||
<ClCompile Include="..\tests\parsing_tables.cpp" />
|
||||
<ClCompile Include="..\tests\tests.cpp">
|
||||
<PrecompiledHeader>Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Natvis Include="toml++.natvis" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\tests\tests.h" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
</Project>
|
53
vs/toml++.natvis
Normal file
53
vs/toml++.natvis
Normal file
@ -0,0 +1,53 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
|
||||
|
||||
<Type Name="::toml::date">
|
||||
<DisplayString>{(int)year}-{(int)month}-{(int)day}</DisplayString>
|
||||
<Expand>
|
||||
<Item Name="year" ExcludeView="simple">year</Item>
|
||||
<Item Name="month" ExcludeView="simple">month</Item>
|
||||
<Item Name="day" ExcludeView="simple">day</Item>
|
||||
</Expand>
|
||||
</Type>
|
||||
|
||||
<Type Name="::toml::time">
|
||||
<DisplayString>{(int)hour}:{(int)minute}:{second + (nanosecond / 1000000000.0)}</DisplayString>
|
||||
<Expand>
|
||||
<Item Name="hour" ExcludeView="simple">hour</Item>
|
||||
<Item Name="minute" ExcludeView="simple">minute</Item>
|
||||
<Item Name="second" ExcludeView="simple">second</Item>
|
||||
<Item Name="nanosecond" ExcludeView="simple">nanosecond</Item>
|
||||
</Expand>
|
||||
</Type>
|
||||
|
||||
<Type Name="::toml::time_offset">
|
||||
<DisplayString Condition="hours >= 0 && minutes >= 0">{(int)hours}:{(int)minutes}</DisplayString>
|
||||
<DisplayString Condition="hours < 0 && minutes >= 0">-{-((int)hours)}:{(int)minutes}</DisplayString>
|
||||
<DisplayString Condition="hours < 0 && minutes < 0">-{-((int)hours)}:{-((int)minutes)}</DisplayString>
|
||||
<DisplayString Condition="hours >= 0 && minutes < 0">-{(int)hours}:{-((int)minutes)}</DisplayString>
|
||||
<Expand>
|
||||
<Item Name="hours" ExcludeView="simple">hours</Item>
|
||||
<Item Name="minutes" ExcludeView="simple">minutes</Item>
|
||||
</Expand>
|
||||
</Type>
|
||||
|
||||
<Type Name="::toml::value<*>">
|
||||
<DisplayString>{{ {val_} }}</DisplayString>
|
||||
<Expand>
|
||||
<Item Name="val_" ExcludeView="simple">val_</Item>
|
||||
</Expand>
|
||||
</Type>
|
||||
|
||||
<Type Name="::toml::source_position">
|
||||
<DisplayString>line {line}, column {column}</DisplayString>
|
||||
<Expand>
|
||||
<Item Name="line" ExcludeView="simple">line</Item>
|
||||
<Item Name="column" ExcludeView="simple">column</Item>
|
||||
</Expand>
|
||||
</Type>
|
||||
|
||||
<Type Name="::toml::impl::utf8_codepoint">
|
||||
<DisplayString>{&bytes,s8} ({position})</DisplayString>
|
||||
</Type>
|
||||
|
||||
</AutoVisualizer>
|
105
vs/toml++.props
Normal file
105
vs/toml++.props
Normal file
@ -0,0 +1,105 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
|
||||
<PropertyGroup>
|
||||
<BuildInfoJobStartTicks>$([System.DateTime]::Now.Ticks)</BuildInfoJobStartTicks>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- :: defaults -->
|
||||
<PropertyGroup>
|
||||
<OutDir>$(SolutionDir)..\bin\$(PlatformTarget)-$(Configuration)\</OutDir>
|
||||
<IntDir>$(SolutionDir)..\build\$(TargetName)$(TargetExt)-$(PlatformTarget)-$(Configuration)-$(PlatformToolsetVersion)\</IntDir>
|
||||
<IncludePath>$(SolutionDir)..\include;$(IncludePath)</IncludePath>
|
||||
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||
<ControlFlowGuard>false</ControlFlowGuard>
|
||||
<RuntimeTypeInfo>false</RuntimeTypeInfo> <!-- /GR- -->
|
||||
<FloatingPointExceptions>false</FloatingPointExceptions> <!-- /fp:except- -->
|
||||
<ExceptionHandling>Sync</ExceptionHandling> <!-- /EHsc -->
|
||||
<ConformanceMode>true</ConformanceMode> <!-- /permissive- -->
|
||||
<StringPooling>true</StringPooling> <!-- /GF -->
|
||||
<OpenMPSupport>false</OpenMPSupport> <!-- /openmp- -->
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat> <!-- /Zi -->
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<LanguageStandard>stdcpplatest</LanguageStandard>
|
||||
<DiagnosticsFormat>Caret</DiagnosticsFormat>
|
||||
<AdditionalOptions>%(AdditionalOptions) /utf-8 /volatile:iso /Zc:__cplusplus /bigobj /Zc:inline /Zc:throwingNew</AdditionalOptions>
|
||||
<PreprocessorDefinitions>%(PreprocessorDefinitions);_CONSOLE</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>%(PreprocessorDefinitions);_ITERATOR_DEBUG_LEVEL=0</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>%(PreprocessorDefinitions);_ITERATOR_DEBUG_LEVEL=0</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>%(PreprocessorDefinitions);_WINSOCK_DEPRECATED_NO_WARNINGS</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>%(PreprocessorDefinitions);_SCL_SECURE_NO_WARNINGS</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>%(PreprocessorDefinitions);_MSC_TOOLSET_VER=$(PlatformToolsetVersion)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<TreatLinkerWarningAsErrors>true</TreatLinkerWarningAsErrors>
|
||||
<SubSystem>Console</SubSystem>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
|
||||
<!-- :: debug -->
|
||||
<PropertyGroup Condition="$(Configuration.ToLower().Contains('debug'))">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="$(Configuration.ToLower().Contains('debug'))">
|
||||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization> <!-- /Od -->
|
||||
<OmitFramePointers>false</OmitFramePointers> <!-- /Oy- -->
|
||||
<PreprocessorDefinitions>%(PreprocessorDefinitions);_DEBUG</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<OptimizeReferences>false</OptimizeReferences> <!-- /OPT:NOREF -->
|
||||
<EnableCOMDATFolding>false</EnableCOMDATFolding> <!-- /OPT:NOICF -->
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
|
||||
<!-- :: release -->
|
||||
<ItemDefinitionGroup Condition="!$(Configuration.ToLower().Contains('debug'))">
|
||||
<ClCompile>
|
||||
<Optimization>MaxSpeed</Optimization> <!-- /O2 -->
|
||||
<OmitFramePointers>true</OmitFramePointers> <!-- /Oy -->
|
||||
<PreprocessorDefinitions>%(PreprocessorDefinitions);NDEBUG</PreprocessorDefinitions>
|
||||
<InlineFunctionExpansion Condition="$(PlatformToolsetVersion) <= 141">AnySuitable</InlineFunctionExpansion> <!-- /Ob2 -->
|
||||
<AdditionalOptions Condition="$(PlatformToolsetVersion) >= 142">%(AdditionalOptions) /Ob3</AdditionalOptions> <!-- /Ob3 -->
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
|
||||
<!-- :: 32-bit -->
|
||||
<ItemDefinitionGroup Condition="'$(PlatformArchitecture)'=='32'">
|
||||
<ClCompile>
|
||||
<EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet> <!-- /arch:SSE2 -->
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
|
||||
<!-- :: 64-bit -->
|
||||
<ItemDefinitionGroup Condition="'$(PlatformArchitecture)'=='64'">
|
||||
<ClCompile>
|
||||
<EnableEnhancedInstructionSet>AdvancedVectorExtensions</EnableEnhancedInstructionSet> <!-- /arch:AVX -->
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
|
||||
<!-- Report how long each build took -->
|
||||
<Target Name="BuildInfoReportDuration" AfterTargets="Build">
|
||||
<Message
|
||||
Importance="high"
|
||||
Text="===== $(ProjectName) ($(Configuration) $(Platform)) built in $([System.TimeSpan]::FromTicks($([System.DateTime]::Now.Ticks))
|
||||
.Subtract($([System.TimeSpan]::FromTicks($(BuildInfoJobStartTicks))))
|
||||
.ToString()
|
||||
). ====="
|
||||
/>
|
||||
</Target>
|
||||
|
||||
</Project>
|
||||
|
133
vs/toml++.sln
Normal file
133
vs/toml++.sln
Normal file
@ -0,0 +1,133 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 16.0.29519.161
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "toml++", "toml++.vcxproj", "{0E287B5A-1168-43FD-B067-F6BE8E182A57}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "example", "example.vcxproj", "{259FCEE5-3442-4076-9547-2BA793ECA1CB}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{4E25CF88-D7D8-4A9C-A52E-0D78281E82EC}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_char", "test_char.vcxproj", "{54532B93-A2F9-49AC-886E-767A6D78E2F2}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_char_noexcept", "test_char_noexcept.vcxproj", "{E888E99C-734D-44C4-B917-0AC8D3E2F48F}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_char8", "test_char8.vcxproj", "{3E4018CE-CCA2-48E6-B11E-732A1B59C672}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_char8_noexcept", "test_char8_noexcept.vcxproj", "{F094F967-42B5-4AD7-AB44-EA044CD9837E}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_strict_char", "test_strict_char.vcxproj", "{89FF67C6-94C0-4C46-8411-7549A36584FB}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_strict_char_noexcept", "test_strict_char_noexcept.vcxproj", "{F05F8C1B-7E23-4147-901E-AD91092E5752}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_strict_char8", "test_strict_char8.vcxproj", "{EAC419E9-0C72-4625-B2B9-E879F697021A}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_strict_char8_noexcept", "test_strict_char8_noexcept.vcxproj", "{9ADB61D3-FDFA-4A9C-A34F-663007BB70F6}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|x64 = Debug|x64
|
||||
Debug|x86 = Debug|x86
|
||||
Release|x64 = Release|x64
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{0E287B5A-1168-43FD-B067-F6BE8E182A57}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{0E287B5A-1168-43FD-B067-F6BE8E182A57}.Debug|x64.Build.0 = Debug|x64
|
||||
{0E287B5A-1168-43FD-B067-F6BE8E182A57}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{0E287B5A-1168-43FD-B067-F6BE8E182A57}.Debug|x86.Build.0 = Debug|Win32
|
||||
{0E287B5A-1168-43FD-B067-F6BE8E182A57}.Release|x64.ActiveCfg = Release|x64
|
||||
{0E287B5A-1168-43FD-B067-F6BE8E182A57}.Release|x64.Build.0 = Release|x64
|
||||
{0E287B5A-1168-43FD-B067-F6BE8E182A57}.Release|x86.ActiveCfg = Release|Win32
|
||||
{0E287B5A-1168-43FD-B067-F6BE8E182A57}.Release|x86.Build.0 = Release|Win32
|
||||
{259FCEE5-3442-4076-9547-2BA793ECA1CB}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{259FCEE5-3442-4076-9547-2BA793ECA1CB}.Debug|x64.Build.0 = Debug|x64
|
||||
{259FCEE5-3442-4076-9547-2BA793ECA1CB}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{259FCEE5-3442-4076-9547-2BA793ECA1CB}.Debug|x86.Build.0 = Debug|Win32
|
||||
{259FCEE5-3442-4076-9547-2BA793ECA1CB}.Release|x64.ActiveCfg = Release|x64
|
||||
{259FCEE5-3442-4076-9547-2BA793ECA1CB}.Release|x64.Build.0 = Release|x64
|
||||
{259FCEE5-3442-4076-9547-2BA793ECA1CB}.Release|x86.ActiveCfg = Release|Win32
|
||||
{259FCEE5-3442-4076-9547-2BA793ECA1CB}.Release|x86.Build.0 = Release|Win32
|
||||
{54532B93-A2F9-49AC-886E-767A6D78E2F2}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{54532B93-A2F9-49AC-886E-767A6D78E2F2}.Debug|x64.Build.0 = Debug|x64
|
||||
{54532B93-A2F9-49AC-886E-767A6D78E2F2}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{54532B93-A2F9-49AC-886E-767A6D78E2F2}.Debug|x86.Build.0 = Debug|Win32
|
||||
{54532B93-A2F9-49AC-886E-767A6D78E2F2}.Release|x64.ActiveCfg = Release|x64
|
||||
{54532B93-A2F9-49AC-886E-767A6D78E2F2}.Release|x64.Build.0 = Release|x64
|
||||
{54532B93-A2F9-49AC-886E-767A6D78E2F2}.Release|x86.ActiveCfg = Release|Win32
|
||||
{54532B93-A2F9-49AC-886E-767A6D78E2F2}.Release|x86.Build.0 = Release|Win32
|
||||
{E888E99C-734D-44C4-B917-0AC8D3E2F48F}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{E888E99C-734D-44C4-B917-0AC8D3E2F48F}.Debug|x64.Build.0 = Debug|x64
|
||||
{E888E99C-734D-44C4-B917-0AC8D3E2F48F}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{E888E99C-734D-44C4-B917-0AC8D3E2F48F}.Debug|x86.Build.0 = Debug|Win32
|
||||
{E888E99C-734D-44C4-B917-0AC8D3E2F48F}.Release|x64.ActiveCfg = Release|x64
|
||||
{E888E99C-734D-44C4-B917-0AC8D3E2F48F}.Release|x64.Build.0 = Release|x64
|
||||
{E888E99C-734D-44C4-B917-0AC8D3E2F48F}.Release|x86.ActiveCfg = Release|Win32
|
||||
{E888E99C-734D-44C4-B917-0AC8D3E2F48F}.Release|x86.Build.0 = Release|Win32
|
||||
{3E4018CE-CCA2-48E6-B11E-732A1B59C672}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{3E4018CE-CCA2-48E6-B11E-732A1B59C672}.Debug|x64.Build.0 = Debug|x64
|
||||
{3E4018CE-CCA2-48E6-B11E-732A1B59C672}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{3E4018CE-CCA2-48E6-B11E-732A1B59C672}.Debug|x86.Build.0 = Debug|Win32
|
||||
{3E4018CE-CCA2-48E6-B11E-732A1B59C672}.Release|x64.ActiveCfg = Release|x64
|
||||
{3E4018CE-CCA2-48E6-B11E-732A1B59C672}.Release|x64.Build.0 = Release|x64
|
||||
{3E4018CE-CCA2-48E6-B11E-732A1B59C672}.Release|x86.ActiveCfg = Release|Win32
|
||||
{3E4018CE-CCA2-48E6-B11E-732A1B59C672}.Release|x86.Build.0 = Release|Win32
|
||||
{F094F967-42B5-4AD7-AB44-EA044CD9837E}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{F094F967-42B5-4AD7-AB44-EA044CD9837E}.Debug|x64.Build.0 = Debug|x64
|
||||
{F094F967-42B5-4AD7-AB44-EA044CD9837E}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{F094F967-42B5-4AD7-AB44-EA044CD9837E}.Debug|x86.Build.0 = Debug|Win32
|
||||
{F094F967-42B5-4AD7-AB44-EA044CD9837E}.Release|x64.ActiveCfg = Release|x64
|
||||
{F094F967-42B5-4AD7-AB44-EA044CD9837E}.Release|x64.Build.0 = Release|x64
|
||||
{F094F967-42B5-4AD7-AB44-EA044CD9837E}.Release|x86.ActiveCfg = Release|Win32
|
||||
{F094F967-42B5-4AD7-AB44-EA044CD9837E}.Release|x86.Build.0 = Release|Win32
|
||||
{89FF67C6-94C0-4C46-8411-7549A36584FB}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{89FF67C6-94C0-4C46-8411-7549A36584FB}.Debug|x64.Build.0 = Debug|x64
|
||||
{89FF67C6-94C0-4C46-8411-7549A36584FB}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{89FF67C6-94C0-4C46-8411-7549A36584FB}.Debug|x86.Build.0 = Debug|Win32
|
||||
{89FF67C6-94C0-4C46-8411-7549A36584FB}.Release|x64.ActiveCfg = Release|x64
|
||||
{89FF67C6-94C0-4C46-8411-7549A36584FB}.Release|x64.Build.0 = Release|x64
|
||||
{89FF67C6-94C0-4C46-8411-7549A36584FB}.Release|x86.ActiveCfg = Release|Win32
|
||||
{89FF67C6-94C0-4C46-8411-7549A36584FB}.Release|x86.Build.0 = Release|Win32
|
||||
{F05F8C1B-7E23-4147-901E-AD91092E5752}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{F05F8C1B-7E23-4147-901E-AD91092E5752}.Debug|x64.Build.0 = Debug|x64
|
||||
{F05F8C1B-7E23-4147-901E-AD91092E5752}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{F05F8C1B-7E23-4147-901E-AD91092E5752}.Debug|x86.Build.0 = Debug|Win32
|
||||
{F05F8C1B-7E23-4147-901E-AD91092E5752}.Release|x64.ActiveCfg = Release|x64
|
||||
{F05F8C1B-7E23-4147-901E-AD91092E5752}.Release|x64.Build.0 = Release|x64
|
||||
{F05F8C1B-7E23-4147-901E-AD91092E5752}.Release|x86.ActiveCfg = Release|Win32
|
||||
{F05F8C1B-7E23-4147-901E-AD91092E5752}.Release|x86.Build.0 = Release|Win32
|
||||
{EAC419E9-0C72-4625-B2B9-E879F697021A}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{EAC419E9-0C72-4625-B2B9-E879F697021A}.Debug|x64.Build.0 = Debug|x64
|
||||
{EAC419E9-0C72-4625-B2B9-E879F697021A}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{EAC419E9-0C72-4625-B2B9-E879F697021A}.Debug|x86.Build.0 = Debug|Win32
|
||||
{EAC419E9-0C72-4625-B2B9-E879F697021A}.Release|x64.ActiveCfg = Release|x64
|
||||
{EAC419E9-0C72-4625-B2B9-E879F697021A}.Release|x64.Build.0 = Release|x64
|
||||
{EAC419E9-0C72-4625-B2B9-E879F697021A}.Release|x86.ActiveCfg = Release|Win32
|
||||
{EAC419E9-0C72-4625-B2B9-E879F697021A}.Release|x86.Build.0 = Release|Win32
|
||||
{9ADB61D3-FDFA-4A9C-A34F-663007BB70F6}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{9ADB61D3-FDFA-4A9C-A34F-663007BB70F6}.Debug|x64.Build.0 = Debug|x64
|
||||
{9ADB61D3-FDFA-4A9C-A34F-663007BB70F6}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{9ADB61D3-FDFA-4A9C-A34F-663007BB70F6}.Debug|x86.Build.0 = Debug|Win32
|
||||
{9ADB61D3-FDFA-4A9C-A34F-663007BB70F6}.Release|x64.ActiveCfg = Release|x64
|
||||
{9ADB61D3-FDFA-4A9C-A34F-663007BB70F6}.Release|x64.Build.0 = Release|x64
|
||||
{9ADB61D3-FDFA-4A9C-A34F-663007BB70F6}.Release|x86.ActiveCfg = Release|Win32
|
||||
{9ADB61D3-FDFA-4A9C-A34F-663007BB70F6}.Release|x86.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(NestedProjects) = preSolution
|
||||
{54532B93-A2F9-49AC-886E-767A6D78E2F2} = {4E25CF88-D7D8-4A9C-A52E-0D78281E82EC}
|
||||
{E888E99C-734D-44C4-B917-0AC8D3E2F48F} = {4E25CF88-D7D8-4A9C-A52E-0D78281E82EC}
|
||||
{3E4018CE-CCA2-48E6-B11E-732A1B59C672} = {4E25CF88-D7D8-4A9C-A52E-0D78281E82EC}
|
||||
{F094F967-42B5-4AD7-AB44-EA044CD9837E} = {4E25CF88-D7D8-4A9C-A52E-0D78281E82EC}
|
||||
{89FF67C6-94C0-4C46-8411-7549A36584FB} = {4E25CF88-D7D8-4A9C-A52E-0D78281E82EC}
|
||||
{F05F8C1B-7E23-4147-901E-AD91092E5752} = {4E25CF88-D7D8-4A9C-A52E-0D78281E82EC}
|
||||
{EAC419E9-0C72-4625-B2B9-E879F697021A} = {4E25CF88-D7D8-4A9C-A52E-0D78281E82EC}
|
||||
{9ADB61D3-FDFA-4A9C-A34F-663007BB70F6} = {4E25CF88-D7D8-4A9C-A52E-0D78281E82EC}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {0926DDCC-88CD-4839-A82D-D9B99E02A0B1}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
78
vs/toml++.vcxproj
Normal file
78
vs/toml++.vcxproj
Normal file
@ -0,0 +1,78 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>16.0</VCProjectVersion>
|
||||
<ProjectGuid>{0E287B5A-1168-43FD-B067-F6BE8E182A57}</ProjectGuid>
|
||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<Import Project="$(ProjectDir)\toml++.props" />
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\include\toml++\toml.h" />
|
||||
<ClInclude Include="..\include\toml++\toml_array.h" />
|
||||
<ClInclude Include="..\include\toml++\toml_common.h" />
|
||||
<ClInclude Include="..\include\toml++\toml_formatter.h" />
|
||||
<ClInclude Include="..\include\toml++\toml_node.h" />
|
||||
<ClInclude Include="..\include\toml++\toml_parser.h" />
|
||||
<ClInclude Include="..\include\toml++\toml_node_view.h" />
|
||||
<ClInclude Include="..\include\toml++\toml_utf8_generated.h" />
|
||||
<ClInclude Include="..\include\toml++\toml_table.h" />
|
||||
<ClInclude Include="..\include\toml++\toml_utf8.h" />
|
||||
<ClInclude Include="..\include\toml++\toml_value.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\.editorconfig" />
|
||||
<None Include="..\python\generate_single_header.py" />
|
||||
<None Include="..\python\generate_unicode_functions.py" />
|
||||
<None Include="..\README.md" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
</Project>
|
22
vs/toml++.vcxproj.filters
Normal file
22
vs/toml++.vcxproj.filters
Normal file
@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\include\toml++\toml_array.h" />
|
||||
<ClInclude Include="..\include\toml++\toml_value.h" />
|
||||
<ClInclude Include="..\include\toml++\toml_parser.h" />
|
||||
<ClInclude Include="..\include\toml++\toml_table.h" />
|
||||
<ClInclude Include="..\include\toml++\toml_common.h" />
|
||||
<ClInclude Include="..\include\toml++\toml.h" />
|
||||
<ClInclude Include="..\include\toml++\toml_utf8.h" />
|
||||
<ClInclude Include="..\include\toml++\toml_node.h" />
|
||||
<ClInclude Include="..\include\toml++\toml_node_view.h" />
|
||||
<ClInclude Include="..\include\toml++\toml_utf8_generated.h" />
|
||||
<ClInclude Include="..\include\toml++\toml_formatter.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\.editorconfig" />
|
||||
<None Include="..\README.md" />
|
||||
<None Include="..\python\generate_single_header.py" />
|
||||
<None Include="..\python\generate_unicode_functions.py" />
|
||||
</ItemGroup>
|
||||
</Project>
|
Loading…
x
Reference in New Issue
Block a user