mirror of
https://github.com/jbeder/yaml-cpp.git
synced 2025-11-26 04:21:44 +00:00
Compare commits
352 Commits
release-0.
...
97498a7640
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
97498a7640 | ||
|
|
65c1c270db | ||
|
|
4fe2fb83fe | ||
|
|
aa8d4e4750 | ||
|
|
2f86d13775 | ||
|
|
c9371de783 | ||
|
|
28f93bdec6 | ||
|
|
39f737443b | ||
|
|
73ef0060aa | ||
|
|
7470c2d871 | ||
|
|
8a9a7b74ef | ||
|
|
d45c4fba3e | ||
|
|
61db89741d | ||
|
|
7def2046ff | ||
|
|
1da813f56a | ||
|
|
f878043f12 | ||
|
|
9ce5a25188 | ||
|
|
ebfbf27115 | ||
|
|
06ffaf3104 | ||
|
|
0b945415fd | ||
|
|
82f3c04081 | ||
|
|
d8de96524c | ||
|
|
5d9e4b6251 | ||
|
|
28c0a1bc25 | ||
|
|
72865f7d32 | ||
|
|
f4bca79dc4 | ||
|
|
d4e00bd473 | ||
|
|
bd070a7b76 | ||
|
|
3d2888cc8a | ||
|
|
c2bec4c755 | ||
|
|
29c59c01d4 | ||
|
|
bc67157109 | ||
|
|
da82fd982c | ||
|
|
1f2b841949 | ||
|
|
47cd2725d6 | ||
|
|
850ec4f39e | ||
|
|
84459a7f98 | ||
|
|
ee9c4d19be | ||
|
|
b38ac5b55f | ||
|
|
7b469b4220 | ||
|
|
8fbf344aee | ||
|
|
06c3d1db51 | ||
|
|
04dddd6999 | ||
|
|
1f5e971f77 | ||
|
|
b11eaf1631 | ||
|
|
9f7babc3ff | ||
|
|
b95aa146ec | ||
|
|
1d8ca1f35e | ||
|
|
76dc671573 | ||
|
|
5c1bbbd276 | ||
|
|
4afd53b0d3 | ||
|
|
96f5c887f3 | ||
|
|
c67d701ad8 | ||
|
|
9eb1142900 | ||
|
|
c28295bda4 | ||
|
|
94710bb221 | ||
|
|
c7639e81d5 | ||
|
|
f30582fb09 | ||
|
|
eaf7205372 | ||
|
|
1c5a38eef3 | ||
|
|
51adc5f739 | ||
|
|
30e6933279 | ||
|
|
db03655d58 | ||
|
|
145eec5f3e | ||
|
|
f791b955d8 | ||
|
|
4fc5ec36bc | ||
|
|
8106fcf1e5 | ||
|
|
c26e047223 | ||
|
|
ac144ed46c | ||
|
|
4c061a5058 | ||
|
|
37f1b8b8c9 | ||
|
|
d046eea331 | ||
|
|
9f31491b0f | ||
|
|
016b2e7769 | ||
|
|
2383e6d0f2 | ||
|
|
6262201182 | ||
|
|
fcbb8193b9 | ||
|
|
c268020048 | ||
|
|
f732014112 | ||
|
|
f6c8b17c3a | ||
|
|
35b4498026 | ||
|
|
b8882652fc | ||
|
|
0e6e28d1a3 | ||
|
|
74f63c1181 | ||
|
|
987a604256 | ||
|
|
55a8037daa | ||
|
|
3ff7ab07ac | ||
|
|
d7f672d141 | ||
|
|
bdc5582b35 | ||
|
|
1b50109f7b | ||
|
|
4ae4cb7309 | ||
|
|
97ebcf035a | ||
|
|
85ad599d79 | ||
|
|
c86a9e424c | ||
|
|
255bf1f9bc | ||
|
|
763b7d6c70 | ||
|
|
e87ed7e5b1 | ||
|
|
c73ee34704 | ||
|
|
190ad502b5 | ||
|
|
420c982310 | ||
|
|
13626af92a | ||
|
|
4c982d59dc | ||
|
|
7d06655611 | ||
|
|
0e6e98e8fb | ||
|
|
4aad2b1666 | ||
|
|
a6db7e32ac | ||
|
|
669af4eb55 | ||
|
|
edadfecdc6 | ||
|
|
26e3b70407 | ||
|
|
cdf89fa352 | ||
|
|
f8e1a7be3b | ||
|
|
bce601f2bf | ||
|
|
d8d9419092 | ||
|
|
974349d015 | ||
|
|
5057a53293 | ||
|
|
634578e477 | ||
|
|
2b65c65e1b | ||
|
|
328d2d85e8 | ||
|
|
4564d9a131 | ||
|
|
2f8997565b | ||
|
|
1713859b05 | ||
|
|
393a02a225 | ||
|
|
0733aeb451 | ||
|
|
0d9dbcfe8c | ||
|
|
da1c8d360e | ||
|
|
6308112e54 | ||
|
|
db6deedcd3 | ||
|
|
79aa6d53e5 | ||
|
|
ef0bba178d | ||
|
|
b591d8ae2a | ||
|
|
0579ae3d97 | ||
|
|
9ee3928754 | ||
|
|
a6bbe0e50a | ||
|
|
98acc5a887 | ||
|
|
1c9abc8fa4 | ||
|
|
11917babc7 | ||
|
|
c2793a36d5 | ||
|
|
bc9874c9ff | ||
|
|
06b99f53db | ||
|
|
c3df6d87d4 | ||
|
|
51ce663085 | ||
|
|
33315286ab | ||
|
|
4571e8177a | ||
|
|
c82d3129dd | ||
|
|
370aceeaf8 | ||
|
|
6d5cfab5fd | ||
|
|
026a53fbe1 | ||
|
|
1c2e767347 | ||
|
|
3f381f13a0 | ||
|
|
08aa252611 | ||
|
|
27d8a0e302 | ||
|
|
97d1ae547c | ||
|
|
5a9ab177ba | ||
|
|
72fe73a104 | ||
|
|
a7a7908dc5 | ||
|
|
0b0bf35c48 | ||
|
|
dbb385bdf5 | ||
|
|
b2cd008717 | ||
|
|
6387cbc0ca | ||
|
|
1bf9540a7d | ||
|
|
4c90f2962e | ||
|
|
4f6d0733c9 | ||
|
|
f05947ae59 | ||
|
|
66171449d4 | ||
|
|
33c9f6e062 | ||
|
|
7e4f290ef9 | ||
|
|
ae811c3d86 | ||
|
|
41001d1bf9 | ||
|
|
a808c1f44a | ||
|
|
4dbfeb0bbc | ||
|
|
33316d531b | ||
|
|
6701275f19 | ||
|
|
cb7bb9821d | ||
|
|
f05b2577ad | ||
|
|
d9c35b6079 | ||
|
|
4b98aedc16 | ||
|
|
a98b8af448 | ||
|
|
9fb5153487 | ||
|
|
513ee81fbf | ||
|
|
9f2781b527 | ||
|
|
7083db28b3 | ||
|
|
2f00649291 | ||
|
|
b35f2a86a6 | ||
|
|
99222fc938 | ||
|
|
4edff1fa5d | ||
|
|
70205f5d88 | ||
|
|
9b8f35093e | ||
|
|
1d8542ad32 | ||
|
|
6f7ead5171 | ||
|
|
cf93f4c57b | ||
|
|
26faac387c | ||
|
|
120863ba5a | ||
|
|
b2f89386d8 | ||
|
|
1bfbd2be4c | ||
|
|
de8253fcb0 | ||
|
|
29dcf92f87 | ||
|
|
ce056acab7 | ||
|
|
9ab22ef493 | ||
|
|
1928bca4a4 | ||
|
|
c9460110e0 | ||
|
|
3dca8668b1 | ||
|
|
587b24e2ee | ||
|
|
5b3e30bfe9 | ||
|
|
72f699f5ce | ||
|
|
a8ba6a8dca | ||
|
|
14c87258cd | ||
|
|
f531f8a8c3 | ||
|
|
52a1378e48 | ||
|
|
c9a0077024 | ||
|
|
b650bc8287 | ||
|
|
21d75fa4cd | ||
|
|
848091124d | ||
|
|
6e87b37034 | ||
|
|
0fddd1e5bd | ||
|
|
99d95d8edc | ||
|
|
a6ed66abca | ||
|
|
e6b3a92e67 | ||
|
|
47d32aadf0 | ||
|
|
9d7e556ed5 | ||
|
|
62ff351432 | ||
|
|
5e9cb0128d | ||
|
|
9a3624205e | ||
|
|
968e0c1f02 | ||
|
|
b218787b98 | ||
|
|
db0bda7087 | ||
|
|
6cdf363625 | ||
|
|
d638508d33 | ||
|
|
90350662c9 | ||
|
|
e0e01d53c2 | ||
|
|
0122697561 | ||
|
|
bd7f8c60c8 | ||
|
|
82e9571213 | ||
|
|
0d5c57150c | ||
|
|
eca9cfd648 | ||
|
|
a2a113c6ff | ||
|
|
283d06f9f7 | ||
|
|
b87c76a2ef | ||
|
|
abf941b20d | ||
|
|
b659858b19 | ||
|
|
2443da5224 | ||
|
|
54fc4dadbb | ||
|
|
774f25800e | ||
|
|
ca77ef716e | ||
|
|
ee99c4151c | ||
|
|
d0da14404e | ||
|
|
45d9035a33 | ||
|
|
b71e672caf | ||
|
|
5e79f5eed3 | ||
|
|
c90c08ccc9 | ||
|
|
3e33bb3166 | ||
|
|
1698b47b65 | ||
|
|
0f9a586ca1 | ||
|
|
4fb1c4b92b | ||
|
|
ab5f9259a4 | ||
|
|
124ae47600 | ||
|
|
f996468a6a | ||
|
|
562aefc114 | ||
|
|
5d5bb52ec2 | ||
|
|
f5d5604a2c | ||
|
|
aac4df342b | ||
|
|
4c9e3d87e1 | ||
|
|
cfb7606a84 | ||
|
|
86ae3a5aa7 | ||
|
|
752804372c | ||
|
|
3f33f337a7 | ||
|
|
5a519a4c6c | ||
|
|
58687ee7c4 | ||
|
|
dc9c750efd | ||
|
|
d96826f12b | ||
|
|
46dcdc3ea2 | ||
|
|
beb44b872c | ||
|
|
5e24f35816 | ||
|
|
e2818c423e | ||
|
|
efbfa1c7c7 | ||
|
|
11607eb5bf | ||
|
|
0fdb1b910c | ||
|
|
c5457e1c6a | ||
|
|
bedb28fdb4 | ||
|
|
86c69bb73c | ||
|
|
f82861001a | ||
|
|
3757b2023b | ||
|
|
147d909fe6 | ||
|
|
e3492bb3fa | ||
|
|
8ff7d76e19 | ||
|
|
2b58c9bc42 | ||
|
|
0f20ddcdcb | ||
|
|
d025040049 | ||
|
|
1f4b6d5c85 | ||
|
|
3d9ad75af7 | ||
|
|
380ecb404e | ||
|
|
994cf97b59 | ||
|
|
96598c5c25 | ||
|
|
b5b03bb9ad | ||
|
|
086fec5c35 | ||
|
|
85af926ddc | ||
|
|
519d33fea3 | ||
|
|
f0b15cd6a0 | ||
|
|
f74ae543b4 | ||
|
|
7c33b3cdab | ||
|
|
728e26e426 | ||
|
|
3392ab980e | ||
|
|
6c569e58b0 | ||
|
|
148da47114 | ||
|
|
a45a61742b | ||
|
|
6e79997bb2 | ||
|
|
f35f4a19fa | ||
|
|
7d2873ce9f | ||
|
|
091ddfa52d | ||
|
|
883a1e8540 | ||
|
|
0d810ad6d5 | ||
|
|
51b59d11ba | ||
|
|
bfb5703ce9 | ||
|
|
cc229e87b3 | ||
|
|
ca34a379c7 | ||
|
|
2a02cee1c8 | ||
|
|
2176fd994e | ||
|
|
0535811c18 | ||
|
|
c5f6482325 | ||
|
|
d155b0d0d2 | ||
|
|
52bcefa1f1 | ||
|
|
34bd1a7083 | ||
|
|
500db60f89 | ||
|
|
178c8d1f27 | ||
|
|
0a1352525a | ||
|
|
f327b565ba | ||
|
|
57805dfd6a | ||
|
|
005a6a19ee | ||
|
|
8c35a8ffab | ||
|
|
9e37409b4b | ||
|
|
a5b72f7ae6 | ||
|
|
dfbb388409 | ||
|
|
e92321aee5 | ||
|
|
24fa1b3380 | ||
|
|
4376ebacaa | ||
|
|
b57efe94e7 | ||
|
|
36fd93a8d5 | ||
|
|
97d56c3f36 | ||
|
|
320b02b14a | ||
|
|
03d6e7d672 | ||
|
|
b426fafff6 | ||
|
|
b0a4de3dd9 | ||
|
|
b43db54810 | ||
|
|
5c390e8d6c | ||
|
|
aa928b925b | ||
|
|
908d38ebef | ||
|
|
ec8aa4fa62 | ||
|
|
5de38a76b6 | ||
|
|
25f3935b7c | ||
|
|
4d44602a5d | ||
|
|
897cfd5b2e | ||
|
|
1a6cb7376a | ||
|
|
66acd0d54b |
1
.bazelignore
Normal file
1
.bazelignore
Normal file
@@ -0,0 +1 @@
|
|||||||
|
test/googletest-1.13.0
|
||||||
@@ -30,7 +30,7 @@ PenaltyReturnTypeOnItsOwnLine: 200
|
|||||||
PointerBindsToType: true
|
PointerBindsToType: true
|
||||||
SpacesBeforeTrailingComments: 2
|
SpacesBeforeTrailingComments: 2
|
||||||
Cpp11BracedListStyle: true
|
Cpp11BracedListStyle: true
|
||||||
Standard: Auto
|
Standard: Cpp11
|
||||||
IndentWidth: 2
|
IndentWidth: 2
|
||||||
TabWidth: 8
|
TabWidth: 8
|
||||||
UseTab: Never
|
UseTab: Never
|
||||||
|
|||||||
50
.codedocs
Normal file
50
.codedocs
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
# CodeDocs.xyz Configuration File
|
||||||
|
|
||||||
|
# Optional project name, if left empty the GitHub repository name will be used.
|
||||||
|
PROJECT_NAME =
|
||||||
|
|
||||||
|
# One or more directories and files that contain example code to be included.
|
||||||
|
EXAMPLE_PATH =
|
||||||
|
|
||||||
|
# One or more directories and files to exclude from documentation generation.
|
||||||
|
# Use relative paths with respect to the repository root directory.
|
||||||
|
EXCLUDE = test/googletest-1.13.0/
|
||||||
|
|
||||||
|
# One or more wildcard patterns to exclude files and directories from document
|
||||||
|
# generation.
|
||||||
|
EXCLUDE_PATTERNS =
|
||||||
|
|
||||||
|
# One or more symbols to exclude from document generation. Symbols can be
|
||||||
|
# namespaces, classes, or functions.
|
||||||
|
EXCLUDE_SYMBOLS =
|
||||||
|
|
||||||
|
# Override the default parser (language) used for each file extension.
|
||||||
|
EXTENSION_MAPPING =
|
||||||
|
|
||||||
|
# Set the wildcard patterns used to filter out the source-files.
|
||||||
|
# If left blank the default is:
|
||||||
|
# *.c, *.cc, *.cxx, *.cpp, *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl,
|
||||||
|
# *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php,
|
||||||
|
# *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown, *.md, *.mm, *.dox, *.py,
|
||||||
|
# *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf, *.qsf, *.as and *.js.
|
||||||
|
FILE_PATTERNS =
|
||||||
|
|
||||||
|
# Hide undocumented class members.
|
||||||
|
HIDE_UNDOC_MEMBERS =
|
||||||
|
|
||||||
|
# Hide undocumented classes.
|
||||||
|
HIDE_UNDOC_CLASSES =
|
||||||
|
|
||||||
|
# Specify a markdown page whose contents should be used as the main page
|
||||||
|
# (index.html). This will override a page marked as \mainpage. For example, a
|
||||||
|
# README.md file usually serves as a useful main page.
|
||||||
|
USE_MDFILE_AS_MAINPAGE = README.md
|
||||||
|
|
||||||
|
# Specify external repository to link documentation with.
|
||||||
|
# This is similar to Doxygen's TAGFILES option, but will automatically link to
|
||||||
|
# tags of other repositories already using CodeDocs. List each repository to
|
||||||
|
# link with by giving its location in the form of owner/repository.
|
||||||
|
# For example:
|
||||||
|
# TAGLINKS = doxygen/doxygen CodeDocs/osg
|
||||||
|
# Note: these repositories must already be built on CodeDocs.
|
||||||
|
TAGLINKS =
|
||||||
11
.github/dependabot.yml
vendored
Normal file
11
.github/dependabot.yml
vendored
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
version: 2
|
||||||
|
updates:
|
||||||
|
- package-ecosystem: "github-actions"
|
||||||
|
directory: "/"
|
||||||
|
schedule:
|
||||||
|
interval: "monthly"
|
||||||
|
groups:
|
||||||
|
github-actions:
|
||||||
|
patterns:
|
||||||
|
- "*"
|
||||||
|
|
||||||
141
.github/workflows/build.yml
vendored
Normal file
141
.github/workflows/build.yml
vendored
Normal file
@@ -0,0 +1,141 @@
|
|||||||
|
name: Github PR
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ master ]
|
||||||
|
pull_request:
|
||||||
|
branches: [ master ]
|
||||||
|
workflow_dispatch:
|
||||||
|
permissions: read-all
|
||||||
|
defaults:
|
||||||
|
run:
|
||||||
|
shell: bash
|
||||||
|
jobs:
|
||||||
|
cmake-build:
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
os: [ubuntu-latest, windows-latest, macos-latest]
|
||||||
|
cxx_standard: [11, 17, 20]
|
||||||
|
build: [static, shared]
|
||||||
|
googletest: [build, system]
|
||||||
|
generator: ["Default Generator", "MinGW Makefiles"]
|
||||||
|
exclude:
|
||||||
|
- os: ubuntu-latest
|
||||||
|
cxx_standard: 11
|
||||||
|
googletest: system
|
||||||
|
- os: macos-latest
|
||||||
|
build: shared
|
||||||
|
- os: macos-latest
|
||||||
|
generator: "MinGW Makefiles"
|
||||||
|
- os: ubuntu-latest
|
||||||
|
generator: "MinGW Makefiles"
|
||||||
|
- os: macos-latest
|
||||||
|
googletest: system
|
||||||
|
- os: windows-latest
|
||||||
|
googletest: system
|
||||||
|
env:
|
||||||
|
YAML_BUILD_SHARED_LIBS: ${{ matrix.build == 'shared' && 'ON' || 'OFF' }}
|
||||||
|
YAML_USE_SYSTEM_GTEST: ${{ matrix.googletest == 'system' && 'ON' || 'OFF' }}
|
||||||
|
CMAKE_GENERATOR: >-
|
||||||
|
${{format(matrix.generator != 'Default Generator' && '-G "{0}"' || '', matrix.generator)}}
|
||||||
|
CMAKE_INSTALL_PREFIX: "${{ github.workspace }}/install-prefix"
|
||||||
|
CMAKE_BUILD_TYPE: Debug
|
||||||
|
CMAKE_CXX_FLAGS_DEBUG: ${{ matrix.googletest == 'build' && '-g -D_GLIBCXX_DEBUG -D_GLIBCXX_DEBUG_PEDANTIC' || '-g' }}
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
steps:
|
||||||
|
|
||||||
|
- uses: awalsh128/cache-apt-pkgs-action@latest
|
||||||
|
if: matrix.os == 'ubuntu-latest'
|
||||||
|
with:
|
||||||
|
packages: googletest libgmock-dev libgtest-dev
|
||||||
|
version: 1.0
|
||||||
|
|
||||||
|
- uses: actions/checkout@v5
|
||||||
|
|
||||||
|
- name: Configure
|
||||||
|
run: |
|
||||||
|
cmake \
|
||||||
|
${{ env.CMAKE_GENERATOR }} \
|
||||||
|
-S "${{ github.workspace }}" \
|
||||||
|
-B build \
|
||||||
|
-D CMAKE_CXX_STANDARD=${{ matrix.cxx_standard }} \
|
||||||
|
-D CMAKE_INSTALL_PREFIX="${{ env.CMAKE_INSTALL_PREFIX }}" \
|
||||||
|
-D CMAKE_BUILD_TYPE=${{ env.CMAKE_BUILD_TYPE }} \
|
||||||
|
-D CMAKE_CXX_FLAGS_DEBUG="${{ env.CMAKE_CXX_FLAGS_DEBUG }}" \
|
||||||
|
-D YAML_BUILD_SHARED_LIBS=${{ env.YAML_BUILD_SHARED_LIBS }} \
|
||||||
|
-D YAML_USE_SYSTEM_GTEST=${{ env.YAML_USE_SYSTEM_GTEST }} \
|
||||||
|
-D YAML_CPP_BUILD_TESTS=ON
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
run: |
|
||||||
|
cmake \
|
||||||
|
--build build \
|
||||||
|
--config ${{ env.CMAKE_BUILD_TYPE }} \
|
||||||
|
--verbose \
|
||||||
|
--parallel
|
||||||
|
|
||||||
|
- name: Run Tests
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
ctest \
|
||||||
|
--test-dir build \
|
||||||
|
--build-config ${{ env.CMAKE_BUILD_TYPE }} \
|
||||||
|
--output-on-failure \
|
||||||
|
--verbose
|
||||||
|
|
||||||
|
- name: Install
|
||||||
|
run: cmake --install build --config ${{ env.CMAKE_BUILD_TYPE }}
|
||||||
|
|
||||||
|
- name: Configure CMake package test
|
||||||
|
run: |
|
||||||
|
cmake \
|
||||||
|
${{ env.CMAKE_GENERATOR }} \
|
||||||
|
-S "${{ github.workspace }}/test/cmake" \
|
||||||
|
-B consumer-build \
|
||||||
|
-D CMAKE_BUILD_TYPE=${{ env.CMAKE_BUILD_TYPE }} \
|
||||||
|
-D CMAKE_PREFIX_PATH="${{ env.CMAKE_INSTALL_PREFIX }}"
|
||||||
|
|
||||||
|
- name: Build CMake package test
|
||||||
|
run: |
|
||||||
|
cmake \
|
||||||
|
--build consumer-build \
|
||||||
|
--config ${{ env.CMAKE_BUILD_TYPE }} \
|
||||||
|
--verbose
|
||||||
|
|
||||||
|
bazel-build:
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
os: [ubuntu-latest, windows-latest, macos-latest]
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v5
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
run: |
|
||||||
|
cd "${{ github.workspace }}"
|
||||||
|
bazel build :all
|
||||||
|
|
||||||
|
- name: Test
|
||||||
|
run: |
|
||||||
|
cd "${{ github.workspace }}"
|
||||||
|
bazel test test
|
||||||
|
|
||||||
|
bzlmod-build:
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
os: [ubuntu-latest, windows-latest, macos-latest]
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v5
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
cd "${{ github.workspace }}"
|
||||||
|
bazel build --enable_bzlmod :all
|
||||||
|
|
||||||
|
- name: Test
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
cd "${{ github.workspace }}"
|
||||||
|
bazel test --enable_bzlmod test
|
||||||
19
.github/workflows/bzlmod-archive.yml
vendored
Normal file
19
.github/workflows/bzlmod-archive.yml
vendored
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
name: Bazel Release
|
||||||
|
|
||||||
|
on:
|
||||||
|
release:
|
||||||
|
types: [published]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
# A release archive is required for bzlmod
|
||||||
|
# See: https://blog.bazel.build/2023/02/15/github-archive-checksum.html
|
||||||
|
bazel-release-archive:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@ff7abcd0c3c05ccf6adc123a8cd1fd4fb30fb493 # v4.1.1
|
||||||
|
- run: git archive $GITHUB_REF -o "yaml-cpp-${GITHUB_REF:10}.tar.gz"
|
||||||
|
- run: gh release upload ${GITHUB_REF:10} "yaml-cpp-${GITHUB_REF:10}.tar.gz"
|
||||||
|
env:
|
||||||
|
GH_TOKEN: ${{ github.token }}
|
||||||
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
build/
|
||||||
|
/tags
|
||||||
|
/bazel-*
|
||||||
21
BUILD.bazel
Normal file
21
BUILD.bazel
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
yaml_cpp_defines = select({
|
||||||
|
# On Windows, ensure static linking is used.
|
||||||
|
"@platforms//os:windows": ["YAML_CPP_STATIC_DEFINE", "YAML_CPP_NO_CONTRIB"],
|
||||||
|
"//conditions:default": [],
|
||||||
|
})
|
||||||
|
|
||||||
|
cc_library(
|
||||||
|
name = "yaml-cpp_internal",
|
||||||
|
visibility = ["//:__subpackages__"],
|
||||||
|
strip_include_prefix = "src",
|
||||||
|
hdrs = glob(["src/**/*.h"]),
|
||||||
|
)
|
||||||
|
|
||||||
|
cc_library(
|
||||||
|
name = "yaml-cpp",
|
||||||
|
visibility = ["//visibility:public"],
|
||||||
|
includes = ["include"],
|
||||||
|
hdrs = glob(["include/**/*.h"]),
|
||||||
|
srcs = glob(["src/**/*.cpp", "src/**/*.h"]),
|
||||||
|
defines = yaml_cpp_defines,
|
||||||
|
)
|
||||||
487
CMakeLists.txt
487
CMakeLists.txt
@@ -1,340 +1,213 @@
|
|||||||
###
|
# 3.5 is actually available almost everywhere.
|
||||||
### CMake settings
|
# 3.30 as the upper policy limit avoids CMake deprecation warnings.
|
||||||
###
|
cmake_minimum_required(VERSION 3.5...3.30)
|
||||||
## Due to Mac OSX we need to keep compatibility with CMake 2.6
|
|
||||||
# see http://www.cmake.org/Wiki/CMake_Policies
|
# enable MSVC_RUNTIME_LIBRARY target property
|
||||||
cmake_minimum_required(VERSION 2.6)
|
# see https://cmake.org/cmake/help/latest/policy/CMP0091.html
|
||||||
# see http://www.cmake.org/cmake/help/cmake-2-8-docs.html#policy:CMP0012
|
if(POLICY CMP0091)
|
||||||
if(POLICY CMP0012)
|
cmake_policy(SET CMP0091 NEW)
|
||||||
cmake_policy(SET CMP0012 OLD)
|
|
||||||
endif()
|
|
||||||
# see http://www.cmake.org/cmake/help/cmake-2-8-docs.html#policy:CMP0015
|
|
||||||
if(POLICY CMP0015)
|
|
||||||
cmake_policy(SET CMP0015 OLD)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
project(YAML_CPP VERSION 0.8.0 LANGUAGES CXX)
|
||||||
|
|
||||||
|
set(YAML_CPP_MAIN_PROJECT OFF)
|
||||||
|
if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
|
||||||
|
set(YAML_CPP_MAIN_PROJECT ON)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
include(CMakePackageConfigHelpers)
|
||||||
|
include(CMakeDependentOption)
|
||||||
include(CheckCXXCompilerFlag)
|
include(CheckCXXCompilerFlag)
|
||||||
|
include(GNUInstallDirs)
|
||||||
|
include(CTest)
|
||||||
|
|
||||||
|
option(YAML_CPP_BUILD_CONTRIB "Enable yaml-cpp contrib in library" ON)
|
||||||
|
option(YAML_CPP_BUILD_TOOLS "Enable parse tools" ON)
|
||||||
|
option(YAML_BUILD_SHARED_LIBS "Build yaml-cpp shared library" ${BUILD_SHARED_LIBS})
|
||||||
|
option(YAML_CPP_INSTALL "Enable generation of yaml-cpp install targets" ${YAML_CPP_MAIN_PROJECT})
|
||||||
|
option(YAML_CPP_FORMAT_SOURCE "Format source" ${YAML_CPP_MAIN_PROJECT})
|
||||||
|
option(YAML_CPP_DISABLE_UNINSTALL "Disable uninstallation of yaml-cpp" OFF)
|
||||||
|
option(YAML_USE_SYSTEM_GTEST "Use system googletest if found" OFF)
|
||||||
|
option(YAML_ENABLE_PIC "Use Position-Independent Code " ON)
|
||||||
|
|
||||||
###
|
cmake_dependent_option(YAML_CPP_BUILD_TESTS
|
||||||
### Project settings
|
"Enable yaml-cpp tests" OFF
|
||||||
###
|
"BUILD_TESTING;YAML_CPP_MAIN_PROJECT" OFF)
|
||||||
project(YAML_CPP)
|
cmake_dependent_option(YAML_MSVC_SHARED_RT
|
||||||
|
"MSVC: Build yaml-cpp with shared runtime libs (/MD)" ON
|
||||||
|
"CMAKE_SYSTEM_NAME MATCHES Windows" OFF)
|
||||||
|
set(YAML_CPP_INSTALL_CMAKEDIR "${CMAKE_INSTALL_LIBDIR}/cmake/yaml-cpp"
|
||||||
|
CACHE STRING "Path to install the CMake package to")
|
||||||
|
|
||||||
|
if (YAML_CPP_FORMAT_SOURCE)
|
||||||
|
find_program(YAML_CPP_CLANG_FORMAT_EXE NAMES clang-format)
|
||||||
|
endif()
|
||||||
|
|
||||||
set(YAML_CPP_VERSION_MAJOR "0")
|
if (YAML_BUILD_SHARED_LIBS)
|
||||||
set(YAML_CPP_VERSION_MINOR "5")
|
set(yaml-cpp-type SHARED)
|
||||||
set(YAML_CPP_VERSION_PATCH "2")
|
set(yaml-cpp-label-postfix "shared")
|
||||||
set(YAML_CPP_VERSION "${YAML_CPP_VERSION_MAJOR}.${YAML_CPP_VERSION_MINOR}.${YAML_CPP_VERSION_PATCH}")
|
|
||||||
|
|
||||||
enable_testing()
|
|
||||||
|
|
||||||
|
|
||||||
###
|
|
||||||
### Project options
|
|
||||||
###
|
|
||||||
## Project stuff
|
|
||||||
option(YAML_CPP_BUILD_TOOLS "Enable testing and parse tools" ON)
|
|
||||||
option(YAML_CPP_BUILD_CONTRIB "Enable contrib stuff in library" ON)
|
|
||||||
|
|
||||||
## Build options
|
|
||||||
# --> General
|
|
||||||
# see http://www.cmake.org/cmake/help/cmake2.6docs.html#variable:BUILD_SHARED_LIBS
|
|
||||||
# http://www.cmake.org/cmake/help/cmake2.6docs.html#command:add_library
|
|
||||||
option(BUILD_SHARED_LIBS "Build Shared Libraries" OFF)
|
|
||||||
|
|
||||||
# --> Apple
|
|
||||||
option(APPLE_UNIVERSAL_BIN "Apple: Build universal binary" OFF)
|
|
||||||
|
|
||||||
# --> Microsoft Visual C++
|
|
||||||
# see http://msdn.microsoft.com/en-us/library/aa278396(v=VS.60).aspx
|
|
||||||
# http://msdn.microsoft.com/en-us/library/2kzt1wy3(v=VS.71).aspx
|
|
||||||
option(MSVC_SHARED_RT "MSVC: Build with shared runtime libs (/MD)" ON)
|
|
||||||
option(MSVC_STHREADED_RT "MSVC: Build with single-threaded static runtime libs (/ML until VS .NET 2003)" OFF)
|
|
||||||
|
|
||||||
###
|
|
||||||
### Sources, headers, directories and libs
|
|
||||||
###
|
|
||||||
|
|
||||||
# From http://www.cmake.org/pipermail/cmake/2010-March/035992.html:
|
|
||||||
# function to collect all the sources from sub-directories
|
|
||||||
# into a single list
|
|
||||||
function(add_sources)
|
|
||||||
get_property(is_defined GLOBAL PROPERTY SRCS_LIST DEFINED)
|
|
||||||
if(NOT is_defined)
|
|
||||||
define_property(GLOBAL PROPERTY SRCS_LIST
|
|
||||||
BRIEF_DOCS "List of source files"
|
|
||||||
FULL_DOCS "List of all source files in the entire project")
|
|
||||||
endif()
|
|
||||||
# make absolute paths
|
|
||||||
set(SRCS)
|
|
||||||
foreach(s IN LISTS ARGN)
|
|
||||||
if(NOT IS_ABSOLUTE "${s}")
|
|
||||||
get_filename_component(s "${s}" ABSOLUTE)
|
|
||||||
endif()
|
|
||||||
list(APPEND SRCS "${s}")
|
|
||||||
endforeach()
|
|
||||||
# append to global list
|
|
||||||
set_property(GLOBAL APPEND PROPERTY SRCS_LIST "${SRCS}")
|
|
||||||
endfunction(add_sources)
|
|
||||||
|
|
||||||
set(header_directory "include/yaml-cpp/")
|
|
||||||
|
|
||||||
file(GLOB sources "src/[a-zA-Z]*.cpp")
|
|
||||||
file(GLOB_RECURSE public_headers "include/yaml-cpp/[a-zA-Z]*.h")
|
|
||||||
file(GLOB private_headers "src/[a-zA-Z]*.h")
|
|
||||||
|
|
||||||
if(YAML_CPP_BUILD_CONTRIB)
|
|
||||||
file(GLOB contrib_sources "src/contrib/[a-zA-Z]*.cpp")
|
|
||||||
file(GLOB contrib_public_headers "include/yaml-cpp/contrib/[a-zA-Z]*.h")
|
|
||||||
file(GLOB contrib_private_headers "src/contrib/[a-zA-Z]*.h")
|
|
||||||
else()
|
else()
|
||||||
add_definitions(-DYAML_CPP_NO_CONTRIB)
|
set(yaml-cpp-type STATIC)
|
||||||
|
set(yaml-cpp-label-postfix "static")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(library_sources
|
set(build-shared $<BOOL:${YAML_BUILD_SHARED_LIBS}>)
|
||||||
${sources}
|
set(build-windows-dll $<AND:$<BOOL:${CMAKE_HOST_WIN32}>,${build-shared}>)
|
||||||
${public_headers}
|
set(not-msvc $<NOT:$<CXX_COMPILER_ID:MSVC>>)
|
||||||
${private_headers}
|
set(msvc-shared_rt $<BOOL:${YAML_MSVC_SHARED_RT}>)
|
||||||
${contrib_sources}
|
|
||||||
${contrib_public_headers}
|
|
||||||
${contrib_private_headers}
|
|
||||||
)
|
|
||||||
add_sources(${library_sources})
|
|
||||||
|
|
||||||
if(VERBOSE)
|
if (NOT DEFINED CMAKE_MSVC_RUNTIME_LIBRARY)
|
||||||
message(STATUS "sources: ${sources}")
|
set(CMAKE_MSVC_RUNTIME_LIBRARY
|
||||||
message(STATUS "public_headers: ${public_headers}")
|
MultiThreaded$<$<CONFIG:Debug>:Debug>$<${msvc-shared_rt}:DLL>)
|
||||||
message(STATUS "private_headers: ${private_headers}")
|
|
||||||
message(STATUS "contrib_sources: ${contrib_sources}")
|
|
||||||
message(STATUS "contrib_public_headers: ${contrib_public_headers}")
|
|
||||||
message(STATUS "contrib_private_headers: ${contrib_private_headers}")
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
include_directories(${YAML_CPP_SOURCE_DIR}/src)
|
set(contrib-pattern "src/contrib/*.cpp")
|
||||||
include_directories(${YAML_CPP_SOURCE_DIR}/include)
|
set(src-pattern "src/*.cpp")
|
||||||
|
if (CMAKE_VERSION VERSION_GREATER 3.12)
|
||||||
find_package(Boost REQUIRED)
|
list(INSERT contrib-pattern 0 CONFIGURE_DEPENDS)
|
||||||
include_directories(${Boost_INCLUDE_DIRS})
|
list(INSERT src-pattern 0 CONFIGURE_DEPENDS)
|
||||||
|
|
||||||
|
|
||||||
###
|
|
||||||
### General compilation settings
|
|
||||||
###
|
|
||||||
set(yaml_c_flags ${CMAKE_C_FLAGS})
|
|
||||||
set(yaml_cxx_flags ${CMAKE_CXX_FLAGS})
|
|
||||||
|
|
||||||
if(BUILD_SHARED_LIBS)
|
|
||||||
set(LABEL_SUFFIX "shared")
|
|
||||||
else()
|
|
||||||
set(LABEL_SUFFIX "static")
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(APPLE)
|
file(GLOB yaml-cpp-contrib-sources ${contrib-pattern})
|
||||||
if(APPLE_UNIVERSAL_BIN)
|
file(GLOB yaml-cpp-sources ${src-pattern})
|
||||||
set(CMAKE_OSX_ARCHITECTURES ppc;i386)
|
|
||||||
endif()
|
set(msvc-rt $<TARGET_PROPERTY:MSVC_RUNTIME_LIBRARY>)
|
||||||
|
|
||||||
|
set(msvc-rt-mtd-static $<STREQUAL:${msvc-rt},MultiThreadedDebug>)
|
||||||
|
set(msvc-rt-mt-static $<STREQUAL:${msvc-rt},MultiThreaded>)
|
||||||
|
|
||||||
|
set(msvc-rt-mtd-dll $<STREQUAL:${msvc-rt},MultiThreadedDebugDLL>)
|
||||||
|
set(msvc-rt-mt-dll $<STREQUAL:${msvc-rt},MultiThreadedDLL>)
|
||||||
|
|
||||||
|
set(backport-msvc-runtime $<VERSION_LESS:${CMAKE_VERSION},3.15>)
|
||||||
|
|
||||||
|
add_library(yaml-cpp ${yaml-cpp-type} "")
|
||||||
|
add_library(yaml-cpp::yaml-cpp ALIAS yaml-cpp)
|
||||||
|
|
||||||
|
set_property(TARGET yaml-cpp
|
||||||
|
PROPERTY
|
||||||
|
MSVC_RUNTIME_LIBRARY ${CMAKE_MSVC_RUNTIME_LIBRARY})
|
||||||
|
set_property(TARGET yaml-cpp
|
||||||
|
PROPERTY
|
||||||
|
CXX_STANDARD_REQUIRED ON)
|
||||||
|
|
||||||
|
if (NOT YAML_BUILD_SHARED_LIBS)
|
||||||
|
set_property(TARGET yaml-cpp PROPERTY POSITION_INDEPENDENT_CODE ${YAML_ENABLE_PIC})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(IPHONE)
|
target_include_directories(yaml-cpp
|
||||||
set(CMAKE_OSX_SYSROOT "iphoneos4.2")
|
PUBLIC
|
||||||
set(CMAKE_OSX_ARCHITECTURES "armv6;armv7")
|
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
|
||||||
|
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
||||||
|
PRIVATE
|
||||||
|
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/src>)
|
||||||
|
|
||||||
|
if (NOT DEFINED CMAKE_CXX_STANDARD)
|
||||||
|
set_target_properties(yaml-cpp
|
||||||
|
PROPERTIES
|
||||||
|
CXX_STANDARD 11)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(WIN32)
|
if(YAML_CPP_MAIN_PROJECT)
|
||||||
if(BUILD_SHARED_LIBS)
|
target_compile_options(yaml-cpp
|
||||||
add_definitions(-D${PROJECT_NAME}_DLL) # use or build Windows DLL
|
PRIVATE
|
||||||
endif()
|
$<${not-msvc}:-Wall -Wextra -Wshadow -Weffc++ -Wno-long-long>
|
||||||
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
|
$<${not-msvc}:-pedantic -pedantic-errors>)
|
||||||
set(CMAKE_INSTALL_PREFIX "C:/")
|
|
||||||
endif()
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# GCC or Clang specialities
|
target_compile_options(yaml-cpp
|
||||||
if("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU" OR
|
PRIVATE
|
||||||
"${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
|
$<$<AND:${backport-msvc-runtime},${msvc-rt-mtd-static}>:-MTd>
|
||||||
### General stuff
|
$<$<AND:${backport-msvc-runtime},${msvc-rt-mt-static}>:-MT>
|
||||||
if(WIN32)
|
$<$<AND:${backport-msvc-runtime},${msvc-rt-mtd-dll}>:-MDd>
|
||||||
set(CMAKE_SHARED_LIBRARY_PREFIX "") # DLLs do not have a "lib" prefix
|
$<$<AND:${backport-msvc-runtime},${msvc-rt-mt-dll}>:-MD>
|
||||||
set(CMAKE_IMPORT_LIBRARY_PREFIX "") # same for DLL import libs
|
|
||||||
set(CMAKE_LINK_DEF_FILE_FLAG "") # CMake workaround (2.8.3)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
### Project stuff
|
# /wd4127 = disable warning C4127 "conditional expression is constant"
|
||||||
if(NOT CMAKE_CONFIGURATION_TYPES AND NOT CMAKE_BUILD_TYPE)
|
# http://msdn.microsoft.com/en-us/library/6t66728h.aspx
|
||||||
set(CMAKE_BUILD_TYPE Release)
|
# /wd4355 = disable warning C4355 "'this' : used in base member initializer list
|
||||||
endif()
|
# http://msdn.microsoft.com/en-us/library/3c594ae3.aspx
|
||||||
#
|
$<$<CXX_COMPILER_ID:MSVC>:/W3 /wd4127 /wd4355>)
|
||||||
set(CMAKE_CXX_FLAGS_RELEASE "-O2")
|
|
||||||
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g")
|
|
||||||
set(CMAKE_CXX_FLAGS_DEBUG "-g")
|
|
||||||
set(CMAKE_CXX_FLAGS_MINSIZEREL "-Os")
|
|
||||||
#
|
|
||||||
set(GCC_EXTRA_OPTIONS "")
|
|
||||||
#
|
|
||||||
set(FLAG_TESTED "-Wextra")
|
|
||||||
check_cxx_compiler_flag(${FLAG_TESTED} FLAG_WEXTRA)
|
|
||||||
if(FLAG_WEXTRA)
|
|
||||||
set(GCC_EXTRA_OPTIONS "${GCC_EXTRA_OPTIONS} ${FLAG_TESTED}")
|
|
||||||
endif()
|
|
||||||
#
|
|
||||||
set(yaml_cxx_flags "-Wall ${GCC_EXTRA_OPTIONS} -pedantic -Wno-long-long ${yaml_cxx_flags}")
|
|
||||||
|
|
||||||
### Make specific
|
target_compile_definitions(yaml-cpp
|
||||||
if(${CMAKE_BUILD_TOOL} MATCHES make OR ${CMAKE_BUILD_TOOL} MATCHES gmake)
|
PUBLIC
|
||||||
add_custom_target(debuggable $(MAKE) clean
|
$<$<NOT:$<BOOL:${YAML_BUILD_SHARED_LIBS}>>:YAML_CPP_STATIC_DEFINE>
|
||||||
COMMAND ${CMAKE_COMMAND} -DCMAKE_BUILD_TYPE=Debug ${CMAKE_SOURCE_DIR}
|
PRIVATE
|
||||||
COMMENT "Adjusting settings for debug compilation"
|
$<${build-windows-dll}:${PROJECT_NAME}_DLL>
|
||||||
VERBATIM)
|
$<$<NOT:$<BOOL:${YAML_CPP_BUILD_CONTRIB}>>:YAML_CPP_NO_CONTRIB>)
|
||||||
add_custom_target(releasable $(MAKE) clean
|
|
||||||
COMMAND ${CMAKE_COMMAND} -DCMAKE_BUILD_TYPE=Release ${CMAKE_SOURCE_DIR}
|
target_sources(yaml-cpp
|
||||||
COMMENT "Adjusting settings for release compilation"
|
PRIVATE
|
||||||
VERBATIM)
|
$<$<BOOL:${YAML_CPP_BUILD_CONTRIB}>:${yaml-cpp-contrib-sources}>
|
||||||
endif()
|
${yaml-cpp-sources})
|
||||||
|
|
||||||
|
if (NOT DEFINED CMAKE_DEBUG_POSTFIX)
|
||||||
|
set(CMAKE_DEBUG_POSTFIX "d")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Microsoft VisualC++ specialities
|
|
||||||
if(MSVC)
|
|
||||||
### General stuff
|
|
||||||
# a) Change MSVC runtime library settings (/MD[d], /MT[d], /ML[d] (single-threaded until VS 2003))
|
|
||||||
# plus set lib suffix for later use and project label accordingly
|
|
||||||
# see http://msdn.microsoft.com/en-us/library/aa278396(v=VS.60).aspx
|
|
||||||
# http://msdn.microsoft.com/en-us/library/2kzt1wy3(v=VS.71).aspx
|
|
||||||
set(LIB_RT_SUFFIX "md") # CMake defaults to /MD for MSVC
|
|
||||||
set(LIB_RT_OPTION "/MD")
|
|
||||||
#
|
|
||||||
if(NOT MSVC_SHARED_RT) # User wants to have static runtime libraries (/MT, /ML)
|
|
||||||
if(MSVC_STHREADED_RT) # User wants to have old single-threaded static runtime libraries
|
|
||||||
set(LIB_RT_SUFFIX "ml")
|
|
||||||
set(LIB_RT_OPTION "/ML")
|
|
||||||
if(NOT ${MSVC_VERSION} LESS 1400)
|
|
||||||
message(FATAL_ERROR "Single-threaded static runtime libraries (/ML) only available until VS .NET 2003 (7.1).")
|
|
||||||
endif()
|
|
||||||
else()
|
|
||||||
set(LIB_RT_SUFFIX "mt")
|
|
||||||
set(LIB_RT_OPTION "/MT")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# correct linker options
|
|
||||||
foreach(flag_var yaml_c_flags yaml_cxx_flags)
|
|
||||||
foreach(config_name "" DEBUG RELEASE MINSIZEREL RELWITHDEBINFO)
|
|
||||||
set(var_name "${flag_var}")
|
|
||||||
if(NOT "${config_name}" STREQUAL "")
|
|
||||||
set(var_name "${var_name}_${config_name}")
|
|
||||||
endif()
|
|
||||||
string(REPLACE "/MD" "${LIB_RT_OPTION}" ${var_name} "${${var_name}}")
|
|
||||||
endforeach()
|
|
||||||
endforeach()
|
|
||||||
endif()
|
|
||||||
#
|
|
||||||
set(LABEL_SUFFIX "${LABEL_SUFFIX} ${LIB_RT_SUFFIX}")
|
|
||||||
|
|
||||||
# b) Change prefix for static libraries
|
|
||||||
set(CMAKE_STATIC_LIBRARY_PREFIX "lib") # to distinguish static libraries from DLL import libs
|
|
||||||
|
|
||||||
# c) Correct suffixes for static libraries
|
|
||||||
if(NOT BUILD_SHARED_LIBS)
|
|
||||||
### General stuff
|
|
||||||
set(LIB_TARGET_SUFFIX "${LIB_SUFFIX}${LIB_RT_SUFFIX}")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
### Project stuff
|
|
||||||
# /W3 = set warning level; see http://msdn.microsoft.com/en-us/library/thxezb7y.aspx
|
|
||||||
# /wd4127 = disable warning C4127 "conditional expression is constant"; see http://msdn.microsoft.com/en-us/library/6t66728h.aspx
|
|
||||||
# /wd4355 = disable warning C4355 "'this' : used in base member initializer list"; http://msdn.microsoft.com/en-us/library/3c594ae3.aspx
|
|
||||||
set(yaml_cxx_flags "/W3 /wd4127 /wd4355 ${yaml_cxx_flags}")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
|
|
||||||
###
|
|
||||||
### General install settings
|
|
||||||
###
|
|
||||||
if(WIN32)
|
|
||||||
set(_library_dir bin) # .dll are in PATH, like executables
|
|
||||||
else()
|
|
||||||
set(_library_dir lib)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(INCLUDE_INSTALL_ROOT_DIR include)
|
|
||||||
|
|
||||||
set(INCLUDE_INSTALL_DIR ${INCLUDE_INSTALL_ROOT_DIR}/yaml-cpp)
|
|
||||||
set(LIB_INSTALL_DIR "${_library_dir}${LIB_SUFFIX}")
|
|
||||||
|
|
||||||
set(_INSTALL_DESTINATIONS
|
|
||||||
RUNTIME DESTINATION bin
|
|
||||||
LIBRARY DESTINATION ${LIB_INSTALL_DIR}
|
|
||||||
ARCHIVE DESTINATION "lib${LIB_SUFFIX}"
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
###
|
|
||||||
### Library
|
|
||||||
###
|
|
||||||
add_library(yaml-cpp ${library_sources})
|
|
||||||
set_target_properties(yaml-cpp PROPERTIES
|
|
||||||
COMPILE_FLAGS "${yaml_c_flags} ${yaml_cxx_flags}"
|
|
||||||
)
|
|
||||||
|
|
||||||
set_target_properties(yaml-cpp PROPERTIES
|
set_target_properties(yaml-cpp PROPERTIES
|
||||||
VERSION "${YAML_CPP_VERSION}"
|
VERSION "${PROJECT_VERSION}"
|
||||||
SOVERSION "${YAML_CPP_VERSION_MAJOR}.${YAML_CPP_VERSION_MINOR}"
|
SOVERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}"
|
||||||
PROJECT_LABEL "yaml-cpp ${LABEL_SUFFIX}"
|
PROJECT_LABEL "yaml-cpp ${yaml-cpp-label-postfix}"
|
||||||
)
|
DEBUG_POSTFIX "${CMAKE_DEBUG_POSTFIX}")
|
||||||
|
|
||||||
if(IPHONE)
|
set(EXPORT_TARGETS yaml-cpp::yaml-cpp)
|
||||||
set_target_properties(yaml-cpp PROPERTIES
|
configure_package_config_file(
|
||||||
XCODE_ATTRIBUTE_IPHONEOS_DEPLOYMENT_TARGET "3.0"
|
"${PROJECT_SOURCE_DIR}/yaml-cpp-config.cmake.in"
|
||||||
)
|
"${PROJECT_BINARY_DIR}/yaml-cpp-config.cmake"
|
||||||
|
INSTALL_DESTINATION "${YAML_CPP_INSTALL_CMAKEDIR}"
|
||||||
|
PATH_VARS CMAKE_INSTALL_INCLUDEDIR CMAKE_INSTALL_LIBDIR)
|
||||||
|
unset(EXPORT_TARGETS)
|
||||||
|
|
||||||
|
write_basic_package_version_file(
|
||||||
|
"${PROJECT_BINARY_DIR}/yaml-cpp-config-version.cmake"
|
||||||
|
COMPATIBILITY AnyNewerVersion)
|
||||||
|
|
||||||
|
configure_file(yaml-cpp.pc.in yaml-cpp.pc @ONLY)
|
||||||
|
|
||||||
|
if (YAML_CPP_INSTALL)
|
||||||
|
install(TARGETS yaml-cpp
|
||||||
|
EXPORT yaml-cpp-targets
|
||||||
|
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||||
|
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||||
|
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||||
|
install(DIRECTORY ${PROJECT_SOURCE_DIR}/include/
|
||||||
|
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
|
||||||
|
FILES_MATCHING PATTERN "*.h")
|
||||||
|
install(EXPORT yaml-cpp-targets
|
||||||
|
NAMESPACE yaml-cpp::
|
||||||
|
DESTINATION "${YAML_CPP_INSTALL_CMAKEDIR}")
|
||||||
|
install(FILES
|
||||||
|
"${PROJECT_BINARY_DIR}/yaml-cpp-config.cmake"
|
||||||
|
"${PROJECT_BINARY_DIR}/yaml-cpp-config-version.cmake"
|
||||||
|
DESTINATION "${YAML_CPP_INSTALL_CMAKEDIR}")
|
||||||
|
install(FILES "${PROJECT_BINARY_DIR}/yaml-cpp.pc"
|
||||||
|
DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(MSVC)
|
if(YAML_CPP_BUILD_TESTS)
|
||||||
if(NOT BUILD_SHARED_LIBS)
|
add_subdirectory(test)
|
||||||
# correct library names
|
|
||||||
set_target_properties(yaml-cpp PROPERTIES
|
|
||||||
DEBUG_POSTFIX "${LIB_TARGET_SUFFIX}d"
|
|
||||||
RELEASE_POSTFIX "${LIB_TARGET_SUFFIX}"
|
|
||||||
MINSIZEREL_POSTFIX "${LIB_TARGET_SUFFIX}"
|
|
||||||
RELWITHDEBINFO_POSTFIX "${LIB_TARGET_SUFFIX}"
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
install(TARGETS yaml-cpp ${_INSTALL_DESTINATIONS})
|
|
||||||
install(
|
|
||||||
DIRECTORY ${header_directory}
|
|
||||||
DESTINATION ${INCLUDE_INSTALL_DIR}
|
|
||||||
FILES_MATCHING PATTERN "*.h"
|
|
||||||
)
|
|
||||||
|
|
||||||
export(
|
|
||||||
TARGETS yaml-cpp
|
|
||||||
FILE "${PROJECT_BINARY_DIR}/yaml-cpp-targets.cmake")
|
|
||||||
export(PACKAGE yaml-cpp)
|
|
||||||
set(EXPORT_TARGETS yaml-cpp CACHE INTERNAL "export targets")
|
|
||||||
|
|
||||||
set(CONFIG_INCLUDE_DIRS "${YAML_CPP_SOURCE_DIR}/include")
|
|
||||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/yaml-cpp-config.cmake.in
|
|
||||||
"${PROJECT_BINARY_DIR}/yaml-cpp-config.cmake" @ONLY)
|
|
||||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/yaml-cpp-config-version.cmake.in
|
|
||||||
"${PROJECT_BINARY_DIR}/yaml-cpp-config-version.cmake" @ONLY)
|
|
||||||
|
|
||||||
if(UNIX)
|
|
||||||
set(PC_FILE ${CMAKE_BINARY_DIR}/yaml-cpp.pc)
|
|
||||||
configure_file("yaml-cpp.pc.cmake" ${PC_FILE} @ONLY)
|
|
||||||
install(FILES ${PC_FILE} DESTINATION ${LIB_INSTALL_DIR}/pkgconfig)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
|
|
||||||
###
|
|
||||||
### Extras
|
|
||||||
###
|
|
||||||
if(YAML_CPP_BUILD_TOOLS)
|
if(YAML_CPP_BUILD_TOOLS)
|
||||||
add_subdirectory(test)
|
add_subdirectory(util)
|
||||||
add_subdirectory(util)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
### Formatting
|
if (YAML_CPP_FORMAT_SOURCE AND YAML_CPP_CLANG_FORMAT_EXE)
|
||||||
get_property(all_sources GLOBAL PROPERTY SRCS_LIST)
|
add_custom_target(format
|
||||||
add_custom_target(format
|
COMMAND clang-format --style=file -i $<TARGET_PROPERTY:yaml-cpp,SOURCES>
|
||||||
COMMAND clang-format --style=file -i ${all_sources}
|
COMMAND_EXPAND_LISTS
|
||||||
COMMENT "Running clang-format"
|
COMMENT "Running clang-format"
|
||||||
VERBATIM)
|
WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}"
|
||||||
|
VERBATIM)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# uninstall target
|
||||||
|
if(YAML_CPP_INSTALL AND NOT YAML_CPP_DISABLE_UNINSTALL AND NOT TARGET uninstall)
|
||||||
|
configure_file(
|
||||||
|
"${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake.in"
|
||||||
|
"${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake"
|
||||||
|
IMMEDIATE @ONLY)
|
||||||
|
|
||||||
|
add_custom_target(uninstall
|
||||||
|
COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake)
|
||||||
|
endif()
|
||||||
|
|||||||
26
CONTRIBUTING.md
Normal file
26
CONTRIBUTING.md
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
# Style
|
||||||
|
|
||||||
|
This project is formatted with [clang-format][fmt] using the style file at the root of the repository. Please run clang-format before sending a pull request.
|
||||||
|
|
||||||
|
In general, try to follow the style of surrounding code. We mostly follow the [Google C++ style guide][cpp-style].
|
||||||
|
|
||||||
|
Commit messages should be in the imperative mood, as described in the [Git contributing file][git-contrib]:
|
||||||
|
|
||||||
|
> Describe your changes in imperative mood, e.g. "make xyzzy do frotz"
|
||||||
|
> instead of "[This patch] makes xyzzy do frotz" or "[I] changed xyzzy
|
||||||
|
> to do frotz", as if you are giving orders to the codebase to change
|
||||||
|
> its behaviour.
|
||||||
|
|
||||||
|
[fmt]: http://clang.llvm.org/docs/ClangFormat.html
|
||||||
|
[cpp-style]: https://google.github.io/styleguide/cppguide.html
|
||||||
|
[git-contrib]: http://git.kernel.org/cgit/git/git.git/tree/Documentation/SubmittingPatches?id=HEAD
|
||||||
|
|
||||||
|
# Tests
|
||||||
|
|
||||||
|
Please verify the tests pass by configuring CMake with `-D YAML_CPP_BUILD_TESTS=ON` and running the target `test/yaml-cpp-tests`.
|
||||||
|
|
||||||
|
If you are adding functionality, add tests accordingly. Note that the "spec tests" are reserved for examples directly from the YAML spec, so if you have new examples, put them in other test files.
|
||||||
|
|
||||||
|
# Pull request process
|
||||||
|
|
||||||
|
Every pull request undergoes a code review. Unfortunately, github's code review process isn't great, but we'll manage. During the code review, if you make changes, add new commits to the pull request for each change. Once the code review is complete, rebase against the master branch and squash into a single commit.
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
Copyright (c) 2008 Jesse Beder.
|
Copyright (c) 2008-2015 Jesse Beder.
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
14
MODULE.bazel
Normal file
14
MODULE.bazel
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
"""
|
||||||
|
yaml-cpp is a YAML parser and emitter in c++ matching the YAML specification.
|
||||||
|
"""
|
||||||
|
|
||||||
|
module(
|
||||||
|
name = "yaml-cpp",
|
||||||
|
compatibility_level = 1,
|
||||||
|
version = "0.8.0",
|
||||||
|
)
|
||||||
|
|
||||||
|
bazel_dep(name = "platforms", version = "0.0.7")
|
||||||
|
bazel_dep(name = "rules_cc", version = "0.0.8")
|
||||||
|
|
||||||
|
bazel_dep(name = "googletest", version = "1.14.0", dev_dependency = True)
|
||||||
114
MODULE.bazel.lock
generated
Normal file
114
MODULE.bazel.lock
generated
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
{
|
||||||
|
"lockFileVersion": 11,
|
||||||
|
"registryFileHashes": {
|
||||||
|
"https://bcr.bazel.build/bazel_registry.json": "8a28e4aff06ee60aed2a8c281907fb8bcbf3b753c91fb5a5c57da3215d5b3497",
|
||||||
|
"https://bcr.bazel.build/modules/abseil-cpp/20210324.2/MODULE.bazel": "7cd0312e064fde87c8d1cd79ba06c876bd23630c83466e9500321be55c96ace2",
|
||||||
|
"https://bcr.bazel.build/modules/abseil-cpp/20211102.0/MODULE.bazel": "70390338f7a5106231d20620712f7cccb659cd0e9d073d1991c038eb9fc57589",
|
||||||
|
"https://bcr.bazel.build/modules/abseil-cpp/20230125.1/MODULE.bazel": "89047429cb0207707b2dface14ba7f8df85273d484c2572755be4bab7ce9c3a0",
|
||||||
|
"https://bcr.bazel.build/modules/abseil-cpp/20230125.1/source.json": "06cc0842d241da0c5edc755edb3c7d0d008d304330e57ecf2d6449fb0b633a82",
|
||||||
|
"https://bcr.bazel.build/modules/apple_support/1.5.0/MODULE.bazel": "50341a62efbc483e8a2a6aec30994a58749bd7b885e18dd96aa8c33031e558ef",
|
||||||
|
"https://bcr.bazel.build/modules/apple_support/1.5.0/source.json": "eb98a7627c0bc486b57f598ad8da50f6625d974c8f723e9ea71bd39f709c9862",
|
||||||
|
"https://bcr.bazel.build/modules/bazel_features/1.11.0/MODULE.bazel": "f9382337dd5a474c3b7d334c2f83e50b6eaedc284253334cf823044a26de03e8",
|
||||||
|
"https://bcr.bazel.build/modules/bazel_features/1.11.0/source.json": "c9320aa53cd1c441d24bd6b716da087ad7e4ff0d9742a9884587596edfe53015",
|
||||||
|
"https://bcr.bazel.build/modules/bazel_skylib/1.0.3/MODULE.bazel": "bcb0fd896384802d1ad283b4e4eb4d718eebd8cb820b0a2c3a347fb971afd9d8",
|
||||||
|
"https://bcr.bazel.build/modules/bazel_skylib/1.2.1/MODULE.bazel": "f35baf9da0efe45fa3da1696ae906eea3d615ad41e2e3def4aeb4e8bc0ef9a7a",
|
||||||
|
"https://bcr.bazel.build/modules/bazel_skylib/1.3.0/MODULE.bazel": "20228b92868bf5cfc41bda7afc8a8ba2a543201851de39d990ec957b513579c5",
|
||||||
|
"https://bcr.bazel.build/modules/bazel_skylib/1.4.1/MODULE.bazel": "a0dcb779424be33100dcae821e9e27e4f2901d9dfd5333efe5ac6a8d7ab75e1d",
|
||||||
|
"https://bcr.bazel.build/modules/bazel_skylib/1.6.1/MODULE.bazel": "8fdee2dbaace6c252131c00e1de4b165dc65af02ea278476187765e1a617b917",
|
||||||
|
"https://bcr.bazel.build/modules/bazel_skylib/1.6.1/source.json": "082ed5f9837901fada8c68c2f3ddc958bb22b6d654f71dd73f3df30d45d4b749",
|
||||||
|
"https://bcr.bazel.build/modules/buildozer/7.1.2/MODULE.bazel": "2e8dd40ede9c454042645fd8d8d0cd1527966aa5c919de86661e62953cd73d84",
|
||||||
|
"https://bcr.bazel.build/modules/buildozer/7.1.2/source.json": "c9028a501d2db85793a6996205c8de120944f50a0d570438fcae0457a5f9d1f8",
|
||||||
|
"https://bcr.bazel.build/modules/googletest/1.11.0/MODULE.bazel": "3a83f095183f66345ca86aa13c58b59f9f94a2f81999c093d4eeaa2d262d12f4",
|
||||||
|
"https://bcr.bazel.build/modules/googletest/1.14.0/MODULE.bazel": "cfbcbf3e6eac06ef9d85900f64424708cc08687d1b527f0ef65aa7517af8118f",
|
||||||
|
"https://bcr.bazel.build/modules/googletest/1.14.0/source.json": "2478949479000fdd7de9a3d0107ba2c85bb5f961c3ecb1aa448f52549ce310b5",
|
||||||
|
"https://bcr.bazel.build/modules/platforms/0.0.4/MODULE.bazel": "9b328e31ee156f53f3c416a64f8491f7eb731742655a47c9eec4703a71644aee",
|
||||||
|
"https://bcr.bazel.build/modules/platforms/0.0.5/MODULE.bazel": "5733b54ea419d5eaf7997054bb55f6a1d0b5ff8aedf0176fef9eea44f3acda37",
|
||||||
|
"https://bcr.bazel.build/modules/platforms/0.0.6/MODULE.bazel": "ad6eeef431dc52aefd2d77ed20a4b353f8ebf0f4ecdd26a807d2da5aa8cd0615",
|
||||||
|
"https://bcr.bazel.build/modules/platforms/0.0.7/MODULE.bazel": "72fd4a0ede9ee5c021f6a8dd92b503e089f46c227ba2813ff183b71616034814",
|
||||||
|
"https://bcr.bazel.build/modules/platforms/0.0.9/MODULE.bazel": "4a87a60c927b56ddd67db50c89acaa62f4ce2a1d2149ccb63ffd871d5ce29ebc",
|
||||||
|
"https://bcr.bazel.build/modules/platforms/0.0.9/source.json": "cd74d854bf16a9e002fb2ca7b1a421f4403cda29f824a765acd3a8c56f8d43e6",
|
||||||
|
"https://bcr.bazel.build/modules/protobuf/21.7/MODULE.bazel": "a5a29bb89544f9b97edce05642fac225a808b5b7be74038ea3640fae2f8e66a7",
|
||||||
|
"https://bcr.bazel.build/modules/protobuf/21.7/source.json": "bbe500720421e582ff2d18b0802464205138c06056f443184de39fbb8187b09b",
|
||||||
|
"https://bcr.bazel.build/modules/protobuf/3.19.0/MODULE.bazel": "6b5fbb433f760a99a22b18b6850ed5784ef0e9928a72668b66e4d7ccd47db9b0",
|
||||||
|
"https://bcr.bazel.build/modules/protobuf/3.19.6/MODULE.bazel": "9233edc5e1f2ee276a60de3eaa47ac4132302ef9643238f23128fea53ea12858",
|
||||||
|
"https://bcr.bazel.build/modules/rules_cc/0.0.1/MODULE.bazel": "cb2aa0747f84c6c3a78dad4e2049c154f08ab9d166b1273835a8174940365647",
|
||||||
|
"https://bcr.bazel.build/modules/rules_cc/0.0.2/MODULE.bazel": "6915987c90970493ab97393024c156ea8fb9f3bea953b2f3ec05c34f19b5695c",
|
||||||
|
"https://bcr.bazel.build/modules/rules_cc/0.0.6/MODULE.bazel": "abf360251023dfe3efcef65ab9d56beefa8394d4176dd29529750e1c57eaa33f",
|
||||||
|
"https://bcr.bazel.build/modules/rules_cc/0.0.8/MODULE.bazel": "964c85c82cfeb6f3855e6a07054fdb159aced38e99a5eecf7bce9d53990afa3e",
|
||||||
|
"https://bcr.bazel.build/modules/rules_cc/0.0.9/MODULE.bazel": "836e76439f354b89afe6a911a7adf59a6b2518fafb174483ad78a2a2fde7b1c5",
|
||||||
|
"https://bcr.bazel.build/modules/rules_cc/0.0.9/source.json": "1f1ba6fea244b616de4a554a0f4983c91a9301640c8fe0dd1d410254115c8430",
|
||||||
|
"https://bcr.bazel.build/modules/rules_java/4.0.0/MODULE.bazel": "5a78a7ae82cd1a33cef56dc578c7d2a46ed0dca12643ee45edbb8417899e6f74",
|
||||||
|
"https://bcr.bazel.build/modules/rules_java/7.6.5/MODULE.bazel": "481164be5e02e4cab6e77a36927683263be56b7e36fef918b458d7a8a1ebadb1",
|
||||||
|
"https://bcr.bazel.build/modules/rules_java/7.6.5/source.json": "a805b889531d1690e3c72a7a7e47a870d00323186a9904b36af83aa3d053ee8d",
|
||||||
|
"https://bcr.bazel.build/modules/rules_jvm_external/4.4.2/MODULE.bazel": "a56b85e418c83eb1839819f0b515c431010160383306d13ec21959ac412d2fe7",
|
||||||
|
"https://bcr.bazel.build/modules/rules_jvm_external/4.4.2/source.json": "a075731e1b46bc8425098512d038d416e966ab19684a10a34f4741295642fc35",
|
||||||
|
"https://bcr.bazel.build/modules/rules_license/0.0.3/MODULE.bazel": "627e9ab0247f7d1e05736b59dbb1b6871373de5ad31c3011880b4133cafd4bd0",
|
||||||
|
"https://bcr.bazel.build/modules/rules_license/0.0.7/MODULE.bazel": "088fbeb0b6a419005b89cf93fe62d9517c0a2b8bb56af3244af65ecfe37e7d5d",
|
||||||
|
"https://bcr.bazel.build/modules/rules_license/0.0.7/source.json": "355cc5737a0f294e560d52b1b7a6492d4fff2caf0bef1a315df5a298fca2d34a",
|
||||||
|
"https://bcr.bazel.build/modules/rules_pkg/0.7.0/MODULE.bazel": "df99f03fc7934a4737122518bb87e667e62d780b610910f0447665a7e2be62dc",
|
||||||
|
"https://bcr.bazel.build/modules/rules_pkg/0.7.0/source.json": "c2557066e0c0342223ba592510ad3d812d4963b9024831f7f66fd0584dd8c66c",
|
||||||
|
"https://bcr.bazel.build/modules/rules_proto/4.0.0/MODULE.bazel": "a7a7b6ce9bee418c1a760b3d84f83a299ad6952f9903c67f19e4edd964894e06",
|
||||||
|
"https://bcr.bazel.build/modules/rules_proto/5.3.0-21.7/MODULE.bazel": "e8dff86b0971688790ae75528fe1813f71809b5afd57facb44dad9e8eca631b7",
|
||||||
|
"https://bcr.bazel.build/modules/rules_proto/5.3.0-21.7/source.json": "d57902c052424dfda0e71646cb12668d39c4620ee0544294d9d941e7d12bc3a9",
|
||||||
|
"https://bcr.bazel.build/modules/rules_python/0.10.2/MODULE.bazel": "cc82bc96f2997baa545ab3ce73f196d040ffb8756fd2d66125a530031cd90e5f",
|
||||||
|
"https://bcr.bazel.build/modules/rules_python/0.22.1/MODULE.bazel": "26114f0c0b5e93018c0c066d6673f1a2c3737c7e90af95eff30cfee38d0bbac7",
|
||||||
|
"https://bcr.bazel.build/modules/rules_python/0.22.1/source.json": "57226905e783bae7c37c2dd662be078728e48fa28ee4324a7eabcafb5a43d014",
|
||||||
|
"https://bcr.bazel.build/modules/rules_python/0.4.0/MODULE.bazel": "9208ee05fd48bf09ac60ed269791cf17fb343db56c8226a720fbb1cdf467166c",
|
||||||
|
"https://bcr.bazel.build/modules/stardoc/0.5.1/MODULE.bazel": "1a05d92974d0c122f5ccf09291442580317cdd859f07a8655f1db9a60374f9f8",
|
||||||
|
"https://bcr.bazel.build/modules/stardoc/0.5.1/source.json": "a96f95e02123320aa015b956f29c00cb818fa891ef823d55148e1a362caacf29",
|
||||||
|
"https://bcr.bazel.build/modules/upb/0.0.0-20220923-a547704/MODULE.bazel": "7298990c00040a0e2f121f6c32544bab27d4452f80d9ce51349b1a28f3005c43",
|
||||||
|
"https://bcr.bazel.build/modules/upb/0.0.0-20220923-a547704/source.json": "f1ef7d3f9e0e26d4b23d1c39b5f5de71f584dd7d1b4ef83d9bbba6ec7a6a6459",
|
||||||
|
"https://bcr.bazel.build/modules/zlib/1.2.11/MODULE.bazel": "07b389abc85fdbca459b69e2ec656ae5622873af3f845e1c9d80fe179f3effa0",
|
||||||
|
"https://bcr.bazel.build/modules/zlib/1.2.12/MODULE.bazel": "3b1a8834ada2a883674be8cbd36ede1b6ec481477ada359cd2d3ddc562340b27",
|
||||||
|
"https://bcr.bazel.build/modules/zlib/1.3.1.bcr.3/MODULE.bazel": "af322bc08976524477c79d1e45e241b6efbeb918c497e8840b8ab116802dda79",
|
||||||
|
"https://bcr.bazel.build/modules/zlib/1.3.1.bcr.3/source.json": "2be409ac3c7601245958cd4fcdff4288be79ed23bd690b4b951f500d54ee6e7d"
|
||||||
|
},
|
||||||
|
"selectedYankedVersions": {},
|
||||||
|
"moduleExtensions": {
|
||||||
|
"@@apple_support~//crosstool:setup.bzl%apple_cc_configure_extension": {
|
||||||
|
"general": {
|
||||||
|
"bzlTransitiveDigest": "PjIds3feoYE8SGbbIq2SFTZy3zmxeO2tQevJZNDo7iY=",
|
||||||
|
"usagesDigest": "+hz7IHWN6A1oVJJWNDB6yZRG+RYhF76wAYItpAeIUIg=",
|
||||||
|
"recordedFileInputs": {},
|
||||||
|
"recordedDirentsInputs": {},
|
||||||
|
"envVariables": {},
|
||||||
|
"generatedRepoSpecs": {
|
||||||
|
"local_config_apple_cc_toolchains": {
|
||||||
|
"bzlFile": "@@apple_support~//crosstool:setup.bzl",
|
||||||
|
"ruleClassName": "_apple_cc_autoconf_toolchains",
|
||||||
|
"attributes": {}
|
||||||
|
},
|
||||||
|
"local_config_apple_cc": {
|
||||||
|
"bzlFile": "@@apple_support~//crosstool:setup.bzl",
|
||||||
|
"ruleClassName": "_apple_cc_autoconf",
|
||||||
|
"attributes": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"recordedRepoMappingEntries": [
|
||||||
|
[
|
||||||
|
"apple_support~",
|
||||||
|
"bazel_tools",
|
||||||
|
"bazel_tools"
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@@platforms//host:extension.bzl%host_platform": {
|
||||||
|
"general": {
|
||||||
|
"bzlTransitiveDigest": "xelQcPZH8+tmuOHVjL9vDxMnnQNMlwj0SlvgoqBkm4U=",
|
||||||
|
"usagesDigest": "pCYpDQmqMbmiiPI1p2Kd3VLm5T48rRAht5WdW0X2GlA=",
|
||||||
|
"recordedFileInputs": {},
|
||||||
|
"recordedDirentsInputs": {},
|
||||||
|
"envVariables": {},
|
||||||
|
"generatedRepoSpecs": {
|
||||||
|
"host_platform": {
|
||||||
|
"bzlFile": "@@platforms//host:extension.bzl",
|
||||||
|
"ruleClassName": "host_platform_repo",
|
||||||
|
"attributes": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"recordedRepoMappingEntries": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
86
README.md
Normal file
86
README.md
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
# yaml-cpp  [](https://codedocs.xyz/jbeder/yaml-cpp/)
|
||||||
|
|
||||||
|
`yaml-cpp` is a [YAML](http://www.yaml.org/) parser and emitter in C++ matching the [YAML 1.2 spec](http://www.yaml.org/spec/1.2/spec.html).
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
See [Tutorial](https://github.com/jbeder/yaml-cpp/wiki/Tutorial) and [How to Emit YAML](https://github.com/jbeder/yaml-cpp/wiki/How-To-Emit-YAML) for reference. For the old API (until 0.5.0), see [How To Parse A Document](https://github.com/jbeder/yaml-cpp/wiki/How-To-Parse-A-Document-(Old-API)).
|
||||||
|
|
||||||
|
## Any Problems?
|
||||||
|
|
||||||
|
If you find a bug, post an [issue](https://github.com/jbeder/yaml-cpp/issues)! If you have questions about how to use yaml-cpp, please post it on http://stackoverflow.com and tag it [`yaml-cpp`](http://stackoverflow.com/questions/tagged/yaml-cpp).
|
||||||
|
|
||||||
|
## How to Build
|
||||||
|
|
||||||
|
`yaml-cpp` uses [CMake](http://www.cmake.org) to support cross-platform building. Install [CMake](http://www.cmake.org) _(Resources -> Download)_ before proceeding. The basic steps to build are:
|
||||||
|
|
||||||
|
**Note:** If you don't use the provided installer for your platform, make sure that you add `CMake`'s bin folder to your path.
|
||||||
|
|
||||||
|
#### 1. Navigate into the source directory, create build folder and run `CMake`:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
mkdir build
|
||||||
|
cd build
|
||||||
|
cmake [-G generator] [-DYAML_BUILD_SHARED_LIBS=on|OFF] ..
|
||||||
|
```
|
||||||
|
|
||||||
|
* The `generator` option is the build system you'd like to use. Run `cmake` without arguments to see a full list of available generators.
|
||||||
|
* On Windows, you might use "Visual Studio 12 2013" (VS 2013 32-bits), or "Visual Studio 14 2015 Win64" (VS 2015 64-bits).
|
||||||
|
* On OS X, you might use "Xcode".
|
||||||
|
* On a UNIX-like system, omit the option (for a Makefile).
|
||||||
|
|
||||||
|
* `yaml-cpp` builds a static library by default, you may want to build a shared library by specifying `-DYAML_BUILD_SHARED_LIBS=ON`.
|
||||||
|
|
||||||
|
* [Debug mode of the GNU standard C++
|
||||||
|
library](https://gcc.gnu.org/onlinedocs/libstdc++/manual/debug_mode.html)
|
||||||
|
can be used when both `yaml-cpp` and client code is compiled with the
|
||||||
|
`_GLIBCXX_DEBUG` flag (e.g. by calling CMake with `-D
|
||||||
|
CMAKE_CXX_FLAGS_DEBUG='-g -D_GLIBCXX_DEBUG'` option).
|
||||||
|
|
||||||
|
Note that for `yaml-cpp` unit tests to run successfully, the _GoogleTest_
|
||||||
|
library also must be built with this flag, i.e. the system one cannot be
|
||||||
|
used (the _YAML_USE_SYSTEM_GTEST_ CMake option must be _OFF_, which is the
|
||||||
|
default).
|
||||||
|
|
||||||
|
* For more options on customizing the build, see the [CMakeLists.txt](https://github.com/jbeder/yaml-cpp/blob/master/CMakeLists.txt) file.
|
||||||
|
|
||||||
|
#### 2. Build it!
|
||||||
|
* The command you'll need to run depends on the generator you chose earlier.
|
||||||
|
|
||||||
|
**Note:** To clean up, just remove the `build` directory.
|
||||||
|
|
||||||
|
## How to Integrate it within your project using CMake
|
||||||
|
|
||||||
|
You can use for example FetchContent :
|
||||||
|
|
||||||
|
```cmake
|
||||||
|
include(FetchContent)
|
||||||
|
|
||||||
|
FetchContent_Declare(
|
||||||
|
yaml-cpp
|
||||||
|
GIT_REPOSITORY https://github.com/jbeder/yaml-cpp.git
|
||||||
|
GIT_TAG <tag_name> # Can be a tag (yaml-cpp-x.x.x), a commit hash, or a branch name (master)
|
||||||
|
)
|
||||||
|
FetchContent_MakeAvailable(yaml-cpp)
|
||||||
|
|
||||||
|
target_link_libraries(YOUR_LIBRARY PUBLIC yaml-cpp::yaml-cpp) # The library or executable that require yaml-cpp library
|
||||||
|
```
|
||||||
|
|
||||||
|
## Recent Releases
|
||||||
|
|
||||||
|
[yaml-cpp 0.8.0](https://github.com/jbeder/yaml-cpp/releases/tag/0.8.0) released!
|
||||||
|
|
||||||
|
[yaml-cpp 0.3.0](https://github.com/jbeder/yaml-cpp/releases/tag/release-0.3.0) is still available if you want the old API.
|
||||||
|
|
||||||
|
**The old API will stop receiving bugfixes in 2026.** The 0.3.x versions provide the old API, and 0.5.x and above all provide the new API.
|
||||||
|
|
||||||
|
# API Documentation
|
||||||
|
|
||||||
|
The autogenerated API reference is hosted on [CodeDocs](https://codedocs.xyz/jbeder/yaml-cpp/index.html)
|
||||||
|
|
||||||
|
# Third Party Integrations
|
||||||
|
|
||||||
|
The following projects are not officially supported:
|
||||||
|
|
||||||
|
- [Qt wrapper](https://gist.github.com/brcha/d392b2fe5f1e427cc8a6)
|
||||||
|
- [UnrealEngine Wrapper](https://github.com/jwindgassen/UnrealYAML)
|
||||||
13
SECURITY.md
Normal file
13
SECURITY.md
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
# Security Policy
|
||||||
|
|
||||||
|
## Supported Versions
|
||||||
|
|
||||||
|
Security updates are applied only to the latest release.
|
||||||
|
|
||||||
|
## Reporting a Vulnerability
|
||||||
|
|
||||||
|
If you have discovered a security vulnerability in this project, please report it privately. **Do not disclose it as a public issue.** This gives us time to work with you to fix the issue before public exposure, reducing the chance that the exploit will be used before a patch is released.
|
||||||
|
|
||||||
|
Please disclose it at [security advisory](https://github.com/jbeder/yaml-cpp/security/advisories/new).
|
||||||
|
|
||||||
|
This project is maintained by a team of volunteers on a reasonable-effort basis. As such, vulnerabilities will be disclosed in a best effort base.
|
||||||
21
cmake_uninstall.cmake.in
Normal file
21
cmake_uninstall.cmake.in
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
if(NOT EXISTS "@CMAKE_BINARY_DIR@/install_manifest.txt")
|
||||||
|
message(FATAL_ERROR "Cannot find install manifest: @CMAKE_BINARY_DIR@/install_manifest.txt")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
file(READ "@CMAKE_BINARY_DIR@/install_manifest.txt" files)
|
||||||
|
string(REGEX REPLACE "\n" ";" files "${files}")
|
||||||
|
foreach(file ${files})
|
||||||
|
message(STATUS "Uninstalling $ENV{DESTDIR}${file}")
|
||||||
|
if(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
|
||||||
|
exec_program(
|
||||||
|
"@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\""
|
||||||
|
OUTPUT_VARIABLE rm_out
|
||||||
|
RETURN_VALUE rm_retval
|
||||||
|
)
|
||||||
|
if(NOT "${rm_retval}" STREQUAL 0)
|
||||||
|
message(FATAL_ERROR "Problem when removing $ENV{DESTDIR}${file}")
|
||||||
|
endif()
|
||||||
|
else(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
|
||||||
|
message(STATUS "File $ENV{DESTDIR}${file} does not exist.")
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
52
docs/Breaking-Changes.md
Normal file
52
docs/Breaking-Changes.md
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
# The following is a list of breaking changes to yaml-cpp, by version #
|
||||||
|
|
||||||
|
# New API #
|
||||||
|
|
||||||
|
## HEAD ##
|
||||||
|
|
||||||
|
* Throws an exception when trying to parse a negative number as an unsigned integer.
|
||||||
|
* Supports the `as<int8_t>`/`as<uint8_t>`, which throws an exception when the value exceeds the range of `int8_t`/`uint8_t`.
|
||||||
|
|
||||||
|
## 0.6.0 ##
|
||||||
|
|
||||||
|
* Requires C++11.
|
||||||
|
|
||||||
|
## 0.5.3 ##
|
||||||
|
|
||||||
|
_none_
|
||||||
|
|
||||||
|
## 0.5.2 ##
|
||||||
|
|
||||||
|
_none_
|
||||||
|
|
||||||
|
## 0.5.1 ##
|
||||||
|
|
||||||
|
* `Node::clear` was replaced by `Node::reset`, which takes an optional node, similar to smart pointers.
|
||||||
|
|
||||||
|
## 0.5.0 ##
|
||||||
|
|
||||||
|
Initial version of the new API.
|
||||||
|
|
||||||
|
# Old API #
|
||||||
|
|
||||||
|
## 0.3.0 ##
|
||||||
|
|
||||||
|
_none_
|
||||||
|
|
||||||
|
## 0.2.7 ##
|
||||||
|
|
||||||
|
* `YAML::Binary` now takes `const unsigned char *` for the binary data (instead of `const char *`).
|
||||||
|
|
||||||
|
## 0.2.6 ##
|
||||||
|
|
||||||
|
* `Node::GetType()` is now `Node::Type()`, and returns an enum `NodeType::value`, where:
|
||||||
|
> > ` struct NodeType { enum value { Null, Scalar, Sequence, Map }; }; `
|
||||||
|
* `Node::GetTag()` is now `Node::Tag()`
|
||||||
|
* `Node::Identity()` is removed, and `Node::IsAlias()` and `Node::IsReferenced()` have been merged into `Node::IsAliased()`. The reason: there's no reason to distinguish an alias node from its anchor - whichever happens to be emitted first will be the anchor, and the rest will be aliases.
|
||||||
|
* `Node::Read<T>` is now `Node::to<T>`. This wasn't a documented function, so it shouldn't break anything.
|
||||||
|
* `Node`'s comparison operators (for example, `operator == (const Node&, const T&)`) have all been removed. These weren't documented either (they were just used for the tests), so this shouldn't break anything either.
|
||||||
|
* The emitter no longer produces the document start by default - if you want it, you can supply it with the manipulator `YAML::BeginDoc`.
|
||||||
|
|
||||||
|
## 0.2.5 ##
|
||||||
|
|
||||||
|
This wiki was started with v0.2.5.
|
||||||
226
docs/How-To-Emit-YAML.md
Normal file
226
docs/How-To-Emit-YAML.md
Normal file
@@ -0,0 +1,226 @@
|
|||||||
|
## Contents ##
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Basic Emitting #
|
||||||
|
|
||||||
|
The model for emitting YAML is `std::ostream` manipulators. A `YAML::Emitter` objects acts as an output stream, and its output can be retrieved through the `c_str()` function (as in `std::string`). For a simple example:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
#include "yaml-cpp/yaml.h"
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
YAML::Emitter out;
|
||||||
|
out << "Hello, World!";
|
||||||
|
|
||||||
|
std::cout << "Here's the output YAML:\n" << out.c_str(); // prints "Hello, World!"
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
# Simple Lists and Maps #
|
||||||
|
|
||||||
|
A `YAML::Emitter` object acts as a state machine, and we use manipulators to move it between states. Here's a simple sequence:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
YAML::Emitter out;
|
||||||
|
out << YAML::BeginSeq;
|
||||||
|
out << "eggs";
|
||||||
|
out << "bread";
|
||||||
|
out << "milk";
|
||||||
|
out << YAML::EndSeq;
|
||||||
|
```
|
||||||
|
|
||||||
|
produces
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- eggs
|
||||||
|
- bread
|
||||||
|
- milk
|
||||||
|
```
|
||||||
|
|
||||||
|
A simple map:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
YAML::Emitter out;
|
||||||
|
out << YAML::BeginMap;
|
||||||
|
out << YAML::Key << "name";
|
||||||
|
out << YAML::Value << "Ryan Braun";
|
||||||
|
out << YAML::Key << "position";
|
||||||
|
out << YAML::Value << "LF";
|
||||||
|
out << YAML::EndMap;
|
||||||
|
```
|
||||||
|
|
||||||
|
produces
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
name: Ryan Braun
|
||||||
|
position: LF
|
||||||
|
```
|
||||||
|
|
||||||
|
These elements can, of course, be nested:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
YAML::Emitter out;
|
||||||
|
out << YAML::BeginMap;
|
||||||
|
out << YAML::Key << "name";
|
||||||
|
out << YAML::Value << "Barack Obama";
|
||||||
|
out << YAML::Key << "children";
|
||||||
|
out << YAML::Value << YAML::BeginSeq << "Sasha" << "Malia" << YAML::EndSeq;
|
||||||
|
out << YAML::EndMap;
|
||||||
|
```
|
||||||
|
|
||||||
|
produces
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
name: Barack Obama
|
||||||
|
children:
|
||||||
|
- Sasha
|
||||||
|
- Malia
|
||||||
|
```
|
||||||
|
|
||||||
|
# Using Manipulators #
|
||||||
|
|
||||||
|
To deviate from standard formatting, you can use manipulators to modify the output format. For example,
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
YAML::Emitter out;
|
||||||
|
out << YAML::Literal << "A\n B\n C";
|
||||||
|
```
|
||||||
|
|
||||||
|
produces
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
|
|
||||||
|
A
|
||||||
|
B
|
||||||
|
C
|
||||||
|
```
|
||||||
|
and
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
YAML::Emitter out;
|
||||||
|
out << YAML::Flow;
|
||||||
|
out << YAML::BeginSeq << 2 << 3 << 5 << 7 << 11 << YAML::EndSeq;
|
||||||
|
```
|
||||||
|
|
||||||
|
produces
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
[2, 3, 5, 7, 11]
|
||||||
|
```
|
||||||
|
|
||||||
|
Comments act like manipulators:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
YAML::Emitter out;
|
||||||
|
out << YAML::BeginMap;
|
||||||
|
out << YAML::Key << "method";
|
||||||
|
out << YAML::Value << "least squares";
|
||||||
|
out << YAML::Comment("should we change this method?");
|
||||||
|
out << YAML::EndMap;
|
||||||
|
```
|
||||||
|
|
||||||
|
produces
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
method: least squares # should we change this method?
|
||||||
|
```
|
||||||
|
|
||||||
|
And so do aliases/anchors:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
YAML::Emitter out;
|
||||||
|
out << YAML::BeginSeq;
|
||||||
|
out << YAML::Anchor("fred");
|
||||||
|
out << YAML::BeginMap;
|
||||||
|
out << YAML::Key << "name" << YAML::Value << "Fred";
|
||||||
|
out << YAML::Key << "age" << YAML::Value << "42";
|
||||||
|
out << YAML::EndMap;
|
||||||
|
out << YAML::Alias("fred");
|
||||||
|
out << YAML::EndSeq;
|
||||||
|
```
|
||||||
|
|
||||||
|
produces
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- &fred
|
||||||
|
name: Fred
|
||||||
|
age: 42
|
||||||
|
- *fred
|
||||||
|
```
|
||||||
|
|
||||||
|
# STL Containers, and Other Overloads #
|
||||||
|
We overload `operator <<` for `std::vector`, `std::list`, and `std::map`, so you can write stuff like:
|
||||||
|
|
||||||
|
{% raw %}
|
||||||
|
```cpp
|
||||||
|
std::vector <int> squares = {1, 4, 9, 16};
|
||||||
|
|
||||||
|
std::map <std::string, int> ages = {{"Daniel", 26}, {"Jesse", 24}};
|
||||||
|
|
||||||
|
YAML::Emitter out;
|
||||||
|
out << YAML::BeginSeq;
|
||||||
|
out << YAML::Flow << squares;
|
||||||
|
out << ages;
|
||||||
|
out << YAML::EndSeq;
|
||||||
|
```
|
||||||
|
{% endraw %}
|
||||||
|
|
||||||
|
produces
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- [1, 4, 9, 16]
|
||||||
|
-
|
||||||
|
Daniel: 26
|
||||||
|
Jesse: 24
|
||||||
|
```
|
||||||
|
|
||||||
|
Of course, you can overload `operator <<` for your own types:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
struct Vec3 { int x; int y; int z; };
|
||||||
|
YAML::Emitter& operator << (YAML::Emitter& out, const Vec3& v) {
|
||||||
|
out << YAML::Flow;
|
||||||
|
out << YAML::BeginSeq << v.x << v.y << v.z << YAML::EndSeq;
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
and it'll play nicely with everything else.
|
||||||
|
|
||||||
|
# Using Existing Nodes #
|
||||||
|
|
||||||
|
We also overload `operator << ` for `YAML::Node`s in both APIs, so you can output existing Nodes. Of course, Nodes in the old API are read-only, so it's tricky to emit them if you want to modify them. So use the new API!
|
||||||
|
|
||||||
|
# Output Encoding #
|
||||||
|
|
||||||
|
The output is always UTF-8. By default, yaml-cpp will output as much as it can without escaping any characters. If you want to restrict the output to ASCII, use the manipulator `YAML::EscapeNonAscii`:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
emitter.SetOutputCharset(YAML::EscapeNonAscii);
|
||||||
|
```
|
||||||
|
|
||||||
|
# Lifetime of Manipulators #
|
||||||
|
|
||||||
|
Manipulators affect the **next** output item in the stream. If that item is a `BeginSeq` or `BeginMap`, the manipulator lasts until the corresponding `EndSeq` or `EndMap`. (However, within that sequence or map, you can override the manipulator locally, etc.; in effect, there's a "manipulator stack" behind the scenes.)
|
||||||
|
|
||||||
|
If you want to permanently change a setting, there are global setters corresponding to each manipulator, e.g.:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
YAML::Emitter out;
|
||||||
|
out.SetIndent(4);
|
||||||
|
out.SetMapStyle(YAML::Flow);
|
||||||
|
```
|
||||||
|
|
||||||
|
# When Something Goes Wrong #
|
||||||
|
|
||||||
|
If something goes wrong when you're emitting a document, it must be something like forgetting a `YAML::EndSeq`, or a misplaced `YAML::Key`. In this case, emitting silently fails (no more output is emitted) and an error flag is set. For example:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
YAML::Emitter out;
|
||||||
|
assert(out.good());
|
||||||
|
out << YAML::Key;
|
||||||
|
assert(!out.good());
|
||||||
|
std::cout << "Emitter error: " << out.GetLastError() << "\n";
|
||||||
|
```
|
||||||
265
docs/How-To-Parse-A-Document-(Old-API).md
Normal file
265
docs/How-To-Parse-A-Document-(Old-API).md
Normal file
@@ -0,0 +1,265 @@
|
|||||||
|
_The following describes the old API. For the new API, see the [Tutorial](https://github.com/jbeder/yaml-cpp/wiki/Tutorial)._
|
||||||
|
|
||||||
|
## Contents ##
|
||||||
|
|
||||||
|
|
||||||
|
# Basic Parsing #
|
||||||
|
|
||||||
|
The parser accepts streams, not file names, so you need to first load the file. Since a YAML file can contain many documents, you can grab them one-by-one. A simple way to parse a YAML file might be:
|
||||||
|
|
||||||
|
```
|
||||||
|
#include <fstream>
|
||||||
|
#include "yaml-cpp/yaml.h"
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
std::ifstream fin("test.yaml");
|
||||||
|
YAML::Parser parser(fin);
|
||||||
|
|
||||||
|
YAML::Node doc;
|
||||||
|
while(parser.GetNextDocument(doc)) {
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
# Reading From the Document #
|
||||||
|
|
||||||
|
Suppose we have a document consisting only of a scalar. We can read that scalar like this:
|
||||||
|
|
||||||
|
```
|
||||||
|
YAML::Node doc; // let's say we've already parsed this document
|
||||||
|
std::string scalar;
|
||||||
|
doc >> scalar;
|
||||||
|
std::cout << "That scalar was: " << scalar << std::endl;
|
||||||
|
```
|
||||||
|
|
||||||
|
How about sequences? Let's say our document now consists only of a sequences of scalars. We can use an iterator:
|
||||||
|
|
||||||
|
```
|
||||||
|
YAML::Node doc; // already parsed
|
||||||
|
for(YAML::Iterator it=doc.begin();it!=doc.end();++it) {
|
||||||
|
std::string scalar;
|
||||||
|
*it >> scalar;
|
||||||
|
std::cout << "Found scalar: " << scalar << std::endl;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
... or we can just loop through:
|
||||||
|
|
||||||
|
```
|
||||||
|
YAML::Node doc; // already parsed
|
||||||
|
for(unsigned i=0;i<doc.size();i++) {
|
||||||
|
std::string scalar;
|
||||||
|
doc[i] >> scalar;
|
||||||
|
std::cout << "Found scalar: " << scalar << std::endl;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
And finally maps. For now, let's say our document is a map with all keys/values being scalars. Again, we can iterate:
|
||||||
|
|
||||||
|
```
|
||||||
|
YAML::Node doc; // already parsed
|
||||||
|
for(YAML::Iterator it=doc.begin();it!=doc.end();++it) {
|
||||||
|
std::string key, value;
|
||||||
|
it.first() >> key;
|
||||||
|
it.second() >> value;
|
||||||
|
std::cout << "Key: " << key << ", value: " << value << std::endl;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Note that dereferencing a map iterator is undefined; instead, use the `first` and `second` methods to get the key and value nodes, respectively.
|
||||||
|
|
||||||
|
Alternatively, we can pick off the values one-by-one, if we know the keys:
|
||||||
|
|
||||||
|
```
|
||||||
|
YAML::Node doc; // already parsed
|
||||||
|
std::string name;
|
||||||
|
doc["name"] >> name;
|
||||||
|
int age;
|
||||||
|
doc["age"] >> age;
|
||||||
|
std::cout << "Found entry with name '" << name << "' and age '" << age << "'\n";
|
||||||
|
```
|
||||||
|
|
||||||
|
One thing to be keep in mind: reading a map by key (as immediately above) requires looping through all entries until we find the right key, which is an O(n) operation. So if you're reading the entire map this way, it'll be O(n^2). For small n, this isn't a big deal, but I wouldn't recommend reading maps with a very large number of entries (>100, say) this way.
|
||||||
|
|
||||||
|
## Optional Keys ##
|
||||||
|
|
||||||
|
If you try to access a key that doesn't exist, `yaml-cpp` throws an exception (see [When Something Goes Wrong](https://github.com/jbeder/yaml-cpp/wiki/How-To-Parse-A-Document-(Old-API)#When_Something_Goes_Wrong). If you have optional keys, it's often easier to use `FindValue` instead of `operator[]`:
|
||||||
|
|
||||||
|
```
|
||||||
|
YAML::Node doc; // already parsed
|
||||||
|
if(const YAML::Node *pName = doc.FindValue("name")) {
|
||||||
|
std::string name;
|
||||||
|
*pName >> name;
|
||||||
|
std::cout << "Key 'name' exists, with value '" << name << "'\n";
|
||||||
|
} else {
|
||||||
|
std::cout << "Key 'name' doesn't exist\n";
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
# Getting More Complicated #
|
||||||
|
|
||||||
|
The above three methods can be combined to read from an arbitrary document. But we can make life a lot easier. Suppose we're reading 3-vectors (i.e., vectors with three components), so we've got a structure looking like this:
|
||||||
|
|
||||||
|
```
|
||||||
|
struct Vec3 {
|
||||||
|
float x, y, z;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
We can read this in one operation by overloading the extraction (>>) operator:
|
||||||
|
|
||||||
|
```
|
||||||
|
void operator >> (const YAML::Node& node, Vec3& v)
|
||||||
|
{
|
||||||
|
node[0] >> v.x;
|
||||||
|
node[1] >> v.y;
|
||||||
|
node[2] >> v.z;
|
||||||
|
}
|
||||||
|
|
||||||
|
// now it's a piece of cake to read it
|
||||||
|
YAML::Node doc; // already parsed
|
||||||
|
Vec3 v;
|
||||||
|
doc >> v;
|
||||||
|
std::cout << "Here's the vector: (" << v.x << ", " << v.y << ", " << v.z << ")\n";
|
||||||
|
```
|
||||||
|
|
||||||
|
# A Complete Example #
|
||||||
|
|
||||||
|
Here's a complete example of how to parse a complex YAML file:
|
||||||
|
|
||||||
|
`monsters.yaml`
|
||||||
|
|
||||||
|
```
|
||||||
|
- name: Ogre
|
||||||
|
position: [0, 5, 0]
|
||||||
|
powers:
|
||||||
|
- name: Club
|
||||||
|
damage: 10
|
||||||
|
- name: Fist
|
||||||
|
damage: 8
|
||||||
|
- name: Dragon
|
||||||
|
position: [1, 0, 10]
|
||||||
|
powers:
|
||||||
|
- name: Fire Breath
|
||||||
|
damage: 25
|
||||||
|
- name: Claws
|
||||||
|
damage: 15
|
||||||
|
- name: Wizard
|
||||||
|
position: [5, -3, 0]
|
||||||
|
powers:
|
||||||
|
- name: Acid Rain
|
||||||
|
damage: 50
|
||||||
|
- name: Staff
|
||||||
|
damage: 3
|
||||||
|
```
|
||||||
|
|
||||||
|
`main.cpp`
|
||||||
|
|
||||||
|
```
|
||||||
|
#include "yaml-cpp/yaml.h"
|
||||||
|
#include <iostream>
|
||||||
|
#include <fstream>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
// our data types
|
||||||
|
struct Vec3 {
|
||||||
|
float x, y, z;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Power {
|
||||||
|
std::string name;
|
||||||
|
int damage;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Monster {
|
||||||
|
std::string name;
|
||||||
|
Vec3 position;
|
||||||
|
std::vector <Power> powers;
|
||||||
|
};
|
||||||
|
|
||||||
|
// now the extraction operators for these types
|
||||||
|
void operator >> (const YAML::Node& node, Vec3& v) {
|
||||||
|
node[0] >> v.x;
|
||||||
|
node[1] >> v.y;
|
||||||
|
node[2] >> v.z;
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator >> (const YAML::Node& node, Power& power) {
|
||||||
|
node["name"] >> power.name;
|
||||||
|
node["damage"] >> power.damage;
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator >> (const YAML::Node& node, Monster& monster) {
|
||||||
|
node["name"] >> monster.name;
|
||||||
|
node["position"] >> monster.position;
|
||||||
|
const YAML::Node& powers = node["powers"];
|
||||||
|
for(unsigned i=0;i<powers.size();i++) {
|
||||||
|
Power power;
|
||||||
|
powers[i] >> power;
|
||||||
|
monster.powers.push_back(power);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
std::ifstream fin("monsters.yaml");
|
||||||
|
YAML::Parser parser(fin);
|
||||||
|
YAML::Node doc;
|
||||||
|
parser.GetNextDocument(doc);
|
||||||
|
for(unsigned i=0;i<doc.size();i++) {
|
||||||
|
Monster monster;
|
||||||
|
doc[i] >> monster;
|
||||||
|
std::cout << monster.name << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
# When Something Goes Wrong #
|
||||||
|
|
||||||
|
... we throw an exception (all exceptions are derived from `YAML::Exception`). If there's a parsing exception (i.e., a malformed YAML document), we throw a `YAML::ParserException`:
|
||||||
|
|
||||||
|
```
|
||||||
|
try {
|
||||||
|
std::ifstream fin("test.yaml");
|
||||||
|
YAML::Parser parser(fin);
|
||||||
|
YAML::Node doc;
|
||||||
|
parser.GetNextDocument(doc);
|
||||||
|
// do stuff
|
||||||
|
} catch(YAML::ParserException& e) {
|
||||||
|
std::cout << e.what() << "\n";
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
If you make a programming error (say, trying to read a scalar from a sequence node, or grabbing a key that doesn't exist), we throw some kind of `YAML::RepresentationException`. To prevent this, you can check what kind of node something is:
|
||||||
|
|
||||||
|
```
|
||||||
|
YAML::Node node;
|
||||||
|
YAML::NodeType::value type = node.Type(); // should be:
|
||||||
|
// YAML::NodeType::Null
|
||||||
|
// YAML::NodeType::Scalar
|
||||||
|
// YAML::NodeType::Sequence
|
||||||
|
// YAML::NodeType::Map
|
||||||
|
```
|
||||||
|
|
||||||
|
# Note about copying `YAML::Node` #
|
||||||
|
|
||||||
|
Currently `YAML::Node` is non-copyable, so you need to do something like
|
||||||
|
|
||||||
|
```
|
||||||
|
const YAML::Node& node = doc["whatever"];
|
||||||
|
```
|
||||||
|
|
||||||
|
This is intended behavior. If you want to copy a node, use the `Clone` function:
|
||||||
|
|
||||||
|
```
|
||||||
|
std::auto_ptr<YAML::Node> pCopy = myOtherNode.Clone();
|
||||||
|
```
|
||||||
|
|
||||||
|
The intent is that if you'd like to keep a `YAML::Node` around for longer than the document will stay in scope, you can clone it and store it as long as you like.
|
||||||
18
docs/Strings.md
Normal file
18
docs/Strings.md
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
# Encodings and `yaml-cpp` #
|
||||||
|
|
||||||
|
`yaml-cpp` will parse any file as specified by the [YAML 1.2 spec](http://www.yaml.org/spec/1.2/spec.html#id2570322). Internally, it stores all strings in UTF-8, and representation is done with UTF-8. This means that in
|
||||||
|
|
||||||
|
```
|
||||||
|
std::string str;
|
||||||
|
node >> str;
|
||||||
|
```
|
||||||
|
|
||||||
|
`str` will be UTF-8. Similarly, if you're accessing a map by string key, you need to pass the key in UTF-8. If your application uses a different encoding, you need to convert to and from UTF-8 to work with `yaml-cpp`. (It's possible we'll add some small conversion functions, but for now it's restricted.)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
For convenience, Richard Weeks has kindly provided a google gadget that converts Unicode to a string literal. It's a Google Gadget, so unfortunately it does not work on GitHub. Patches welcome to port it to a usable format here:
|
||||||
|
|
||||||
|
```
|
||||||
|
<wiki:gadget url="http://hosting.gmodules.com/ig/gadgets/file/111180078345548400783/c-style-utf8-encoder.xml"/>
|
||||||
|
```
|
||||||
201
docs/Tutorial.md
Normal file
201
docs/Tutorial.md
Normal file
@@ -0,0 +1,201 @@
|
|||||||
|
# Introduction #
|
||||||
|
|
||||||
|
A typical example, loading a configuration file, might look like this:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
YAML::Node config = YAML::LoadFile("config.yaml");
|
||||||
|
|
||||||
|
if (config["lastLogin"]) {
|
||||||
|
std::cout << "Last logged in: " << config["lastLogin"].as<DateTime>() << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string username = config["username"].as<std::string>();
|
||||||
|
const std::string password = config["password"].as<std::string>();
|
||||||
|
login(username, password);
|
||||||
|
config["lastLogin"] = getCurrentDateTime();
|
||||||
|
|
||||||
|
std::ofstream fout("config.yaml");
|
||||||
|
fout << config;
|
||||||
|
```
|
||||||
|
|
||||||
|
# Basic Parsing and Node Editing #
|
||||||
|
|
||||||
|
All nodes in a YAML document (including the root) are represented by `YAML::Node`. You can check what kind it is:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
YAML::Node node = YAML::Load("[1, 2, 3]");
|
||||||
|
assert(node.Type() == YAML::NodeType::Sequence);
|
||||||
|
assert(node.IsSequence()); // a shortcut!
|
||||||
|
```
|
||||||
|
|
||||||
|
Collection nodes (sequences and maps) act somewhat like STL vectors and maps:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
YAML::Node primes = YAML::Load("[2, 3, 5, 7, 11]");
|
||||||
|
for (std::size_t i=0;i<primes.size();i++) {
|
||||||
|
std::cout << primes[i].as<int>() << "\n";
|
||||||
|
}
|
||||||
|
// or:
|
||||||
|
for (YAML::const_iterator it=primes.begin();it!=primes.end();++it) {
|
||||||
|
std::cout << it->as<int>() << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
primes.push_back(13);
|
||||||
|
assert(primes.size() == 6);
|
||||||
|
```
|
||||||
|
|
||||||
|
and
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
YAML::Node lineup = YAML::Load("{1B: Prince Fielder, 2B: Rickie Weeks, LF: Ryan Braun}");
|
||||||
|
for(YAML::const_iterator it=lineup.begin();it!=lineup.end();++it) {
|
||||||
|
std::cout << "Playing at " << it->first.as<std::string>() << " is " << it->second.as<std::string>() << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
lineup["RF"] = "Corey Hart";
|
||||||
|
lineup["C"] = "Jonathan Lucroy";
|
||||||
|
assert(lineup.size() == 5);
|
||||||
|
```
|
||||||
|
|
||||||
|
Querying for keys does **not** create them automatically (this makes handling optional map entries very easy)
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
YAML::Node node = YAML::Load("{name: Brewers, city: Milwaukee}");
|
||||||
|
if (node["name"]) {
|
||||||
|
std::cout << node["name"].as<std::string>() << "\n";
|
||||||
|
}
|
||||||
|
if (node["mascot"]) {
|
||||||
|
std::cout << node["mascot"].as<std::string>() << "\n";
|
||||||
|
}
|
||||||
|
assert(node.size() == 2); // the previous call didn't create a node
|
||||||
|
```
|
||||||
|
|
||||||
|
If you're not sure what kind of data you're getting, you can query the type of a node:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
switch (node.Type()) {
|
||||||
|
case Null: // ...
|
||||||
|
case Scalar: // ...
|
||||||
|
case Sequence: // ...
|
||||||
|
case Map: // ...
|
||||||
|
case Undefined: // ...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
or ask directly whether it's a particular type, e.g.:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
if (node.IsSequence()) {
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
# Building Nodes #
|
||||||
|
|
||||||
|
You can build `YAML::Node` from scratch:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
YAML::Node node; // starts out as null
|
||||||
|
node["key"] = "value"; // it now is a map node
|
||||||
|
node["seq"].push_back("first element"); // node["seq"] automatically becomes a sequence
|
||||||
|
node["seq"].push_back("second element");
|
||||||
|
|
||||||
|
node["mirror"] = node["seq"][0]; // this creates an alias
|
||||||
|
node["seq"][0] = "1st element"; // this also changes node["mirror"]
|
||||||
|
node["mirror"] = "element #1"; // and this changes node["seq"][0] - they're really the "same" node
|
||||||
|
|
||||||
|
node["self"] = node; // you can even create self-aliases
|
||||||
|
node[node["mirror"]] = node["seq"]; // and strange loops :)
|
||||||
|
```
|
||||||
|
|
||||||
|
The above node is now:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
&1
|
||||||
|
key: value
|
||||||
|
&2 seq: [&3 "element #1", second element]
|
||||||
|
mirror: *3
|
||||||
|
self: *1
|
||||||
|
*3 : *2
|
||||||
|
```
|
||||||
|
|
||||||
|
# How Sequences Turn Into Maps #
|
||||||
|
|
||||||
|
Sequences can be turned into maps by asking for non-integer keys. For example,
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
YAML::Node node = YAML::Load("[1, 2, 3]");
|
||||||
|
node[1] = 5; // still a sequence, [1, 5, 3]
|
||||||
|
node.push_back(-3) // still a sequence, [1, 5, 3, -3]
|
||||||
|
node["key"] = "value"; // now it's a map! {0: 1, 1: 5, 2: 3, 3: -3, key: value}
|
||||||
|
```
|
||||||
|
|
||||||
|
Indexing a sequence node by an index that's not in its range will _usually_ turn it into a map, but if the index is one past the end of the sequence, then the sequence will grow by one to accommodate it. (That's the **only** exception to this rule.) For example,
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
YAML::Node node = YAML::Load("[1, 2, 3]");
|
||||||
|
node[3] = 4; // still a sequence, [1, 2, 3, 4]
|
||||||
|
node[10] = 10; // now it's a map! {0: 1, 1: 2, 2: 3, 3: 4, 10: 10}
|
||||||
|
```
|
||||||
|
|
||||||
|
# Converting To/From Native Data Types #
|
||||||
|
|
||||||
|
Yaml-cpp has built-in conversion to and from most built-in data types, as well as `std::vector`, `std::list`, and `std::map`. The following examples demonstrate when those conversions are used:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
YAML::Node node = YAML::Load("{pi: 3.14159, [0, 1]: integers}");
|
||||||
|
|
||||||
|
// this needs the conversion from Node to double
|
||||||
|
double pi = node["pi"].as<double>();
|
||||||
|
|
||||||
|
// this needs the conversion from double to Node
|
||||||
|
node["e"] = 2.71828;
|
||||||
|
|
||||||
|
// this needs the conversion from Node to std::vector<int> (*not* the other way around!)
|
||||||
|
std::vector<int> v;
|
||||||
|
v.push_back(0);
|
||||||
|
v.push_back(1);
|
||||||
|
std::string str = node[v].as<std::string>();
|
||||||
|
```
|
||||||
|
|
||||||
|
To use yaml-cpp with your own data types, you need to specialize the YAML::convert<> template class. For example, suppose you had a simple `Vec3` class:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
struct Vec3 { double x, y, z; /* etc - make sure you have overloaded operator== */ };
|
||||||
|
```
|
||||||
|
|
||||||
|
You could write
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
namespace YAML {
|
||||||
|
template<>
|
||||||
|
struct convert<Vec3> {
|
||||||
|
static Node encode(const Vec3& rhs) {
|
||||||
|
Node node;
|
||||||
|
node.push_back(rhs.x);
|
||||||
|
node.push_back(rhs.y);
|
||||||
|
node.push_back(rhs.z);
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool decode(const Node& node, Vec3& rhs) {
|
||||||
|
if(!node.IsSequence() || node.size() != 3) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
rhs.x = node[0].as<double>();
|
||||||
|
rhs.y = node[1].as<double>();
|
||||||
|
rhs.z = node[2].as<double>();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Then you could use `Vec3` wherever you could use any other type:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
YAML::Node node = YAML::Load("start: [1, 3, 0]");
|
||||||
|
Vec3 v = node["start"].as<Vec3>();
|
||||||
|
node["end"] = Vec3(2, -1, 0);
|
||||||
|
```
|
||||||
1
docs/_config.yml
Normal file
1
docs/_config.yml
Normal file
@@ -0,0 +1 @@
|
|||||||
|
theme: jekyll-theme-slate
|
||||||
1
docs/index.md
Normal file
1
docs/index.md
Normal file
@@ -0,0 +1 @@
|
|||||||
|
To learn how to use the library, see the [Tutorial](https://github.com/jbeder/yaml-cpp/wiki/Tutorial) and [How To Emit YAML](https://github.com/jbeder/yaml-cpp/wiki/How-To-Emit-YAML)
|
||||||
@@ -10,7 +10,7 @@
|
|||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
|
|
||||||
namespace YAML {
|
namespace YAML {
|
||||||
typedef std::size_t anchor_t;
|
using anchor_t = std::size_t;
|
||||||
const anchor_t NullAnchor = 0;
|
const anchor_t NullAnchor = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,9 +19,13 @@ YAML_CPP_API std::vector<unsigned char> DecodeBase64(const std::string &input);
|
|||||||
|
|
||||||
class YAML_CPP_API Binary {
|
class YAML_CPP_API Binary {
|
||||||
public:
|
public:
|
||||||
Binary() : m_unownedData(0), m_unownedSize(0) {}
|
|
||||||
Binary(const unsigned char *data_, std::size_t size_)
|
Binary(const unsigned char *data_, std::size_t size_)
|
||||||
: m_unownedData(data_), m_unownedSize(size_) {}
|
: m_data{}, m_unownedData(data_), m_unownedSize(size_) {}
|
||||||
|
Binary() : Binary(nullptr, 0) {}
|
||||||
|
Binary(const Binary &) = default;
|
||||||
|
Binary(Binary &&) = default;
|
||||||
|
Binary &operator=(const Binary &) = default;
|
||||||
|
Binary &operator=(Binary &&) = default;
|
||||||
|
|
||||||
bool owned() const { return !m_unownedData; }
|
bool owned() const { return !m_unownedData; }
|
||||||
std::size_t size() const { return owned() ? m_data.size() : m_unownedSize; }
|
std::size_t size() const { return owned() ? m_data.size() : m_unownedSize; }
|
||||||
@@ -35,7 +39,7 @@ class YAML_CPP_API Binary {
|
|||||||
rhs.clear();
|
rhs.clear();
|
||||||
rhs.resize(m_unownedSize);
|
rhs.resize(m_unownedSize);
|
||||||
std::copy(m_unownedData, m_unownedData + m_unownedSize, rhs.begin());
|
std::copy(m_unownedData, m_unownedData + m_unownedSize, rhs.begin());
|
||||||
m_unownedData = 0;
|
m_unownedData = nullptr;
|
||||||
m_unownedSize = 0;
|
m_unownedSize = 0;
|
||||||
} else {
|
} else {
|
||||||
m_data.swap(rhs);
|
m_data.swap(rhs);
|
||||||
@@ -62,6 +66,6 @@ class YAML_CPP_API Binary {
|
|||||||
const unsigned char *m_unownedData;
|
const unsigned char *m_unownedData;
|
||||||
std::size_t m_unownedSize;
|
std::size_t m_unownedSize;
|
||||||
};
|
};
|
||||||
}
|
} // namespace YAML
|
||||||
|
|
||||||
#endif // BASE64_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#endif // BASE64_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|||||||
@@ -12,14 +12,17 @@
|
|||||||
#include "../anchor.h"
|
#include "../anchor.h"
|
||||||
|
|
||||||
namespace YAML {
|
namespace YAML {
|
||||||
/// AnchorDict
|
/**
|
||||||
/// . An object that stores and retrieves values correlating to anchor_t
|
* An object that stores and retrieves values correlating to {@link anchor_t}
|
||||||
/// values.
|
* values.
|
||||||
/// . Efficient implementation that can make assumptions about how anchor_t
|
*
|
||||||
/// values are assigned by the Parser class.
|
* <p>Efficient implementation that can make assumptions about how
|
||||||
|
* {@code anchor_t} values are assigned by the {@link Parser} class.
|
||||||
|
*/
|
||||||
template <class T>
|
template <class T>
|
||||||
class AnchorDict {
|
class AnchorDict {
|
||||||
public:
|
public:
|
||||||
|
AnchorDict() : m_data{} {}
|
||||||
void Register(anchor_t anchor, T value) {
|
void Register(anchor_t anchor, T value) {
|
||||||
if (anchor > m_data.size()) {
|
if (anchor > m_data.size()) {
|
||||||
m_data.resize(anchor);
|
m_data.resize(anchor);
|
||||||
@@ -32,6 +35,6 @@ class AnchorDict {
|
|||||||
private:
|
private:
|
||||||
std::vector<T> m_data;
|
std::vector<T> m_data;
|
||||||
};
|
};
|
||||||
}
|
} // namespace YAML
|
||||||
|
|
||||||
#endif // ANCHORDICT_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#endif // ANCHORDICT_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|||||||
@@ -15,10 +15,12 @@ class Parser;
|
|||||||
|
|
||||||
// GraphBuilderInterface
|
// GraphBuilderInterface
|
||||||
// . Abstraction of node creation
|
// . Abstraction of node creation
|
||||||
// . pParentNode is always NULL or the return value of one of the NewXXX()
|
// . pParentNode is always nullptr or the return value of one of the NewXXX()
|
||||||
// functions.
|
// functions.
|
||||||
class GraphBuilderInterface {
|
class GraphBuilderInterface {
|
||||||
public:
|
public:
|
||||||
|
virtual ~GraphBuilderInterface() = 0;
|
||||||
|
|
||||||
// Create and return a new node with a null value.
|
// Create and return a new node with a null value.
|
||||||
virtual void *NewNull(const Mark &mark, void *pParentNode) = 0;
|
virtual void *NewNull(const Mark &mark, void *pParentNode) = 0;
|
||||||
|
|
||||||
@@ -71,9 +73,9 @@ class GraphBuilder : public GraphBuilderInterface {
|
|||||||
typedef typename Impl::Map Map;
|
typedef typename Impl::Map Map;
|
||||||
|
|
||||||
GraphBuilder(Impl &impl) : m_impl(impl) {
|
GraphBuilder(Impl &impl) : m_impl(impl) {
|
||||||
Map *pMap = NULL;
|
Map *pMap = nullptr;
|
||||||
Sequence *pSeq = NULL;
|
Sequence *pSeq = nullptr;
|
||||||
Node *pNode = NULL;
|
Node *pNode = nullptr;
|
||||||
|
|
||||||
// Type consistency checks
|
// Type consistency checks
|
||||||
pNode = pMap;
|
pNode = pMap;
|
||||||
|
|||||||
77
include/yaml-cpp/depthguard.h
Normal file
77
include/yaml-cpp/depthguard.h
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
#ifndef DEPTH_GUARD_H_00000000000000000000000000000000000000000000000000000000
|
||||||
|
#define DEPTH_GUARD_H_00000000000000000000000000000000000000000000000000000000
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) || \
|
||||||
|
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||||
|
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||||
|
#pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "exceptions.h"
|
||||||
|
|
||||||
|
namespace YAML {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The DeepRecursion class
|
||||||
|
* An exception class which is thrown by DepthGuard. Ideally it should be
|
||||||
|
* a member of DepthGuard. However, DepthGuard is a templated class which means
|
||||||
|
* that any catch points would then need to know the template parameters. It is
|
||||||
|
* simpler for clients to not have to know at the catch point what was the
|
||||||
|
* maximum depth.
|
||||||
|
*/
|
||||||
|
class DeepRecursion : public ParserException {
|
||||||
|
public:
|
||||||
|
virtual ~DeepRecursion() = default;
|
||||||
|
|
||||||
|
DeepRecursion(int depth, const Mark& mark_, const std::string& msg_);
|
||||||
|
|
||||||
|
// Returns the recursion depth when the exception was thrown
|
||||||
|
int depth() const {
|
||||||
|
return m_depth;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
int m_depth = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The DepthGuard class
|
||||||
|
* DepthGuard takes a reference to an integer. It increments the integer upon
|
||||||
|
* construction of DepthGuard and decrements the integer upon destruction.
|
||||||
|
*
|
||||||
|
* If the integer would be incremented past max_depth, then an exception is
|
||||||
|
* thrown. This is ideally geared toward guarding against deep recursion.
|
||||||
|
*
|
||||||
|
* @param max_depth
|
||||||
|
* compile-time configurable maximum depth.
|
||||||
|
*/
|
||||||
|
template <int max_depth = 2000>
|
||||||
|
class DepthGuard final {
|
||||||
|
public:
|
||||||
|
DepthGuard(int & depth_, const Mark& mark_, const std::string& msg_) : m_depth(depth_) {
|
||||||
|
++m_depth;
|
||||||
|
if ( max_depth <= m_depth ) {
|
||||||
|
throw DeepRecursion{m_depth, mark_, msg_};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DepthGuard(const DepthGuard & copy_ctor) = delete;
|
||||||
|
DepthGuard(DepthGuard && move_ctor) = delete;
|
||||||
|
DepthGuard & operator=(const DepthGuard & copy_assign) = delete;
|
||||||
|
DepthGuard & operator=(DepthGuard && move_assign) = delete;
|
||||||
|
|
||||||
|
~DepthGuard() {
|
||||||
|
--m_depth;
|
||||||
|
}
|
||||||
|
|
||||||
|
int current_depth() const {
|
||||||
|
return m_depth;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
int & m_depth;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace YAML
|
||||||
|
|
||||||
|
#endif // DEPTH_GUARD_H_00000000000000000000000000000000000000000000000000000000
|
||||||
@@ -1,37 +1,59 @@
|
|||||||
#ifndef DLL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#ifndef DLL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
#define DLL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#define DLL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|
||||||
#if defined(_MSC_VER) || \
|
// Definition YAML_CPP_STATIC_DEFINE using to building YAML-CPP as static
|
||||||
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
// library (definition created by CMake or defined manually)
|
||||||
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
|
||||||
#pragma once
|
// Definition yaml_cpp_EXPORTS using to building YAML-CPP as dll/so library
|
||||||
|
// (definition created by CMake or defined manually)
|
||||||
|
|
||||||
|
#ifdef YAML_CPP_STATIC_DEFINE
|
||||||
|
# define YAML_CPP_API
|
||||||
|
# define YAML_CPP_NO_EXPORT
|
||||||
|
#else
|
||||||
|
# if defined(_MSC_VER) || defined(__MINGW32__) || defined(__MINGW64__)
|
||||||
|
# ifndef YAML_CPP_API
|
||||||
|
# ifdef yaml_cpp_EXPORTS
|
||||||
|
/* We are building this library */
|
||||||
|
# define YAML_CPP_API __declspec(dllexport)
|
||||||
|
# else
|
||||||
|
/* We are using this library */
|
||||||
|
# define YAML_CPP_API __declspec(dllimport)
|
||||||
|
# endif
|
||||||
|
# endif
|
||||||
|
# ifndef YAML_CPP_NO_EXPORT
|
||||||
|
# define YAML_CPP_NO_EXPORT
|
||||||
|
# endif
|
||||||
|
# else /* No _MSC_VER */
|
||||||
|
# ifndef YAML_CPP_API
|
||||||
|
# ifdef yaml_cpp_EXPORTS
|
||||||
|
/* We are building this library */
|
||||||
|
# define YAML_CPP_API __attribute__((visibility("default")))
|
||||||
|
# else
|
||||||
|
/* We are using this library */
|
||||||
|
# define YAML_CPP_API __attribute__((visibility("default")))
|
||||||
|
# endif
|
||||||
|
# endif
|
||||||
|
# ifndef YAML_CPP_NO_EXPORT
|
||||||
|
# define YAML_CPP_NO_EXPORT __attribute__((visibility("hidden")))
|
||||||
|
# endif
|
||||||
|
# endif /* _MSC_VER */
|
||||||
|
#endif /* YAML_CPP_STATIC_DEFINE */
|
||||||
|
|
||||||
|
#ifndef YAML_CPP_DEPRECATED
|
||||||
|
# ifdef _MSC_VER
|
||||||
|
# define YAML_CPP_DEPRECATED __declspec(deprecated)
|
||||||
|
# else
|
||||||
|
# define YAML_CPP_DEPRECATED __attribute__ ((__deprecated__))
|
||||||
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// The following ifdef block is the standard way of creating macros which make
|
#ifndef YAML_CPP_DEPRECATED_EXPORT
|
||||||
// exporting
|
# define YAML_CPP_DEPRECATED_EXPORT YAML_CPP_API YAML_CPP_DEPRECATED
|
||||||
// from a DLL simpler. All files within this DLL are compiled with the
|
#endif
|
||||||
// yaml_cpp_EXPORTS
|
|
||||||
// symbol defined on the command line. this symbol should not be defined on any
|
|
||||||
// project
|
|
||||||
// that uses this DLL. This way any other project whose source files include
|
|
||||||
// this file see
|
|
||||||
// YAML_CPP_API functions as being imported from a DLL, whereas this DLL sees
|
|
||||||
// symbols
|
|
||||||
// defined with this macro as being exported.
|
|
||||||
#undef YAML_CPP_API
|
|
||||||
|
|
||||||
#ifdef YAML_CPP_DLL // Using or Building YAML-CPP DLL (definition defined
|
#ifndef YAML_CPP_DEPRECATED_NO_EXPORT
|
||||||
// manually)
|
# define YAML_CPP_DEPRECATED_NO_EXPORT YAML_CPP_NO_EXPORT YAML_CPP_DEPRECATED
|
||||||
#ifdef yaml_cpp_EXPORTS // Building YAML-CPP DLL (definition created by CMake
|
#endif
|
||||||
// or defined manually)
|
|
||||||
// #pragma message( "Defining YAML_CPP_API for DLL export" )
|
|
||||||
#define YAML_CPP_API __declspec(dllexport)
|
|
||||||
#else // yaml_cpp_EXPORTS
|
|
||||||
// #pragma message( "Defining YAML_CPP_API for DLL import" )
|
|
||||||
#define YAML_CPP_API __declspec(dllimport)
|
|
||||||
#endif // yaml_cpp_EXPORTS
|
|
||||||
#else // YAML_CPP_DLL
|
|
||||||
#define YAML_CPP_API
|
|
||||||
#endif // YAML_CPP_DLL
|
|
||||||
|
|
||||||
#endif // DLL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#endif /* DLL_H_62B23520_7C8E_11DE_8A39_0800200C9A66 */
|
||||||
|
|||||||
@@ -23,22 +23,23 @@ class Emitter;
|
|||||||
class EmitFromEvents : public EventHandler {
|
class EmitFromEvents : public EventHandler {
|
||||||
public:
|
public:
|
||||||
EmitFromEvents(Emitter& emitter);
|
EmitFromEvents(Emitter& emitter);
|
||||||
|
~EmitFromEvents() override = default;
|
||||||
|
|
||||||
virtual void OnDocumentStart(const Mark& mark);
|
void OnDocumentStart(const Mark& mark) override;
|
||||||
virtual void OnDocumentEnd();
|
void OnDocumentEnd() override;
|
||||||
|
|
||||||
virtual void OnNull(const Mark& mark, anchor_t anchor);
|
void OnNull(const Mark& mark, anchor_t anchor) override;
|
||||||
virtual void OnAlias(const Mark& mark, anchor_t anchor);
|
void OnAlias(const Mark& mark, anchor_t anchor) override;
|
||||||
virtual void OnScalar(const Mark& mark, const std::string& tag,
|
void OnScalar(const Mark& mark, const std::string& tag,
|
||||||
anchor_t anchor, const std::string& value);
|
anchor_t anchor, const std::string& value) override;
|
||||||
|
|
||||||
virtual void OnSequenceStart(const Mark& mark, const std::string& tag,
|
void OnSequenceStart(const Mark& mark, const std::string& tag,
|
||||||
anchor_t anchor, EmitterStyle::value style);
|
anchor_t anchor, EmitterStyle::value style) override;
|
||||||
virtual void OnSequenceEnd();
|
void OnSequenceEnd() override;
|
||||||
|
|
||||||
virtual void OnMapStart(const Mark& mark, const std::string& tag,
|
void OnMapStart(const Mark& mark, const std::string& tag,
|
||||||
anchor_t anchor, EmitterStyle::value style);
|
anchor_t anchor, EmitterStyle::value style) override;
|
||||||
virtual void OnMapEnd();
|
void OnMapEnd() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void BeginNode();
|
void BeginNode();
|
||||||
|
|||||||
@@ -7,18 +7,26 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
|
#include <cstring>
|
||||||
|
#include <limits>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
#if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || __cplusplus >= 201703L)
|
||||||
|
#include <string_view>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "yaml-cpp/binary.h"
|
#include "yaml-cpp/binary.h"
|
||||||
#include "yaml-cpp/dll.h"
|
#include "yaml-cpp/dll.h"
|
||||||
#include "yaml-cpp/emitterdef.h"
|
#include "yaml-cpp/emitterdef.h"
|
||||||
#include "yaml-cpp/emittermanip.h"
|
#include "yaml-cpp/emittermanip.h"
|
||||||
#include "yaml-cpp/noncopyable.h"
|
|
||||||
#include "yaml-cpp/null.h"
|
#include "yaml-cpp/null.h"
|
||||||
#include "yaml-cpp/ostream_wrapper.h"
|
#include "yaml-cpp/ostream_wrapper.h"
|
||||||
|
#include "yaml-cpp/fptostring.h"
|
||||||
|
|
||||||
namespace YAML {
|
namespace YAML {
|
||||||
class Binary;
|
class Binary;
|
||||||
@@ -28,10 +36,12 @@ struct _Null;
|
|||||||
namespace YAML {
|
namespace YAML {
|
||||||
class EmitterState;
|
class EmitterState;
|
||||||
|
|
||||||
class YAML_CPP_API Emitter : private noncopyable {
|
class YAML_CPP_API Emitter {
|
||||||
public:
|
public:
|
||||||
Emitter();
|
Emitter();
|
||||||
explicit Emitter(std::ostream& stream);
|
explicit Emitter(std::ostream& stream);
|
||||||
|
Emitter(const Emitter&) = delete;
|
||||||
|
Emitter& operator=(const Emitter&) = delete;
|
||||||
~Emitter();
|
~Emitter();
|
||||||
|
|
||||||
// output
|
// output
|
||||||
@@ -46,6 +56,7 @@ class YAML_CPP_API Emitter : private noncopyable {
|
|||||||
bool SetOutputCharset(EMITTER_MANIP value);
|
bool SetOutputCharset(EMITTER_MANIP value);
|
||||||
bool SetStringFormat(EMITTER_MANIP value);
|
bool SetStringFormat(EMITTER_MANIP value);
|
||||||
bool SetBoolFormat(EMITTER_MANIP value);
|
bool SetBoolFormat(EMITTER_MANIP value);
|
||||||
|
bool SetNullFormat(EMITTER_MANIP value);
|
||||||
bool SetIntBase(EMITTER_MANIP value);
|
bool SetIntBase(EMITTER_MANIP value);
|
||||||
bool SetSeqFormat(EMITTER_MANIP value);
|
bool SetSeqFormat(EMITTER_MANIP value);
|
||||||
bool SetMapFormat(EMITTER_MANIP value);
|
bool SetMapFormat(EMITTER_MANIP value);
|
||||||
@@ -54,6 +65,7 @@ class YAML_CPP_API Emitter : private noncopyable {
|
|||||||
bool SetPostCommentIndent(std::size_t n);
|
bool SetPostCommentIndent(std::size_t n);
|
||||||
bool SetFloatPrecision(std::size_t n);
|
bool SetFloatPrecision(std::size_t n);
|
||||||
bool SetDoublePrecision(std::size_t n);
|
bool SetDoublePrecision(std::size_t n);
|
||||||
|
void RestoreGlobalModifiedSettings();
|
||||||
|
|
||||||
// local setters
|
// local setters
|
||||||
Emitter& SetLocalValue(EMITTER_MANIP value);
|
Emitter& SetLocalValue(EMITTER_MANIP value);
|
||||||
@@ -61,6 +73,7 @@ class YAML_CPP_API Emitter : private noncopyable {
|
|||||||
Emitter& SetLocalPrecision(const _Precision& precision);
|
Emitter& SetLocalPrecision(const _Precision& precision);
|
||||||
|
|
||||||
// overloads of write
|
// overloads of write
|
||||||
|
Emitter& Write(const char* str, std::size_t size);
|
||||||
Emitter& Write(const std::string& str);
|
Emitter& Write(const std::string& str);
|
||||||
Emitter& Write(bool b);
|
Emitter& Write(bool b);
|
||||||
Emitter& Write(char ch);
|
Emitter& Write(char ch);
|
||||||
@@ -119,10 +132,11 @@ class YAML_CPP_API Emitter : private noncopyable {
|
|||||||
void SpaceOrIndentTo(bool requireSpace, std::size_t indent);
|
void SpaceOrIndentTo(bool requireSpace, std::size_t indent);
|
||||||
|
|
||||||
const char* ComputeFullBoolName(bool b) const;
|
const char* ComputeFullBoolName(bool b) const;
|
||||||
|
const char* ComputeNullName() const;
|
||||||
bool CanEmitNewline() const;
|
bool CanEmitNewline() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::auto_ptr<EmitterState> m_pState;
|
std::unique_ptr<EmitterState> m_pState;
|
||||||
ostream_wrapper m_stream;
|
ostream_wrapper m_stream;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -134,6 +148,7 @@ inline Emitter& Emitter::WriteIntegralType(T value) {
|
|||||||
PrepareNode(EmitterNodeType::Scalar);
|
PrepareNode(EmitterNodeType::Scalar);
|
||||||
|
|
||||||
std::stringstream stream;
|
std::stringstream stream;
|
||||||
|
stream.imbue(std::locale::classic());
|
||||||
PrepareIntegralStream(stream);
|
PrepareIntegralStream(stream);
|
||||||
stream << value;
|
stream << value;
|
||||||
m_stream << stream.str();
|
m_stream << stream.str();
|
||||||
@@ -151,8 +166,29 @@ inline Emitter& Emitter::WriteStreamable(T value) {
|
|||||||
PrepareNode(EmitterNodeType::Scalar);
|
PrepareNode(EmitterNodeType::Scalar);
|
||||||
|
|
||||||
std::stringstream stream;
|
std::stringstream stream;
|
||||||
|
stream.imbue(std::locale::classic());
|
||||||
SetStreamablePrecision<T>(stream);
|
SetStreamablePrecision<T>(stream);
|
||||||
stream << value;
|
|
||||||
|
bool special = false;
|
||||||
|
if (std::is_floating_point<T>::value) {
|
||||||
|
if ((std::numeric_limits<T>::has_quiet_NaN ||
|
||||||
|
std::numeric_limits<T>::has_signaling_NaN) &&
|
||||||
|
std::isnan(value)) {
|
||||||
|
special = true;
|
||||||
|
stream << ".nan";
|
||||||
|
} else if (std::numeric_limits<T>::has_infinity && std::isinf(value)) {
|
||||||
|
special = true;
|
||||||
|
if (std::signbit(value)) {
|
||||||
|
stream << "-.inf";
|
||||||
|
} else {
|
||||||
|
stream << ".inf";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!special) {
|
||||||
|
stream << FpToString(value, stream.precision());
|
||||||
|
}
|
||||||
m_stream << stream.str();
|
m_stream << stream.str();
|
||||||
|
|
||||||
StartedScalar();
|
StartedScalar();
|
||||||
@@ -162,17 +198,22 @@ inline Emitter& Emitter::WriteStreamable(T value) {
|
|||||||
|
|
||||||
template <>
|
template <>
|
||||||
inline void Emitter::SetStreamablePrecision<float>(std::stringstream& stream) {
|
inline void Emitter::SetStreamablePrecision<float>(std::stringstream& stream) {
|
||||||
stream.precision(GetFloatPrecision());
|
stream.precision(static_cast<std::streamsize>(GetFloatPrecision()));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
inline void Emitter::SetStreamablePrecision<double>(std::stringstream& stream) {
|
inline void Emitter::SetStreamablePrecision<double>(std::stringstream& stream) {
|
||||||
stream.precision(GetDoublePrecision());
|
stream.precision(static_cast<std::streamsize>(GetDoublePrecision()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// overloads of insertion
|
// overloads of insertion
|
||||||
|
#if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || __cplusplus >= 201703L)
|
||||||
|
inline Emitter& operator<<(Emitter& emitter, const std::string_view& v) {
|
||||||
|
return emitter.Write(v.data(), v.size());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
inline Emitter& operator<<(Emitter& emitter, const std::string& v) {
|
inline Emitter& operator<<(Emitter& emitter, const std::string& v) {
|
||||||
return emitter.Write(v);
|
return emitter.Write(v.data(), v.size());
|
||||||
}
|
}
|
||||||
inline Emitter& operator<<(Emitter& emitter, bool v) {
|
inline Emitter& operator<<(Emitter& emitter, bool v) {
|
||||||
return emitter.Write(v);
|
return emitter.Write(v);
|
||||||
@@ -203,7 +244,7 @@ inline Emitter& operator<<(Emitter& emitter, const Binary& b) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline Emitter& operator<<(Emitter& emitter, const char* v) {
|
inline Emitter& operator<<(Emitter& emitter, const char* v) {
|
||||||
return emitter.Write(std::string(v));
|
return emitter.Write(v, std::strlen(v));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Emitter& operator<<(Emitter& emitter, int v) {
|
inline Emitter& operator<<(Emitter& emitter, int v) {
|
||||||
@@ -249,6 +290,6 @@ inline Emitter& operator<<(Emitter& emitter, _Indent indent) {
|
|||||||
inline Emitter& operator<<(Emitter& emitter, _Precision precision) {
|
inline Emitter& operator<<(Emitter& emitter, _Precision precision) {
|
||||||
return emitter.SetLocalPrecision(precision);
|
return emitter.SetLocalPrecision(precision);
|
||||||
}
|
}
|
||||||
}
|
} // namespace YAML
|
||||||
|
|
||||||
#endif // EMITTER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#endif // EMITTER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ enum EMITTER_MANIP {
|
|||||||
// output character set
|
// output character set
|
||||||
EmitNonAscii,
|
EmitNonAscii,
|
||||||
EscapeNonAscii,
|
EscapeNonAscii,
|
||||||
|
EscapeAsJson,
|
||||||
|
|
||||||
// string manipulators
|
// string manipulators
|
||||||
// Auto, // duplicate
|
// Auto, // duplicate
|
||||||
@@ -26,6 +27,12 @@ enum EMITTER_MANIP {
|
|||||||
DoubleQuoted,
|
DoubleQuoted,
|
||||||
Literal,
|
Literal,
|
||||||
|
|
||||||
|
// null manipulators
|
||||||
|
LowerNull,
|
||||||
|
UpperNull,
|
||||||
|
CamelNull,
|
||||||
|
TildeNull,
|
||||||
|
|
||||||
// bool manipulators
|
// bool manipulators
|
||||||
YesNoBool, // yes, no
|
YesNoBool, // yes, no
|
||||||
TrueFalseBool, // true, false
|
TrueFalseBool, // true, false
|
||||||
@@ -74,14 +81,14 @@ struct _Alias {
|
|||||||
std::string content;
|
std::string content;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline _Alias Alias(const std::string content) { return _Alias(content); }
|
inline _Alias Alias(const std::string& content) { return _Alias(content); }
|
||||||
|
|
||||||
struct _Anchor {
|
struct _Anchor {
|
||||||
_Anchor(const std::string& content_) : content(content_) {}
|
_Anchor(const std::string& content_) : content(content_) {}
|
||||||
std::string content;
|
std::string content;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline _Anchor Anchor(const std::string content) { return _Anchor(content); }
|
inline _Anchor Anchor(const std::string& content) { return _Anchor(content); }
|
||||||
|
|
||||||
struct _Tag {
|
struct _Tag {
|
||||||
struct Type {
|
struct Type {
|
||||||
@@ -96,11 +103,11 @@ struct _Tag {
|
|||||||
Type::value type;
|
Type::value type;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline _Tag VerbatimTag(const std::string content) {
|
inline _Tag VerbatimTag(const std::string& content) {
|
||||||
return _Tag("", content, _Tag::Type::Verbatim);
|
return _Tag("", content, _Tag::Type::Verbatim);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline _Tag LocalTag(const std::string content) {
|
inline _Tag LocalTag(const std::string& content) {
|
||||||
return _Tag("", content, _Tag::Type::PrimaryHandle);
|
return _Tag("", content, _Tag::Type::PrimaryHandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,7 +115,7 @@ inline _Tag LocalTag(const std::string& prefix, const std::string content) {
|
|||||||
return _Tag(prefix, content, _Tag::Type::NamedHandle);
|
return _Tag(prefix, content, _Tag::Type::NamedHandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline _Tag SecondaryTag(const std::string content) {
|
inline _Tag SecondaryTag(const std::string& content) {
|
||||||
return _Tag("", content, _Tag::Type::NamedHandle);
|
return _Tag("", content, _Tag::Type::NamedHandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -117,7 +124,7 @@ struct _Comment {
|
|||||||
std::string content;
|
std::string content;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline _Comment Comment(const std::string content) { return _Comment(content); }
|
inline _Comment Comment(const std::string& content) { return _Comment(content); }
|
||||||
|
|
||||||
struct _Precision {
|
struct _Precision {
|
||||||
_Precision(int floatPrecision_, int doublePrecision_)
|
_Precision(int floatPrecision_, int doublePrecision_)
|
||||||
|
|||||||
@@ -8,9 +8,10 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace YAML {
|
namespace YAML {
|
||||||
struct EmitterStyle {
|
namespace EmitterStyle {
|
||||||
enum value { Default, Block, Flow };
|
enum value { Default, Block, Flow };
|
||||||
};
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // EMITTERSTYLE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#endif // EMITTERSTYLE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ struct Mark;
|
|||||||
|
|
||||||
class EventHandler {
|
class EventHandler {
|
||||||
public:
|
public:
|
||||||
virtual ~EventHandler() {}
|
virtual ~EventHandler() = default;
|
||||||
|
|
||||||
virtual void OnDocumentStart(const Mark& mark) = 0;
|
virtual void OnDocumentStart(const Mark& mark) = 0;
|
||||||
virtual void OnDocumentEnd() = 0;
|
virtual void OnDocumentEnd() = 0;
|
||||||
@@ -34,7 +34,12 @@ class EventHandler {
|
|||||||
virtual void OnMapStart(const Mark& mark, const std::string& tag,
|
virtual void OnMapStart(const Mark& mark, const std::string& tag,
|
||||||
anchor_t anchor, EmitterStyle::value style) = 0;
|
anchor_t anchor, EmitterStyle::value style) = 0;
|
||||||
virtual void OnMapEnd() = 0;
|
virtual void OnMapEnd() = 0;
|
||||||
|
|
||||||
|
virtual void OnAnchor(const Mark& /*mark*/,
|
||||||
|
const std::string& /*anchor_name*/) {
|
||||||
|
// empty default implementation for compatibility
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
} // namespace YAML
|
||||||
|
|
||||||
#endif // EVENTHANDLER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#endif // EVENTHANDLER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|||||||
@@ -8,10 +8,11 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "yaml-cpp/mark.h"
|
#include "yaml-cpp/mark.h"
|
||||||
|
#include "yaml-cpp/noexcept.h"
|
||||||
#include "yaml-cpp/traits.h"
|
#include "yaml-cpp/traits.h"
|
||||||
|
#include <sstream>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <sstream>
|
|
||||||
|
|
||||||
namespace YAML {
|
namespace YAML {
|
||||||
// error messages
|
// error messages
|
||||||
@@ -47,6 +48,8 @@ const char* const UNKNOWN_TOKEN = "unknown token";
|
|||||||
const char* const DOC_IN_SCALAR = "illegal document indicator in scalar";
|
const char* const DOC_IN_SCALAR = "illegal document indicator in scalar";
|
||||||
const char* const EOF_IN_SCALAR = "illegal EOF in scalar";
|
const char* const EOF_IN_SCALAR = "illegal EOF in scalar";
|
||||||
const char* const CHAR_IN_SCALAR = "illegal character in scalar";
|
const char* const CHAR_IN_SCALAR = "illegal character in scalar";
|
||||||
|
const char* const UNEXPECTED_SCALAR = "unexpected scalar";
|
||||||
|
const char* const UNEXPECTED_FLOW = "plain value cannot start with flow indicator character";
|
||||||
const char* const TAB_IN_INDENTATION =
|
const char* const TAB_IN_INDENTATION =
|
||||||
"illegal tab when looking for indentation";
|
"illegal tab when looking for indentation";
|
||||||
const char* const FLOW_END = "illegal flow end";
|
const char* const FLOW_END = "illegal flow end";
|
||||||
@@ -64,7 +67,7 @@ const char* const ZERO_INDENT_IN_BLOCK =
|
|||||||
const char* const CHAR_IN_BLOCK = "unexpected character in block scalar";
|
const char* const CHAR_IN_BLOCK = "unexpected character in block scalar";
|
||||||
const char* const AMBIGUOUS_ANCHOR =
|
const char* const AMBIGUOUS_ANCHOR =
|
||||||
"cannot assign the same alias to multiple nodes";
|
"cannot assign the same alias to multiple nodes";
|
||||||
const char* const UNKNOWN_ANCHOR = "the referenced anchor is not defined";
|
const char* const UNKNOWN_ANCHOR = "the referenced anchor is not defined: ";
|
||||||
|
|
||||||
const char* const INVALID_NODE =
|
const char* const INVALID_NODE =
|
||||||
"invalid node; this may result from using a map iterator as a sequence "
|
"invalid node; this may result from using a map iterator as a sequence "
|
||||||
@@ -89,7 +92,7 @@ const char* const BAD_FILE = "bad file";
|
|||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline const std::string KEY_NOT_FOUND_WITH_KEY(
|
inline const std::string KEY_NOT_FOUND_WITH_KEY(
|
||||||
const T&, typename disable_if<is_numeric<T> >::type* = 0) {
|
const T&, typename disable_if<is_numeric<T>>::type* = 0) {
|
||||||
return KEY_NOT_FOUND;
|
return KEY_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,20 +102,63 @@ inline const std::string KEY_NOT_FOUND_WITH_KEY(const std::string& key) {
|
|||||||
return stream.str();
|
return stream.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
inline const std::string KEY_NOT_FOUND_WITH_KEY(const char* key) {
|
||||||
inline const std::string KEY_NOT_FOUND_WITH_KEY(
|
|
||||||
const T& key, typename enable_if<is_numeric<T> >::type* = 0) {
|
|
||||||
std::stringstream stream;
|
std::stringstream stream;
|
||||||
stream << KEY_NOT_FOUND << ": " << key;
|
stream << KEY_NOT_FOUND << ": " << key;
|
||||||
return stream.str();
|
return stream.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline const std::string KEY_NOT_FOUND_WITH_KEY(
|
||||||
|
const T& key, typename enable_if<is_numeric<T>>::type* = 0) {
|
||||||
|
std::stringstream stream;
|
||||||
|
stream << KEY_NOT_FOUND << ": " << key;
|
||||||
|
return stream.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
class Exception : public std::runtime_error {
|
template <typename T>
|
||||||
|
inline const std::string BAD_SUBSCRIPT_WITH_KEY(
|
||||||
|
const T&, typename disable_if<is_numeric<T>>::type* = nullptr) {
|
||||||
|
return BAD_SUBSCRIPT;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const std::string BAD_SUBSCRIPT_WITH_KEY(const std::string& key) {
|
||||||
|
std::stringstream stream;
|
||||||
|
stream << BAD_SUBSCRIPT << " (key: \"" << key << "\")";
|
||||||
|
return stream.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const std::string BAD_SUBSCRIPT_WITH_KEY(const char* key) {
|
||||||
|
std::stringstream stream;
|
||||||
|
stream << BAD_SUBSCRIPT << " (key: \"" << key << "\")";
|
||||||
|
return stream.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline const std::string BAD_SUBSCRIPT_WITH_KEY(
|
||||||
|
const T& key, typename enable_if<is_numeric<T>>::type* = nullptr) {
|
||||||
|
std::stringstream stream;
|
||||||
|
stream << BAD_SUBSCRIPT << " (key: \"" << key << "\")";
|
||||||
|
return stream.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const std::string INVALID_NODE_WITH_KEY(const std::string& key) {
|
||||||
|
std::stringstream stream;
|
||||||
|
if (key.empty()) {
|
||||||
|
return INVALID_NODE;
|
||||||
|
}
|
||||||
|
stream << "invalid node; first invalid key: \"" << key << "\"";
|
||||||
|
return stream.str();
|
||||||
|
}
|
||||||
|
} // namespace ErrorMsg
|
||||||
|
|
||||||
|
class YAML_CPP_API Exception : public std::runtime_error {
|
||||||
public:
|
public:
|
||||||
Exception(const Mark& mark_, const std::string& msg_)
|
Exception(const Mark& mark_, const std::string& msg_)
|
||||||
: std::runtime_error(build_what(mark_, msg_)), mark(mark_), msg(msg_) {}
|
: std::runtime_error(build_what(mark_, msg_)), mark(mark_), msg(msg_) {}
|
||||||
virtual ~Exception() throw() {}
|
~Exception() YAML_CPP_NOEXCEPT override;
|
||||||
|
|
||||||
|
Exception(const Exception&) = default;
|
||||||
|
|
||||||
Mark mark;
|
Mark mark;
|
||||||
std::string msg;
|
std::string msg;
|
||||||
@@ -120,6 +166,10 @@ class Exception : public std::runtime_error {
|
|||||||
private:
|
private:
|
||||||
static const std::string build_what(const Mark& mark,
|
static const std::string build_what(const Mark& mark,
|
||||||
const std::string& msg) {
|
const std::string& msg) {
|
||||||
|
if (mark.is_null()) {
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
|
||||||
std::stringstream output;
|
std::stringstream output;
|
||||||
output << "yaml-cpp: error at line " << mark.line + 1 << ", column "
|
output << "yaml-cpp: error at line " << mark.line + 1 << ", column "
|
||||||
<< mark.column + 1 << ": " << msg;
|
<< mark.column + 1 << ": " << msg;
|
||||||
@@ -127,39 +177,47 @@ class Exception : public std::runtime_error {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class ParserException : public Exception {
|
class YAML_CPP_API ParserException : public Exception {
|
||||||
public:
|
public:
|
||||||
ParserException(const Mark& mark_, const std::string& msg_)
|
ParserException(const Mark& mark_, const std::string& msg_)
|
||||||
: Exception(mark_, msg_) {}
|
: Exception(mark_, msg_) {}
|
||||||
|
ParserException(const ParserException&) = default;
|
||||||
|
~ParserException() YAML_CPP_NOEXCEPT override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class RepresentationException : public Exception {
|
class YAML_CPP_API RepresentationException : public Exception {
|
||||||
public:
|
public:
|
||||||
RepresentationException(const Mark& mark_, const std::string& msg_)
|
RepresentationException(const Mark& mark_, const std::string& msg_)
|
||||||
: Exception(mark_, msg_) {}
|
: Exception(mark_, msg_) {}
|
||||||
|
RepresentationException(const RepresentationException&) = default;
|
||||||
|
~RepresentationException() YAML_CPP_NOEXCEPT override;
|
||||||
};
|
};
|
||||||
|
|
||||||
// representation exceptions
|
// representation exceptions
|
||||||
class InvalidScalar : public RepresentationException {
|
class YAML_CPP_API InvalidScalar : public RepresentationException {
|
||||||
public:
|
public:
|
||||||
InvalidScalar(const Mark& mark_)
|
InvalidScalar(const Mark& mark_)
|
||||||
: RepresentationException(mark_, ErrorMsg::INVALID_SCALAR) {}
|
: RepresentationException(mark_, ErrorMsg::INVALID_SCALAR) {}
|
||||||
|
InvalidScalar(const InvalidScalar&) = default;
|
||||||
|
~InvalidScalar() YAML_CPP_NOEXCEPT override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class KeyNotFound : public RepresentationException {
|
class YAML_CPP_API KeyNotFound : public RepresentationException {
|
||||||
public:
|
public:
|
||||||
template <typename T>
|
template <typename T>
|
||||||
KeyNotFound(const Mark& mark_, const T& key_)
|
KeyNotFound(const Mark& mark_, const T& key_)
|
||||||
: RepresentationException(mark_, ErrorMsg::KEY_NOT_FOUND_WITH_KEY(key_)) {
|
: RepresentationException(mark_, ErrorMsg::KEY_NOT_FOUND_WITH_KEY(key_)) {
|
||||||
}
|
}
|
||||||
|
KeyNotFound(const KeyNotFound&) = default;
|
||||||
|
~KeyNotFound() YAML_CPP_NOEXCEPT override;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class TypedKeyNotFound : public KeyNotFound {
|
class YAML_CPP_API TypedKeyNotFound : public KeyNotFound {
|
||||||
public:
|
public:
|
||||||
TypedKeyNotFound(const Mark& mark_, const T& key_)
|
TypedKeyNotFound(const Mark& mark_, const T& key_)
|
||||||
: KeyNotFound(mark_, key_), key(key_) {}
|
: KeyNotFound(mark_, key_), key(key_) {}
|
||||||
virtual ~TypedKeyNotFound() throw() {}
|
~TypedKeyNotFound() YAML_CPP_NOEXCEPT override = default;
|
||||||
|
|
||||||
T key;
|
T key;
|
||||||
};
|
};
|
||||||
@@ -170,58 +228,78 @@ inline TypedKeyNotFound<T> MakeTypedKeyNotFound(const Mark& mark,
|
|||||||
return TypedKeyNotFound<T>(mark, key);
|
return TypedKeyNotFound<T>(mark, key);
|
||||||
}
|
}
|
||||||
|
|
||||||
class InvalidNode : public RepresentationException {
|
class YAML_CPP_API InvalidNode : public RepresentationException {
|
||||||
public:
|
public:
|
||||||
InvalidNode()
|
InvalidNode(const std::string& key)
|
||||||
: RepresentationException(Mark::null_mark(), ErrorMsg::INVALID_NODE) {}
|
: RepresentationException(Mark::null_mark(),
|
||||||
|
ErrorMsg::INVALID_NODE_WITH_KEY(key)) {}
|
||||||
|
InvalidNode(const InvalidNode&) = default;
|
||||||
|
~InvalidNode() YAML_CPP_NOEXCEPT override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class BadConversion : public RepresentationException {
|
class YAML_CPP_API BadConversion : public RepresentationException {
|
||||||
public:
|
public:
|
||||||
BadConversion()
|
explicit BadConversion(const Mark& mark_)
|
||||||
: RepresentationException(Mark::null_mark(), ErrorMsg::BAD_CONVERSION) {}
|
: RepresentationException(mark_, ErrorMsg::BAD_CONVERSION) {}
|
||||||
|
BadConversion(const BadConversion&) = default;
|
||||||
|
~BadConversion() YAML_CPP_NOEXCEPT override;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class TypedBadConversion : public BadConversion {
|
class TypedBadConversion : public BadConversion {
|
||||||
public:
|
public:
|
||||||
TypedBadConversion() : BadConversion() {}
|
explicit TypedBadConversion(const Mark& mark_) : BadConversion(mark_) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
class BadDereference : public RepresentationException {
|
class YAML_CPP_API BadDereference : public RepresentationException {
|
||||||
public:
|
public:
|
||||||
BadDereference()
|
BadDereference()
|
||||||
: RepresentationException(Mark::null_mark(), ErrorMsg::BAD_DEREFERENCE) {}
|
: RepresentationException(Mark::null_mark(), ErrorMsg::BAD_DEREFERENCE) {}
|
||||||
|
BadDereference(const BadDereference&) = default;
|
||||||
|
~BadDereference() YAML_CPP_NOEXCEPT override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class BadSubscript : public RepresentationException {
|
class YAML_CPP_API BadSubscript : public RepresentationException {
|
||||||
public:
|
public:
|
||||||
BadSubscript()
|
template <typename Key>
|
||||||
: RepresentationException(Mark::null_mark(), ErrorMsg::BAD_SUBSCRIPT) {}
|
BadSubscript(const Mark& mark_, const Key& key)
|
||||||
|
: RepresentationException(mark_, ErrorMsg::BAD_SUBSCRIPT_WITH_KEY(key)) {}
|
||||||
|
BadSubscript(const BadSubscript&) = default;
|
||||||
|
~BadSubscript() YAML_CPP_NOEXCEPT override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class BadPushback : public RepresentationException {
|
class YAML_CPP_API BadPushback : public RepresentationException {
|
||||||
public:
|
public:
|
||||||
BadPushback()
|
BadPushback()
|
||||||
: RepresentationException(Mark::null_mark(), ErrorMsg::BAD_PUSHBACK) {}
|
: RepresentationException(Mark::null_mark(), ErrorMsg::BAD_PUSHBACK) {}
|
||||||
|
BadPushback(const BadPushback&) = default;
|
||||||
|
~BadPushback() YAML_CPP_NOEXCEPT override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class BadInsert : public RepresentationException {
|
class YAML_CPP_API BadInsert : public RepresentationException {
|
||||||
public:
|
public:
|
||||||
BadInsert()
|
BadInsert()
|
||||||
: RepresentationException(Mark::null_mark(), ErrorMsg::BAD_INSERT) {}
|
: RepresentationException(Mark::null_mark(), ErrorMsg::BAD_INSERT) {}
|
||||||
|
BadInsert(const BadInsert&) = default;
|
||||||
|
~BadInsert() YAML_CPP_NOEXCEPT override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class EmitterException : public Exception {
|
class YAML_CPP_API EmitterException : public Exception {
|
||||||
public:
|
public:
|
||||||
EmitterException(const std::string& msg_)
|
EmitterException(const std::string& msg_)
|
||||||
: Exception(Mark::null_mark(), msg_) {}
|
: Exception(Mark::null_mark(), msg_) {}
|
||||||
|
EmitterException(const EmitterException&) = default;
|
||||||
|
~EmitterException() YAML_CPP_NOEXCEPT override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class BadFile : public Exception {
|
class YAML_CPP_API BadFile : public Exception {
|
||||||
public:
|
public:
|
||||||
BadFile() : Exception(Mark::null_mark(), ErrorMsg::BAD_FILE) {}
|
explicit BadFile(const std::string& filename)
|
||||||
|
: Exception(Mark::null_mark(),
|
||||||
|
std::string(ErrorMsg::BAD_FILE) + ": " + filename) {}
|
||||||
|
BadFile(const BadFile&) = default;
|
||||||
|
~BadFile() YAML_CPP_NOEXCEPT override;
|
||||||
};
|
};
|
||||||
}
|
} // namespace YAML
|
||||||
|
|
||||||
#endif // EXCEPTIONS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#endif // EXCEPTIONS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|||||||
15
include/yaml-cpp/fptostring.h
Normal file
15
include/yaml-cpp/fptostring.h
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
#ifndef YAML_H_FPTOSTRING
|
||||||
|
#define YAML_H_FPTOSTRING
|
||||||
|
|
||||||
|
#include "yaml-cpp/dll.h"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace YAML {
|
||||||
|
// "precision = 0" refers to shortest known unique representation of the value
|
||||||
|
YAML_CPP_API std::string FpToString(float v, size_t precision = 0);
|
||||||
|
YAML_CPP_API std::string FpToString(double v, size_t precision = 0);
|
||||||
|
YAML_CPP_API std::string FpToString(long double v, size_t precision = 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -15,6 +15,8 @@ struct YAML_CPP_API Mark {
|
|||||||
|
|
||||||
static const Mark null_mark() { return Mark(-1, -1, -1); }
|
static const Mark null_mark() { return Mark(-1, -1, -1); }
|
||||||
|
|
||||||
|
bool is_null() const { return pos == -1 && line == -1 && column == -1; }
|
||||||
|
|
||||||
int pos;
|
int pos;
|
||||||
int line, column;
|
int line, column;
|
||||||
|
|
||||||
|
|||||||
@@ -7,18 +7,29 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
#include <cmath>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <unordered_map>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include <type_traits>
|
||||||
|
#include <valarray>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || __cplusplus >= 201703L)
|
||||||
|
#include <string_view>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "yaml-cpp/binary.h"
|
#include "yaml-cpp/binary.h"
|
||||||
#include "yaml-cpp/node/impl.h"
|
#include "yaml-cpp/node/impl.h"
|
||||||
#include "yaml-cpp/node/iterator.h"
|
#include "yaml-cpp/node/iterator.h"
|
||||||
#include "yaml-cpp/node/node.h"
|
#include "yaml-cpp/node/node.h"
|
||||||
#include "yaml-cpp/node/type.h"
|
#include "yaml-cpp/node/type.h"
|
||||||
#include "yaml-cpp/null.h"
|
#include "yaml-cpp/null.h"
|
||||||
|
#include "yaml-cpp/fptostring.h"
|
||||||
|
|
||||||
|
|
||||||
namespace YAML {
|
namespace YAML {
|
||||||
class Binary;
|
class Binary;
|
||||||
@@ -43,6 +54,17 @@ inline bool IsNaN(const std::string& input) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Node
|
||||||
|
template <>
|
||||||
|
struct convert<Node> {
|
||||||
|
static Node encode(const Node& rhs) { return rhs; }
|
||||||
|
|
||||||
|
static bool decode(const Node& node, Node& rhs) {
|
||||||
|
rhs.reset(node);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// std::string
|
// std::string
|
||||||
template <>
|
template <>
|
||||||
struct convert<std::string> {
|
struct convert<std::string> {
|
||||||
@@ -59,14 +81,33 @@ struct convert<std::string> {
|
|||||||
// C-strings can only be encoded
|
// C-strings can only be encoded
|
||||||
template <>
|
template <>
|
||||||
struct convert<const char*> {
|
struct convert<const char*> {
|
||||||
static Node encode(const char*& rhs) { return Node(rhs); }
|
static Node encode(const char* rhs) { return Node(rhs); }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct convert<char*> {
|
||||||
|
static Node encode(const char* rhs) { return Node(rhs); }
|
||||||
};
|
};
|
||||||
|
|
||||||
template <std::size_t N>
|
template <std::size_t N>
|
||||||
struct convert<const char[N]> {
|
struct convert<char[N]> {
|
||||||
static Node encode(const char(&rhs)[N]) { return Node(rhs); }
|
static Node encode(const char* rhs) { return Node(rhs); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || __cplusplus >= 201703L)
|
||||||
|
template <>
|
||||||
|
struct convert<std::string_view> {
|
||||||
|
static Node encode(std::string_view rhs) { return Node(std::string(rhs)); }
|
||||||
|
|
||||||
|
static bool decode(const Node& node, std::string_view& rhs) {
|
||||||
|
if (!node.IsScalar())
|
||||||
|
return false;
|
||||||
|
rhs = node.Scalar();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct convert<_Null> {
|
struct convert<_Null> {
|
||||||
static Node encode(const _Null& /* rhs */) { return Node(); }
|
static Node encode(const _Null& /* rhs */) { return Node(); }
|
||||||
@@ -76,42 +117,100 @@ struct convert<_Null> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#define YAML_DEFINE_CONVERT_STREAMABLE(type, negative_op) \
|
namespace conversion {
|
||||||
template <> \
|
template <typename T>
|
||||||
struct convert<type> { \
|
typename std::enable_if< std::is_floating_point<T>::value, void>::type
|
||||||
static Node encode(const type& rhs) { \
|
inner_encode(const T& rhs, std::stringstream& stream){
|
||||||
std::stringstream stream; \
|
if (std::isnan(rhs)) {
|
||||||
stream.precision(std::numeric_limits<type>::digits10 + 1); \
|
stream << ".nan";
|
||||||
stream << rhs; \
|
} else if (std::isinf(rhs)) {
|
||||||
return Node(stream.str()); \
|
if (std::signbit(rhs)) {
|
||||||
} \
|
stream << "-.inf";
|
||||||
\
|
} else {
|
||||||
static bool decode(const Node& node, type& rhs) { \
|
stream << ".inf";
|
||||||
if (node.Type() != NodeType::Scalar) \
|
}
|
||||||
return false; \
|
} else {
|
||||||
const std::string& input = node.Scalar(); \
|
stream << FpToString(rhs, stream.precision());
|
||||||
std::stringstream stream(input); \
|
}
|
||||||
stream.unsetf(std::ios::dec); \
|
}
|
||||||
if ((stream >> std::noskipws >> rhs) && (stream >> std::ws).eof()) \
|
|
||||||
return true; \
|
template <typename T>
|
||||||
if (std::numeric_limits<type>::has_infinity) { \
|
typename std::enable_if<!std::is_floating_point<T>::value, void>::type
|
||||||
if (conversion::IsInfinity(input)) { \
|
inner_encode(const T& rhs, std::stringstream& stream){
|
||||||
rhs = std::numeric_limits<type>::infinity(); \
|
stream << rhs;
|
||||||
return true; \
|
}
|
||||||
} else if (conversion::IsNegativeInfinity(input)) { \
|
|
||||||
rhs = negative_op std::numeric_limits<type>::infinity(); \
|
template <typename T>
|
||||||
return true; \
|
typename std::enable_if<(std::is_same<T, unsigned char>::value ||
|
||||||
} \
|
std::is_same<T, signed char>::value), bool>::type
|
||||||
} \
|
ConvertStreamTo(std::stringstream& stream, T& rhs) {
|
||||||
\
|
int num;
|
||||||
if (std::numeric_limits<type>::has_quiet_NaN && \
|
if ((stream >> std::noskipws >> num) && (stream >> std::ws).eof()) {
|
||||||
conversion::IsNaN(input)) { \
|
if (num >= (std::numeric_limits<T>::min)() &&
|
||||||
rhs = std::numeric_limits<type>::quiet_NaN(); \
|
num <= (std::numeric_limits<T>::max)()) {
|
||||||
return true; \
|
rhs = static_cast<T>(num);
|
||||||
} \
|
return true;
|
||||||
\
|
}
|
||||||
return false; \
|
}
|
||||||
} \
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
typename std::enable_if<!(std::is_same<T, unsigned char>::value ||
|
||||||
|
std::is_same<T, signed char>::value), bool>::type
|
||||||
|
ConvertStreamTo(std::stringstream& stream, T& rhs) {
|
||||||
|
if ((stream >> std::noskipws >> rhs) && (stream >> std::ws).eof()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define YAML_DEFINE_CONVERT_STREAMABLE(type, negative_op) \
|
||||||
|
template <> \
|
||||||
|
struct convert<type> { \
|
||||||
|
\
|
||||||
|
static Node encode(const type& rhs) { \
|
||||||
|
std::stringstream stream; \
|
||||||
|
stream.imbue(std::locale::classic()); \
|
||||||
|
stream.precision(std::numeric_limits<type>::max_digits10); \
|
||||||
|
conversion::inner_encode(rhs, stream); \
|
||||||
|
return Node(stream.str()); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
static bool decode(const Node& node, type& rhs) { \
|
||||||
|
if (node.Type() != NodeType::Scalar) { \
|
||||||
|
return false; \
|
||||||
|
} \
|
||||||
|
const std::string& input = node.Scalar(); \
|
||||||
|
std::stringstream stream(input); \
|
||||||
|
stream.imbue(std::locale::classic()); \
|
||||||
|
stream.unsetf(std::ios::dec); \
|
||||||
|
if ((stream.peek() == '-') && std::is_unsigned<type>::value) { \
|
||||||
|
return false; \
|
||||||
|
} \
|
||||||
|
if (conversion::ConvertStreamTo(stream, rhs)) { \
|
||||||
|
return true; \
|
||||||
|
} \
|
||||||
|
if (std::numeric_limits<type>::has_infinity) { \
|
||||||
|
if (conversion::IsInfinity(input)) { \
|
||||||
|
rhs = std::numeric_limits<type>::infinity(); \
|
||||||
|
return true; \
|
||||||
|
} else if (conversion::IsNegativeInfinity(input)) { \
|
||||||
|
rhs = negative_op std::numeric_limits<type>::infinity(); \
|
||||||
|
return true; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
if (std::numeric_limits<type>::has_quiet_NaN) { \
|
||||||
|
if (conversion::IsNaN(input)) { \
|
||||||
|
rhs = std::numeric_limits<type>::quiet_NaN(); \
|
||||||
|
return true; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
return false; \
|
||||||
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(type) \
|
#define YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(type) \
|
||||||
@@ -150,89 +249,176 @@ struct convert<bool> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// std::map
|
// std::map
|
||||||
template <typename K, typename V>
|
template <typename K, typename V, typename C, typename A>
|
||||||
struct convert<std::map<K, V> > {
|
struct convert<std::map<K, V, C, A>> {
|
||||||
static Node encode(const std::map<K, V>& rhs) {
|
static Node encode(const std::map<K, V, C, A>& rhs) {
|
||||||
Node node(NodeType::Map);
|
Node node(NodeType::Map);
|
||||||
for (typename std::map<K, V>::const_iterator it = rhs.begin();
|
for (const auto& element : rhs)
|
||||||
it != rhs.end(); ++it)
|
node.force_insert(element.first, element.second);
|
||||||
node.force_insert(it->first, it->second);
|
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool decode(const Node& node, std::map<K, V>& rhs) {
|
static bool decode(const Node& node, std::map<K, V, C, A>& rhs) {
|
||||||
if (!node.IsMap())
|
if (!node.IsMap())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
rhs.clear();
|
rhs.clear();
|
||||||
for (const_iterator it = node.begin(); it != node.end(); ++it)
|
for (const auto& element : node)
|
||||||
#if defined(__GNUC__) && __GNUC__ < 4
|
#if defined(__GNUC__) && __GNUC__ < 4
|
||||||
// workaround for GCC 3:
|
// workaround for GCC 3:
|
||||||
rhs[it->first.template as<K>()] = it->second.template as<V>();
|
rhs[element.first.template as<K>()] = element.second.template as<V>();
|
||||||
#else
|
#else
|
||||||
rhs[it->first.as<K>()] = it->second.as<V>();
|
rhs[element.first.as<K>()] = element.second.as<V>();
|
||||||
|
#endif
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// std::unordered_map
|
||||||
|
template <typename K, typename V, typename H, typename P, typename A>
|
||||||
|
struct convert<std::unordered_map<K, V, H, P, A>> {
|
||||||
|
static Node encode(const std::unordered_map<K, V, H, P, A>& rhs) {
|
||||||
|
Node node(NodeType::Map);
|
||||||
|
for (const auto& element : rhs)
|
||||||
|
node.force_insert(element.first, element.second);
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool decode(const Node& node, std::unordered_map<K, V, H, P, A>& rhs) {
|
||||||
|
if (!node.IsMap())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
rhs.clear();
|
||||||
|
for (const auto& element : node)
|
||||||
|
#if defined(__GNUC__) && __GNUC__ < 4
|
||||||
|
// workaround for GCC 3:
|
||||||
|
rhs[element.first.template as<K>()] = element.second.template as<V>();
|
||||||
|
#else
|
||||||
|
rhs[element.first.as<K>()] = element.second.as<V>();
|
||||||
#endif
|
#endif
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// std::vector
|
// std::vector
|
||||||
template <typename T>
|
template <typename T, typename A>
|
||||||
struct convert<std::vector<T> > {
|
struct convert<std::vector<T, A>> {
|
||||||
static Node encode(const std::vector<T>& rhs) {
|
static Node encode(const std::vector<T, A>& rhs) {
|
||||||
Node node(NodeType::Sequence);
|
Node node(NodeType::Sequence);
|
||||||
for (typename std::vector<T>::const_iterator it = rhs.begin();
|
for (const auto& element : rhs)
|
||||||
it != rhs.end(); ++it)
|
node.push_back(element);
|
||||||
node.push_back(*it);
|
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool decode(const Node& node, std::vector<T>& rhs) {
|
static bool decode(const Node& node, std::vector<T, A>& rhs) {
|
||||||
if (!node.IsSequence())
|
if (!node.IsSequence())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
rhs.clear();
|
rhs.clear();
|
||||||
for (const_iterator it = node.begin(); it != node.end(); ++it)
|
for (const auto& element : node)
|
||||||
#if defined(__GNUC__) && __GNUC__ < 4
|
#if defined(__GNUC__) && __GNUC__ < 4
|
||||||
// workaround for GCC 3:
|
// workaround for GCC 3:
|
||||||
rhs.push_back(it->template as<T>());
|
rhs.push_back(element.template as<T>());
|
||||||
#else
|
#else
|
||||||
rhs.push_back(it->as<T>());
|
rhs.push_back(element.as<T>());
|
||||||
#endif
|
#endif
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// std::list
|
// std::list
|
||||||
template <typename T>
|
template <typename T, typename A>
|
||||||
struct convert<std::list<T> > {
|
struct convert<std::list<T,A>> {
|
||||||
static Node encode(const std::list<T>& rhs) {
|
static Node encode(const std::list<T,A>& rhs) {
|
||||||
Node node(NodeType::Sequence);
|
Node node(NodeType::Sequence);
|
||||||
for (typename std::list<T>::const_iterator it = rhs.begin();
|
for (const auto& element : rhs)
|
||||||
it != rhs.end(); ++it)
|
node.push_back(element);
|
||||||
node.push_back(*it);
|
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool decode(const Node& node, std::list<T>& rhs) {
|
static bool decode(const Node& node, std::list<T,A>& rhs) {
|
||||||
if (!node.IsSequence())
|
if (!node.IsSequence())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
rhs.clear();
|
rhs.clear();
|
||||||
for (const_iterator it = node.begin(); it != node.end(); ++it)
|
for (const auto& element : node)
|
||||||
#if defined(__GNUC__) && __GNUC__ < 4
|
#if defined(__GNUC__) && __GNUC__ < 4
|
||||||
// workaround for GCC 3:
|
// workaround for GCC 3:
|
||||||
rhs.push_back(it->template as<T>());
|
rhs.push_back(element.template as<T>());
|
||||||
#else
|
#else
|
||||||
rhs.push_back(it->as<T>());
|
rhs.push_back(element.as<T>());
|
||||||
#endif
|
#endif
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// std::array
|
||||||
|
template <typename T, std::size_t N>
|
||||||
|
struct convert<std::array<T, N>> {
|
||||||
|
static Node encode(const std::array<T, N>& rhs) {
|
||||||
|
Node node(NodeType::Sequence);
|
||||||
|
for (const auto& element : rhs) {
|
||||||
|
node.push_back(element);
|
||||||
|
}
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool decode(const Node& node, std::array<T, N>& rhs) {
|
||||||
|
if (!isNodeValid(node)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto i = 0u; i < node.size(); ++i) {
|
||||||
|
#if defined(__GNUC__) && __GNUC__ < 4
|
||||||
|
// workaround for GCC 3:
|
||||||
|
rhs[i] = node[i].template as<T>();
|
||||||
|
#else
|
||||||
|
rhs[i] = node[i].as<T>();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
static bool isNodeValid(const Node& node) {
|
||||||
|
return node.IsSequence() && node.size() == N;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// std::valarray
|
||||||
|
template <typename T>
|
||||||
|
struct convert<std::valarray<T>> {
|
||||||
|
static Node encode(const std::valarray<T>& rhs) {
|
||||||
|
Node node(NodeType::Sequence);
|
||||||
|
for (const auto& element : rhs) {
|
||||||
|
node.push_back(element);
|
||||||
|
}
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool decode(const Node& node, std::valarray<T>& rhs) {
|
||||||
|
if (!node.IsSequence()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
rhs.resize(node.size());
|
||||||
|
for (auto i = 0u; i < node.size(); ++i) {
|
||||||
|
#if defined(__GNUC__) && __GNUC__ < 4
|
||||||
|
// workaround for GCC 3:
|
||||||
|
rhs[i] = node[i].template as<T>();
|
||||||
|
#else
|
||||||
|
rhs[i] = node[i].as<T>();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
// std::pair
|
// std::pair
|
||||||
template <typename T, typename U>
|
template <typename T, typename U>
|
||||||
struct convert<std::pair<T, U> > {
|
struct convert<std::pair<T, U>> {
|
||||||
static Node encode(const std::pair<T, U>& rhs) {
|
static Node encode(const std::pair<T, U>& rhs) {
|
||||||
Node node(NodeType::Sequence);
|
Node node(NodeType::Sequence);
|
||||||
node.push_back(rhs.first);
|
node.push_back(rhs.first);
|
||||||
|
|||||||
@@ -1,26 +0,0 @@
|
|||||||
#ifndef NODE_DETAIL_BOOL_TYPE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
|
||||||
#define NODE_DETAIL_BOOL_TYPE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
|
||||||
|
|
||||||
#if defined(_MSC_VER) || \
|
|
||||||
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
|
||||||
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
|
||||||
#pragma once
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace YAML {
|
|
||||||
namespace detail {
|
|
||||||
struct unspecified_bool {
|
|
||||||
struct NOT_ALLOWED;
|
|
||||||
static void true_value(NOT_ALLOWED*) {}
|
|
||||||
};
|
|
||||||
typedef void (*unspecified_bool_type)(unspecified_bool::NOT_ALLOWED*);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#define YAML_CPP_OPERATOR_BOOL() \
|
|
||||||
operator YAML::detail::unspecified_bool_type() const { \
|
|
||||||
return this->operator!() ? 0 \
|
|
||||||
: &YAML::detail::unspecified_bool::true_value; \
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // NODE_DETAIL_BOOL_TYPE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
|
||||||
@@ -9,7 +9,9 @@
|
|||||||
|
|
||||||
#include "yaml-cpp/node/detail/node.h"
|
#include "yaml-cpp/node/detail/node.h"
|
||||||
#include "yaml-cpp/node/detail/node_data.h"
|
#include "yaml-cpp/node/detail/node_data.h"
|
||||||
#include <boost/type_traits.hpp>
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
namespace YAML {
|
namespace YAML {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
@@ -17,23 +19,23 @@ template <typename Key, typename Enable = void>
|
|||||||
struct get_idx {
|
struct get_idx {
|
||||||
static node* get(const std::vector<node*>& /* sequence */,
|
static node* get(const std::vector<node*>& /* sequence */,
|
||||||
const Key& /* key */, shared_memory_holder /* pMemory */) {
|
const Key& /* key */, shared_memory_holder /* pMemory */) {
|
||||||
return 0;
|
return nullptr;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Key>
|
template <typename Key>
|
||||||
struct get_idx<
|
struct get_idx<Key,
|
||||||
Key, typename boost::enable_if_c<boost::is_unsigned<Key>::value &&
|
typename std::enable_if<std::is_unsigned<Key>::value &&
|
||||||
!boost::is_same<Key, bool>::value>::type> {
|
!std::is_same<Key, bool>::value>::type> {
|
||||||
static node* get(const std::vector<node*>& sequence, const Key& key,
|
static node* get(const std::vector<node*>& sequence, const Key& key,
|
||||||
shared_memory_holder /* pMemory */) {
|
shared_memory_holder /* pMemory */) {
|
||||||
return key < sequence.size() ? sequence[key] : 0;
|
return key < sequence.size() ? sequence[key] : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static node* get(std::vector<node*>& sequence, const Key& key,
|
static node* get(std::vector<node*>& sequence, const Key& key,
|
||||||
shared_memory_holder pMemory) {
|
shared_memory_holder pMemory) {
|
||||||
if (key > sequence.size())
|
if (key > sequence.size() || (key > 0 && !sequence[key - 1]->is_defined()))
|
||||||
return 0;
|
return nullptr;
|
||||||
if (key == sequence.size())
|
if (key == sequence.size())
|
||||||
sequence.push_back(&pMemory->create_node());
|
sequence.push_back(&pMemory->create_node());
|
||||||
return sequence[key];
|
return sequence[key];
|
||||||
@@ -41,18 +43,56 @@ struct get_idx<
|
|||||||
};
|
};
|
||||||
|
|
||||||
template <typename Key>
|
template <typename Key>
|
||||||
struct get_idx<Key, typename boost::enable_if<boost::is_signed<Key> >::type> {
|
struct get_idx<Key, typename std::enable_if<std::is_signed<Key>::value>::type> {
|
||||||
static node* get(const std::vector<node*>& sequence, const Key& key,
|
static node* get(const std::vector<node*>& sequence, const Key& key,
|
||||||
shared_memory_holder pMemory) {
|
shared_memory_holder pMemory) {
|
||||||
return key >= 0 ? get_idx<std::size_t>::get(
|
return key >= 0 ? get_idx<std::size_t>::get(
|
||||||
sequence, static_cast<std::size_t>(key), pMemory)
|
sequence, static_cast<std::size_t>(key), pMemory)
|
||||||
: 0;
|
: nullptr;
|
||||||
}
|
}
|
||||||
static node* get(std::vector<node*>& sequence, const Key& key,
|
static node* get(std::vector<node*>& sequence, const Key& key,
|
||||||
shared_memory_holder pMemory) {
|
shared_memory_holder pMemory) {
|
||||||
return key >= 0 ? get_idx<std::size_t>::get(
|
return key >= 0 ? get_idx<std::size_t>::get(
|
||||||
sequence, static_cast<std::size_t>(key), pMemory)
|
sequence, static_cast<std::size_t>(key), pMemory)
|
||||||
: 0;
|
: nullptr;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Key, typename Enable = void>
|
||||||
|
struct remove_idx {
|
||||||
|
static bool remove(std::vector<node*>&, const Key&, std::size_t&) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Key>
|
||||||
|
struct remove_idx<
|
||||||
|
Key, typename std::enable_if<std::is_unsigned<Key>::value &&
|
||||||
|
!std::is_same<Key, bool>::value>::type> {
|
||||||
|
|
||||||
|
static bool remove(std::vector<node*>& sequence, const Key& key,
|
||||||
|
std::size_t& seqSize) {
|
||||||
|
if (key >= sequence.size()) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
sequence.erase(sequence.begin() + key);
|
||||||
|
if (seqSize > key) {
|
||||||
|
--seqSize;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Key>
|
||||||
|
struct remove_idx<Key,
|
||||||
|
typename std::enable_if<std::is_signed<Key>::value>::type> {
|
||||||
|
|
||||||
|
static bool remove(std::vector<node*>& sequence, const Key& key,
|
||||||
|
std::size_t& seqSize) {
|
||||||
|
return key >= 0 ? remove_idx<std::size_t>::remove(
|
||||||
|
sequence, static_cast<std::size_t>(key), seqSize)
|
||||||
|
: false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -66,7 +106,11 @@ inline bool node::equals(const T& rhs, shared_memory_holder pMemory) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline bool node::equals(const char* rhs, shared_memory_holder pMemory) {
|
inline bool node::equals(const char* rhs, shared_memory_holder pMemory) {
|
||||||
return equals<std::string>(rhs, pMemory);
|
std::string lhs;
|
||||||
|
if (convert<std::string>::decode(Node(*this, std::move(pMemory)), lhs)) {
|
||||||
|
return lhs == rhs;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// indexing
|
// indexing
|
||||||
@@ -78,22 +122,20 @@ inline node* node_data::get(const Key& key,
|
|||||||
break;
|
break;
|
||||||
case NodeType::Undefined:
|
case NodeType::Undefined:
|
||||||
case NodeType::Null:
|
case NodeType::Null:
|
||||||
return NULL;
|
return nullptr;
|
||||||
case NodeType::Sequence:
|
case NodeType::Sequence:
|
||||||
if (node* pNode = get_idx<Key>::get(m_sequence, key, pMemory))
|
if (node* pNode = get_idx<Key>::get(m_sequence, key, pMemory))
|
||||||
return pNode;
|
return pNode;
|
||||||
return NULL;
|
return nullptr;
|
||||||
case NodeType::Scalar:
|
case NodeType::Scalar:
|
||||||
throw BadSubscript();
|
throw BadSubscript(m_mark, key);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (node_map::const_iterator it = m_map.begin(); it != m_map.end(); ++it) {
|
auto it = std::find_if(m_map.begin(), m_map.end(), [&](const kv_pair m) {
|
||||||
if (it->first->equals(key, pMemory)) {
|
return m.first->equals(key, pMemory);
|
||||||
return it->second;
|
});
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
return it != m_map.end() ? it->second : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Key>
|
template <typename Key>
|
||||||
@@ -112,13 +154,15 @@ inline node& node_data::get(const Key& key, shared_memory_holder pMemory) {
|
|||||||
convert_to_map(pMemory);
|
convert_to_map(pMemory);
|
||||||
break;
|
break;
|
||||||
case NodeType::Scalar:
|
case NodeType::Scalar:
|
||||||
throw BadSubscript();
|
throw BadSubscript(m_mark, key);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (node_map::const_iterator it = m_map.begin(); it != m_map.end(); ++it) {
|
auto it = std::find_if(m_map.begin(), m_map.end(), [&](const kv_pair m) {
|
||||||
if (it->first->equals(key, pMemory)) {
|
return m.first->equals(key, pMemory);
|
||||||
return *it->second;
|
});
|
||||||
}
|
|
||||||
|
if (it != m_map.end()) {
|
||||||
|
return *it->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
node& k = convert_to_node(key, pMemory);
|
node& k = convert_to_node(key, pMemory);
|
||||||
@@ -129,12 +173,26 @@ inline node& node_data::get(const Key& key, shared_memory_holder pMemory) {
|
|||||||
|
|
||||||
template <typename Key>
|
template <typename Key>
|
||||||
inline bool node_data::remove(const Key& key, shared_memory_holder pMemory) {
|
inline bool node_data::remove(const Key& key, shared_memory_holder pMemory) {
|
||||||
if (m_type != NodeType::Map)
|
if (m_type == NodeType::Sequence) {
|
||||||
return false;
|
return remove_idx<Key>::remove(m_sequence, key, m_seqSize);
|
||||||
|
}
|
||||||
|
|
||||||
for (node_map::iterator it = m_map.begin(); it != m_map.end(); ++it) {
|
if (m_type == NodeType::Map) {
|
||||||
if (equals(*it->first, key, pMemory)) {
|
kv_pairs::iterator it = m_undefinedPairs.begin();
|
||||||
m_map.erase(it);
|
while (it != m_undefinedPairs.end()) {
|
||||||
|
kv_pairs::iterator jt = std::next(it);
|
||||||
|
if (it->first->equals(key, pMemory)) {
|
||||||
|
m_undefinedPairs.erase(it);
|
||||||
|
}
|
||||||
|
it = jt;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto iter = std::find_if(m_map.begin(), m_map.end(), [&](const kv_pair m) {
|
||||||
|
return m.first->equals(key, pMemory);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (iter != m_map.end()) {
|
||||||
|
m_map.erase(iter);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,47 +8,75 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "yaml-cpp/dll.h"
|
#include "yaml-cpp/dll.h"
|
||||||
#include "yaml-cpp/node/ptr.h"
|
|
||||||
#include "yaml-cpp/node/detail/node_iterator.h"
|
#include "yaml-cpp/node/detail/node_iterator.h"
|
||||||
#include <boost/iterator/iterator_adaptor.hpp>
|
#include "yaml-cpp/node/node.h"
|
||||||
#include <boost/utility.hpp>
|
#include "yaml-cpp/node/ptr.h"
|
||||||
|
#include <cstddef>
|
||||||
|
#include <iterator>
|
||||||
|
|
||||||
|
|
||||||
namespace YAML {
|
namespace YAML {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
struct iterator_value;
|
struct iterator_value;
|
||||||
|
|
||||||
template <typename V>
|
template <typename V>
|
||||||
class iterator_base
|
class iterator_base {
|
||||||
: public boost::iterator_adaptor<iterator_base<V>, node_iterator, V,
|
|
||||||
std::forward_iterator_tag, V> {
|
|
||||||
private:
|
private:
|
||||||
template <typename>
|
template <typename>
|
||||||
friend class iterator_base;
|
friend class iterator_base;
|
||||||
struct enabler {};
|
struct enabler {};
|
||||||
typedef typename iterator_base::base_type base_type;
|
using base_type = node_iterator;
|
||||||
|
|
||||||
|
struct proxy {
|
||||||
|
explicit proxy(const V& x) : m_ref(x) {}
|
||||||
|
V* operator->() { return std::addressof(m_ref); }
|
||||||
|
operator V*() { return std::addressof(m_ref); }
|
||||||
|
|
||||||
|
V m_ref;
|
||||||
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef typename iterator_base::value_type value_type;
|
using iterator_category = std::forward_iterator_tag;
|
||||||
|
using value_type = V;
|
||||||
|
using difference_type = std::ptrdiff_t;
|
||||||
|
using pointer = V*;
|
||||||
|
using reference = V&;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
iterator_base() {}
|
iterator_base() : m_iterator(), m_pMemory() {}
|
||||||
explicit iterator_base(base_type rhs, shared_memory_holder pMemory)
|
explicit iterator_base(base_type rhs, shared_memory_holder pMemory)
|
||||||
: iterator_base::iterator_adaptor_(rhs), m_pMemory(pMemory) {}
|
: m_iterator(rhs), m_pMemory(pMemory) {}
|
||||||
|
|
||||||
template <class W>
|
template <class W>
|
||||||
iterator_base(const iterator_base<W>& rhs,
|
iterator_base(const iterator_base<W>& rhs,
|
||||||
typename boost::enable_if<boost::is_convertible<W*, V*>,
|
typename std::enable_if<std::is_convertible<W*, V*>::value,
|
||||||
enabler>::type = enabler())
|
enabler>::type = enabler())
|
||||||
: iterator_base::iterator_adaptor_(rhs.base()),
|
: m_iterator(rhs.m_iterator), m_pMemory(rhs.m_pMemory) {}
|
||||||
m_pMemory(rhs.m_pMemory) {}
|
|
||||||
|
|
||||||
private:
|
iterator_base<V>& operator++() {
|
||||||
friend class boost::iterator_core_access;
|
++m_iterator;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
void increment() { this->base_reference() = boost::next(this->base()); }
|
iterator_base<V> operator++(int) {
|
||||||
|
iterator_base<V> iterator_pre(*this);
|
||||||
|
++(*this);
|
||||||
|
return iterator_pre;
|
||||||
|
}
|
||||||
|
|
||||||
value_type dereference() const {
|
template <typename W>
|
||||||
const typename base_type::value_type& v = *this->base();
|
bool operator==(const iterator_base<W>& rhs) const {
|
||||||
|
return m_iterator == rhs.m_iterator;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename W>
|
||||||
|
bool operator!=(const iterator_base<W>& rhs) const {
|
||||||
|
return m_iterator != rhs.m_iterator;
|
||||||
|
}
|
||||||
|
|
||||||
|
value_type operator*() const {
|
||||||
|
const typename base_type::value_type& v = *m_iterator;
|
||||||
if (v.pNode)
|
if (v.pNode)
|
||||||
return value_type(Node(*v, m_pMemory));
|
return value_type(Node(*v, m_pMemory));
|
||||||
if (v.first && v.second)
|
if (v.first && v.second)
|
||||||
@@ -56,10 +84,13 @@ class iterator_base
|
|||||||
return value_type();
|
return value_type();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
proxy operator->() const { return proxy(**this); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
base_type m_iterator;
|
||||||
shared_memory_holder m_pMemory;
|
shared_memory_holder m_pMemory;
|
||||||
};
|
};
|
||||||
}
|
} // namespace detail
|
||||||
}
|
} // namespace YAML
|
||||||
|
|
||||||
#endif // VALUE_DETAIL_ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#endif // VALUE_DETAIL_ITERATOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|||||||
@@ -13,7 +13,6 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace YAML {
|
namespace YAML {
|
||||||
class node;
|
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
struct iterator_value;
|
struct iterator_value;
|
||||||
@@ -21,8 +20,8 @@ template <typename V>
|
|||||||
class iterator_base;
|
class iterator_base;
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef detail::iterator_base<detail::iterator_value> iterator;
|
using iterator = detail::iterator_base<detail::iterator_value>;
|
||||||
typedef detail::iterator_base<const detail::iterator_value> const_iterator;
|
using const_iterator = detail::iterator_base<const detail::iterator_value>;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // VALUE_DETAIL_ITERATOR_FWD_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#endif // VALUE_DETAIL_ITERATOR_FWD_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|||||||
@@ -7,8 +7,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <boost/shared_ptr.hpp>
|
|
||||||
#include <boost/smart_ptr/shared_ptr.hpp>
|
|
||||||
#include <set>
|
#include <set>
|
||||||
|
|
||||||
#include "yaml-cpp/dll.h"
|
#include "yaml-cpp/dll.h"
|
||||||
@@ -24,11 +22,13 @@ namespace YAML {
|
|||||||
namespace detail {
|
namespace detail {
|
||||||
class YAML_CPP_API memory {
|
class YAML_CPP_API memory {
|
||||||
public:
|
public:
|
||||||
|
memory() : m_nodes{} {}
|
||||||
node& create_node();
|
node& create_node();
|
||||||
void merge(const memory& rhs);
|
void merge(const memory& rhs);
|
||||||
|
size_t size() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef std::set<shared_node> Nodes;
|
using Nodes = std::set<shared_node>;
|
||||||
Nodes m_nodes;
|
Nodes m_nodes;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -40,9 +40,9 @@ class YAML_CPP_API memory_holder {
|
|||||||
void merge(memory_holder& rhs);
|
void merge(memory_holder& rhs);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
boost::shared_ptr<memory> m_pMemory;
|
shared_memory m_pMemory;
|
||||||
};
|
};
|
||||||
}
|
} // namespace detail
|
||||||
}
|
} // namespace YAML
|
||||||
|
|
||||||
#endif // VALUE_DETAIL_MEMORY_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#endif // VALUE_DETAIL_MEMORY_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|||||||
@@ -7,24 +7,32 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "yaml-cpp/emitterstyle.h"
|
|
||||||
#include "yaml-cpp/dll.h"
|
#include "yaml-cpp/dll.h"
|
||||||
#include "yaml-cpp/node/type.h"
|
#include "yaml-cpp/emitterstyle.h"
|
||||||
#include "yaml-cpp/node/ptr.h"
|
|
||||||
#include "yaml-cpp/node/detail/node_ref.h"
|
#include "yaml-cpp/node/detail/node_ref.h"
|
||||||
|
#include "yaml-cpp/node/ptr.h"
|
||||||
|
#include "yaml-cpp/node/type.h"
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <boost/utility.hpp>
|
#include <atomic>
|
||||||
|
|
||||||
namespace YAML {
|
namespace YAML {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
class node : private boost::noncopyable {
|
class node {
|
||||||
|
private:
|
||||||
|
struct less {
|
||||||
|
bool operator ()(const node* l, const node* r) const {return l->m_index < r->m_index;}
|
||||||
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
node() : m_pRef(new node_ref) {}
|
node() : m_pRef(new node_ref), m_dependencies{}, m_index{} {}
|
||||||
|
node(const node&) = delete;
|
||||||
|
node& operator=(const node&) = delete;
|
||||||
|
|
||||||
bool is(const node& rhs) const { return m_pRef == rhs.m_pRef; }
|
bool is(const node& rhs) const { return m_pRef == rhs.m_pRef; }
|
||||||
const node_ref* ref() const { return m_pRef.get(); }
|
const node_ref* ref() const { return m_pRef.get(); }
|
||||||
|
|
||||||
bool is_defined() const { return m_pRef->is_defined(); }
|
bool is_defined() const { return m_pRef->is_defined(); }
|
||||||
|
const Mark& mark() const { return m_pRef->mark(); }
|
||||||
NodeType::value type() const { return m_pRef->type(); }
|
NodeType::value type() const { return m_pRef->type(); }
|
||||||
|
|
||||||
const std::string& scalar() const { return m_pRef->scalar(); }
|
const std::string& scalar() const { return m_pRef->scalar(); }
|
||||||
@@ -40,9 +48,8 @@ class node : private boost::noncopyable {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
m_pRef->mark_defined();
|
m_pRef->mark_defined();
|
||||||
for (nodes::iterator it = m_dependencies.begin();
|
for (node* dependency : m_dependencies)
|
||||||
it != m_dependencies.end(); ++it)
|
dependency->mark_defined();
|
||||||
(*it)->mark_defined();
|
|
||||||
m_dependencies.clear();
|
m_dependencies.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,6 +71,8 @@ class node : private boost::noncopyable {
|
|||||||
m_pRef->set_data(*rhs.m_pRef);
|
m_pRef->set_data(*rhs.m_pRef);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void set_mark(const Mark& mark) { m_pRef->set_mark(mark); }
|
||||||
|
|
||||||
void set_type(NodeType::value type) {
|
void set_type(NodeType::value type) {
|
||||||
if (type != NodeType::Undefined)
|
if (type != NodeType::Undefined)
|
||||||
mark_defined();
|
mark_defined();
|
||||||
@@ -102,9 +111,10 @@ class node : private boost::noncopyable {
|
|||||||
node_iterator end() { return m_pRef->end(); }
|
node_iterator end() { return m_pRef->end(); }
|
||||||
|
|
||||||
// sequence
|
// sequence
|
||||||
void push_back(node& node, shared_memory_holder pMemory) {
|
void push_back(node& input, shared_memory_holder pMemory) {
|
||||||
m_pRef->push_back(node, pMemory);
|
m_pRef->push_back(input, pMemory);
|
||||||
node.add_dependency(*this);
|
input.add_dependency(*this);
|
||||||
|
m_index = m_amount.fetch_add(1);
|
||||||
}
|
}
|
||||||
void insert(node& key, node& value, shared_memory_holder pMemory) {
|
void insert(node& key, node& value, shared_memory_holder pMemory) {
|
||||||
m_pRef->insert(key, value, pMemory);
|
m_pRef->insert(key, value, pMemory);
|
||||||
@@ -116,7 +126,7 @@ class node : private boost::noncopyable {
|
|||||||
template <typename Key>
|
template <typename Key>
|
||||||
node* get(const Key& key, shared_memory_holder pMemory) const {
|
node* get(const Key& key, shared_memory_holder pMemory) const {
|
||||||
// NOTE: this returns a non-const node so that the top-level Node can wrap
|
// NOTE: this returns a non-const node so that the top-level Node can wrap
|
||||||
// it, and returns a pointer so that it can be NULL (if there is no such
|
// it, and returns a pointer so that it can be nullptr (if there is no such
|
||||||
// key).
|
// key).
|
||||||
return static_cast<const node_ref&>(*m_pRef).get(key, pMemory);
|
return static_cast<const node_ref&>(*m_pRef).get(key, pMemory);
|
||||||
}
|
}
|
||||||
@@ -133,7 +143,7 @@ class node : private boost::noncopyable {
|
|||||||
|
|
||||||
node* get(node& key, shared_memory_holder pMemory) const {
|
node* get(node& key, shared_memory_holder pMemory) const {
|
||||||
// NOTE: this returns a non-const node so that the top-level Node can wrap
|
// NOTE: this returns a non-const node so that the top-level Node can wrap
|
||||||
// it, and returns a pointer so that it can be NULL (if there is no such
|
// it, and returns a pointer so that it can be nullptr (if there is no such
|
||||||
// key).
|
// key).
|
||||||
return static_cast<const node_ref&>(*m_pRef).get(key, pMemory);
|
return static_cast<const node_ref&>(*m_pRef).get(key, pMemory);
|
||||||
}
|
}
|
||||||
@@ -156,10 +166,12 @@ class node : private boost::noncopyable {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
shared_node_ref m_pRef;
|
shared_node_ref m_pRef;
|
||||||
typedef std::set<node*> nodes;
|
using nodes = std::set<node*, less>;
|
||||||
nodes m_dependencies;
|
nodes m_dependencies;
|
||||||
|
size_t m_index;
|
||||||
|
static YAML_CPP_API std::atomic<size_t> m_amount;
|
||||||
};
|
};
|
||||||
}
|
} // namespace detail
|
||||||
}
|
} // namespace YAML
|
||||||
|
|
||||||
#endif // NODE_DETAIL_NODE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#endif // NODE_DETAIL_NODE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|||||||
@@ -7,8 +7,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <boost/noncopyable.hpp>
|
|
||||||
#include <boost/utility.hpp>
|
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <string>
|
#include <string>
|
||||||
@@ -29,11 +27,14 @@ class node;
|
|||||||
|
|
||||||
namespace YAML {
|
namespace YAML {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
class YAML_CPP_API node_data : private boost::noncopyable {
|
class YAML_CPP_API node_data {
|
||||||
public:
|
public:
|
||||||
node_data();
|
node_data();
|
||||||
|
node_data(const node_data&) = delete;
|
||||||
|
node_data& operator=(const node_data&) = delete;
|
||||||
|
|
||||||
void mark_defined();
|
void mark_defined();
|
||||||
|
void set_mark(const Mark& mark);
|
||||||
void set_type(NodeType::value type);
|
void set_type(NodeType::value type);
|
||||||
void set_tag(const std::string& tag);
|
void set_tag(const std::string& tag);
|
||||||
void set_null();
|
void set_null();
|
||||||
@@ -41,6 +42,7 @@ class YAML_CPP_API node_data : private boost::noncopyable {
|
|||||||
void set_style(EmitterStyle::value style);
|
void set_style(EmitterStyle::value style);
|
||||||
|
|
||||||
bool is_defined() const { return m_isDefined; }
|
bool is_defined() const { return m_isDefined; }
|
||||||
|
const Mark& mark() const { return m_mark; }
|
||||||
NodeType::value type() const {
|
NodeType::value type() const {
|
||||||
return m_isDefined ? m_type : NodeType::Undefined;
|
return m_isDefined ? m_type : NodeType::Undefined;
|
||||||
}
|
}
|
||||||
@@ -58,8 +60,8 @@ class YAML_CPP_API node_data : private boost::noncopyable {
|
|||||||
node_iterator end();
|
node_iterator end();
|
||||||
|
|
||||||
// sequence
|
// sequence
|
||||||
void push_back(node& node, shared_memory_holder pMemory);
|
void push_back(node& node, const shared_memory_holder& pMemory);
|
||||||
void insert(node& key, node& value, shared_memory_holder pMemory);
|
void insert(node& key, node& value, const shared_memory_holder& pMemory);
|
||||||
|
|
||||||
// indexing
|
// indexing
|
||||||
template <typename Key>
|
template <typename Key>
|
||||||
@@ -69,9 +71,9 @@ class YAML_CPP_API node_data : private boost::noncopyable {
|
|||||||
template <typename Key>
|
template <typename Key>
|
||||||
bool remove(const Key& key, shared_memory_holder pMemory);
|
bool remove(const Key& key, shared_memory_holder pMemory);
|
||||||
|
|
||||||
node* get(node& key, shared_memory_holder pMemory) const;
|
node* get(node& key, const shared_memory_holder& pMemory) const;
|
||||||
node& get(node& key, shared_memory_holder pMemory);
|
node& get(node& key, const shared_memory_holder& pMemory);
|
||||||
bool remove(node& key, shared_memory_holder pMemory);
|
bool remove(node& key, const shared_memory_holder& pMemory);
|
||||||
|
|
||||||
// map
|
// map
|
||||||
template <typename Key, typename Value>
|
template <typename Key, typename Value>
|
||||||
@@ -79,7 +81,7 @@ class YAML_CPP_API node_data : private boost::noncopyable {
|
|||||||
shared_memory_holder pMemory);
|
shared_memory_holder pMemory);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static std::string empty_scalar;
|
static const std::string& empty_scalar();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void compute_seq_size() const;
|
void compute_seq_size() const;
|
||||||
@@ -89,14 +91,15 @@ class YAML_CPP_API node_data : private boost::noncopyable {
|
|||||||
void reset_map();
|
void reset_map();
|
||||||
|
|
||||||
void insert_map_pair(node& key, node& value);
|
void insert_map_pair(node& key, node& value);
|
||||||
void convert_to_map(shared_memory_holder pMemory);
|
void convert_to_map(const shared_memory_holder& pMemory);
|
||||||
void convert_sequence_to_map(shared_memory_holder pMemory);
|
void convert_sequence_to_map(const shared_memory_holder& pMemory);
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
static node& convert_to_node(const T& rhs, shared_memory_holder pMemory);
|
static node& convert_to_node(const T& rhs, shared_memory_holder pMemory);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool m_isDefined;
|
bool m_isDefined;
|
||||||
|
Mark m_mark;
|
||||||
NodeType::value m_type;
|
NodeType::value m_type;
|
||||||
std::string m_tag;
|
std::string m_tag;
|
||||||
EmitterStyle::value m_style;
|
EmitterStyle::value m_style;
|
||||||
@@ -105,17 +108,17 @@ class YAML_CPP_API node_data : private boost::noncopyable {
|
|||||||
std::string m_scalar;
|
std::string m_scalar;
|
||||||
|
|
||||||
// sequence
|
// sequence
|
||||||
typedef std::vector<node*> node_seq;
|
using node_seq = std::vector<node *>;
|
||||||
node_seq m_sequence;
|
node_seq m_sequence;
|
||||||
|
|
||||||
mutable std::size_t m_seqSize;
|
mutable std::size_t m_seqSize;
|
||||||
|
|
||||||
// map
|
// map
|
||||||
typedef std::map<node*, node*> node_map;
|
using node_map = std::vector<std::pair<node*, node*>>;
|
||||||
node_map m_map;
|
node_map m_map;
|
||||||
|
|
||||||
typedef std::pair<node*, node*> kv_pair;
|
using kv_pair = std::pair<node*, node*>;
|
||||||
typedef std::list<kv_pair> kv_pairs;
|
using kv_pairs = std::list<kv_pair>;
|
||||||
mutable kv_pairs m_undefinedPairs;
|
mutable kv_pairs m_undefinedPairs;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,8 +9,9 @@
|
|||||||
|
|
||||||
#include "yaml-cpp/dll.h"
|
#include "yaml-cpp/dll.h"
|
||||||
#include "yaml-cpp/node/ptr.h"
|
#include "yaml-cpp/node/ptr.h"
|
||||||
#include <boost/iterator/iterator_facade.hpp>
|
#include <cstddef>
|
||||||
#include <boost/utility/enable_if.hpp>
|
#include <iterator>
|
||||||
|
#include <memory>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@@ -18,16 +19,16 @@
|
|||||||
namespace YAML {
|
namespace YAML {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
struct iterator_type {
|
struct iterator_type {
|
||||||
enum value { None, Sequence, Map };
|
enum value { NoneType, Sequence, Map };
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename V>
|
template <typename V>
|
||||||
struct node_iterator_value : public std::pair<V*, V*> {
|
struct node_iterator_value : public std::pair<V*, V*> {
|
||||||
typedef std::pair<V*, V*> kv;
|
using kv = std::pair<V*, V*>;
|
||||||
|
|
||||||
node_iterator_value() : kv(), pNode(0) {}
|
node_iterator_value() : kv(), pNode(nullptr) {}
|
||||||
explicit node_iterator_value(V& rhs) : kv(), pNode(&rhs) {}
|
explicit node_iterator_value(V& rhs) : kv(), pNode(&rhs) {}
|
||||||
explicit node_iterator_value(V& key, V& value) : kv(&key, &value), pNode(0) {}
|
explicit node_iterator_value(V& key, V& value) : kv(&key, &value), pNode(nullptr) {}
|
||||||
|
|
||||||
V& operator*() const { return *pNode; }
|
V& operator*() const { return *pNode; }
|
||||||
V& operator->() const { return *pNode; }
|
V& operator->() const { return *pNode; }
|
||||||
@@ -35,36 +36,45 @@ struct node_iterator_value : public std::pair<V*, V*> {
|
|||||||
V* pNode;
|
V* pNode;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::vector<node*> node_seq;
|
using node_seq = std::vector<node *>;
|
||||||
typedef std::map<node*, node*> node_map;
|
using node_map = std::vector<std::pair<node*, node*>>;
|
||||||
|
|
||||||
template <typename V>
|
template <typename V>
|
||||||
struct node_iterator_type {
|
struct node_iterator_type {
|
||||||
typedef node_seq::iterator seq;
|
using seq = node_seq::iterator;
|
||||||
typedef node_map::iterator map;
|
using map = node_map::iterator;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename V>
|
template <typename V>
|
||||||
struct node_iterator_type<const V> {
|
struct node_iterator_type<const V> {
|
||||||
typedef node_seq::const_iterator seq;
|
using seq = node_seq::const_iterator;
|
||||||
typedef node_map::const_iterator map;
|
using map = node_map::const_iterator;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename V>
|
template <typename V>
|
||||||
class node_iterator_base
|
class node_iterator_base {
|
||||||
: public boost::iterator_facade<
|
|
||||||
node_iterator_base<V>, node_iterator_value<V>,
|
|
||||||
std::forward_iterator_tag, node_iterator_value<V> > {
|
|
||||||
private:
|
private:
|
||||||
struct enabler {};
|
struct enabler {};
|
||||||
|
|
||||||
|
struct proxy {
|
||||||
|
explicit proxy(const node_iterator_value<V>& x) : m_ref(x) {}
|
||||||
|
node_iterator_value<V>* operator->() { return std::addressof(m_ref); }
|
||||||
|
operator node_iterator_value<V>*() { return std::addressof(m_ref); }
|
||||||
|
|
||||||
|
node_iterator_value<V> m_ref;
|
||||||
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef typename node_iterator_type<V>::seq SeqIter;
|
using iterator_category = std::forward_iterator_tag;
|
||||||
typedef typename node_iterator_type<V>::map MapIter;
|
using value_type = node_iterator_value<V>;
|
||||||
typedef node_iterator_value<V> value_type;
|
using difference_type = std::ptrdiff_t;
|
||||||
|
using pointer = node_iterator_value<V>*;
|
||||||
|
using reference = node_iterator_value<V>&;
|
||||||
|
using SeqIter = typename node_iterator_type<V>::seq;
|
||||||
|
using MapIter = typename node_iterator_type<V>::map;
|
||||||
|
|
||||||
node_iterator_base()
|
node_iterator_base()
|
||||||
: m_type(iterator_type::None), m_seqIt(), m_mapIt(), m_mapEnd() {}
|
: m_type(iterator_type::NoneType), m_seqIt(), m_mapIt(), m_mapEnd() {}
|
||||||
explicit node_iterator_base(SeqIter seqIt)
|
explicit node_iterator_base(SeqIter seqIt)
|
||||||
: m_type(iterator_type::Sequence),
|
: m_type(iterator_type::Sequence),
|
||||||
m_seqIt(seqIt),
|
m_seqIt(seqIt),
|
||||||
@@ -80,25 +90,23 @@ class node_iterator_base
|
|||||||
|
|
||||||
template <typename W>
|
template <typename W>
|
||||||
node_iterator_base(const node_iterator_base<W>& rhs,
|
node_iterator_base(const node_iterator_base<W>& rhs,
|
||||||
typename boost::enable_if<boost::is_convertible<W*, V*>,
|
typename std::enable_if<std::is_convertible<W*, V*>::value,
|
||||||
enabler>::type = enabler())
|
enabler>::type = enabler())
|
||||||
: m_type(rhs.m_type),
|
: m_type(rhs.m_type),
|
||||||
m_seqIt(rhs.m_seqIt),
|
m_seqIt(rhs.m_seqIt),
|
||||||
m_mapIt(rhs.m_mapIt),
|
m_mapIt(rhs.m_mapIt),
|
||||||
m_mapEnd(rhs.m_mapEnd) {}
|
m_mapEnd(rhs.m_mapEnd) {}
|
||||||
|
|
||||||
private:
|
|
||||||
friend class boost::iterator_core_access;
|
|
||||||
template <typename>
|
template <typename>
|
||||||
friend class node_iterator_base;
|
friend class node_iterator_base;
|
||||||
|
|
||||||
template <typename W>
|
template <typename W>
|
||||||
bool equal(const node_iterator_base<W>& rhs) const {
|
bool operator==(const node_iterator_base<W>& rhs) const {
|
||||||
if (m_type != rhs.m_type)
|
if (m_type != rhs.m_type)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
switch (m_type) {
|
switch (m_type) {
|
||||||
case iterator_type::None:
|
case iterator_type::NoneType:
|
||||||
return true;
|
return true;
|
||||||
case iterator_type::Sequence:
|
case iterator_type::Sequence:
|
||||||
return m_seqIt == rhs.m_seqIt;
|
return m_seqIt == rhs.m_seqIt;
|
||||||
@@ -108,9 +116,14 @@ class node_iterator_base
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void increment() {
|
template <typename W>
|
||||||
|
bool operator!=(const node_iterator_base<W>& rhs) const {
|
||||||
|
return !(*this == rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
node_iterator_base<V>& operator++() {
|
||||||
switch (m_type) {
|
switch (m_type) {
|
||||||
case iterator_type::None:
|
case iterator_type::NoneType:
|
||||||
break;
|
break;
|
||||||
case iterator_type::Sequence:
|
case iterator_type::Sequence:
|
||||||
++m_seqIt;
|
++m_seqIt;
|
||||||
@@ -120,11 +133,18 @@ class node_iterator_base
|
|||||||
m_mapIt = increment_until_defined(m_mapIt);
|
m_mapIt = increment_until_defined(m_mapIt);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
value_type dereference() const {
|
node_iterator_base<V> operator++(int) {
|
||||||
|
node_iterator_base<V> iterator_pre(*this);
|
||||||
|
++(*this);
|
||||||
|
return iterator_pre;
|
||||||
|
}
|
||||||
|
|
||||||
|
value_type operator*() const {
|
||||||
switch (m_type) {
|
switch (m_type) {
|
||||||
case iterator_type::None:
|
case iterator_type::NoneType:
|
||||||
return value_type();
|
return value_type();
|
||||||
case iterator_type::Sequence:
|
case iterator_type::Sequence:
|
||||||
return value_type(**m_seqIt);
|
return value_type(**m_seqIt);
|
||||||
@@ -134,6 +154,8 @@ class node_iterator_base
|
|||||||
return value_type();
|
return value_type();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
proxy operator->() const { return proxy(**this); }
|
||||||
|
|
||||||
MapIter increment_until_defined(MapIter it) {
|
MapIter increment_until_defined(MapIter it) {
|
||||||
while (it != m_mapEnd && !is_defined(it))
|
while (it != m_mapEnd && !is_defined(it))
|
||||||
++it;
|
++it;
|
||||||
@@ -151,8 +173,8 @@ class node_iterator_base
|
|||||||
MapIter m_mapIt, m_mapEnd;
|
MapIter m_mapIt, m_mapEnd;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef node_iterator_base<node> node_iterator;
|
using node_iterator = node_iterator_base<node>;
|
||||||
typedef node_iterator_base<const node> const_node_iterator;
|
using const_node_iterator = node_iterator_base<const node>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,15 +11,17 @@
|
|||||||
#include "yaml-cpp/node/type.h"
|
#include "yaml-cpp/node/type.h"
|
||||||
#include "yaml-cpp/node/ptr.h"
|
#include "yaml-cpp/node/ptr.h"
|
||||||
#include "yaml-cpp/node/detail/node_data.h"
|
#include "yaml-cpp/node/detail/node_data.h"
|
||||||
#include <boost/utility.hpp>
|
|
||||||
|
|
||||||
namespace YAML {
|
namespace YAML {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
class node_ref : private boost::noncopyable {
|
class node_ref {
|
||||||
public:
|
public:
|
||||||
node_ref() : m_pData(new node_data) {}
|
node_ref() : m_pData(new node_data) {}
|
||||||
|
node_ref(const node_ref&) = delete;
|
||||||
|
node_ref& operator=(const node_ref&) = delete;
|
||||||
|
|
||||||
bool is_defined() const { return m_pData->is_defined(); }
|
bool is_defined() const { return m_pData->is_defined(); }
|
||||||
|
const Mark& mark() const { return m_pData->mark(); }
|
||||||
NodeType::value type() const { return m_pData->type(); }
|
NodeType::value type() const { return m_pData->type(); }
|
||||||
const std::string& scalar() const { return m_pData->scalar(); }
|
const std::string& scalar() const { return m_pData->scalar(); }
|
||||||
const std::string& tag() const { return m_pData->tag(); }
|
const std::string& tag() const { return m_pData->tag(); }
|
||||||
@@ -28,6 +30,7 @@ class node_ref : private boost::noncopyable {
|
|||||||
void mark_defined() { m_pData->mark_defined(); }
|
void mark_defined() { m_pData->mark_defined(); }
|
||||||
void set_data(const node_ref& rhs) { m_pData = rhs.m_pData; }
|
void set_data(const node_ref& rhs) { m_pData = rhs.m_pData; }
|
||||||
|
|
||||||
|
void set_mark(const Mark& mark) { m_pData->set_mark(mark); }
|
||||||
void set_type(NodeType::value type) { m_pData->set_type(type); }
|
void set_type(NodeType::value type) { m_pData->set_type(type); }
|
||||||
void set_tag(const std::string& tag) { m_pData->set_tag(tag); }
|
void set_tag(const std::string& tag) { m_pData->set_tag(tag); }
|
||||||
void set_null() { m_pData->set_null(); }
|
void set_null() { m_pData->set_null(); }
|
||||||
|
|||||||
@@ -16,10 +16,17 @@ namespace YAML {
|
|||||||
class Emitter;
|
class Emitter;
|
||||||
class Node;
|
class Node;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Emits the node to the given {@link Emitter}. If there is an error in writing,
|
||||||
|
* {@link Emitter#good} will return false.
|
||||||
|
*/
|
||||||
YAML_CPP_API Emitter& operator<<(Emitter& out, const Node& node);
|
YAML_CPP_API Emitter& operator<<(Emitter& out, const Node& node);
|
||||||
|
|
||||||
|
/** Emits the node to the given output stream. */
|
||||||
YAML_CPP_API std::ostream& operator<<(std::ostream& out, const Node& node);
|
YAML_CPP_API std::ostream& operator<<(std::ostream& out, const Node& node);
|
||||||
|
|
||||||
|
/** Converts the node to a YAML string. */
|
||||||
YAML_CPP_API std::string Dump(const Node& node);
|
YAML_CPP_API std::string Dump(const Node& node);
|
||||||
}
|
} // namespace YAML
|
||||||
|
|
||||||
#endif // NODE_EMIT_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#endif // NODE_EMIT_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|||||||
@@ -7,18 +7,21 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "yaml-cpp/node/node.h"
|
#include "yaml-cpp/exceptions.h"
|
||||||
#include "yaml-cpp/node/iterator.h"
|
|
||||||
#include "yaml-cpp/node/detail/memory.h"
|
#include "yaml-cpp/node/detail/memory.h"
|
||||||
#include "yaml-cpp/node/detail/node.h"
|
#include "yaml-cpp/node/detail/node.h"
|
||||||
#include "yaml-cpp/exceptions.h"
|
#include "yaml-cpp/node/iterator.h"
|
||||||
|
#include "yaml-cpp/node/node.h"
|
||||||
|
#include <sstream>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace YAML {
|
namespace YAML {
|
||||||
inline Node::Node() : m_isValid(true), m_pNode(NULL) {}
|
inline Node::Node()
|
||||||
|
: m_isValid(true), m_invalidKey{}, m_pMemory(nullptr), m_pNode(nullptr) {}
|
||||||
|
|
||||||
inline Node::Node(NodeType::value type)
|
inline Node::Node(NodeType::value type)
|
||||||
: m_isValid(true),
|
: m_isValid(true),
|
||||||
|
m_invalidKey{},
|
||||||
m_pMemory(new detail::memory_holder),
|
m_pMemory(new detail::memory_holder),
|
||||||
m_pNode(&m_pMemory->create_node()) {
|
m_pNode(&m_pMemory->create_node()) {
|
||||||
m_pNode->set_type(type);
|
m_pNode->set_type(type);
|
||||||
@@ -27,6 +30,7 @@ inline Node::Node(NodeType::value type)
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
inline Node::Node(const T& rhs)
|
inline Node::Node(const T& rhs)
|
||||||
: m_isValid(true),
|
: m_isValid(true),
|
||||||
|
m_invalidKey{},
|
||||||
m_pMemory(new detail::memory_holder),
|
m_pMemory(new detail::memory_holder),
|
||||||
m_pNode(&m_pMemory->create_node()) {
|
m_pNode(&m_pMemory->create_node()) {
|
||||||
Assign(rhs);
|
Assign(rhs);
|
||||||
@@ -34,24 +38,26 @@ inline Node::Node(const T& rhs)
|
|||||||
|
|
||||||
inline Node::Node(const detail::iterator_value& rhs)
|
inline Node::Node(const detail::iterator_value& rhs)
|
||||||
: m_isValid(rhs.m_isValid),
|
: m_isValid(rhs.m_isValid),
|
||||||
|
m_invalidKey(rhs.m_invalidKey),
|
||||||
m_pMemory(rhs.m_pMemory),
|
m_pMemory(rhs.m_pMemory),
|
||||||
m_pNode(rhs.m_pNode) {}
|
m_pNode(rhs.m_pNode) {}
|
||||||
|
|
||||||
inline Node::Node(const Node& rhs)
|
inline Node::Node(const Node&) = default;
|
||||||
: m_isValid(rhs.m_isValid),
|
|
||||||
m_pMemory(rhs.m_pMemory),
|
|
||||||
m_pNode(rhs.m_pNode) {}
|
|
||||||
|
|
||||||
inline Node::Node(Zombie) : m_isValid(false), m_pNode(NULL) {}
|
inline Node::Node(Zombie)
|
||||||
|
: m_isValid(false), m_invalidKey{}, m_pMemory{}, m_pNode(nullptr) {}
|
||||||
|
|
||||||
|
inline Node::Node(Zombie, const std::string& key)
|
||||||
|
: m_isValid(false), m_invalidKey(key), m_pMemory{}, m_pNode(nullptr) {}
|
||||||
|
|
||||||
inline Node::Node(detail::node& node, detail::shared_memory_holder pMemory)
|
inline Node::Node(detail::node& node, detail::shared_memory_holder pMemory)
|
||||||
: m_isValid(true), m_pMemory(pMemory), m_pNode(&node) {}
|
: m_isValid(true), m_invalidKey{}, m_pMemory(pMemory), m_pNode(&node) {}
|
||||||
|
|
||||||
inline Node::~Node() {}
|
inline Node::~Node() = default;
|
||||||
|
|
||||||
inline void Node::EnsureNodeExists() const {
|
inline void Node::EnsureNodeExists() const {
|
||||||
if (!m_isValid)
|
if (!m_isValid)
|
||||||
throw InvalidNode();
|
throw InvalidNode(m_invalidKey);
|
||||||
if (!m_pNode) {
|
if (!m_pNode) {
|
||||||
m_pMemory.reset(new detail::memory_holder);
|
m_pMemory.reset(new detail::memory_holder);
|
||||||
m_pNode = &m_pMemory->create_node();
|
m_pNode = &m_pMemory->create_node();
|
||||||
@@ -66,9 +72,16 @@ inline bool Node::IsDefined() const {
|
|||||||
return m_pNode ? m_pNode->is_defined() : true;
|
return m_pNode ? m_pNode->is_defined() : true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline Mark Node::Mark() const {
|
||||||
|
if (!m_isValid) {
|
||||||
|
throw InvalidNode(m_invalidKey);
|
||||||
|
}
|
||||||
|
return m_pNode ? m_pNode->mark() : Mark::null_mark();
|
||||||
|
}
|
||||||
|
|
||||||
inline NodeType::value Node::Type() const {
|
inline NodeType::value Node::Type() const {
|
||||||
if (!m_isValid)
|
if (!m_isValid)
|
||||||
throw InvalidNode();
|
throw InvalidNode(m_invalidKey);
|
||||||
return m_pNode ? m_pNode->type() : NodeType::Null;
|
return m_pNode ? m_pNode->type() : NodeType::Null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -80,11 +93,11 @@ struct as_if {
|
|||||||
explicit as_if(const Node& node_) : node(node_) {}
|
explicit as_if(const Node& node_) : node(node_) {}
|
||||||
const Node& node;
|
const Node& node;
|
||||||
|
|
||||||
const T operator()(const S& fallback) const {
|
T operator()(const S& fallback) const {
|
||||||
if (!node.m_pNode)
|
if (!node.m_pNode)
|
||||||
return fallback;
|
return fallback;
|
||||||
|
|
||||||
T t;
|
T t = fallback;
|
||||||
if (convert<T>::decode(node, t))
|
if (convert<T>::decode(node, t))
|
||||||
return t;
|
return t;
|
||||||
return fallback;
|
return fallback;
|
||||||
@@ -96,7 +109,9 @@ struct as_if<std::string, S> {
|
|||||||
explicit as_if(const Node& node_) : node(node_) {}
|
explicit as_if(const Node& node_) : node(node_) {}
|
||||||
const Node& node;
|
const Node& node;
|
||||||
|
|
||||||
const std::string operator()(const S& fallback) const {
|
std::string operator()(const S& fallback) const {
|
||||||
|
if (node.Type() == NodeType::Null)
|
||||||
|
return "null";
|
||||||
if (node.Type() != NodeType::Scalar)
|
if (node.Type() != NodeType::Scalar)
|
||||||
return fallback;
|
return fallback;
|
||||||
return node.Scalar();
|
return node.Scalar();
|
||||||
@@ -108,14 +123,14 @@ struct as_if<T, void> {
|
|||||||
explicit as_if(const Node& node_) : node(node_) {}
|
explicit as_if(const Node& node_) : node(node_) {}
|
||||||
const Node& node;
|
const Node& node;
|
||||||
|
|
||||||
const T operator()() const {
|
T operator()() const {
|
||||||
if (!node.m_pNode)
|
if (!node.m_pNode) // no fallback
|
||||||
throw TypedBadConversion<T>();
|
throw InvalidNode(node.m_invalidKey);
|
||||||
|
|
||||||
T t;
|
T t;
|
||||||
if (convert<T>::decode(node, t))
|
if (convert<T>::decode(node, t))
|
||||||
return t;
|
return t;
|
||||||
throw TypedBadConversion<T>();
|
throw TypedBadConversion<T>(node.Mark());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -124,56 +139,56 @@ struct as_if<std::string, void> {
|
|||||||
explicit as_if(const Node& node_) : node(node_) {}
|
explicit as_if(const Node& node_) : node(node_) {}
|
||||||
const Node& node;
|
const Node& node;
|
||||||
|
|
||||||
const std::string operator()() const {
|
std::string operator()() const {
|
||||||
|
if (node.Type() == NodeType::Undefined) // no fallback
|
||||||
|
throw InvalidNode(node.m_invalidKey);
|
||||||
|
if (node.Type() == NodeType::Null)
|
||||||
|
return "null";
|
||||||
if (node.Type() != NodeType::Scalar)
|
if (node.Type() != NodeType::Scalar)
|
||||||
throw TypedBadConversion<std::string>();
|
throw TypedBadConversion<std::string>(node.Mark());
|
||||||
return node.Scalar();
|
return node.Scalar();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// access functions
|
// access functions
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline const T Node::as() const {
|
inline T Node::as() const {
|
||||||
if (!m_isValid)
|
if (!m_isValid)
|
||||||
throw InvalidNode();
|
throw InvalidNode(m_invalidKey);
|
||||||
return as_if<T, void>(*this)();
|
return as_if<T, void>(*this)();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, typename S>
|
template <typename T, typename S>
|
||||||
inline const T Node::as(const S& fallback) const {
|
inline T Node::as(const S& fallback) const {
|
||||||
if (!m_isValid)
|
if (!m_isValid)
|
||||||
throw InvalidNode();
|
return fallback;
|
||||||
return as_if<T, S>(*this)(fallback);
|
return as_if<T, S>(*this)(fallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const std::string& Node::Scalar() const {
|
inline const std::string& Node::Scalar() const {
|
||||||
if (!m_isValid)
|
if (!m_isValid)
|
||||||
throw InvalidNode();
|
throw InvalidNode(m_invalidKey);
|
||||||
return m_pNode ? m_pNode->scalar() : detail::node_data::empty_scalar;
|
return m_pNode ? m_pNode->scalar() : detail::node_data::empty_scalar();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const std::string& Node::Tag() const {
|
inline const std::string& Node::Tag() const {
|
||||||
if (!m_isValid)
|
if (!m_isValid)
|
||||||
throw InvalidNode();
|
throw InvalidNode(m_invalidKey);
|
||||||
return m_pNode ? m_pNode->tag() : detail::node_data::empty_scalar;
|
return m_pNode ? m_pNode->tag() : detail::node_data::empty_scalar();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void Node::SetTag(const std::string& tag) {
|
inline void Node::SetTag(const std::string& tag) {
|
||||||
if (!m_isValid)
|
|
||||||
throw InvalidNode();
|
|
||||||
EnsureNodeExists();
|
EnsureNodeExists();
|
||||||
m_pNode->set_tag(tag);
|
m_pNode->set_tag(tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline EmitterStyle::value Node::Style() const {
|
inline EmitterStyle::value Node::Style() const {
|
||||||
if (!m_isValid)
|
if (!m_isValid)
|
||||||
throw InvalidNode();
|
throw InvalidNode(m_invalidKey);
|
||||||
return m_pNode ? m_pNode->style() : EmitterStyle::Default;
|
return m_pNode ? m_pNode->style() : EmitterStyle::Default;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void Node::SetStyle(EmitterStyle::value style) {
|
inline void Node::SetStyle(EmitterStyle::value style) {
|
||||||
if (!m_isValid)
|
|
||||||
throw InvalidNode();
|
|
||||||
EnsureNodeExists();
|
EnsureNodeExists();
|
||||||
m_pNode->set_style(style);
|
m_pNode->set_style(style);
|
||||||
}
|
}
|
||||||
@@ -181,7 +196,7 @@ inline void Node::SetStyle(EmitterStyle::value style) {
|
|||||||
// assignment
|
// assignment
|
||||||
inline bool Node::is(const Node& rhs) const {
|
inline bool Node::is(const Node& rhs) const {
|
||||||
if (!m_isValid || !rhs.m_isValid)
|
if (!m_isValid || !rhs.m_isValid)
|
||||||
throw InvalidNode();
|
throw InvalidNode(m_invalidKey);
|
||||||
if (!m_pNode || !rhs.m_pNode)
|
if (!m_pNode || !rhs.m_pNode)
|
||||||
return false;
|
return false;
|
||||||
return m_pNode->is(*rhs.m_pNode);
|
return m_pNode->is(*rhs.m_pNode);
|
||||||
@@ -189,15 +204,20 @@ inline bool Node::is(const Node& rhs) const {
|
|||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline Node& Node::operator=(const T& rhs) {
|
inline Node& Node::operator=(const T& rhs) {
|
||||||
if (!m_isValid)
|
|
||||||
throw InvalidNode();
|
|
||||||
Assign(rhs);
|
Assign(rhs);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline Node& Node::operator=(const Node& rhs) {
|
||||||
|
if (is(rhs))
|
||||||
|
return *this;
|
||||||
|
AssignNode(rhs);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
inline void Node::reset(const YAML::Node& rhs) {
|
inline void Node::reset(const YAML::Node& rhs) {
|
||||||
if (!m_isValid || !rhs.m_isValid)
|
if (!m_isValid || !rhs.m_isValid)
|
||||||
throw InvalidNode();
|
throw InvalidNode(m_invalidKey);
|
||||||
m_pMemory = rhs.m_pMemory;
|
m_pMemory = rhs.m_pMemory;
|
||||||
m_pNode = rhs.m_pNode;
|
m_pNode = rhs.m_pNode;
|
||||||
}
|
}
|
||||||
@@ -205,44 +225,27 @@ inline void Node::reset(const YAML::Node& rhs) {
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
inline void Node::Assign(const T& rhs) {
|
inline void Node::Assign(const T& rhs) {
|
||||||
if (!m_isValid)
|
if (!m_isValid)
|
||||||
throw InvalidNode();
|
throw InvalidNode(m_invalidKey);
|
||||||
AssignData(convert<T>::encode(rhs));
|
AssignData(convert<T>::encode(rhs));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
inline void Node::Assign(const std::string& rhs) {
|
inline void Node::Assign(const std::string& rhs) {
|
||||||
if (!m_isValid)
|
|
||||||
throw InvalidNode();
|
|
||||||
EnsureNodeExists();
|
EnsureNodeExists();
|
||||||
m_pNode->set_scalar(rhs);
|
m_pNode->set_scalar(rhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void Node::Assign(const char* rhs) {
|
inline void Node::Assign(const char* rhs) {
|
||||||
if (!m_isValid)
|
|
||||||
throw InvalidNode();
|
|
||||||
EnsureNodeExists();
|
EnsureNodeExists();
|
||||||
m_pNode->set_scalar(rhs);
|
m_pNode->set_scalar(rhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void Node::Assign(char* rhs) {
|
inline void Node::Assign(char* rhs) {
|
||||||
if (!m_isValid)
|
|
||||||
throw InvalidNode();
|
|
||||||
EnsureNodeExists();
|
EnsureNodeExists();
|
||||||
m_pNode->set_scalar(rhs);
|
m_pNode->set_scalar(rhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Node& Node::operator=(const Node& rhs) {
|
|
||||||
if (!m_isValid || !rhs.m_isValid)
|
|
||||||
throw InvalidNode();
|
|
||||||
if (is(rhs))
|
|
||||||
return *this;
|
|
||||||
AssignNode(rhs);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void Node::AssignData(const Node& rhs) {
|
inline void Node::AssignData(const Node& rhs) {
|
||||||
if (!m_isValid || !rhs.m_isValid)
|
|
||||||
throw InvalidNode();
|
|
||||||
EnsureNodeExists();
|
EnsureNodeExists();
|
||||||
rhs.EnsureNodeExists();
|
rhs.EnsureNodeExists();
|
||||||
|
|
||||||
@@ -251,8 +254,8 @@ inline void Node::AssignData(const Node& rhs) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline void Node::AssignNode(const Node& rhs) {
|
inline void Node::AssignNode(const Node& rhs) {
|
||||||
if (!m_isValid || !rhs.m_isValid)
|
if (!m_isValid)
|
||||||
throw InvalidNode();
|
throw InvalidNode(m_invalidKey);
|
||||||
rhs.EnsureNodeExists();
|
rhs.EnsureNodeExists();
|
||||||
|
|
||||||
if (!m_pNode) {
|
if (!m_pNode) {
|
||||||
@@ -269,32 +272,32 @@ inline void Node::AssignNode(const Node& rhs) {
|
|||||||
// size/iterator
|
// size/iterator
|
||||||
inline std::size_t Node::size() const {
|
inline std::size_t Node::size() const {
|
||||||
if (!m_isValid)
|
if (!m_isValid)
|
||||||
throw InvalidNode();
|
throw InvalidNode(m_invalidKey);
|
||||||
return m_pNode ? m_pNode->size() : 0;
|
return m_pNode ? m_pNode->size() : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const_iterator Node::begin() const {
|
inline const_iterator Node::begin() const {
|
||||||
if (!m_isValid)
|
if (!m_isValid)
|
||||||
throw InvalidNode();
|
return const_iterator();
|
||||||
return m_pNode ? const_iterator(m_pNode->begin(), m_pMemory)
|
return m_pNode ? const_iterator(m_pNode->begin(), m_pMemory)
|
||||||
: const_iterator();
|
: const_iterator();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline iterator Node::begin() {
|
inline iterator Node::begin() {
|
||||||
if (!m_isValid)
|
if (!m_isValid)
|
||||||
throw InvalidNode();
|
return iterator();
|
||||||
return m_pNode ? iterator(m_pNode->begin(), m_pMemory) : iterator();
|
return m_pNode ? iterator(m_pNode->begin(), m_pMemory) : iterator();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const_iterator Node::end() const {
|
inline const_iterator Node::end() const {
|
||||||
if (!m_isValid)
|
if (!m_isValid)
|
||||||
throw InvalidNode();
|
return const_iterator();
|
||||||
return m_pNode ? const_iterator(m_pNode->end(), m_pMemory) : const_iterator();
|
return m_pNode ? const_iterator(m_pNode->end(), m_pMemory) : const_iterator();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline iterator Node::end() {
|
inline iterator Node::end() {
|
||||||
if (!m_isValid)
|
if (!m_isValid)
|
||||||
throw InvalidNode();
|
return iterator();
|
||||||
return m_pNode ? iterator(m_pNode->end(), m_pMemory) : iterator();
|
return m_pNode ? iterator(m_pNode->end(), m_pMemory) : iterator();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -302,13 +305,11 @@ inline iterator Node::end() {
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
inline void Node::push_back(const T& rhs) {
|
inline void Node::push_back(const T& rhs) {
|
||||||
if (!m_isValid)
|
if (!m_isValid)
|
||||||
throw InvalidNode();
|
throw InvalidNode(m_invalidKey);
|
||||||
push_back(Node(rhs));
|
push_back(Node(rhs));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void Node::push_back(const Node& rhs) {
|
inline void Node::push_back(const Node& rhs) {
|
||||||
if (!m_isValid || !rhs.m_isValid)
|
|
||||||
throw InvalidNode();
|
|
||||||
EnsureNodeExists();
|
EnsureNodeExists();
|
||||||
rhs.EnsureNodeExists();
|
rhs.EnsureNodeExists();
|
||||||
|
|
||||||
@@ -316,99 +317,49 @@ inline void Node::push_back(const Node& rhs) {
|
|||||||
m_pMemory->merge(*rhs.m_pMemory);
|
m_pMemory->merge(*rhs.m_pMemory);
|
||||||
}
|
}
|
||||||
|
|
||||||
// helpers for indexing
|
template<typename Key>
|
||||||
namespace detail {
|
std::string key_to_string(const Key& key) {
|
||||||
template <typename T>
|
return streamable_to_string<Key, is_streamable<std::stringstream, Key>::value>().impl(key);
|
||||||
struct to_value_t {
|
|
||||||
explicit to_value_t(const T& t_) : t(t_) {}
|
|
||||||
const T& t;
|
|
||||||
typedef const T& return_type;
|
|
||||||
|
|
||||||
const T& operator()() const { return t; }
|
|
||||||
};
|
|
||||||
|
|
||||||
template <>
|
|
||||||
struct to_value_t<const char*> {
|
|
||||||
explicit to_value_t(const char* t_) : t(t_) {}
|
|
||||||
const char* t;
|
|
||||||
typedef std::string return_type;
|
|
||||||
|
|
||||||
const std::string operator()() const { return t; }
|
|
||||||
};
|
|
||||||
|
|
||||||
template <>
|
|
||||||
struct to_value_t<char*> {
|
|
||||||
explicit to_value_t(char* t_) : t(t_) {}
|
|
||||||
const char* t;
|
|
||||||
typedef std::string return_type;
|
|
||||||
|
|
||||||
const std::string operator()() const { return t; }
|
|
||||||
};
|
|
||||||
|
|
||||||
template <std::size_t N>
|
|
||||||
struct to_value_t<char[N]> {
|
|
||||||
explicit to_value_t(const char* t_) : t(t_) {}
|
|
||||||
const char* t;
|
|
||||||
typedef std::string return_type;
|
|
||||||
|
|
||||||
const std::string operator()() const { return t; }
|
|
||||||
};
|
|
||||||
|
|
||||||
// converts C-strings to std::strings so they can be copied
|
|
||||||
template <typename T>
|
|
||||||
inline typename to_value_t<T>::return_type to_value(const T& t) {
|
|
||||||
return to_value_t<T>(t)();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// indexing
|
// indexing
|
||||||
template <typename Key>
|
template <typename Key>
|
||||||
inline const Node Node::operator[](const Key& key) const {
|
inline const Node Node::operator[](const Key& key) const {
|
||||||
if (!m_isValid)
|
|
||||||
throw InvalidNode();
|
|
||||||
EnsureNodeExists();
|
EnsureNodeExists();
|
||||||
detail::node* value = static_cast<const detail::node&>(*m_pNode)
|
detail::node* value =
|
||||||
.get(detail::to_value(key), m_pMemory);
|
static_cast<const detail::node&>(*m_pNode).get(key, m_pMemory);
|
||||||
if (!value) {
|
if (!value) {
|
||||||
return Node(ZombieNode);
|
return Node(ZombieNode, key_to_string(key));
|
||||||
}
|
}
|
||||||
return Node(*value, m_pMemory);
|
return Node(*value, m_pMemory);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Key>
|
template <typename Key>
|
||||||
inline Node Node::operator[](const Key& key) {
|
inline Node Node::operator[](const Key& key) {
|
||||||
if (!m_isValid)
|
|
||||||
throw InvalidNode();
|
|
||||||
EnsureNodeExists();
|
EnsureNodeExists();
|
||||||
detail::node& value = m_pNode->get(detail::to_value(key), m_pMemory);
|
detail::node& value = m_pNode->get(key, m_pMemory);
|
||||||
return Node(value, m_pMemory);
|
return Node(value, m_pMemory);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Key>
|
template <typename Key>
|
||||||
inline bool Node::remove(const Key& key) {
|
inline bool Node::remove(const Key& key) {
|
||||||
if (!m_isValid)
|
|
||||||
throw InvalidNode();
|
|
||||||
EnsureNodeExists();
|
EnsureNodeExists();
|
||||||
return m_pNode->remove(detail::to_value(key), m_pMemory);
|
return m_pNode->remove(key, m_pMemory);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const Node Node::operator[](const Node& key) const {
|
inline const Node Node::operator[](const Node& key) const {
|
||||||
if (!m_isValid || !key.m_isValid)
|
|
||||||
throw InvalidNode();
|
|
||||||
EnsureNodeExists();
|
EnsureNodeExists();
|
||||||
key.EnsureNodeExists();
|
key.EnsureNodeExists();
|
||||||
m_pMemory->merge(*key.m_pMemory);
|
m_pMemory->merge(*key.m_pMemory);
|
||||||
detail::node* value =
|
detail::node* value =
|
||||||
static_cast<const detail::node&>(*m_pNode).get(*key.m_pNode, m_pMemory);
|
static_cast<const detail::node&>(*m_pNode).get(*key.m_pNode, m_pMemory);
|
||||||
if (!value) {
|
if (!value) {
|
||||||
return Node(ZombieNode);
|
return Node(ZombieNode, key_to_string(key));
|
||||||
}
|
}
|
||||||
return Node(*value, m_pMemory);
|
return Node(*value, m_pMemory);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Node Node::operator[](const Node& key) {
|
inline Node Node::operator[](const Node& key) {
|
||||||
if (!m_isValid || !key.m_isValid)
|
|
||||||
throw InvalidNode();
|
|
||||||
EnsureNodeExists();
|
EnsureNodeExists();
|
||||||
key.EnsureNodeExists();
|
key.EnsureNodeExists();
|
||||||
m_pMemory->merge(*key.m_pMemory);
|
m_pMemory->merge(*key.m_pMemory);
|
||||||
@@ -417,8 +368,6 @@ inline Node Node::operator[](const Node& key) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline bool Node::remove(const Node& key) {
|
inline bool Node::remove(const Node& key) {
|
||||||
if (!m_isValid || !key.m_isValid)
|
|
||||||
throw InvalidNode();
|
|
||||||
EnsureNodeExists();
|
EnsureNodeExists();
|
||||||
key.EnsureNodeExists();
|
key.EnsureNodeExists();
|
||||||
return m_pNode->remove(*key.m_pNode, m_pMemory);
|
return m_pNode->remove(*key.m_pNode, m_pMemory);
|
||||||
@@ -427,15 +376,12 @@ inline bool Node::remove(const Node& key) {
|
|||||||
// map
|
// map
|
||||||
template <typename Key, typename Value>
|
template <typename Key, typename Value>
|
||||||
inline void Node::force_insert(const Key& key, const Value& value) {
|
inline void Node::force_insert(const Key& key, const Value& value) {
|
||||||
if (!m_isValid)
|
|
||||||
throw InvalidNode();
|
|
||||||
EnsureNodeExists();
|
EnsureNodeExists();
|
||||||
m_pNode->force_insert(detail::to_value(key), detail::to_value(value),
|
m_pNode->force_insert(key, value, m_pMemory);
|
||||||
m_pMemory);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// free functions
|
// free functions
|
||||||
inline bool operator==(const Node& lhs, const Node& rhs) { return lhs.is(rhs); }
|
inline bool operator==(const Node& lhs, const Node& rhs) { return lhs.is(rhs); }
|
||||||
}
|
} // namespace YAML
|
||||||
|
|
||||||
#endif // NODE_IMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#endif // NODE_IMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|||||||
@@ -15,10 +15,13 @@
|
|||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
// Assert in place so gcc + libc++ combination properly builds
|
||||||
|
static_assert(std::is_constructible<YAML::Node, const YAML::Node&>::value, "Node must be copy constructable");
|
||||||
|
|
||||||
namespace YAML {
|
namespace YAML {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
struct iterator_value : public Node, std::pair<Node, Node> {
|
struct iterator_value : public Node, std::pair<Node, Node> {
|
||||||
iterator_value() {}
|
iterator_value() = default;
|
||||||
explicit iterator_value(const Node& rhs)
|
explicit iterator_value(const Node& rhs)
|
||||||
: Node(rhs),
|
: Node(rhs),
|
||||||
std::pair<Node, Node>(Node(Node::ZombieNode), Node(Node::ZombieNode)) {}
|
std::pair<Node, Node>(Node(Node::ZombieNode), Node(Node::ZombieNode)) {}
|
||||||
|
|||||||
@@ -8,10 +8,11 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#include "yaml-cpp/dll.h"
|
#include "yaml-cpp/dll.h"
|
||||||
#include "yaml-cpp/emitterstyle.h"
|
#include "yaml-cpp/emitterstyle.h"
|
||||||
#include "yaml-cpp/node/detail/bool_type.h"
|
#include "yaml-cpp/mark.h"
|
||||||
#include "yaml-cpp/node/detail/iterator_fwd.h"
|
#include "yaml-cpp/node/detail/iterator_fwd.h"
|
||||||
#include "yaml-cpp/node/ptr.h"
|
#include "yaml-cpp/node/ptr.h"
|
||||||
#include "yaml-cpp/node/type.h"
|
#include "yaml-cpp/node/type.h"
|
||||||
@@ -37,8 +38,8 @@ class YAML_CPP_API Node {
|
|||||||
template <typename T, typename S>
|
template <typename T, typename S>
|
||||||
friend struct as_if;
|
friend struct as_if;
|
||||||
|
|
||||||
typedef YAML::iterator iterator;
|
using iterator = YAML::iterator;
|
||||||
typedef YAML::const_iterator const_iterator;
|
using const_iterator = YAML::const_iterator;
|
||||||
|
|
||||||
Node();
|
Node();
|
||||||
explicit Node(NodeType::value type);
|
explicit Node(NodeType::value type);
|
||||||
@@ -48,6 +49,7 @@ class YAML_CPP_API Node {
|
|||||||
Node(const Node& rhs);
|
Node(const Node& rhs);
|
||||||
~Node();
|
~Node();
|
||||||
|
|
||||||
|
YAML::Mark Mark() const;
|
||||||
NodeType::value Type() const;
|
NodeType::value Type() const;
|
||||||
bool IsDefined() const;
|
bool IsDefined() const;
|
||||||
bool IsNull() const { return Type() == NodeType::Null; }
|
bool IsNull() const { return Type() == NodeType::Null; }
|
||||||
@@ -56,14 +58,14 @@ class YAML_CPP_API Node {
|
|||||||
bool IsMap() const { return Type() == NodeType::Map; }
|
bool IsMap() const { return Type() == NodeType::Map; }
|
||||||
|
|
||||||
// bool conversions
|
// bool conversions
|
||||||
YAML_CPP_OPERATOR_BOOL();
|
explicit operator bool() const { return IsDefined(); }
|
||||||
bool operator!() const { return !IsDefined(); }
|
bool operator!() const { return !IsDefined(); }
|
||||||
|
|
||||||
// access
|
// access
|
||||||
template <typename T>
|
template <typename T>
|
||||||
const T as() const;
|
T as() const;
|
||||||
template <typename T, typename S>
|
template <typename T, typename S>
|
||||||
const T as(const S& fallback) const;
|
T as(const S& fallback) const;
|
||||||
const std::string& Scalar() const;
|
const std::string& Scalar() const;
|
||||||
|
|
||||||
const std::string& Tag() const;
|
const std::string& Tag() const;
|
||||||
@@ -114,6 +116,7 @@ class YAML_CPP_API Node {
|
|||||||
private:
|
private:
|
||||||
enum Zombie { ZombieNode };
|
enum Zombie { ZombieNode };
|
||||||
explicit Node(Zombie);
|
explicit Node(Zombie);
|
||||||
|
explicit Node(Zombie, const std::string&);
|
||||||
explicit Node(detail::node& node, detail::shared_memory_holder pMemory);
|
explicit Node(detail::node& node, detail::shared_memory_holder pMemory);
|
||||||
|
|
||||||
void EnsureNodeExists() const;
|
void EnsureNodeExists() const;
|
||||||
@@ -128,6 +131,8 @@ class YAML_CPP_API Node {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
bool m_isValid;
|
bool m_isValid;
|
||||||
|
// String representation of invalid key, if the node is invalid.
|
||||||
|
std::string m_invalidKey;
|
||||||
mutable detail::shared_memory_holder m_pMemory;
|
mutable detail::shared_memory_holder m_pMemory;
|
||||||
mutable detail::node* m_pNode;
|
mutable detail::node* m_pNode;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -16,15 +16,63 @@
|
|||||||
namespace YAML {
|
namespace YAML {
|
||||||
class Node;
|
class Node;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads the input string as a single YAML document.
|
||||||
|
*
|
||||||
|
* @throws {@link ParserException} if it is malformed.
|
||||||
|
*/
|
||||||
YAML_CPP_API Node Load(const std::string& input);
|
YAML_CPP_API Node Load(const std::string& input);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads the input string as a single YAML document.
|
||||||
|
*
|
||||||
|
* @throws {@link ParserException} if it is malformed.
|
||||||
|
*/
|
||||||
YAML_CPP_API Node Load(const char* input);
|
YAML_CPP_API Node Load(const char* input);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads the input stream as a single YAML document.
|
||||||
|
*
|
||||||
|
* @throws {@link ParserException} if it is malformed.
|
||||||
|
*/
|
||||||
YAML_CPP_API Node Load(std::istream& input);
|
YAML_CPP_API Node Load(std::istream& input);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads the input file as a single YAML document.
|
||||||
|
*
|
||||||
|
* @throws {@link ParserException} if it is malformed.
|
||||||
|
* @throws {@link BadFile} if the file cannot be loaded.
|
||||||
|
*/
|
||||||
YAML_CPP_API Node LoadFile(const std::string& filename);
|
YAML_CPP_API Node LoadFile(const std::string& filename);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads the input string as a list of YAML documents.
|
||||||
|
*
|
||||||
|
* @throws {@link ParserException} if it is malformed.
|
||||||
|
*/
|
||||||
YAML_CPP_API std::vector<Node> LoadAll(const std::string& input);
|
YAML_CPP_API std::vector<Node> LoadAll(const std::string& input);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads the input string as a list of YAML documents.
|
||||||
|
*
|
||||||
|
* @throws {@link ParserException} if it is malformed.
|
||||||
|
*/
|
||||||
YAML_CPP_API std::vector<Node> LoadAll(const char* input);
|
YAML_CPP_API std::vector<Node> LoadAll(const char* input);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads the input stream as a list of YAML documents.
|
||||||
|
*
|
||||||
|
* @throws {@link ParserException} if it is malformed.
|
||||||
|
*/
|
||||||
YAML_CPP_API std::vector<Node> LoadAll(std::istream& input);
|
YAML_CPP_API std::vector<Node> LoadAll(std::istream& input);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads the input file as a list of YAML documents.
|
||||||
|
*
|
||||||
|
* @throws {@link ParserException} if it is malformed.
|
||||||
|
* @throws {@link BadFile} if the file cannot be loaded.
|
||||||
|
*/
|
||||||
YAML_CPP_API std::vector<Node> LoadAllFromFile(const std::string& filename);
|
YAML_CPP_API std::vector<Node> LoadAllFromFile(const std::string& filename);
|
||||||
}
|
} // namespace YAML
|
||||||
|
|
||||||
#endif // VALUE_PARSE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#endif // VALUE_PARSE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|||||||
@@ -7,8 +7,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "yaml-cpp/dll.h"
|
#include <memory>
|
||||||
#include <boost/shared_ptr.hpp>
|
|
||||||
|
|
||||||
namespace YAML {
|
namespace YAML {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
@@ -18,11 +17,11 @@ class node_data;
|
|||||||
class memory;
|
class memory;
|
||||||
class memory_holder;
|
class memory_holder;
|
||||||
|
|
||||||
typedef boost::shared_ptr<node> shared_node;
|
using shared_node = std::shared_ptr<node>;
|
||||||
typedef boost::shared_ptr<node_ref> shared_node_ref;
|
using shared_node_ref = std::shared_ptr<node_ref>;
|
||||||
typedef boost::shared_ptr<node_data> shared_node_data;
|
using shared_node_data = std::shared_ptr<node_data>;
|
||||||
typedef boost::shared_ptr<memory_holder> shared_memory_holder;
|
using shared_memory_holder = std::shared_ptr<memory_holder>;
|
||||||
typedef boost::shared_ptr<memory> shared_memory;
|
using shared_memory = std::shared_ptr<memory>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,9 +8,10 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace YAML {
|
namespace YAML {
|
||||||
struct NodeType {
|
namespace NodeType {
|
||||||
enum value { Undefined, Null, Scalar, Sequence, Map };
|
enum value { Undefined, Null, Scalar, Sequence, Map };
|
||||||
};
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // VALUE_TYPE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#endif // VALUE_TYPE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|||||||
18
include/yaml-cpp/noexcept.h
Normal file
18
include/yaml-cpp/noexcept.h
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
#ifndef NOEXCEPT_H_768872DA_476C_11EA_88B8_90B11C0C0FF8
|
||||||
|
#define NOEXCEPT_H_768872DA_476C_11EA_88B8_90B11C0C0FF8
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) || \
|
||||||
|
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||||
|
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||||
|
#pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// This is here for compatibility with older versions of Visual Studio
|
||||||
|
// which don't support noexcept.
|
||||||
|
#if defined(_MSC_VER) && _MSC_VER < 1900
|
||||||
|
#define YAML_CPP_NOEXCEPT _NOEXCEPT
|
||||||
|
#else
|
||||||
|
#define YAML_CPP_NOEXCEPT noexcept
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
#ifndef NONCOPYABLE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
|
||||||
#define NONCOPYABLE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
|
||||||
|
|
||||||
#if defined(_MSC_VER) || \
|
|
||||||
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
|
||||||
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
|
||||||
#pragma once
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "yaml-cpp/dll.h"
|
|
||||||
|
|
||||||
namespace YAML {
|
|
||||||
// this is basically boost::noncopyable
|
|
||||||
class YAML_CPP_API noncopyable {
|
|
||||||
protected:
|
|
||||||
noncopyable() {}
|
|
||||||
~noncopyable() {}
|
|
||||||
|
|
||||||
private:
|
|
||||||
noncopyable(const noncopyable&);
|
|
||||||
const noncopyable& operator=(const noncopyable&);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // NONCOPYABLE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
|
||||||
@@ -8,6 +8,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "yaml-cpp/dll.h"
|
#include "yaml-cpp/dll.h"
|
||||||
|
#include <cstddef>
|
||||||
|
|
||||||
namespace YAML {
|
namespace YAML {
|
||||||
class Node;
|
class Node;
|
||||||
@@ -17,6 +18,7 @@ inline bool operator==(const _Null&, const _Null&) { return true; }
|
|||||||
inline bool operator!=(const _Null&, const _Null&) { return false; }
|
inline bool operator!=(const _Null&, const _Null&) { return false; }
|
||||||
|
|
||||||
YAML_CPP_API bool IsNull(const Node& node); // old API only
|
YAML_CPP_API bool IsNull(const Node& node); // old API only
|
||||||
|
YAML_CPP_API bool IsNullString(const char* str, std::size_t size);
|
||||||
|
|
||||||
extern YAML_CPP_API _Null Null;
|
extern YAML_CPP_API _Null Null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,10 @@ class YAML_CPP_API ostream_wrapper {
|
|||||||
public:
|
public:
|
||||||
ostream_wrapper();
|
ostream_wrapper();
|
||||||
explicit ostream_wrapper(std::ostream& stream);
|
explicit ostream_wrapper(std::ostream& stream);
|
||||||
|
ostream_wrapper(const ostream_wrapper&) = delete;
|
||||||
|
ostream_wrapper(ostream_wrapper&&) = delete;
|
||||||
|
ostream_wrapper& operator=(const ostream_wrapper&) = delete;
|
||||||
|
ostream_wrapper& operator=(ostream_wrapper&&) = delete;
|
||||||
~ostream_wrapper();
|
~ostream_wrapper();
|
||||||
|
|
||||||
void write(const std::string& str);
|
void write(const std::string& str);
|
||||||
@@ -26,7 +30,7 @@ class YAML_CPP_API ostream_wrapper {
|
|||||||
|
|
||||||
const char* str() const {
|
const char* str() const {
|
||||||
if (m_pStream) {
|
if (m_pStream) {
|
||||||
return 0;
|
return nullptr;
|
||||||
} else {
|
} else {
|
||||||
m_buffer[m_pos] = '\0';
|
m_buffer[m_pos] = '\0';
|
||||||
return &m_buffer[0];
|
return &m_buffer[0];
|
||||||
@@ -52,7 +56,7 @@ class YAML_CPP_API ostream_wrapper {
|
|||||||
|
|
||||||
template <std::size_t N>
|
template <std::size_t N>
|
||||||
inline ostream_wrapper& operator<<(ostream_wrapper& stream,
|
inline ostream_wrapper& operator<<(ostream_wrapper& stream,
|
||||||
const char(&str)[N]) {
|
const char (&str)[N]) {
|
||||||
stream.write(str, N - 1);
|
stream.write(str, N - 1);
|
||||||
return stream;
|
return stream;
|
||||||
}
|
}
|
||||||
@@ -67,6 +71,6 @@ inline ostream_wrapper& operator<<(ostream_wrapper& stream, char ch) {
|
|||||||
stream.write(&ch, 1);
|
stream.write(&ch, 1);
|
||||||
return stream;
|
return stream;
|
||||||
}
|
}
|
||||||
}
|
} // namespace YAML
|
||||||
|
|
||||||
#endif // OSTREAM_WRAPPER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#endif // OSTREAM_WRAPPER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|||||||
@@ -11,7 +11,6 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#include "yaml-cpp/dll.h"
|
#include "yaml-cpp/dll.h"
|
||||||
#include "yaml-cpp/noncopyable.h"
|
|
||||||
|
|
||||||
namespace YAML {
|
namespace YAML {
|
||||||
class EventHandler;
|
class EventHandler;
|
||||||
@@ -20,29 +19,72 @@ class Scanner;
|
|||||||
struct Directives;
|
struct Directives;
|
||||||
struct Token;
|
struct Token;
|
||||||
|
|
||||||
class YAML_CPP_API Parser : private noncopyable {
|
/**
|
||||||
|
* A parser turns a stream of bytes into one stream of "events" per YAML
|
||||||
|
* document in the input stream.
|
||||||
|
*/
|
||||||
|
class YAML_CPP_API Parser {
|
||||||
public:
|
public:
|
||||||
|
/** Constructs an empty parser (with no input. */
|
||||||
Parser();
|
Parser();
|
||||||
Parser(std::istream& in);
|
|
||||||
|
Parser(const Parser&) = delete;
|
||||||
|
Parser(Parser&&) = delete;
|
||||||
|
Parser& operator=(const Parser&) = delete;
|
||||||
|
Parser& operator=(Parser&&) = delete;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a parser from the given input stream. The input stream must
|
||||||
|
* live as long as the parser.
|
||||||
|
*/
|
||||||
|
explicit Parser(std::istream& in);
|
||||||
|
|
||||||
~Parser();
|
~Parser();
|
||||||
|
|
||||||
operator bool() const;
|
/** Evaluates to true if the parser has some valid input to be read. */
|
||||||
|
explicit operator bool() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resets the parser with the given input stream. Any existing state is
|
||||||
|
* erased.
|
||||||
|
*/
|
||||||
void Load(std::istream& in);
|
void Load(std::istream& in);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles the next document by calling events on the {@code eventHandler}.
|
||||||
|
*
|
||||||
|
* @throw a ParserException on error.
|
||||||
|
* @return false if there are no more documents
|
||||||
|
*/
|
||||||
bool HandleNextDocument(EventHandler& eventHandler);
|
bool HandleNextDocument(EventHandler& eventHandler);
|
||||||
|
|
||||||
void PrintTokens(std::ostream& out);
|
void PrintTokens(std::ostream& out);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
/**
|
||||||
|
* Reads any directives that are next in the queue, setting the internal
|
||||||
|
* {@code m_pDirectives} state.
|
||||||
|
*/
|
||||||
void ParseDirectives();
|
void ParseDirectives();
|
||||||
|
|
||||||
void HandleDirective(const Token& token);
|
void HandleDirective(const Token& token);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles a "YAML" directive, which should be of the form 'major.minor' (like
|
||||||
|
* a version number).
|
||||||
|
*/
|
||||||
void HandleYamlDirective(const Token& token);
|
void HandleYamlDirective(const Token& token);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles a "TAG" directive, which should be of the form 'handle prefix',
|
||||||
|
* where 'handle' is converted to 'prefix' in the file.
|
||||||
|
*/
|
||||||
void HandleTagDirective(const Token& token);
|
void HandleTagDirective(const Token& token);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::auto_ptr<Scanner> m_pScanner;
|
std::unique_ptr<Scanner> m_pScanner;
|
||||||
std::auto_ptr<Directives> m_pDirectives;
|
std::unique_ptr<Directives> m_pDirectives;
|
||||||
};
|
};
|
||||||
}
|
} // namespace YAML
|
||||||
|
|
||||||
#endif // PARSER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#endif // PARSER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|||||||
@@ -16,8 +16,8 @@ namespace YAML {
|
|||||||
template <typename Seq>
|
template <typename Seq>
|
||||||
inline Emitter& EmitSeq(Emitter& emitter, const Seq& seq) {
|
inline Emitter& EmitSeq(Emitter& emitter, const Seq& seq) {
|
||||||
emitter << BeginSeq;
|
emitter << BeginSeq;
|
||||||
for (typename Seq::const_iterator it = seq.begin(); it != seq.end(); ++it)
|
for (const auto& v : seq)
|
||||||
emitter << *it;
|
emitter << v;
|
||||||
emitter << EndSeq;
|
emitter << EndSeq;
|
||||||
return emitter;
|
return emitter;
|
||||||
}
|
}
|
||||||
@@ -39,10 +39,9 @@ inline Emitter& operator<<(Emitter& emitter, const std::set<T>& v) {
|
|||||||
|
|
||||||
template <typename K, typename V>
|
template <typename K, typename V>
|
||||||
inline Emitter& operator<<(Emitter& emitter, const std::map<K, V>& m) {
|
inline Emitter& operator<<(Emitter& emitter, const std::map<K, V>& m) {
|
||||||
typedef typename std::map<K, V> map;
|
|
||||||
emitter << BeginMap;
|
emitter << BeginMap;
|
||||||
for (typename map::const_iterator it = m.begin(); it != m.end(); ++it)
|
for (const auto& v : m)
|
||||||
emitter << Key << it->first << Value << it->second;
|
emitter << Key << v.first << Value << v.second;
|
||||||
emitter << EndMap;
|
emitter << EndMap;
|
||||||
return emitter;
|
return emitter;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,11 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <type_traits>
|
||||||
|
#include <utility>
|
||||||
|
#include <string>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
namespace YAML {
|
namespace YAML {
|
||||||
template <typename>
|
template <typename>
|
||||||
struct is_numeric {
|
struct is_numeric {
|
||||||
@@ -79,7 +84,7 @@ struct is_numeric<long double> {
|
|||||||
|
|
||||||
template <bool, class T = void>
|
template <bool, class T = void>
|
||||||
struct enable_if_c {
|
struct enable_if_c {
|
||||||
typedef T type;
|
using type = T;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
@@ -90,7 +95,7 @@ struct enable_if : public enable_if_c<Cond::value, T> {};
|
|||||||
|
|
||||||
template <bool, class T = void>
|
template <bool, class T = void>
|
||||||
struct disable_if_c {
|
struct disable_if_c {
|
||||||
typedef T type;
|
using type = T;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
@@ -100,4 +105,32 @@ template <class Cond, class T = void>
|
|||||||
struct disable_if : public disable_if_c<Cond::value, T> {};
|
struct disable_if : public disable_if_c<Cond::value, T> {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename S, typename T>
|
||||||
|
struct is_streamable {
|
||||||
|
template <typename StreamT, typename ValueT>
|
||||||
|
static auto test(int)
|
||||||
|
-> decltype(std::declval<StreamT&>() << std::declval<ValueT>(), std::true_type());
|
||||||
|
|
||||||
|
template <typename, typename>
|
||||||
|
static auto test(...) -> std::false_type;
|
||||||
|
|
||||||
|
static const bool value = decltype(test<S, T>(0))::value;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename Key, bool Streamable>
|
||||||
|
struct streamable_to_string {
|
||||||
|
static std::string impl(const Key& key) {
|
||||||
|
std::stringstream ss;
|
||||||
|
ss.imbue(std::locale::classic());
|
||||||
|
ss << key;
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename Key>
|
||||||
|
struct streamable_to_string<Key, false> {
|
||||||
|
static std::string impl(const Key&) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
};
|
||||||
#endif // TRAITS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#endif // TRAITS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
#include "yaml-cpp/binary.h"
|
#include "yaml-cpp/binary.h"
|
||||||
|
|
||||||
|
#include <cctype>
|
||||||
|
|
||||||
namespace YAML {
|
namespace YAML {
|
||||||
static const char encoding[] =
|
static const char encoding[] =
|
||||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||||
@@ -64,7 +66,7 @@ static const unsigned char decoding[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
std::vector<unsigned char> DecodeBase64(const std::string &input) {
|
std::vector<unsigned char> DecodeBase64(const std::string &input) {
|
||||||
typedef std::vector<unsigned char> ret_type;
|
using ret_type = std::vector<unsigned char>;
|
||||||
if (input.empty())
|
if (input.empty())
|
||||||
return ret_type();
|
return ret_type();
|
||||||
|
|
||||||
@@ -72,22 +74,27 @@ std::vector<unsigned char> DecodeBase64(const std::string &input) {
|
|||||||
unsigned char *out = &ret[0];
|
unsigned char *out = &ret[0];
|
||||||
|
|
||||||
unsigned value = 0;
|
unsigned value = 0;
|
||||||
for (std::size_t i = 0; i < input.size(); i++) {
|
for (std::size_t i = 0, cnt = 0; i < input.size(); i++) {
|
||||||
unsigned char d = decoding[static_cast<unsigned>(input[i])];
|
if (std::isspace(static_cast<unsigned char>(input[i]))) {
|
||||||
|
// skip newlines
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
unsigned char d = decoding[static_cast<unsigned char>(input[i])];
|
||||||
if (d == 255)
|
if (d == 255)
|
||||||
return ret_type();
|
return ret_type();
|
||||||
|
|
||||||
value = (value << 6) | d;
|
value = (value << 6) | d;
|
||||||
if (i % 4 == 3) {
|
if (cnt % 4 == 3) {
|
||||||
*out++ = value >> 16;
|
*out++ = value >> 16;
|
||||||
if (i > 0 && input[i - 1] != '=')
|
if (i > 0 && input[i - 1] != '=')
|
||||||
*out++ = value >> 8;
|
*out++ = value >> 8;
|
||||||
if (input[i] != '=')
|
if (input[i] != '=')
|
||||||
*out++ = value;
|
*out++ = value;
|
||||||
}
|
}
|
||||||
|
++cnt;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret.resize(out - &ret[0]);
|
ret.resize(out - &ret[0]);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
} // namespace YAML
|
||||||
|
|||||||
@@ -7,8 +7,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <stack>
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
#include <stack>
|
||||||
|
|
||||||
namespace YAML {
|
namespace YAML {
|
||||||
struct CollectionType {
|
struct CollectionType {
|
||||||
@@ -17,6 +17,7 @@ struct CollectionType {
|
|||||||
|
|
||||||
class CollectionStack {
|
class CollectionStack {
|
||||||
public:
|
public:
|
||||||
|
CollectionStack() : collectionStack{} {}
|
||||||
CollectionType::value GetCurCollectionType() const {
|
CollectionType::value GetCurCollectionType() const {
|
||||||
if (collectionStack.empty())
|
if (collectionStack.empty())
|
||||||
return CollectionType::NoCollection;
|
return CollectionType::NoCollection;
|
||||||
@@ -28,12 +29,13 @@ class CollectionStack {
|
|||||||
}
|
}
|
||||||
void PopCollectionType(CollectionType::value type) {
|
void PopCollectionType(CollectionType::value type) {
|
||||||
assert(type == GetCurCollectionType());
|
assert(type == GetCurCollectionType());
|
||||||
|
(void)type;
|
||||||
collectionStack.pop();
|
collectionStack.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::stack<CollectionType::value> collectionStack;
|
std::stack<CollectionType::value> collectionStack;
|
||||||
};
|
};
|
||||||
}
|
} // namespace YAML
|
||||||
|
|
||||||
#endif // COLLECTIONSTACK_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#endif // COLLECTIONSTACK_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|||||||
4196
src/contrib/dragonbox.h
Normal file
4196
src/contrib/dragonbox.h
Normal file
File diff suppressed because it is too large
Load Diff
@@ -10,8 +10,7 @@ void* BuildGraphOfNextDocument(Parser& parser,
|
|||||||
GraphBuilderAdapter eventHandler(graphBuilder);
|
GraphBuilderAdapter eventHandler(graphBuilder);
|
||||||
if (parser.HandleNextDocument(eventHandler)) {
|
if (parser.HandleNextDocument(eventHandler)) {
|
||||||
return eventHandler.RootNode();
|
return eventHandler.RootNode();
|
||||||
} else {
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
} // namespace YAML
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ void GraphBuilderAdapter::OnMapStart(const Mark &mark, const std::string &tag,
|
|||||||
EmitterStyle::value /* style */) {
|
EmitterStyle::value /* style */) {
|
||||||
void *pNode = m_builder.NewMap(mark, tag, GetCurrentParent());
|
void *pNode = m_builder.NewMap(mark, tag, GetCurrentParent());
|
||||||
m_containers.push(ContainerFrame(pNode, m_pKeyNode));
|
m_containers.push(ContainerFrame(pNode, m_pKeyNode));
|
||||||
m_pKeyNode = NULL;
|
m_pKeyNode = nullptr;
|
||||||
RegisterAnchor(anchor, pNode);
|
RegisterAnchor(anchor, pNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -62,7 +62,7 @@ void GraphBuilderAdapter::OnMapEnd() {
|
|||||||
|
|
||||||
void *GraphBuilderAdapter::GetCurrentParent() const {
|
void *GraphBuilderAdapter::GetCurrentParent() const {
|
||||||
if (m_containers.empty()) {
|
if (m_containers.empty()) {
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
return m_containers.top().pContainer;
|
return m_containers.top().pContainer;
|
||||||
}
|
}
|
||||||
@@ -83,7 +83,7 @@ void GraphBuilderAdapter::DispositionNode(void *pNode) {
|
|||||||
if (m_containers.top().isMap()) {
|
if (m_containers.top().isMap()) {
|
||||||
if (m_pKeyNode) {
|
if (m_pKeyNode) {
|
||||||
m_builder.AssignInMap(pContainer, m_pKeyNode, pNode);
|
m_builder.AssignInMap(pContainer, m_pKeyNode, pNode);
|
||||||
m_pKeyNode = NULL;
|
m_pKeyNode = nullptr;
|
||||||
} else {
|
} else {
|
||||||
m_pKeyNode = pNode;
|
m_pKeyNode = pNode;
|
||||||
}
|
}
|
||||||
@@ -91,4 +91,4 @@ void GraphBuilderAdapter::DispositionNode(void *pNode) {
|
|||||||
m_builder.AppendToSequence(pContainer, pNode);
|
m_builder.AppendToSequence(pContainer, pNode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} // namespace YAML
|
||||||
|
|||||||
@@ -13,7 +13,6 @@
|
|||||||
|
|
||||||
#include "yaml-cpp/anchor.h"
|
#include "yaml-cpp/anchor.h"
|
||||||
#include "yaml-cpp/contrib/anchordict.h"
|
#include "yaml-cpp/contrib/anchordict.h"
|
||||||
#include "yaml-cpp/contrib/graphbuilder.h"
|
|
||||||
#include "yaml-cpp/emitterstyle.h"
|
#include "yaml-cpp/emitterstyle.h"
|
||||||
#include "yaml-cpp/eventhandler.h"
|
#include "yaml-cpp/eventhandler.h"
|
||||||
|
|
||||||
@@ -26,7 +25,15 @@ namespace YAML {
|
|||||||
class GraphBuilderAdapter : public EventHandler {
|
class GraphBuilderAdapter : public EventHandler {
|
||||||
public:
|
public:
|
||||||
GraphBuilderAdapter(GraphBuilderInterface& builder)
|
GraphBuilderAdapter(GraphBuilderInterface& builder)
|
||||||
: m_builder(builder), m_pRootNode(NULL), m_pKeyNode(NULL) {}
|
: m_builder(builder),
|
||||||
|
m_containers{},
|
||||||
|
m_anchors{},
|
||||||
|
m_pRootNode(nullptr),
|
||||||
|
m_pKeyNode(nullptr) {}
|
||||||
|
GraphBuilderAdapter(const GraphBuilderAdapter&) = delete;
|
||||||
|
GraphBuilderAdapter(GraphBuilderAdapter&&) = delete;
|
||||||
|
GraphBuilderAdapter& operator=(const GraphBuilderAdapter&) = delete;
|
||||||
|
GraphBuilderAdapter& operator=(GraphBuilderAdapter&&) = delete;
|
||||||
|
|
||||||
virtual void OnDocumentStart(const Mark& mark) { (void)mark; }
|
virtual void OnDocumentStart(const Mark& mark) { (void)mark; }
|
||||||
virtual void OnDocumentEnd() {}
|
virtual void OnDocumentEnd() {}
|
||||||
@@ -50,8 +57,8 @@ class GraphBuilderAdapter : public EventHandler {
|
|||||||
struct ContainerFrame {
|
struct ContainerFrame {
|
||||||
ContainerFrame(void* pSequence)
|
ContainerFrame(void* pSequence)
|
||||||
: pContainer(pSequence), pPrevKeyNode(&sequenceMarker) {}
|
: pContainer(pSequence), pPrevKeyNode(&sequenceMarker) {}
|
||||||
ContainerFrame(void* pMap, void* pPrevKeyNode)
|
ContainerFrame(void* pMap, void* pPreviousKeyNode)
|
||||||
: pContainer(pMap), pPrevKeyNode(pPrevKeyNode) {}
|
: pContainer(pMap), pPrevKeyNode(pPreviousKeyNode) {}
|
||||||
|
|
||||||
void* pContainer;
|
void* pContainer;
|
||||||
void* pPrevKeyNode;
|
void* pPrevKeyNode;
|
||||||
@@ -74,6 +81,6 @@ class GraphBuilderAdapter : public EventHandler {
|
|||||||
void RegisterAnchor(anchor_t anchor, void* pNode);
|
void RegisterAnchor(anchor_t anchor, void* pNode);
|
||||||
void DispositionNode(void* pNode);
|
void DispositionNode(void* pNode);
|
||||||
};
|
};
|
||||||
}
|
} // namespace YAML
|
||||||
|
|
||||||
#endif // GRAPHBUILDERADAPTER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#endif // GRAPHBUILDERADAPTER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|||||||
32
src/contrib/yaml-cpp.natvis
Normal file
32
src/contrib/yaml-cpp.natvis
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- MSVC Debugger visualization hints for YAML::Node and YAML::detail::node -->
|
||||||
|
<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
|
||||||
|
<Type Name="YAML::Node">
|
||||||
|
<DisplayString Condition="!m_isValid">{{invalid}}</DisplayString>
|
||||||
|
<DisplayString Condition="!m_pNode">{{pNode==nullptr}}</DisplayString>
|
||||||
|
<DisplayString>{{ {*m_pNode} }}</DisplayString>
|
||||||
|
<Expand>
|
||||||
|
<Item Condition="m_pNode->m_pRef._Ptr->m_pData._Ptr->m_type==YAML::NodeType::Scalar" Name="scalar">m_pNode->m_pRef._Ptr->m_pData._Ptr->m_scalar</Item>
|
||||||
|
<Item Condition="m_pNode->m_pRef._Ptr->m_pData._Ptr->m_type==YAML::NodeType::Sequence" Name="sequence">m_pNode->m_pRef._Ptr->m_pData._Ptr->m_sequence</Item>
|
||||||
|
<Item Condition="m_pNode->m_pRef._Ptr->m_pData._Ptr->m_type==YAML::NodeType::Map" Name="map">m_pNode->m_pRef._Ptr->m_pData._Ptr->m_map</Item>
|
||||||
|
<Item Name="[details]" >m_pNode->m_pRef._Ptr->m_pData._Ptr</Item>
|
||||||
|
</Expand>
|
||||||
|
</Type>
|
||||||
|
|
||||||
|
<Type Name="YAML::detail::node">
|
||||||
|
<DisplayString Condition="!m_pRef._Ptr">{{node:pRef==nullptr}}</DisplayString>
|
||||||
|
<DisplayString Condition="!m_pRef._Ptr->m_pData._Ptr">{{node:pRef->pData==nullptr}}</DisplayString>
|
||||||
|
<DisplayString Condition="!m_pRef._Ptr->m_pData._Ptr->m_isDefined">{{undefined}}</DisplayString>
|
||||||
|
<DisplayString Condition="m_pRef._Ptr->m_pData._Ptr->m_type==YAML::NodeType::Scalar">{{{m_pRef._Ptr->m_pData._Ptr->m_scalar}}}</DisplayString>
|
||||||
|
<DisplayString Condition="m_pRef._Ptr->m_pData._Ptr->m_type==YAML::NodeType::Map">{{ Map {m_pRef._Ptr->m_pData._Ptr->m_map}}}</DisplayString>
|
||||||
|
<DisplayString Condition="m_pRef._Ptr->m_pData._Ptr->m_type==YAML::NodeType::Sequence">{{ Seq {m_pRef._Ptr->m_pData._Ptr->m_sequence}}}</DisplayString>
|
||||||
|
<DisplayString>{{{m_pRef._Ptr->m_pData._Ptr->m_type}}}</DisplayString>
|
||||||
|
<Expand>
|
||||||
|
<Item Condition="m_pRef._Ptr->m_pData._Ptr->m_type==YAML::NodeType::Scalar" Name="scalar">m_pRef._Ptr->m_pData._Ptr->m_scalar</Item>
|
||||||
|
<Item Condition="m_pRef._Ptr->m_pData._Ptr->m_type==YAML::NodeType::Sequence" Name="sequence">m_pRef._Ptr->m_pData._Ptr->m_sequence</Item>
|
||||||
|
<Item Condition="m_pRef._Ptr->m_pData._Ptr->m_type==YAML::NodeType::Map" Name="map">m_pRef._Ptr->m_pData._Ptr->m_map</Item>
|
||||||
|
<Item Name="[details]" >m_pRef._Ptr->m_pData._Ptr</Item>
|
||||||
|
</Expand>
|
||||||
|
</Type>
|
||||||
|
|
||||||
|
</AutoVisualizer>
|
||||||
9
src/contrib/yaml-cpp.natvis.md
Normal file
9
src/contrib/yaml-cpp.natvis.md
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
# MSVC debugger visualizer for YAML::Node
|
||||||
|
|
||||||
|
## How to use
|
||||||
|
Add yaml-cpp.natvis to your Visual C++ project like any other source file. It will be included in the debug information, and improve debugger display on YAML::Node and contained types.
|
||||||
|
|
||||||
|
## Compatibility and Troubleshooting
|
||||||
|
|
||||||
|
This has been tested for MSVC 2017. It is expected to be compatible with VS 2015 and VS 2019. If you have any problems, you can open an issue here: https://github.com/peterchen-cp/yaml-cpp-natvis
|
||||||
|
|
||||||
@@ -16,11 +16,7 @@ std::string tolower(const std::string& str) {
|
|||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
bool IsEntirely(const std::string& str, T func) {
|
bool IsEntirely(const std::string& str, T func) {
|
||||||
for (std::size_t i = 0; i < str.size(); i++)
|
return std::all_of(str.begin(), str.end(), [=](char ch) { return func(ch); });
|
||||||
if (!func(str[i]))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsFlexibleCase
|
// IsFlexibleCase
|
||||||
@@ -39,7 +35,7 @@ bool IsFlexibleCase(const std::string& str) {
|
|||||||
std::string rest = str.substr(1);
|
std::string rest = str.substr(1);
|
||||||
return firstcaps && (IsEntirely(rest, IsLower) || IsEntirely(rest, IsUpper));
|
return firstcaps && (IsEntirely(rest, IsLower) || IsEntirely(rest, IsUpper));
|
||||||
}
|
}
|
||||||
}
|
} // namespace
|
||||||
|
|
||||||
namespace YAML {
|
namespace YAML {
|
||||||
bool convert<bool>::decode(const Node& node, bool& rhs) {
|
bool convert<bool>::decode(const Node& node, bool& rhs) {
|
||||||
@@ -52,19 +48,22 @@ bool convert<bool>::decode(const Node& node, bool& rhs) {
|
|||||||
static const struct {
|
static const struct {
|
||||||
std::string truename, falsename;
|
std::string truename, falsename;
|
||||||
} names[] = {
|
} names[] = {
|
||||||
{"y", "n"}, {"yes", "no"}, {"true", "false"}, {"on", "off"},
|
{"y", "n"},
|
||||||
|
{"yes", "no"},
|
||||||
|
{"true", "false"},
|
||||||
|
{"on", "off"},
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!IsFlexibleCase(node.Scalar()))
|
if (!IsFlexibleCase(node.Scalar()))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
for (unsigned i = 0; i < sizeof(names) / sizeof(names[0]); i++) {
|
for (const auto& name : names) {
|
||||||
if (names[i].truename == tolower(node.Scalar())) {
|
if (name.truename == tolower(node.Scalar())) {
|
||||||
rhs = true;
|
rhs = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (names[i].falsename == tolower(node.Scalar())) {
|
if (name.falsename == tolower(node.Scalar())) {
|
||||||
rhs = false;
|
rhs = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -72,4 +71,4 @@ bool convert<bool>::decode(const Node& node, bool& rhs) {
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
} // namespace YAML
|
||||||
|
|||||||
9
src/depthguard.cpp
Normal file
9
src/depthguard.cpp
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
#include "yaml-cpp/depthguard.h"
|
||||||
|
|
||||||
|
namespace YAML {
|
||||||
|
|
||||||
|
DeepRecursion::DeepRecursion(int depth, const Mark& mark_,
|
||||||
|
const std::string& msg_)
|
||||||
|
: ParserException(mark_, msg_), m_depth(depth) {}
|
||||||
|
|
||||||
|
} // namespace YAML
|
||||||
@@ -1,16 +1,11 @@
|
|||||||
#include "directives.h"
|
#include "directives.h"
|
||||||
|
|
||||||
namespace YAML {
|
namespace YAML {
|
||||||
Directives::Directives() {
|
Directives::Directives() : version{true, 1, 2}, tags{} {}
|
||||||
// version
|
|
||||||
version.isDefault = true;
|
|
||||||
version.major = 1;
|
|
||||||
version.minor = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::string Directives::TranslateTagHandle(
|
std::string Directives::TranslateTagHandle(
|
||||||
const std::string& handle) const {
|
const std::string& handle) const {
|
||||||
std::map<std::string, std::string>::const_iterator it = tags.find(handle);
|
auto it = tags.find(handle);
|
||||||
if (it == tags.end()) {
|
if (it == tags.end()) {
|
||||||
if (handle == "!!")
|
if (handle == "!!")
|
||||||
return "tag:yaml.org,2002:";
|
return "tag:yaml.org,2002:";
|
||||||
@@ -19,4 +14,4 @@ const std::string Directives::TranslateTagHandle(
|
|||||||
|
|
||||||
return it->second;
|
return it->second;
|
||||||
}
|
}
|
||||||
}
|
} // namespace YAML
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ struct Version {
|
|||||||
struct Directives {
|
struct Directives {
|
||||||
Directives();
|
Directives();
|
||||||
|
|
||||||
const std::string TranslateTagHandle(const std::string& handle) const;
|
std::string TranslateTagHandle(const std::string& handle) const;
|
||||||
|
|
||||||
Version version;
|
Version version;
|
||||||
std::map<std::string, std::string> tags;
|
std::map<std::string, std::string> tags;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#include "yaml-cpp/node/emit.h"
|
#include "yaml-cpp/node/emit.h"
|
||||||
|
#include "nodeevents.h"
|
||||||
#include "yaml-cpp/emitfromevents.h"
|
#include "yaml-cpp/emitfromevents.h"
|
||||||
#include "yaml-cpp/emitter.h"
|
#include "yaml-cpp/emitter.h"
|
||||||
#include "nodeevents.h"
|
|
||||||
|
|
||||||
namespace YAML {
|
namespace YAML {
|
||||||
Emitter& operator<<(Emitter& out, const Node& node) {
|
Emitter& operator<<(Emitter& out, const Node& node) {
|
||||||
@@ -22,4 +22,4 @@ std::string Dump(const Node& node) {
|
|||||||
emitter << node;
|
emitter << node;
|
||||||
return emitter.c_str();
|
return emitter.c_str();
|
||||||
}
|
}
|
||||||
}
|
} // namespace YAML
|
||||||
|
|||||||
@@ -16,10 +16,11 @@ std::string ToString(YAML::anchor_t anchor) {
|
|||||||
stream << anchor;
|
stream << anchor;
|
||||||
return stream.str();
|
return stream.str();
|
||||||
}
|
}
|
||||||
}
|
} // namespace
|
||||||
|
|
||||||
namespace YAML {
|
namespace YAML {
|
||||||
EmitFromEvents::EmitFromEvents(Emitter& emitter) : m_emitter(emitter) {}
|
EmitFromEvents::EmitFromEvents(Emitter& emitter)
|
||||||
|
: m_emitter(emitter), m_stateStack{} {}
|
||||||
|
|
||||||
void EmitFromEvents::OnDocumentStart(const Mark&) {}
|
void EmitFromEvents::OnDocumentStart(const Mark&) {}
|
||||||
|
|
||||||
@@ -58,6 +59,8 @@ void EmitFromEvents::OnSequenceStart(const Mark&, const std::string& tag,
|
|||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
// Restore the global settings to eliminate the override from node style
|
||||||
|
m_emitter.RestoreGlobalModifiedSettings();
|
||||||
m_emitter << BeginSeq;
|
m_emitter << BeginSeq;
|
||||||
m_stateStack.push(State::WaitingForSequenceEntry);
|
m_stateStack.push(State::WaitingForSequenceEntry);
|
||||||
}
|
}
|
||||||
@@ -82,6 +85,8 @@ void EmitFromEvents::OnMapStart(const Mark&, const std::string& tag,
|
|||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
// Restore the global settings to eliminate the override from node style
|
||||||
|
m_emitter.RestoreGlobalModifiedSettings();
|
||||||
m_emitter << BeginMap;
|
m_emitter << BeginMap;
|
||||||
m_stateStack.push(State::WaitingForKey);
|
m_stateStack.push(State::WaitingForKey);
|
||||||
}
|
}
|
||||||
@@ -111,9 +116,14 @@ void EmitFromEvents::BeginNode() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void EmitFromEvents::EmitProps(const std::string& tag, anchor_t anchor) {
|
void EmitFromEvents::EmitProps(const std::string& tag, anchor_t anchor) {
|
||||||
if (!tag.empty() && tag != "?")
|
if (!tag.empty() && tag != "?" && tag != "!"){
|
||||||
m_emitter << VerbatimTag(tag);
|
if (tag[0] == '!') {
|
||||||
|
m_emitter << LocalTag(std::string(tag.begin()+1, tag.end()));
|
||||||
|
} else {
|
||||||
|
m_emitter << VerbatimTag(tag);
|
||||||
|
}
|
||||||
|
}
|
||||||
if (anchor)
|
if (anchor)
|
||||||
m_emitter << Anchor(ToString(anchor));
|
m_emitter << Anchor(ToString(anchor));
|
||||||
}
|
}
|
||||||
}
|
} // namespace YAML
|
||||||
|
|||||||
118
src/emitter.cpp
118
src/emitter.cpp
@@ -11,12 +11,12 @@ namespace YAML {
|
|||||||
class Binary;
|
class Binary;
|
||||||
struct _Null;
|
struct _Null;
|
||||||
|
|
||||||
Emitter::Emitter() : m_pState(new EmitterState) {}
|
Emitter::Emitter() : m_pState(new EmitterState), m_stream{} {}
|
||||||
|
|
||||||
Emitter::Emitter(std::ostream& stream)
|
Emitter::Emitter(std::ostream& stream)
|
||||||
: m_pState(new EmitterState), m_stream(stream) {}
|
: m_pState(new EmitterState), m_stream(stream) {}
|
||||||
|
|
||||||
Emitter::~Emitter() {}
|
Emitter::~Emitter() = default;
|
||||||
|
|
||||||
const char* Emitter::c_str() const { return m_stream.str(); }
|
const char* Emitter::c_str() const { return m_stream.str(); }
|
||||||
|
|
||||||
@@ -49,6 +49,10 @@ bool Emitter::SetBoolFormat(EMITTER_MANIP value) {
|
|||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Emitter::SetNullFormat(EMITTER_MANIP value) {
|
||||||
|
return m_pState->SetNullFormat(value, FmtScope::Global);
|
||||||
|
}
|
||||||
|
|
||||||
bool Emitter::SetIntBase(EMITTER_MANIP value) {
|
bool Emitter::SetIntBase(EMITTER_MANIP value) {
|
||||||
return m_pState->SetIntFormat(value, FmtScope::Global);
|
return m_pState->SetIntFormat(value, FmtScope::Global);
|
||||||
}
|
}
|
||||||
@@ -86,6 +90,10 @@ bool Emitter::SetDoublePrecision(std::size_t n) {
|
|||||||
return m_pState->SetDoublePrecision(n, FmtScope::Global);
|
return m_pState->SetDoublePrecision(n, FmtScope::Global);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Emitter::RestoreGlobalModifiedSettings() {
|
||||||
|
m_pState->RestoreGlobalModifiedSettings();
|
||||||
|
}
|
||||||
|
|
||||||
// SetLocalValue
|
// SetLocalValue
|
||||||
// . Either start/end a group, or set a modifier locally
|
// . Either start/end a group, or set a modifier locally
|
||||||
Emitter& Emitter::SetLocalValue(EMITTER_MANIP value) {
|
Emitter& Emitter::SetLocalValue(EMITTER_MANIP value) {
|
||||||
@@ -197,6 +205,7 @@ void Emitter::EmitBeginSeq() {
|
|||||||
void Emitter::EmitEndSeq() {
|
void Emitter::EmitEndSeq() {
|
||||||
if (!good())
|
if (!good())
|
||||||
return;
|
return;
|
||||||
|
FlowType::value originalType = m_pState->CurGroupFlowType();
|
||||||
|
|
||||||
if (m_pState->CurGroupChildCount() == 0)
|
if (m_pState->CurGroupChildCount() == 0)
|
||||||
m_pState->ForceFlow();
|
m_pState->ForceFlow();
|
||||||
@@ -204,9 +213,14 @@ void Emitter::EmitEndSeq() {
|
|||||||
if (m_pState->CurGroupFlowType() == FlowType::Flow) {
|
if (m_pState->CurGroupFlowType() == FlowType::Flow) {
|
||||||
if (m_stream.comment())
|
if (m_stream.comment())
|
||||||
m_stream << "\n";
|
m_stream << "\n";
|
||||||
m_stream << IndentTo(m_pState->CurIndent());
|
if (originalType == FlowType::Block || m_pState->HasBegunNode())
|
||||||
if (m_pState->CurGroupChildCount() == 0)
|
m_stream << IndentTo(m_pState->CurIndent());
|
||||||
|
if (originalType == FlowType::Block) {
|
||||||
m_stream << "[";
|
m_stream << "[";
|
||||||
|
} else {
|
||||||
|
if (m_pState->CurGroupChildCount() == 0 && !m_pState->HasBegunNode())
|
||||||
|
m_stream << "[";
|
||||||
|
}
|
||||||
m_stream << "]";
|
m_stream << "]";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -227,6 +241,7 @@ void Emitter::EmitBeginMap() {
|
|||||||
void Emitter::EmitEndMap() {
|
void Emitter::EmitEndMap() {
|
||||||
if (!good())
|
if (!good())
|
||||||
return;
|
return;
|
||||||
|
FlowType::value originalType = m_pState->CurGroupFlowType();
|
||||||
|
|
||||||
if (m_pState->CurGroupChildCount() == 0)
|
if (m_pState->CurGroupChildCount() == 0)
|
||||||
m_pState->ForceFlow();
|
m_pState->ForceFlow();
|
||||||
@@ -235,8 +250,12 @@ void Emitter::EmitEndMap() {
|
|||||||
if (m_stream.comment())
|
if (m_stream.comment())
|
||||||
m_stream << "\n";
|
m_stream << "\n";
|
||||||
m_stream << IndentTo(m_pState->CurIndent());
|
m_stream << IndentTo(m_pState->CurIndent());
|
||||||
if (m_pState->CurGroupChildCount() == 0)
|
if (originalType == FlowType::Block) {
|
||||||
m_stream << "{";
|
m_stream << "{";
|
||||||
|
} else {
|
||||||
|
if (m_pState->CurGroupChildCount() == 0 && !m_pState->HasBegunNode())
|
||||||
|
m_stream << "{";
|
||||||
|
}
|
||||||
m_stream << "}";
|
m_stream << "}";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -285,10 +304,8 @@ void Emitter::PrepareTopNode(EmitterNodeType::value child) {
|
|||||||
if (child == EmitterNodeType::NoType)
|
if (child == EmitterNodeType::NoType)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (m_pState->CurGroupChildCount() > 0 && m_stream.col() > 0) {
|
if (m_pState->CurGroupChildCount() > 0 && m_stream.col() > 0)
|
||||||
if (child != EmitterNodeType::NoType)
|
EmitBeginDoc();
|
||||||
EmitBeginDoc();
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (child) {
|
switch (child) {
|
||||||
case EmitterNodeType::NoType:
|
case EmitterNodeType::NoType:
|
||||||
@@ -488,6 +505,9 @@ void Emitter::FlowMapPrepareSimpleKeyValue(EmitterNodeType::value child) {
|
|||||||
if (m_stream.comment())
|
if (m_stream.comment())
|
||||||
m_stream << "\n";
|
m_stream << "\n";
|
||||||
m_stream << IndentTo(lastIndent);
|
m_stream << IndentTo(lastIndent);
|
||||||
|
if (m_pState->HasAlias()) {
|
||||||
|
m_stream << " ";
|
||||||
|
}
|
||||||
m_stream << ":";
|
m_stream << ":";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -514,7 +534,8 @@ void Emitter::BlockMapPrepareNode(EmitterNodeType::value child) {
|
|||||||
if (m_pState->GetMapKeyFormat() == LongKey)
|
if (m_pState->GetMapKeyFormat() == LongKey)
|
||||||
m_pState->SetLongKey();
|
m_pState->SetLongKey();
|
||||||
if (child == EmitterNodeType::BlockSeq ||
|
if (child == EmitterNodeType::BlockSeq ||
|
||||||
child == EmitterNodeType::BlockMap)
|
child == EmitterNodeType::BlockMap ||
|
||||||
|
child == EmitterNodeType::Property)
|
||||||
m_pState->SetLongKey();
|
m_pState->SetLongKey();
|
||||||
|
|
||||||
if (m_pState->CurGroupLongKey())
|
if (m_pState->CurGroupLongKey())
|
||||||
@@ -558,6 +579,8 @@ void Emitter::BlockMapPrepareLongKey(EmitterNodeType::value child) {
|
|||||||
break;
|
break;
|
||||||
case EmitterNodeType::BlockSeq:
|
case EmitterNodeType::BlockSeq:
|
||||||
case EmitterNodeType::BlockMap:
|
case EmitterNodeType::BlockMap:
|
||||||
|
if (m_pState->HasBegunContent())
|
||||||
|
m_stream << "\n";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -581,8 +604,12 @@ void Emitter::BlockMapPrepareLongKeyValue(EmitterNodeType::value child) {
|
|||||||
case EmitterNodeType::Scalar:
|
case EmitterNodeType::Scalar:
|
||||||
case EmitterNodeType::FlowSeq:
|
case EmitterNodeType::FlowSeq:
|
||||||
case EmitterNodeType::FlowMap:
|
case EmitterNodeType::FlowMap:
|
||||||
|
SpaceOrIndentTo(true, curIndent + 1);
|
||||||
|
break;
|
||||||
case EmitterNodeType::BlockSeq:
|
case EmitterNodeType::BlockSeq:
|
||||||
case EmitterNodeType::BlockMap:
|
case EmitterNodeType::BlockMap:
|
||||||
|
if (m_pState->HasBegunContent())
|
||||||
|
m_stream << "\n";
|
||||||
SpaceOrIndentTo(true, curIndent + 1);
|
SpaceOrIndentTo(true, curIndent + 1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -621,6 +648,9 @@ void Emitter::BlockMapPrepareSimpleKeyValue(EmitterNodeType::value child) {
|
|||||||
const std::size_t nextIndent = curIndent + m_pState->CurGroupIndent();
|
const std::size_t nextIndent = curIndent + m_pState->CurGroupIndent();
|
||||||
|
|
||||||
if (!m_pState->HasBegunNode()) {
|
if (!m_pState->HasBegunNode()) {
|
||||||
|
if (m_pState->HasAlias()) {
|
||||||
|
m_stream << " ";
|
||||||
|
}
|
||||||
m_stream << ":";
|
m_stream << ":";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -674,32 +704,45 @@ void Emitter::StartedScalar() { m_pState->StartedScalar(); }
|
|||||||
// *******************************************************************************************
|
// *******************************************************************************************
|
||||||
// overloads of Write
|
// overloads of Write
|
||||||
|
|
||||||
Emitter& Emitter::Write(const std::string& str) {
|
StringEscaping::value GetStringEscapingStyle(const EMITTER_MANIP emitterManip) {
|
||||||
|
switch (emitterManip) {
|
||||||
|
case EscapeNonAscii:
|
||||||
|
return StringEscaping::NonAscii;
|
||||||
|
case EscapeAsJson:
|
||||||
|
return StringEscaping::JSON;
|
||||||
|
default:
|
||||||
|
return StringEscaping::None;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Emitter& Emitter::Write(const char* str, std::size_t size) {
|
||||||
if (!good())
|
if (!good())
|
||||||
return *this;
|
return *this;
|
||||||
|
|
||||||
const bool escapeNonAscii = m_pState->GetOutputCharset() == EscapeNonAscii;
|
StringEscaping::value stringEscaping = GetStringEscapingStyle(m_pState->GetOutputCharset());
|
||||||
const StringFormat::value strFormat =
|
|
||||||
Utils::ComputeStringFormat(str, m_pState->GetStringFormat(),
|
|
||||||
m_pState->CurGroupFlowType(), escapeNonAscii);
|
|
||||||
|
|
||||||
if (strFormat == StringFormat::Literal)
|
const StringFormat::value strFormat =
|
||||||
|
Utils::ComputeStringFormat(str, size, m_pState->GetStringFormat(),
|
||||||
|
m_pState->CurGroupFlowType(), stringEscaping == StringEscaping::NonAscii);
|
||||||
|
|
||||||
|
if (strFormat == StringFormat::Literal || size > 1024)
|
||||||
m_pState->SetMapKeyFormat(YAML::LongKey, FmtScope::Local);
|
m_pState->SetMapKeyFormat(YAML::LongKey, FmtScope::Local);
|
||||||
|
|
||||||
PrepareNode(EmitterNodeType::Scalar);
|
PrepareNode(EmitterNodeType::Scalar);
|
||||||
|
|
||||||
switch (strFormat) {
|
switch (strFormat) {
|
||||||
case StringFormat::Plain:
|
case StringFormat::Plain:
|
||||||
m_stream << str;
|
m_stream.write(str, size);
|
||||||
break;
|
break;
|
||||||
case StringFormat::SingleQuoted:
|
case StringFormat::SingleQuoted:
|
||||||
Utils::WriteSingleQuotedString(m_stream, str);
|
Utils::WriteSingleQuotedString(m_stream, str, size);
|
||||||
break;
|
break;
|
||||||
case StringFormat::DoubleQuoted:
|
case StringFormat::DoubleQuoted:
|
||||||
Utils::WriteDoubleQuotedString(m_stream, str, escapeNonAscii);
|
Utils::WriteDoubleQuotedString(m_stream, str, size, stringEscaping);
|
||||||
break;
|
break;
|
||||||
case StringFormat::Literal:
|
case StringFormat::Literal:
|
||||||
Utils::WriteLiteralString(m_stream, str,
|
Utils::WriteLiteralString(m_stream, str, size,
|
||||||
m_pState->CurIndent() + m_pState->GetIndent());
|
m_pState->CurIndent() + m_pState->GetIndent());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -709,6 +752,10 @@ Emitter& Emitter::Write(const std::string& str) {
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Emitter& Emitter::Write(const std::string& str) {
|
||||||
|
return Write(str.data(), str.size());
|
||||||
|
}
|
||||||
|
|
||||||
std::size_t Emitter::GetFloatPrecision() const {
|
std::size_t Emitter::GetFloatPrecision() const {
|
||||||
return m_pState->GetFloatPrecision();
|
return m_pState->GetFloatPrecision();
|
||||||
}
|
}
|
||||||
@@ -766,6 +813,21 @@ const char* Emitter::ComputeFullBoolName(bool b) const {
|
|||||||
// these answers
|
// these answers
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char* Emitter::ComputeNullName() const {
|
||||||
|
switch (m_pState->GetNullFormat()) {
|
||||||
|
case LowerNull:
|
||||||
|
return "null";
|
||||||
|
case UpperNull:
|
||||||
|
return "NULL";
|
||||||
|
case CamelNull:
|
||||||
|
return "Null";
|
||||||
|
case TildeNull:
|
||||||
|
// fallthrough
|
||||||
|
default:
|
||||||
|
return "~";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Emitter& Emitter::Write(bool b) {
|
Emitter& Emitter::Write(bool b) {
|
||||||
if (!good())
|
if (!good())
|
||||||
return *this;
|
return *this;
|
||||||
@@ -787,8 +849,10 @@ Emitter& Emitter::Write(char ch) {
|
|||||||
if (!good())
|
if (!good())
|
||||||
return *this;
|
return *this;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
PrepareNode(EmitterNodeType::Scalar);
|
PrepareNode(EmitterNodeType::Scalar);
|
||||||
Utils::WriteChar(m_stream, ch);
|
Utils::WriteChar(m_stream, ch, GetStringEscapingStyle(m_pState->GetOutputCharset()));
|
||||||
StartedScalar();
|
StartedScalar();
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
@@ -805,13 +869,15 @@ Emitter& Emitter::Write(const _Alias& alias) {
|
|||||||
|
|
||||||
PrepareNode(EmitterNodeType::Scalar);
|
PrepareNode(EmitterNodeType::Scalar);
|
||||||
|
|
||||||
if (!Utils::WriteAlias(m_stream, alias.content)) {
|
if (!Utils::WriteAlias(m_stream, alias.content.data(), alias.content.size())) {
|
||||||
m_pState->SetError(ErrorMsg::INVALID_ALIAS);
|
m_pState->SetError(ErrorMsg::INVALID_ALIAS);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
StartedScalar();
|
StartedScalar();
|
||||||
|
|
||||||
|
m_pState->SetAlias();
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -826,7 +892,7 @@ Emitter& Emitter::Write(const _Anchor& anchor) {
|
|||||||
|
|
||||||
PrepareNode(EmitterNodeType::Property);
|
PrepareNode(EmitterNodeType::Property);
|
||||||
|
|
||||||
if (!Utils::WriteAnchor(m_stream, anchor.content)) {
|
if (!Utils::WriteAnchor(m_stream, anchor.content.data(), anchor.content.size())) {
|
||||||
m_pState->SetError(ErrorMsg::INVALID_ANCHOR);
|
m_pState->SetError(ErrorMsg::INVALID_ANCHOR);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@@ -875,7 +941,7 @@ Emitter& Emitter::Write(const _Comment& comment) {
|
|||||||
|
|
||||||
if (m_stream.col() > 0)
|
if (m_stream.col() > 0)
|
||||||
m_stream << Indentation(m_pState->GetPreCommentIndent());
|
m_stream << Indentation(m_pState->GetPreCommentIndent());
|
||||||
Utils::WriteComment(m_stream, comment.content,
|
Utils::WriteComment(m_stream, comment.content.data(), comment.content.size(),
|
||||||
m_pState->GetPostCommentIndent());
|
m_pState->GetPostCommentIndent());
|
||||||
|
|
||||||
m_pState->SetNonContent();
|
m_pState->SetNonContent();
|
||||||
@@ -889,7 +955,7 @@ Emitter& Emitter::Write(const _Null& /*null*/) {
|
|||||||
|
|
||||||
PrepareNode(EmitterNodeType::Scalar);
|
PrepareNode(EmitterNodeType::Scalar);
|
||||||
|
|
||||||
m_stream << "~";
|
m_stream << ComputeNullName();
|
||||||
|
|
||||||
StartedScalar();
|
StartedScalar();
|
||||||
|
|
||||||
@@ -908,4 +974,4 @@ Emitter& Emitter::Write(const Binary& binary) {
|
|||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
}
|
} // namespace YAML
|
||||||
|
|||||||
@@ -6,29 +6,35 @@
|
|||||||
namespace YAML {
|
namespace YAML {
|
||||||
EmitterState::EmitterState()
|
EmitterState::EmitterState()
|
||||||
: m_isGood(true),
|
: m_isGood(true),
|
||||||
|
m_lastError{},
|
||||||
|
// default global manipulators
|
||||||
|
m_charset(EmitNonAscii),
|
||||||
|
m_strFmt(Auto),
|
||||||
|
m_boolFmt(TrueFalseBool),
|
||||||
|
m_boolLengthFmt(LongBool),
|
||||||
|
m_boolCaseFmt(LowerCase),
|
||||||
|
m_nullFmt(TildeNull),
|
||||||
|
m_intFmt(Dec),
|
||||||
|
m_indent(2),
|
||||||
|
m_preCommentIndent(2),
|
||||||
|
m_postCommentIndent(1),
|
||||||
|
m_seqFmt(Block),
|
||||||
|
m_mapFmt(Block),
|
||||||
|
m_mapKeyFmt(Auto),
|
||||||
|
m_floatPrecision(std::numeric_limits<float>::max_digits10),
|
||||||
|
m_doublePrecision(std::numeric_limits<double>::max_digits10),
|
||||||
|
//
|
||||||
|
m_modifiedSettings{},
|
||||||
|
m_globalModifiedSettings{},
|
||||||
|
m_groups{},
|
||||||
m_curIndent(0),
|
m_curIndent(0),
|
||||||
m_hasAnchor(false),
|
m_hasAnchor(false),
|
||||||
|
m_hasAlias(false),
|
||||||
m_hasTag(false),
|
m_hasTag(false),
|
||||||
m_hasNonContent(false),
|
m_hasNonContent(false),
|
||||||
m_docCount(0) {
|
m_docCount(0) {}
|
||||||
// set default global manipulators
|
|
||||||
m_charset.set(EmitNonAscii);
|
|
||||||
m_strFmt.set(Auto);
|
|
||||||
m_boolFmt.set(TrueFalseBool);
|
|
||||||
m_boolLengthFmt.set(LongBool);
|
|
||||||
m_boolCaseFmt.set(LowerCase);
|
|
||||||
m_intFmt.set(Dec);
|
|
||||||
m_indent.set(2);
|
|
||||||
m_preCommentIndent.set(2);
|
|
||||||
m_postCommentIndent.set(1);
|
|
||||||
m_seqFmt.set(Block);
|
|
||||||
m_mapFmt.set(Block);
|
|
||||||
m_mapKeyFmt.set(Auto);
|
|
||||||
m_floatPrecision.set(std::numeric_limits<float>::digits10 + 1);
|
|
||||||
m_doublePrecision.set(std::numeric_limits<double>::digits10 + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
EmitterState::~EmitterState() {}
|
EmitterState::~EmitterState() = default;
|
||||||
|
|
||||||
// SetLocalValue
|
// SetLocalValue
|
||||||
// . We blindly tries to set all possible formatters to this value
|
// . We blindly tries to set all possible formatters to this value
|
||||||
@@ -39,6 +45,7 @@ void EmitterState::SetLocalValue(EMITTER_MANIP value) {
|
|||||||
SetBoolFormat(value, FmtScope::Local);
|
SetBoolFormat(value, FmtScope::Local);
|
||||||
SetBoolCaseFormat(value, FmtScope::Local);
|
SetBoolCaseFormat(value, FmtScope::Local);
|
||||||
SetBoolLengthFormat(value, FmtScope::Local);
|
SetBoolLengthFormat(value, FmtScope::Local);
|
||||||
|
SetNullFormat(value, FmtScope::Local);
|
||||||
SetIntFormat(value, FmtScope::Local);
|
SetIntFormat(value, FmtScope::Local);
|
||||||
SetFlowType(GroupType::Seq, value, FmtScope::Local);
|
SetFlowType(GroupType::Seq, value, FmtScope::Local);
|
||||||
SetFlowType(GroupType::Map, value, FmtScope::Local);
|
SetFlowType(GroupType::Map, value, FmtScope::Local);
|
||||||
@@ -47,37 +54,43 @@ void EmitterState::SetLocalValue(EMITTER_MANIP value) {
|
|||||||
|
|
||||||
void EmitterState::SetAnchor() { m_hasAnchor = true; }
|
void EmitterState::SetAnchor() { m_hasAnchor = true; }
|
||||||
|
|
||||||
|
void EmitterState::SetAlias() { m_hasAlias = true; }
|
||||||
|
|
||||||
void EmitterState::SetTag() { m_hasTag = true; }
|
void EmitterState::SetTag() { m_hasTag = true; }
|
||||||
|
|
||||||
void EmitterState::SetNonContent() { m_hasNonContent = true; }
|
void EmitterState::SetNonContent() { m_hasNonContent = true; }
|
||||||
|
|
||||||
void EmitterState::SetLongKey() {
|
void EmitterState::SetLongKey() {
|
||||||
assert(!m_groups.empty());
|
assert(!m_groups.empty());
|
||||||
if (m_groups.empty())
|
if (m_groups.empty()) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
assert(m_groups.top().type == GroupType::Map);
|
assert(m_groups.back()->type == GroupType::Map);
|
||||||
m_groups.top().longKey = true;
|
m_groups.back()->longKey = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitterState::ForceFlow() {
|
void EmitterState::ForceFlow() {
|
||||||
assert(!m_groups.empty());
|
assert(!m_groups.empty());
|
||||||
if (m_groups.empty())
|
if (m_groups.empty()) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
m_groups.top().flowType = FlowType::Flow;
|
m_groups.back()->flowType = FlowType::Flow;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitterState::StartedNode() {
|
void EmitterState::StartedNode() {
|
||||||
if (m_groups.empty()) {
|
if (m_groups.empty()) {
|
||||||
m_docCount++;
|
m_docCount++;
|
||||||
} else {
|
} else {
|
||||||
m_groups.top().childCount++;
|
m_groups.back()->childCount++;
|
||||||
if (m_groups.top().childCount % 2 == 0)
|
if (m_groups.back()->childCount % 2 == 0) {
|
||||||
m_groups.top().longKey = false;
|
m_groups.back()->longKey = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_hasAnchor = false;
|
m_hasAnchor = false;
|
||||||
|
m_hasAlias = false;
|
||||||
m_hasTag = false;
|
m_hasTag = false;
|
||||||
m_hasNonContent = false;
|
m_hasNonContent = false;
|
||||||
}
|
}
|
||||||
@@ -87,15 +100,13 @@ EmitterNodeType::value EmitterState::NextGroupType(
|
|||||||
if (type == GroupType::Seq) {
|
if (type == GroupType::Seq) {
|
||||||
if (GetFlowType(type) == Block)
|
if (GetFlowType(type) == Block)
|
||||||
return EmitterNodeType::BlockSeq;
|
return EmitterNodeType::BlockSeq;
|
||||||
else
|
return EmitterNodeType::FlowSeq;
|
||||||
return EmitterNodeType::FlowSeq;
|
|
||||||
} else {
|
|
||||||
if (GetFlowType(type) == Block)
|
|
||||||
return EmitterNodeType::BlockMap;
|
|
||||||
else
|
|
||||||
return EmitterNodeType::FlowMap;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (GetFlowType(type) == Block)
|
||||||
|
return EmitterNodeType::BlockMap;
|
||||||
|
return EmitterNodeType::FlowMap;
|
||||||
|
|
||||||
// can't happen
|
// can't happen
|
||||||
assert(false);
|
assert(false);
|
||||||
return EmitterNodeType::NoType;
|
return EmitterNodeType::NoType;
|
||||||
@@ -121,41 +132,56 @@ void EmitterState::StartedScalar() {
|
|||||||
void EmitterState::StartedGroup(GroupType::value type) {
|
void EmitterState::StartedGroup(GroupType::value type) {
|
||||||
StartedNode();
|
StartedNode();
|
||||||
|
|
||||||
const int lastGroupIndent = (m_groups.empty() ? 0 : m_groups.top().indent);
|
const std::size_t lastGroupIndent =
|
||||||
|
(m_groups.empty() ? 0 : m_groups.back()->indent);
|
||||||
m_curIndent += lastGroupIndent;
|
m_curIndent += lastGroupIndent;
|
||||||
|
|
||||||
std::auto_ptr<Group> pGroup(new Group(type));
|
// TODO: Create move constructors for settings types to simplify transfer
|
||||||
|
std::unique_ptr<Group> pGroup(new Group(type));
|
||||||
|
|
||||||
// transfer settings (which last until this group is done)
|
// transfer settings (which last until this group is done)
|
||||||
pGroup->modifiedSettings = m_modifiedSettings;
|
//
|
||||||
|
// NB: if pGroup->modifiedSettings == m_modifiedSettings,
|
||||||
|
// m_modifiedSettings is not changed!
|
||||||
|
pGroup->modifiedSettings = std::move(m_modifiedSettings);
|
||||||
|
|
||||||
// set up group
|
// set up group
|
||||||
if (GetFlowType(type) == Block)
|
if (GetFlowType(type) == Block) {
|
||||||
pGroup->flowType = FlowType::Block;
|
pGroup->flowType = FlowType::Block;
|
||||||
else
|
} else {
|
||||||
pGroup->flowType = FlowType::Flow;
|
pGroup->flowType = FlowType::Flow;
|
||||||
|
}
|
||||||
pGroup->indent = GetIndent();
|
pGroup->indent = GetIndent();
|
||||||
|
|
||||||
m_groups.push(pGroup);
|
m_groups.push_back(std::move(pGroup));
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitterState::EndedGroup(GroupType::value type) {
|
void EmitterState::EndedGroup(GroupType::value type) {
|
||||||
if (m_groups.empty()) {
|
if (m_groups.empty()) {
|
||||||
if (type == GroupType::Seq)
|
if (type == GroupType::Seq) {
|
||||||
return SetError(ErrorMsg::UNEXPECTED_END_SEQ);
|
return SetError(ErrorMsg::UNEXPECTED_END_SEQ);
|
||||||
else
|
}
|
||||||
return SetError(ErrorMsg::UNEXPECTED_END_MAP);
|
return SetError(ErrorMsg::UNEXPECTED_END_MAP);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_hasTag) {
|
||||||
|
SetError(ErrorMsg::INVALID_TAG);
|
||||||
|
}
|
||||||
|
if (m_hasAnchor) {
|
||||||
|
SetError(ErrorMsg::INVALID_ANCHOR);
|
||||||
}
|
}
|
||||||
|
|
||||||
// get rid of the current group
|
// get rid of the current group
|
||||||
{
|
{
|
||||||
std::auto_ptr<Group> pFinishedGroup = m_groups.pop();
|
std::unique_ptr<Group> pFinishedGroup = std::move(m_groups.back());
|
||||||
if (pFinishedGroup->type != type)
|
m_groups.pop_back();
|
||||||
|
if (pFinishedGroup->type != type) {
|
||||||
return SetError(ErrorMsg::UNMATCHED_GROUP_TAG);
|
return SetError(ErrorMsg::UNMATCHED_GROUP_TAG);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// reset old settings
|
// reset old settings
|
||||||
std::size_t lastIndent = (m_groups.empty() ? 0 : m_groups.top().indent);
|
std::size_t lastIndent = (m_groups.empty() ? 0 : m_groups.back()->indent);
|
||||||
assert(m_curIndent >= lastIndent);
|
assert(m_curIndent >= lastIndent);
|
||||||
m_curIndent -= lastIndent;
|
m_curIndent -= lastIndent;
|
||||||
|
|
||||||
@@ -164,49 +190,59 @@ void EmitterState::EndedGroup(GroupType::value type) {
|
|||||||
m_globalModifiedSettings.restore();
|
m_globalModifiedSettings.restore();
|
||||||
|
|
||||||
ClearModifiedSettings();
|
ClearModifiedSettings();
|
||||||
|
m_hasAnchor = false;
|
||||||
|
m_hasTag = false;
|
||||||
|
m_hasNonContent = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
EmitterNodeType::value EmitterState::CurGroupNodeType() const {
|
EmitterNodeType::value EmitterState::CurGroupNodeType() const {
|
||||||
if (m_groups.empty())
|
if (m_groups.empty()) {
|
||||||
return EmitterNodeType::NoType;
|
return EmitterNodeType::NoType;
|
||||||
|
}
|
||||||
|
|
||||||
return m_groups.top().NodeType();
|
return m_groups.back()->NodeType();
|
||||||
}
|
}
|
||||||
|
|
||||||
GroupType::value EmitterState::CurGroupType() const {
|
GroupType::value EmitterState::CurGroupType() const {
|
||||||
return m_groups.empty() ? GroupType::NoType : m_groups.top().type;
|
return m_groups.empty() ? GroupType::NoType : m_groups.back()->type;
|
||||||
}
|
}
|
||||||
|
|
||||||
FlowType::value EmitterState::CurGroupFlowType() const {
|
FlowType::value EmitterState::CurGroupFlowType() const {
|
||||||
return m_groups.empty() ? FlowType::NoType : m_groups.top().flowType;
|
return m_groups.empty() ? FlowType::NoType : m_groups.back()->flowType;
|
||||||
}
|
}
|
||||||
|
|
||||||
int EmitterState::CurGroupIndent() const {
|
std::size_t EmitterState::CurGroupIndent() const {
|
||||||
return m_groups.empty() ? 0 : m_groups.top().indent;
|
return m_groups.empty() ? 0 : m_groups.back()->indent;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t EmitterState::CurGroupChildCount() const {
|
std::size_t EmitterState::CurGroupChildCount() const {
|
||||||
return m_groups.empty() ? m_docCount : m_groups.top().childCount;
|
return m_groups.empty() ? m_docCount : m_groups.back()->childCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EmitterState::CurGroupLongKey() const {
|
bool EmitterState::CurGroupLongKey() const {
|
||||||
return m_groups.empty() ? false : m_groups.top().longKey;
|
return m_groups.empty() ? false : m_groups.back()->longKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
int EmitterState::LastIndent() const {
|
std::size_t EmitterState::LastIndent() const {
|
||||||
if (m_groups.size() <= 1)
|
if (m_groups.size() <= 1) {
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
return m_curIndent - m_groups.top(-1).indent;
|
return m_curIndent - m_groups[m_groups.size() - 2]->indent;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitterState::ClearModifiedSettings() { m_modifiedSettings.clear(); }
|
void EmitterState::ClearModifiedSettings() { m_modifiedSettings.clear(); }
|
||||||
|
|
||||||
|
void EmitterState::RestoreGlobalModifiedSettings() {
|
||||||
|
m_globalModifiedSettings.restore();
|
||||||
|
}
|
||||||
|
|
||||||
bool EmitterState::SetOutputCharset(EMITTER_MANIP value,
|
bool EmitterState::SetOutputCharset(EMITTER_MANIP value,
|
||||||
FmtScope::value scope) {
|
FmtScope::value scope) {
|
||||||
switch (value) {
|
switch (value) {
|
||||||
case EmitNonAscii:
|
case EmitNonAscii:
|
||||||
case EscapeNonAscii:
|
case EscapeNonAscii:
|
||||||
|
case EscapeAsJson:
|
||||||
_Set(m_charset, value, scope);
|
_Set(m_charset, value, scope);
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
@@ -264,6 +300,19 @@ bool EmitterState::SetBoolCaseFormat(EMITTER_MANIP value,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool EmitterState::SetNullFormat(EMITTER_MANIP value, FmtScope::value scope) {
|
||||||
|
switch (value) {
|
||||||
|
case LowerNull:
|
||||||
|
case UpperNull:
|
||||||
|
case CamelNull:
|
||||||
|
case TildeNull:
|
||||||
|
_Set(m_nullFmt, value, scope);
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool EmitterState::SetIntFormat(EMITTER_MANIP value, FmtScope::value scope) {
|
bool EmitterState::SetIntFormat(EMITTER_MANIP value, FmtScope::value scope) {
|
||||||
switch (value) {
|
switch (value) {
|
||||||
case Dec:
|
case Dec:
|
||||||
@@ -334,17 +383,18 @@ bool EmitterState::SetMapKeyFormat(EMITTER_MANIP value, FmtScope::value scope) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EmitterState::SetFloatPrecision(int value, FmtScope::value scope) {
|
bool EmitterState::SetFloatPrecision(std::size_t value, FmtScope::value scope) {
|
||||||
if (value < 0 || value > std::numeric_limits<float>::digits10 + 1)
|
if (value > std::numeric_limits<float>::max_digits10)
|
||||||
return false;
|
return false;
|
||||||
_Set(m_floatPrecision, value, scope);
|
_Set(m_floatPrecision, value, scope);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EmitterState::SetDoublePrecision(int value, FmtScope::value scope) {
|
bool EmitterState::SetDoublePrecision(std::size_t value,
|
||||||
if (value < 0 || value > std::numeric_limits<double>::digits10 + 1)
|
FmtScope::value scope) {
|
||||||
|
if (value > std::numeric_limits<double>::max_digits10)
|
||||||
return false;
|
return false;
|
||||||
_Set(m_doublePrecision, value, scope);
|
_Set(m_doublePrecision, value, scope);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
} // namespace YAML
|
||||||
|
|||||||
@@ -7,15 +7,15 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "ptr_stack.h"
|
|
||||||
#include "setting.h"
|
#include "setting.h"
|
||||||
#include "yaml-cpp/emitterdef.h"
|
#include "yaml-cpp/emitterdef.h"
|
||||||
#include "yaml-cpp/emittermanip.h"
|
#include "yaml-cpp/emittermanip.h"
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <vector>
|
|
||||||
#include <stack>
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <stack>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace YAML {
|
namespace YAML {
|
||||||
struct FmtScope {
|
struct FmtScope {
|
||||||
@@ -43,6 +43,7 @@ class EmitterState {
|
|||||||
|
|
||||||
// node handling
|
// node handling
|
||||||
void SetAnchor();
|
void SetAnchor();
|
||||||
|
void SetAlias();
|
||||||
void SetTag();
|
void SetTag();
|
||||||
void SetNonContent();
|
void SetNonContent();
|
||||||
void SetLongKey();
|
void SetLongKey();
|
||||||
@@ -58,13 +59,14 @@ class EmitterState {
|
|||||||
|
|
||||||
GroupType::value CurGroupType() const;
|
GroupType::value CurGroupType() const;
|
||||||
FlowType::value CurGroupFlowType() const;
|
FlowType::value CurGroupFlowType() const;
|
||||||
int CurGroupIndent() const;
|
std::size_t CurGroupIndent() const;
|
||||||
std::size_t CurGroupChildCount() const;
|
std::size_t CurGroupChildCount() const;
|
||||||
bool CurGroupLongKey() const;
|
bool CurGroupLongKey() const;
|
||||||
|
|
||||||
int LastIndent() const;
|
std::size_t LastIndent() const;
|
||||||
int CurIndent() const { return m_curIndent; }
|
std::size_t CurIndent() const { return m_curIndent; }
|
||||||
bool HasAnchor() const { return m_hasAnchor; }
|
bool HasAnchor() const { return m_hasAnchor; }
|
||||||
|
bool HasAlias() const { return m_hasAlias; }
|
||||||
bool HasTag() const { return m_hasTag; }
|
bool HasTag() const { return m_hasTag; }
|
||||||
bool HasBegunNode() const {
|
bool HasBegunNode() const {
|
||||||
return m_hasAnchor || m_hasTag || m_hasNonContent;
|
return m_hasAnchor || m_hasTag || m_hasNonContent;
|
||||||
@@ -72,6 +74,7 @@ class EmitterState {
|
|||||||
bool HasBegunContent() const { return m_hasAnchor || m_hasTag; }
|
bool HasBegunContent() const { return m_hasAnchor || m_hasTag; }
|
||||||
|
|
||||||
void ClearModifiedSettings();
|
void ClearModifiedSettings();
|
||||||
|
void RestoreGlobalModifiedSettings();
|
||||||
|
|
||||||
// formatters
|
// formatters
|
||||||
void SetLocalValue(EMITTER_MANIP value);
|
void SetLocalValue(EMITTER_MANIP value);
|
||||||
@@ -91,16 +94,19 @@ class EmitterState {
|
|||||||
bool SetBoolCaseFormat(EMITTER_MANIP value, FmtScope::value scope);
|
bool SetBoolCaseFormat(EMITTER_MANIP value, FmtScope::value scope);
|
||||||
EMITTER_MANIP GetBoolCaseFormat() const { return m_boolCaseFmt.get(); }
|
EMITTER_MANIP GetBoolCaseFormat() const { return m_boolCaseFmt.get(); }
|
||||||
|
|
||||||
|
bool SetNullFormat(EMITTER_MANIP value, FmtScope::value scope);
|
||||||
|
EMITTER_MANIP GetNullFormat() const { return m_nullFmt.get(); }
|
||||||
|
|
||||||
bool SetIntFormat(EMITTER_MANIP value, FmtScope::value scope);
|
bool SetIntFormat(EMITTER_MANIP value, FmtScope::value scope);
|
||||||
EMITTER_MANIP GetIntFormat() const { return m_intFmt.get(); }
|
EMITTER_MANIP GetIntFormat() const { return m_intFmt.get(); }
|
||||||
|
|
||||||
bool SetIndent(std::size_t value, FmtScope::value scope);
|
bool SetIndent(std::size_t value, FmtScope::value scope);
|
||||||
int GetIndent() const { return m_indent.get(); }
|
std::size_t GetIndent() const { return m_indent.get(); }
|
||||||
|
|
||||||
bool SetPreCommentIndent(std::size_t value, FmtScope::value scope);
|
bool SetPreCommentIndent(std::size_t value, FmtScope::value scope);
|
||||||
int GetPreCommentIndent() const { return m_preCommentIndent.get(); }
|
std::size_t GetPreCommentIndent() const { return m_preCommentIndent.get(); }
|
||||||
bool SetPostCommentIndent(std::size_t value, FmtScope::value scope);
|
bool SetPostCommentIndent(std::size_t value, FmtScope::value scope);
|
||||||
int GetPostCommentIndent() const { return m_postCommentIndent.get(); }
|
std::size_t GetPostCommentIndent() const { return m_postCommentIndent.get(); }
|
||||||
|
|
||||||
bool SetFlowType(GroupType::value groupType, EMITTER_MANIP value,
|
bool SetFlowType(GroupType::value groupType, EMITTER_MANIP value,
|
||||||
FmtScope::value scope);
|
FmtScope::value scope);
|
||||||
@@ -109,9 +115,9 @@ class EmitterState {
|
|||||||
bool SetMapKeyFormat(EMITTER_MANIP value, FmtScope::value scope);
|
bool SetMapKeyFormat(EMITTER_MANIP value, FmtScope::value scope);
|
||||||
EMITTER_MANIP GetMapKeyFormat() const { return m_mapKeyFmt.get(); }
|
EMITTER_MANIP GetMapKeyFormat() const { return m_mapKeyFmt.get(); }
|
||||||
|
|
||||||
bool SetFloatPrecision(int value, FmtScope::value scope);
|
bool SetFloatPrecision(std::size_t value, FmtScope::value scope);
|
||||||
std::size_t GetFloatPrecision() const { return m_floatPrecision.get(); }
|
std::size_t GetFloatPrecision() const { return m_floatPrecision.get(); }
|
||||||
bool SetDoublePrecision(int value, FmtScope::value scope);
|
bool SetDoublePrecision(std::size_t value, FmtScope::value scope);
|
||||||
std::size_t GetDoublePrecision() const { return m_doublePrecision.get(); }
|
std::size_t GetDoublePrecision() const { return m_doublePrecision.get(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -131,25 +137,31 @@ class EmitterState {
|
|||||||
Setting<EMITTER_MANIP> m_boolFmt;
|
Setting<EMITTER_MANIP> m_boolFmt;
|
||||||
Setting<EMITTER_MANIP> m_boolLengthFmt;
|
Setting<EMITTER_MANIP> m_boolLengthFmt;
|
||||||
Setting<EMITTER_MANIP> m_boolCaseFmt;
|
Setting<EMITTER_MANIP> m_boolCaseFmt;
|
||||||
|
Setting<EMITTER_MANIP> m_nullFmt;
|
||||||
Setting<EMITTER_MANIP> m_intFmt;
|
Setting<EMITTER_MANIP> m_intFmt;
|
||||||
Setting<std::size_t> m_indent;
|
Setting<std::size_t> m_indent;
|
||||||
Setting<std::size_t> m_preCommentIndent, m_postCommentIndent;
|
Setting<std::size_t> m_preCommentIndent, m_postCommentIndent;
|
||||||
Setting<EMITTER_MANIP> m_seqFmt;
|
Setting<EMITTER_MANIP> m_seqFmt;
|
||||||
Setting<EMITTER_MANIP> m_mapFmt;
|
Setting<EMITTER_MANIP> m_mapFmt;
|
||||||
Setting<EMITTER_MANIP> m_mapKeyFmt;
|
Setting<EMITTER_MANIP> m_mapKeyFmt;
|
||||||
Setting<int> m_floatPrecision;
|
Setting<std::size_t> m_floatPrecision;
|
||||||
Setting<int> m_doublePrecision;
|
Setting<std::size_t> m_doublePrecision;
|
||||||
|
|
||||||
SettingChanges m_modifiedSettings;
|
SettingChanges m_modifiedSettings;
|
||||||
SettingChanges m_globalModifiedSettings;
|
SettingChanges m_globalModifiedSettings;
|
||||||
|
|
||||||
struct Group {
|
struct Group {
|
||||||
explicit Group(GroupType::value type_)
|
explicit Group(GroupType::value type_)
|
||||||
: type(type_), indent(0), childCount(0), longKey(false) {}
|
: type(type_),
|
||||||
|
flowType{},
|
||||||
|
indent(0),
|
||||||
|
childCount(0),
|
||||||
|
longKey(false),
|
||||||
|
modifiedSettings{} {}
|
||||||
|
|
||||||
GroupType::value type;
|
GroupType::value type;
|
||||||
FlowType::value flowType;
|
FlowType::value flowType;
|
||||||
int indent;
|
std::size_t indent;
|
||||||
std::size_t childCount;
|
std::size_t childCount;
|
||||||
bool longKey;
|
bool longKey;
|
||||||
|
|
||||||
@@ -174,9 +186,10 @@ class EmitterState {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
ptr_stack<Group> m_groups;
|
std::vector<std::unique_ptr<Group>> m_groups;
|
||||||
std::size_t m_curIndent;
|
std::size_t m_curIndent;
|
||||||
bool m_hasAnchor;
|
bool m_hasAnchor;
|
||||||
|
bool m_hasAlias;
|
||||||
bool m_hasTag;
|
bool m_hasTag;
|
||||||
bool m_hasNonContent;
|
bool m_hasNonContent;
|
||||||
std::size_t m_docCount;
|
std::size_t m_docCount;
|
||||||
@@ -198,6 +211,6 @@ void EmitterState::_Set(Setting<T>& fmt, T value, FmtScope::value scope) {
|
|||||||
assert(false);
|
assert(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} // namespace YAML
|
||||||
|
|
||||||
#endif // EMITTERSTATE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#endif // EMITTERSTATE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
#include <algorithm>
|
||||||
|
#include <cstdint>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
@@ -8,6 +10,7 @@
|
|||||||
#include "regeximpl.h"
|
#include "regeximpl.h"
|
||||||
#include "stringsource.h"
|
#include "stringsource.h"
|
||||||
#include "yaml-cpp/binary.h" // IWYU pragma: keep
|
#include "yaml-cpp/binary.h" // IWYU pragma: keep
|
||||||
|
#include "yaml-cpp/null.h"
|
||||||
#include "yaml-cpp/ostream_wrapper.h"
|
#include "yaml-cpp/ostream_wrapper.h"
|
||||||
|
|
||||||
namespace YAML {
|
namespace YAML {
|
||||||
@@ -86,8 +89,8 @@ int Utf8BytesIndicated(char ch) {
|
|||||||
bool IsTrailingByte(char ch) { return (ch & 0xC0) == 0x80; }
|
bool IsTrailingByte(char ch) { return (ch & 0xC0) == 0x80; }
|
||||||
|
|
||||||
bool GetNextCodePointAndAdvance(int& codePoint,
|
bool GetNextCodePointAndAdvance(int& codePoint,
|
||||||
std::string::const_iterator& first,
|
const char*& first,
|
||||||
std::string::const_iterator last) {
|
const char* last) {
|
||||||
if (first == last)
|
if (first == last)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@@ -133,12 +136,12 @@ void WriteCodePoint(ostream_wrapper& out, int codePoint) {
|
|||||||
if (codePoint < 0 || codePoint > 0x10FFFF) {
|
if (codePoint < 0 || codePoint > 0x10FFFF) {
|
||||||
codePoint = REPLACEMENT_CHARACTER;
|
codePoint = REPLACEMENT_CHARACTER;
|
||||||
}
|
}
|
||||||
if (codePoint < 0x7F) {
|
if (codePoint <= 0x7F) {
|
||||||
out << static_cast<char>(codePoint);
|
out << static_cast<char>(codePoint);
|
||||||
} else if (codePoint < 0x7FF) {
|
} else if (codePoint <= 0x7FF) {
|
||||||
out << static_cast<char>(0xC0 | (codePoint >> 6))
|
out << static_cast<char>(0xC0 | (codePoint >> 6))
|
||||||
<< static_cast<char>(0x80 | (codePoint & 0x3F));
|
<< static_cast<char>(0x80 | (codePoint & 0x3F));
|
||||||
} else if (codePoint < 0xFFFF) {
|
} else if (codePoint <= 0xFFFF) {
|
||||||
out << static_cast<char>(0xE0 | (codePoint >> 12))
|
out << static_cast<char>(0xE0 | (codePoint >> 12))
|
||||||
<< static_cast<char>(0x80 | ((codePoint >> 6) & 0x3F))
|
<< static_cast<char>(0x80 | ((codePoint >> 6) & 0x3F))
|
||||||
<< static_cast<char>(0x80 | (codePoint & 0x3F));
|
<< static_cast<char>(0x80 | (codePoint & 0x3F));
|
||||||
@@ -150,43 +153,39 @@ void WriteCodePoint(ostream_wrapper& out, int codePoint) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsValidPlainScalar(const std::string& str, FlowType::value flowType,
|
bool IsValidPlainScalar(const char* str, std::size_t size, FlowType::value flowType,
|
||||||
bool allowOnlyAscii) {
|
bool allowOnlyAscii) {
|
||||||
if (str.empty()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// check against null
|
// check against null
|
||||||
if (str == "null") {
|
if (IsNullString(str, size)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// check the start
|
// check the start
|
||||||
const RegEx& start = (flowType == FlowType::Flow ? Exp::PlainScalarInFlow()
|
const RegEx& start = (flowType == FlowType::Flow ? Exp::PlainScalarInFlow()
|
||||||
: Exp::PlainScalar());
|
: Exp::PlainScalar());
|
||||||
if (!start.Matches(str)) {
|
if (!start.Matches(StringCharSource(str, size))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// and check the end for plain whitespace (which can't be faithfully kept in a
|
// and check the end for plain whitespace (which can't be faithfully kept in a
|
||||||
// plain scalar)
|
// plain scalar)
|
||||||
if (!str.empty() && *str.rbegin() == ' ') {
|
if (size != 0 && str[size - 1] == ' ') {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// then check until something is disallowed
|
// then check until something is disallowed
|
||||||
static const RegEx& disallowed_flow =
|
static const RegEx disallowed_flow =
|
||||||
Exp::EndScalarInFlow() || (Exp::BlankOrBreak() + Exp::Comment()) ||
|
Exp::EndScalarInFlow() | (Exp::BlankOrBreak() + Exp::Comment()) |
|
||||||
Exp::NotPrintable() || Exp::Utf8_ByteOrderMark() || Exp::Break() ||
|
Exp::NotPrintable() | Exp::Utf8_ByteOrderMark() | Exp::Break() |
|
||||||
Exp::Tab();
|
Exp::Tab() | Exp::Ampersand();
|
||||||
static const RegEx& disallowed_block =
|
static const RegEx disallowed_block =
|
||||||
Exp::EndScalar() || (Exp::BlankOrBreak() + Exp::Comment()) ||
|
Exp::EndScalar() | (Exp::BlankOrBreak() + Exp::Comment()) |
|
||||||
Exp::NotPrintable() || Exp::Utf8_ByteOrderMark() || Exp::Break() ||
|
Exp::NotPrintable() | Exp::Utf8_ByteOrderMark() | Exp::Break() |
|
||||||
Exp::Tab();
|
Exp::Tab() | Exp::Ampersand();
|
||||||
const RegEx& disallowed =
|
const RegEx& disallowed =
|
||||||
flowType == FlowType::Flow ? disallowed_flow : disallowed_block;
|
flowType == FlowType::Flow ? disallowed_flow : disallowed_block;
|
||||||
|
|
||||||
StringCharSource buffer(str.c_str(), str.size());
|
StringCharSource buffer(str, size);
|
||||||
while (buffer) {
|
while (buffer) {
|
||||||
if (disallowed.Matches(buffer)) {
|
if (disallowed.Matches(buffer)) {
|
||||||
return false;
|
return false;
|
||||||
@@ -200,48 +199,54 @@ bool IsValidPlainScalar(const std::string& str, FlowType::value flowType,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsValidSingleQuotedScalar(const std::string& str, bool escapeNonAscii) {
|
bool IsValidSingleQuotedScalar(const char* str, std::size_t size, bool escapeNonAscii) {
|
||||||
// TODO: check for non-printable characters?
|
// TODO: check for non-printable characters?
|
||||||
for (std::size_t i = 0; i < str.size(); i++) {
|
return std::none_of(str, str + size, [=](char ch) {
|
||||||
if (escapeNonAscii && (0x80 <= static_cast<unsigned char>(str[i]))) {
|
return (escapeNonAscii && (0x80 <= static_cast<unsigned char>(ch))) ||
|
||||||
return false;
|
(ch == '\n');
|
||||||
}
|
});
|
||||||
if (str[i] == '\n') {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsValidLiteralScalar(const std::string& str, FlowType::value flowType,
|
bool IsValidLiteralScalar(const char* str, std::size_t size, FlowType::value flowType,
|
||||||
bool escapeNonAscii) {
|
bool escapeNonAscii) {
|
||||||
if (flowType == FlowType::Flow) {
|
if (flowType == FlowType::Flow) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: check for non-printable characters?
|
// TODO: check for non-printable characters?
|
||||||
for (std::size_t i = 0; i < str.size(); i++) {
|
return std::none_of(str, str + size, [=](char ch) {
|
||||||
if (escapeNonAscii && (0x80 <= static_cast<unsigned char>(str[i]))) {
|
return (escapeNonAscii && (0x80 <= static_cast<unsigned char>(ch)));
|
||||||
return false;
|
});
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WriteDoubleQuoteEscapeSequence(ostream_wrapper& out, int codePoint) {
|
std::pair<uint16_t, uint16_t> EncodeUTF16SurrogatePair(int codePoint) {
|
||||||
|
const uint32_t leadOffset = 0xD800 - (0x10000 >> 10);
|
||||||
|
|
||||||
|
return {
|
||||||
|
leadOffset | (codePoint >> 10),
|
||||||
|
0xDC00 | (codePoint & 0x3FF),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void WriteDoubleQuoteEscapeSequence(ostream_wrapper& out, int codePoint, StringEscaping::value stringEscapingStyle) {
|
||||||
static const char hexDigits[] = "0123456789abcdef";
|
static const char hexDigits[] = "0123456789abcdef";
|
||||||
|
|
||||||
out << "\\";
|
out << "\\";
|
||||||
int digits = 8;
|
int digits = 8;
|
||||||
if (codePoint < 0xFF) {
|
if (codePoint < 0xFF && stringEscapingStyle != StringEscaping::JSON) {
|
||||||
out << "x";
|
out << "x";
|
||||||
digits = 2;
|
digits = 2;
|
||||||
} else if (codePoint < 0xFFFF) {
|
} else if (codePoint < 0xFFFF) {
|
||||||
out << "u";
|
out << "u";
|
||||||
digits = 4;
|
digits = 4;
|
||||||
} else {
|
} else if (stringEscapingStyle != StringEscaping::JSON) {
|
||||||
out << "U";
|
out << "U";
|
||||||
digits = 8;
|
digits = 8;
|
||||||
|
} else {
|
||||||
|
auto surrogatePair = EncodeUTF16SurrogatePair(codePoint);
|
||||||
|
WriteDoubleQuoteEscapeSequence(out, surrogatePair.first, stringEscapingStyle);
|
||||||
|
WriteDoubleQuoteEscapeSequence(out, surrogatePair.second, stringEscapingStyle);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write digits into the escape sequence
|
// Write digits into the escape sequence
|
||||||
@@ -249,10 +254,10 @@ void WriteDoubleQuoteEscapeSequence(ostream_wrapper& out, int codePoint) {
|
|||||||
out << hexDigits[(codePoint >> (4 * (digits - 1))) & 0xF];
|
out << hexDigits[(codePoint >> (4 * (digits - 1))) & 0xF];
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WriteAliasName(ostream_wrapper& out, const std::string& str) {
|
bool WriteAliasName(ostream_wrapper& out, const char* str, std::size_t size) {
|
||||||
int codePoint;
|
int codePoint;
|
||||||
for (std::string::const_iterator i = str.begin();
|
for (const char* i = str;
|
||||||
GetNextCodePointAndAdvance(codePoint, i, str.end());) {
|
GetNextCodePointAndAdvance(codePoint, i, str + size);) {
|
||||||
if (!IsAnchorChar(codePoint)) {
|
if (!IsAnchorChar(codePoint)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -261,27 +266,27 @@ bool WriteAliasName(ostream_wrapper& out, const std::string& str) {
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
} // namespace
|
||||||
|
|
||||||
StringFormat::value ComputeStringFormat(const std::string& str,
|
StringFormat::value ComputeStringFormat(const char* str, std::size_t size,
|
||||||
EMITTER_MANIP strFormat,
|
EMITTER_MANIP strFormat,
|
||||||
FlowType::value flowType,
|
FlowType::value flowType,
|
||||||
bool escapeNonAscii) {
|
bool escapeNonAscii) {
|
||||||
switch (strFormat) {
|
switch (strFormat) {
|
||||||
case Auto:
|
case Auto:
|
||||||
if (IsValidPlainScalar(str, flowType, escapeNonAscii)) {
|
if (IsValidPlainScalar(str, size, flowType, escapeNonAscii)) {
|
||||||
return StringFormat::Plain;
|
return StringFormat::Plain;
|
||||||
}
|
}
|
||||||
return StringFormat::DoubleQuoted;
|
return StringFormat::DoubleQuoted;
|
||||||
case SingleQuoted:
|
case SingleQuoted:
|
||||||
if (IsValidSingleQuotedScalar(str, escapeNonAscii)) {
|
if (IsValidSingleQuotedScalar(str, size, escapeNonAscii)) {
|
||||||
return StringFormat::SingleQuoted;
|
return StringFormat::SingleQuoted;
|
||||||
}
|
}
|
||||||
return StringFormat::DoubleQuoted;
|
return StringFormat::DoubleQuoted;
|
||||||
case DoubleQuoted:
|
case DoubleQuoted:
|
||||||
return StringFormat::DoubleQuoted;
|
return StringFormat::DoubleQuoted;
|
||||||
case Literal:
|
case Literal:
|
||||||
if (IsValidLiteralScalar(str, flowType, escapeNonAscii)) {
|
if (IsValidLiteralScalar(str, size, flowType, escapeNonAscii)) {
|
||||||
return StringFormat::Literal;
|
return StringFormat::Literal;
|
||||||
}
|
}
|
||||||
return StringFormat::DoubleQuoted;
|
return StringFormat::DoubleQuoted;
|
||||||
@@ -292,11 +297,11 @@ StringFormat::value ComputeStringFormat(const std::string& str,
|
|||||||
return StringFormat::DoubleQuoted;
|
return StringFormat::DoubleQuoted;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WriteSingleQuotedString(ostream_wrapper& out, const std::string& str) {
|
bool WriteSingleQuotedString(ostream_wrapper& out, const char* str, std::size_t size) {
|
||||||
out << "'";
|
out << "'";
|
||||||
int codePoint;
|
int codePoint;
|
||||||
for (std::string::const_iterator i = str.begin();
|
for (const char* i = str;
|
||||||
GetNextCodePointAndAdvance(codePoint, i, str.end());) {
|
GetNextCodePointAndAdvance(codePoint, i, str + size);) {
|
||||||
if (codePoint == '\n') {
|
if (codePoint == '\n') {
|
||||||
return false; // We can't handle a new line and the attendant indentation
|
return false; // We can't handle a new line and the attendant indentation
|
||||||
// yet
|
// yet
|
||||||
@@ -312,12 +317,12 @@ bool WriteSingleQuotedString(ostream_wrapper& out, const std::string& str) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WriteDoubleQuotedString(ostream_wrapper& out, const std::string& str,
|
bool WriteDoubleQuotedString(ostream_wrapper& out, const char* str, std::size_t size,
|
||||||
bool escapeNonAscii) {
|
StringEscaping::value stringEscaping) {
|
||||||
out << "\"";
|
out << "\"";
|
||||||
int codePoint;
|
int codePoint;
|
||||||
for (std::string::const_iterator i = str.begin();
|
for (const char* i = str;
|
||||||
GetNextCodePointAndAdvance(codePoint, i, str.end());) {
|
GetNextCodePointAndAdvance(codePoint, i, str + size);) {
|
||||||
switch (codePoint) {
|
switch (codePoint) {
|
||||||
case '\"':
|
case '\"':
|
||||||
out << "\\\"";
|
out << "\\\"";
|
||||||
@@ -337,16 +342,19 @@ bool WriteDoubleQuotedString(ostream_wrapper& out, const std::string& str,
|
|||||||
case '\b':
|
case '\b':
|
||||||
out << "\\b";
|
out << "\\b";
|
||||||
break;
|
break;
|
||||||
|
case '\f':
|
||||||
|
out << "\\f";
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
if (codePoint < 0x20 ||
|
if (codePoint < 0x20 ||
|
||||||
(codePoint >= 0x80 &&
|
(codePoint >= 0x80 &&
|
||||||
codePoint <= 0xA0)) { // Control characters and non-breaking space
|
codePoint <= 0xA0)) { // Control characters and non-breaking space
|
||||||
WriteDoubleQuoteEscapeSequence(out, codePoint);
|
WriteDoubleQuoteEscapeSequence(out, codePoint, stringEscaping);
|
||||||
} else if (codePoint == 0xFEFF) { // Byte order marks (ZWNS) should be
|
} else if (codePoint == 0xFEFF) { // Byte order marks (ZWNS) should be
|
||||||
// escaped (YAML 1.2, sec. 5.2)
|
// escaped (YAML 1.2, sec. 5.2)
|
||||||
WriteDoubleQuoteEscapeSequence(out, codePoint);
|
WriteDoubleQuoteEscapeSequence(out, codePoint, stringEscaping);
|
||||||
} else if (escapeNonAscii && codePoint > 0x7E) {
|
} else if (stringEscaping == StringEscaping::NonAscii && codePoint > 0x7E) {
|
||||||
WriteDoubleQuoteEscapeSequence(out, codePoint);
|
WriteDoubleQuoteEscapeSequence(out, codePoint, stringEscaping);
|
||||||
} else {
|
} else {
|
||||||
WriteCodePoint(out, codePoint);
|
WriteCodePoint(out, codePoint);
|
||||||
}
|
}
|
||||||
@@ -356,52 +364,60 @@ bool WriteDoubleQuotedString(ostream_wrapper& out, const std::string& str,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WriteLiteralString(ostream_wrapper& out, const std::string& str,
|
bool WriteLiteralString(ostream_wrapper& out, const char* str, std::size_t size,
|
||||||
int indent) {
|
std::size_t indent) {
|
||||||
out << "|\n";
|
out << "|\n";
|
||||||
out << IndentTo(indent);
|
|
||||||
int codePoint;
|
int codePoint;
|
||||||
for (std::string::const_iterator i = str.begin();
|
for (const char* i = str;
|
||||||
GetNextCodePointAndAdvance(codePoint, i, str.end());) {
|
GetNextCodePointAndAdvance(codePoint, i, str + size);) {
|
||||||
if (codePoint == '\n') {
|
if (codePoint == '\n') {
|
||||||
out << "\n" << IndentTo(indent);
|
out << "\n";
|
||||||
} else {
|
} else {
|
||||||
|
out<< IndentTo(indent);
|
||||||
WriteCodePoint(out, codePoint);
|
WriteCodePoint(out, codePoint);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WriteChar(ostream_wrapper& out, char ch) {
|
bool WriteChar(ostream_wrapper& out, char ch, StringEscaping::value stringEscapingStyle) {
|
||||||
if (('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z')) {
|
if (('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z')) {
|
||||||
out << ch;
|
out << ch;
|
||||||
} else if ((0x20 <= ch && ch <= 0x7e) || ch == ' ') {
|
} else if (ch == '\"') {
|
||||||
out << "\"" << ch << "\"";
|
out << R"("\"")";
|
||||||
} else if (ch == '\t') {
|
} else if (ch == '\t') {
|
||||||
out << "\"\\t\"";
|
out << R"("\t")";
|
||||||
} else if (ch == '\n') {
|
} else if (ch == '\n') {
|
||||||
out << "\"\\n\"";
|
out << R"("\n")";
|
||||||
} else if (ch == '\b') {
|
} else if (ch == '\b') {
|
||||||
out << "\"\\b\"";
|
out << R"("\b")";
|
||||||
|
} else if (ch == '\r') {
|
||||||
|
out << R"("\r")";
|
||||||
|
} else if (ch == '\f') {
|
||||||
|
out << R"("\f")";
|
||||||
|
} else if (ch == '\\') {
|
||||||
|
out << R"("\\")";
|
||||||
|
} else if (0x20 <= ch && ch <= 0x7e) {
|
||||||
|
out << "\"" << ch << "\"";
|
||||||
} else {
|
} else {
|
||||||
out << "\"";
|
out << "\"";
|
||||||
WriteDoubleQuoteEscapeSequence(out, ch);
|
WriteDoubleQuoteEscapeSequence(out, ch, stringEscapingStyle);
|
||||||
out << "\"";
|
out << "\"";
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WriteComment(ostream_wrapper& out, const std::string& str,
|
bool WriteComment(ostream_wrapper& out, const char* str, std::size_t size,
|
||||||
int postCommentIndent) {
|
std::size_t postCommentIndent) {
|
||||||
const std::size_t curIndent = out.col();
|
const std::size_t curIndent = out.col();
|
||||||
out << "#" << Indentation(postCommentIndent);
|
out << "#" << Indentation(postCommentIndent);
|
||||||
out.set_comment();
|
out.set_comment();
|
||||||
int codePoint;
|
int codePoint;
|
||||||
for (std::string::const_iterator i = str.begin();
|
for (const char* i = str;
|
||||||
GetNextCodePointAndAdvance(codePoint, i, str.end());) {
|
GetNextCodePointAndAdvance(codePoint, i, str + size);) {
|
||||||
if (codePoint == '\n') {
|
if (codePoint == '\n') {
|
||||||
out << "\n" << IndentTo(curIndent) << "#"
|
out << "\n"
|
||||||
<< Indentation(postCommentIndent);
|
<< IndentTo(curIndent) << "#" << Indentation(postCommentIndent);
|
||||||
out.set_comment();
|
out.set_comment();
|
||||||
} else {
|
} else {
|
||||||
WriteCodePoint(out, codePoint);
|
WriteCodePoint(out, codePoint);
|
||||||
@@ -410,14 +426,14 @@ bool WriteComment(ostream_wrapper& out, const std::string& str,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WriteAlias(ostream_wrapper& out, const std::string& str) {
|
bool WriteAlias(ostream_wrapper& out, const char* str, std::size_t size) {
|
||||||
out << "*";
|
out << "*";
|
||||||
return WriteAliasName(out, str);
|
return WriteAliasName(out, str, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WriteAnchor(ostream_wrapper& out, const std::string& str) {
|
bool WriteAnchor(ostream_wrapper& out, const char* str, std::size_t size) {
|
||||||
out << "&";
|
out << "&";
|
||||||
return WriteAliasName(out, str);
|
return WriteAliasName(out, str, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WriteTag(ostream_wrapper& out, const std::string& str, bool verbatim) {
|
bool WriteTag(ostream_wrapper& out, const std::string& str, bool verbatim) {
|
||||||
@@ -474,9 +490,10 @@ bool WriteTagWithPrefix(ostream_wrapper& out, const std::string& prefix,
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool WriteBinary(ostream_wrapper& out, const Binary& binary) {
|
bool WriteBinary(ostream_wrapper& out, const Binary& binary) {
|
||||||
WriteDoubleQuotedString(out, EncodeBase64(binary.data(), binary.size()),
|
std::string encoded = EncodeBase64(binary.data(), binary.size());
|
||||||
false);
|
WriteDoubleQuotedString(out, encoded.data(), encoded.size(),
|
||||||
|
StringEscaping::None);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
} // namespace Utils
|
||||||
}
|
} // namespace YAML
|
||||||
|
|||||||
@@ -24,22 +24,27 @@ struct StringFormat {
|
|||||||
enum value { Plain, SingleQuoted, DoubleQuoted, Literal };
|
enum value { Plain, SingleQuoted, DoubleQuoted, Literal };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct StringEscaping {
|
||||||
|
enum value { None, NonAscii, JSON };
|
||||||
|
};
|
||||||
|
|
||||||
namespace Utils {
|
namespace Utils {
|
||||||
StringFormat::value ComputeStringFormat(const std::string& str,
|
StringFormat::value ComputeStringFormat(const char* str, std::size_t size,
|
||||||
EMITTER_MANIP strFormat,
|
EMITTER_MANIP strFormat,
|
||||||
FlowType::value flowType,
|
FlowType::value flowType,
|
||||||
bool escapeNonAscii);
|
bool escapeNonAscii);
|
||||||
|
|
||||||
bool WriteSingleQuotedString(ostream_wrapper& out, const std::string& str);
|
bool WriteSingleQuotedString(ostream_wrapper& out, const char* str, std::size_t size);
|
||||||
bool WriteDoubleQuotedString(ostream_wrapper& out, const std::string& str,
|
bool WriteDoubleQuotedString(ostream_wrapper& out, const char* str, std::size_t size,
|
||||||
bool escapeNonAscii);
|
StringEscaping::value stringEscaping);
|
||||||
bool WriteLiteralString(ostream_wrapper& out, const std::string& str,
|
bool WriteLiteralString(ostream_wrapper& out, const char* str, std::size_t size,
|
||||||
int indent);
|
std::size_t indent);
|
||||||
bool WriteChar(ostream_wrapper& out, char ch);
|
bool WriteChar(ostream_wrapper& out, char ch,
|
||||||
bool WriteComment(ostream_wrapper& out, const std::string& str,
|
StringEscaping::value stringEscapingStyle);
|
||||||
int postCommentIndent);
|
bool WriteComment(ostream_wrapper& out, const char* str, std::size_t size,
|
||||||
bool WriteAlias(ostream_wrapper& out, const std::string& str);
|
std::size_t postCommentIndent);
|
||||||
bool WriteAnchor(ostream_wrapper& out, const std::string& str);
|
bool WriteAlias(ostream_wrapper& out, const char* str, std::size_t size);
|
||||||
|
bool WriteAnchor(ostream_wrapper& out, const char* str, std::size_t size);
|
||||||
bool WriteTag(ostream_wrapper& out, const std::string& str, bool verbatim);
|
bool WriteTag(ostream_wrapper& out, const std::string& str, bool verbatim);
|
||||||
bool WriteTagWithPrefix(ostream_wrapper& out, const std::string& prefix,
|
bool WriteTagWithPrefix(ostream_wrapper& out, const std::string& prefix,
|
||||||
const std::string& tag);
|
const std::string& tag);
|
||||||
|
|||||||
20
src/exceptions.cpp
Normal file
20
src/exceptions.cpp
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
#include "yaml-cpp/exceptions.h"
|
||||||
|
#include "yaml-cpp/noexcept.h"
|
||||||
|
|
||||||
|
namespace YAML {
|
||||||
|
|
||||||
|
// These destructors are defined out-of-line so the vtable is only emitted once.
|
||||||
|
Exception::~Exception() YAML_CPP_NOEXCEPT = default;
|
||||||
|
ParserException::~ParserException() YAML_CPP_NOEXCEPT = default;
|
||||||
|
RepresentationException::~RepresentationException() YAML_CPP_NOEXCEPT = default;
|
||||||
|
InvalidScalar::~InvalidScalar() YAML_CPP_NOEXCEPT = default;
|
||||||
|
KeyNotFound::~KeyNotFound() YAML_CPP_NOEXCEPT = default;
|
||||||
|
InvalidNode::~InvalidNode() YAML_CPP_NOEXCEPT = default;
|
||||||
|
BadConversion::~BadConversion() YAML_CPP_NOEXCEPT = default;
|
||||||
|
BadDereference::~BadDereference() YAML_CPP_NOEXCEPT = default;
|
||||||
|
BadSubscript::~BadSubscript() YAML_CPP_NOEXCEPT = default;
|
||||||
|
BadPushback::~BadPushback() YAML_CPP_NOEXCEPT = default;
|
||||||
|
BadInsert::~BadInsert() YAML_CPP_NOEXCEPT = default;
|
||||||
|
EmitterException::~EmitterException() YAML_CPP_NOEXCEPT = default;
|
||||||
|
BadFile::~BadFile() YAML_CPP_NOEXCEPT = default;
|
||||||
|
} // namespace YAML
|
||||||
21
src/exp.cpp
21
src/exp.cpp
@@ -12,8 +12,7 @@ namespace YAML {
|
|||||||
namespace Exp {
|
namespace Exp {
|
||||||
unsigned ParseHex(const std::string& str, const Mark& mark) {
|
unsigned ParseHex(const std::string& str, const Mark& mark) {
|
||||||
unsigned value = 0;
|
unsigned value = 0;
|
||||||
for (std::size_t i = 0; i < str.size(); i++) {
|
for (char ch : str) {
|
||||||
char ch = str[i];
|
|
||||||
int digit = 0;
|
int digit = 0;
|
||||||
if ('a' <= ch && ch <= 'f')
|
if ('a' <= ch && ch <= 'f')
|
||||||
digit = ch - 'a' + 10;
|
digit = ch - 'a' + 10;
|
||||||
@@ -55,14 +54,16 @@ std::string Escape(Stream& in, int codeLength) {
|
|||||||
// now break it up into chars
|
// now break it up into chars
|
||||||
if (value <= 0x7F)
|
if (value <= 0x7F)
|
||||||
return Str(value);
|
return Str(value);
|
||||||
else if (value <= 0x7FF)
|
|
||||||
|
if (value <= 0x7FF)
|
||||||
return Str(0xC0 + (value >> 6)) + Str(0x80 + (value & 0x3F));
|
return Str(0xC0 + (value >> 6)) + Str(0x80 + (value & 0x3F));
|
||||||
else if (value <= 0xFFFF)
|
|
||||||
|
if (value <= 0xFFFF)
|
||||||
return Str(0xE0 + (value >> 12)) + Str(0x80 + ((value >> 6) & 0x3F)) +
|
return Str(0xE0 + (value >> 12)) + Str(0x80 + ((value >> 6) & 0x3F)) +
|
||||||
Str(0x80 + (value & 0x3F));
|
Str(0x80 + (value & 0x3F));
|
||||||
else
|
|
||||||
return Str(0xF0 + (value >> 18)) + Str(0x80 + ((value >> 12) & 0x3F)) +
|
return Str(0xF0 + (value >> 18)) + Str(0x80 + ((value >> 12) & 0x3F)) +
|
||||||
Str(0x80 + ((value >> 6) & 0x3F)) + Str(0x80 + (value & 0x3F));
|
Str(0x80 + ((value >> 6) & 0x3F)) + Str(0x80 + (value & 0x3F));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Escape
|
// Escape
|
||||||
@@ -104,7 +105,7 @@ std::string Escape(Stream& in) {
|
|||||||
case 'e':
|
case 'e':
|
||||||
return "\x1B";
|
return "\x1B";
|
||||||
case ' ':
|
case ' ':
|
||||||
return "\x20";
|
return R"( )";
|
||||||
case '\"':
|
case '\"':
|
||||||
return "\"";
|
return "\"";
|
||||||
case '\'':
|
case '\'':
|
||||||
@@ -132,5 +133,5 @@ std::string Escape(Stream& in) {
|
|||||||
std::stringstream msg;
|
std::stringstream msg;
|
||||||
throw ParserException(in.mark(), std::string(ErrorMsg::INVALID_ESCAPE) + ch);
|
throw ParserException(in.mark(), std::string(ErrorMsg::INVALID_ESCAPE) + ch);
|
||||||
}
|
}
|
||||||
}
|
} // namespace Exp
|
||||||
}
|
} // namespace YAML
|
||||||
|
|||||||
81
src/exp.h
81
src/exp.h
@@ -20,6 +20,10 @@ namespace YAML {
|
|||||||
|
|
||||||
namespace Exp {
|
namespace Exp {
|
||||||
// misc
|
// misc
|
||||||
|
inline const RegEx& Empty() {
|
||||||
|
static const RegEx e;
|
||||||
|
return e;
|
||||||
|
}
|
||||||
inline const RegEx& Space() {
|
inline const RegEx& Space() {
|
||||||
static const RegEx e = RegEx(' ');
|
static const RegEx e = RegEx(' ');
|
||||||
return e;
|
return e;
|
||||||
@@ -29,15 +33,15 @@ inline const RegEx& Tab() {
|
|||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
inline const RegEx& Blank() {
|
inline const RegEx& Blank() {
|
||||||
static const RegEx e = Space() || Tab();
|
static const RegEx e = Space() | Tab();
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
inline const RegEx& Break() {
|
inline const RegEx& Break() {
|
||||||
static const RegEx e = RegEx('\n') || RegEx("\r\n");
|
static const RegEx e = RegEx('\n') | RegEx("\r\n") | RegEx('\r');
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
inline const RegEx& BlankOrBreak() {
|
inline const RegEx& BlankOrBreak() {
|
||||||
static const RegEx e = Blank() || Break();
|
static const RegEx e = Blank() | Break();
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
inline const RegEx& Digit() {
|
inline const RegEx& Digit() {
|
||||||
@@ -45,29 +49,29 @@ inline const RegEx& Digit() {
|
|||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
inline const RegEx& Alpha() {
|
inline const RegEx& Alpha() {
|
||||||
static const RegEx e = RegEx('a', 'z') || RegEx('A', 'Z');
|
static const RegEx e = RegEx('a', 'z') | RegEx('A', 'Z');
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
inline const RegEx& AlphaNumeric() {
|
inline const RegEx& AlphaNumeric() {
|
||||||
static const RegEx e = Alpha() || Digit();
|
static const RegEx e = Alpha() | Digit();
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
inline const RegEx& Word() {
|
inline const RegEx& Word() {
|
||||||
static const RegEx e = AlphaNumeric() || RegEx('-');
|
static const RegEx e = AlphaNumeric() | RegEx('-');
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
inline const RegEx& Hex() {
|
inline const RegEx& Hex() {
|
||||||
static const RegEx e = Digit() || RegEx('A', 'F') || RegEx('a', 'f');
|
static const RegEx e = Digit() | RegEx('A', 'F') | RegEx('a', 'f');
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
// Valid Unicode code points that are not part of c-printable (YAML 1.2, sec.
|
// Valid Unicode code points that are not part of c-printable (YAML 1.2, sec.
|
||||||
// 5.1)
|
// 5.1)
|
||||||
inline const RegEx& NotPrintable() {
|
inline const RegEx& NotPrintable() {
|
||||||
static const RegEx e =
|
static const RegEx e =
|
||||||
RegEx(0) ||
|
RegEx(0) |
|
||||||
RegEx("\x01\x02\x03\x04\x05\x06\x07\x08\x0B\x0C\x7F", REGEX_OR) ||
|
RegEx("\x01\x02\x03\x04\x05\x06\x07\x08\x0B\x0C\x7F", REGEX_OR) |
|
||||||
RegEx(0x0E, 0x1F) ||
|
RegEx(0x0E, 0x1F) |
|
||||||
(RegEx('\xC2') + (RegEx('\x80', '\x84') || RegEx('\x86', '\x9F')));
|
(RegEx('\xC2') + (RegEx('\x80', '\x84') | RegEx('\x86', '\x9F')));
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
inline const RegEx& Utf8_ByteOrderMark() {
|
inline const RegEx& Utf8_ByteOrderMark() {
|
||||||
@@ -78,19 +82,19 @@ inline const RegEx& Utf8_ByteOrderMark() {
|
|||||||
// actual tags
|
// actual tags
|
||||||
|
|
||||||
inline const RegEx& DocStart() {
|
inline const RegEx& DocStart() {
|
||||||
static const RegEx e = RegEx("---") + (BlankOrBreak() || RegEx());
|
static const RegEx e = RegEx("---") + (BlankOrBreak() | RegEx());
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
inline const RegEx& DocEnd() {
|
inline const RegEx& DocEnd() {
|
||||||
static const RegEx e = RegEx("...") + (BlankOrBreak() || RegEx());
|
static const RegEx e = RegEx("...") + (BlankOrBreak() | RegEx());
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
inline const RegEx& DocIndicator() {
|
inline const RegEx& DocIndicator() {
|
||||||
static const RegEx e = DocStart() || DocEnd();
|
static const RegEx e = DocStart() | DocEnd();
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
inline const RegEx& BlockEntry() {
|
inline const RegEx& BlockEntry() {
|
||||||
static const RegEx e = RegEx('-') + (BlankOrBreak() || RegEx());
|
static const RegEx e = RegEx('-') + (BlankOrBreak() | RegEx());
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
inline const RegEx& Key() {
|
inline const RegEx& Key() {
|
||||||
@@ -102,36 +106,40 @@ inline const RegEx& KeyInFlow() {
|
|||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
inline const RegEx& Value() {
|
inline const RegEx& Value() {
|
||||||
static const RegEx e = RegEx(':') + (BlankOrBreak() || RegEx());
|
static const RegEx e = RegEx(':') + (BlankOrBreak() | RegEx());
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
inline const RegEx& ValueInFlow() {
|
inline const RegEx& ValueInFlow() {
|
||||||
static const RegEx e = RegEx(':') + (BlankOrBreak() || RegEx(",}", REGEX_OR));
|
static const RegEx e = RegEx(':') + (BlankOrBreak() | RegEx(",]}", REGEX_OR));
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
inline const RegEx& ValueInJSONFlow() {
|
inline const RegEx& ValueInJSONFlow() {
|
||||||
static const RegEx e = RegEx(':');
|
static const RegEx e = RegEx(':');
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
inline const RegEx& Ampersand() {
|
||||||
|
static const RegEx e = RegEx('&');
|
||||||
|
return e;
|
||||||
|
}
|
||||||
inline const RegEx Comment() {
|
inline const RegEx Comment() {
|
||||||
static const RegEx e = RegEx('#');
|
static const RegEx e = RegEx('#');
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
inline const RegEx& Anchor() {
|
inline const RegEx& Anchor() {
|
||||||
static const RegEx e = !(RegEx("[]{},", REGEX_OR) || BlankOrBreak());
|
static const RegEx e = !(RegEx("[]{},", REGEX_OR) | BlankOrBreak());
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
inline const RegEx& AnchorEnd() {
|
inline const RegEx& AnchorEnd() {
|
||||||
static const RegEx e = RegEx("?:,]}%@`", REGEX_OR) || BlankOrBreak();
|
static const RegEx e = RegEx("?:,]}%@`", REGEX_OR) | BlankOrBreak();
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
inline const RegEx& URI() {
|
inline const RegEx& URI() {
|
||||||
static const RegEx e = Word() || RegEx("#;/?:@&=+$,_.!~*'()[]", REGEX_OR) ||
|
static const RegEx e = Word() | RegEx("#;/?:@&=+$,_.!~*'()[]", REGEX_OR) |
|
||||||
(RegEx('%') + Hex() + Hex());
|
(RegEx('%') + Hex() + Hex());
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
inline const RegEx& Tag() {
|
inline const RegEx& Tag() {
|
||||||
static const RegEx e = Word() || RegEx("#;/?:@&=+$_.~*'", REGEX_OR) ||
|
static const RegEx e = Word() | RegEx("#;/?:@&=+$_.~*'()", REGEX_OR) |
|
||||||
(RegEx('%') + Hex() + Hex());
|
(RegEx('%') + Hex() + Hex());
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
@@ -144,27 +152,36 @@ inline const RegEx& Tag() {
|
|||||||
// space.
|
// space.
|
||||||
inline const RegEx& PlainScalar() {
|
inline const RegEx& PlainScalar() {
|
||||||
static const RegEx e =
|
static const RegEx e =
|
||||||
!(BlankOrBreak() || RegEx(",[]{}#&*!|>\'\"%@`", REGEX_OR) ||
|
!(BlankOrBreak() | RegEx(",[]{}#&*!|>\'\"%@`", REGEX_OR) |
|
||||||
(RegEx("-?:", REGEX_OR) + (BlankOrBreak() || RegEx())));
|
(RegEx("-?:", REGEX_OR) + (BlankOrBreak() | RegEx())));
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
inline const RegEx& PlainScalarInFlow() {
|
inline const RegEx& PlainScalarInFlow() {
|
||||||
static const RegEx e =
|
static const RegEx e =
|
||||||
!(BlankOrBreak() || RegEx("?,[]{}#&*!|>\'\"%@`", REGEX_OR) ||
|
!(BlankOrBreak() | RegEx("?,[]{}#&*!|>\'\"%@`", REGEX_OR) |
|
||||||
(RegEx("-:", REGEX_OR) + Blank()));
|
(RegEx("-:", REGEX_OR) + (Blank() | RegEx())));
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
inline const RegEx& EndScalar() {
|
inline const RegEx& EndScalar() {
|
||||||
static const RegEx e = RegEx(':') + (BlankOrBreak() || RegEx());
|
static const RegEx e = RegEx(':') + (BlankOrBreak() | RegEx());
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
inline const RegEx& EndScalarInFlow() {
|
inline const RegEx& EndScalarInFlow() {
|
||||||
static const RegEx e =
|
static const RegEx e =
|
||||||
(RegEx(':') + (BlankOrBreak() || RegEx() || RegEx(",]}", REGEX_OR))) ||
|
(RegEx(':') + (BlankOrBreak() | RegEx() | RegEx(",]}", REGEX_OR))) |
|
||||||
RegEx(",?[]{}", REGEX_OR);
|
RegEx(",?[]{}", REGEX_OR);
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline const RegEx& ScanScalarEndInFlow() {
|
||||||
|
static const RegEx e = (EndScalarInFlow() | (BlankOrBreak() + Comment()));
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const RegEx& ScanScalarEnd() {
|
||||||
|
static const RegEx e = EndScalar() | (BlankOrBreak() + Comment());
|
||||||
|
return e;
|
||||||
|
}
|
||||||
inline const RegEx& EscSingleQuote() {
|
inline const RegEx& EscSingleQuote() {
|
||||||
static const RegEx e = RegEx("\'\'");
|
static const RegEx e = RegEx("\'\'");
|
||||||
return e;
|
return e;
|
||||||
@@ -179,15 +196,15 @@ inline const RegEx& ChompIndicator() {
|
|||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
inline const RegEx& Chomp() {
|
inline const RegEx& Chomp() {
|
||||||
static const RegEx e = (ChompIndicator() + Digit()) ||
|
static const RegEx e = (ChompIndicator() + Digit()) |
|
||||||
(Digit() + ChompIndicator()) || ChompIndicator() ||
|
(Digit() + ChompIndicator()) | ChompIndicator() |
|
||||||
Digit();
|
Digit();
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
// and some functions
|
// and some functions
|
||||||
std::string Escape(Stream& in);
|
std::string Escape(Stream& in);
|
||||||
}
|
} // namespace Exp
|
||||||
|
|
||||||
namespace Keys {
|
namespace Keys {
|
||||||
const char Directive = '%';
|
const char Directive = '%';
|
||||||
@@ -203,7 +220,7 @@ const char LiteralScalar = '|';
|
|||||||
const char FoldedScalar = '>';
|
const char FoldedScalar = '>';
|
||||||
const char VerbatimTagStart = '<';
|
const char VerbatimTagStart = '<';
|
||||||
const char VerbatimTagEnd = '>';
|
const char VerbatimTagEnd = '>';
|
||||||
}
|
} // namespace Keys
|
||||||
}
|
} // namespace YAML
|
||||||
|
|
||||||
#endif // EXP_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#endif // EXP_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|||||||
238
src/fptostring.cpp
Normal file
238
src/fptostring.cpp
Normal file
@@ -0,0 +1,238 @@
|
|||||||
|
#include "yaml-cpp/fptostring.h"
|
||||||
|
#include "contrib/dragonbox.h"
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
#include <cassert>
|
||||||
|
#include <cmath>
|
||||||
|
#include <limits>
|
||||||
|
#include <sstream>
|
||||||
|
#include <tuple>
|
||||||
|
|
||||||
|
namespace YAML {
|
||||||
|
namespace detail {
|
||||||
|
namespace fp_formatting {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a integer into its ASCII digits.
|
||||||
|
*
|
||||||
|
* @param begin/end - a buffer, must be at least 20bytes long.
|
||||||
|
* @param value - input value.
|
||||||
|
* @param width - minimum number of digits, fill with '0' to the left. Must be equal or smaller than the buffer size.
|
||||||
|
* @return - number of digits filled into the buffer (or -1 if preconditions are not meet)
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* std::array<char, 20> buffer;
|
||||||
|
* auto ct = ConvertToChars(buffer.begin(), buffer.end(), 23, 3);
|
||||||
|
* assert(ct = 3);
|
||||||
|
* assert(buffer[0] == '0');
|
||||||
|
* assert(buffer[1] == '2');
|
||||||
|
* assert(buffer[2] == '3');
|
||||||
|
*/
|
||||||
|
int ConvertToChars(char* begin, char* end, size_t value, int width=1) {
|
||||||
|
// precondition of this function (will trigger in debug build)
|
||||||
|
assert(width >= 1);
|
||||||
|
assert(end >= begin); // end must be after begin
|
||||||
|
assert(end-begin >= width); // Buffer must be large enough
|
||||||
|
assert(end-begin >= 20); // 2^64 has 20digits, so at least 20 digits must be available
|
||||||
|
|
||||||
|
// defensive programming, abort if precondition are not met (will trigger in release build)
|
||||||
|
if (width < 1) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (end < begin) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (end-begin < width) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (end-begin < 20) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// count number of digits, and fill digits array accordingly
|
||||||
|
int digits_ct{};
|
||||||
|
while (value > 0) {
|
||||||
|
char c = value % 10 + '0';
|
||||||
|
value = value / 10;
|
||||||
|
digits_ct += 1;
|
||||||
|
*(end-digits_ct) = c;
|
||||||
|
}
|
||||||
|
while(digits_ct < width) {
|
||||||
|
assert(digits_ct < 64);
|
||||||
|
digits_ct += 1;
|
||||||
|
*(end-digits_ct) = '0';
|
||||||
|
}
|
||||||
|
// move data to the front of the array
|
||||||
|
std::memmove(begin, end-digits_ct, digits_ct);
|
||||||
|
return digits_ct;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a float or double to a string.
|
||||||
|
*
|
||||||
|
* converts a value 'v' to a string. Uses dragonbox for formatting.
|
||||||
|
*/
|
||||||
|
template <typename T>
|
||||||
|
std::string FpToString(T v, int precision = 0) {
|
||||||
|
// hard coded constant, at which exponent should switch to a scientific notation
|
||||||
|
int const lowerExponentThreshold = -5;
|
||||||
|
int const upperExponentThreshold = (precision==0)?6:precision;
|
||||||
|
if (precision == 0) {
|
||||||
|
precision = 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
// dragonbox/to_decimal does not handle value 0, inf, NaN
|
||||||
|
if (v == 0 || std::isinf(v) || std::isnan(v)) {
|
||||||
|
std::stringstream ss;
|
||||||
|
ss.imbue(std::locale::classic());
|
||||||
|
ss << v;
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto r = jkj::dragonbox::to_decimal(v);
|
||||||
|
|
||||||
|
auto digits = std::array<char, 20>{}; // max digits of size_t is 20.
|
||||||
|
auto digits_ct = ConvertToChars(digits.data(), digits.data() + digits.size(), r.significand);
|
||||||
|
|
||||||
|
// defensive programming, ConvertToChars arguments are invalid
|
||||||
|
if (digits_ct == -1) {
|
||||||
|
std::stringstream ss;
|
||||||
|
ss.imbue(std::locale::classic());
|
||||||
|
ss << v;
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if requested precision is lower than
|
||||||
|
// required digits for exact representation
|
||||||
|
if (digits_ct > precision) {
|
||||||
|
auto diff = digits_ct - precision;
|
||||||
|
r.exponent += diff;
|
||||||
|
digits_ct = precision;
|
||||||
|
|
||||||
|
// round numbers if required
|
||||||
|
if (digits[digits_ct] >= '5') {
|
||||||
|
int i{digits_ct-1};
|
||||||
|
digits[i] += 1;
|
||||||
|
while (digits[i] == '9'+1) {
|
||||||
|
digits_ct -= 1;
|
||||||
|
r.exponent += 1;
|
||||||
|
if (i > 0) {
|
||||||
|
digits[i-1] += 1;
|
||||||
|
i -= 1;
|
||||||
|
} else {
|
||||||
|
digits_ct = 1;
|
||||||
|
digits[0] = '1';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::array<char, 28> output_buffer; // max digits of size_t plus sign, a dot and 2 letters for 'e+' or 'e-' and 4 letters for the exponent
|
||||||
|
auto output_ptr = &output_buffer[0];
|
||||||
|
|
||||||
|
// print '-' symbol for negative numbers
|
||||||
|
if (r.is_negative) {
|
||||||
|
*(output_ptr++) = '-';
|
||||||
|
}
|
||||||
|
|
||||||
|
// exponent if only a single non-zero digit is before the decimal point
|
||||||
|
int const exponent = r.exponent + digits_ct - 1;
|
||||||
|
|
||||||
|
// case 1: scientific notation
|
||||||
|
if (exponent >= upperExponentThreshold || exponent <= lowerExponentThreshold) {
|
||||||
|
// print first digit
|
||||||
|
*(output_ptr++) = digits[0];
|
||||||
|
|
||||||
|
// print digits after decimal point
|
||||||
|
if (digits_ct > 1) {
|
||||||
|
*(output_ptr++) = '.';
|
||||||
|
// print significant numbers after decimal point
|
||||||
|
for (int i{1}; i < digits_ct; ++i) {
|
||||||
|
*(output_ptr++) = digits[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*(output_ptr++) = 'e';
|
||||||
|
*(output_ptr++) = (exponent>=0)?'+':'-';
|
||||||
|
auto exp_digits = std::array<char, 20>{};
|
||||||
|
auto exp_digits_ct = ConvertToChars(exp_digits.data(), exp_digits.data() + exp_digits.size(), std::abs(exponent), /*.precision=*/ 2);
|
||||||
|
|
||||||
|
// defensive programming, ConvertToChars arguments are invalid
|
||||||
|
if (exp_digits_ct == -1) {
|
||||||
|
std::stringstream ss;
|
||||||
|
ss.imbue(std::locale::classic());
|
||||||
|
ss << v;
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i{0}; i < exp_digits_ct; ++i) {
|
||||||
|
*(output_ptr++) = exp_digits[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
// case 2: default notation
|
||||||
|
} else {
|
||||||
|
auto const digits_end = digits.begin() + digits_ct;
|
||||||
|
auto digits_iter = digits.begin();
|
||||||
|
|
||||||
|
// print digits before point
|
||||||
|
int const before_decimal_digits = digits_ct + r.exponent;
|
||||||
|
if (before_decimal_digits > 0) {
|
||||||
|
// print digits before point
|
||||||
|
for (int i{0}; i < std::min(before_decimal_digits, digits_ct); ++i) {
|
||||||
|
*(output_ptr++) = *(digits_iter++);
|
||||||
|
}
|
||||||
|
// print trailing zeros before point
|
||||||
|
for (int i{0}; i < before_decimal_digits - digits_ct; ++i) {
|
||||||
|
*(output_ptr++) = '0';
|
||||||
|
}
|
||||||
|
|
||||||
|
// print 0 before point if none where printed before
|
||||||
|
} else {
|
||||||
|
*(output_ptr++) = '0';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (digits_iter != digits_end) {
|
||||||
|
*(output_ptr++) = '.';
|
||||||
|
// print 0 after decimal point, to fill until first digits
|
||||||
|
int const after_decimal_zeros = -digits_ct - r.exponent;
|
||||||
|
for (int i{0}; i < after_decimal_zeros; ++i) {
|
||||||
|
*(output_ptr++) = '0';
|
||||||
|
}
|
||||||
|
|
||||||
|
// print significant numbers after decimal point
|
||||||
|
for (;digits_iter < digits_end; ++digits_iter) {
|
||||||
|
*(output_ptr++) = *digits_iter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*output_ptr = '\0';
|
||||||
|
return std::string{&output_buffer[0], output_ptr};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string FpToString(float v, size_t precision) {
|
||||||
|
return detail::fp_formatting::FpToString(v, precision);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string FpToString(double v, size_t precision) {
|
||||||
|
return detail::fp_formatting::FpToString(v, precision);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* dragonbox only works for floats/doubles not long double
|
||||||
|
*/
|
||||||
|
std::string FpToString(long double v, size_t precision) {
|
||||||
|
std::stringstream ss;
|
||||||
|
ss.imbue(std::locale::classic());
|
||||||
|
if (precision == 0) {
|
||||||
|
precision = std::numeric_limits<long double>::max_digits10;
|
||||||
|
}
|
||||||
|
ss.precision(precision);
|
||||||
|
ss << v;
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -7,7 +7,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
|
|
||||||
#include "yaml-cpp/ostream_wrapper.h"
|
#include "yaml-cpp/ostream_wrapper.h"
|
||||||
|
|||||||
@@ -9,6 +9,10 @@ void memory_holder::merge(memory_holder& rhs) {
|
|||||||
if (m_pMemory == rhs.m_pMemory)
|
if (m_pMemory == rhs.m_pMemory)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (m_pMemory->size() < rhs.m_pMemory->size()) {
|
||||||
|
std::swap(m_pMemory, rhs.m_pMemory);
|
||||||
|
}
|
||||||
|
|
||||||
m_pMemory->merge(*rhs.m_pMemory);
|
m_pMemory->merge(*rhs.m_pMemory);
|
||||||
rhs.m_pMemory = m_pMemory;
|
rhs.m_pMemory = m_pMemory;
|
||||||
}
|
}
|
||||||
@@ -22,5 +26,9 @@ node& memory::create_node() {
|
|||||||
void memory::merge(const memory& rhs) {
|
void memory::merge(const memory& rhs) {
|
||||||
m_nodes.insert(rhs.m_nodes.begin(), rhs.m_nodes.end());
|
m_nodes.insert(rhs.m_nodes.begin(), rhs.m_nodes.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t memory::size() const {
|
||||||
|
return m_nodes.size();
|
||||||
}
|
}
|
||||||
}
|
} // namespace detail
|
||||||
|
} // namespace YAML
|
||||||
|
|||||||
@@ -9,4 +9,4 @@ Node Clone(const Node& node) {
|
|||||||
events.Emit(builder);
|
events.Emit(builder);
|
||||||
return builder.Root();
|
return builder.Root();
|
||||||
}
|
}
|
||||||
}
|
} // namespace YAML
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#include <assert.h>
|
#include <algorithm>
|
||||||
#include <boost/smart_ptr/shared_ptr.hpp>
|
#include <cassert>
|
||||||
|
#include <iterator>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
#include "yaml-cpp/exceptions.h"
|
#include "yaml-cpp/exceptions.h"
|
||||||
@@ -12,14 +13,24 @@
|
|||||||
|
|
||||||
namespace YAML {
|
namespace YAML {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
YAML_CPP_API std::atomic<size_t> node::m_amount{0};
|
||||||
|
|
||||||
std::string node_data::empty_scalar;
|
const std::string& node_data::empty_scalar() {
|
||||||
|
static const std::string svalue;
|
||||||
|
return svalue;
|
||||||
|
}
|
||||||
|
|
||||||
node_data::node_data()
|
node_data::node_data()
|
||||||
: m_isDefined(false),
|
: m_isDefined(false),
|
||||||
|
m_mark(Mark::null_mark()),
|
||||||
m_type(NodeType::Null),
|
m_type(NodeType::Null),
|
||||||
|
m_tag{},
|
||||||
m_style(EmitterStyle::Default),
|
m_style(EmitterStyle::Default),
|
||||||
m_seqSize(0) {}
|
m_scalar{},
|
||||||
|
m_sequence{},
|
||||||
|
m_seqSize(0),
|
||||||
|
m_map{},
|
||||||
|
m_undefinedPairs{} {}
|
||||||
|
|
||||||
void node_data::mark_defined() {
|
void node_data::mark_defined() {
|
||||||
if (m_type == NodeType::Undefined)
|
if (m_type == NodeType::Undefined)
|
||||||
@@ -27,6 +38,8 @@ void node_data::mark_defined() {
|
|||||||
m_isDefined = true;
|
m_isDefined = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void node_data::set_mark(const Mark& mark) { m_mark = mark; }
|
||||||
|
|
||||||
void node_data::set_type(NodeType::value type) {
|
void node_data::set_type(NodeType::value type) {
|
||||||
if (type == NodeType::Undefined) {
|
if (type == NodeType::Undefined) {
|
||||||
m_type = type;
|
m_type = type;
|
||||||
@@ -97,9 +110,9 @@ void node_data::compute_seq_size() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void node_data::compute_map_size() const {
|
void node_data::compute_map_size() const {
|
||||||
kv_pairs::iterator it = m_undefinedPairs.begin();
|
auto it = m_undefinedPairs.begin();
|
||||||
while (it != m_undefinedPairs.end()) {
|
while (it != m_undefinedPairs.end()) {
|
||||||
kv_pairs::iterator jt = boost::next(it);
|
auto jt = std::next(it);
|
||||||
if (it->first->is_defined() && it->second->is_defined())
|
if (it->first->is_defined() && it->second->is_defined())
|
||||||
m_undefinedPairs.erase(it);
|
m_undefinedPairs.erase(it);
|
||||||
it = jt;
|
it = jt;
|
||||||
@@ -108,7 +121,7 @@ void node_data::compute_map_size() const {
|
|||||||
|
|
||||||
const_node_iterator node_data::begin() const {
|
const_node_iterator node_data::begin() const {
|
||||||
if (!m_isDefined)
|
if (!m_isDefined)
|
||||||
return const_node_iterator();
|
return {};
|
||||||
|
|
||||||
switch (m_type) {
|
switch (m_type) {
|
||||||
case NodeType::Sequence:
|
case NodeType::Sequence:
|
||||||
@@ -116,13 +129,13 @@ const_node_iterator node_data::begin() const {
|
|||||||
case NodeType::Map:
|
case NodeType::Map:
|
||||||
return const_node_iterator(m_map.begin(), m_map.end());
|
return const_node_iterator(m_map.begin(), m_map.end());
|
||||||
default:
|
default:
|
||||||
return const_node_iterator();
|
return {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
node_iterator node_data::begin() {
|
node_iterator node_data::begin() {
|
||||||
if (!m_isDefined)
|
if (!m_isDefined)
|
||||||
return node_iterator();
|
return {};
|
||||||
|
|
||||||
switch (m_type) {
|
switch (m_type) {
|
||||||
case NodeType::Sequence:
|
case NodeType::Sequence:
|
||||||
@@ -130,13 +143,13 @@ node_iterator node_data::begin() {
|
|||||||
case NodeType::Map:
|
case NodeType::Map:
|
||||||
return node_iterator(m_map.begin(), m_map.end());
|
return node_iterator(m_map.begin(), m_map.end());
|
||||||
default:
|
default:
|
||||||
return node_iterator();
|
return {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const_node_iterator node_data::end() const {
|
const_node_iterator node_data::end() const {
|
||||||
if (!m_isDefined)
|
if (!m_isDefined)
|
||||||
return const_node_iterator();
|
return {};
|
||||||
|
|
||||||
switch (m_type) {
|
switch (m_type) {
|
||||||
case NodeType::Sequence:
|
case NodeType::Sequence:
|
||||||
@@ -144,13 +157,13 @@ const_node_iterator node_data::end() const {
|
|||||||
case NodeType::Map:
|
case NodeType::Map:
|
||||||
return const_node_iterator(m_map.end(), m_map.end());
|
return const_node_iterator(m_map.end(), m_map.end());
|
||||||
default:
|
default:
|
||||||
return const_node_iterator();
|
return {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
node_iterator node_data::end() {
|
node_iterator node_data::end() {
|
||||||
if (!m_isDefined)
|
if (!m_isDefined)
|
||||||
return node_iterator();
|
return {};
|
||||||
|
|
||||||
switch (m_type) {
|
switch (m_type) {
|
||||||
case NodeType::Sequence:
|
case NodeType::Sequence:
|
||||||
@@ -158,12 +171,13 @@ node_iterator node_data::end() {
|
|||||||
case NodeType::Map:
|
case NodeType::Map:
|
||||||
return node_iterator(m_map.end(), m_map.end());
|
return node_iterator(m_map.end(), m_map.end());
|
||||||
default:
|
default:
|
||||||
return node_iterator();
|
return {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// sequence
|
// sequence
|
||||||
void node_data::push_back(node& node, shared_memory_holder /* pMemory */) {
|
void node_data::push_back(node& node,
|
||||||
|
const shared_memory_holder& /* pMemory */) {
|
||||||
if (m_type == NodeType::Undefined || m_type == NodeType::Null) {
|
if (m_type == NodeType::Undefined || m_type == NodeType::Null) {
|
||||||
m_type = NodeType::Sequence;
|
m_type = NodeType::Sequence;
|
||||||
reset_sequence();
|
reset_sequence();
|
||||||
@@ -175,7 +189,8 @@ void node_data::push_back(node& node, shared_memory_holder /* pMemory */) {
|
|||||||
m_sequence.push_back(&node);
|
m_sequence.push_back(&node);
|
||||||
}
|
}
|
||||||
|
|
||||||
void node_data::insert(node& key, node& value, shared_memory_holder pMemory) {
|
void node_data::insert(node& key, node& value,
|
||||||
|
const shared_memory_holder& pMemory) {
|
||||||
switch (m_type) {
|
switch (m_type) {
|
||||||
case NodeType::Map:
|
case NodeType::Map:
|
||||||
break;
|
break;
|
||||||
@@ -185,27 +200,28 @@ void node_data::insert(node& key, node& value, shared_memory_holder pMemory) {
|
|||||||
convert_to_map(pMemory);
|
convert_to_map(pMemory);
|
||||||
break;
|
break;
|
||||||
case NodeType::Scalar:
|
case NodeType::Scalar:
|
||||||
throw BadSubscript();
|
throw BadSubscript(m_mark, key);
|
||||||
}
|
}
|
||||||
|
|
||||||
insert_map_pair(key, value);
|
insert_map_pair(key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
// indexing
|
// indexing
|
||||||
node* node_data::get(node& key, shared_memory_holder /* pMemory */) const {
|
node* node_data::get(node& key,
|
||||||
|
const shared_memory_holder& /* pMemory */) const {
|
||||||
if (m_type != NodeType::Map) {
|
if (m_type != NodeType::Map) {
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (node_map::const_iterator it = m_map.begin(); it != m_map.end(); ++it) {
|
for (const auto& it : m_map) {
|
||||||
if (it->first->is(key))
|
if (it.first->is(key))
|
||||||
return it->second;
|
return it.second;
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
node& node_data::get(node& key, shared_memory_holder pMemory) {
|
node& node_data::get(node& key, const shared_memory_holder& pMemory) {
|
||||||
switch (m_type) {
|
switch (m_type) {
|
||||||
case NodeType::Map:
|
case NodeType::Map:
|
||||||
break;
|
break;
|
||||||
@@ -215,12 +231,12 @@ node& node_data::get(node& key, shared_memory_holder pMemory) {
|
|||||||
convert_to_map(pMemory);
|
convert_to_map(pMemory);
|
||||||
break;
|
break;
|
||||||
case NodeType::Scalar:
|
case NodeType::Scalar:
|
||||||
throw BadSubscript();
|
throw BadSubscript(m_mark, key);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (node_map::const_iterator it = m_map.begin(); it != m_map.end(); ++it) {
|
for (const auto& it : m_map) {
|
||||||
if (it->first->is(key))
|
if (it.first->is(key))
|
||||||
return *it->second;
|
return *it.second;
|
||||||
}
|
}
|
||||||
|
|
||||||
node& value = pMemory->create_node();
|
node& value = pMemory->create_node();
|
||||||
@@ -228,15 +244,26 @@ node& node_data::get(node& key, shared_memory_holder pMemory) {
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool node_data::remove(node& key, shared_memory_holder /* pMemory */) {
|
bool node_data::remove(node& key, const shared_memory_holder& /* pMemory */) {
|
||||||
if (m_type != NodeType::Map)
|
if (m_type != NodeType::Map)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
for (node_map::iterator it = m_map.begin(); it != m_map.end(); ++it) {
|
for (auto it = m_undefinedPairs.begin(); it != m_undefinedPairs.end();) {
|
||||||
if (it->first->is(key)) {
|
auto jt = std::next(it);
|
||||||
m_map.erase(it);
|
if (it->first->is(key))
|
||||||
return true;
|
m_undefinedPairs.erase(it);
|
||||||
}
|
it = jt;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto it =
|
||||||
|
std::find_if(m_map.begin(), m_map.end(),
|
||||||
|
[&](std::pair<YAML::detail::node*, YAML::detail::node*> j) {
|
||||||
|
return (j.first->is(key));
|
||||||
|
});
|
||||||
|
|
||||||
|
if (it != m_map.end()) {
|
||||||
|
m_map.erase(it);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@@ -253,12 +280,13 @@ void node_data::reset_map() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void node_data::insert_map_pair(node& key, node& value) {
|
void node_data::insert_map_pair(node& key, node& value) {
|
||||||
m_map[&key] = &value;
|
m_map.emplace_back(&key, &value);
|
||||||
|
|
||||||
if (!key.is_defined() || !value.is_defined())
|
if (!key.is_defined() || !value.is_defined())
|
||||||
m_undefinedPairs.push_back(kv_pair(&key, &value));
|
m_undefinedPairs.emplace_back(&key, &value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void node_data::convert_to_map(shared_memory_holder pMemory) {
|
void node_data::convert_to_map(const shared_memory_holder& pMemory) {
|
||||||
switch (m_type) {
|
switch (m_type) {
|
||||||
case NodeType::Undefined:
|
case NodeType::Undefined:
|
||||||
case NodeType::Null:
|
case NodeType::Null:
|
||||||
@@ -276,12 +304,13 @@ void node_data::convert_to_map(shared_memory_holder pMemory) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void node_data::convert_sequence_to_map(shared_memory_holder pMemory) {
|
void node_data::convert_sequence_to_map(const shared_memory_holder& pMemory) {
|
||||||
assert(m_type == NodeType::Sequence);
|
assert(m_type == NodeType::Sequence);
|
||||||
|
|
||||||
reset_map();
|
reset_map();
|
||||||
for (std::size_t i = 0; i < m_sequence.size(); i++) {
|
for (std::size_t i = 0; i < m_sequence.size(); i++) {
|
||||||
std::stringstream stream;
|
std::stringstream stream;
|
||||||
|
stream.imbue(std::locale::classic());
|
||||||
stream << i;
|
stream << i;
|
||||||
|
|
||||||
node& key = pMemory->create_node();
|
node& key = pMemory->create_node();
|
||||||
@@ -292,5 +321,5 @@ void node_data::convert_sequence_to_map(shared_memory_holder pMemory) {
|
|||||||
reset_sequence();
|
reset_sequence();
|
||||||
m_type = NodeType::Map;
|
m_type = NodeType::Map;
|
||||||
}
|
}
|
||||||
}
|
} // namespace detail
|
||||||
}
|
} // namespace YAML
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
#include <assert.h>
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
#include "nodebuilder.h"
|
#include "nodebuilder.h"
|
||||||
@@ -11,11 +10,16 @@ namespace YAML {
|
|||||||
struct Mark;
|
struct Mark;
|
||||||
|
|
||||||
NodeBuilder::NodeBuilder()
|
NodeBuilder::NodeBuilder()
|
||||||
: m_pMemory(new detail::memory_holder), m_pRoot(0), m_mapDepth(0) {
|
: m_pMemory(new detail::memory_holder),
|
||||||
m_anchors.push_back(0); // since the anchors start at 1
|
m_pRoot(nullptr),
|
||||||
|
m_stack{},
|
||||||
|
m_anchors{},
|
||||||
|
m_keys{},
|
||||||
|
m_mapDepth(0) {
|
||||||
|
m_anchors.push_back(nullptr); // since the anchors start at 1
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeBuilder::~NodeBuilder() {}
|
NodeBuilder::~NodeBuilder() = default;
|
||||||
|
|
||||||
Node NodeBuilder::Root() {
|
Node NodeBuilder::Root() {
|
||||||
if (!m_pRoot)
|
if (!m_pRoot)
|
||||||
@@ -28,8 +32,8 @@ void NodeBuilder::OnDocumentStart(const Mark&) {}
|
|||||||
|
|
||||||
void NodeBuilder::OnDocumentEnd() {}
|
void NodeBuilder::OnDocumentEnd() {}
|
||||||
|
|
||||||
void NodeBuilder::OnNull(const Mark& /* mark */, anchor_t anchor) {
|
void NodeBuilder::OnNull(const Mark& mark, anchor_t anchor) {
|
||||||
detail::node& node = Push(anchor);
|
detail::node& node = Push(mark, anchor);
|
||||||
node.set_null();
|
node.set_null();
|
||||||
Pop();
|
Pop();
|
||||||
}
|
}
|
||||||
@@ -40,18 +44,17 @@ void NodeBuilder::OnAlias(const Mark& /* mark */, anchor_t anchor) {
|
|||||||
Pop();
|
Pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
void NodeBuilder::OnScalar(const Mark& /* mark */, const std::string& tag,
|
void NodeBuilder::OnScalar(const Mark& mark, const std::string& tag,
|
||||||
anchor_t anchor, const std::string& value) {
|
anchor_t anchor, const std::string& value) {
|
||||||
detail::node& node = Push(anchor);
|
detail::node& node = Push(mark, anchor);
|
||||||
node.set_scalar(value);
|
node.set_scalar(value);
|
||||||
node.set_tag(tag);
|
node.set_tag(tag);
|
||||||
Pop();
|
Pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
void NodeBuilder::OnSequenceStart(const Mark& /* mark */,
|
void NodeBuilder::OnSequenceStart(const Mark& mark, const std::string& tag,
|
||||||
const std::string& tag, anchor_t anchor,
|
anchor_t anchor, EmitterStyle::value style) {
|
||||||
EmitterStyle::value style) {
|
detail::node& node = Push(mark, anchor);
|
||||||
detail::node& node = Push(anchor);
|
|
||||||
node.set_tag(tag);
|
node.set_tag(tag);
|
||||||
node.set_type(NodeType::Sequence);
|
node.set_type(NodeType::Sequence);
|
||||||
node.set_style(style);
|
node.set_style(style);
|
||||||
@@ -59,9 +62,9 @@ void NodeBuilder::OnSequenceStart(const Mark& /* mark */,
|
|||||||
|
|
||||||
void NodeBuilder::OnSequenceEnd() { Pop(); }
|
void NodeBuilder::OnSequenceEnd() { Pop(); }
|
||||||
|
|
||||||
void NodeBuilder::OnMapStart(const Mark& /* mark */, const std::string& tag,
|
void NodeBuilder::OnMapStart(const Mark& mark, const std::string& tag,
|
||||||
anchor_t anchor, EmitterStyle::value style) {
|
anchor_t anchor, EmitterStyle::value style) {
|
||||||
detail::node& node = Push(anchor);
|
detail::node& node = Push(mark, anchor);
|
||||||
node.set_type(NodeType::Map);
|
node.set_type(NodeType::Map);
|
||||||
node.set_tag(tag);
|
node.set_tag(tag);
|
||||||
node.set_style(style);
|
node.set_style(style);
|
||||||
@@ -74,8 +77,9 @@ void NodeBuilder::OnMapEnd() {
|
|||||||
Pop();
|
Pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
detail::node& NodeBuilder::Push(anchor_t anchor) {
|
detail::node& NodeBuilder::Push(const Mark& mark, anchor_t anchor) {
|
||||||
detail::node& node = m_pMemory->create_node();
|
detail::node& node = m_pMemory->create_node();
|
||||||
|
node.set_mark(mark);
|
||||||
RegisterAnchor(anchor, node);
|
RegisterAnchor(anchor, node);
|
||||||
Push(node);
|
Push(node);
|
||||||
return node;
|
return node;
|
||||||
@@ -88,7 +92,7 @@ void NodeBuilder::Push(detail::node& node) {
|
|||||||
|
|
||||||
m_stack.push_back(&node);
|
m_stack.push_back(&node);
|
||||||
if (needsKey)
|
if (needsKey)
|
||||||
m_keys.push_back(PushedKey(&node, false));
|
m_keys.emplace_back(&node, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NodeBuilder::Pop() {
|
void NodeBuilder::Pop() {
|
||||||
@@ -127,4 +131,4 @@ void NodeBuilder::RegisterAnchor(anchor_t anchor, detail::node& node) {
|
|||||||
m_anchors.push_back(&node);
|
m_anchors.push_back(&node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} // namespace YAML
|
||||||
|
|||||||
@@ -27,28 +27,32 @@ class Node;
|
|||||||
class NodeBuilder : public EventHandler {
|
class NodeBuilder : public EventHandler {
|
||||||
public:
|
public:
|
||||||
NodeBuilder();
|
NodeBuilder();
|
||||||
virtual ~NodeBuilder();
|
NodeBuilder(const NodeBuilder&) = delete;
|
||||||
|
NodeBuilder(NodeBuilder&&) = delete;
|
||||||
|
NodeBuilder& operator=(const NodeBuilder&) = delete;
|
||||||
|
NodeBuilder& operator=(NodeBuilder&&) = delete;
|
||||||
|
~NodeBuilder() override;
|
||||||
|
|
||||||
Node Root();
|
Node Root();
|
||||||
|
|
||||||
virtual void OnDocumentStart(const Mark& mark);
|
void OnDocumentStart(const Mark& mark) override;
|
||||||
virtual void OnDocumentEnd();
|
void OnDocumentEnd() override;
|
||||||
|
|
||||||
virtual void OnNull(const Mark& mark, anchor_t anchor);
|
void OnNull(const Mark& mark, anchor_t anchor) override;
|
||||||
virtual void OnAlias(const Mark& mark, anchor_t anchor);
|
void OnAlias(const Mark& mark, anchor_t anchor) override;
|
||||||
virtual void OnScalar(const Mark& mark, const std::string& tag,
|
void OnScalar(const Mark& mark, const std::string& tag,
|
||||||
anchor_t anchor, const std::string& value);
|
anchor_t anchor, const std::string& value) override;
|
||||||
|
|
||||||
virtual void OnSequenceStart(const Mark& mark, const std::string& tag,
|
void OnSequenceStart(const Mark& mark, const std::string& tag,
|
||||||
anchor_t anchor, EmitterStyle::value style);
|
anchor_t anchor, EmitterStyle::value style) override;
|
||||||
virtual void OnSequenceEnd();
|
void OnSequenceEnd() override;
|
||||||
|
|
||||||
virtual void OnMapStart(const Mark& mark, const std::string& tag,
|
void OnMapStart(const Mark& mark, const std::string& tag,
|
||||||
anchor_t anchor, EmitterStyle::value style);
|
anchor_t anchor, EmitterStyle::value style) override;
|
||||||
virtual void OnMapEnd();
|
void OnMapEnd() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
detail::node& Push(anchor_t anchor);
|
detail::node& Push(const Mark& mark, anchor_t anchor);
|
||||||
void Push(detail::node& node);
|
void Push(detail::node& node);
|
||||||
void Pop();
|
void Pop();
|
||||||
void RegisterAnchor(anchor_t anchor, detail::node& node);
|
void RegisterAnchor(anchor_t anchor, detail::node& node);
|
||||||
@@ -57,14 +61,14 @@ class NodeBuilder : public EventHandler {
|
|||||||
detail::shared_memory_holder m_pMemory;
|
detail::shared_memory_holder m_pMemory;
|
||||||
detail::node* m_pRoot;
|
detail::node* m_pRoot;
|
||||||
|
|
||||||
typedef std::vector<detail::node*> Nodes;
|
using Nodes = std::vector<detail::node *>;
|
||||||
Nodes m_stack;
|
Nodes m_stack;
|
||||||
Nodes m_anchors;
|
Nodes m_anchors;
|
||||||
|
|
||||||
typedef std::pair<detail::node*, bool> PushedKey;
|
using PushedKey = std::pair<detail::node*, bool>;
|
||||||
std::vector<PushedKey> m_keys;
|
std::vector<PushedKey> m_keys;
|
||||||
std::size_t m_mapDepth;
|
std::size_t m_mapDepth;
|
||||||
};
|
};
|
||||||
}
|
} // namespace YAML
|
||||||
|
|
||||||
#endif // NODE_NODEBUILDER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#endif // NODE_NODEBUILDER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|||||||
@@ -13,14 +13,14 @@ void NodeEvents::AliasManager::RegisterReference(const detail::node& node) {
|
|||||||
|
|
||||||
anchor_t NodeEvents::AliasManager::LookupAnchor(
|
anchor_t NodeEvents::AliasManager::LookupAnchor(
|
||||||
const detail::node& node) const {
|
const detail::node& node) const {
|
||||||
AnchorByIdentity::const_iterator it = m_anchorByIdentity.find(node.ref());
|
auto it = m_anchorByIdentity.find(node.ref());
|
||||||
if (it == m_anchorByIdentity.end())
|
if (it == m_anchorByIdentity.end())
|
||||||
return 0;
|
return 0;
|
||||||
return it->second;
|
return it->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeEvents::NodeEvents(const Node& node)
|
NodeEvents::NodeEvents(const Node& node)
|
||||||
: m_pMemory(node.m_pMemory), m_root(node.m_pNode) {
|
: m_pMemory(node.m_pMemory), m_root(node.m_pNode), m_refCount{} {
|
||||||
if (m_root)
|
if (m_root)
|
||||||
Setup(*m_root);
|
Setup(*m_root);
|
||||||
}
|
}
|
||||||
@@ -32,13 +32,12 @@ void NodeEvents::Setup(const detail::node& node) {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if (node.type() == NodeType::Sequence) {
|
if (node.type() == NodeType::Sequence) {
|
||||||
for (detail::const_node_iterator it = node.begin(); it != node.end(); ++it)
|
for (auto element : node)
|
||||||
Setup(**it);
|
Setup(*element);
|
||||||
} else if (node.type() == NodeType::Map) {
|
} else if (node.type() == NodeType::Map) {
|
||||||
for (detail::const_node_iterator it = node.begin(); it != node.end();
|
for (auto element : node) {
|
||||||
++it) {
|
Setup(*element.first);
|
||||||
Setup(*it->first);
|
Setup(*element.second);
|
||||||
Setup(*it->second);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -77,17 +76,15 @@ void NodeEvents::Emit(const detail::node& node, EventHandler& handler,
|
|||||||
break;
|
break;
|
||||||
case NodeType::Sequence:
|
case NodeType::Sequence:
|
||||||
handler.OnSequenceStart(Mark(), node.tag(), anchor, node.style());
|
handler.OnSequenceStart(Mark(), node.tag(), anchor, node.style());
|
||||||
for (detail::const_node_iterator it = node.begin(); it != node.end();
|
for (auto element : node)
|
||||||
++it)
|
Emit(*element, handler, am);
|
||||||
Emit(**it, handler, am);
|
|
||||||
handler.OnSequenceEnd();
|
handler.OnSequenceEnd();
|
||||||
break;
|
break;
|
||||||
case NodeType::Map:
|
case NodeType::Map:
|
||||||
handler.OnMapStart(Mark(), node.tag(), anchor, node.style());
|
handler.OnMapStart(Mark(), node.tag(), anchor, node.style());
|
||||||
for (detail::const_node_iterator it = node.begin(); it != node.end();
|
for (auto element : node) {
|
||||||
++it) {
|
Emit(*element.first, handler, am);
|
||||||
Emit(*it->first, handler, am);
|
Emit(*element.second, handler, am);
|
||||||
Emit(*it->second, handler, am);
|
|
||||||
}
|
}
|
||||||
handler.OnMapEnd();
|
handler.OnMapEnd();
|
||||||
break;
|
break;
|
||||||
@@ -95,7 +92,7 @@ void NodeEvents::Emit(const detail::node& node, EventHandler& handler,
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool NodeEvents::IsAliased(const detail::node& node) const {
|
bool NodeEvents::IsAliased(const detail::node& node) const {
|
||||||
RefCount::const_iterator it = m_refCount.find(node.ref());
|
auto it = m_refCount.find(node.ref());
|
||||||
return it != m_refCount.end() && it->second > 1;
|
return it != m_refCount.end() && it->second > 1;
|
||||||
}
|
}
|
||||||
}
|
} // namespace YAML
|
||||||
|
|||||||
@@ -26,13 +26,17 @@ class Node;
|
|||||||
class NodeEvents {
|
class NodeEvents {
|
||||||
public:
|
public:
|
||||||
explicit NodeEvents(const Node& node);
|
explicit NodeEvents(const Node& node);
|
||||||
|
NodeEvents(const NodeEvents&) = delete;
|
||||||
|
NodeEvents(NodeEvents&&) = delete;
|
||||||
|
NodeEvents& operator=(const NodeEvents&) = delete;
|
||||||
|
NodeEvents& operator=(NodeEvents&&) = delete;
|
||||||
|
|
||||||
void Emit(EventHandler& handler);
|
void Emit(EventHandler& handler);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class AliasManager {
|
class AliasManager {
|
||||||
public:
|
public:
|
||||||
AliasManager() : m_curAnchor(0) {}
|
AliasManager() : m_anchorByIdentity{}, m_curAnchor(0) {}
|
||||||
|
|
||||||
void RegisterReference(const detail::node& node);
|
void RegisterReference(const detail::node& node);
|
||||||
anchor_t LookupAnchor(const detail::node& node) const;
|
anchor_t LookupAnchor(const detail::node& node) const;
|
||||||
@@ -41,7 +45,7 @@ class NodeEvents {
|
|||||||
anchor_t _CreateNewAnchor() { return ++m_curAnchor; }
|
anchor_t _CreateNewAnchor() { return ++m_curAnchor; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef std::map<const detail::node_ref*, anchor_t> AnchorByIdentity;
|
using AnchorByIdentity = std::map<const detail::node_ref*, anchor_t>;
|
||||||
AnchorByIdentity m_anchorByIdentity;
|
AnchorByIdentity m_anchorByIdentity;
|
||||||
|
|
||||||
anchor_t m_curAnchor;
|
anchor_t m_curAnchor;
|
||||||
@@ -56,9 +60,9 @@ class NodeEvents {
|
|||||||
detail::shared_memory_holder m_pMemory;
|
detail::shared_memory_holder m_pMemory;
|
||||||
detail::node* m_root;
|
detail::node* m_root;
|
||||||
|
|
||||||
typedef std::map<const detail::node_ref*, int> RefCount;
|
using RefCount = std::map<const detail::node_ref*, int>;
|
||||||
RefCount m_refCount;
|
RefCount m_refCount;
|
||||||
};
|
};
|
||||||
}
|
} // namespace YAML
|
||||||
|
|
||||||
#endif // NODE_NODEEVENTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#endif // NODE_NODEEVENTS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|||||||
12
src/null.cpp
12
src/null.cpp
@@ -1,5 +1,17 @@
|
|||||||
#include "yaml-cpp/null.h"
|
#include "yaml-cpp/null.h"
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
namespace YAML {
|
namespace YAML {
|
||||||
_Null Null;
|
_Null Null;
|
||||||
|
|
||||||
|
template <std::size_t N>
|
||||||
|
static bool same(const char* str, std::size_t size, const char (&literal)[N]) {
|
||||||
|
constexpr int literalSize = N - 1; // minus null terminator
|
||||||
|
return size == literalSize && std::strncmp(str, literal, literalSize) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IsNullString(const char* str, std::size_t size) {
|
||||||
|
return size == 0 || same(str, size, "~") || same(str, size, "null") ||
|
||||||
|
same(str, size, "Null") || same(str, size, "NULL");
|
||||||
|
}
|
||||||
|
} // namespace YAML
|
||||||
|
|||||||
@@ -2,21 +2,26 @@
|
|||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <iostream>
|
#include <ostream>
|
||||||
|
|
||||||
namespace YAML {
|
namespace YAML {
|
||||||
ostream_wrapper::ostream_wrapper()
|
ostream_wrapper::ostream_wrapper()
|
||||||
: m_buffer(1, '\0'),
|
: m_buffer(1, '\0'),
|
||||||
m_pStream(0),
|
m_pStream(nullptr),
|
||||||
m_pos(0),
|
m_pos(0),
|
||||||
m_row(0),
|
m_row(0),
|
||||||
m_col(0),
|
m_col(0),
|
||||||
m_comment(false) {}
|
m_comment(false) {}
|
||||||
|
|
||||||
ostream_wrapper::ostream_wrapper(std::ostream& stream)
|
ostream_wrapper::ostream_wrapper(std::ostream& stream)
|
||||||
: m_pStream(&stream), m_pos(0), m_row(0), m_col(0), m_comment(false) {}
|
: m_buffer{},
|
||||||
|
m_pStream(&stream),
|
||||||
|
m_pos(0),
|
||||||
|
m_row(0),
|
||||||
|
m_col(0),
|
||||||
|
m_comment(false) {}
|
||||||
|
|
||||||
ostream_wrapper::~ostream_wrapper() {}
|
ostream_wrapper::~ostream_wrapper() = default;
|
||||||
|
|
||||||
void ostream_wrapper::write(const std::string& str) {
|
void ostream_wrapper::write(const std::string& str) {
|
||||||
if (m_pStream) {
|
if (m_pStream) {
|
||||||
@@ -26,8 +31,8 @@ void ostream_wrapper::write(const std::string& str) {
|
|||||||
std::copy(str.begin(), str.end(), m_buffer.begin() + m_pos);
|
std::copy(str.begin(), str.end(), m_buffer.begin() + m_pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (std::size_t i = 0; i < str.size(); i++) {
|
for (char ch : str) {
|
||||||
update_pos(str[i]);
|
update_pos(ch);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,4 +59,4 @@ void ostream_wrapper::update_pos(char ch) {
|
|||||||
m_comment = false;
|
m_comment = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} // namespace YAML
|
||||||
|
|||||||
@@ -3,10 +3,10 @@
|
|||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
#include "yaml-cpp/node/node.h"
|
|
||||||
#include "yaml-cpp/node/impl.h"
|
|
||||||
#include "yaml-cpp/parser.h"
|
|
||||||
#include "nodebuilder.h"
|
#include "nodebuilder.h"
|
||||||
|
#include "yaml-cpp/node/impl.h"
|
||||||
|
#include "yaml-cpp/node/node.h"
|
||||||
|
#include "yaml-cpp/parser.h"
|
||||||
|
|
||||||
namespace YAML {
|
namespace YAML {
|
||||||
Node Load(const std::string& input) {
|
Node Load(const std::string& input) {
|
||||||
@@ -22,16 +22,18 @@ Node Load(const char* input) {
|
|||||||
Node Load(std::istream& input) {
|
Node Load(std::istream& input) {
|
||||||
Parser parser(input);
|
Parser parser(input);
|
||||||
NodeBuilder builder;
|
NodeBuilder builder;
|
||||||
if (!parser.HandleNextDocument(builder))
|
if (!parser.HandleNextDocument(builder)) {
|
||||||
return Node();
|
return Node();
|
||||||
|
}
|
||||||
|
|
||||||
return builder.Root();
|
return builder.Root();
|
||||||
}
|
}
|
||||||
|
|
||||||
Node LoadFile(const std::string& filename) {
|
Node LoadFile(const std::string& filename) {
|
||||||
std::ifstream fin(filename.c_str());
|
std::ifstream fin(filename);
|
||||||
if (!fin)
|
if (!fin) {
|
||||||
throw BadFile();
|
throw BadFile(filename);
|
||||||
|
}
|
||||||
return Load(fin);
|
return Load(fin);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,10 +51,11 @@ std::vector<Node> LoadAll(std::istream& input) {
|
|||||||
std::vector<Node> docs;
|
std::vector<Node> docs;
|
||||||
|
|
||||||
Parser parser(input);
|
Parser parser(input);
|
||||||
while (1) {
|
while (true) {
|
||||||
NodeBuilder builder;
|
NodeBuilder builder;
|
||||||
if (!parser.HandleNextDocument(builder))
|
if (!parser.HandleNextDocument(builder) || builder.Root().IsNull()) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
docs.push_back(builder.Root());
|
docs.push_back(builder.Root());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,9 +63,10 @@ std::vector<Node> LoadAll(std::istream& input) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::vector<Node> LoadAllFromFile(const std::string& filename) {
|
std::vector<Node> LoadAllFromFile(const std::string& filename) {
|
||||||
std::ifstream fin(filename.c_str());
|
std::ifstream fin(filename);
|
||||||
if (!fin)
|
if (!fin) {
|
||||||
throw BadFile();
|
throw BadFile(filename);
|
||||||
|
}
|
||||||
return LoadAll(fin);
|
return LoadAll(fin);
|
||||||
}
|
}
|
||||||
}
|
} // namespace YAML
|
||||||
|
|||||||
@@ -11,55 +11,47 @@
|
|||||||
namespace YAML {
|
namespace YAML {
|
||||||
class EventHandler;
|
class EventHandler;
|
||||||
|
|
||||||
Parser::Parser() {}
|
Parser::Parser() : m_pScanner{}, m_pDirectives{} {}
|
||||||
|
|
||||||
Parser::Parser(std::istream& in) { Load(in); }
|
Parser::Parser(std::istream& in) : Parser() { Load(in); }
|
||||||
|
|
||||||
Parser::~Parser() {}
|
Parser::~Parser() = default;
|
||||||
|
|
||||||
Parser::operator bool() const {
|
Parser::operator bool() const { return m_pScanner && !m_pScanner->empty(); }
|
||||||
return m_pScanner.get() && !m_pScanner->empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Parser::Load(std::istream& in) {
|
void Parser::Load(std::istream& in) {
|
||||||
m_pScanner.reset(new Scanner(in));
|
m_pScanner.reset(new Scanner(in));
|
||||||
m_pDirectives.reset(new Directives);
|
m_pDirectives.reset(new Directives);
|
||||||
}
|
}
|
||||||
|
|
||||||
// HandleNextDocument
|
|
||||||
// . Handles the next document
|
|
||||||
// . Throws a ParserException on error.
|
|
||||||
// . Returns false if there are no more documents
|
|
||||||
bool Parser::HandleNextDocument(EventHandler& eventHandler) {
|
bool Parser::HandleNextDocument(EventHandler& eventHandler) {
|
||||||
if (!m_pScanner.get())
|
if (!m_pScanner)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
ParseDirectives();
|
ParseDirectives();
|
||||||
if (m_pScanner->empty())
|
if (m_pScanner->empty()) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
SingleDocParser sdp(*m_pScanner, *m_pDirectives);
|
SingleDocParser sdp(*m_pScanner, *m_pDirectives);
|
||||||
sdp.HandleDocument(eventHandler);
|
sdp.HandleDocument(eventHandler);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParseDirectives
|
|
||||||
// . Reads any directives that are next in the queue.
|
|
||||||
void Parser::ParseDirectives() {
|
void Parser::ParseDirectives() {
|
||||||
bool readDirective = false;
|
bool readDirective = false;
|
||||||
|
|
||||||
while (1) {
|
while (!m_pScanner->empty()) {
|
||||||
if (m_pScanner->empty())
|
|
||||||
break;
|
|
||||||
|
|
||||||
Token& token = m_pScanner->peek();
|
Token& token = m_pScanner->peek();
|
||||||
if (token.type != Token::DIRECTIVE)
|
if (token.type != Token::DIRECTIVE) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// we keep the directives from the last document if none are specified;
|
// we keep the directives from the last document if none are specified;
|
||||||
// but if any directives are specific, then we reset them
|
// but if any directives are specific, then we reset them
|
||||||
if (!readDirective)
|
if (!readDirective) {
|
||||||
m_pDirectives.reset(new Directives);
|
m_pDirectives.reset(new Directives);
|
||||||
|
}
|
||||||
|
|
||||||
readDirective = true;
|
readDirective = true;
|
||||||
HandleDirective(token);
|
HandleDirective(token);
|
||||||
@@ -68,61 +60,61 @@ void Parser::ParseDirectives() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Parser::HandleDirective(const Token& token) {
|
void Parser::HandleDirective(const Token& token) {
|
||||||
if (token.value == "YAML")
|
if (token.value == "YAML") {
|
||||||
HandleYamlDirective(token);
|
HandleYamlDirective(token);
|
||||||
else if (token.value == "TAG")
|
} else if (token.value == "TAG") {
|
||||||
HandleTagDirective(token);
|
HandleTagDirective(token);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// HandleYamlDirective
|
|
||||||
// . Should be of the form 'major.minor' (like a version number)
|
|
||||||
void Parser::HandleYamlDirective(const Token& token) {
|
void Parser::HandleYamlDirective(const Token& token) {
|
||||||
if (token.params.size() != 1)
|
if (token.params.size() != 1) {
|
||||||
throw ParserException(token.mark, ErrorMsg::YAML_DIRECTIVE_ARGS);
|
throw ParserException(token.mark, ErrorMsg::YAML_DIRECTIVE_ARGS);
|
||||||
|
}
|
||||||
|
|
||||||
if (!m_pDirectives->version.isDefault)
|
if (!m_pDirectives->version.isDefault) {
|
||||||
throw ParserException(token.mark, ErrorMsg::REPEATED_YAML_DIRECTIVE);
|
throw ParserException(token.mark, ErrorMsg::REPEATED_YAML_DIRECTIVE);
|
||||||
|
}
|
||||||
|
|
||||||
std::stringstream str(token.params[0]);
|
std::stringstream str(token.params[0]);
|
||||||
|
str.imbue(std::locale::classic());
|
||||||
str >> m_pDirectives->version.major;
|
str >> m_pDirectives->version.major;
|
||||||
str.get();
|
str.get();
|
||||||
str >> m_pDirectives->version.minor;
|
str >> m_pDirectives->version.minor;
|
||||||
if (!str || str.peek() != EOF)
|
if (!str || str.peek() != EOF) {
|
||||||
throw ParserException(
|
throw ParserException(
|
||||||
token.mark, std::string(ErrorMsg::YAML_VERSION) + token.params[0]);
|
token.mark, std::string(ErrorMsg::YAML_VERSION) + token.params[0]);
|
||||||
|
}
|
||||||
|
|
||||||
if (m_pDirectives->version.major > 1)
|
if (m_pDirectives->version.major > 1) {
|
||||||
throw ParserException(token.mark, ErrorMsg::YAML_MAJOR_VERSION);
|
throw ParserException(token.mark, ErrorMsg::YAML_MAJOR_VERSION);
|
||||||
|
}
|
||||||
|
|
||||||
m_pDirectives->version.isDefault = false;
|
m_pDirectives->version.isDefault = false;
|
||||||
// TODO: warning on major == 1, minor > 2?
|
// TODO: warning on major == 1, minor > 2?
|
||||||
}
|
}
|
||||||
|
|
||||||
// HandleTagDirective
|
|
||||||
// . Should be of the form 'handle prefix', where 'handle' is converted to
|
|
||||||
// 'prefix' in the file.
|
|
||||||
void Parser::HandleTagDirective(const Token& token) {
|
void Parser::HandleTagDirective(const Token& token) {
|
||||||
if (token.params.size() != 2)
|
if (token.params.size() != 2)
|
||||||
throw ParserException(token.mark, ErrorMsg::TAG_DIRECTIVE_ARGS);
|
throw ParserException(token.mark, ErrorMsg::TAG_DIRECTIVE_ARGS);
|
||||||
|
|
||||||
const std::string& handle = token.params[0];
|
const std::string& handle = token.params[0];
|
||||||
const std::string& prefix = token.params[1];
|
const std::string& prefix = token.params[1];
|
||||||
if (m_pDirectives->tags.find(handle) != m_pDirectives->tags.end())
|
if (m_pDirectives->tags.find(handle) != m_pDirectives->tags.end()) {
|
||||||
throw ParserException(token.mark, ErrorMsg::REPEATED_TAG_DIRECTIVE);
|
throw ParserException(token.mark, ErrorMsg::REPEATED_TAG_DIRECTIVE);
|
||||||
|
}
|
||||||
|
|
||||||
m_pDirectives->tags[handle] = prefix;
|
m_pDirectives->tags[handle] = prefix;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Parser::PrintTokens(std::ostream& out) {
|
void Parser::PrintTokens(std::ostream& out) {
|
||||||
if (!m_pScanner.get())
|
if (!m_pScanner) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
while (1) {
|
while (!m_pScanner->empty()) {
|
||||||
if (m_pScanner->empty())
|
|
||||||
break;
|
|
||||||
|
|
||||||
out << m_pScanner->peek() << "\n";
|
out << m_pScanner->peek() << "\n";
|
||||||
m_pScanner->pop();
|
m_pScanner->pop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} // namespace YAML
|
||||||
|
|||||||
@@ -1,53 +0,0 @@
|
|||||||
#ifndef PTR_STACK_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
|
||||||
#define PTR_STACK_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
|
||||||
|
|
||||||
#if defined(_MSC_VER) || \
|
|
||||||
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
|
||||||
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
|
||||||
#pragma once
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <cstddef>
|
|
||||||
#include <cstdlib>
|
|
||||||
#include <memory>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include "yaml-cpp/noncopyable.h"
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
class ptr_stack : private YAML::noncopyable {
|
|
||||||
public:
|
|
||||||
ptr_stack() {}
|
|
||||||
~ptr_stack() { clear(); }
|
|
||||||
|
|
||||||
void clear() {
|
|
||||||
for (std::size_t i = 0; i < m_data.size(); i++)
|
|
||||||
delete m_data[i];
|
|
||||||
m_data.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::size_t size() const { return m_data.size(); }
|
|
||||||
bool empty() const { return m_data.empty(); }
|
|
||||||
|
|
||||||
void push(std::auto_ptr<T> t) {
|
|
||||||
m_data.push_back(NULL);
|
|
||||||
m_data.back() = t.release();
|
|
||||||
}
|
|
||||||
std::auto_ptr<T> pop() {
|
|
||||||
std::auto_ptr<T> t(m_data.back());
|
|
||||||
m_data.pop_back();
|
|
||||||
return t;
|
|
||||||
}
|
|
||||||
T& top() { return *m_data.back(); }
|
|
||||||
const T& top() const { return *m_data.back(); }
|
|
||||||
|
|
||||||
T& top(std::ptrdiff_t diff) { return **(m_data.end() - 1 + diff); }
|
|
||||||
const T& top(std::ptrdiff_t diff) const {
|
|
||||||
return **(m_data.end() - 1 + diff);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::vector<T*> m_data;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // PTR_STACK_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
|
||||||
@@ -12,38 +12,34 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "yaml-cpp/noncopyable.h"
|
|
||||||
|
|
||||||
namespace YAML {
|
namespace YAML {
|
||||||
|
|
||||||
|
// TODO: This class is no longer needed
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class ptr_vector : private YAML::noncopyable {
|
class ptr_vector {
|
||||||
public:
|
public:
|
||||||
ptr_vector() {}
|
ptr_vector() : m_data{} {}
|
||||||
~ptr_vector() { clear(); }
|
ptr_vector(const ptr_vector&) = delete;
|
||||||
|
ptr_vector(ptr_vector&&) = default;
|
||||||
|
ptr_vector& operator=(const ptr_vector&) = delete;
|
||||||
|
ptr_vector& operator=(ptr_vector&&) = default;
|
||||||
|
|
||||||
void clear() {
|
void clear() { m_data.clear(); }
|
||||||
for (std::size_t i = 0; i < m_data.size(); i++)
|
|
||||||
delete m_data[i];
|
|
||||||
m_data.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::size_t size() const { return m_data.size(); }
|
std::size_t size() const { return m_data.size(); }
|
||||||
bool empty() const { return m_data.empty(); }
|
bool empty() const { return m_data.empty(); }
|
||||||
|
|
||||||
void push_back(std::auto_ptr<T> t) {
|
void push_back(std::unique_ptr<T>&& t) { m_data.push_back(std::move(t)); }
|
||||||
m_data.push_back(NULL);
|
|
||||||
m_data.back() = t.release();
|
|
||||||
}
|
|
||||||
T& operator[](std::size_t i) { return *m_data[i]; }
|
T& operator[](std::size_t i) { return *m_data[i]; }
|
||||||
const T& operator[](std::size_t i) const { return *m_data[i]; }
|
const T& operator[](std::size_t i) const { return *m_data[i]; }
|
||||||
|
|
||||||
T& back() { return *m_data.back(); }
|
T& back() { return *(m_data.back().get()); }
|
||||||
const T& back() const { return *m_data.back(); }
|
|
||||||
|
const T& back() const { return *(m_data.back().get()); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<T*> m_data;
|
std::vector<std::unique_ptr<T>> m_data;
|
||||||
};
|
};
|
||||||
}
|
} // namespace YAML
|
||||||
|
|
||||||
#endif // PTR_VECTOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
#endif // PTR_VECTOR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user