Compare commits
71 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 |
1
.bazelignore
Normal file
1
.bazelignore
Normal file
@ -0,0 +1 @@
|
||||
test/gtest-1.11.0
|
||||
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:
|
||||
- "*"
|
||||
|
||||
103
.github/workflows/build.yml
vendored
103
.github/workflows/build.yml
vendored
@ -6,49 +6,101 @@ on:
|
||||
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_CPP_BUILD_TESTS: 'ON'
|
||||
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: actions/checkout@v2
|
||||
|
||||
- name: Get number of CPU cores
|
||||
uses: SimenB/github-actions-cpu-cores@v1
|
||||
- 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@v4
|
||||
|
||||
- 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
|
||||
shell: bash
|
||||
run: |
|
||||
cmake ${{ env.CMAKE_GENERATOR }} -S "${{ github.workspace }}" -B build -DYAML_BUILD_SHARED_LIBS=${{ env.YAML_BUILD_SHARED_LIBS }}
|
||||
cd build && cmake --build . --parallel ${{ steps.cpu-cores.outputs.count }}
|
||||
|
||||
- name: Build Tests
|
||||
shell: bash
|
||||
run: |
|
||||
cmake ${{ env.CMAKE_GENERATOR }} -S "${{ github.workspace }}" -B build -DYAML_BUILD_SHARED_LIBS=${{ env.YAML_BUILD_SHARED_LIBS }} -DYAML_CPP_BUILD_TESTS=${{ env.YAML_CPP_BUILD_TESTS }}
|
||||
cd build && cmake --build . --parallel ${{ steps.cpu-cores.outputs.count }}
|
||||
cmake \
|
||||
--build build \
|
||||
--config ${{ env.CMAKE_BUILD_TYPE }} \
|
||||
--verbose \
|
||||
--parallel
|
||||
|
||||
- name: Run Tests
|
||||
shell: bash
|
||||
run: |
|
||||
cd build && ctest -C Debug --output-on-failure --verbose
|
||||
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:
|
||||
@ -56,17 +108,34 @@ jobs:
|
||||
os: [ubuntu-latest, windows-latest, macos-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Build
|
||||
shell: bash
|
||||
run: |
|
||||
cd "${{ github.workspace }}"
|
||||
bazel build :all
|
||||
|
||||
- name: Test
|
||||
shell: bash
|
||||
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@v4
|
||||
|
||||
- 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@b4ffde65f46336ab88eb53be808477a3936bae11 # 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 }}
|
||||
@ -1,5 +1,6 @@
|
||||
# 3.5 is actually available almost everywhere, but this a good minimum
|
||||
cmake_minimum_required(VERSION 3.4)
|
||||
# 3.5 is actually available almost everywhere, but this a good minimum.
|
||||
# 3.14 as the upper policy limit avoids CMake deprecation warnings.
|
||||
cmake_minimum_required(VERSION 3.4...3.14)
|
||||
|
||||
# enable MSVC_RUNTIME_LIBRARY target property
|
||||
# see https://cmake.org/cmake/help/latest/policy/CMP0091.html
|
||||
@ -24,13 +25,19 @@ 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" ON)
|
||||
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
|
||||
"Enable yaml-cpp tests" OFF
|
||||
"BUILD_TESTING;YAML_CPP_MAIN_PROJECT" OFF)
|
||||
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)
|
||||
@ -85,7 +92,7 @@ set_property(TARGET yaml-cpp
|
||||
CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
if (NOT YAML_BUILD_SHARED_LIBS)
|
||||
set_property(TARGET yaml-cpp PROPERTY POSITION_INDEPENDENT_CODE ON)
|
||||
set_property(TARGET yaml-cpp PROPERTY POSITION_INDEPENDENT_CODE ${YAML_ENABLE_PIC})
|
||||
endif()
|
||||
|
||||
target_include_directories(yaml-cpp
|
||||
@ -143,13 +150,12 @@ set_target_properties(yaml-cpp PROPERTIES
|
||||
PROJECT_LABEL "yaml-cpp ${yaml-cpp-label-postfix}"
|
||||
DEBUG_POSTFIX "${CMAKE_DEBUG_POSTFIX}")
|
||||
|
||||
set(CONFIG_EXPORT_DIR "${CMAKE_INSTALL_LIBDIR}/cmake/yaml-cpp")
|
||||
set(EXPORT_TARGETS yaml-cpp)
|
||||
set(EXPORT_TARGETS yaml-cpp::yaml-cpp)
|
||||
configure_package_config_file(
|
||||
"${PROJECT_SOURCE_DIR}/yaml-cpp-config.cmake.in"
|
||||
"${PROJECT_BINARY_DIR}/yaml-cpp-config.cmake"
|
||||
INSTALL_DESTINATION "${CONFIG_EXPORT_DIR}"
|
||||
PATH_VARS CMAKE_INSTALL_INCLUDEDIR CMAKE_INSTALL_LIBDIR CONFIG_EXPORT_DIR YAML_BUILD_SHARED_LIBS)
|
||||
INSTALL_DESTINATION "${YAML_CPP_INSTALL_CMAKEDIR}"
|
||||
PATH_VARS CMAKE_INSTALL_INCLUDEDIR CMAKE_INSTALL_LIBDIR)
|
||||
unset(EXPORT_TARGETS)
|
||||
|
||||
write_basic_package_version_file(
|
||||
@ -169,15 +175,14 @@ if (YAML_CPP_INSTALL)
|
||||
FILES_MATCHING PATTERN "*.h")
|
||||
install(EXPORT yaml-cpp-targets
|
||||
NAMESPACE yaml-cpp::
|
||||
DESTINATION "${CONFIG_EXPORT_DIR}")
|
||||
DESTINATION "${YAML_CPP_INSTALL_CMAKEDIR}")
|
||||
install(FILES
|
||||
"${PROJECT_BINARY_DIR}/yaml-cpp-config.cmake"
|
||||
"${PROJECT_BINARY_DIR}/yaml-cpp-config-version.cmake"
|
||||
DESTINATION "${CONFIG_EXPORT_DIR}")
|
||||
DESTINATION "${YAML_CPP_INSTALL_CMAKEDIR}")
|
||||
install(FILES "${PROJECT_BINARY_DIR}/yaml-cpp.pc"
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
|
||||
endif()
|
||||
unset(CONFIG_EXPORT_DIR)
|
||||
|
||||
if(YAML_CPP_BUILD_TESTS)
|
||||
add_subdirectory(test)
|
||||
@ -192,11 +197,12 @@ if (YAML_CPP_FORMAT_SOURCE AND YAML_CPP_CLANG_FORMAT_EXE)
|
||||
COMMAND clang-format --style=file -i $<TARGET_PROPERTY:yaml-cpp,SOURCES>
|
||||
COMMAND_EXPAND_LISTS
|
||||
COMMENT "Running clang-format"
|
||||
WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}"
|
||||
VERBATIM)
|
||||
endif()
|
||||
|
||||
# uninstall target
|
||||
if(NOT TARGET uninstall)
|
||||
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"
|
||||
|
||||
@ -17,9 +17,9 @@ Commit messages should be in the imperative mood, as described in the [Git contr
|
||||
|
||||
# Tests
|
||||
|
||||
Please verify the tests pass by running the target `test/yaml-cpp-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.
|
||||
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
|
||||
|
||||
|
||||
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": []
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
32
README.md
32
README.md
@ -31,6 +31,17 @@ cmake [-G generator] [-DYAML_BUILD_SHARED_LIBS=on|OFF] ..
|
||||
|
||||
* `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!
|
||||
@ -38,13 +49,30 @@ cmake [-G generator] [-DYAML_BUILD_SHARED_LIBS=on|OFF] ..
|
||||
|
||||
**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.6.0](https://github.com/jbeder/yaml-cpp/releases/tag/yaml-cpp-0.6.0) released! This release requires C++11, and no longer depends on Boost.
|
||||
[yaml-cpp 0.8.0](https://github.com/jbeder/yaml-cpp/releases/tag/yaml-cpp-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 continue to be supported, and will still receive bugfixes!** The 0.3.x and 0.4.x versions will be old API releases, and 0.5.x and above will all be new API releases.
|
||||
**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
|
||||
|
||||
|
||||
10
WORKSPACE
10
WORKSPACE
@ -1,10 +0,0 @@
|
||||
workspace(name = "com_github_jbeder_yaml_cpp")
|
||||
|
||||
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
|
||||
|
||||
http_archive(
|
||||
name = "com_google_googletest",
|
||||
strip_prefix = "googletest-release-1.8.1",
|
||||
url = "https://github.com/google/googletest/archive/release-1.8.1.tar.gz",
|
||||
sha256 = "9bf1fe5182a604b4135edc1a425ae356c9ad15e9b23f9f12a02e80184c3a249c",
|
||||
)
|
||||
@ -154,16 +154,11 @@ produces
|
||||
# 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;
|
||||
squares.push_back(1);
|
||||
squares.push_back(4);
|
||||
squares.push_back(9);
|
||||
squares.push_back(16);
|
||||
std::vector <int> squares = {1, 4, 9, 16};
|
||||
|
||||
std::map <std::string, int> ages;
|
||||
ages["Daniel"] = 26;
|
||||
ages["Jesse"] = 24;
|
||||
std::map <std::string, int> ages = {{"Daniel", 26}, {"Jesse", 24}};
|
||||
|
||||
YAML::Emitter out;
|
||||
out << YAML::BeginSeq;
|
||||
@ -171,6 +166,7 @@ out << YAML::Flow << squares;
|
||||
out << ages;
|
||||
out << YAML::EndSeq;
|
||||
```
|
||||
{% endraw %}
|
||||
|
||||
produces
|
||||
|
||||
|
||||
@ -15,11 +15,9 @@
|
||||
# ifndef YAML_CPP_API
|
||||
# ifdef yaml_cpp_EXPORTS
|
||||
/* We are building this library */
|
||||
# pragma message( "Defining YAML_CPP_API for DLL export" )
|
||||
# define YAML_CPP_API __declspec(dllexport)
|
||||
# else
|
||||
/* We are using this library */
|
||||
# pragma message( "Defining YAML_CPP_API for DLL import" )
|
||||
# define YAML_CPP_API __declspec(dllimport)
|
||||
# endif
|
||||
# endif
|
||||
|
||||
@ -23,6 +23,7 @@ class Emitter;
|
||||
class EmitFromEvents : public EventHandler {
|
||||
public:
|
||||
EmitFromEvents(Emitter& emitter);
|
||||
~EmitFromEvents() override = default;
|
||||
|
||||
void OnDocumentStart(const Mark& mark) override;
|
||||
void OnDocumentEnd() override;
|
||||
|
||||
@ -9,18 +9,24 @@
|
||||
|
||||
#include <cmath>
|
||||
#include <cstddef>
|
||||
#include <cstring>
|
||||
#include <limits>
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
#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/dll.h"
|
||||
#include "yaml-cpp/emitterdef.h"
|
||||
#include "yaml-cpp/emittermanip.h"
|
||||
#include "yaml-cpp/null.h"
|
||||
#include "yaml-cpp/ostream_wrapper.h"
|
||||
#include "yaml-cpp/fptostring.h"
|
||||
|
||||
namespace YAML {
|
||||
class Binary;
|
||||
@ -67,6 +73,7 @@ class YAML_CPP_API Emitter {
|
||||
Emitter& SetLocalPrecision(const _Precision& precision);
|
||||
|
||||
// overloads of write
|
||||
Emitter& Write(const char* str, std::size_t size);
|
||||
Emitter& Write(const std::string& str);
|
||||
Emitter& Write(bool b);
|
||||
Emitter& Write(char ch);
|
||||
@ -141,6 +148,7 @@ inline Emitter& Emitter::WriteIntegralType(T value) {
|
||||
PrepareNode(EmitterNodeType::Scalar);
|
||||
|
||||
std::stringstream stream;
|
||||
stream.imbue(std::locale("C"));
|
||||
PrepareIntegralStream(stream);
|
||||
stream << value;
|
||||
m_stream << stream.str();
|
||||
@ -158,6 +166,7 @@ inline Emitter& Emitter::WriteStreamable(T value) {
|
||||
PrepareNode(EmitterNodeType::Scalar);
|
||||
|
||||
std::stringstream stream;
|
||||
stream.imbue(std::locale("C"));
|
||||
SetStreamablePrecision<T>(stream);
|
||||
|
||||
bool special = false;
|
||||
@ -178,7 +187,7 @@ inline Emitter& Emitter::WriteStreamable(T value) {
|
||||
}
|
||||
|
||||
if (!special) {
|
||||
stream << value;
|
||||
stream << FpToString(value, stream.precision());
|
||||
}
|
||||
m_stream << stream.str();
|
||||
|
||||
@ -198,8 +207,13 @@ inline void Emitter::SetStreamablePrecision<double>(std::stringstream& stream) {
|
||||
}
|
||||
|
||||
// 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) {
|
||||
return emitter.Write(v);
|
||||
return emitter.Write(v.data(), v.size());
|
||||
}
|
||||
inline Emitter& operator<<(Emitter& emitter, bool v) {
|
||||
return emitter.Write(v);
|
||||
@ -230,7 +244,7 @@ inline Emitter& operator<<(Emitter& emitter, const Binary& b) {
|
||||
}
|
||||
|
||||
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) {
|
||||
|
||||
@ -8,9 +8,10 @@
|
||||
#endif
|
||||
|
||||
namespace YAML {
|
||||
struct EmitterStyle {
|
||||
enum value { Default, Block, Flow };
|
||||
};
|
||||
namespace EmitterStyle {
|
||||
enum value { Default, Block, Flow };
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // EMITTERSTYLE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
|
||||
@ -48,6 +48,8 @@ const char* const UNKNOWN_TOKEN = "unknown token";
|
||||
const char* const DOC_IN_SCALAR = "illegal document indicator 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 UNEXPECTED_SCALAR = "unexpected scalar";
|
||||
const char* const UNEXPECTED_FLOW = "plain value cannot start with flow indicator character";
|
||||
const char* const TAB_IN_INDENTATION =
|
||||
"illegal tab when looking for indentation";
|
||||
const char* const FLOW_END = "illegal flow end";
|
||||
|
||||
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
|
||||
@ -18,7 +18,7 @@
|
||||
#include <valarray>
|
||||
#include <vector>
|
||||
|
||||
#if __cplusplus >= 201703L
|
||||
#if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || __cplusplus >= 201703L)
|
||||
#include <string_view>
|
||||
#endif
|
||||
|
||||
@ -28,6 +28,7 @@
|
||||
#include "yaml-cpp/node/node.h"
|
||||
#include "yaml-cpp/node/type.h"
|
||||
#include "yaml-cpp/null.h"
|
||||
#include "yaml-cpp/fptostring.h"
|
||||
|
||||
|
||||
namespace YAML {
|
||||
@ -93,7 +94,7 @@ struct convert<char[N]> {
|
||||
static Node encode(const char* rhs) { return Node(rhs); }
|
||||
};
|
||||
|
||||
#if __cplusplus >= 201703L
|
||||
#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)); }
|
||||
@ -129,7 +130,7 @@ inner_encode(const T& rhs, std::stringstream& stream){
|
||||
stream << ".inf";
|
||||
}
|
||||
} else {
|
||||
stream << rhs;
|
||||
stream << FpToString(rhs, stream.precision());
|
||||
}
|
||||
}
|
||||
|
||||
@ -171,6 +172,7 @@ ConvertStreamTo(std::stringstream& stream, T& rhs) {
|
||||
\
|
||||
static Node encode(const type& rhs) { \
|
||||
std::stringstream stream; \
|
||||
stream.imbue(std::locale("C")); \
|
||||
stream.precision(std::numeric_limits<type>::max_digits10); \
|
||||
conversion::inner_encode(rhs, stream); \
|
||||
return Node(stream.str()); \
|
||||
@ -182,6 +184,7 @@ ConvertStreamTo(std::stringstream& stream, T& rhs) {
|
||||
} \
|
||||
const std::string& input = node.Scalar(); \
|
||||
std::stringstream stream(input); \
|
||||
stream.imbue(std::locale("C")); \
|
||||
stream.unsetf(std::ios::dec); \
|
||||
if ((stream.peek() == '-') && std::is_unsigned<type>::value) { \
|
||||
return false; \
|
||||
|
||||
@ -41,7 +41,7 @@ class iterator_base {
|
||||
using value_type = V;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using pointer = V*;
|
||||
using reference = V;
|
||||
using reference = V&;
|
||||
|
||||
public:
|
||||
iterator_base() : m_iterator(), m_pMemory() {}
|
||||
|
||||
@ -69,7 +69,7 @@ class node_iterator_base {
|
||||
using value_type = node_iterator_value<V>;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using pointer = node_iterator_value<V>*;
|
||||
using reference = 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;
|
||||
|
||||
|
||||
@ -97,7 +97,7 @@ struct as_if {
|
||||
if (!node.m_pNode)
|
||||
return fallback;
|
||||
|
||||
T t;
|
||||
T t = fallback;
|
||||
if (convert<T>::decode(node, t))
|
||||
return t;
|
||||
return fallback;
|
||||
@ -124,8 +124,8 @@ struct as_if<T, void> {
|
||||
const Node& node;
|
||||
|
||||
T operator()() const {
|
||||
if (!node.m_pNode)
|
||||
throw TypedBadConversion<T>(node.Mark());
|
||||
if (!node.m_pNode) // no fallback
|
||||
throw InvalidNode(node.m_invalidKey);
|
||||
|
||||
T t;
|
||||
if (convert<T>::decode(node, t))
|
||||
@ -140,6 +140,8 @@ struct as_if<std::string, void> {
|
||||
const Node& node;
|
||||
|
||||
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)
|
||||
|
||||
@ -8,9 +8,10 @@
|
||||
#endif
|
||||
|
||||
namespace YAML {
|
||||
struct NodeType {
|
||||
enum value { Undefined, Null, Scalar, Sequence, Map };
|
||||
};
|
||||
namespace NodeType {
|
||||
enum value { Undefined, Null, Scalar, Sequence, Map };
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // VALUE_TYPE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
#endif
|
||||
|
||||
#include "yaml-cpp/dll.h"
|
||||
#include <string>
|
||||
#include <cstddef>
|
||||
|
||||
namespace YAML {
|
||||
class Node;
|
||||
@ -18,7 +18,7 @@ inline bool operator==(const _Null&, const _Null&) { return true; }
|
||||
inline bool operator!=(const _Null&, const _Null&) { return false; }
|
||||
|
||||
YAML_CPP_API bool IsNull(const Node& node); // old API only
|
||||
YAML_CPP_API bool IsNullString(const std::string& str);
|
||||
YAML_CPP_API bool IsNullString(const char* str, std::size_t size);
|
||||
|
||||
extern YAML_CPP_API _Null Null;
|
||||
}
|
||||
|
||||
@ -121,6 +121,7 @@ template<typename Key, bool Streamable>
|
||||
struct streamable_to_string {
|
||||
static std::string impl(const Key& key) {
|
||||
std::stringstream ss;
|
||||
ss.imbue(std::locale("C"));
|
||||
ss << key;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
4196
src/contrib/dragonbox.h
Normal file
4196
src/contrib/dragonbox.h
Normal file
File diff suppressed because it is too large
Load Diff
@ -116,8 +116,13 @@ void EmitFromEvents::BeginNode() {
|
||||
}
|
||||
|
||||
void EmitFromEvents::EmitProps(const std::string& tag, anchor_t anchor) {
|
||||
if (!tag.empty() && tag != "?" && tag != "!")
|
||||
if (!tag.empty() && tag != "?" && tag != "!"){
|
||||
if (tag[0] == '!') {
|
||||
m_emitter << LocalTag(std::string(tag.begin()+1, tag.end()));
|
||||
} else {
|
||||
m_emitter << VerbatimTag(tag);
|
||||
}
|
||||
}
|
||||
if (anchor)
|
||||
m_emitter << Anchor(ToString(anchor));
|
||||
}
|
||||
|
||||
@ -213,6 +213,7 @@ void Emitter::EmitEndSeq() {
|
||||
if (m_pState->CurGroupFlowType() == FlowType::Flow) {
|
||||
if (m_stream.comment())
|
||||
m_stream << "\n";
|
||||
if (originalType == FlowType::Block || m_pState->HasBegunNode())
|
||||
m_stream << IndentTo(m_pState->CurIndent());
|
||||
if (originalType == FlowType::Block) {
|
||||
m_stream << "[";
|
||||
@ -715,33 +716,33 @@ StringEscaping::value GetStringEscapingStyle(const EMITTER_MANIP emitterManip) {
|
||||
}
|
||||
}
|
||||
|
||||
Emitter& Emitter::Write(const std::string& str) {
|
||||
Emitter& Emitter::Write(const char* str, std::size_t size) {
|
||||
if (!good())
|
||||
return *this;
|
||||
|
||||
StringEscaping::value stringEscaping = GetStringEscapingStyle(m_pState->GetOutputCharset());
|
||||
|
||||
const StringFormat::value strFormat =
|
||||
Utils::ComputeStringFormat(str, m_pState->GetStringFormat(),
|
||||
Utils::ComputeStringFormat(str, size, m_pState->GetStringFormat(),
|
||||
m_pState->CurGroupFlowType(), stringEscaping == StringEscaping::NonAscii);
|
||||
|
||||
if (strFormat == StringFormat::Literal || str.size() > 1024)
|
||||
if (strFormat == StringFormat::Literal || size > 1024)
|
||||
m_pState->SetMapKeyFormat(YAML::LongKey, FmtScope::Local);
|
||||
|
||||
PrepareNode(EmitterNodeType::Scalar);
|
||||
|
||||
switch (strFormat) {
|
||||
case StringFormat::Plain:
|
||||
m_stream << str;
|
||||
m_stream.write(str, size);
|
||||
break;
|
||||
case StringFormat::SingleQuoted:
|
||||
Utils::WriteSingleQuotedString(m_stream, str);
|
||||
Utils::WriteSingleQuotedString(m_stream, str, size);
|
||||
break;
|
||||
case StringFormat::DoubleQuoted:
|
||||
Utils::WriteDoubleQuotedString(m_stream, str, stringEscaping);
|
||||
Utils::WriteDoubleQuotedString(m_stream, str, size, stringEscaping);
|
||||
break;
|
||||
case StringFormat::Literal:
|
||||
Utils::WriteLiteralString(m_stream, str,
|
||||
Utils::WriteLiteralString(m_stream, str, size,
|
||||
m_pState->CurIndent() + m_pState->GetIndent());
|
||||
break;
|
||||
}
|
||||
@ -751,6 +752,10 @@ Emitter& Emitter::Write(const std::string& str) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
Emitter& Emitter::Write(const std::string& str) {
|
||||
return Write(str.data(), str.size());
|
||||
}
|
||||
|
||||
std::size_t Emitter::GetFloatPrecision() const {
|
||||
return m_pState->GetFloatPrecision();
|
||||
}
|
||||
@ -864,7 +869,7 @@ Emitter& Emitter::Write(const _Alias& alias) {
|
||||
|
||||
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);
|
||||
return *this;
|
||||
}
|
||||
@ -887,7 +892,7 @@ Emitter& Emitter::Write(const _Anchor& anchor) {
|
||||
|
||||
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);
|
||||
return *this;
|
||||
}
|
||||
@ -936,7 +941,7 @@ Emitter& Emitter::Write(const _Comment& comment) {
|
||||
|
||||
if (m_stream.col() > 0)
|
||||
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->SetNonContent();
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <iomanip>
|
||||
#include <sstream>
|
||||
|
||||
@ -88,8 +89,8 @@ int Utf8BytesIndicated(char ch) {
|
||||
bool IsTrailingByte(char ch) { return (ch & 0xC0) == 0x80; }
|
||||
|
||||
bool GetNextCodePointAndAdvance(int& codePoint,
|
||||
std::string::const_iterator& first,
|
||||
std::string::const_iterator last) {
|
||||
const char*& first,
|
||||
const char* last) {
|
||||
if (first == last)
|
||||
return false;
|
||||
|
||||
@ -152,39 +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) {
|
||||
// check against null
|
||||
if (IsNullString(str)) {
|
||||
if (IsNullString(str, size)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// check the start
|
||||
const RegEx& start = (flowType == FlowType::Flow ? Exp::PlainScalarInFlow()
|
||||
: Exp::PlainScalar());
|
||||
if (!start.Matches(str)) {
|
||||
if (!start.Matches(StringCharSource(str, size))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// and check the end for plain whitespace (which can't be faithfully kept in a
|
||||
// plain scalar)
|
||||
if (!str.empty() && *str.rbegin() == ' ') {
|
||||
if (size != 0 && str[size - 1] == ' ') {
|
||||
return false;
|
||||
}
|
||||
|
||||
// then check until something is disallowed
|
||||
static const RegEx& disallowed_flow =
|
||||
static const RegEx disallowed_flow =
|
||||
Exp::EndScalarInFlow() | (Exp::BlankOrBreak() + Exp::Comment()) |
|
||||
Exp::NotPrintable() | Exp::Utf8_ByteOrderMark() | Exp::Break() |
|
||||
Exp::Tab() | Exp::Ampersand();
|
||||
static const RegEx& disallowed_block =
|
||||
static const RegEx disallowed_block =
|
||||
Exp::EndScalar() | (Exp::BlankOrBreak() + Exp::Comment()) |
|
||||
Exp::NotPrintable() | Exp::Utf8_ByteOrderMark() | Exp::Break() |
|
||||
Exp::Tab() | Exp::Ampersand();
|
||||
const RegEx& disallowed =
|
||||
flowType == FlowType::Flow ? disallowed_flow : disallowed_block;
|
||||
|
||||
StringCharSource buffer(str.c_str(), str.size());
|
||||
StringCharSource buffer(str, size);
|
||||
while (buffer) {
|
||||
if (disallowed.Matches(buffer)) {
|
||||
return false;
|
||||
@ -198,22 +199,22 @@ bool IsValidPlainScalar(const std::string& str, FlowType::value flowType,
|
||||
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?
|
||||
return std::none_of(str.begin(), str.end(), [=](char ch) {
|
||||
return std::none_of(str, str + size, [=](char ch) {
|
||||
return (escapeNonAscii && (0x80 <= static_cast<unsigned char>(ch))) ||
|
||||
(ch == '\n');
|
||||
});
|
||||
}
|
||||
|
||||
bool IsValidLiteralScalar(const std::string& str, FlowType::value flowType,
|
||||
bool IsValidLiteralScalar(const char* str, std::size_t size, FlowType::value flowType,
|
||||
bool escapeNonAscii) {
|
||||
if (flowType == FlowType::Flow) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: check for non-printable characters?
|
||||
return std::none_of(str.begin(), str.end(), [=](char ch) {
|
||||
return std::none_of(str, str + size, [=](char ch) {
|
||||
return (escapeNonAscii && (0x80 <= static_cast<unsigned char>(ch)));
|
||||
});
|
||||
}
|
||||
@ -253,10 +254,10 @@ void WriteDoubleQuoteEscapeSequence(ostream_wrapper& out, int codePoint, StringE
|
||||
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;
|
||||
for (std::string::const_iterator i = str.begin();
|
||||
GetNextCodePointAndAdvance(codePoint, i, str.end());) {
|
||||
for (const char* i = str;
|
||||
GetNextCodePointAndAdvance(codePoint, i, str + size);) {
|
||||
if (!IsAnchorChar(codePoint)) {
|
||||
return false;
|
||||
}
|
||||
@ -267,25 +268,25 @@ bool WriteAliasName(ostream_wrapper& out, const std::string& str) {
|
||||
}
|
||||
} // namespace
|
||||
|
||||
StringFormat::value ComputeStringFormat(const std::string& str,
|
||||
StringFormat::value ComputeStringFormat(const char* str, std::size_t size,
|
||||
EMITTER_MANIP strFormat,
|
||||
FlowType::value flowType,
|
||||
bool escapeNonAscii) {
|
||||
switch (strFormat) {
|
||||
case Auto:
|
||||
if (IsValidPlainScalar(str, flowType, escapeNonAscii)) {
|
||||
if (IsValidPlainScalar(str, size, flowType, escapeNonAscii)) {
|
||||
return StringFormat::Plain;
|
||||
}
|
||||
return StringFormat::DoubleQuoted;
|
||||
case SingleQuoted:
|
||||
if (IsValidSingleQuotedScalar(str, escapeNonAscii)) {
|
||||
if (IsValidSingleQuotedScalar(str, size, escapeNonAscii)) {
|
||||
return StringFormat::SingleQuoted;
|
||||
}
|
||||
return StringFormat::DoubleQuoted;
|
||||
case DoubleQuoted:
|
||||
return StringFormat::DoubleQuoted;
|
||||
case Literal:
|
||||
if (IsValidLiteralScalar(str, flowType, escapeNonAscii)) {
|
||||
if (IsValidLiteralScalar(str, size, flowType, escapeNonAscii)) {
|
||||
return StringFormat::Literal;
|
||||
}
|
||||
return StringFormat::DoubleQuoted;
|
||||
@ -296,11 +297,11 @@ StringFormat::value ComputeStringFormat(const std::string& str,
|
||||
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 << "'";
|
||||
int codePoint;
|
||||
for (std::string::const_iterator i = str.begin();
|
||||
GetNextCodePointAndAdvance(codePoint, i, str.end());) {
|
||||
for (const char* i = str;
|
||||
GetNextCodePointAndAdvance(codePoint, i, str + size);) {
|
||||
if (codePoint == '\n') {
|
||||
return false; // We can't handle a new line and the attendant indentation
|
||||
// yet
|
||||
@ -316,12 +317,12 @@ bool WriteSingleQuotedString(ostream_wrapper& out, const std::string& str) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WriteDoubleQuotedString(ostream_wrapper& out, const std::string& str,
|
||||
bool WriteDoubleQuotedString(ostream_wrapper& out, const char* str, std::size_t size,
|
||||
StringEscaping::value stringEscaping) {
|
||||
out << "\"";
|
||||
int codePoint;
|
||||
for (std::string::const_iterator i = str.begin();
|
||||
GetNextCodePointAndAdvance(codePoint, i, str.end());) {
|
||||
for (const char* i = str;
|
||||
GetNextCodePointAndAdvance(codePoint, i, str + size);) {
|
||||
switch (codePoint) {
|
||||
case '\"':
|
||||
out << "\\\"";
|
||||
@ -363,12 +364,12 @@ bool WriteDoubleQuotedString(ostream_wrapper& out, const std::string& str,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WriteLiteralString(ostream_wrapper& out, const std::string& str,
|
||||
bool WriteLiteralString(ostream_wrapper& out, const char* str, std::size_t size,
|
||||
std::size_t indent) {
|
||||
out << "|\n";
|
||||
int codePoint;
|
||||
for (std::string::const_iterator i = str.begin();
|
||||
GetNextCodePointAndAdvance(codePoint, i, str.end());) {
|
||||
for (const char* i = str;
|
||||
GetNextCodePointAndAdvance(codePoint, i, str + size);) {
|
||||
if (codePoint == '\n') {
|
||||
out << "\n";
|
||||
} else {
|
||||
@ -406,14 +407,14 @@ bool WriteChar(ostream_wrapper& out, char ch, StringEscaping::value stringEscapi
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WriteComment(ostream_wrapper& out, const std::string& str,
|
||||
bool WriteComment(ostream_wrapper& out, const char* str, std::size_t size,
|
||||
std::size_t postCommentIndent) {
|
||||
const std::size_t curIndent = out.col();
|
||||
out << "#" << Indentation(postCommentIndent);
|
||||
out.set_comment();
|
||||
int codePoint;
|
||||
for (std::string::const_iterator i = str.begin();
|
||||
GetNextCodePointAndAdvance(codePoint, i, str.end());) {
|
||||
for (const char* i = str;
|
||||
GetNextCodePointAndAdvance(codePoint, i, str + size);) {
|
||||
if (codePoint == '\n') {
|
||||
out << "\n"
|
||||
<< IndentTo(curIndent) << "#" << Indentation(postCommentIndent);
|
||||
@ -425,14 +426,14 @@ bool WriteComment(ostream_wrapper& out, const std::string& str,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WriteAlias(ostream_wrapper& out, const std::string& str) {
|
||||
bool WriteAlias(ostream_wrapper& out, const char* str, std::size_t size) {
|
||||
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 << "&";
|
||||
return WriteAliasName(out, str);
|
||||
return WriteAliasName(out, str, size);
|
||||
}
|
||||
|
||||
bool WriteTag(ostream_wrapper& out, const std::string& str, bool verbatim) {
|
||||
@ -489,7 +490,8 @@ bool WriteTagWithPrefix(ostream_wrapper& out, const std::string& prefix,
|
||||
}
|
||||
|
||||
bool WriteBinary(ostream_wrapper& out, const Binary& binary) {
|
||||
WriteDoubleQuotedString(out, EncodeBase64(binary.data(), binary.size()),
|
||||
std::string encoded = EncodeBase64(binary.data(), binary.size());
|
||||
WriteDoubleQuotedString(out, encoded.data(), encoded.size(),
|
||||
StringEscaping::None);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -29,22 +29,22 @@ struct StringEscaping {
|
||||
};
|
||||
|
||||
namespace Utils {
|
||||
StringFormat::value ComputeStringFormat(const std::string& str,
|
||||
StringFormat::value ComputeStringFormat(const char* str, std::size_t size,
|
||||
EMITTER_MANIP strFormat,
|
||||
FlowType::value flowType,
|
||||
bool escapeNonAscii);
|
||||
|
||||
bool WriteSingleQuotedString(ostream_wrapper& out, const std::string& str);
|
||||
bool WriteDoubleQuotedString(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 char* str, std::size_t size,
|
||||
StringEscaping::value stringEscaping);
|
||||
bool WriteLiteralString(ostream_wrapper& out, const std::string& str,
|
||||
bool WriteLiteralString(ostream_wrapper& out, const char* str, std::size_t size,
|
||||
std::size_t indent);
|
||||
bool WriteChar(ostream_wrapper& out, char ch,
|
||||
StringEscaping::value stringEscapingStyle);
|
||||
bool WriteComment(ostream_wrapper& out, const std::string& str,
|
||||
bool WriteComment(ostream_wrapper& out, const char* str, std::size_t size,
|
||||
std::size_t postCommentIndent);
|
||||
bool WriteAlias(ostream_wrapper& out, const std::string& str);
|
||||
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 WriteTagWithPrefix(ostream_wrapper& out, const std::string& prefix,
|
||||
const std::string& tag);
|
||||
|
||||
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("C"));
|
||||
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("C"));
|
||||
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("C"));
|
||||
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("C"));
|
||||
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
|
||||
#endif
|
||||
|
||||
#include <iostream>
|
||||
#include <cstddef>
|
||||
|
||||
#include "yaml-cpp/ostream_wrapper.h"
|
||||
|
||||
@ -310,6 +310,7 @@ void node_data::convert_sequence_to_map(const shared_memory_holder& pMemory) {
|
||||
reset_map();
|
||||
for (std::size_t i = 0; i < m_sequence.size(); i++) {
|
||||
std::stringstream stream;
|
||||
stream.imbue(std::locale("C"));
|
||||
stream << i;
|
||||
|
||||
node& key = pMemory->create_node();
|
||||
|
||||
13
src/null.cpp
13
src/null.cpp
@ -1,10 +1,17 @@
|
||||
#include "yaml-cpp/null.h"
|
||||
#include <cstring>
|
||||
|
||||
namespace YAML {
|
||||
_Null Null;
|
||||
|
||||
bool IsNullString(const std::string& str) {
|
||||
return str.empty() || str == "~" || str == "null" || str == "Null" ||
|
||||
str == "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,7 +2,7 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
#include <ostream>
|
||||
|
||||
namespace YAML {
|
||||
ostream_wrapper::ostream_wrapper()
|
||||
|
||||
@ -53,7 +53,7 @@ std::vector<Node> LoadAll(std::istream& input) {
|
||||
Parser parser(input);
|
||||
while (true) {
|
||||
NodeBuilder builder;
|
||||
if (!parser.HandleNextDocument(builder)) {
|
||||
if (!parser.HandleNextDocument(builder) || builder.Root().IsNull()) {
|
||||
break;
|
||||
}
|
||||
docs.push_back(builder.Root());
|
||||
|
||||
@ -77,6 +77,7 @@ void Parser::HandleYamlDirective(const Token& token) {
|
||||
}
|
||||
|
||||
std::stringstream str(token.params[0]);
|
||||
str.imbue(std::locale("C"));
|
||||
str >> m_pDirectives->version.major;
|
||||
str.get();
|
||||
str >> m_pDirectives->version.minor;
|
||||
|
||||
@ -27,6 +27,10 @@ inline bool RegEx::Matches(const Stream& in) const { return Match(in) >= 0; }
|
||||
|
||||
template <typename Source>
|
||||
inline bool RegEx::Matches(const Source& source) const {
|
||||
#if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201103L) || __cplusplus >= 201103L)
|
||||
static_assert(!std::is_same<Source, const char*>::value,
|
||||
#endif
|
||||
"Must use StringCharSource instead of plain C-string");
|
||||
return Match(source) >= 0;
|
||||
}
|
||||
|
||||
|
||||
@ -13,6 +13,7 @@ Scanner::Scanner(std::istream& in)
|
||||
m_startedStream(false),
|
||||
m_endedStream(false),
|
||||
m_simpleKeyAllowed(false),
|
||||
m_scalarValueAllowed(false),
|
||||
m_canBeJSONFlow(false),
|
||||
m_simpleKeys{},
|
||||
m_indents{},
|
||||
@ -127,6 +128,17 @@ void Scanner::ScanNextToken() {
|
||||
}
|
||||
|
||||
if (INPUT.peek() == Keys::FlowEntry) {
|
||||
// values starting with `,` are not allowed.
|
||||
// eg: reject `,foo`
|
||||
if (INPUT.column() == 0) {
|
||||
throw ParserException(INPUT.mark(), ErrorMsg::UNEXPECTED_FLOW);
|
||||
}
|
||||
// if we already parsed a quoted scalar value and we are not in a flow,
|
||||
// then `,` is not a valid character.
|
||||
// eg: reject `"foo",`
|
||||
if (!m_scalarValueAllowed) {
|
||||
throw ParserException(INPUT.mark(), ErrorMsg::UNEXPECTED_SCALAR);
|
||||
}
|
||||
return ScanFlowEntry();
|
||||
}
|
||||
|
||||
@ -159,6 +171,13 @@ void Scanner::ScanNextToken() {
|
||||
return ScanBlockScalar();
|
||||
}
|
||||
|
||||
// if we already parsed a quoted scalar value in this line,
|
||||
// another scalar value is an error.
|
||||
// eg: reject `"foo" "bar"`
|
||||
if (!m_scalarValueAllowed) {
|
||||
throw ParserException(INPUT.mark(), ErrorMsg::UNEXPECTED_SCALAR);
|
||||
}
|
||||
|
||||
if (INPUT.peek() == '\'' || INPUT.peek() == '\"') {
|
||||
return ScanQuotedScalar();
|
||||
}
|
||||
@ -203,6 +222,9 @@ void Scanner::ScanToNextToken() {
|
||||
// oh yeah, and let's get rid of that simple key
|
||||
InvalidateSimpleKey();
|
||||
|
||||
// new line - we accept a scalar value now
|
||||
m_scalarValueAllowed = true;
|
||||
|
||||
// new line - we may be able to accept a simple key now
|
||||
if (InBlockContext()) {
|
||||
m_simpleKeyAllowed = true;
|
||||
@ -245,6 +267,7 @@ const RegEx& Scanner::GetValueRegex() const {
|
||||
void Scanner::StartStream() {
|
||||
m_startedStream = true;
|
||||
m_simpleKeyAllowed = true;
|
||||
m_scalarValueAllowed = true;
|
||||
std::unique_ptr<IndentMarker> pIndent(
|
||||
new IndentMarker(-1, IndentMarker::NONE));
|
||||
m_indentRefs.push_back(std::move(pIndent));
|
||||
@ -261,6 +284,7 @@ void Scanner::EndStream() {
|
||||
PopAllSimpleKeys();
|
||||
|
||||
m_simpleKeyAllowed = false;
|
||||
m_scalarValueAllowed = false;
|
||||
m_endedStream = true;
|
||||
}
|
||||
|
||||
|
||||
@ -177,6 +177,7 @@ class Scanner {
|
||||
// state info
|
||||
bool m_startedStream, m_endedStream;
|
||||
bool m_simpleKeyAllowed;
|
||||
bool m_scalarValueAllowed;
|
||||
bool m_canBeJSONFlow;
|
||||
std::stack<SimpleKey> m_simpleKeys;
|
||||
std::stack<IndentMarker *> m_indents;
|
||||
|
||||
@ -211,6 +211,9 @@ void Scanner::ScanValue() {
|
||||
m_simpleKeyAllowed = InBlockContext();
|
||||
}
|
||||
|
||||
// we are parsing a `key: value` pair; scalars are always allowed
|
||||
m_scalarValueAllowed = true;
|
||||
|
||||
// eat
|
||||
Mark mark = INPUT.mark();
|
||||
INPUT.eat(1);
|
||||
@ -360,6 +363,10 @@ void Scanner::ScanQuotedScalar() {
|
||||
// and scan
|
||||
scalar = ScanScalar(INPUT, params);
|
||||
m_simpleKeyAllowed = false;
|
||||
// we just scanned a quoted scalar;
|
||||
// we can only have another scalar in this line
|
||||
// if we are in a flow, eg: `[ "foo", "bar" ]` is ok, but `"foo", "bar"` isn't.
|
||||
m_scalarValueAllowed = InFlowContext();
|
||||
m_canBeJSONFlow = true;
|
||||
|
||||
Token token(Token::NON_PLAIN_SCALAR, mark);
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
#include <algorithm>
|
||||
#include <cstdio>
|
||||
#include <sstream>
|
||||
|
||||
@ -95,7 +94,7 @@ void SingleDocParser::HandleNode(EventHandler& eventHandler) {
|
||||
tag = (token.type == Token::NON_PLAIN_SCALAR ? "!" : "?");
|
||||
|
||||
if (token.type == Token::PLAIN_SCALAR
|
||||
&& tag.compare("?") == 0 && IsNullString(token.value)) {
|
||||
&& tag.compare("?") == 0 && IsNullString(token.value.data(), token.value.size())) {
|
||||
eventHandler.OnNull(mark, anchor);
|
||||
m_scanner.pop();
|
||||
return;
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
#include <iostream>
|
||||
#include <istream>
|
||||
|
||||
#include "stream.h"
|
||||
|
||||
@ -262,7 +262,24 @@ char Stream::get() {
|
||||
AdvanceCurrent();
|
||||
m_mark.column++;
|
||||
|
||||
if (ch == '\n') {
|
||||
// if line ending symbol is unknown, set it to the first
|
||||
// encountered line ending.
|
||||
// if line ending '\r' set ending symbol to '\r'
|
||||
// other wise set it to '\n'
|
||||
if (!m_lineEndingSymbol) {
|
||||
if (ch == '\n') { // line ending is '\n'
|
||||
m_lineEndingSymbol = '\n';
|
||||
} else if (ch == '\r') {
|
||||
auto ch2 = peek();
|
||||
if (ch2 == '\n') { // line ending is '\r\n'
|
||||
m_lineEndingSymbol = '\n';
|
||||
} else { // line ending is '\r'
|
||||
m_lineEndingSymbol = '\r';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ch == m_lineEndingSymbol) {
|
||||
m_mark.column = 0;
|
||||
m_mark.line++;
|
||||
}
|
||||
|
||||
@ -11,7 +11,7 @@
|
||||
#include <cstddef>
|
||||
#include <deque>
|
||||
#include <ios>
|
||||
#include <iostream>
|
||||
#include <istream>
|
||||
#include <set>
|
||||
#include <string>
|
||||
|
||||
@ -53,6 +53,7 @@ class Stream {
|
||||
Mark m_mark;
|
||||
|
||||
CharacterSet m_charSet;
|
||||
char m_lineEndingSymbol{}; // 0 means it is not determined yet, must be '\n' or '\r'
|
||||
mutable std::deque<char> m_readahead;
|
||||
unsigned char* const m_pPrefetched;
|
||||
mutable size_t m_nPrefetchedAvailable;
|
||||
|
||||
@ -8,17 +8,18 @@
|
||||
#endif
|
||||
|
||||
#include "yaml-cpp/mark.h"
|
||||
#include <iostream>
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace YAML {
|
||||
const std::string TokenNames[] = {
|
||||
constexpr const char* TokenNames[] = {
|
||||
"DIRECTIVE", "DOC_START", "DOC_END", "BLOCK_SEQ_START",
|
||||
"BLOCK_MAP_START", "BLOCK_SEQ_END", "BLOCK_MAP_END", "BLOCK_ENTRY",
|
||||
"FLOW_SEQ_START", "FLOW_MAP_START", "FLOW_SEQ_END", "FLOW_MAP_END",
|
||||
"FLOW_MAP_COMPACT", "FLOW_ENTRY", "KEY", "VALUE",
|
||||
"ANCHOR", "ALIAS", "TAG", "SCALAR"};
|
||||
"ANCHOR", "ALIAS", "TAG", "SCALAR",
|
||||
"NON_PLAIN_SCALAR"};
|
||||
|
||||
struct Token {
|
||||
// enums
|
||||
|
||||
@ -1,14 +1,28 @@
|
||||
package(default_visibility = ["//test:__subpackages__"])
|
||||
|
||||
cc_library(
|
||||
name = "mock_event_handler",
|
||||
hdrs = ["mock_event_handler.h"],
|
||||
strip_include_prefix = "//test",
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "specexamples",
|
||||
hdrs = ["specexamples.h"],
|
||||
strip_include_prefix = "//test",
|
||||
)
|
||||
|
||||
cc_test(
|
||||
name = "test",
|
||||
srcs = glob([
|
||||
"*.cpp",
|
||||
"*.h",
|
||||
"integrations/*.cpp",
|
||||
"node/*.cpp",
|
||||
]),
|
||||
deps = [
|
||||
":mock_event_handler",
|
||||
":specexamples",
|
||||
"//:yaml-cpp",
|
||||
"//:yaml-cpp_internal",
|
||||
"@com_google_googletest//:gtest_main",
|
||||
"@googletest//:gtest_main",
|
||||
],
|
||||
)
|
||||
|
||||
@ -2,13 +2,20 @@ find_package(Threads REQUIRED)
|
||||
|
||||
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
|
||||
set(BUILD_MOCK ON CACHE BOOL "" FORCE)
|
||||
set(INSTALL_GTEST OFF CACHE BOOL "" FORCE)
|
||||
set(CMAKE_POLICY_DEFAULT_CMP0048 NEW)
|
||||
|
||||
add_subdirectory(
|
||||
if(YAML_USE_SYSTEM_GTEST)
|
||||
find_package(GTest)
|
||||
if (NOT GTEST_FOUND)
|
||||
message(FATAL_ERROR "system googletest was requested but not found")
|
||||
endif()
|
||||
else()
|
||||
add_subdirectory(
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/gtest-1.11.0"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/prefix")
|
||||
|
||||
include_directories(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/gtest-1.11.0/googletest/include")
|
||||
include_directories(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/gtest-1.11.0/googletest/include")
|
||||
endif()
|
||||
|
||||
set(test-new-api-pattern "new-api/*.cpp")
|
||||
set(test-source-pattern "*.cpp" "integration/*.cpp" "node/*.cpp")
|
||||
@ -33,11 +40,12 @@ target_include_directories(yaml-cpp-tests
|
||||
target_compile_options(yaml-cpp-tests
|
||||
PRIVATE
|
||||
$<$<CXX_COMPILER_ID:Clang>:-Wno-c99-extensions -Wno-variadic-macros -Wno-sign-compare>
|
||||
$<$<CXX_COMPILER_ID:GNU>:-Wno-variadic-macros -Wno-sign-compare>)
|
||||
$<$<CXX_COMPILER_ID:GNU>:-Wno-variadic-macros -Wno-sign-compare -Wno-narrowing>)
|
||||
target_link_libraries(yaml-cpp-tests
|
||||
PRIVATE
|
||||
Threads::Threads
|
||||
yaml-cpp
|
||||
gtest
|
||||
gmock)
|
||||
|
||||
set_property(TARGET yaml-cpp-tests PROPERTY CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
21
test/cmake/CMakeLists.txt
Normal file
21
test/cmake/CMakeLists.txt
Normal file
@ -0,0 +1,21 @@
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
project(yaml-cpp-consumer LANGUAGES CXX)
|
||||
|
||||
find_package(yaml-cpp CONFIG REQUIRED)
|
||||
get_target_property(LIBRARY_TYPE yaml-cpp::yaml-cpp TYPE)
|
||||
|
||||
if(LIBRARY_TYPE STREQUAL "SHARED_LIBRARY")
|
||||
if(NOT YAML_CPP_SHARED_LIBS_BUILT)
|
||||
message(FATAL_ERROR "Library type (${LIBRARY_TYPE}) contradicts config: ${YAML_CPP_SHARED_LIBS_BUILT}")
|
||||
endif()
|
||||
else()
|
||||
if(YAML_CPP_SHARED_LIBS_BUILT)
|
||||
message(FATAL_ERROR "Library type (${LIBRARY_TYPE}) contradicts config: ${YAML_CPP_SHARED_LIBS_BUILT}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
add_executable(main main.cpp)
|
||||
if (NOT DEFINED CMAKE_CXX_STANDARD)
|
||||
set_target_properties(main PROPERTIES CXX_STANDARD 11)
|
||||
endif()
|
||||
target_link_libraries(main PRIVATE ${YAML_CPP_LIBRARIES})
|
||||
3
test/cmake/main.cpp
Normal file
3
test/cmake/main.cpp
Normal file
@ -0,0 +1,3 @@
|
||||
#include "yaml-cpp/yaml.h"
|
||||
|
||||
int main(int, char**) { YAML::Parser foo{}; }
|
||||
242
test/fptostring_test.cpp
Normal file
242
test/fptostring_test.cpp
Normal file
@ -0,0 +1,242 @@
|
||||
#include "yaml-cpp/fptostring.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
namespace YAML {
|
||||
namespace {
|
||||
|
||||
/**
|
||||
* Helper function, that converts double to string as std::stringstream would do
|
||||
*/
|
||||
template <typename T>
|
||||
static std::string convert_with_stringstream(T v, size_t precision = 0) {
|
||||
std::stringstream ss;
|
||||
if (precision > 0) {
|
||||
ss << std::setprecision(precision);
|
||||
}
|
||||
ss << v;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
// Caution: Test involving 'convert_with_stringstream' are based on std::stringstream
|
||||
// having certain printing behavior, if these changes, the unit test might fail.
|
||||
// This is not a fault of FpToString just a weakness of the way these
|
||||
// tests are constructed
|
||||
|
||||
TEST(FpToStringTest, conversion_double) {
|
||||
// Issue motivating FpToString function,
|
||||
// https://github.com/jbeder/yaml-cpp/issues/1289
|
||||
// Original problem at hand:
|
||||
EXPECT_EQ("34.34", FpToString(34.34));
|
||||
EXPECT_EQ("56.56", FpToString(56.56));
|
||||
EXPECT_EQ("12.12", FpToString(12.12));
|
||||
EXPECT_EQ("78.78", FpToString(78.78));
|
||||
|
||||
// Special challenge with rounding
|
||||
// https://github.com/jbeder/yaml-cpp/issues/1289#issuecomment-2211705536
|
||||
EXPECT_EQ("1.54743e+26", FpToString(1.5474250491e+26f));
|
||||
EXPECT_EQ(convert_with_stringstream(1.5474250491e+26f), FpToString(1.5474250491e+26f));
|
||||
EXPECT_EQ("1.5474251e+26", FpToString(1.5474250491e+26f, 8));
|
||||
|
||||
// prints the same way as std::stringstream
|
||||
EXPECT_EQ(convert_with_stringstream(1.), FpToString(1.));
|
||||
EXPECT_EQ(convert_with_stringstream(1e0), FpToString(1e0));
|
||||
EXPECT_EQ(convert_with_stringstream(1e1), FpToString(1e1));
|
||||
EXPECT_EQ(convert_with_stringstream(1e2), FpToString(1e2));
|
||||
EXPECT_EQ(convert_with_stringstream(1e3), FpToString(1e3));
|
||||
EXPECT_EQ(convert_with_stringstream(1e4), FpToString(1e4));
|
||||
EXPECT_EQ(convert_with_stringstream(1e5), FpToString(1e5));
|
||||
EXPECT_EQ(convert_with_stringstream(1e6), FpToString(1e6));
|
||||
EXPECT_EQ(convert_with_stringstream(1e7), FpToString(1e7));
|
||||
EXPECT_EQ(convert_with_stringstream(1e8), FpToString(1e8));
|
||||
EXPECT_EQ(convert_with_stringstream(1e9), FpToString(1e9));
|
||||
|
||||
// Print by default values below 1e6 without scientific notation
|
||||
EXPECT_EQ("1", FpToString(1.));
|
||||
EXPECT_EQ("1", FpToString(1e0));
|
||||
EXPECT_EQ("10", FpToString(1e1));
|
||||
EXPECT_EQ("100", FpToString(1e2));
|
||||
EXPECT_EQ("1000", FpToString(1e3));
|
||||
EXPECT_EQ("10000", FpToString(1e4));
|
||||
EXPECT_EQ("100000", FpToString(1e5));
|
||||
EXPECT_EQ("1e+06", FpToString(1e6));
|
||||
EXPECT_EQ("1e+07", FpToString(1e7));
|
||||
EXPECT_EQ("1e+08", FpToString(1e8));
|
||||
EXPECT_EQ("1e+09", FpToString(1e9));
|
||||
|
||||
// prints the same way as std::stringstream
|
||||
EXPECT_EQ(convert_with_stringstream(1.), FpToString(1.));
|
||||
EXPECT_EQ(convert_with_stringstream(1e-0), FpToString(1e-0));
|
||||
EXPECT_EQ(convert_with_stringstream(1e-1), FpToString(1e-1));
|
||||
EXPECT_EQ(convert_with_stringstream(1e-2), FpToString(1e-2));
|
||||
EXPECT_EQ(convert_with_stringstream(1e-3), FpToString(1e-3));
|
||||
EXPECT_EQ(convert_with_stringstream(1e-4), FpToString(1e-4));
|
||||
EXPECT_EQ(convert_with_stringstream(1e-5), FpToString(1e-5));
|
||||
EXPECT_EQ(convert_with_stringstream(1e-6), FpToString(1e-6));
|
||||
EXPECT_EQ(convert_with_stringstream(1e-7), FpToString(1e-7));
|
||||
EXPECT_EQ(convert_with_stringstream(1e-8), FpToString(1e-8));
|
||||
EXPECT_EQ(convert_with_stringstream(1e-9), FpToString(1e-9));
|
||||
|
||||
// Print by default values above 1e-5 without scientific notation
|
||||
EXPECT_EQ("1", FpToString(1.));
|
||||
EXPECT_EQ("1", FpToString(1e-0));
|
||||
EXPECT_EQ("0.1", FpToString(1e-1));
|
||||
EXPECT_EQ("0.01", FpToString(1e-2));
|
||||
EXPECT_EQ("0.001", FpToString(1e-3));
|
||||
EXPECT_EQ("0.0001", FpToString(1e-4));
|
||||
EXPECT_EQ("1e-05", FpToString(1e-5));
|
||||
EXPECT_EQ("1e-06", FpToString(1e-6));
|
||||
EXPECT_EQ("1e-07", FpToString(1e-7));
|
||||
EXPECT_EQ("1e-08", FpToString(1e-8));
|
||||
EXPECT_EQ("1e-09", FpToString(1e-9));
|
||||
|
||||
// changing precision has the same effect as std::stringstream
|
||||
EXPECT_EQ(convert_with_stringstream(123., 1), FpToString(123., 1));
|
||||
EXPECT_EQ(convert_with_stringstream(1234567., 7), FpToString(1234567., 7));
|
||||
EXPECT_EQ(convert_with_stringstream(12345.67, 7), FpToString(12345.67, 7));
|
||||
EXPECT_EQ(convert_with_stringstream(1234567e-9, 7), FpToString(1234567e-9, 7));
|
||||
EXPECT_EQ(convert_with_stringstream(1234567e-9, 1), FpToString(1234567e-9, 1));
|
||||
|
||||
// known example that is difficult to round
|
||||
EXPECT_EQ("1", FpToString(0.9999, 2));
|
||||
EXPECT_EQ("-1", FpToString(-0.9999, 2));
|
||||
|
||||
// some more random tests
|
||||
EXPECT_EQ("1.25", FpToString(1.25));
|
||||
EXPECT_EQ("34.34", FpToString(34.34));
|
||||
EXPECT_EQ("1e+20", FpToString(1e+20));
|
||||
EXPECT_EQ("1.1e+20", FpToString(1.1e+20));
|
||||
EXPECT_EQ("1e-20", FpToString(1e-20));
|
||||
EXPECT_EQ("1.1e-20", FpToString(1.1e-20));
|
||||
EXPECT_EQ("1e-20", FpToString(0.1e-19));
|
||||
EXPECT_EQ("1.1e-20", FpToString(0.11e-19));
|
||||
|
||||
EXPECT_EQ("19", FpToString(18.9, 2));
|
||||
EXPECT_EQ("20", FpToString(19.9, 2));
|
||||
EXPECT_EQ("2e+01", FpToString(19.9, 1));
|
||||
EXPECT_EQ("1.2e-05", FpToString(1.234e-5, 2));
|
||||
EXPECT_EQ("1.3e-05", FpToString(1.299e-5, 2));
|
||||
|
||||
EXPECT_EQ("-1", FpToString(-1.));
|
||||
EXPECT_EQ("-1.25", FpToString(-1.25));
|
||||
EXPECT_EQ("-34.34", FpToString(-34.34));
|
||||
EXPECT_EQ("-1e+20", FpToString(-1e+20));
|
||||
EXPECT_EQ("-1.1e+20", FpToString(-1.1e+20));
|
||||
EXPECT_EQ("-1e-20", FpToString(-1e-20));
|
||||
EXPECT_EQ("-1.1e-20", FpToString(-1.1e-20));
|
||||
EXPECT_EQ("-1e-20", FpToString(-0.1e-19));
|
||||
EXPECT_EQ("-1.1e-20", FpToString(-0.11e-19));
|
||||
|
||||
EXPECT_EQ("-19", FpToString(-18.9, 2));
|
||||
EXPECT_EQ("-20", FpToString(-19.9, 2));
|
||||
EXPECT_EQ("-2e+01", FpToString(-19.9, 1));
|
||||
EXPECT_EQ("-1.2e-05", FpToString(-1.234e-5, 2));
|
||||
EXPECT_EQ("-1.3e-05", FpToString(-1.299e-5, 2));
|
||||
}
|
||||
|
||||
TEST(FpToStringTest, conversion_float) {
|
||||
// Issue motivating FpToString function,
|
||||
// https://github.com/jbeder/yaml-cpp/issues/1289
|
||||
// Original problem at hand:
|
||||
EXPECT_EQ("34.34", FpToString(34.34f));
|
||||
EXPECT_EQ("56.56", FpToString(56.56f));
|
||||
EXPECT_EQ("12.12", FpToString(12.12f));
|
||||
EXPECT_EQ("78.78", FpToString(78.78f));
|
||||
|
||||
// prints the same way as std::stringstream
|
||||
EXPECT_EQ(convert_with_stringstream(1.f), FpToString(1.f));
|
||||
EXPECT_EQ(convert_with_stringstream(1e0f), FpToString(1e0f));
|
||||
EXPECT_EQ(convert_with_stringstream(1e1f), FpToString(1e1f));
|
||||
EXPECT_EQ(convert_with_stringstream(1e2f), FpToString(1e2f));
|
||||
EXPECT_EQ(convert_with_stringstream(1e3f), FpToString(1e3f));
|
||||
EXPECT_EQ(convert_with_stringstream(1e4f), FpToString(1e4f));
|
||||
EXPECT_EQ(convert_with_stringstream(1e5f), FpToString(1e5f));
|
||||
EXPECT_EQ(convert_with_stringstream(1e6f), FpToString(1e6f));
|
||||
EXPECT_EQ(convert_with_stringstream(1e7f), FpToString(1e7f));
|
||||
EXPECT_EQ(convert_with_stringstream(1e8f), FpToString(1e8f));
|
||||
EXPECT_EQ(convert_with_stringstream(1e9f), FpToString(1e9f));
|
||||
|
||||
// Print by default values below 1e6 without scientific notation
|
||||
EXPECT_EQ("1", FpToString(1.f));
|
||||
EXPECT_EQ("1", FpToString(1e0f));
|
||||
EXPECT_EQ("10", FpToString(1e1f));
|
||||
EXPECT_EQ("100", FpToString(1e2f));
|
||||
EXPECT_EQ("1000", FpToString(1e3f));
|
||||
EXPECT_EQ("10000", FpToString(1e4f));
|
||||
EXPECT_EQ("100000", FpToString(1e5f));
|
||||
EXPECT_EQ("1e+06", FpToString(1e6f));
|
||||
EXPECT_EQ("1e+07", FpToString(1e7f));
|
||||
EXPECT_EQ("1e+08", FpToString(1e8f));
|
||||
EXPECT_EQ("1e+09", FpToString(1e9f));
|
||||
|
||||
// prints the same way as std::stringstream
|
||||
EXPECT_EQ(convert_with_stringstream(1.f), FpToString(1.f));
|
||||
EXPECT_EQ(convert_with_stringstream(1e-0f), FpToString(1e-0f));
|
||||
EXPECT_EQ(convert_with_stringstream(1e-1f), FpToString(1e-1f));
|
||||
EXPECT_EQ(convert_with_stringstream(1e-2f), FpToString(1e-2f));
|
||||
EXPECT_EQ(convert_with_stringstream(1e-3f), FpToString(1e-3f));
|
||||
EXPECT_EQ(convert_with_stringstream(1e-4f), FpToString(1e-4f));
|
||||
EXPECT_EQ(convert_with_stringstream(1e-5f), FpToString(1e-5f));
|
||||
EXPECT_EQ(convert_with_stringstream(1e-6f), FpToString(1e-6f));
|
||||
EXPECT_EQ(convert_with_stringstream(1e-7f), FpToString(1e-7f));
|
||||
EXPECT_EQ(convert_with_stringstream(1e-8f), FpToString(1e-8f));
|
||||
EXPECT_EQ(convert_with_stringstream(1e-9f), FpToString(1e-9f));
|
||||
|
||||
// Print by default values above 1e-5 without scientific notation
|
||||
EXPECT_EQ("1", FpToString(1.f));
|
||||
EXPECT_EQ("1", FpToString(1e-0f));
|
||||
EXPECT_EQ("0.1", FpToString(1e-1f));
|
||||
EXPECT_EQ("0.01", FpToString(1e-2f));
|
||||
EXPECT_EQ("0.001", FpToString(1e-3f));
|
||||
EXPECT_EQ("0.0001", FpToString(1e-4f));
|
||||
EXPECT_EQ("1e-05", FpToString(1e-5f));
|
||||
EXPECT_EQ("1e-06", FpToString(1e-6f));
|
||||
EXPECT_EQ("1e-07", FpToString(1e-7f));
|
||||
EXPECT_EQ("1e-08", FpToString(1e-8f));
|
||||
EXPECT_EQ("1e-09", FpToString(1e-9f));
|
||||
|
||||
// changing precision has the same effect as std::stringstream
|
||||
EXPECT_EQ(convert_with_stringstream(123.f, 1), FpToString(123.f, 1));
|
||||
EXPECT_EQ(convert_with_stringstream(1234567.f, 7), FpToString(1234567.f, 7));
|
||||
EXPECT_EQ(convert_with_stringstream(12345.67f, 7), FpToString(12345.67f, 7));
|
||||
EXPECT_EQ(convert_with_stringstream(1234567e-9f, 7), FpToString(1234567e-9f, 7));
|
||||
EXPECT_EQ(convert_with_stringstream(1234567e-9f, 1), FpToString(1234567e-9f, 1));
|
||||
|
||||
// known example that is difficult to round
|
||||
EXPECT_EQ("1", FpToString(0.9999f, 2));
|
||||
EXPECT_EQ("-1", FpToString(-0.9999f, 2));
|
||||
|
||||
// some more random tests
|
||||
EXPECT_EQ("1.25", FpToString(1.25f));
|
||||
EXPECT_EQ("34.34", FpToString(34.34f));
|
||||
EXPECT_EQ("1e+20", FpToString(1e+20f));
|
||||
EXPECT_EQ("1.1e+20", FpToString(1.1e+20f));
|
||||
EXPECT_EQ("1e-20", FpToString(1e-20f));
|
||||
EXPECT_EQ("1.1e-20", FpToString(1.1e-20f));
|
||||
EXPECT_EQ("1e-20", FpToString(0.1e-19f));
|
||||
EXPECT_EQ("1.1e-20", FpToString(0.11e-19f));
|
||||
|
||||
EXPECT_EQ("19", FpToString(18.9f, 2));
|
||||
EXPECT_EQ("20", FpToString(19.9f, 2));
|
||||
EXPECT_EQ("2e+01", FpToString(19.9f, 1));
|
||||
EXPECT_EQ("1.2e-05", FpToString(1.234e-5f, 2));
|
||||
EXPECT_EQ("1.3e-05", FpToString(1.299e-5f, 2));
|
||||
|
||||
EXPECT_EQ("-1", FpToString(-1.f));
|
||||
EXPECT_EQ("-1.25", FpToString(-1.25f));
|
||||
EXPECT_EQ("-34.34", FpToString(-34.34f));
|
||||
EXPECT_EQ("-1e+20", FpToString(-1e+20f));
|
||||
EXPECT_EQ("-1.1e+20", FpToString(-1.1e+20f));
|
||||
EXPECT_EQ("-1e-20", FpToString(-1e-20f));
|
||||
EXPECT_EQ("-1.1e-20", FpToString(-1.1e-20f));
|
||||
EXPECT_EQ("-1e-20", FpToString(-0.1e-19f));
|
||||
EXPECT_EQ("-1.1e-20", FpToString(-0.11e-19f));
|
||||
|
||||
EXPECT_EQ("-19", FpToString(-18.9f, 2));
|
||||
EXPECT_EQ("-20", FpToString(-19.9f, 2));
|
||||
EXPECT_EQ("-2e+01", FpToString(-19.9f, 1));
|
||||
EXPECT_EQ("-1.2e-05", FpToString(-1.234e-5f, 2));
|
||||
EXPECT_EQ("-1.3e-05", FpToString(-1.299e-5f, 2));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace YAML
|
||||
14
test/integration/BUILD.bazel
Normal file
14
test/integration/BUILD.bazel
Normal file
@ -0,0 +1,14 @@
|
||||
cc_test(
|
||||
name = "test",
|
||||
srcs = glob([
|
||||
"*.cpp",
|
||||
"*.h",
|
||||
]),
|
||||
deps = [
|
||||
"//:yaml-cpp",
|
||||
"//:yaml-cpp_internal",
|
||||
"//test:mock_event_handler",
|
||||
"//test:specexamples",
|
||||
"@googletest//:gtest_main",
|
||||
],
|
||||
)
|
||||
@ -46,6 +46,26 @@ TEST_F(EmitterTest, SimpleScalar) {
|
||||
ExpectEmit("Hello, World!");
|
||||
}
|
||||
|
||||
TEST_F(EmitterTest, SimpleStdStringScalar) {
|
||||
out << std::string("Hello, std string");
|
||||
|
||||
ExpectEmit("Hello, std string");
|
||||
}
|
||||
|
||||
#if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || __cplusplus >= 201703L)
|
||||
TEST_F(EmitterTest, SimpleStdStringViewScalar) {
|
||||
out << std::string_view("Hello, std string view");
|
||||
|
||||
ExpectEmit("Hello, std string view");
|
||||
}
|
||||
|
||||
TEST_F(EmitterTest, UnterminatedStdStringViewScalar) {
|
||||
out << std::string_view("HelloUnterminated", 5);
|
||||
|
||||
ExpectEmit("Hello");
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST_F(EmitterTest, SimpleQuotedScalar) {
|
||||
Node n(Load("\"test\""));
|
||||
out << n;
|
||||
@ -104,9 +124,11 @@ TEST_F(EmitterTest, NumberPrecision) {
|
||||
out << 3.1425926f;
|
||||
out << 53.5893;
|
||||
out << 2384626.4338;
|
||||
out << 1999926.4338;
|
||||
out << 9999926.4338;
|
||||
out << EndSeq;
|
||||
|
||||
ExpectEmit("- 3.14\n- 54\n- 2.4e+06");
|
||||
ExpectEmit("- 3.14\n- 54\n- 2.4e+06\n- 2e+06\n- 1e+07");
|
||||
}
|
||||
|
||||
TEST_F(EmitterTest, SimpleSeq) {
|
||||
@ -176,6 +198,17 @@ TEST_F(EmitterTest, EmptyFlowSeqWithBegunContent) {
|
||||
]])");
|
||||
}
|
||||
|
||||
TEST_F(EmitterTest, EmptyFlowSeqInMap) {
|
||||
out << BeginMap;
|
||||
out << Key << Flow << BeginSeq << EndSeq;
|
||||
out << Value << 1;
|
||||
out << Key << 2;
|
||||
out << Value << Flow << BeginSeq << EndSeq;
|
||||
out << EndMap;
|
||||
|
||||
ExpectEmit("[]: 1\n2: []");
|
||||
}
|
||||
|
||||
TEST_F(EmitterTest, EmptyFlowMapWithBegunContent) {
|
||||
out << Flow;
|
||||
out << BeginSeq;
|
||||
@ -616,6 +649,17 @@ TEST_F(EmitterTest, LocalTagWithScalar) {
|
||||
ExpectEmit("!foo bar");
|
||||
}
|
||||
|
||||
TEST_F(EmitterTest, LocalTagRetainedAfterLoadingNode) {
|
||||
Node n = Node("hello");
|
||||
out << LocalTag("foo") << n;
|
||||
std::string expected = "!foo hello";
|
||||
ExpectEmit(expected);
|
||||
Node yamlNode = Load(out.c_str());
|
||||
Emitter emitter;
|
||||
emitter << yamlNode;
|
||||
EXPECT_EQ(expected, emitter.c_str());
|
||||
}
|
||||
|
||||
TEST_F(EmitterTest, ComplexDoc) {
|
||||
out << BeginMap;
|
||||
out << Key << "receipt";
|
||||
|
||||
@ -334,6 +334,77 @@ TEST(NodeTest, LoadQuotedNull) {
|
||||
EXPECT_EQ(node.as<std::string>(), "null");
|
||||
}
|
||||
|
||||
TEST(NodeTest, LoadNonClosedQuotedString) {
|
||||
EXPECT_THROW(Load(R"("foo)"), ParserException);
|
||||
}
|
||||
|
||||
TEST(NodeTest, LoadWrongQuotedString) {
|
||||
EXPECT_THROW(Load(R"("foo" [)"), ParserException);
|
||||
EXPECT_THROW(Load(R"("foo", [)"), ParserException);
|
||||
}
|
||||
|
||||
TEST(NodeTest, LoadUnquotedQuotedStrings) {
|
||||
Node node = Load(R"(foo,"bar")");
|
||||
EXPECT_EQ(node.as<std::string>(), "foo,\"bar\"");
|
||||
|
||||
node = Load(R"(foo,bar)");
|
||||
EXPECT_EQ(node.as<std::string>(), "foo,bar");
|
||||
|
||||
node = Load(R"(foo,)");
|
||||
EXPECT_EQ(node.as<std::string>(), "foo,");
|
||||
|
||||
node = Load(R"(foo "bar")");
|
||||
EXPECT_EQ(node.as<std::string>(), "foo \"bar\"");
|
||||
}
|
||||
|
||||
TEST(NodeTest, LoadCommaSeparatedStrings) {
|
||||
EXPECT_THROW(Load(R"("foo","bar")"), ParserException);
|
||||
EXPECT_THROW(Load(R"("foo",bar)"), ParserException);
|
||||
EXPECT_THROW(Load(R"(,)"), ParserException);
|
||||
EXPECT_THROW(Load(R"("foo",)"), ParserException);
|
||||
EXPECT_THROW(Load(R"("foo","")"), ParserException);
|
||||
EXPECT_THROW(Load(R"("foo",)"), ParserException);
|
||||
EXPECT_THROW(Load(R"(,"foo")"), ParserException);
|
||||
EXPECT_THROW(Load(R"(,foo)"), ParserException);
|
||||
}
|
||||
|
||||
TEST(NodeSpecTest, InfiniteLoopNodes) {
|
||||
// Until yaml-cpp <= 0.8.0 this caused an infinite loop;
|
||||
// After, it triggers an exception (but LoadAll is smart enough to avoid
|
||||
// the infinite loop in any case).
|
||||
EXPECT_THROW(LoadAll(R"(,)"), ParserException);
|
||||
}
|
||||
|
||||
struct NewLineStringsTestCase {
|
||||
std::string input;
|
||||
std::string expected_content;
|
||||
bool should_throw;
|
||||
};
|
||||
TEST(NodeTest, LoadNewLineStrings) {
|
||||
std::vector<NewLineStringsTestCase> tests = {
|
||||
{"foo\n, bar", "foo , bar", false},
|
||||
{"foo\n, \"bar\"", "foo , \"bar\"", false},
|
||||
{"\"foo\"\n, \"bar\"", "", true},
|
||||
{"\"foo\"\n, bar", "", true},
|
||||
};
|
||||
for (const NewLineStringsTestCase& test : tests) {
|
||||
if (test.should_throw) {
|
||||
EXPECT_THROW(Load(test.input), ParserException);
|
||||
} else {
|
||||
Node node = Load(test.input);
|
||||
Emitter emitter;
|
||||
emitter << node;
|
||||
EXPECT_EQ(NodeType::Scalar, node.Type());
|
||||
EXPECT_EQ(test.expected_content, std::string(emitter.c_str()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST(NodeTest, LoadSameLineStrings) {
|
||||
EXPECT_THROW(Load(R"("foo" "bar")"), ParserException);
|
||||
EXPECT_THROW(Load(R"("foo" bar)"), ParserException);
|
||||
}
|
||||
|
||||
TEST(NodeTest, LoadTagWithParenthesis) {
|
||||
Node node = Load("!Complex(Tag) foo");
|
||||
EXPECT_EQ(node.Tag(), "!Complex(Tag)");
|
||||
@ -360,5 +431,21 @@ TEST(LoadNodeTest, BlockCRNLEncoded) {
|
||||
EXPECT_EQ(1, node["followup"].as<int>());
|
||||
}
|
||||
|
||||
TEST(LoadNodeTest, BlockCREncoded) {
|
||||
Node node = Load(
|
||||
"blockText: |\r"
|
||||
" some arbitrary text \r"
|
||||
" spanning some \r"
|
||||
" lines, that are split \r"
|
||||
" by CR and NL\r"
|
||||
"followup: 1");
|
||||
EXPECT_EQ(
|
||||
"some arbitrary text \nspanning some \nlines, that are split \nby CR and "
|
||||
"NL\n",
|
||||
node["blockText"].as<std::string>());
|
||||
EXPECT_EQ(1, node["followup"].as<int>());
|
||||
}
|
||||
|
||||
|
||||
} // namespace
|
||||
} // namespace YAML
|
||||
|
||||
@ -191,6 +191,14 @@ TEST(NodeTest, MapElementRemoval) {
|
||||
EXPECT_TRUE(!node["foo"]);
|
||||
}
|
||||
|
||||
TEST(NodeTest, MissingKey) {
|
||||
Node node;
|
||||
node["foo"] = "value";
|
||||
EXPECT_TRUE(!node["bar"]);
|
||||
EXPECT_EQ(NodeType::Undefined, node["bar"].Type());
|
||||
EXPECT_THROW(node["bar"].as<std::string>(), InvalidNode);
|
||||
}
|
||||
|
||||
TEST(NodeTest, MapIntegerElementRemoval) {
|
||||
Node node;
|
||||
node[1] = "hello";
|
||||
@ -749,8 +757,15 @@ TEST_F(NodeEmitterTest, SimpleFlowSeqNode) {
|
||||
node.push_back(1.5);
|
||||
node.push_back(2.25);
|
||||
node.push_back(3.125);
|
||||
node.push_back(34.34);
|
||||
node.push_back(56.56);
|
||||
node.push_back(12.12);
|
||||
node.push_back(78.78);
|
||||
node.push_back(0.0003);
|
||||
node.push_back(4000.);
|
||||
node.push_back(1.5474251e+26f);
|
||||
|
||||
ExpectOutput("[1.5, 2.25, 3.125]", node);
|
||||
ExpectOutput("[1.5, 2.25, 3.125, 34.34, 56.56, 12.12, 78.78, 0.0003, 4000, 1.5474251e+26]", node);
|
||||
}
|
||||
|
||||
TEST_F(NodeEmitterTest, NestFlowSeqNode) {
|
||||
@ -849,5 +864,17 @@ TEST_F(NodeEmitterTest, NestFlowMapListNode) {
|
||||
|
||||
ExpectOutput("{position: [1.5, 2.25, 3.125]}", mapNode);
|
||||
}
|
||||
|
||||
TEST_F(NodeEmitterTest, RobustAgainstLocale) {
|
||||
std::locale::global(std::locale(""));
|
||||
Node node;
|
||||
node.push_back(1.5);
|
||||
node.push_back(2.25);
|
||||
node.push_back(3.125);
|
||||
node.push_back(123456789);
|
||||
|
||||
ExpectOutput("- 1.5\n- 2.25\n- 3.125\n- 123456789", node);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -20,10 +20,10 @@ class NullEventHandler : public YAML::EventHandler {
|
||||
void OnScalar(const Mark&, const std::string&, anchor_t,
|
||||
const std::string&) override {}
|
||||
void OnSequenceStart(const Mark&, const std::string&, anchor_t,
|
||||
YAML::EmitterStyle::value style) override {}
|
||||
YAML::EmitterStyle::value) override {}
|
||||
void OnSequenceEnd() override {}
|
||||
void OnMapStart(const Mark&, const std::string&, anchor_t,
|
||||
YAML::EmitterStyle::value style) override {}
|
||||
YAML::EmitterStyle::value) override {}
|
||||
void OnMapEnd() override {}
|
||||
};
|
||||
|
||||
|
||||
@ -18,10 +18,10 @@ class NullEventHandler : public YAML::EventHandler {
|
||||
void OnScalar(const Mark&, const std::string&, anchor_t,
|
||||
const std::string&) override {}
|
||||
void OnSequenceStart(const Mark&, const std::string&, anchor_t,
|
||||
YAML::EmitterStyle::value style) override {}
|
||||
YAML::EmitterStyle::value) override {}
|
||||
void OnSequenceEnd() override {}
|
||||
void OnMapStart(const Mark&, const std::string&, anchor_t,
|
||||
YAML::EmitterStyle::value style) override {}
|
||||
YAML::EmitterStyle::value) override {}
|
||||
void OnMapEnd() override {}
|
||||
};
|
||||
|
||||
|
||||
@ -11,12 +11,23 @@ set_and_check(YAML_CPP_INCLUDE_DIR "@PACKAGE_CMAKE_INSTALL_INCLUDEDIR@")
|
||||
set_and_check(YAML_CPP_LIBRARY_DIR "@PACKAGE_CMAKE_INSTALL_LIBDIR@")
|
||||
|
||||
# Are we building shared libraries?
|
||||
set(YAML_CPP_SHARED_LIBS_BUILT "@PACKAGE_YAML_BUILD_SHARED_LIBS@")
|
||||
set(YAML_CPP_SHARED_LIBS_BUILT @YAML_BUILD_SHARED_LIBS@)
|
||||
|
||||
# Our library dependencies (contains definitions for IMPORTED targets)
|
||||
include(@PACKAGE_CONFIG_EXPORT_DIR@/yaml-cpp-targets.cmake)
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/yaml-cpp-targets.cmake")
|
||||
|
||||
# These are IMPORTED targets created by yaml-cpp-targets.cmake
|
||||
set(YAML_CPP_LIBRARIES "@EXPORT_TARGETS@")
|
||||
|
||||
check_required_components(@EXPORT_TARGETS@)
|
||||
# Protect against multiple inclusion, which would fail when already imported targets are added once more.
|
||||
if(NOT TARGET yaml-cpp)
|
||||
add_library(yaml-cpp INTERFACE IMPORTED)
|
||||
target_link_libraries(yaml-cpp INTERFACE yaml-cpp::yaml-cpp)
|
||||
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.17)
|
||||
set_target_properties(yaml-cpp PROPERTIES
|
||||
DEPRECATION "The target yaml-cpp is deprecated and will be removed in version 0.10.0. Use the yaml-cpp::yaml-cpp target instead."
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
check_required_components(yaml-cpp)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user