Compare commits

..
3 Commits
Author SHA1 Message Date
Jesse Beder 1bcc5e2390 Switch build command to use cmake instead of make.
This allows it to be cross-platform.
2019-03-24 18:27:01 -05:00
Jesse Beder 8f3b8dffb0 Change language from c++ to cpp. 2019-03-24 18:06:06 -05:00
Jesse Beder 7710ef360b Add windows to travis build. 2019-03-24 17:57:10 -05:00
564 changed files with 117281 additions and 83928 deletions
-1
View File
@@ -1 +0,0 @@
test/googletest-1.16.0
+1 -1
View File
@@ -8,7 +8,7 @@ EXAMPLE_PATH =
# One or more directories and files to exclude from documentation generation.
# Use relative paths with respect to the repository root directory.
EXCLUDE = test/googletest-1.16.0/
EXCLUDE = test/gtest-1.8.0/
# One or more wildcard patterns to exclude files and directories from document
# generation.
-25
View File
@@ -1,25 +0,0 @@
name: Quick CMake config
description: "Runs CMake 3.14+ (if already setup)"
inputs:
args:
description: "Other arguments"
required: false
default: ""
cmake-version:
description: "The CMake version to run"
required: true
runs:
using: composite
steps:
- name: CMake ${{ inputs.cmake-version }}
uses: jwlawson/actions-setup-cmake@v2.2
with:
cmake-version: "${{ inputs.cmake-version }}"
- run: |
mkdir -p build-tmp
touch build-tmp/tmp
rm -r build-tmp/*
(cd build-tmp && cmake .. ${{ inputs.args }})
rm -r build-tmp
shell: bash
-11
View File
@@ -1,11 +0,0 @@
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "monthly"
groups:
github-actions:
patterns:
- "*"
-161
View File
@@ -1,161 +0,0 @@
name: Github PR
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
workflow_dispatch:
permissions: read-all
defaults:
run:
shell: bash
jobs:
cmake-build:
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macos-latest, windows-11-arm]
cxx_standard: [11, 20, 23]
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
- os: windows-11-arm
googletest: system
env:
YAML_BUILD_SHARED_LIBS: ${{ matrix.build == 'shared' && 'ON' || 'OFF' }}
YAML_USE_SYSTEM_GTEST: ${{ matrix.googletest == 'system' && 'ON' || 'OFF' }}
CMAKE_GENERATOR: >-
${{format(matrix.generator != 'Default Generator' && '-G "{0}"' || '', matrix.generator)}}
CMAKE_INSTALL_PREFIX: "${{ github.workspace }}/install-prefix"
CMAKE_BUILD_TYPE: Debug
CMAKE_CXX_FLAGS_DEBUG: ${{ matrix.googletest == 'build' && '-g -D_GLIBCXX_DEBUG -D_GLIBCXX_DEBUG_PEDANTIC' || '-g' }}
runs-on: ${{ matrix.os }}
steps:
- uses: awalsh128/cache-apt-pkgs-action@latest
if: matrix.os == 'ubuntu-latest'
with:
packages: googletest libgmock-dev libgtest-dev
version: 1.0
- uses: actions/checkout@v7
- name: Configure
run: |
cmake \
${{ env.CMAKE_GENERATOR }} \
-S "${{ github.workspace }}" \
-B build \
-D CMAKE_CXX_STANDARD=${{ matrix.cxx_standard }} \
-D CMAKE_INSTALL_PREFIX="${{ env.CMAKE_INSTALL_PREFIX }}" \
-D CMAKE_BUILD_TYPE=${{ env.CMAKE_BUILD_TYPE }} \
-D CMAKE_CXX_FLAGS_DEBUG="${{ env.CMAKE_CXX_FLAGS_DEBUG }}" \
-D YAML_BUILD_SHARED_LIBS=${{ env.YAML_BUILD_SHARED_LIBS }} \
-D YAML_USE_SYSTEM_GTEST=${{ env.YAML_USE_SYSTEM_GTEST }} \
-D YAML_CPP_BUILD_TESTS=ON
- name: Build
run: |
cmake \
--build build \
--config ${{ env.CMAKE_BUILD_TYPE }} \
--verbose \
--parallel
- name: Run Tests
shell: bash
run: |
ctest \
--test-dir build \
--build-config ${{ env.CMAKE_BUILD_TYPE }} \
--output-on-failure \
--verbose
- name: Install
run: cmake --install build --config ${{ env.CMAKE_BUILD_TYPE }}
- name: Configure CMake package test
run: |
cmake \
${{ env.CMAKE_GENERATOR }} \
-S "${{ github.workspace }}/test/cmake" \
-B consumer-build \
-D CMAKE_BUILD_TYPE=${{ env.CMAKE_BUILD_TYPE }} \
-D CMAKE_PREFIX_PATH="${{ env.CMAKE_INSTALL_PREFIX }}"
- name: Build CMake package test
run: |
cmake \
--build consumer-build \
--config ${{ env.CMAKE_BUILD_TYPE }} \
--verbose
cmake-config-oldest-cmake:
name: CMake version range config check (Ubuntu 24.04)
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v7
- name: Check CMake 3.15
uses: ./.github/actions/quick_cmake
with:
cmake-version: "3.15"
if: success() || failure()
- name: Check CMake 4.3
uses: ./.github/actions/quick_cmake
with:
cmake-version: "4.3"
if: success() || failure()
bazel-build:
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest, windows-11-arm]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v7
- name: Build
run: |
cd "${{ github.workspace }}"
bazel build :all
- name: Test
run: |
cd "${{ github.workspace }}"
bazel test test
bzlmod-build:
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest, windows-11-arm]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v7
- 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
View File
@@ -1,19 +0,0 @@
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@v7
- 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
View File
@@ -1,3 +1,2 @@
build/
/tags
/bazel-*
+28
View File
@@ -0,0 +1,28 @@
language: cpp
before_install:
- |
if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then
sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y \
&& sudo apt-get update -qq \
&& if [ "$CXX" == "g++" ]; then
sudo apt-get install -qq g++-4.7 && export CXX="g++-4.7" CC="gcc-4.7"
fi
fi
before_script:
- mkdir build
- cd build
- cmake ..
script:
- cmake --build .
- test/run-tests
matrix:
include:
- os: linux
compiler: gcc
- os: osx
compiler: clang
- os: osx
compiler: gcc
- os: windows
compiler: clang
-32
View File
@@ -1,32 +0,0 @@
load("@rules_cc//cc:defs.bzl", "cc_library")
yaml_cpp_defines = select({
# On Windows, ensure static linking is used.
"@platforms//os:windows": ["YAML_CPP_STATIC_DEFINE", "YAML_CPP_NO_CONTRIB"],
"//conditions:default": [],
})
yaml_copts = select({
"@platforms//os:windows": [],
"//conditions:default": [
"-fexceptions",
],
})
cc_library(
name = "yaml-cpp_internal",
visibility = ["//:__subpackages__"],
strip_include_prefix = "src",
hdrs = glob(["src/**/*.h"]),
copts = yaml_copts,
)
cc_library(
name = "yaml-cpp",
visibility = ["//visibility:public"],
includes = ["include"],
hdrs = glob(["include/**/*.h"]),
srcs = glob(["src/**/*.cpp", "src/**/*.h"]),
defines = yaml_cpp_defines,
copts = yaml_copts,
)
+327 -156
View File
@@ -1,193 +1,364 @@
cmake_minimum_required(VERSION 3.15..4.3)
###
### CMake settings
###
# see http://www.cmake.org/Wiki/CMake_Policies
cmake_minimum_required(VERSION 3.1)
project(YAML_CPP VERSION 0.9.0 LANGUAGES CXX)
set(YAML_CPP_MAIN_PROJECT OFF)
if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
set(YAML_CPP_MAIN_PROJECT ON)
endif()
include(CMakePackageConfigHelpers)
include(CMakeDependentOption)
include(CheckCXXCompilerFlag)
include(GNUInstallDirs)
include(CTest)
option(YAML_CPP_BUILD_CONTRIB "Enable yaml-cpp contrib in library" ON)
###
### Project settings
###
project(YAML_CPP)
set(YAML_CPP_VERSION_MAJOR "0")
set(YAML_CPP_VERSION_MINOR "6")
set(YAML_CPP_VERSION_PATCH "2")
set(YAML_CPP_VERSION "${YAML_CPP_VERSION_MAJOR}.${YAML_CPP_VERSION_MINOR}.${YAML_CPP_VERSION_PATCH}")
###
### Project options
###
## Project stuff
option(YAML_CPP_BUILD_TESTS "Enable testing" ON)
option(YAML_CPP_BUILD_TOOLS "Enable parse tools" ON)
option(YAML_BUILD_SHARED_LIBS "Build yaml-cpp shared library" ${BUILD_SHARED_LIBS})
option(YAML_CPP_INSTALL "Enable generation of yaml-cpp install targets" ${YAML_CPP_MAIN_PROJECT})
option(YAML_CPP_FORMAT_SOURCE "Format source" ${YAML_CPP_MAIN_PROJECT})
option(YAML_CPP_DISABLE_UNINSTALL "Disable uninstallation of yaml-cpp" OFF)
option(YAML_USE_SYSTEM_GTEST "Use system googletest if found" OFF)
option(YAML_ENABLE_PIC "Use Position-Independent Code " ON)
option(YAML_CPP_USE_STRICT_FLAGS "Uses strict compilation flags e.g.: -Wall" ${YAML_CPP_MAIN_PROJECT})
option(YAML_CPP_BUILD_CONTRIB "Enable contrib stuff in library" ON)
option(YAML_CPP_INSTALL "Enable generation of install target" 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)
endif()
## Build options
# --> General
# see http://www.cmake.org/cmake/help/cmake2.6docs.html#variable:BUILD_SHARED_LIBS
# http://www.cmake.org/cmake/help/cmake2.6docs.html#command:add_library
option(BUILD_SHARED_LIBS "Build Shared Libraries" OFF)
if (YAML_BUILD_SHARED_LIBS)
set(yaml-cpp-type SHARED)
set(yaml-cpp-label-postfix "shared")
# Set minimum C++ to 2011 standards
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# --> Apple
option(APPLE_UNIVERSAL_BIN "Apple: Build universal binary" OFF)
# --> Microsoft Visual C++
# see http://msdn.microsoft.com/en-us/library/aa278396(v=VS.60).aspx
# http://msdn.microsoft.com/en-us/library/2kzt1wy3(v=VS.71).aspx
option(MSVC_SHARED_RT "MSVC: Build with shared runtime libs (/MD)" ON)
option(MSVC_STHREADED_RT "MSVC: Build with single-threaded static runtime libs (/ML until VS .NET 2003)" OFF)
###
### Sources, headers, directories and libs
###
# From http://www.cmake.org/pipermail/cmake/2010-March/035992.html:
# function to collect all the sources from sub-directories
# into a single list
function(add_sources)
get_property(is_defined GLOBAL PROPERTY SRCS_LIST DEFINED)
if(NOT is_defined)
define_property(GLOBAL PROPERTY SRCS_LIST
BRIEF_DOCS "List of source files"
FULL_DOCS "List of all source files in the entire project")
endif()
# make absolute paths
set(SRCS)
foreach(s IN LISTS ARGN)
if(NOT IS_ABSOLUTE "${s}")
get_filename_component(s "${s}" ABSOLUTE)
endif()
list(APPEND SRCS "${s}")
endforeach()
# append to global list
set_property(GLOBAL APPEND PROPERTY SRCS_LIST "${SRCS}")
endfunction(add_sources)
set(header_directory "include/yaml-cpp/")
file(GLOB sources "src/[a-zA-Z]*.cpp")
file(GLOB_RECURSE public_headers "include/yaml-cpp/[a-zA-Z]*.h")
file(GLOB private_headers "src/[a-zA-Z]*.h")
if(YAML_CPP_BUILD_CONTRIB)
file(GLOB contrib_sources "src/contrib/[a-zA-Z]*.cpp")
file(GLOB contrib_public_headers "include/yaml-cpp/contrib/[a-zA-Z]*.h")
file(GLOB contrib_private_headers "src/contrib/[a-zA-Z]*.h")
else()
set(yaml-cpp-type STATIC)
set(yaml-cpp-label-postfix "static")
add_definitions(-DYAML_CPP_NO_CONTRIB)
endif()
set(build-shared $<BOOL:${YAML_BUILD_SHARED_LIBS}>)
set(build-windows-dll $<AND:$<BOOL:${CMAKE_HOST_WIN32}>,${build-shared}>)
set(msvc-shared_rt $<BOOL:${YAML_MSVC_SHARED_RT}>)
set(library_sources
${sources}
${public_headers}
${private_headers}
${contrib_sources}
${contrib_public_headers}
${contrib_private_headers}
)
add_sources(${library_sources})
set(print-warnings $<NOT:$<OR:$<CXX_COMPILER_ID:MSVC>,$<CXX_COMPILER_ID:NVHPC>>>)
if (NOT DEFINED CMAKE_MSVC_RUNTIME_LIBRARY)
set(CMAKE_MSVC_RUNTIME_LIBRARY
MultiThreaded$<$<CONFIG:Debug>:Debug>$<${msvc-shared_rt}:DLL>)
if(VERBOSE)
message(STATUS "sources: ${sources}")
message(STATUS "public_headers: ${public_headers}")
message(STATUS "private_headers: ${private_headers}")
message(STATUS "contrib_sources: ${contrib_sources}")
message(STATUS "contrib_public_headers: ${contrib_public_headers}")
message(STATUS "contrib_private_headers: ${contrib_private_headers}")
endif()
file(GLOB yaml-cpp-contrib-sources CONFIGURE_DEPENDS "src/contrib/*.cpp")
file(GLOB yaml-cpp-sources CONFIGURE_DEPENDS "src/*.cpp")
set(msvc-rt $<TARGET_PROPERTY:MSVC_RUNTIME_LIBRARY>)
set(msvc-rt-mtd-static $<STREQUAL:${msvc-rt},MultiThreadedDebug>)
set(msvc-rt-mt-static $<STREQUAL:${msvc-rt},MultiThreaded>)
set(msvc-rt-mtd-dll $<STREQUAL:${msvc-rt},MultiThreadedDebugDLL>)
set(msvc-rt-mt-dll $<STREQUAL:${msvc-rt},MultiThreadedDLL>)
add_library(yaml-cpp ${yaml-cpp-type} "")
add_library(yaml-cpp::yaml-cpp ALIAS yaml-cpp)
set_property(TARGET yaml-cpp
PROPERTY
MSVC_RUNTIME_LIBRARY ${CMAKE_MSVC_RUNTIME_LIBRARY})
set_property(TARGET yaml-cpp
PROPERTY
CXX_STANDARD_REQUIRED ON)
if (NOT YAML_BUILD_SHARED_LIBS)
set_property(TARGET yaml-cpp PROPERTY POSITION_INDEPENDENT_CODE ${YAML_ENABLE_PIC})
if (CMAKE_VERSION VERSION_LESS 2.8.12)
include_directories(${YAML_CPP_SOURCE_DIR}/src)
include_directories(${YAML_CPP_SOURCE_DIR}/include)
endif()
target_include_directories(yaml-cpp
PUBLIC
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
PRIVATE
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/src>)
if (NOT DEFINED CMAKE_CXX_STANDARD)
set_target_properties(yaml-cpp
PROPERTIES
CXX_STANDARD 11)
###
### General compilation settings
###
set(yaml_c_flags ${CMAKE_C_FLAGS})
set(yaml_cxx_flags ${CMAKE_CXX_FLAGS})
if(BUILD_SHARED_LIBS)
set(LABEL_SUFFIX "shared")
else()
set(LABEL_SUFFIX "static")
endif()
if (YAML_CPP_USE_STRICT_FLAGS)
target_compile_options(yaml-cpp
PRIVATE
$<${print-warnings}:-Wall -Wextra -Wshadow -Weffc++ -Wno-long-long>
$<${print-warnings}:-pedantic -pedantic-errors>)
if(APPLE)
if(APPLE_UNIVERSAL_BIN)
set(CMAKE_OSX_ARCHITECTURES ppc;i386)
endif()
endif()
target_compile_options(yaml-cpp
PRIVATE
# /wd4127 = disable warning C4127 "conditional expression is constant"
# http://msdn.microsoft.com/en-us/library/6t66728h.aspx
# /wd4355 = disable warning C4355 "'this' : used in base member initializer list
# http://msdn.microsoft.com/en-us/library/3c594ae3.aspx
$<$<CXX_COMPILER_ID:MSVC>:/W3 /wd4127 /wd4355>)
if(IPHONE)
set(CMAKE_OSX_SYSROOT "iphoneos4.2")
set(CMAKE_OSX_ARCHITECTURES "armv6;armv7")
endif()
target_compile_definitions(yaml-cpp
PUBLIC
$<$<NOT:$<BOOL:${YAML_BUILD_SHARED_LIBS}>>:YAML_CPP_STATIC_DEFINE>
PRIVATE
$<${build-windows-dll}:${PROJECT_NAME}_DLL>
$<$<NOT:$<BOOL:${YAML_CPP_BUILD_CONTRIB}>>:YAML_CPP_NO_CONTRIB>)
if(WIN32)
if(BUILD_SHARED_LIBS)
add_definitions(-D${PROJECT_NAME}_DLL) # use or build Windows DLL
endif()
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
set(CMAKE_INSTALL_PREFIX "C:/")
endif()
endif()
target_sources(yaml-cpp
PRIVATE
$<$<BOOL:${YAML_CPP_BUILD_CONTRIB}>:${yaml-cpp-contrib-sources}>
${yaml-cpp-sources})
# GCC or Clang or Intel Compiler specialities
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU" OR
(CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND NOT "x${CMAKE_CXX_SIMULATE_ID}" STREQUAL "xMSVC") OR
CMAKE_CXX_COMPILER_ID MATCHES "Intel")
if (NOT DEFINED CMAKE_DEBUG_POSTFIX)
set(CMAKE_DEBUG_POSTFIX "d")
### General stuff
if(WIN32)
set(CMAKE_SHARED_LIBRARY_PREFIX "") # DLLs do not have a "lib" prefix
set(CMAKE_IMPORT_LIBRARY_PREFIX "") # same for DLL import libs
set(CMAKE_LINK_DEF_FILE_FLAG "") # CMake workaround (2.8.3)
endif()
### Project stuff
if(NOT CMAKE_CONFIGURATION_TYPES AND NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Release)
endif()
#
set(GCC_EXTRA_OPTIONS "")
#
if(BUILD_SHARED_LIBS)
set(GCC_EXTRA_OPTIONS "${GCC_EXTRA_OPTIONS} -fPIC")
endif()
#
set(FLAG_TESTED "-Wextra -Wshadow -Weffc++ -pedantic -pedantic-errors")
check_cxx_compiler_flag(${FLAG_TESTED} FLAG_WEXTRA)
if(FLAG_WEXTRA)
set(GCC_EXTRA_OPTIONS "${GCC_EXTRA_OPTIONS} ${FLAG_TESTED}")
endif()
#
set(yaml_cxx_flags "-Wall ${GCC_EXTRA_OPTIONS} -pedantic -Wno-long-long ${yaml_cxx_flags}")
### Make specific
if(${CMAKE_BUILD_TOOL} MATCHES make OR ${CMAKE_BUILD_TOOL} MATCHES gmake)
add_custom_target(debuggable ${CMAKE_MAKE_PROGRAM} clean
COMMAND ${CMAKE_COMMAND} -DCMAKE_BUILD_TYPE=Debug ${CMAKE_SOURCE_DIR}
COMMENT "Adjusting settings for debug compilation"
VERBATIM)
add_custom_target(releasable ${CMAKE_MAKE_PROGRAM} clean
COMMAND ${CMAKE_COMMAND} -DCMAKE_BUILD_TYPE=Release ${CMAKE_SOURCE_DIR}
COMMENT "Adjusting settings for release compilation"
VERBATIM)
endif()
endif()
# Microsoft VisualC++ specialities
if(MSVC)
### General stuff
# a) Change MSVC runtime library settings (/MD[d], /MT[d], /ML[d] (single-threaded until VS 2003))
# plus set lib suffix for later use and project label accordingly
# see http://msdn.microsoft.com/en-us/library/aa278396(v=VS.60).aspx
# http://msdn.microsoft.com/en-us/library/2kzt1wy3(v=VS.71).aspx
set(LIB_RT_SUFFIX "md") # CMake defaults to /MD for MSVC
set(LIB_RT_OPTION "/MD")
#
if(NOT MSVC_SHARED_RT) # User wants to have static runtime libraries (/MT, /ML)
if(MSVC_STHREADED_RT) # User wants to have old single-threaded static runtime libraries
set(LIB_RT_SUFFIX "ml")
set(LIB_RT_OPTION "/ML")
if(NOT ${MSVC_VERSION} LESS 1400)
message(FATAL_ERROR "Single-threaded static runtime libraries (/ML) only available until VS .NET 2003 (7.1).")
endif()
else()
set(LIB_RT_SUFFIX "mt")
set(LIB_RT_OPTION "/MT")
endif()
# correct linker options
foreach(flag_var CMAKE_C_FLAGS CMAKE_CXX_FLAGS)
foreach(config_name "" DEBUG RELEASE MINSIZEREL RELWITHDEBINFO)
set(var_name "${flag_var}")
if(NOT "${config_name}" STREQUAL "")
set(var_name "${var_name}_${config_name}")
endif()
string(REPLACE "/MD" "${LIB_RT_OPTION}" ${var_name} "${${var_name}}")
set(${var_name} "${${var_name}}" CACHE STRING "" FORCE)
endforeach()
endforeach()
endif()
#
set(LABEL_SUFFIX "${LABEL_SUFFIX} ${LIB_RT_SUFFIX}")
# b) Change prefix for static libraries
set(CMAKE_STATIC_LIBRARY_PREFIX "lib") # to distinguish static libraries from DLL import libs
# c) Correct suffixes for static libraries
if(NOT BUILD_SHARED_LIBS)
### General stuff
set(LIB_TARGET_SUFFIX "${LIB_SUFFIX}${LIB_RT_SUFFIX}")
endif()
### Project stuff
# /W3 = set warning level; see http://msdn.microsoft.com/en-us/library/thxezb7y.aspx
# /wd4127 = disable warning C4127 "conditional expression is constant"; see http://msdn.microsoft.com/en-us/library/6t66728h.aspx
# /wd4355 = disable warning C4355 "'this' : used in base member initializer list"; http://msdn.microsoft.com/en-us/library/3c594ae3.aspx
set(yaml_cxx_flags "/W3 /wd4127 /wd4355 ${yaml_cxx_flags}")
endif()
###
### General install settings
###
set(INCLUDE_INSTALL_ROOT_DIR include)
set(INCLUDE_INSTALL_DIR ${INCLUDE_INSTALL_ROOT_DIR}/yaml-cpp)
set(LIB_INSTALL_DIR "lib${LIB_SUFFIX}")
set(_INSTALL_DESTINATIONS
RUNTIME DESTINATION bin
LIBRARY DESTINATION ${LIB_INSTALL_DIR}
ARCHIVE DESTINATION ${LIB_INSTALL_DIR}
)
###
### Library
###
add_library(yaml-cpp ${library_sources})
if (NOT CMAKE_VERSION VERSION_LESS 2.8.12)
target_include_directories(yaml-cpp
PUBLIC $<BUILD_INTERFACE:${YAML_CPP_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:${INCLUDE_INSTALL_ROOT_DIR}>
PRIVATE $<BUILD_INTERFACE:${YAML_CPP_SOURCE_DIR}/src>)
endif()
set_target_properties(yaml-cpp PROPERTIES
VERSION "${PROJECT_VERSION}"
SOVERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}"
PROJECT_LABEL "yaml-cpp ${yaml-cpp-label-postfix}"
DEBUG_POSTFIX "${CMAKE_DEBUG_POSTFIX}")
COMPILE_FLAGS "${yaml_c_flags} ${yaml_cxx_flags}"
)
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 "${YAML_CPP_INSTALL_CMAKEDIR}"
PATH_VARS CMAKE_INSTALL_INCLUDEDIR CMAKE_INSTALL_LIBDIR)
unset(EXPORT_TARGETS)
set_target_properties(yaml-cpp PROPERTIES
VERSION "${YAML_CPP_VERSION}"
SOVERSION "${YAML_CPP_VERSION_MAJOR}.${YAML_CPP_VERSION_MINOR}"
PROJECT_LABEL "yaml-cpp ${LABEL_SUFFIX}"
)
write_basic_package_version_file(
"${PROJECT_BINARY_DIR}/yaml-cpp-config-version.cmake"
COMPATIBILITY AnyNewerVersion)
if(IPHONE)
set_target_properties(yaml-cpp PROPERTIES
XCODE_ATTRIBUTE_IPHONEOS_DEPLOYMENT_TARGET "3.0"
)
endif()
configure_file(yaml-cpp.pc.in yaml-cpp.pc @ONLY)
if(MSVC)
if(NOT BUILD_SHARED_LIBS)
# correct library names
set_target_properties(yaml-cpp PROPERTIES
DEBUG_POSTFIX "${LIB_TARGET_SUFFIX}d"
RELEASE_POSTFIX "${LIB_TARGET_SUFFIX}"
MINSIZEREL_POSTFIX "${LIB_TARGET_SUFFIX}"
RELWITHDEBINFO_POSTFIX "${LIB_TARGET_SUFFIX}"
)
endif()
endif()
if (YAML_CPP_INSTALL)
install(TARGETS yaml-cpp
EXPORT yaml-cpp-targets
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
install(DIRECTORY ${PROJECT_SOURCE_DIR}/include/
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
FILES_MATCHING PATTERN "*.h")
install(EXPORT yaml-cpp-targets
NAMESPACE yaml-cpp::
DESTINATION "${YAML_CPP_INSTALL_CMAKEDIR}")
install(FILES
"${PROJECT_BINARY_DIR}/yaml-cpp-config.cmake"
"${PROJECT_BINARY_DIR}/yaml-cpp-config-version.cmake"
DESTINATION "${YAML_CPP_INSTALL_CMAKEDIR}")
install(FILES "${PROJECT_BINARY_DIR}/yaml-cpp.pc"
DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
install(TARGETS yaml-cpp EXPORT yaml-cpp-targets ${_INSTALL_DESTINATIONS})
install(
DIRECTORY ${header_directory}
DESTINATION ${INCLUDE_INSTALL_DIR}
FILES_MATCHING PATTERN "*.h"
)
endif()
export(
TARGETS yaml-cpp
FILE "${PROJECT_BINARY_DIR}/yaml-cpp-targets.cmake")
export(PACKAGE yaml-cpp)
set(EXPORT_TARGETS yaml-cpp CACHE INTERNAL "export targets")
set(CONFIG_INCLUDE_DIRS "${YAML_CPP_SOURCE_DIR}/include")
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/yaml-cpp-config.cmake.in
"${PROJECT_BINARY_DIR}/yaml-cpp-config.cmake" @ONLY)
if(WIN32 AND NOT CYGWIN)
set(INSTALL_CMAKE_DIR CMake)
else()
set(INSTALL_CMAKE_DIR ${LIB_INSTALL_DIR}/cmake/yaml-cpp)
endif()
file(RELATIVE_PATH REL_INCLUDE_DIR "${CMAKE_INSTALL_PREFIX}/${INSTALL_CMAKE_DIR}" "${CMAKE_INSTALL_PREFIX}/${INCLUDE_INSTALL_ROOT_DIR}")
set(CONFIG_INCLUDE_DIRS "\${YAML_CPP_CMAKE_DIR}/${REL_INCLUDE_DIR}")
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/yaml-cpp-config.cmake.in
"${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/yaml-cpp-config.cmake" @ONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/yaml-cpp-config-version.cmake.in
"${PROJECT_BINARY_DIR}/yaml-cpp-config-version.cmake" @ONLY)
if (YAML_CPP_INSTALL)
install(FILES
"${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/yaml-cpp-config.cmake"
"${PROJECT_BINARY_DIR}/yaml-cpp-config-version.cmake"
DESTINATION "${INSTALL_CMAKE_DIR}" COMPONENT dev)
install(EXPORT yaml-cpp-targets DESTINATION ${INSTALL_CMAKE_DIR})
if(UNIX)
set(PC_FILE ${CMAKE_BINARY_DIR}/yaml-cpp.pc)
configure_file("yaml-cpp.pc.cmake" ${PC_FILE} @ONLY)
install(FILES ${PC_FILE} DESTINATION ${LIB_INSTALL_DIR}/pkgconfig)
endif()
endif()
###
### Extras
###
if(YAML_CPP_BUILD_TESTS)
add_subdirectory(test)
enable_testing()
add_subdirectory(test)
endif()
if(YAML_CPP_BUILD_TOOLS)
add_subdirectory(util)
add_subdirectory(util)
endif()
if (YAML_CPP_FORMAT_SOURCE AND YAML_CPP_CLANG_FORMAT_EXE)
add_custom_target(format
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(YAML_CPP_INSTALL AND NOT YAML_CPP_DISABLE_UNINSTALL AND NOT TARGET uninstall)
configure_file(
"${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake.in"
"${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake"
IMMEDIATE @ONLY)
add_custom_target(uninstall
COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake)
endif()
### Formatting
get_property(all_sources GLOBAL PROPERTY SRCS_LIST)
add_custom_target(format
COMMAND clang-format --style=file -i ${all_sources}
COMMENT "Running clang-format"
VERBATIM)
+2 -11
View File
@@ -17,19 +17,10 @@ Commit messages should be in the imperative mood, as described in the [Git contr
# Tests
Please verify the tests pass by configuring CMake with `-D YAML_CPP_BUILD_TESTS=ON` and running the target `test/yaml-cpp-tests`.
Please verify the tests pass by running the target `tests/run_tests`.
If you are adding functionality, add tests accordingly. Note that the "spec tests" are reserved for examples directly from the YAML spec, so if you have new examples, put them in other test files.
If you are adding functionality, add tests accordingly.
# Pull request process
Every pull request undergoes a code review. Unfortunately, github's code review process isn't great, but we'll manage. During the code review, if you make changes, add new commits to the pull request for each change. Once the code review is complete, rebase against the master branch and squash into a single commit.
# AI Usage
The following rules are in service of producing correct, maintainable code while not inundating the maintainers.
1. You (the author of the PR) are responsible for the PR, regardless of the tools you use to create it. Make sure you understand it thoroughly and agree with its contents before you submit a PR.
2. Corollary: AI is not a co-author, AI is a tool. If you wouldn't list Emacs as a co-author, don't list Claude either. (Maybe it will be someday, but not yet.)
3. Do not use AI to generate documentation. It's fine for code, but it's [painful](https://samkriss.substack.com/p/if-you-let-ai-do-your-writing-i-will) to read AI text.
4. No "low effort" AI PRs. Don't just paste an issue into Claude and ask it to fix it; don't just ask it for a vulnerability report. That's fine as a starting point, but if that's *all* you do, then you haven't provided any value; you've just added work for the maintainers, who could have easily pasted the issue into Claude themselves.
-14
View File
@@ -1,14 +0,0 @@
"""
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 = "1.0.0")
bazel_dep(name = "rules_cc", version = "0.2.14")
bazel_dep(name = "googletest", version = "1.17.0.bcr.2", dev_dependency = True)
-282
View File
@@ -1,282 +0,0 @@
{
"lockFileVersion": 24,
"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/20230802.0.bcr.1/MODULE.bazel": "1c8cec495288dccd14fdae6e3f95f772c1c91857047a098fad772034264cc8cb",
"https://bcr.bazel.build/modules/abseil-cpp/20230802.0/MODULE.bazel": "d253ae36a8bd9ee3c5955384096ccb6baf16a1b1e93e858370da0a3b94f77c16",
"https://bcr.bazel.build/modules/abseil-cpp/20230802.1/MODULE.bazel": "fa92e2eb41a04df73cdabeec37107316f7e5272650f81d6cc096418fe647b915",
"https://bcr.bazel.build/modules/abseil-cpp/20240116.1/MODULE.bazel": "37bcdb4440fbb61df6a1c296ae01b327f19e9bb521f9b8e26ec854b6f97309ed",
"https://bcr.bazel.build/modules/abseil-cpp/20240116.2/MODULE.bazel": "73939767a4686cd9a520d16af5ab440071ed75cec1a876bf2fcfaf1f71987a16",
"https://bcr.bazel.build/modules/abseil-cpp/20250127.1/MODULE.bazel": "c4a89e7ceb9bf1e25cf84a9f830ff6b817b72874088bf5141b314726e46a57c1",
"https://bcr.bazel.build/modules/abseil-cpp/20250512.1/MODULE.bazel": "d209fdb6f36ffaf61c509fcc81b19e81b411a999a934a032e10cd009a0226215",
"https://bcr.bazel.build/modules/abseil-cpp/20250512.1/source.json": "d725d73707d01bb46ab3ca59ba408b8e9bd336642ca77a2269d4bfb8bbfd413d",
"https://bcr.bazel.build/modules/apple_support/1.15.1/MODULE.bazel": "a0556fefca0b1bb2de8567b8827518f94db6a6e7e7d632b4c48dc5f865bc7c85",
"https://bcr.bazel.build/modules/apple_support/1.22.1/MODULE.bazel": "90bd1a660590f3ceffbdf524e37483094b29352d85317060b2327fff8f3f4458",
"https://bcr.bazel.build/modules/apple_support/1.23.1/MODULE.bazel": "53763fed456a968cf919b3240427cf3a9d5481ec5466abc9d5dc51bc70087442",
"https://bcr.bazel.build/modules/apple_support/1.23.1/source.json": "d888b44312eb0ad2c21a91d026753f330caa48a25c9b2102fae75eb2b0dcfdd2",
"https://bcr.bazel.build/modules/bazel_features/1.1.1/MODULE.bazel": "27b8c79ef57efe08efccbd9dd6ef70d61b4798320b8d3c134fd571f78963dbcd",
"https://bcr.bazel.build/modules/bazel_features/1.11.0/MODULE.bazel": "f9382337dd5a474c3b7d334c2f83e50b6eaedc284253334cf823044a26de03e8",
"https://bcr.bazel.build/modules/bazel_features/1.15.0/MODULE.bazel": "d38ff6e517149dc509406aca0db3ad1efdd890a85e049585b7234d04238e2a4d",
"https://bcr.bazel.build/modules/bazel_features/1.17.0/MODULE.bazel": "039de32d21b816b47bd42c778e0454217e9c9caac4a3cf8e15c7231ee3ddee4d",
"https://bcr.bazel.build/modules/bazel_features/1.18.0/MODULE.bazel": "1be0ae2557ab3a72a57aeb31b29be347bcdc5d2b1eb1e70f39e3851a7e97041a",
"https://bcr.bazel.build/modules/bazel_features/1.19.0/MODULE.bazel": "59adcdf28230d220f0067b1f435b8537dd033bfff8db21335ef9217919c7fb58",
"https://bcr.bazel.build/modules/bazel_features/1.21.0/MODULE.bazel": "675642261665d8eea09989aa3b8afb5c37627f1be178382c320d1b46afba5e3b",
"https://bcr.bazel.build/modules/bazel_features/1.27.0/MODULE.bazel": "621eeee06c4458a9121d1f104efb80f39d34deff4984e778359c60eaf1a8cb65",
"https://bcr.bazel.build/modules/bazel_features/1.28.0/MODULE.bazel": "4b4200e6cbf8fa335b2c3f43e1d6ef3e240319c33d43d60cc0fbd4b87ece299d",
"https://bcr.bazel.build/modules/bazel_features/1.30.0/MODULE.bazel": "a14b62d05969a293b80257e72e597c2da7f717e1e69fa8b339703ed6731bec87",
"https://bcr.bazel.build/modules/bazel_features/1.30.0/source.json": "b07e17f067fe4f69f90b03b36ef1e08fe0d1f3cac254c1241a1818773e3423bc",
"https://bcr.bazel.build/modules/bazel_features/1.4.1/MODULE.bazel": "e45b6bb2350aff3e442ae1111c555e27eac1d915e77775f6fdc4b351b758b5d7",
"https://bcr.bazel.build/modules/bazel_features/1.9.1/MODULE.bazel": "8f679097876a9b609ad1f60249c49d68bfab783dd9be012faf9d82547b14815a",
"https://bcr.bazel.build/modules/bazel_skylib/1.0.3/MODULE.bazel": "bcb0fd896384802d1ad283b4e4eb4d718eebd8cb820b0a2c3a347fb971afd9d8",
"https://bcr.bazel.build/modules/bazel_skylib/1.1.1/MODULE.bazel": "1add3e7d93ff2e6998f9e118022c84d163917d912f5afafb3058e3d2f1545b5e",
"https://bcr.bazel.build/modules/bazel_skylib/1.2.0/MODULE.bazel": "44fe84260e454ed94ad326352a698422dbe372b21a1ac9f3eab76eb531223686",
"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.4.2/MODULE.bazel": "3bd40978e7a1fac911d5989e6b09d8f64921865a45822d8b09e815eaa726a651",
"https://bcr.bazel.build/modules/bazel_skylib/1.5.0/MODULE.bazel": "32880f5e2945ce6a03d1fbd588e9198c0a959bb42297b2cfaf1685b7bc32e138",
"https://bcr.bazel.build/modules/bazel_skylib/1.6.1/MODULE.bazel": "8fdee2dbaace6c252131c00e1de4b165dc65af02ea278476187765e1a617b917",
"https://bcr.bazel.build/modules/bazel_skylib/1.7.0/MODULE.bazel": "0db596f4563de7938de764cc8deeabec291f55e8ec15299718b93c4423e9796d",
"https://bcr.bazel.build/modules/bazel_skylib/1.7.1/MODULE.bazel": "3120d80c5861aa616222ec015332e5f8d3171e062e3e804a2a0253e1be26e59b",
"https://bcr.bazel.build/modules/bazel_skylib/1.7.1/source.json": "f121b43eeefc7c29efbd51b83d08631e2347297c95aac9764a701f2a6a2bb953",
"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/google_benchmark/1.8.2/MODULE.bazel": "a70cf1bba851000ba93b58ae2f6d76490a9feb74192e57ab8e8ff13c34ec50cb",
"https://bcr.bazel.build/modules/googletest/1.11.0/MODULE.bazel": "3a83f095183f66345ca86aa13c58b59f9f94a2f81999c093d4eeaa2d262d12f4",
"https://bcr.bazel.build/modules/googletest/1.14.0.bcr.1/MODULE.bazel": "22c31a561553727960057361aa33bf20fb2e98584bc4fec007906e27053f80c6",
"https://bcr.bazel.build/modules/googletest/1.14.0/MODULE.bazel": "cfbcbf3e6eac06ef9d85900f64424708cc08687d1b527f0ef65aa7517af8118f",
"https://bcr.bazel.build/modules/googletest/1.15.2/MODULE.bazel": "6de1edc1d26cafb0ea1a6ab3f4d4192d91a312fd2d360b63adaa213cd00b2108",
"https://bcr.bazel.build/modules/googletest/1.17.0.bcr.2/MODULE.bazel": "827f54f492a3ce549c940106d73de332c2b30cebd0c20c0bc5d786aba7f116cb",
"https://bcr.bazel.build/modules/googletest/1.17.0.bcr.2/source.json": "3664514073a819992320ffbce5825e4238459df344d8b01748af2208f8d2e1eb",
"https://bcr.bazel.build/modules/googletest/1.17.0/MODULE.bazel": "dbec758171594a705933a29fcf69293d2468c49ec1f2ebca65c36f504d72df46",
"https://bcr.bazel.build/modules/jsoncpp/1.9.5/MODULE.bazel": "31271aedc59e815656f5736f282bb7509a97c7ecb43e927ac1a37966e0578075",
"https://bcr.bazel.build/modules/jsoncpp/1.9.5/source.json": "4108ee5085dd2885a341c7fab149429db457b3169b86eb081fa245eadf69169d",
"https://bcr.bazel.build/modules/libpfm/4.11.0/MODULE.bazel": "45061ff025b301940f1e30d2c16bea596c25b176c8b6b3087e92615adbd52902",
"https://bcr.bazel.build/modules/platforms/0.0.10/MODULE.bazel": "8cb8efaf200bdeb2150d93e162c40f388529a25852b332cec879373771e48ed5",
"https://bcr.bazel.build/modules/platforms/0.0.11/MODULE.bazel": "0daefc49732e227caa8bfa834d65dc52e8cc18a2faf80df25e8caea151a9413f",
"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.8/MODULE.bazel": "9f142c03e348f6d263719f5074b21ef3adf0b139ee4c5133e2aa35664da9eb2d",
"https://bcr.bazel.build/modules/platforms/0.0.9/MODULE.bazel": "4a87a60c927b56ddd67db50c89acaa62f4ce2a1d2149ccb63ffd871d5ce29ebc",
"https://bcr.bazel.build/modules/platforms/1.0.0/MODULE.bazel": "f05feb42b48f1b3c225e4ccf351f367be0371411a803198ec34a389fb22aa580",
"https://bcr.bazel.build/modules/platforms/1.0.0/source.json": "f4ff1fd412e0246fd38c82328eb209130ead81d62dcd5a9e40910f867f733d96",
"https://bcr.bazel.build/modules/protobuf/21.7/MODULE.bazel": "a5a29bb89544f9b97edce05642fac225a808b5b7be74038ea3640fae2f8e66a7",
"https://bcr.bazel.build/modules/protobuf/23.1/MODULE.bazel": "88b393b3eb4101d18129e5db51847cd40a5517a53e81216144a8c32dfeeca52a",
"https://bcr.bazel.build/modules/protobuf/24.4/MODULE.bazel": "7bc7ce5f2abf36b3b7b7c8218d3acdebb9426aeb35c2257c96445756f970eb12",
"https://bcr.bazel.build/modules/protobuf/27.0/MODULE.bazel": "7873b60be88844a0a1d8f80b9d5d20cfbd8495a689b8763e76c6372998d3f64c",
"https://bcr.bazel.build/modules/protobuf/27.1/MODULE.bazel": "703a7b614728bb06647f965264967a8ef1c39e09e8f167b3ca0bb1fd80449c0d",
"https://bcr.bazel.build/modules/protobuf/29.0-rc2/MODULE.bazel": "6241d35983510143049943fc0d57937937122baf1b287862f9dc8590fc4c37df",
"https://bcr.bazel.build/modules/protobuf/29.0-rc3/MODULE.bazel": "33c2dfa286578573afc55a7acaea3cada4122b9631007c594bf0729f41c8de92",
"https://bcr.bazel.build/modules/protobuf/29.0/MODULE.bazel": "319dc8bf4c679ff87e71b1ccfb5a6e90a6dbc4693501d471f48662ac46d04e4e",
"https://bcr.bazel.build/modules/protobuf/29.0/source.json": "b857f93c796750eef95f0d61ee378f3420d00ee1dd38627b27193aa482f4f981",
"https://bcr.bazel.build/modules/protobuf/3.19.0/MODULE.bazel": "6b5fbb433f760a99a22b18b6850ed5784ef0e9928a72668b66e4d7ccd47db9b0",
"https://bcr.bazel.build/modules/pybind11_bazel/2.11.1/MODULE.bazel": "88af1c246226d87e65be78ed49ecd1e6f5e98648558c14ce99176da041dc378e",
"https://bcr.bazel.build/modules/pybind11_bazel/2.12.0/MODULE.bazel": "e6f4c20442eaa7c90d7190d8dc539d0ab422f95c65a57cc59562170c58ae3d34",
"https://bcr.bazel.build/modules/pybind11_bazel/2.13.6/MODULE.bazel": "2d746fda559464b253b2b2e6073cb51643a2ac79009ca02100ebbc44b4548656",
"https://bcr.bazel.build/modules/pybind11_bazel/2.13.6/source.json": "6aa0703de8efb20cc897bbdbeb928582ee7beaf278bcd001ac253e1605bddfae",
"https://bcr.bazel.build/modules/re2/2023-09-01/MODULE.bazel": "cb3d511531b16cfc78a225a9e2136007a48cf8a677e4264baeab57fe78a80206",
"https://bcr.bazel.build/modules/re2/2024-07-02.bcr.1/MODULE.bazel": "b4963dda9b31080be1905ef085ecd7dd6cd47c05c79b9cdf83ade83ab2ab271a",
"https://bcr.bazel.build/modules/re2/2024-07-02/MODULE.bazel": "0eadc4395959969297cbcf31a249ff457f2f1d456228c67719480205aa306daa",
"https://bcr.bazel.build/modules/re2/2025-08-12.bcr.1/MODULE.bazel": "e09b434b122bfb786a69179f9b325e35cb1856c3f56a7a81dd61609260ed46e1",
"https://bcr.bazel.build/modules/re2/2025-08-12.bcr.1/source.json": "a8ae7c09533bf67f9f6e5122d884d5741600b09d78dca6fc0f2f8d2ee0c2d957",
"https://bcr.bazel.build/modules/rules_android/0.1.1/MODULE.bazel": "48809ab0091b07ad0182defb787c4c5328bd3a278938415c00a7b69b50c4d3a8",
"https://bcr.bazel.build/modules/rules_android/0.1.1/source.json": "e6986b41626ee10bdc864937ffb6d6bf275bb5b9c65120e6137d56e6331f089e",
"https://bcr.bazel.build/modules/rules_cc/0.0.1/MODULE.bazel": "cb2aa0747f84c6c3a78dad4e2049c154f08ab9d166b1273835a8174940365647",
"https://bcr.bazel.build/modules/rules_cc/0.0.10/MODULE.bazel": "ec1705118f7eaedd6e118508d3d26deba2a4e76476ada7e0e3965211be012002",
"https://bcr.bazel.build/modules/rules_cc/0.0.13/MODULE.bazel": "0e8529ed7b323dad0775ff924d2ae5af7640b23553dfcd4d34344c7e7a867191",
"https://bcr.bazel.build/modules/rules_cc/0.0.14/MODULE.bazel": "5e343a3aac88b8d7af3b1b6d2093b55c347b8eefc2e7d1442f7a02dc8fea48ac",
"https://bcr.bazel.build/modules/rules_cc/0.0.15/MODULE.bazel": "6704c35f7b4a72502ee81f61bf88706b54f06b3cbe5558ac17e2e14666cd5dcc",
"https://bcr.bazel.build/modules/rules_cc/0.0.16/MODULE.bazel": "7661303b8fc1b4d7f532e54e9d6565771fea666fbdf839e0a86affcd02defe87",
"https://bcr.bazel.build/modules/rules_cc/0.0.17/MODULE.bazel": "2ae1d8f4238ec67d7185d8861cb0a2cdf4bc608697c331b95bf990e69b62e64a",
"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.1.1/MODULE.bazel": "2f0222a6f229f0bf44cd711dc13c858dad98c62d52bd51d8fc3a764a83125513",
"https://bcr.bazel.build/modules/rules_cc/0.1.4/MODULE.bazel": "bb03a452a7527ac25a7518fb86a946ef63df860b9657d8323a0c50f8504fb0b9",
"https://bcr.bazel.build/modules/rules_cc/0.2.14/MODULE.bazel": "353c99ed148887ee89c54a17d4100ae7e7e436593d104b668476019023b58df8",
"https://bcr.bazel.build/modules/rules_cc/0.2.14/source.json": "55d0a4587c5592fad350f6e698530f4faf0e7dd15e69d43f8d87e220c78bea54",
"https://bcr.bazel.build/modules/rules_cc/0.2.8/MODULE.bazel": "f1df20f0bf22c28192a794f29b501ee2018fa37a3862a1a2132ae2940a23a642",
"https://bcr.bazel.build/modules/rules_foreign_cc/0.9.0/MODULE.bazel": "c9e8c682bf75b0e7c704166d79b599f93b72cfca5ad7477df596947891feeef6",
"https://bcr.bazel.build/modules/rules_fuzzing/0.5.2/MODULE.bazel": "40c97d1144356f52905566c55811f13b299453a14ac7769dfba2ac38192337a8",
"https://bcr.bazel.build/modules/rules_fuzzing/0.5.2/source.json": "c8b1e2c717646f1702290959a3302a178fb639d987ab61d548105019f11e527e",
"https://bcr.bazel.build/modules/rules_java/4.0.0/MODULE.bazel": "5a78a7ae82cd1a33cef56dc578c7d2a46ed0dca12643ee45edbb8417899e6f74",
"https://bcr.bazel.build/modules/rules_java/5.3.5/MODULE.bazel": "a4ec4f2db570171e3e5eb753276ee4b389bae16b96207e9d3230895c99644b86",
"https://bcr.bazel.build/modules/rules_java/6.0.0/MODULE.bazel": "8a43b7df601a7ec1af61d79345c17b31ea1fedc6711fd4abfd013ea612978e39",
"https://bcr.bazel.build/modules/rules_java/6.4.0/MODULE.bazel": "e986a9fe25aeaa84ac17ca093ef13a4637f6107375f64667a15999f77db6c8f6",
"https://bcr.bazel.build/modules/rules_java/6.5.2/MODULE.bazel": "1d440d262d0e08453fa0c4d8f699ba81609ed0e9a9a0f02cd10b3e7942e61e31",
"https://bcr.bazel.build/modules/rules_java/7.1.0/MODULE.bazel": "30d9135a2b6561c761bd67bd4990da591e6bdc128790ce3e7afd6a3558b2fb64",
"https://bcr.bazel.build/modules/rules_java/7.10.0/MODULE.bazel": "530c3beb3067e870561739f1144329a21c851ff771cd752a49e06e3dc9c2e71a",
"https://bcr.bazel.build/modules/rules_java/7.12.2/MODULE.bazel": "579c505165ee757a4280ef83cda0150eea193eed3bef50b1004ba88b99da6de6",
"https://bcr.bazel.build/modules/rules_java/7.2.0/MODULE.bazel": "06c0334c9be61e6cef2c8c84a7800cef502063269a5af25ceb100b192453d4ab",
"https://bcr.bazel.build/modules/rules_java/7.3.2/MODULE.bazel": "50dece891cfdf1741ea230d001aa9c14398062f2b7c066470accace78e412bc2",
"https://bcr.bazel.build/modules/rules_java/7.6.1/MODULE.bazel": "2f14b7e8a1aa2f67ae92bc69d1ec0fa8d9f827c4e17ff5e5f02e91caa3b2d0fe",
"https://bcr.bazel.build/modules/rules_java/8.14.0/MODULE.bazel": "717717ed40cc69994596a45aec6ea78135ea434b8402fb91b009b9151dd65615",
"https://bcr.bazel.build/modules/rules_java/8.14.0/source.json": "8a88c4ca9e8759da53cddc88123880565c520503321e2566b4e33d0287a3d4bc",
"https://bcr.bazel.build/modules/rules_java/8.3.2/MODULE.bazel": "7336d5511ad5af0b8615fdc7477535a2e4e723a357b6713af439fe8cf0195017",
"https://bcr.bazel.build/modules/rules_java/8.5.1/MODULE.bazel": "d8a9e38cc5228881f7055a6079f6f7821a073df3744d441978e7a43e20226939",
"https://bcr.bazel.build/modules/rules_jvm_external/4.4.2/MODULE.bazel": "a56b85e418c83eb1839819f0b515c431010160383306d13ec21959ac412d2fe7",
"https://bcr.bazel.build/modules/rules_jvm_external/5.1/MODULE.bazel": "33f6f999e03183f7d088c9be518a63467dfd0be94a11d0055fe2d210f89aa909",
"https://bcr.bazel.build/modules/rules_jvm_external/5.2/MODULE.bazel": "d9351ba35217ad0de03816ef3ed63f89d411349353077348a45348b096615036",
"https://bcr.bazel.build/modules/rules_jvm_external/5.3/MODULE.bazel": "bf93870767689637164657731849fb887ad086739bd5d360d90007a581d5527d",
"https://bcr.bazel.build/modules/rules_jvm_external/6.1/MODULE.bazel": "75b5fec090dbd46cf9b7d8ea08cf84a0472d92ba3585b476f44c326eda8059c4",
"https://bcr.bazel.build/modules/rules_jvm_external/6.3/MODULE.bazel": "c998e060b85f71e00de5ec552019347c8bca255062c990ac02d051bb80a38df0",
"https://bcr.bazel.build/modules/rules_jvm_external/6.3/source.json": "6f5f5a5a4419ae4e37c35a5bb0a6ae657ed40b7abc5a5189111b47fcebe43197",
"https://bcr.bazel.build/modules/rules_kotlin/1.9.0/MODULE.bazel": "ef85697305025e5a61f395d4eaede272a5393cee479ace6686dba707de804d59",
"https://bcr.bazel.build/modules/rules_kotlin/1.9.6/MODULE.bazel": "d269a01a18ee74d0335450b10f62c9ed81f2321d7958a2934e44272fe82dcef3",
"https://bcr.bazel.build/modules/rules_kotlin/1.9.6/source.json": "2faa4794364282db7c06600b7e5e34867a564ae91bda7cae7c29c64e9466b7d5",
"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/1.0.0/MODULE.bazel": "a7fda60eefdf3d8c827262ba499957e4df06f659330bbe6cdbdb975b768bb65c",
"https://bcr.bazel.build/modules/rules_license/1.0.0/source.json": "a52c89e54cc311196e478f8382df91c15f7a2bfdf4c6cd0e2675cc2ff0b56efb",
"https://bcr.bazel.build/modules/rules_pkg/0.7.0/MODULE.bazel": "df99f03fc7934a4737122518bb87e667e62d780b610910f0447665a7e2be62dc",
"https://bcr.bazel.build/modules/rules_pkg/1.0.1/MODULE.bazel": "5b1df97dbc29623bccdf2b0dcd0f5cb08e2f2c9050aab1092fd39a41e82686ff",
"https://bcr.bazel.build/modules/rules_pkg/1.0.1/source.json": "bd82e5d7b9ce2d31e380dd9f50c111d678c3bdaca190cb76b0e1c71b05e1ba8a",
"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/6.0.0-rc1/MODULE.bazel": "1e5b502e2e1a9e825eef74476a5a1ee524a92297085015a052510b09a1a09483",
"https://bcr.bazel.build/modules/rules_proto/6.0.2/MODULE.bazel": "ce916b775a62b90b61888052a416ccdda405212b6aaeb39522f7dc53431a5e73",
"https://bcr.bazel.build/modules/rules_proto/7.0.2/MODULE.bazel": "bf81793bd6d2ad89a37a40693e56c61b0ee30f7a7fdbaf3eabbf5f39de47dea2",
"https://bcr.bazel.build/modules/rules_proto/7.0.2/source.json": "1e5e7260ae32ef4f2b52fd1d0de8d03b606a44c91b694d2f1afb1d3b28a48ce1",
"https://bcr.bazel.build/modules/rules_python/0.10.2/MODULE.bazel": "cc82bc96f2997baa545ab3ce73f196d040ffb8756fd2d66125a530031cd90e5f",
"https://bcr.bazel.build/modules/rules_python/0.23.1/MODULE.bazel": "49ffccf0511cb8414de28321f5fcf2a31312b47c40cc21577144b7447f2bf300",
"https://bcr.bazel.build/modules/rules_python/0.25.0/MODULE.bazel": "72f1506841c920a1afec76975b35312410eea3aa7b63267436bfb1dd91d2d382",
"https://bcr.bazel.build/modules/rules_python/0.28.0/MODULE.bazel": "cba2573d870babc976664a912539b320cbaa7114cd3e8f053c720171cde331ed",
"https://bcr.bazel.build/modules/rules_python/0.31.0/MODULE.bazel": "93a43dc47ee570e6ec9f5779b2e64c1476a6ce921c48cc9a1678a91dd5f8fd58",
"https://bcr.bazel.build/modules/rules_python/0.33.2/MODULE.bazel": "3e036c4ad8d804a4dad897d333d8dce200d943df4827cb849840055be8d2e937",
"https://bcr.bazel.build/modules/rules_python/0.34.0/MODULE.bazel": "1d623d026e075b78c9fde483a889cda7996f5da4f36dffb24c246ab30f06513a",
"https://bcr.bazel.build/modules/rules_python/0.4.0/MODULE.bazel": "9208ee05fd48bf09ac60ed269791cf17fb343db56c8226a720fbb1cdf467166c",
"https://bcr.bazel.build/modules/rules_python/0.40.0/MODULE.bazel": "9d1a3cd88ed7d8e39583d9ffe56ae8a244f67783ae89b60caafc9f5cf318ada7",
"https://bcr.bazel.build/modules/rules_python/1.5.1/MODULE.bazel": "acfe65880942d44a69129d4c5c3122d57baaf3edf58ae5a6bd4edea114906bf5",
"https://bcr.bazel.build/modules/rules_python/1.5.1/source.json": "aa903e1bcbdfa1580f2b8e2d55100b7c18bc92d779ebb507fec896c75635f7bd",
"https://bcr.bazel.build/modules/rules_shell/0.2.0/MODULE.bazel": "fda8a652ab3c7d8fee214de05e7a9916d8b28082234e8d2c0094505c5268ed3c",
"https://bcr.bazel.build/modules/rules_shell/0.2.0/source.json": "7f27af3c28037d9701487c4744b5448d26537cc66cdef0d8df7ae85411f8de95",
"https://bcr.bazel.build/modules/stardoc/0.5.1/MODULE.bazel": "1a05d92974d0c122f5ccf09291442580317cdd859f07a8655f1db9a60374f9f8",
"https://bcr.bazel.build/modules/stardoc/0.5.3/MODULE.bazel": "c7f6948dae6999bf0db32c1858ae345f112cacf98f174c7a8bb707e41b974f1c",
"https://bcr.bazel.build/modules/stardoc/0.5.6/MODULE.bazel": "c43dabc564990eeab55e25ed61c07a1aadafe9ece96a4efabb3f8bf9063b71ef",
"https://bcr.bazel.build/modules/stardoc/0.7.0/MODULE.bazel": "05e3d6d30c099b6770e97da986c53bd31844d7f13d41412480ea265ac9e8079c",
"https://bcr.bazel.build/modules/stardoc/0.7.1/MODULE.bazel": "3548faea4ee5dda5580f9af150e79d0f6aea934fc60c1cc50f4efdd9420759e7",
"https://bcr.bazel.build/modules/stardoc/0.7.2/MODULE.bazel": "fc152419aa2ea0f51c29583fab1e8c99ddefd5b3778421845606ee628629e0e5",
"https://bcr.bazel.build/modules/stardoc/0.7.2/source.json": "58b029e5e901d6802967754adf0a9056747e8176f017cfe3607c0851f4d42216",
"https://bcr.bazel.build/modules/upb/0.0.0-20220923-a547704/MODULE.bazel": "7298990c00040a0e2f121f6c32544bab27d4452f80d9ce51349b1a28f3005c43",
"https://bcr.bazel.build/modules/upb/0.0.0-20230516-61a97ef/MODULE.bazel": "c0df5e35ad55e264160417fd0875932ee3c9dda63d9fccace35ac62f45e1b6f9",
"https://bcr.bazel.build/modules/zlib/1.2.11/MODULE.bazel": "07b389abc85fdbca459b69e2ec656ae5622873af3f845e1c9d80fe179f3effa0",
"https://bcr.bazel.build/modules/zlib/1.3.1.bcr.5/MODULE.bazel": "eec517b5bbe5492629466e11dae908d043364302283de25581e3eb944326c4ca",
"https://bcr.bazel.build/modules/zlib/1.3.1.bcr.5/source.json": "22bc55c47af97246cfc093d0acf683a7869377de362b5d1c552c2c2e16b7a806",
"https://bcr.bazel.build/modules/zlib/1.3.1/MODULE.bazel": "751c9940dcfe869f5f7274e1295422a34623555916eb98c174c1e945594bf198"
},
"selectedYankedVersions": {},
"moduleExtensions": {
"@@rules_kotlin+//src/main/starlark/core/repositories:bzlmod_setup.bzl%rules_kotlin_extensions": {
"general": {
"bzlTransitiveDigest": "rL/34P1aFDq2GqVC2zCFgQ8nTuOC6ziogocpvG50Qz8=",
"usagesDigest": "QI2z8ZUR+mqtbwsf2fLqYdJAkPOHdOV+tF2yVAUgRzw=",
"recordedFileInputs": {},
"recordedDirentsInputs": {},
"envVariables": {},
"generatedRepoSpecs": {
"com_github_jetbrains_kotlin_git": {
"repoRuleId": "@@rules_kotlin+//src/main/starlark/core/repositories:compiler.bzl%kotlin_compiler_git_repository",
"attributes": {
"urls": [
"https://github.com/JetBrains/kotlin/releases/download/v1.9.23/kotlin-compiler-1.9.23.zip"
],
"sha256": "93137d3aab9afa9b27cb06a824c2324195c6b6f6179d8a8653f440f5bd58be88"
}
},
"com_github_jetbrains_kotlin": {
"repoRuleId": "@@rules_kotlin+//src/main/starlark/core/repositories:compiler.bzl%kotlin_capabilities_repository",
"attributes": {
"git_repository_name": "com_github_jetbrains_kotlin_git",
"compiler_version": "1.9.23"
}
},
"com_github_google_ksp": {
"repoRuleId": "@@rules_kotlin+//src/main/starlark/core/repositories:ksp.bzl%ksp_compiler_plugin_repository",
"attributes": {
"urls": [
"https://github.com/google/ksp/releases/download/1.9.23-1.0.20/artifacts.zip"
],
"sha256": "ee0618755913ef7fd6511288a232e8fad24838b9af6ea73972a76e81053c8c2d",
"strip_version": "1.9.23-1.0.20"
}
},
"com_github_pinterest_ktlint": {
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_file",
"attributes": {
"sha256": "01b2e0ef893383a50dbeb13970fe7fa3be36ca3e83259e01649945b09d736985",
"urls": [
"https://github.com/pinterest/ktlint/releases/download/1.3.0/ktlint"
],
"executable": true
}
},
"rules_android": {
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
"attributes": {
"sha256": "cd06d15dd8bb59926e4d65f9003bfc20f9da4b2519985c27e190cddc8b7a7806",
"strip_prefix": "rules_android-0.1.1",
"urls": [
"https://github.com/bazelbuild/rules_android/archive/v0.1.1.zip"
]
}
}
},
"recordedRepoMappingEntries": [
[
"rules_kotlin+",
"bazel_tools",
"bazel_tools"
]
]
}
},
"@@rules_python+//python/uv:uv.bzl%uv": {
"general": {
"bzlTransitiveDigest": "8vT1ddXtljNxYD0tJkksqzeKE6xqx4Ix+tXthAppjTI=",
"usagesDigest": "WYhzIw9khRBy34H1GxV5+fI1yi07O90NmCXosPUdHWQ=",
"recordedFileInputs": {},
"recordedDirentsInputs": {},
"envVariables": {},
"generatedRepoSpecs": {
"uv": {
"repoRuleId": "@@rules_python+//python/uv/private:uv_toolchains_repo.bzl%uv_toolchains_repo",
"attributes": {
"toolchain_type": "'@@rules_python+//python/uv:uv_toolchain_type'",
"toolchain_names": [
"none"
],
"toolchain_implementations": {
"none": "'@@rules_python+//python:none'"
},
"toolchain_compatible_with": {
"none": [
"@platforms//:incompatible"
]
},
"toolchain_target_settings": {}
}
}
},
"recordedRepoMappingEntries": [
[
"rules_python+",
"bazel_tools",
"bazel_tools"
],
[
"rules_python+",
"platforms",
"platforms"
]
]
}
}
},
"facts": {}
}
+27 -58
View File
@@ -1,82 +1,51 @@
# yaml-cpp ![Build Status](https://github.com/jbeder/yaml-cpp/actions/workflows/build.yml/badge.svg) [![Documentation](https://codedocs.xyz/jbeder/yaml-cpp.svg)](https://codedocs.xyz/jbeder/yaml-cpp/)
# yaml-cpp [![Build Status](https://travis-ci.org/jbeder/yaml-cpp.svg?branch=master)](https://travis-ci.org/jbeder/yaml-cpp) [![Documentation](https://codedocs.xyz/jbeder/yaml-cpp.svg)](https://codedocs.xyz/jbeder/yaml-cpp/)
`yaml-cpp` is a [YAML](http://www.yaml.org/) parser and emitter in C++ matching the [YAML 1.2 spec](http://www.yaml.org/spec/1.2/spec.html).
yaml-cpp is a [YAML](http://www.yaml.org/) parser and emitter in C++ matching the [YAML 1.2 spec](http://www.yaml.org/spec/1.2/spec.html).
## Usage
To get a feel for how it can be used, see the [Tutorial](https://github.com/jbeder/yaml-cpp/wiki/Tutorial) or [How to Emit YAML](https://github.com/jbeder/yaml-cpp/wiki/How-To-Emit-YAML). For the old API (version < 0.5.0), see [How To Parse A Document](https://github.com/jbeder/yaml-cpp/wiki/How-To-Parse-A-Document-(Old-API)).
See [Tutorial](https://github.com/jbeder/yaml-cpp/wiki/Tutorial) and [How to Emit YAML](https://github.com/jbeder/yaml-cpp/wiki/How-To-Emit-YAML) for reference. For the old API (until 0.5.0), see [How To Parse A Document](https://github.com/jbeder/yaml-cpp/wiki/How-To-Parse-A-Document-(Old-API)).
# Problems? #
## How to Build
If you find a bug, post an [issue](https://github.com/jbeder/yaml-cpp/issues)! If you have questions about how to use yaml-cpp, please post it on http://stackoverflow.com and tag it [`yaml-cpp`](http://stackoverflow.com/questions/tagged/yaml-cpp).
`yaml-cpp` uses [CMake](http://www.cmake.org) to support cross-platform building. Install [CMake](http://www.cmake.org) _(Resources -> Download)_ before proceeding. The basic steps to build are:
# How to Build #
**Note:** If you don't use the provided installer for your platform, make sure that you add `CMake`'s bin folder to your path.
yaml-cpp uses [CMake](http://www.cmake.org) to support cross-platform building. The basic steps to build are:
#### 1. Navigate into the source directory, create build folder and run `CMake`:
1. Download and install [CMake](http://www.cmake.org) (Resources -> Download).
```sh
**Note:** If you don't use the provided installer for your platform, make sure that you add CMake's bin folder to your path.
2. Navigate into the source directory, and type:
```
mkdir build
cd build
cmake [-G generator] [-DYAML_BUILD_SHARED_LIBS=on|OFF] ..
```
* The `generator` option is the build system you'd like to use. Run `cmake` without arguments to see a full list of available generators.
* On Windows, you might use "Visual Studio 12 2013" (VS 2013 32-bits), or "Visual Studio 14 2015 Win64" (VS 2015 64-bits).
* On OS X, you might use "Xcode".
* On a UNIX-like system, omit the option (for a Makefile).
3. Run CMake. The basic syntax is:
* `yaml-cpp` builds a static library by default, you may want to build a shared library by specifying `-DYAML_BUILD_SHARED_LIBS=ON`.
```
cmake [-G generator] [-DBUILD_SHARED_LIBS=ON|OFF] ..
```
* [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).
* The `generator` is whatever type of build system you'd like to use. To see a full list of generators on your platform, just run `cmake` (with no arguments). For example:
* On Windows, you might use "Visual Studio 12 2013" to generate a Visual Studio 2013 solution or "Visual Studio 14 2015 Win64" to generate a 64-bit Visual Studio 2015 solution.
* On OS X, you might use "Xcode" to generate an Xcode project
* On a UNIX-y system, simply omit the option to generate a makefile
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).
* yaml-cpp defaults to building a static library, but you may build a shared library by specifying `-DBUILD_SHARED_LIBS=ON`.
* For more options on customizing the build, see the [CMakeLists.txt](https://github.com/jbeder/yaml-cpp/blob/master/CMakeLists.txt) file.
#### 2. Build it!
* The command you'll need to run depends on the generator you chose earlier.
4. Build it!
**Note:** To clean up, just remove the `build` directory.
5. To clean up, just remove the `build` directory.
## How to Integrate it within your project using CMake
# Recent Release #
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.9.0](https://github.com/jbeder/yaml-cpp/releases/tag/yaml-cpp-0.9.0) released!
[yaml-cpp 0.6.0](https://github.com/jbeder/yaml-cpp/releases/tag/yaml-cpp-0.6.0) has been released! This release requires C++11, and no longer depends on Boost.
[yaml-cpp 0.3.0](https://github.com/jbeder/yaml-cpp/releases/tag/release-0.3.0) is still available if you want the old API.
**The old API will stop receiving bugfixes in 2026.** The 0.3.x versions provide the old API, and 0.5.x and above all provide the new API.
# API Documentation
The autogenerated API reference is hosted on [CodeDocs](https://codedocs.xyz/jbeder/yaml-cpp/index.html)
# Third Party Integrations
The following projects are not officially supported:
- [Qt wrapper](https://gist.github.com/brcha/d392b2fe5f1e427cc8a6)
- [UnrealEngine Wrapper](https://github.com/jwindgassen/UnrealYAML)
**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.
-13
View File
@@ -1,13 +0,0 @@
# Security Policy
## Supported Versions
Security updates are applied only to the latest release.
## Reporting a Vulnerability
If you have discovered a security vulnerability in this project, please report it privately. **Do not disclose it as a public issue.** This gives us time to work with you to fix the issue before public exposure, reducing the chance that the exploit will be used before a patch is released.
Please disclose it at [security advisory](https://github.com/jbeder/yaml-cpp/security/advisories/new).
This project is maintained by a team of volunteers on a reasonable-effort basis. As such, vulnerabilities will be disclosed in a best effort base.
-21
View File
@@ -1,21 +0,0 @@
if(NOT EXISTS "@CMAKE_BINARY_DIR@/install_manifest.txt")
message(FATAL_ERROR "Cannot find install manifest: @CMAKE_BINARY_DIR@/install_manifest.txt")
endif()
file(READ "@CMAKE_BINARY_DIR@/install_manifest.txt" files)
string(REGEX REPLACE "\n" ";" files "${files}")
foreach(file ${files})
message(STATUS "Uninstalling $ENV{DESTDIR}${file}")
if(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
exec_program(
"@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\""
OUTPUT_VARIABLE rm_out
RETURN_VALUE rm_retval
)
if(NOT "${rm_retval}" STREQUAL 0)
message(FATAL_ERROR "Problem when removing $ENV{DESTDIR}${file}")
endif()
else(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
message(STATUS "File $ENV{DESTDIR}${file} does not exist.")
endif()
endforeach()
-52
View File
@@ -1,52 +0,0 @@
# The following is a list of breaking changes to yaml-cpp, by version #
# New API #
## HEAD ##
* Throws an exception when trying to parse a negative number as an unsigned integer.
* Supports the `as<int8_t>`/`as<uint8_t>`, which throws an exception when the value exceeds the range of `int8_t`/`uint8_t`.
## 0.6.0 ##
* Requires C++11.
## 0.5.3 ##
_none_
## 0.5.2 ##
_none_
## 0.5.1 ##
* `Node::clear` was replaced by `Node::reset`, which takes an optional node, similar to smart pointers.
## 0.5.0 ##
Initial version of the new API.
# Old API #
## 0.3.0 ##
_none_
## 0.2.7 ##
* `YAML::Binary` now takes `const unsigned char *` for the binary data (instead of `const char *`).
## 0.2.6 ##
* `Node::GetType()` is now `Node::Type()`, and returns an enum `NodeType::value`, where:
> > ` struct NodeType { enum value { Null, Scalar, Sequence, Map }; }; `
* `Node::GetTag()` is now `Node::Tag()`
* `Node::Identity()` is removed, and `Node::IsAlias()` and `Node::IsReferenced()` have been merged into `Node::IsAliased()`. The reason: there's no reason to distinguish an alias node from its anchor - whichever happens to be emitted first will be the anchor, and the rest will be aliases.
* `Node::Read<T>` is now `Node::to<T>`. This wasn't a documented function, so it shouldn't break anything.
* `Node`'s comparison operators (for example, `operator == (const Node&, const T&)`) have all been removed. These weren't documented either (they were just used for the tests), so this shouldn't break anything either.
* The emitter no longer produces the document start by default - if you want it, you can supply it with the manipulator `YAML::BeginDoc`.
## 0.2.5 ##
This wiki was started with v0.2.5.
-226
View File
@@ -1,226 +0,0 @@
## Contents ##
# Basic Emitting #
The model for emitting YAML is `std::ostream` manipulators. A `YAML::Emitter` objects acts as an output stream, and its output can be retrieved through the `c_str()` function (as in `std::string`). For a simple example:
```cpp
#include "yaml-cpp/yaml.h"
int main()
{
YAML::Emitter out;
out << "Hello, World!";
std::cout << "Here's the output YAML:\n" << out.c_str(); // prints "Hello, World!"
return 0;
}
```
# Simple Lists and Maps #
A `YAML::Emitter` object acts as a state machine, and we use manipulators to move it between states. Here's a simple sequence:
```cpp
YAML::Emitter out;
out << YAML::BeginSeq;
out << "eggs";
out << "bread";
out << "milk";
out << YAML::EndSeq;
```
produces
```yaml
- eggs
- bread
- milk
```
A simple map:
```cpp
YAML::Emitter out;
out << YAML::BeginMap;
out << YAML::Key << "name";
out << YAML::Value << "Ryan Braun";
out << YAML::Key << "position";
out << YAML::Value << "LF";
out << YAML::EndMap;
```
produces
```yaml
name: Ryan Braun
position: LF
```
These elements can, of course, be nested:
```cpp
YAML::Emitter out;
out << YAML::BeginMap;
out << YAML::Key << "name";
out << YAML::Value << "Barack Obama";
out << YAML::Key << "children";
out << YAML::Value << YAML::BeginSeq << "Sasha" << "Malia" << YAML::EndSeq;
out << YAML::EndMap;
```
produces
```yaml
name: Barack Obama
children:
- Sasha
- Malia
```
# Using Manipulators #
To deviate from standard formatting, you can use manipulators to modify the output format. For example,
```cpp
YAML::Emitter out;
out << YAML::Literal << "A\n B\n C";
```
produces
```yaml
|
A
B
C
```
and
```cpp
YAML::Emitter out;
out << YAML::Flow;
out << YAML::BeginSeq << 2 << 3 << 5 << 7 << 11 << YAML::EndSeq;
```
produces
```yaml
[2, 3, 5, 7, 11]
```
Comments act like manipulators:
```cpp
YAML::Emitter out;
out << YAML::BeginMap;
out << YAML::Key << "method";
out << YAML::Value << "least squares";
out << YAML::Comment("should we change this method?");
out << YAML::EndMap;
```
produces
```yaml
method: least squares # should we change this method?
```
And so do aliases/anchors:
```cpp
YAML::Emitter out;
out << YAML::BeginSeq;
out << YAML::Anchor("fred");
out << YAML::BeginMap;
out << YAML::Key << "name" << YAML::Value << "Fred";
out << YAML::Key << "age" << YAML::Value << "42";
out << YAML::EndMap;
out << YAML::Alias("fred");
out << YAML::EndSeq;
```
produces
```yaml
- &fred
name: Fred
age: 42
- *fred
```
# STL Containers, and Other Overloads #
We overload `operator <<` for `std::vector`, `std::list`, and `std::map`, so you can write stuff like:
{% raw %}
```cpp
std::vector <int> squares = {1, 4, 9, 16};
std::map <std::string, int> ages = {{"Daniel", 26}, {"Jesse", 24}};
YAML::Emitter out;
out << YAML::BeginSeq;
out << YAML::Flow << squares;
out << ages;
out << YAML::EndSeq;
```
{% endraw %}
produces
```yaml
- [1, 4, 9, 16]
-
Daniel: 26
Jesse: 24
```
Of course, you can overload `operator <<` for your own types:
```cpp
struct Vec3 { int x; int y; int z; };
YAML::Emitter& operator << (YAML::Emitter& out, const Vec3& v) {
out << YAML::Flow;
out << YAML::BeginSeq << v.x << v.y << v.z << YAML::EndSeq;
return out;
}
```
and it'll play nicely with everything else.
# Using Existing Nodes #
We also overload `operator << ` for `YAML::Node`s in both APIs, so you can output existing Nodes. Of course, Nodes in the old API are read-only, so it's tricky to emit them if you want to modify them. So use the new API!
# Output Encoding #
The output is always UTF-8. By default, yaml-cpp will output as much as it can without escaping any characters. If you want to restrict the output to ASCII, use the manipulator `YAML::EscapeNonAscii`:
```cpp
emitter.SetOutputCharset(YAML::EscapeNonAscii);
```
# Lifetime of Manipulators #
Manipulators affect the **next** output item in the stream. If that item is a `BeginSeq` or `BeginMap`, the manipulator lasts until the corresponding `EndSeq` or `EndMap`. (However, within that sequence or map, you can override the manipulator locally, etc.; in effect, there's a "manipulator stack" behind the scenes.)
If you want to permanently change a setting, there are global setters corresponding to each manipulator, e.g.:
```cpp
YAML::Emitter out;
out.SetIndent(4);
out.SetMapStyle(YAML::Flow);
```
# When Something Goes Wrong #
If something goes wrong when you're emitting a document, it must be something like forgetting a `YAML::EndSeq`, or a misplaced `YAML::Key`. In this case, emitting silently fails (no more output is emitted) and an error flag is set. For example:
```cpp
YAML::Emitter out;
assert(out.good());
out << YAML::Key;
assert(!out.good());
std::cout << "Emitter error: " << out.GetLastError() << "\n";
```
-265
View File
@@ -1,265 +0,0 @@
_The following describes the old API. For the new API, see the [Tutorial](https://github.com/jbeder/yaml-cpp/wiki/Tutorial)._
## Contents ##
# Basic Parsing #
The parser accepts streams, not file names, so you need to first load the file. Since a YAML file can contain many documents, you can grab them one-by-one. A simple way to parse a YAML file might be:
```
#include <fstream>
#include "yaml-cpp/yaml.h"
int main()
{
std::ifstream fin("test.yaml");
YAML::Parser parser(fin);
YAML::Node doc;
while(parser.GetNextDocument(doc)) {
// ...
}
return 0;
}
```
# Reading From the Document #
Suppose we have a document consisting only of a scalar. We can read that scalar like this:
```
YAML::Node doc; // let's say we've already parsed this document
std::string scalar;
doc >> scalar;
std::cout << "That scalar was: " << scalar << std::endl;
```
How about sequences? Let's say our document now consists only of a sequences of scalars. We can use an iterator:
```
YAML::Node doc; // already parsed
for(YAML::Iterator it=doc.begin();it!=doc.end();++it) {
std::string scalar;
*it >> scalar;
std::cout << "Found scalar: " << scalar << std::endl;
}
```
... or we can just loop through:
```
YAML::Node doc; // already parsed
for(unsigned i=0;i<doc.size();i++) {
std::string scalar;
doc[i] >> scalar;
std::cout << "Found scalar: " << scalar << std::endl;
}
```
And finally maps. For now, let's say our document is a map with all keys/values being scalars. Again, we can iterate:
```
YAML::Node doc; // already parsed
for(YAML::Iterator it=doc.begin();it!=doc.end();++it) {
std::string key, value;
it.first() >> key;
it.second() >> value;
std::cout << "Key: " << key << ", value: " << value << std::endl;
}
```
Note that dereferencing a map iterator is undefined; instead, use the `first` and `second` methods to get the key and value nodes, respectively.
Alternatively, we can pick off the values one-by-one, if we know the keys:
```
YAML::Node doc; // already parsed
std::string name;
doc["name"] >> name;
int age;
doc["age"] >> age;
std::cout << "Found entry with name '" << name << "' and age '" << age << "'\n";
```
One thing to be keep in mind: reading a map by key (as immediately above) requires looping through all entries until we find the right key, which is an O(n) operation. So if you're reading the entire map this way, it'll be O(n^2). For small n, this isn't a big deal, but I wouldn't recommend reading maps with a very large number of entries (>100, say) this way.
## Optional Keys ##
If you try to access a key that doesn't exist, `yaml-cpp` throws an exception (see [When Something Goes Wrong](https://github.com/jbeder/yaml-cpp/wiki/How-To-Parse-A-Document-(Old-API)#When_Something_Goes_Wrong). If you have optional keys, it's often easier to use `FindValue` instead of `operator[]`:
```
YAML::Node doc; // already parsed
if(const YAML::Node *pName = doc.FindValue("name")) {
std::string name;
*pName >> name;
std::cout << "Key 'name' exists, with value '" << name << "'\n";
} else {
std::cout << "Key 'name' doesn't exist\n";
}
```
# Getting More Complicated #
The above three methods can be combined to read from an arbitrary document. But we can make life a lot easier. Suppose we're reading 3-vectors (i.e., vectors with three components), so we've got a structure looking like this:
```
struct Vec3 {
float x, y, z;
};
```
We can read this in one operation by overloading the extraction (>>) operator:
```
void operator >> (const YAML::Node& node, Vec3& v)
{
node[0] >> v.x;
node[1] >> v.y;
node[2] >> v.z;
}
// now it's a piece of cake to read it
YAML::Node doc; // already parsed
Vec3 v;
doc >> v;
std::cout << "Here's the vector: (" << v.x << ", " << v.y << ", " << v.z << ")\n";
```
# A Complete Example #
Here's a complete example of how to parse a complex YAML file:
`monsters.yaml`
```
- name: Ogre
position: [0, 5, 0]
powers:
- name: Club
damage: 10
- name: Fist
damage: 8
- name: Dragon
position: [1, 0, 10]
powers:
- name: Fire Breath
damage: 25
- name: Claws
damage: 15
- name: Wizard
position: [5, -3, 0]
powers:
- name: Acid Rain
damage: 50
- name: Staff
damage: 3
```
`main.cpp`
```
#include "yaml-cpp/yaml.h"
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
// our data types
struct Vec3 {
float x, y, z;
};
struct Power {
std::string name;
int damage;
};
struct Monster {
std::string name;
Vec3 position;
std::vector <Power> powers;
};
// now the extraction operators for these types
void operator >> (const YAML::Node& node, Vec3& v) {
node[0] >> v.x;
node[1] >> v.y;
node[2] >> v.z;
}
void operator >> (const YAML::Node& node, Power& power) {
node["name"] >> power.name;
node["damage"] >> power.damage;
}
void operator >> (const YAML::Node& node, Monster& monster) {
node["name"] >> monster.name;
node["position"] >> monster.position;
const YAML::Node& powers = node["powers"];
for(unsigned i=0;i<powers.size();i++) {
Power power;
powers[i] >> power;
monster.powers.push_back(power);
}
}
int main()
{
std::ifstream fin("monsters.yaml");
YAML::Parser parser(fin);
YAML::Node doc;
parser.GetNextDocument(doc);
for(unsigned i=0;i<doc.size();i++) {
Monster monster;
doc[i] >> monster;
std::cout << monster.name << "\n";
}
return 0;
}
```
# When Something Goes Wrong #
... we throw an exception (all exceptions are derived from `YAML::Exception`). If there's a parsing exception (i.e., a malformed YAML document), we throw a `YAML::ParserException`:
```
try {
std::ifstream fin("test.yaml");
YAML::Parser parser(fin);
YAML::Node doc;
parser.GetNextDocument(doc);
// do stuff
} catch(YAML::ParserException& e) {
std::cout << e.what() << "\n";
}
```
If you make a programming error (say, trying to read a scalar from a sequence node, or grabbing a key that doesn't exist), we throw some kind of `YAML::RepresentationException`. To prevent this, you can check what kind of node something is:
```
YAML::Node node;
YAML::NodeType::value type = node.Type(); // should be:
// YAML::NodeType::Null
// YAML::NodeType::Scalar
// YAML::NodeType::Sequence
// YAML::NodeType::Map
```
# Note about copying `YAML::Node` #
Currently `YAML::Node` is non-copyable, so you need to do something like
```
const YAML::Node& node = doc["whatever"];
```
This is intended behavior. If you want to copy a node, use the `Clone` function:
```
std::auto_ptr<YAML::Node> pCopy = myOtherNode.Clone();
```
The intent is that if you'd like to keep a `YAML::Node` around for longer than the document will stay in scope, you can clone it and store it as long as you like.
-18
View File
@@ -1,18 +0,0 @@
# Encodings and `yaml-cpp` #
`yaml-cpp` will parse any file as specified by the [YAML 1.2 spec](http://www.yaml.org/spec/1.2/spec.html#id2570322). Internally, it stores all strings in UTF-8, and representation is done with UTF-8. This means that in
```
std::string str;
node >> str;
```
`str` will be UTF-8. Similarly, if you're accessing a map by string key, you need to pass the key in UTF-8. If your application uses a different encoding, you need to convert to and from UTF-8 to work with `yaml-cpp`. (It's possible we'll add some small conversion functions, but for now it's restricted.)
---
For convenience, Richard Weeks has kindly provided a google gadget that converts Unicode to a string literal. It's a Google Gadget, so unfortunately it does not work on GitHub. Patches welcome to port it to a usable format here:
```
<wiki:gadget url="http://hosting.gmodules.com/ig/gadgets/file/111180078345548400783/c-style-utf8-encoder.xml"/>
```
-201
View File
@@ -1,201 +0,0 @@
# Introduction #
A typical example, loading a configuration file, might look like this:
```cpp
YAML::Node config = YAML::LoadFile("config.yaml");
if (config["lastLogin"]) {
std::cout << "Last logged in: " << config["lastLogin"].as<DateTime>() << "\n";
}
const std::string username = config["username"].as<std::string>();
const std::string password = config["password"].as<std::string>();
login(username, password);
config["lastLogin"] = getCurrentDateTime();
std::ofstream fout("config.yaml");
fout << config;
```
# Basic Parsing and Node Editing #
All nodes in a YAML document (including the root) are represented by `YAML::Node`. You can check what kind it is:
```cpp
YAML::Node node = YAML::Load("[1, 2, 3]");
assert(node.Type() == YAML::NodeType::Sequence);
assert(node.IsSequence()); // a shortcut!
```
Collection nodes (sequences and maps) act somewhat like STL vectors and maps:
```cpp
YAML::Node primes = YAML::Load("[2, 3, 5, 7, 11]");
for (std::size_t i=0;i<primes.size();i++) {
std::cout << primes[i].as<int>() << "\n";
}
// or:
for (YAML::const_iterator it=primes.begin();it!=primes.end();++it) {
std::cout << it->as<int>() << "\n";
}
primes.push_back(13);
assert(primes.size() == 6);
```
and
```cpp
YAML::Node lineup = YAML::Load("{1B: Prince Fielder, 2B: Rickie Weeks, LF: Ryan Braun}");
for(YAML::const_iterator it=lineup.begin();it!=lineup.end();++it) {
std::cout << "Playing at " << it->first.as<std::string>() << " is " << it->second.as<std::string>() << "\n";
}
lineup["RF"] = "Corey Hart";
lineup["C"] = "Jonathan Lucroy";
assert(lineup.size() == 5);
```
Querying for keys does **not** create them automatically (this makes handling optional map entries very easy)
```cpp
YAML::Node node = YAML::Load("{name: Brewers, city: Milwaukee}");
if (node["name"]) {
std::cout << node["name"].as<std::string>() << "\n";
}
if (node["mascot"]) {
std::cout << node["mascot"].as<std::string>() << "\n";
}
assert(node.size() == 2); // the previous call didn't create a node
```
If you're not sure what kind of data you're getting, you can query the type of a node:
```cpp
switch (node.Type()) {
case Null: // ...
case Scalar: // ...
case Sequence: // ...
case Map: // ...
case Undefined: // ...
}
```
or ask directly whether it's a particular type, e.g.:
```cpp
if (node.IsSequence()) {
// ...
}
```
# Building Nodes #
You can build `YAML::Node` from scratch:
```cpp
YAML::Node node; // starts out as null
node["key"] = "value"; // it now is a map node
node["seq"].push_back("first element"); // node["seq"] automatically becomes a sequence
node["seq"].push_back("second element");
node["mirror"] = node["seq"][0]; // this creates an alias
node["seq"][0] = "1st element"; // this also changes node["mirror"]
node["mirror"] = "element #1"; // and this changes node["seq"][0] - they're really the "same" node
node["self"] = node; // you can even create self-aliases
node[node["mirror"]] = node["seq"]; // and strange loops :)
```
The above node is now:
```yaml
&1
key: value
&2 seq: [&3 "element #1", second element]
mirror: *3
self: *1
*3 : *2
```
# How Sequences Turn Into Maps #
Sequences can be turned into maps by asking for non-integer keys. For example,
```cpp
YAML::Node node = YAML::Load("[1, 2, 3]");
node[1] = 5; // still a sequence, [1, 5, 3]
node.push_back(-3) // still a sequence, [1, 5, 3, -3]
node["key"] = "value"; // now it's a map! {0: 1, 1: 5, 2: 3, 3: -3, key: value}
```
Indexing a sequence node by an index that's not in its range will _usually_ turn it into a map, but if the index is one past the end of the sequence, then the sequence will grow by one to accommodate it. (That's the **only** exception to this rule.) For example,
```cpp
YAML::Node node = YAML::Load("[1, 2, 3]");
node[3] = 4; // still a sequence, [1, 2, 3, 4]
node[10] = 10; // now it's a map! {0: 1, 1: 2, 2: 3, 3: 4, 10: 10}
```
# Converting To/From Native Data Types #
Yaml-cpp has built-in conversion to and from most built-in data types, as well as `std::vector`, `std::list`, and `std::map`. The following examples demonstrate when those conversions are used:
```cpp
YAML::Node node = YAML::Load("{pi: 3.14159, [0, 1]: integers}");
// this needs the conversion from Node to double
double pi = node["pi"].as<double>();
// this needs the conversion from double to Node
node["e"] = 2.71828;
// this needs the conversion from Node to std::vector<int> (*not* the other way around!)
std::vector<int> v;
v.push_back(0);
v.push_back(1);
std::string str = node[v].as<std::string>();
```
To use yaml-cpp with your own data types, you need to specialize the YAML::convert<> template class. For example, suppose you had a simple `Vec3` class:
```cpp
struct Vec3 { double x, y, z; /* etc - make sure you have overloaded operator== */ };
```
You could write
```cpp
namespace YAML {
template<>
struct convert<Vec3> {
static Node encode(const Vec3& rhs) {
Node node;
node.push_back(rhs.x);
node.push_back(rhs.y);
node.push_back(rhs.z);
return node;
}
static bool decode(const Node& node, Vec3& rhs) {
if(!node.IsSequence() || node.size() != 3) {
return false;
}
rhs.x = node[0].as<double>();
rhs.y = node[1].as<double>();
rhs.z = node[2].as<double>();
return true;
}
};
}
```
Then you could use `Vec3` wherever you could use any other type:
```cpp
YAML::Node node = YAML::Load("start: [1, 3, 0]");
Vec3 v = node["start"].as<Vec3>();
node["end"] = Vec3(2, -1, 0);
```
-1
View File
@@ -1 +0,0 @@
theme: jekyll-theme-slate
-1
View File
@@ -1 +0,0 @@
To learn how to use the library, see the [Tutorial](https://github.com/jbeder/yaml-cpp/wiki/Tutorial) and [How To Emit YAML](https://github.com/jbeder/yaml-cpp/wiki/How-To-Emit-YAML)
+1 -1
View File
@@ -10,7 +10,7 @@
#include <cstddef>
namespace YAML {
using anchor_t = std::size_t;
typedef std::size_t anchor_t;
const anchor_t NullAnchor = 0;
}
+1 -1
View File
@@ -39,7 +39,7 @@ class YAML_CPP_API Binary {
rhs.clear();
rhs.resize(m_unownedSize);
std::copy(m_unownedData, m_unownedData + m_unownedSize, rhs.begin());
m_unownedData = nullptr;
m_unownedData = 0;
m_unownedSize = 0;
} else {
m_data.swap(rhs);
+4 -4
View File
@@ -15,7 +15,7 @@ class Parser;
// GraphBuilderInterface
// . Abstraction of node creation
// . pParentNode is always nullptr or the return value of one of the NewXXX()
// . pParentNode is always NULL or the return value of one of the NewXXX()
// functions.
class GraphBuilderInterface {
public:
@@ -73,9 +73,9 @@ class GraphBuilder : public GraphBuilderInterface {
typedef typename Impl::Map Map;
GraphBuilder(Impl &impl) : m_impl(impl) {
Map *pMap = nullptr;
Sequence *pSeq = nullptr;
Node *pNode = nullptr;
Map *pMap = NULL;
Sequence *pSeq = NULL;
Node *pNode = NULL;
// Type consistency checks
pNode = pMap;
-77
View File
@@ -1,77 +0,0 @@
#ifndef DEPTH_GUARD_H_00000000000000000000000000000000000000000000000000000000
#define DEPTH_GUARD_H_00000000000000000000000000000000000000000000000000000000
#if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once
#endif
#include "exceptions.h"
namespace YAML {
/**
* @brief The DeepRecursion class
* An exception class which is thrown by DepthGuard. Ideally it should be
* a member of DepthGuard. However, DepthGuard is a templated class which means
* that any catch points would then need to know the template parameters. It is
* simpler for clients to not have to know at the catch point what was the
* maximum depth.
*/
class DeepRecursion : public ParserException {
public:
virtual ~DeepRecursion() = default;
DeepRecursion(int depth, const Mark& mark_, const std::string& msg_);
// Returns the recursion depth when the exception was thrown
int depth() const {
return m_depth;
}
private:
int m_depth = 0;
};
/**
* @brief The DepthGuard class
* DepthGuard takes a reference to an integer. It increments the integer upon
* construction of DepthGuard and decrements the integer upon destruction.
*
* If the integer would be incremented past max_depth, then an exception is
* thrown. This is ideally geared toward guarding against deep recursion.
*
* @param max_depth
* compile-time configurable maximum depth.
*/
template <int max_depth = 2000>
class DepthGuard final {
public:
DepthGuard(int & depth_, const Mark& mark_, const std::string& msg_) : m_depth(depth_) {
++m_depth;
if ( max_depth <= m_depth ) {
throw DeepRecursion{m_depth, mark_, msg_};
}
}
DepthGuard(const DepthGuard & copy_ctor) = delete;
DepthGuard(DepthGuard && move_ctor) = delete;
DepthGuard & operator=(const DepthGuard & copy_assign) = delete;
DepthGuard & operator=(DepthGuard && move_assign) = delete;
~DepthGuard() {
--m_depth;
}
int current_depth() const {
return m_depth;
}
private:
int & m_depth;
};
} // namespace YAML
#endif // DEPTH_GUARD_H_00000000000000000000000000000000000000000000000000000000
+26 -52
View File
@@ -1,59 +1,33 @@
#ifndef DLL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define DLL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
// Definition YAML_CPP_STATIC_DEFINE using to building YAML-CPP as static
// library (definition created by CMake or defined manually)
// Definition yaml_cpp_EXPORTS using to building YAML-CPP as dll/so library
// (definition created by CMake or defined manually)
#ifdef YAML_CPP_STATIC_DEFINE
# define YAML_CPP_API
# define YAML_CPP_NO_EXPORT
#else
# if defined(_MSC_VER) || defined(__MINGW32__) || defined(__MINGW64__)
# ifndef YAML_CPP_API
# ifdef yaml_cpp_EXPORTS
/* We are building this library */
# define YAML_CPP_API __declspec(dllexport)
# else
/* We are using this library */
# define YAML_CPP_API __declspec(dllimport)
# endif
# endif
# ifndef YAML_CPP_NO_EXPORT
# define YAML_CPP_NO_EXPORT
# endif
# else /* No _MSC_VER */
# ifndef YAML_CPP_API
# ifdef yaml_cpp_EXPORTS
/* We are building this library */
# define YAML_CPP_API __attribute__((visibility("default")))
# else
/* We are using this library */
# define YAML_CPP_API __attribute__((visibility("default")))
# endif
# endif
# ifndef YAML_CPP_NO_EXPORT
# define YAML_CPP_NO_EXPORT __attribute__((visibility("hidden")))
# endif
# endif /* _MSC_VER */
#endif /* YAML_CPP_STATIC_DEFINE */
#ifndef YAML_CPP_DEPRECATED
# ifdef _MSC_VER
# define YAML_CPP_DEPRECATED __declspec(deprecated)
# else
# define YAML_CPP_DEPRECATED __attribute__ ((__deprecated__))
# endif
#if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once
#endif
#ifndef YAML_CPP_DEPRECATED_EXPORT
# define YAML_CPP_DEPRECATED_EXPORT YAML_CPP_API YAML_CPP_DEPRECATED
#endif
// The following ifdef block is the standard way of creating macros which make
// exporting from a DLL simpler. All files within this DLL are compiled with the
// yaml_cpp_EXPORTS symbol defined on the command line. This symbol should not
// be defined on any project that uses this DLL. This way any other project
// whose source files include this file see YAML_CPP_API functions as being
// imported from a DLL, whereas this DLL sees symbols defined with this macro as
// being exported.
#undef YAML_CPP_API
#ifndef YAML_CPP_DEPRECATED_NO_EXPORT
# define YAML_CPP_DEPRECATED_NO_EXPORT YAML_CPP_NO_EXPORT YAML_CPP_DEPRECATED
#endif
#ifdef YAML_CPP_DLL // Using or Building YAML-CPP DLL (definition defined
// manually)
#ifdef yaml_cpp_EXPORTS // Building YAML-CPP DLL (definition created by CMake
// or defined manually)
// #pragma message( "Defining YAML_CPP_API for DLL export" )
#define YAML_CPP_API __declspec(dllexport)
#else // yaml_cpp_EXPORTS
// #pragma message( "Defining YAML_CPP_API for DLL import" )
#define YAML_CPP_API __declspec(dllimport)
#endif // yaml_cpp_EXPORTS
#else // YAML_CPP_DLL
#define YAML_CPP_API
#endif // YAML_CPP_DLL
#endif /* DLL_H_62B23520_7C8E_11DE_8A39_0800200C9A66 */
#endif // DLL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+12 -13
View File
@@ -23,23 +23,22 @@ class Emitter;
class EmitFromEvents : public EventHandler {
public:
EmitFromEvents(Emitter& emitter);
~EmitFromEvents() override = default;
void OnDocumentStart(const Mark& mark) override;
void OnDocumentEnd() override;
virtual void OnDocumentStart(const Mark& mark);
virtual void OnDocumentEnd();
void OnNull(const Mark& mark, anchor_t anchor) override;
void OnAlias(const Mark& mark, anchor_t anchor) override;
void OnScalar(const Mark& mark, const std::string& tag,
anchor_t anchor, const std::string& value) override;
virtual void OnNull(const Mark& mark, anchor_t anchor);
virtual void OnAlias(const Mark& mark, anchor_t anchor);
virtual void OnScalar(const Mark& mark, const std::string& tag,
anchor_t anchor, const std::string& value);
void OnSequenceStart(const Mark& mark, const std::string& tag,
anchor_t anchor, EmitterStyle::value style) override;
void OnSequenceEnd() override;
virtual void OnSequenceStart(const Mark& mark, const std::string& tag,
anchor_t anchor, EmitterStyle::value style);
virtual void OnSequenceEnd();
void OnMapStart(const Mark& mark, const std::string& tag,
anchor_t anchor, EmitterStyle::value style) override;
void OnMapEnd() override;
virtual void OnMapStart(const Mark& mark, const std::string& tag,
anchor_t anchor, EmitterStyle::value style);
virtual void OnMapEnd();
private:
void BeginNode();
+4 -60
View File
@@ -7,18 +7,10 @@
#pragma once
#endif
#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"
@@ -26,7 +18,6 @@
#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;
@@ -56,7 +47,6 @@ class YAML_CPP_API Emitter {
bool SetOutputCharset(EMITTER_MANIP value);
bool SetStringFormat(EMITTER_MANIP value);
bool SetBoolFormat(EMITTER_MANIP value);
bool SetNullFormat(EMITTER_MANIP value);
bool SetIntBase(EMITTER_MANIP value);
bool SetSeqFormat(EMITTER_MANIP value);
bool SetMapFormat(EMITTER_MANIP value);
@@ -65,17 +55,13 @@ class YAML_CPP_API Emitter {
bool SetPostCommentIndent(std::size_t n);
bool SetFloatPrecision(std::size_t n);
bool SetDoublePrecision(std::size_t n);
bool SetShowTrailingZero(bool value);
void RestoreGlobalModifiedSettings();
// local setters
Emitter& SetLocalValue(EMITTER_MANIP value);
Emitter& SetLocalIndent(const _Indent& indent);
Emitter& SetLocalWrap(const _Wrap& wrap);
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);
@@ -97,7 +83,6 @@ class YAML_CPP_API Emitter {
void SetStreamablePrecision(std::stringstream&) {}
std::size_t GetFloatPrecision() const;
std::size_t GetDoublePrecision() const;
bool GetShowTrailingZero() const;
void PrepareIntegralStream(std::stringstream& stream) const;
void StartedScalar();
@@ -135,7 +120,6 @@ class YAML_CPP_API Emitter {
void SpaceOrIndentTo(bool requireSpace, std::size_t indent);
const char* ComputeFullBoolName(bool b) const;
const char* ComputeNullName() const;
bool CanEmitNewline() const;
private:
@@ -151,7 +135,6 @@ inline Emitter& Emitter::WriteIntegralType(T value) {
PrepareNode(EmitterNodeType::Scalar);
std::stringstream stream;
stream.imbue(std::locale::classic());
PrepareIntegralStream(stream);
stream << value;
m_stream << stream.str();
@@ -169,38 +152,8 @@ inline Emitter& Emitter::WriteStreamable(T value) {
PrepareNode(EmitterNodeType::Scalar);
std::stringstream stream;
stream.imbue(std::locale::classic());
SetStreamablePrecision<T>(stream);
bool special = false;
if (std::is_floating_point<T>::value) {
if ((std::numeric_limits<T>::has_quiet_NaN ||
std::numeric_limits<T>::has_signaling_NaN) &&
std::isnan(value)) {
special = true;
stream << ".nan";
} else if (std::numeric_limits<T>::has_infinity && std::isinf(value)) {
special = true;
if (std::signbit(value)) {
stream << "-.inf";
} else {
stream << ".inf";
}
}
}
if (!special) {
auto value_as_str = FpToString(value, static_cast<size_t>(stream.precision()));
if (GetShowTrailingZero()) {
bool isInScientificNotation = (value_as_str.find('e') != std::string::npos);
bool hasDot = (value_as_str.find('.') != std::string::npos);
if (!isInScientificNotation && !hasDot) {
value_as_str += ".0";
}
}
stream << value_as_str;
}
stream << value;
m_stream << stream.str();
StartedScalar();
@@ -219,13 +172,8 @@ 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.data(), v.size());
return emitter.Write(v);
}
inline Emitter& operator<<(Emitter& emitter, bool v) {
return emitter.Write(v);
@@ -234,7 +182,7 @@ inline Emitter& operator<<(Emitter& emitter, char v) {
return emitter.Write(v);
}
inline Emitter& operator<<(Emitter& emitter, unsigned char v) {
return emitter.WriteIntegralType(static_cast<unsigned int>(v));
return emitter.Write(static_cast<char>(v));
}
inline Emitter& operator<<(Emitter& emitter, const _Alias& v) {
return emitter.Write(v);
@@ -256,7 +204,7 @@ inline Emitter& operator<<(Emitter& emitter, const Binary& b) {
}
inline Emitter& operator<<(Emitter& emitter, const char* v) {
return emitter.Write(v, std::strlen(v));
return emitter.Write(std::string(v));
}
inline Emitter& operator<<(Emitter& emitter, int v) {
@@ -299,10 +247,6 @@ inline Emitter& operator<<(Emitter& emitter, _Indent indent) {
return emitter.SetLocalIndent(indent);
}
inline Emitter& operator<<(Emitter& emitter, _Wrap wrap) {
return emitter.SetLocalWrap(wrap);
}
inline Emitter& operator<<(Emitter& emitter, _Precision precision) {
return emitter.SetLocalPrecision(precision);
}
+6 -20
View File
@@ -19,7 +19,6 @@ enum EMITTER_MANIP {
// output character set
EmitNonAscii,
EscapeNonAscii,
EscapeAsJson,
// string manipulators
// Auto, // duplicate
@@ -27,12 +26,6 @@ enum EMITTER_MANIP {
DoubleQuoted,
Literal,
// null manipulators
LowerNull,
UpperNull,
CamelNull,
TildeNull,
// bool manipulators
YesNoBool, // yes, no
TrueFalseBool, // true, false
@@ -76,26 +69,19 @@ struct _Indent {
inline _Indent Indent(int value) { return _Indent(value); }
struct _Wrap {
_Wrap(int value_) : value(value_) {}
int value;
};
inline _Wrap Wrap(int value) { return _Wrap(value); }
struct _Alias {
_Alias(const std::string& content_) : content(content_) {}
std::string content;
};
inline _Alias Alias(const std::string& content) { return _Alias(content); }
inline _Alias Alias(const std::string content) { return _Alias(content); }
struct _Anchor {
_Anchor(const std::string& content_) : content(content_) {}
std::string content;
};
inline _Anchor Anchor(const std::string& content) { return _Anchor(content); }
inline _Anchor Anchor(const std::string content) { return _Anchor(content); }
struct _Tag {
struct Type {
@@ -110,11 +96,11 @@ struct _Tag {
Type::value type;
};
inline _Tag VerbatimTag(const std::string& content) {
inline _Tag VerbatimTag(const std::string content) {
return _Tag("", content, _Tag::Type::Verbatim);
}
inline _Tag LocalTag(const std::string& content) {
inline _Tag LocalTag(const std::string content) {
return _Tag("", content, _Tag::Type::PrimaryHandle);
}
@@ -122,7 +108,7 @@ inline _Tag LocalTag(const std::string& prefix, const std::string content) {
return _Tag(prefix, content, _Tag::Type::NamedHandle);
}
inline _Tag SecondaryTag(const std::string& content) {
inline _Tag SecondaryTag(const std::string content) {
return _Tag("", content, _Tag::Type::NamedHandle);
}
@@ -131,7 +117,7 @@ struct _Comment {
std::string content;
};
inline _Comment Comment(const std::string& content) { return _Comment(content); }
inline _Comment Comment(const std::string content) { return _Comment(content); }
struct _Precision {
_Precision(int floatPrecision_, int doublePrecision_)
+3 -4
View File
@@ -8,10 +8,9 @@
#endif
namespace YAML {
namespace EmitterStyle {
enum value { Default, Block, Flow };
}
struct EmitterStyle {
enum value { Default, Block, Flow };
};
}
#endif // EMITTERSTYLE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+1 -1
View File
@@ -17,7 +17,7 @@ struct Mark;
class EventHandler {
public:
virtual ~EventHandler() = default;
virtual ~EventHandler() {}
virtual void OnDocumentStart(const Mark& mark) = 0;
virtual void OnDocumentEnd() = 0;
+31 -96
View File
@@ -8,12 +8,19 @@
#endif
#include "yaml-cpp/mark.h"
#include "yaml-cpp/noexcept.h"
#include "yaml-cpp/traits.h"
#include <sstream>
#include <stdexcept>
#include <string>
// This is here for compatibility with older versions of Visual Studio
// which don't support noexcept
#if defined(_MSC_VER) && _MSC_VER < 1900
#define YAML_CPP_NOEXCEPT _NOEXCEPT
#else
#define YAML_CPP_NOEXCEPT noexcept
#endif
namespace YAML {
// error messages
namespace ErrorMsg {
@@ -48,8 +55,6 @@ 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";
@@ -67,7 +72,7 @@ const char* const ZERO_INDENT_IN_BLOCK =
const char* const CHAR_IN_BLOCK = "unexpected character in block scalar";
const char* const AMBIGUOUS_ANCHOR =
"cannot assign the same alias to multiple nodes";
const char* const UNKNOWN_ANCHOR = "the referenced anchor is not defined: ";
const char* const UNKNOWN_ANCHOR = "the referenced anchor is not defined";
const char* const INVALID_NODE =
"invalid node; this may result from using a map iterator as a sequence "
@@ -89,8 +94,6 @@ const char* const INVALID_ANCHOR = "invalid anchor";
const char* const INVALID_ALIAS = "invalid alias";
const char* const INVALID_TAG = "invalid tag";
const char* const BAD_FILE = "bad file";
const char* const UNEXPECTED_TOKEN_AFTER_DOC = "unexpected token after end of document";
const char* const NON_UNIQUE_MAP_KEY = "map keys must be unique";
template <typename T>
inline const std::string KEY_NOT_FOUND_WITH_KEY(
@@ -104,12 +107,6 @@ inline const std::string KEY_NOT_FOUND_WITH_KEY(const std::string& key) {
return stream.str();
}
inline const std::string KEY_NOT_FOUND_WITH_KEY(const char* key) {
std::stringstream stream;
stream << KEY_NOT_FOUND << ": " << key;
return stream.str();
}
template <typename T>
inline const std::string KEY_NOT_FOUND_WITH_KEY(
const T& key, typename enable_if<is_numeric<T>>::type* = 0) {
@@ -117,48 +114,13 @@ inline const std::string KEY_NOT_FOUND_WITH_KEY(
stream << KEY_NOT_FOUND << ": " << key;
return stream.str();
}
template <typename T>
inline const std::string BAD_SUBSCRIPT_WITH_KEY(
const T&, typename disable_if<is_numeric<T>>::type* = nullptr) {
return BAD_SUBSCRIPT;
}
inline const std::string BAD_SUBSCRIPT_WITH_KEY(const std::string& key) {
std::stringstream stream;
stream << BAD_SUBSCRIPT << " (key: \"" << key << "\")";
return stream.str();
}
inline const std::string BAD_SUBSCRIPT_WITH_KEY(const char* key) {
std::stringstream stream;
stream << BAD_SUBSCRIPT << " (key: \"" << key << "\")";
return stream.str();
}
template <typename T>
inline const std::string BAD_SUBSCRIPT_WITH_KEY(
const T& key, typename enable_if<is_numeric<T>>::type* = nullptr) {
std::stringstream stream;
stream << BAD_SUBSCRIPT << " (key: \"" << key << "\")";
return stream.str();
}
inline const std::string INVALID_NODE_WITH_KEY(const std::string& key) {
std::stringstream stream;
if (key.empty()) {
return INVALID_NODE;
}
stream << "invalid node; first invalid key: \"" << key << "\"";
return stream.str();
}
} // namespace ErrorMsg
class YAML_CPP_API Exception : public std::runtime_error {
public:
Exception(const Mark& mark_, const std::string& msg_)
: std::runtime_error(build_what(mark_, msg_)), mark(mark_), msg(msg_) {}
~Exception() YAML_CPP_NOEXCEPT override;
virtual ~Exception() YAML_CPP_NOEXCEPT;
Exception(const Exception&) = default;
@@ -169,7 +131,7 @@ class YAML_CPP_API Exception : public std::runtime_error {
static const std::string build_what(const Mark& mark,
const std::string& msg) {
if (mark.is_null()) {
return msg;
return msg.c_str();
}
std::stringstream output;
@@ -184,7 +146,7 @@ class YAML_CPP_API ParserException : public Exception {
ParserException(const Mark& mark_, const std::string& msg_)
: Exception(mark_, msg_) {}
ParserException(const ParserException&) = default;
~ParserException() YAML_CPP_NOEXCEPT override;
virtual ~ParserException() YAML_CPP_NOEXCEPT;
};
class YAML_CPP_API RepresentationException : public Exception {
@@ -192,7 +154,7 @@ class YAML_CPP_API RepresentationException : public Exception {
RepresentationException(const Mark& mark_, const std::string& msg_)
: Exception(mark_, msg_) {}
RepresentationException(const RepresentationException&) = default;
~RepresentationException() YAML_CPP_NOEXCEPT override;
virtual ~RepresentationException() YAML_CPP_NOEXCEPT;
};
// representation exceptions
@@ -201,7 +163,7 @@ class YAML_CPP_API InvalidScalar : public RepresentationException {
InvalidScalar(const Mark& mark_)
: RepresentationException(mark_, ErrorMsg::INVALID_SCALAR) {}
InvalidScalar(const InvalidScalar&) = default;
~InvalidScalar() YAML_CPP_NOEXCEPT override;
virtual ~InvalidScalar() YAML_CPP_NOEXCEPT;
};
class YAML_CPP_API KeyNotFound : public RepresentationException {
@@ -211,7 +173,7 @@ class YAML_CPP_API KeyNotFound : public RepresentationException {
: RepresentationException(mark_, ErrorMsg::KEY_NOT_FOUND_WITH_KEY(key_)) {
}
KeyNotFound(const KeyNotFound&) = default;
~KeyNotFound() YAML_CPP_NOEXCEPT override;
virtual ~KeyNotFound() YAML_CPP_NOEXCEPT;
};
template <typename T>
@@ -219,7 +181,7 @@ class YAML_CPP_API TypedKeyNotFound : public KeyNotFound {
public:
TypedKeyNotFound(const Mark& mark_, const T& key_)
: KeyNotFound(mark_, key_), key(key_) {}
~TypedKeyNotFound() YAML_CPP_NOEXCEPT override = default;
virtual ~TypedKeyNotFound() YAML_CPP_NOEXCEPT {}
T key;
};
@@ -232,11 +194,10 @@ inline TypedKeyNotFound<T> MakeTypedKeyNotFound(const Mark& mark,
class YAML_CPP_API InvalidNode : public RepresentationException {
public:
InvalidNode(const std::string& key)
: RepresentationException(Mark::null_mark(),
ErrorMsg::INVALID_NODE_WITH_KEY(key)) {}
InvalidNode()
: RepresentationException(Mark::null_mark(), ErrorMsg::INVALID_NODE) {}
InvalidNode(const InvalidNode&) = default;
~InvalidNode() YAML_CPP_NOEXCEPT override;
virtual ~InvalidNode() YAML_CPP_NOEXCEPT;
};
class YAML_CPP_API BadConversion : public RepresentationException {
@@ -244,7 +205,7 @@ class YAML_CPP_API BadConversion : public RepresentationException {
explicit BadConversion(const Mark& mark_)
: RepresentationException(mark_, ErrorMsg::BAD_CONVERSION) {}
BadConversion(const BadConversion&) = default;
~BadConversion() YAML_CPP_NOEXCEPT override;
virtual ~BadConversion() YAML_CPP_NOEXCEPT;
};
template <typename T>
@@ -258,16 +219,15 @@ class YAML_CPP_API BadDereference : public RepresentationException {
BadDereference()
: RepresentationException(Mark::null_mark(), ErrorMsg::BAD_DEREFERENCE) {}
BadDereference(const BadDereference&) = default;
~BadDereference() YAML_CPP_NOEXCEPT override;
virtual ~BadDereference() YAML_CPP_NOEXCEPT;
};
class YAML_CPP_API BadSubscript : public RepresentationException {
public:
template <typename Key>
BadSubscript(const Mark& mark_, const Key& key)
: RepresentationException(mark_, ErrorMsg::BAD_SUBSCRIPT_WITH_KEY(key)) {}
BadSubscript()
: RepresentationException(Mark::null_mark(), ErrorMsg::BAD_SUBSCRIPT) {}
BadSubscript(const BadSubscript&) = default;
~BadSubscript() YAML_CPP_NOEXCEPT override;
virtual ~BadSubscript() YAML_CPP_NOEXCEPT;
};
class YAML_CPP_API BadPushback : public RepresentationException {
@@ -275,7 +235,7 @@ class YAML_CPP_API BadPushback : public RepresentationException {
BadPushback()
: RepresentationException(Mark::null_mark(), ErrorMsg::BAD_PUSHBACK) {}
BadPushback(const BadPushback&) = default;
~BadPushback() YAML_CPP_NOEXCEPT override;
virtual ~BadPushback() YAML_CPP_NOEXCEPT;
};
class YAML_CPP_API BadInsert : public RepresentationException {
@@ -283,7 +243,7 @@ class YAML_CPP_API BadInsert : public RepresentationException {
BadInsert()
: RepresentationException(Mark::null_mark(), ErrorMsg::BAD_INSERT) {}
BadInsert(const BadInsert&) = default;
~BadInsert() YAML_CPP_NOEXCEPT override;
virtual ~BadInsert() YAML_CPP_NOEXCEPT;
};
class YAML_CPP_API EmitterException : public Exception {
@@ -291,42 +251,17 @@ class YAML_CPP_API EmitterException : public Exception {
EmitterException(const std::string& msg_)
: Exception(Mark::null_mark(), msg_) {}
EmitterException(const EmitterException&) = default;
~EmitterException() YAML_CPP_NOEXCEPT override;
virtual ~EmitterException() YAML_CPP_NOEXCEPT;
};
class YAML_CPP_API BadFile : public Exception {
public:
explicit BadFile(const std::string& filename)
: Exception(Mark::null_mark(),
std::string(ErrorMsg::BAD_FILE) + ": " + filename) {}
BadFile() : Exception(Mark::null_mark(), ErrorMsg::BAD_FILE) {}
BadFile(const BadFile&) = default;
~BadFile() YAML_CPP_NOEXCEPT override;
virtual ~BadFile() YAML_CPP_NOEXCEPT;
};
}
class YAML_CPP_API NonUniqueMapKey : public RepresentationException {
public:
template <typename Key>
NonUniqueMapKey(const Mark& mark_, const Key& /*key*/)
: RepresentationException(mark_, ErrorMsg::NON_UNIQUE_MAP_KEY) {}
NonUniqueMapKey(const NonUniqueMapKey&) = default;
~NonUniqueMapKey() YAML_CPP_NOEXCEPT override;
};
} // namespace YAML
#if defined(_MSC_VER)
#define YAML_ATTRIBUTE_NO_SANITIZE_ADDRESS __declspec(no_sanitize_address)
#elif defined(__has_cpp_attribute) && __has_cpp_attribute(gnu::no_sanitize)
#define YAML_ATTRIBUTE_NO_SANITIZE_ADDRESS [[gnu::no_sanitize("address")]]
#elif defined(__has_cpp_attribute) && __has_cpp_attribute(clang::no_sanitize)
#define YAML_ATTRIBUTE_NO_SANITIZE_ADDRESS [[clang::no_sanitize("address")]]
#elif defined(__has_attribute) && __has_attribute(no_sanitize)
#define YAML_ATTRIBUTE_NO_SANITIZE_ADDRESS \
__attribute__((no_sanitize("address")))
#elif defined(__has_attribute) && __has_attribute(no_sanitize_address)
#define YAML_ATTRIBUTE_NO_SANITIZE_ADDRESS __attribute__((no_sanitize_address))
#else
#define YAML_ATTRIBUTE_NO_SANITIZE_ADDRESS
#endif
#undef YAML_CPP_NOEXCEPT
#endif // EXCEPTIONS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
-15
View File
@@ -1,15 +0,0 @@
#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
+70 -246
View File
@@ -8,29 +8,18 @@
#endif
#include <array>
#include <cmath>
#include <limits>
#include <list>
#include <map>
#include <unordered_map>
#include <unordered_set>
#include <sstream>
#include <type_traits>
#include <valarray>
#include <vector>
#if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || __cplusplus >= 201703L)
#include <string_view>
#endif
#include "yaml-cpp/binary.h"
#include "yaml-cpp/node/impl.h"
#include "yaml-cpp/node/iterator.h"
#include "yaml-cpp/node/node.h"
#include "yaml-cpp/node/type.h"
#include "yaml-cpp/null.h"
#include "yaml-cpp/fptostring.h"
namespace YAML {
class Binary;
@@ -82,33 +71,14 @@ struct convert<std::string> {
// C-strings can only be encoded
template <>
struct convert<const char*> {
static Node encode(const char* rhs) { return Node(rhs); }
};
template <>
struct convert<char*> {
static Node encode(const char* rhs) { return Node(rhs); }
static Node encode(const char*& rhs) { return Node(rhs); }
};
template <std::size_t N>
struct convert<char[N]> {
static Node encode(const char* rhs) { return Node(rhs); }
struct convert<const char[N]> {
static Node encode(const char(&rhs)[N]) { return Node(rhs); }
};
#if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || __cplusplus >= 201703L)
template <>
struct convert<std::string_view> {
static Node encode(std::string_view rhs) { return Node(std::string(rhs)); }
static bool decode(const Node& node, std::string_view& rhs) {
if (!node.IsScalar())
return false;
rhs = node.Scalar();
return true;
}
};
#endif
template <>
struct convert<_Null> {
static Node encode(const _Null& /* rhs */) { return Node(); }
@@ -118,109 +88,43 @@ struct convert<_Null> {
}
};
namespace conversion {
template <typename T>
typename std::enable_if< std::is_floating_point<T>::value, void>::type
inner_encode(const T& rhs, std::stringstream& stream){
if (std::isnan(rhs)) {
stream << ".nan";
} else if (std::isinf(rhs)) {
if (std::signbit(rhs)) {
stream << "-.inf";
} else {
stream << ".inf";
}
} else {
stream << FpToString(rhs, static_cast<size_t>(stream.precision()));
}
}
template <typename T>
typename std::enable_if<!std::is_floating_point<T>::value, void>::type
inner_encode(const T& rhs, std::stringstream& stream){
stream << rhs;
}
template <typename T>
typename std::enable_if<(std::is_same<T, unsigned char>::value ||
std::is_same<T, signed char>::value), bool>::type
ConvertStreamTo(std::stringstream& stream, T& rhs) {
int num;
if ((stream >> std::noskipws >> num) && (stream >> std::ws).eof()) {
if (num >= (std::numeric_limits<T>::min)() &&
num <= (std::numeric_limits<T>::max)()) {
rhs = static_cast<T>(num);
return true;
}
}
return false;
}
template <typename T>
typename std::enable_if<!(std::is_same<T, unsigned char>::value ||
std::is_same<T, signed char>::value), bool>::type
ConvertStreamTo(std::stringstream& stream, T& rhs) {
if ((stream >> std::noskipws >> rhs) && (stream >> std::ws).eof()) {
return true;
}
return false;
}
// Rewrite a valid YAML 1.2 octal scalar ("0o14") to the stream-parseable "014".
inline std::string NormalizeOctalPrefix(std::string s) {
if (s.size() > 2 && s[0] == '0' && (s[1] == 'o' || s[1] == 'O') &&
s.find_first_not_of("01234567", 2) == std::string::npos) {
s.erase(1, 1);
}
return s;
}
}
#define YAML_DEFINE_CONVERT_STREAMABLE(type, negative_op) \
template <> \
struct convert<type> { \
\
static Node encode(const type& rhs) { \
std::stringstream stream; \
stream.imbue(std::locale::classic()); \
stream.precision(std::numeric_limits<type>::max_digits10); \
conversion::inner_encode(rhs, stream); \
return Node(stream.str()); \
} \
\
static bool decode(const Node& node, type& rhs) { \
if (node.Type() != NodeType::Scalar) { \
return false; \
} \
const std::string& input = node.Scalar(); \
std::stringstream stream(conversion::NormalizeOctalPrefix(input)); \
stream.imbue(std::locale::classic()); \
stream.unsetf(std::ios::dec); \
if ((stream.peek() == '-') && std::is_unsigned<type>::value) { \
return false; \
} \
if (conversion::ConvertStreamTo(stream, rhs)) { \
return true; \
} \
if (std::numeric_limits<type>::has_infinity) { \
if (conversion::IsInfinity(input)) { \
rhs = std::numeric_limits<type>::infinity(); \
return true; \
} else if (conversion::IsNegativeInfinity(input)) { \
rhs = negative_op std::numeric_limits<type>::infinity(); \
return true; \
} \
} \
\
if (std::numeric_limits<type>::has_quiet_NaN) { \
if (conversion::IsNaN(input)) { \
rhs = std::numeric_limits<type>::quiet_NaN(); \
return true; \
} \
} \
\
return false; \
} \
#define YAML_DEFINE_CONVERT_STREAMABLE(type, negative_op) \
template <> \
struct convert<type> { \
static Node encode(const type& rhs) { \
std::stringstream stream; \
stream.precision(std::numeric_limits<type>::max_digits10); \
stream << rhs; \
return Node(stream.str()); \
} \
\
static bool decode(const Node& node, type& rhs) { \
if (node.Type() != NodeType::Scalar) \
return false; \
const std::string& input = node.Scalar(); \
std::stringstream stream(input); \
stream.unsetf(std::ios::dec); \
if ((stream >> std::noskipws >> rhs) && (stream >> std::ws).eof()) \
return true; \
if (std::numeric_limits<type>::has_infinity) { \
if (conversion::IsInfinity(input)) { \
rhs = std::numeric_limits<type>::infinity(); \
return true; \
} else if (conversion::IsNegativeInfinity(input)) { \
rhs = negative_op std::numeric_limits<type>::infinity(); \
return true; \
} \
} \
\
if (std::numeric_limits<type>::has_quiet_NaN) { \
if (conversion::IsNaN(input)) { \
rhs = std::numeric_limits<type>::quiet_NaN(); \
return true; \
} \
} \
\
return false; \
} \
}
#define YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(type) \
@@ -259,130 +163,81 @@ struct convert<bool> {
};
// std::map
template <typename K, typename V, typename C, typename A>
struct convert<std::map<K, V, C, A>> {
static Node encode(const std::map<K, V, C, A>& rhs) {
template <typename K, typename V>
struct convert<std::map<K, V>> {
static Node encode(const std::map<K, V>& rhs) {
Node node(NodeType::Map);
for (const auto& element : rhs)
node.force_insert(element.first, element.second);
for (typename std::map<K, V>::const_iterator it = rhs.begin();
it != rhs.end(); ++it)
node.force_insert(it->first, it->second);
return node;
}
static bool decode(const Node& node, std::map<K, V, C, A>& rhs) {
static bool decode(const Node& node, std::map<K, V>& rhs) {
if (!node.IsMap())
return false;
rhs.clear();
for (const auto& element : node)
for (const_iterator it = node.begin(); it != node.end(); ++it)
#if defined(__GNUC__) && __GNUC__ < 4
// workaround for GCC 3:
rhs[element.first.template as<K>()] = element.second.template as<V>();
rhs[it->first.template as<K>()] = it->second.template as<V>();
#else
rhs[element.first.as<K>()] = element.second.as<V>();
#endif
return true;
}
};
// std::unordered_map
template <typename K, typename V, typename H, typename P, typename A>
struct convert<std::unordered_map<K, V, H, P, A>> {
static Node encode(const std::unordered_map<K, V, H, P, A>& rhs) {
Node node(NodeType::Map);
for (const auto& element : rhs)
node.force_insert(element.first, element.second);
return node;
}
static bool decode(const Node& node, std::unordered_map<K, V, H, P, A>& rhs) {
if (!node.IsMap())
return false;
rhs.clear();
for (const auto& element : node)
#if defined(__GNUC__) && __GNUC__ < 4
// workaround for GCC 3:
rhs[element.first.template as<K>()] = element.second.template as<V>();
#else
rhs[element.first.as<K>()] = element.second.as<V>();
#endif
return true;
}
};
// std::unordered_set
template <typename T, typename H, typename P, typename A>
struct convert<std::unordered_set<T, H, P, A>> {
static Node encode(const std::unordered_set<T, H, P, A>& rhs) {
Node node(NodeType::Sequence);
for (const auto& element : rhs)
node.push_back(element);
return node;
}
static bool decode(const Node& node, std::unordered_set<T, H, P, A>& rhs) {
if (!node.IsSequence())
return false;
rhs.clear();
for (const auto& element : node)
#if defined(__GNUC__) && __GNUC__ < 4
// workaround for GCC 3:
rhs.insert(element.template as<T>());
#else
rhs.insert(element.as<T>());
rhs[it->first.as<K>()] = it->second.as<V>();
#endif
return true;
}
};
// std::vector
template <typename T, typename A>
struct convert<std::vector<T, A>> {
static Node encode(const std::vector<T, A>& rhs) {
template <typename T>
struct convert<std::vector<T>> {
static Node encode(const std::vector<T>& rhs) {
Node node(NodeType::Sequence);
for (const auto& element : rhs)
node.push_back(element);
for (typename std::vector<T>::const_iterator it = rhs.begin();
it != rhs.end(); ++it)
node.push_back(*it);
return node;
}
static bool decode(const Node& node, std::vector<T, A>& rhs) {
static bool decode(const Node& node, std::vector<T>& rhs) {
if (!node.IsSequence())
return false;
rhs.clear();
for (const auto& element : node)
for (const_iterator it = node.begin(); it != node.end(); ++it)
#if defined(__GNUC__) && __GNUC__ < 4
// workaround for GCC 3:
rhs.push_back(element.template as<T>());
rhs.push_back(it->template as<T>());
#else
rhs.push_back(element.as<T>());
rhs.push_back(it->as<T>());
#endif
return true;
}
};
// std::list
template <typename T, typename A>
struct convert<std::list<T,A>> {
static Node encode(const std::list<T,A>& rhs) {
template <typename T>
struct convert<std::list<T>> {
static Node encode(const std::list<T>& rhs) {
Node node(NodeType::Sequence);
for (const auto& element : rhs)
node.push_back(element);
for (typename std::list<T>::const_iterator it = rhs.begin();
it != rhs.end(); ++it)
node.push_back(*it);
return node;
}
static bool decode(const Node& node, std::list<T,A>& rhs) {
static bool decode(const Node& node, std::list<T>& rhs) {
if (!node.IsSequence())
return false;
rhs.clear();
for (const auto& element : node)
for (const_iterator it = node.begin(); it != node.end(); ++it)
#if defined(__GNUC__) && __GNUC__ < 4
// workaround for GCC 3:
rhs.push_back(element.template as<T>());
rhs.push_back(it->template as<T>());
#else
rhs.push_back(element.as<T>());
rhs.push_back(it->as<T>());
#endif
return true;
}
@@ -421,37 +276,6 @@ struct convert<std::array<T, N>> {
}
};
// std::valarray
template <typename T>
struct convert<std::valarray<T>> {
static Node encode(const std::valarray<T>& rhs) {
Node node(NodeType::Sequence);
for (const auto& element : rhs) {
node.push_back(element);
}
return node;
}
static bool decode(const Node& node, std::valarray<T>& rhs) {
if (!node.IsSequence()) {
return false;
}
rhs.resize(node.size());
for (auto i = 0u; i < node.size(); ++i) {
#if defined(__GNUC__) && __GNUC__ < 4
// workaround for GCC 3:
rhs[i] = node[i].template as<T>();
#else
rhs[i] = node[i].as<T>();
#endif
}
return true;
}
};
// std::pair
template <typename T, typename U>
struct convert<std::pair<T, U>> {
+26
View File
@@ -0,0 +1,26 @@
#ifndef NODE_DETAIL_BOOL_TYPE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define NODE_DETAIL_BOOL_TYPE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once
#endif
namespace YAML {
namespace detail {
struct unspecified_bool {
struct NOT_ALLOWED;
static void true_value(NOT_ALLOWED*) {}
};
typedef void (*unspecified_bool_type)(unspecified_bool::NOT_ALLOWED*);
}
}
#define YAML_CPP_OPERATOR_BOOL() \
operator YAML::detail::unspecified_bool_type() const { \
return this->operator!() ? 0 \
: &YAML::detail::unspecified_bool::true_value; \
}
#endif // NODE_DETAIL_BOOL_TYPE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+33 -50
View File
@@ -9,8 +9,6 @@
#include "yaml-cpp/node/detail/node.h"
#include "yaml-cpp/node/detail/node_data.h"
#include <algorithm>
#include <type_traits>
namespace YAML {
@@ -19,7 +17,7 @@ template <typename Key, typename Enable = void>
struct get_idx {
static node* get(const std::vector<node*>& /* sequence */,
const Key& /* key */, shared_memory_holder /* pMemory */) {
return nullptr;
return 0;
}
};
@@ -29,13 +27,13 @@ struct get_idx<Key,
!std::is_same<Key, bool>::value>::type> {
static node* get(const std::vector<node*>& sequence, const Key& key,
shared_memory_holder /* pMemory */) {
return key < sequence.size() ? sequence[key] : nullptr;
return key < sequence.size() ? sequence[key] : 0;
}
static node* get(std::vector<node*>& sequence, const Key& key,
shared_memory_holder pMemory) {
if (key > sequence.size() || (key > 0 && !sequence[key - 1]->is_defined()))
return nullptr;
return 0;
if (key == sequence.size())
sequence.push_back(&pMemory->create_node());
return sequence[key];
@@ -43,26 +41,24 @@ struct get_idx<Key,
};
template <typename Key>
struct get_idx<Key, typename std::enable_if<std::is_signed<Key>::value && std::is_integral<Key>::value>::type> {
struct get_idx<Key, typename std::enable_if<std::is_signed<Key>::value>::type> {
static node* get(const std::vector<node*>& sequence, const Key& key,
shared_memory_holder pMemory) {
return key >= 0 ? get_idx<std::size_t>::get(
sequence, static_cast<std::size_t>(key), pMemory)
: nullptr;
: 0;
}
static node* get(std::vector<node*>& sequence, const Key& key,
shared_memory_holder pMemory) {
return key >= 0 ? get_idx<std::size_t>::get(
sequence, static_cast<std::size_t>(key), pMemory)
: nullptr;
: 0;
}
};
template <typename Key, typename Enable = void>
struct remove_idx {
static bool remove(std::vector<node*>&, const Key&, std::size_t&) {
return false;
}
static bool remove(std::vector<node*>&, const Key&) { return false; }
};
template <typename Key>
@@ -70,15 +66,11 @@ struct remove_idx<
Key, typename std::enable_if<std::is_unsigned<Key>::value &&
!std::is_same<Key, bool>::value>::type> {
static bool remove(std::vector<node*>& sequence, const Key& key,
std::size_t& seqSize) {
static bool remove(std::vector<node*>& sequence, const Key& key) {
if (key >= sequence.size()) {
return false;
} else {
sequence.erase(sequence.begin() + key);
if (seqSize > key) {
--seqSize;
}
return true;
}
}
@@ -88,10 +80,9 @@ template <typename Key>
struct remove_idx<Key,
typename std::enable_if<std::is_signed<Key>::value>::type> {
static bool remove(std::vector<node*>& sequence, const Key& key,
std::size_t& seqSize) {
static bool remove(std::vector<node*>& sequence, const Key& key) {
return key >= 0 ? remove_idx<std::size_t>::remove(
sequence, static_cast<std::size_t>(key), seqSize)
sequence, static_cast<std::size_t>(key))
: false;
}
};
@@ -106,11 +97,7 @@ inline bool node::equals(const T& rhs, shared_memory_holder pMemory) {
}
inline bool node::equals(const char* rhs, shared_memory_holder pMemory) {
std::string lhs;
if (convert<std::string>::decode(Node(*this, std::move(pMemory)), lhs)) {
return lhs == rhs;
}
return false;
return equals<std::string>(rhs, pMemory);
}
// indexing
@@ -122,20 +109,22 @@ inline node* node_data::get(const Key& key,
break;
case NodeType::Undefined:
case NodeType::Null:
return nullptr;
return NULL;
case NodeType::Sequence:
if (node* pNode = get_idx<Key>::get(m_sequence, key, pMemory))
return pNode;
return nullptr;
return NULL;
case NodeType::Scalar:
throw BadSubscript(m_mark, key);
throw BadSubscript();
}
auto it = std::find_if(m_map.begin(), m_map.end(), [&](const kv_pair m) {
return m.first->equals(key, pMemory);
});
for (node_map::const_iterator it = m_map.begin(); it != m_map.end(); ++it) {
if (it->first->equals(key, pMemory)) {
return it->second;
}
}
return it != m_map.end() ? it->second : nullptr;
return NULL;
}
template <typename Key>
@@ -154,15 +143,13 @@ inline node& node_data::get(const Key& key, shared_memory_holder pMemory) {
convert_to_map(pMemory);
break;
case NodeType::Scalar:
throw BadSubscript(m_mark, key);
throw BadSubscript();
}
auto it = std::find_if(m_map.begin(), m_map.end(), [&](const kv_pair m) {
return m.first->equals(key, pMemory);
});
if (it != m_map.end()) {
return *it->second;
for (node_map::const_iterator it = m_map.begin(); it != m_map.end(); ++it) {
if (it->first->equals(key, pMemory)) {
return *it->second;
}
}
node& k = convert_to_node(key, pMemory);
@@ -174,10 +161,8 @@ inline node& node_data::get(const Key& key, shared_memory_holder pMemory) {
template <typename Key>
inline bool node_data::remove(const Key& key, shared_memory_holder pMemory) {
if (m_type == NodeType::Sequence) {
return remove_idx<Key>::remove(m_sequence, key, m_seqSize);
}
if (m_type == NodeType::Map) {
return remove_idx<Key>::remove(m_sequence, key);
} else if (m_type == NodeType::Map) {
kv_pairs::iterator it = m_undefinedPairs.begin();
while (it != m_undefinedPairs.end()) {
kv_pairs::iterator jt = std::next(it);
@@ -187,13 +172,11 @@ inline bool node_data::remove(const Key& key, shared_memory_holder pMemory) {
it = jt;
}
auto iter = std::find_if(m_map.begin(), m_map.end(), [&](const kv_pair m) {
return m.first->equals(key, pMemory);
});
if (iter != m_map.end()) {
m_map.erase(iter);
return true;
for (node_map::iterator iter = m_map.begin(); iter != m_map.end(); ++iter) {
if (iter->first->equals(key, pMemory)) {
m_map.erase(iter);
return true;
}
}
}
@@ -218,7 +201,7 @@ inline void node_data::force_insert(const Key& key, const Value& value,
node& k = convert_to_node(key, pMemory);
node& v = convert_to_node(value, pMemory);
insert_map_pair(k, v, true);
insert_map_pair(k, v);
}
template <typename T>
+6 -12
View File
@@ -26,16 +26,12 @@ class iterator_base {
template <typename>
friend class iterator_base;
struct enabler {};
using base_type = node_iterator;
typedef node_iterator base_type;
struct proxy {
explicit proxy(const V& x) : m_ref(x) {}
V* operator->() YAML_ATTRIBUTE_LIFETIME_BOUND {
return std::addressof(m_ref);
}
operator V*() YAML_ATTRIBUTE_LIFETIME_BOUND {
return std::addressof(m_ref);
}
V* operator->() { return std::addressof(m_ref); }
operator V*() { return std::addressof(m_ref); }
V m_ref;
};
@@ -45,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() {}
@@ -79,7 +75,7 @@ class iterator_base {
return m_iterator != rhs.m_iterator;
}
value_type operator*() const YAML_ATTRIBUTE_LIFETIME_BOUND {
value_type operator*() const {
const typename base_type::value_type& v = *m_iterator;
if (v.pNode)
return value_type(Node(*v, m_pMemory));
@@ -88,9 +84,7 @@ class iterator_base {
return value_type();
}
proxy operator->() const YAML_ATTRIBUTE_LIFETIME_BOUND {
return proxy(**this);
}
proxy operator->() const { return proxy(**this); }
private:
base_type m_iterator;
+2 -2
View File
@@ -20,8 +20,8 @@ template <typename V>
class iterator_base;
}
using iterator = detail::iterator_base<detail::iterator_value>;
using const_iterator = detail::iterator_base<const detail::iterator_value>;
typedef detail::iterator_base<detail::iterator_value> iterator;
typedef detail::iterator_base<const detail::iterator_value> const_iterator;
}
#endif // VALUE_DETAIL_ITERATOR_FWD_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+2 -3
View File
@@ -25,16 +25,15 @@ class YAML_CPP_API memory {
memory() : m_nodes{} {}
node& create_node();
void merge(const memory& rhs);
size_t size() const;
private:
using Nodes = std::set<shared_node>;
typedef std::set<shared_node> Nodes;
Nodes m_nodes;
};
class YAML_CPP_API memory_holder {
public:
memory_holder() : m_pMemory(std::make_shared<memory>()) {}
memory_holder() : m_pMemory(new memory) {}
node& create_node() { return m_pMemory->create_node(); }
void merge(memory_holder& rhs);
+7 -15
View File
@@ -13,18 +13,12 @@
#include "yaml-cpp/node/ptr.h"
#include "yaml-cpp/node/type.h"
#include <set>
#include <atomic>
namespace YAML {
namespace detail {
class node {
private:
struct less {
bool operator ()(const node* l, const node* r) const {return l->m_index < r->m_index;}
};
public:
node() : m_pRef(std::make_shared<node_ref>()), m_dependencies{}, m_index{} {}
node() : m_pRef(new node_ref), m_dependencies{} {}
node(const node&) = delete;
node& operator=(const node&) = delete;
@@ -48,8 +42,9 @@ class node {
return;
m_pRef->mark_defined();
for (node* dependency : m_dependencies)
dependency->mark_defined();
for (nodes::iterator it = m_dependencies.begin();
it != m_dependencies.end(); ++it)
(*it)->mark_defined();
m_dependencies.clear();
}
@@ -114,7 +109,6 @@ class node {
void push_back(node& input, shared_memory_holder pMemory) {
m_pRef->push_back(input, pMemory);
input.add_dependency(*this);
m_index = m_amount.fetch_add(1);
}
void insert(node& key, node& value, shared_memory_holder pMemory) {
m_pRef->insert(key, value, pMemory);
@@ -126,7 +120,7 @@ class node {
template <typename Key>
node* get(const Key& key, shared_memory_holder pMemory) const {
// NOTE: this returns a non-const node so that the top-level Node can wrap
// it, and returns a pointer so that it can be nullptr (if there is no such
// it, and returns a pointer so that it can be NULL (if there is no such
// key).
return static_cast<const node_ref&>(*m_pRef).get(key, pMemory);
}
@@ -143,7 +137,7 @@ class node {
node* get(node& key, shared_memory_holder pMemory) const {
// NOTE: this returns a non-const node so that the top-level Node can wrap
// it, and returns a pointer so that it can be nullptr (if there is no such
// it, and returns a pointer so that it can be NULL (if there is no such
// key).
return static_cast<const node_ref&>(*m_pRef).get(key, pMemory);
}
@@ -166,10 +160,8 @@ class node {
private:
shared_node_ref m_pRef;
using nodes = std::set<node*, less>;
typedef std::set<node*> nodes;
nodes m_dependencies;
size_t m_index;
static YAML_CPP_API std::atomic<size_t> m_amount;
};
} // namespace detail
} // namespace YAML
+12 -12
View File
@@ -60,8 +60,8 @@ class YAML_CPP_API node_data {
node_iterator end();
// sequence
void push_back(node& node, const shared_memory_holder& pMemory);
void insert(node& key, node& value, const shared_memory_holder& pMemory);
void push_back(node& node, shared_memory_holder pMemory);
void insert(node& key, node& value, shared_memory_holder pMemory);
// indexing
template <typename Key>
@@ -71,9 +71,9 @@ class YAML_CPP_API node_data {
template <typename Key>
bool remove(const Key& key, shared_memory_holder pMemory);
node* get(node& key, const shared_memory_holder& pMemory) const;
node& get(node& key, const shared_memory_holder& pMemory);
bool remove(node& key, const shared_memory_holder& pMemory);
node* get(node& key, shared_memory_holder pMemory) const;
node& get(node& key, shared_memory_holder pMemory);
bool remove(node& key, shared_memory_holder pMemory);
// map
template <typename Key, typename Value>
@@ -90,9 +90,9 @@ class YAML_CPP_API node_data {
void reset_sequence();
void reset_map();
void insert_map_pair(node& key, node& value, bool force = false);
void convert_to_map(const shared_memory_holder& pMemory);
void convert_sequence_to_map(const shared_memory_holder& pMemory);
void insert_map_pair(node& key, node& value);
void convert_to_map(shared_memory_holder pMemory);
void convert_sequence_to_map(shared_memory_holder pMemory);
template <typename T>
static node& convert_to_node(const T& rhs, shared_memory_holder pMemory);
@@ -108,17 +108,17 @@ class YAML_CPP_API node_data {
std::string m_scalar;
// sequence
using node_seq = std::vector<node *>;
typedef std::vector<node*> node_seq;
node_seq m_sequence;
mutable std::size_t m_seqSize;
// map
using node_map = std::vector<std::pair<node*, node*>>;
typedef std::vector<std::pair<node*, node*>> node_map;
node_map m_map;
using kv_pair = std::pair<node*, node*>;
using kv_pairs = std::list<kv_pair>;
typedef std::pair<node*, node*> kv_pair;
typedef std::list<kv_pair> kv_pairs;
mutable kv_pairs m_undefinedPairs;
};
}
+20 -25
View File
@@ -24,11 +24,11 @@ struct iterator_type {
template <typename V>
struct node_iterator_value : public std::pair<V*, V*> {
using kv = std::pair<V*, V*>;
typedef std::pair<V*, V*> kv;
node_iterator_value() : kv(), pNode(nullptr) {}
node_iterator_value() : kv(), pNode(0) {}
explicit node_iterator_value(V& rhs) : kv(), pNode(&rhs) {}
explicit node_iterator_value(V& key, V& value) : kv(&key, &value), pNode(nullptr) {}
explicit node_iterator_value(V& key, V& value) : kv(&key, &value), pNode(0) {}
V& operator*() const { return *pNode; }
V& operator->() const { return *pNode; }
@@ -36,46 +36,41 @@ struct node_iterator_value : public std::pair<V*, V*> {
V* pNode;
};
using node_seq = std::vector<node *>;
using node_map = std::vector<std::pair<node*, node*>>;
typedef std::vector<node*> node_seq;
typedef std::vector<std::pair<node*, node*>> node_map;
template <typename V>
struct node_iterator_type {
using seq = node_seq::iterator;
using map = node_map::iterator;
typedef node_seq::iterator seq;
typedef node_map::iterator map;
};
template <typename V>
struct node_iterator_type<const V> {
using seq = node_seq::const_iterator;
using map = node_map::const_iterator;
typedef node_seq::const_iterator seq;
typedef node_map::const_iterator map;
};
template <typename V>
class node_iterator_base {
class node_iterator_base
: public std::iterator<std::forward_iterator_tag, node_iterator_value<V>,
std::ptrdiff_t, node_iterator_value<V>*,
node_iterator_value<V>> {
private:
struct enabler {};
struct proxy {
explicit proxy(const node_iterator_value<V>& x) : m_ref(x) {}
node_iterator_value<V>* operator->() YAML_ATTRIBUTE_LIFETIME_BOUND {
return std::addressof(m_ref);
}
operator node_iterator_value<V>*() YAML_ATTRIBUTE_LIFETIME_BOUND {
return std::addressof(m_ref);
}
node_iterator_value<V>* operator->() { return std::addressof(m_ref); }
operator node_iterator_value<V>*() { return std::addressof(m_ref); }
node_iterator_value<V> m_ref;
};
public:
using iterator_category = std::forward_iterator_tag;
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 SeqIter = typename node_iterator_type<V>::seq;
using MapIter = typename node_iterator_type<V>::map;
typedef typename node_iterator_type<V>::seq SeqIter;
typedef typename node_iterator_type<V>::map MapIter;
typedef node_iterator_value<V> value_type;
node_iterator_base()
: m_type(iterator_type::NoneType), m_seqIt(), m_mapIt(), m_mapEnd() {}
@@ -177,8 +172,8 @@ class node_iterator_base {
MapIter m_mapIt, m_mapEnd;
};
using node_iterator = node_iterator_base<node>;
using const_node_iterator = node_iterator_base<const node>;
typedef node_iterator_base<node> node_iterator;
typedef node_iterator_base<const node> const_node_iterator;
}
}
+1 -1
View File
@@ -16,7 +16,7 @@ namespace YAML {
namespace detail {
class node_ref {
public:
node_ref() : m_pData(std::make_shared<node_data>()) {}
node_ref() : m_pData(new node_data) {}
node_ref(const node_ref&) = delete;
node_ref& operator=(const node_ref&) = delete;
+110 -71
View File
@@ -12,17 +12,14 @@
#include "yaml-cpp/node/detail/node.h"
#include "yaml-cpp/node/iterator.h"
#include "yaml-cpp/node/node.h"
#include <sstream>
#include <string>
namespace YAML {
inline Node::Node()
: m_isValid(true), m_invalidKey{}, m_pMemory(nullptr), m_pNode(nullptr) {}
inline Node::Node() : m_isValid(true), m_pMemory(nullptr), m_pNode(nullptr) {}
inline Node::Node(NodeType::value type)
: m_isValid(true),
m_invalidKey{},
m_pMemory(std::make_shared<detail::memory_holder>()),
m_pMemory(new detail::memory_holder),
m_pNode(&m_pMemory->create_node()) {
m_pNode->set_type(type);
}
@@ -30,34 +27,31 @@ inline Node::Node(NodeType::value type)
template <typename T>
inline Node::Node(const T& rhs)
: m_isValid(true),
m_invalidKey{},
m_pMemory(std::make_shared<detail::memory_holder>()),
m_pMemory(new detail::memory_holder),
m_pNode(&m_pMemory->create_node()) {
Assign(rhs);
}
inline Node::Node(const detail::iterator_value& rhs)
: m_isValid(rhs.m_isValid),
m_invalidKey(rhs.m_invalidKey),
m_pMemory(rhs.m_pMemory),
m_pNode(rhs.m_pNode) {}
inline Node::Node(const Node&) = default;
inline Node::Node(const Node& rhs)
: m_isValid(rhs.m_isValid),
m_pMemory(rhs.m_pMemory),
m_pNode(rhs.m_pNode) {}
inline Node::Node(Zombie)
: m_isValid(false), m_invalidKey{}, m_pMemory{}, m_pNode(nullptr) {}
inline Node::Node(Zombie, const std::string& key)
: m_isValid(false), m_invalidKey(key), m_pMemory{}, m_pNode(nullptr) {}
inline Node::Node(Zombie) : m_isValid(false), m_pMemory{}, m_pNode(nullptr) {}
inline Node::Node(detail::node& node, detail::shared_memory_holder pMemory)
: m_isValid(true), m_invalidKey{}, m_pMemory(pMemory), m_pNode(&node) {}
: m_isValid(true), m_pMemory(pMemory), m_pNode(&node) {}
inline Node::~Node() = default;
inline Node::~Node() {}
inline void Node::EnsureNodeExists() const {
if (!m_isValid)
throw InvalidNode(m_invalidKey);
throw InvalidNode();
if (!m_pNode) {
m_pMemory.reset(new detail::memory_holder);
m_pNode = &m_pMemory->create_node();
@@ -65,12 +59,6 @@ inline void Node::EnsureNodeExists() const {
}
}
inline void Node::Invalidate() {
m_isValid = false;
m_pNode = nullptr;
m_pMemory = nullptr;
}
inline bool Node::IsDefined() const {
if (!m_isValid) {
return false;
@@ -80,14 +68,14 @@ inline bool Node::IsDefined() const {
inline Mark Node::Mark() const {
if (!m_isValid) {
throw InvalidNode(m_invalidKey);
throw InvalidNode();
}
return m_pNode ? m_pNode->mark() : Mark::null_mark();
}
inline NodeType::value Node::Type() const {
if (!m_isValid)
throw InvalidNode(m_invalidKey);
throw InvalidNode();
return m_pNode ? m_pNode->type() : NodeType::Null;
}
@@ -103,7 +91,7 @@ struct as_if {
if (!node.m_pNode)
return fallback;
T t = fallback;
T t;
if (convert<T>::decode(node, t))
return t;
return fallback;
@@ -116,8 +104,6 @@ struct as_if<std::string, S> {
const Node& node;
std::string operator()(const S& fallback) const {
if (node.Type() == NodeType::Null)
return "null";
if (node.Type() != NodeType::Scalar)
return fallback;
return node.Scalar();
@@ -130,8 +116,8 @@ struct as_if<T, void> {
const Node& node;
T operator()() const {
if (!node.m_pNode) // no fallback
throw InvalidNode(node.m_invalidKey);
if (!node.m_pNode)
throw TypedBadConversion<T>(node.Mark());
T t;
if (convert<T>::decode(node, t))
@@ -146,10 +132,6 @@ 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)
throw TypedBadConversion<std::string>(node.Mark());
return node.Scalar();
@@ -160,7 +142,7 @@ struct as_if<std::string, void> {
template <typename T>
inline T Node::as() const {
if (!m_isValid)
throw InvalidNode(m_invalidKey);
throw InvalidNode();
return as_if<T, void>(*this)();
}
@@ -173,36 +155,32 @@ inline T Node::as(const S& fallback) const {
inline const std::string& Node::Scalar() const {
if (!m_isValid)
throw InvalidNode(m_invalidKey);
throw InvalidNode();
return m_pNode ? m_pNode->scalar() : detail::node_data::empty_scalar();
}
YAML_ATTRIBUTE_NO_SANITIZE_ADDRESS
inline const std::string& Node::UninstrumentedScalarForTesting() const {
if (m_isValid && m_pMemory != nullptr && m_pNode != nullptr)
throw InvalidNode("use-after-free");
else
throw BadDereference();
}
inline const std::string& Node::Tag() const {
if (!m_isValid)
throw InvalidNode(m_invalidKey);
throw InvalidNode();
return m_pNode ? m_pNode->tag() : detail::node_data::empty_scalar();
}
inline void Node::SetTag(const std::string& tag) {
if (!m_isValid)
throw InvalidNode();
EnsureNodeExists();
m_pNode->set_tag(tag);
}
inline EmitterStyle::value Node::Style() const {
if (!m_isValid)
throw InvalidNode(m_invalidKey);
throw InvalidNode();
return m_pNode ? m_pNode->style() : EmitterStyle::Default;
}
inline void Node::SetStyle(EmitterStyle::value style) {
if (!m_isValid)
throw InvalidNode();
EnsureNodeExists();
m_pNode->set_style(style);
}
@@ -210,7 +188,7 @@ inline void Node::SetStyle(EmitterStyle::value style) {
// assignment
inline bool Node::is(const Node& rhs) const {
if (!m_isValid || !rhs.m_isValid)
throw InvalidNode(m_invalidKey);
throw InvalidNode();
if (!m_pNode || !rhs.m_pNode)
return false;
return m_pNode->is(*rhs.m_pNode);
@@ -218,11 +196,15 @@ inline bool Node::is(const Node& rhs) const {
template <typename T>
inline Node& Node::operator=(const T& rhs) {
if (!m_isValid)
throw InvalidNode();
Assign(rhs);
return *this;
}
inline Node& Node::operator=(const Node& rhs) {
if (!m_isValid || !rhs.m_isValid)
throw InvalidNode();
if (is(rhs))
return *this;
AssignNode(rhs);
@@ -231,7 +213,7 @@ inline Node& Node::operator=(const Node& rhs) {
inline void Node::reset(const YAML::Node& rhs) {
if (!m_isValid || !rhs.m_isValid)
throw InvalidNode(m_invalidKey);
throw InvalidNode();
m_pMemory = rhs.m_pMemory;
m_pNode = rhs.m_pNode;
}
@@ -239,27 +221,35 @@ inline void Node::reset(const YAML::Node& rhs) {
template <typename T>
inline void Node::Assign(const T& rhs) {
if (!m_isValid)
throw InvalidNode(m_invalidKey);
throw InvalidNode();
AssignData(convert<T>::encode(rhs));
}
template <>
inline void Node::Assign(const std::string& rhs) {
if (!m_isValid)
throw InvalidNode();
EnsureNodeExists();
m_pNode->set_scalar(rhs);
}
inline void Node::Assign(const char* rhs) {
if (!m_isValid)
throw InvalidNode();
EnsureNodeExists();
m_pNode->set_scalar(rhs);
}
inline void Node::Assign(char* rhs) {
if (!m_isValid)
throw InvalidNode();
EnsureNodeExists();
m_pNode->set_scalar(rhs);
}
inline void Node::AssignData(const Node& rhs) {
if (!m_isValid || !rhs.m_isValid)
throw InvalidNode();
EnsureNodeExists();
rhs.EnsureNodeExists();
@@ -268,8 +258,8 @@ inline void Node::AssignData(const Node& rhs) {
}
inline void Node::AssignNode(const Node& rhs) {
if (!m_isValid)
throw InvalidNode(m_invalidKey);
if (!m_isValid || !rhs.m_isValid)
throw InvalidNode();
rhs.EnsureNodeExists();
if (!m_pNode) {
@@ -286,7 +276,7 @@ inline void Node::AssignNode(const Node& rhs) {
// size/iterator
inline std::size_t Node::size() const {
if (!m_isValid)
throw InvalidNode(m_invalidKey);
throw InvalidNode();
return m_pNode ? m_pNode->size() : 0;
}
@@ -319,11 +309,13 @@ inline iterator Node::end() {
template <typename T>
inline void Node::push_back(const T& rhs) {
if (!m_isValid)
throw InvalidNode(m_invalidKey);
throw InvalidNode();
push_back(Node(rhs));
}
inline void Node::push_back(const Node& rhs) {
if (!m_isValid || !rhs.m_isValid)
throw InvalidNode();
EnsureNodeExists();
rhs.EnsureNodeExists();
@@ -331,49 +323,99 @@ inline void Node::push_back(const Node& rhs) {
m_pMemory->merge(*rhs.m_pMemory);
}
template<typename Key>
std::string key_to_string(const Key& key) {
return streamable_to_string<Key, is_streamable<std::stringstream, Key>::value>().impl(key);
// helpers for indexing
namespace detail {
template <typename T>
struct to_value_t {
explicit to_value_t(const T& t_) : t(t_) {}
const T& t;
typedef const T& return_type;
const T& operator()() const { return t; }
};
template <>
struct to_value_t<const char*> {
explicit to_value_t(const char* t_) : t(t_) {}
const char* t;
typedef std::string return_type;
const std::string operator()() const { return t; }
};
template <>
struct to_value_t<char*> {
explicit to_value_t(char* t_) : t(t_) {}
const char* t;
typedef std::string return_type;
const std::string operator()() const { return t; }
};
template <std::size_t N>
struct to_value_t<char[N]> {
explicit to_value_t(const char* t_) : t(t_) {}
const char* t;
typedef std::string return_type;
const std::string operator()() const { return t; }
};
// converts C-strings to std::strings so they can be copied
template <typename T>
inline typename to_value_t<T>::return_type to_value(const T& t) {
return to_value_t<T>(t)();
}
} // namespace detail
// indexing
template <typename Key>
inline const Node Node::operator[](const Key& key) const {
if (!m_isValid)
throw InvalidNode();
EnsureNodeExists();
detail::node* value =
static_cast<const detail::node&>(*m_pNode).get(key, m_pMemory);
detail::node* value = static_cast<const detail::node&>(*m_pNode).get(
detail::to_value(key), m_pMemory);
if (!value) {
return Node(ZombieNode, key_to_string(key));
return Node(ZombieNode);
}
return Node(*value, m_pMemory);
}
template <typename Key>
inline Node Node::operator[](const Key& key) {
if (!m_isValid)
throw InvalidNode();
EnsureNodeExists();
detail::node& value = m_pNode->get(key, m_pMemory);
detail::node& value = m_pNode->get(detail::to_value(key), m_pMemory);
return Node(value, m_pMemory);
}
template <typename Key>
inline bool Node::remove(const Key& key) {
if (!m_isValid)
throw InvalidNode();
EnsureNodeExists();
return m_pNode->remove(key, m_pMemory);
return m_pNode->remove(detail::to_value(key), m_pMemory);
}
inline const Node Node::operator[](const Node& key) const {
if (!m_isValid || !key.m_isValid)
throw InvalidNode();
EnsureNodeExists();
key.EnsureNodeExists();
m_pMemory->merge(*key.m_pMemory);
detail::node* value =
static_cast<const detail::node&>(*m_pNode).get(*key.m_pNode, m_pMemory);
if (!value) {
return Node(ZombieNode, key_to_string(key));
return Node(ZombieNode);
}
return Node(*value, m_pMemory);
}
inline Node Node::operator[](const Node& key) {
if (!m_isValid || !key.m_isValid)
throw InvalidNode();
EnsureNodeExists();
key.EnsureNodeExists();
m_pMemory->merge(*key.m_pMemory);
@@ -382,6 +424,8 @@ inline Node Node::operator[](const Node& key) {
}
inline bool Node::remove(const Node& key) {
if (!m_isValid || !key.m_isValid)
throw InvalidNode();
EnsureNodeExists();
key.EnsureNodeExists();
return m_pNode->remove(*key.m_pNode, m_pMemory);
@@ -390,16 +434,11 @@ inline bool Node::remove(const Node& key) {
// map
template <typename Key, typename Value>
inline void Node::force_insert(const Key& key, const Value& value) {
EnsureNodeExists();
m_pNode->force_insert(key, value, m_pMemory);
}
template <typename Key>
inline bool Node::contains(const Key& key) const {
if (!m_isValid)
throw InvalidNode(m_invalidKey);
if (!m_pNode) return false;
return (static_cast<const detail::node*>(m_pNode))->get(key, m_pMemory) != nullptr;
throw InvalidNode();
EnsureNodeExists();
m_pNode->force_insert(detail::to_value(key), detail::to_value(value),
m_pMemory);
}
// free functions
+1 -9
View File
@@ -15,23 +15,15 @@
#include <utility>
#include <vector>
// Assert in place so gcc + libc++ combination properly builds
static_assert(std::is_constructible<YAML::Node, const YAML::Node&>::value, "Node must be copy constructable");
namespace YAML {
namespace detail {
struct iterator_value : public Node, std::pair<Node, Node> {
iterator_value() = default;
iterator_value() {}
explicit iterator_value(const Node& rhs)
: Node(rhs),
std::pair<Node, Node>(Node(Node::ZombieNode), Node(Node::ZombieNode)) {}
explicit iterator_value(const Node& key, const Node& value)
: Node(Node::ZombieNode), std::pair<Node, Node>(key, value) {}
~iterator_value() noexcept {
this->Node::Invalidate();
first.Invalidate();
second.Invalidate();
}
};
}
}
+4 -12
View File
@@ -8,11 +8,11 @@
#endif
#include <stdexcept>
#include <string>
#include "yaml-cpp/dll.h"
#include "yaml-cpp/emitterstyle.h"
#include "yaml-cpp/mark.h"
#include "yaml-cpp/node/detail/bool_type.h"
#include "yaml-cpp/node/detail/iterator_fwd.h"
#include "yaml-cpp/node/ptr.h"
#include "yaml-cpp/node/type.h"
@@ -38,8 +38,8 @@ class YAML_CPP_API Node {
template <typename T, typename S>
friend struct as_if;
using iterator = YAML::iterator;
using const_iterator = YAML::const_iterator;
typedef YAML::iterator iterator;
typedef YAML::const_iterator const_iterator;
Node();
explicit Node(NodeType::value type);
@@ -58,7 +58,7 @@ class YAML_CPP_API Node {
bool IsMap() const { return Type() == NodeType::Map; }
// bool conversions
explicit operator bool() const { return IsDefined(); }
YAML_CPP_OPERATOR_BOOL()
bool operator!() const { return !IsDefined(); }
// access
@@ -67,7 +67,6 @@ class YAML_CPP_API Node {
template <typename T, typename S>
T as(const S& fallback) const;
const std::string& Scalar() const;
const std::string& UninstrumentedScalarForTesting() const;
const std::string& Tag() const;
void SetTag(const std::string& tag);
@@ -114,17 +113,12 @@ class YAML_CPP_API Node {
template <typename Key, typename Value>
void force_insert(const Key& key, const Value& value);
template <typename Key>
bool contains(const Key& key) const;
private:
enum Zombie { ZombieNode };
explicit Node(Zombie);
explicit Node(Zombie, const std::string&);
explicit Node(detail::node& node, detail::shared_memory_holder pMemory);
void EnsureNodeExists() const;
void Invalidate();
template <typename T>
void Assign(const T& rhs);
@@ -136,8 +130,6 @@ class YAML_CPP_API Node {
private:
bool m_isValid;
// String representation of invalid key, if the node is invalid.
std::string m_invalidKey;
mutable detail::shared_memory_holder m_pMemory;
mutable detail::node* m_pNode;
};
+6 -17
View File
@@ -7,6 +7,7 @@
#pragma once
#endif
#include "yaml-cpp/dll.h"
#include <memory>
namespace YAML {
@@ -17,24 +18,12 @@ class node_data;
class memory;
class memory_holder;
using shared_node = std::shared_ptr<node>;
using shared_node_ref = std::shared_ptr<node_ref>;
using shared_node_data = std::shared_ptr<node_data>;
using shared_memory_holder = std::shared_ptr<memory_holder>;
using shared_memory = std::shared_ptr<memory>;
typedef std::shared_ptr<node> shared_node;
typedef std::shared_ptr<node_ref> shared_node_ref;
typedef std::shared_ptr<node_data> shared_node_data;
typedef std::shared_ptr<memory_holder> shared_memory_holder;
typedef std::shared_ptr<memory> shared_memory;
}
}
#if defined(__has_cpp_attribute) && __has_cpp_attribute(msvc::lifetimebound)
#define YAML_ATTRIBUTE_LIFETIME_BOUND [[msvc::lifetimebound]]
#elif defined(__has_cpp_attribute) && __has_cpp_attribute(gnu::lifetimebound)
#define YAML_ATTRIBUTE_LIFETIME_BOUND [[gnu::lifetimebound]]
#elif defined(__has_cpp_attribute) && __has_cpp_attribute(clang::lifetimebound)
#define YAML_ATTRIBUTE_LIFETIME_BOUND [[clang::lifetimebound]]
#elif defined(__has_attribute) && __has_attribute(lifetimebound)
#define YAML_ATTRIBUTE_LIFETIME_BOUND __attribute__((lifetimebound))
#else
#define YAML_ATTRIBUTE_LIFETIME_BOUND
#endif
#endif // VALUE_PTR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+3 -4
View File
@@ -8,10 +8,9 @@
#endif
namespace YAML {
namespace NodeType {
enum value { Undefined, Null, Scalar, Sequence, Map };
}
struct NodeType {
enum value { Undefined, Null, Scalar, Sequence, Map };
};
}
#endif // VALUE_TYPE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
-18
View File
@@ -1,18 +0,0 @@
#ifndef NOEXCEPT_H_768872DA_476C_11EA_88B8_90B11C0C0FF8
#define NOEXCEPT_H_768872DA_476C_11EA_88B8_90B11C0C0FF8
#if defined(_MSC_VER) || \
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
#pragma once
#endif
// This is here for compatibility with older versions of Visual Studio
// which don't support noexcept.
#if defined(_MSC_VER) && _MSC_VER < 1900
#define YAML_CPP_NOEXCEPT _NOEXCEPT
#else
#define YAML_CPP_NOEXCEPT noexcept
#endif
#endif
+2 -2
View File
@@ -8,7 +8,7 @@
#endif
#include "yaml-cpp/dll.h"
#include <cstddef>
#include <string>
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 char* str, std::size_t size);
YAML_CPP_API bool IsNullString(const std::string& str);
extern YAML_CPP_API _Null Null;
}
+1 -2
View File
@@ -7,7 +7,6 @@
#pragma once
#endif
#include <ostream>
#include <string>
#include <vector>
@@ -31,7 +30,7 @@ class YAML_CPP_API ostream_wrapper {
const char* str() const {
if (m_pStream) {
return nullptr;
return 0;
} else {
m_buffer[m_pos] = '\0';
return &m_buffer[0];
+1 -2
View File
@@ -7,9 +7,8 @@
#pragma once
#endif
#include <istream>
#include <ios>
#include <memory>
#include <ostream>
#include "yaml-cpp/dll.h"
+5 -4
View File
@@ -16,8 +16,8 @@ namespace YAML {
template <typename Seq>
inline Emitter& EmitSeq(Emitter& emitter, const Seq& seq) {
emitter << BeginSeq;
for (const auto& v : seq)
emitter << v;
for (typename Seq::const_iterator it = seq.begin(); it != seq.end(); ++it)
emitter << *it;
emitter << EndSeq;
return emitter;
}
@@ -39,9 +39,10 @@ inline Emitter& operator<<(Emitter& emitter, const std::set<T>& v) {
template <typename K, typename V>
inline Emitter& operator<<(Emitter& emitter, const std::map<K, V>& m) {
typedef typename std::map<K, V> map;
emitter << BeginMap;
for (const auto& v : m)
emitter << Key << v.first << Value << v.second;
for (typename map::const_iterator it = m.begin(); it != m.end(); ++it)
emitter << Key << it->first << Value << it->second;
emitter << EndMap;
return emitter;
}
+2 -35
View File
@@ -7,11 +7,6 @@
#pragma once
#endif
#include <type_traits>
#include <utility>
#include <string>
#include <sstream>
namespace YAML {
template <typename>
struct is_numeric {
@@ -84,7 +79,7 @@ struct is_numeric<long double> {
template <bool, class T = void>
struct enable_if_c {
using type = T;
typedef T type;
};
template <class T>
@@ -95,7 +90,7 @@ struct enable_if : public enable_if_c<Cond::value, T> {};
template <bool, class T = void>
struct disable_if_c {
using type = T;
typedef T type;
};
template <class T>
@@ -105,32 +100,4 @@ template <class Cond, class T = void>
struct disable_if : public disable_if_c<Cond::value, T> {};
}
template <typename S, typename T>
struct is_streamable {
template <typename StreamT, typename ValueT>
static auto test(int)
-> decltype(std::declval<StreamT&>() << std::declval<ValueT>(), std::true_type());
template <typename, typename>
static auto test(...) -> std::false_type;
static const bool value = decltype(test<S, T>(0))::value;
};
template<typename Key, bool Streamable>
struct streamable_to_string {
static std::string impl(const Key& key) {
std::stringstream ss;
ss.imbue(std::locale::classic());
ss << key;
return ss.str();
}
};
template<typename Key>
struct streamable_to_string<Key, false> {
static std::string impl(const Key&) {
return "";
}
};
#endif // TRAITS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
-4
View File
@@ -7,8 +7,6 @@
#pragma once
#endif
// IWYU pragma: begin_exports
#include "yaml-cpp/parser.h"
#include "yaml-cpp/emitter.h"
#include "yaml-cpp/emitterstyle.h"
@@ -23,6 +21,4 @@
#include "yaml-cpp/node/parse.h"
#include "yaml-cpp/node/emit.h"
// IWYU pragma: end_exports
#endif // YAML_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+7 -14
View File
@@ -66,7 +66,7 @@ static const unsigned char decoding[] = {
};
std::vector<unsigned char> DecodeBase64(const std::string &input) {
using ret_type = std::vector<unsigned char>;
typedef std::vector<unsigned char> ret_type;
if (input.empty())
return ret_type();
@@ -74,34 +74,27 @@ std::vector<unsigned char> DecodeBase64(const std::string &input) {
unsigned char *out = &ret[0];
unsigned value = 0;
std::size_t cnt = 0;
for (std::size_t i = 0; i < input.size(); i++) {
if (std::isspace(static_cast<unsigned char>(input[i]))) {
for (std::size_t i = 0, cnt = 0; i < input.size(); i++) {
if (std::isspace(input[i])) {
// skip newlines
continue;
}
unsigned char d = decoding[static_cast<unsigned char>(input[i])];
unsigned char d = decoding[static_cast<unsigned>(input[i])];
if (d == 255)
return ret_type();
value = (value << 6) | d;
if (cnt == 3) {
if (cnt % 4 == 3) {
*out++ = value >> 16;
if (i > 0 && input[i - 1] != '=')
*out++ = value >> 8;
if (input[i] != '=')
*out++ = value;
cnt = 0;
} else {
++cnt;
}
}
if (cnt != 0) {
// An invalid number of characters were encountered.
return ret_type();
++cnt;
}
ret.resize(out - &ret[0]);
return ret;
}
} // namespace YAML
}
File diff suppressed because it is too large Load Diff
+3 -2
View File
@@ -10,7 +10,8 @@ void* BuildGraphOfNextDocument(Parser& parser,
GraphBuilderAdapter eventHandler(graphBuilder);
if (parser.HandleNextDocument(eventHandler)) {
return eventHandler.RootNode();
} else {
return nullptr;
}
return nullptr;
}
} // namespace YAML
}
+1 -1
View File
@@ -91,4 +91,4 @@ void GraphBuilderAdapter::DispositionNode(void *pNode) {
m_builder.AppendToSequence(pContainer, pNode);
}
}
} // namespace YAML
}
+1
View File
@@ -13,6 +13,7 @@
#include "yaml-cpp/anchor.h"
#include "yaml-cpp/contrib/anchordict.h"
#include "yaml-cpp/contrib/graphbuilder.h"
#include "yaml-cpp/emitterstyle.h"
#include "yaml-cpp/eventhandler.h"
+11 -10
View File
@@ -16,7 +16,11 @@ std::string tolower(const std::string& str) {
template <typename T>
bool IsEntirely(const std::string& str, T func) {
return std::all_of(str.begin(), str.end(), [=](char ch) { return func(ch); });
for (std::size_t i = 0; i < str.size(); i++)
if (!func(str[i]))
return false;
return true;
}
// IsFlexibleCase
@@ -35,7 +39,7 @@ bool IsFlexibleCase(const std::string& str) {
std::string rest = str.substr(1);
return firstcaps && (IsEntirely(rest, IsLower) || IsEntirely(rest, IsUpper));
}
} // namespace
}
namespace YAML {
bool convert<bool>::decode(const Node& node, bool& rhs) {
@@ -48,22 +52,19 @@ bool convert<bool>::decode(const Node& node, bool& rhs) {
static const struct {
std::string truename, falsename;
} names[] = {
{"y", "n"},
{"yes", "no"},
{"true", "false"},
{"on", "off"},
{"y", "n"}, {"yes", "no"}, {"true", "false"}, {"on", "off"},
};
if (!IsFlexibleCase(node.Scalar()))
return false;
for (const auto& name : names) {
if (name.truename == tolower(node.Scalar())) {
for (unsigned i = 0; i < sizeof(names) / sizeof(names[0]); i++) {
if (names[i].truename == tolower(node.Scalar())) {
rhs = true;
return true;
}
if (name.falsename == tolower(node.Scalar())) {
if (names[i].falsename == tolower(node.Scalar())) {
rhs = false;
return true;
}
@@ -71,4 +72,4 @@ bool convert<bool>::decode(const Node& node, bool& rhs) {
return false;
}
} // namespace YAML
}
-9
View File
@@ -1,9 +0,0 @@
#include "yaml-cpp/depthguard.h"
namespace YAML {
DeepRecursion::DeepRecursion(int depth, const Mark& mark_,
const std::string& msg_)
: ParserException(mark_, msg_), m_depth(depth) {}
} // namespace YAML
+2 -2
View File
@@ -3,9 +3,9 @@
namespace YAML {
Directives::Directives() : version{true, 1, 2}, tags{} {}
std::string Directives::TranslateTagHandle(
const std::string Directives::TranslateTagHandle(
const std::string& handle) const {
auto it = tags.find(handle);
std::map<std::string, std::string>::const_iterator it = tags.find(handle);
if (it == tags.end()) {
if (handle == "!!")
return "tag:yaml.org,2002:";
+1 -1
View File
@@ -19,7 +19,7 @@ struct Version {
struct Directives {
Directives();
std::string TranslateTagHandle(const std::string& handle) const;
const std::string TranslateTagHandle(const std::string& handle) const;
Version version;
std::map<std::string, std::string> tags;
+1 -1
View File
@@ -1,7 +1,7 @@
#include "yaml-cpp/node/emit.h"
#include "nodeevents.h"
#include "yaml-cpp/emitfromevents.h"
#include "yaml-cpp/emitter.h"
#include "nodeevents.h"
namespace YAML {
Emitter& operator<<(Emitter& out, const Node& node) {
+2 -26
View File
@@ -59,8 +59,6 @@ void EmitFromEvents::OnSequenceStart(const Mark&, const std::string& tag,
default:
break;
}
// Restore the global settings to eliminate the override from node style
m_emitter.RestoreGlobalModifiedSettings();
m_emitter << BeginSeq;
m_stateStack.push(State::WaitingForSequenceEntry);
}
@@ -85,8 +83,6 @@ void EmitFromEvents::OnMapStart(const Mark&, const std::string& tag,
default:
break;
}
// Restore the global settings to eliminate the override from node style
m_emitter.RestoreGlobalModifiedSettings();
m_emitter << BeginMap;
m_stateStack.push(State::WaitingForKey);
}
@@ -116,28 +112,8 @@ void EmitFromEvents::BeginNode() {
}
void EmitFromEvents::EmitProps(const std::string& tag, anchor_t anchor) {
if (!tag.empty() && tag != "?" && tag != "!"){
if (tag.size() >= 2 && tag[0] == '!' && tag[1] == '!') {
// Tags like "!!str" use the secondary tag handle; emit them through
// SecondaryTag so the rendered output keeps both bangs instead of
// failing the LocalTag regex check on the inner '!'. See #1373.
m_emitter << SecondaryTag(std::string(tag.begin()+2, tag.end()));
} else if (tag[0] == '!') {
auto prefix_end = tag.begin() + 1;
while (prefix_end != tag.end() && *prefix_end != '!') {
++prefix_end;
}
if (prefix_end == tag.end()) {
m_emitter << LocalTag(std::string(tag.begin() + 1, tag.end()));
}
else {
m_emitter << LocalTag(std::string(tag.begin() + 1, prefix_end),
std::string(prefix_end + 1, tag.end()));
}
} else {
m_emitter << VerbatimTag(tag);
}
}
if (!tag.empty() && tag != "?" && tag != "!")
m_emitter << VerbatimTag(tag);
if (anchor)
m_emitter << Anchor(ToString(anchor));
}
+20 -126
View File
@@ -16,7 +16,7 @@ Emitter::Emitter() : m_pState(new EmitterState), m_stream{} {}
Emitter::Emitter(std::ostream& stream)
: m_pState(new EmitterState), m_stream(stream) {}
Emitter::~Emitter() = default;
Emitter::~Emitter() {}
const char* Emitter::c_str() const { return m_stream.str(); }
@@ -49,10 +49,6 @@ bool Emitter::SetBoolFormat(EMITTER_MANIP value) {
return ok;
}
bool Emitter::SetNullFormat(EMITTER_MANIP value) {
return m_pState->SetNullFormat(value, FmtScope::Global);
}
bool Emitter::SetIntBase(EMITTER_MANIP value) {
return m_pState->SetIntFormat(value, FmtScope::Global);
}
@@ -90,14 +86,6 @@ bool Emitter::SetDoublePrecision(std::size_t n) {
return m_pState->SetDoublePrecision(n, FmtScope::Global);
}
bool Emitter::SetShowTrailingZero(bool value) {
return m_pState->SetShowTrailingZero(value, FmtScope::Global);
}
void Emitter::RestoreGlobalModifiedSettings() {
m_pState->RestoreGlobalModifiedSettings();
}
// SetLocalValue
// . Either start/end a group, or set a modifier locally
Emitter& Emitter::SetLocalValue(EMITTER_MANIP value) {
@@ -145,11 +133,6 @@ Emitter& Emitter::SetLocalIndent(const _Indent& indent) {
return *this;
}
Emitter& Emitter::SetLocalWrap(const _Wrap& wrap) {
m_pState->SetWrap(wrap.value, FmtScope::Local);
return *this;
}
Emitter& Emitter::SetLocalPrecision(const _Precision& precision) {
if (precision.floatPrecision >= 0)
m_pState->SetFloatPrecision(precision.floatPrecision, FmtScope::Local);
@@ -214,7 +197,6 @@ void Emitter::EmitBeginSeq() {
void Emitter::EmitEndSeq() {
if (!good())
return;
FlowType::value originalType = m_pState->CurGroupFlowType();
if (m_pState->CurGroupChildCount() == 0)
m_pState->ForceFlow();
@@ -222,14 +204,9 @@ 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 << IndentTo(m_pState->CurIndent());
if (m_pState->CurGroupChildCount() == 0)
m_stream << "[";
} else {
if (m_pState->CurGroupChildCount() == 0 && !m_pState->HasBegunNode())
m_stream << "[";
}
m_stream << "]";
}
@@ -250,7 +227,6 @@ void Emitter::EmitBeginMap() {
void Emitter::EmitEndMap() {
if (!good())
return;
FlowType::value originalType = m_pState->CurGroupFlowType();
if (m_pState->CurGroupChildCount() == 0)
m_pState->ForceFlow();
@@ -259,12 +235,8 @@ void Emitter::EmitEndMap() {
if (m_stream.comment())
m_stream << "\n";
m_stream << IndentTo(m_pState->CurIndent());
if (originalType == FlowType::Block) {
if (m_pState->CurGroupChildCount() == 0)
m_stream << "{";
} else {
if (m_pState->CurGroupChildCount() == 0 && !m_pState->HasBegunNode())
m_stream << "{";
}
m_stream << "}";
}
@@ -514,9 +486,6 @@ void Emitter::FlowMapPrepareSimpleKeyValue(EmitterNodeType::value child) {
if (m_stream.comment())
m_stream << "\n";
m_stream << IndentTo(lastIndent);
if (m_pState->HasAlias()) {
m_stream << " ";
}
m_stream << ":";
}
@@ -543,8 +512,7 @@ void Emitter::BlockMapPrepareNode(EmitterNodeType::value child) {
if (m_pState->GetMapKeyFormat() == LongKey)
m_pState->SetLongKey();
if (child == EmitterNodeType::BlockSeq ||
child == EmitterNodeType::BlockMap ||
child == EmitterNodeType::Property)
child == EmitterNodeType::BlockMap)
m_pState->SetLongKey();
if (m_pState->CurGroupLongKey())
@@ -588,8 +556,6 @@ void Emitter::BlockMapPrepareLongKey(EmitterNodeType::value child) {
break;
case EmitterNodeType::BlockSeq:
case EmitterNodeType::BlockMap:
if (m_pState->HasBegunContent())
m_stream << "\n";
break;
}
}
@@ -613,12 +579,8 @@ void Emitter::BlockMapPrepareLongKeyValue(EmitterNodeType::value child) {
case EmitterNodeType::Scalar:
case EmitterNodeType::FlowSeq:
case EmitterNodeType::FlowMap:
SpaceOrIndentTo(true, curIndent + 1);
break;
case EmitterNodeType::BlockSeq:
case EmitterNodeType::BlockMap:
if (m_pState->HasBegunContent())
m_stream << "\n";
SpaceOrIndentTo(true, curIndent + 1);
break;
}
@@ -657,9 +619,6 @@ void Emitter::BlockMapPrepareSimpleKeyValue(EmitterNodeType::value child) {
const std::size_t nextIndent = curIndent + m_pState->CurGroupIndent();
if (!m_pState->HasBegunNode()) {
if (m_pState->HasAlias()) {
m_stream << " ";
}
m_stream << ":";
}
@@ -713,45 +672,32 @@ void Emitter::StartedScalar() { m_pState->StartedScalar(); }
// *******************************************************************************************
// overloads of Write
StringEscaping::value GetStringEscapingStyle(const EMITTER_MANIP emitterManip) {
switch (emitterManip) {
case EscapeNonAscii:
return StringEscaping::NonAscii;
case EscapeAsJson:
return StringEscaping::JSON;
default:
return StringEscaping::None;
break;
}
}
Emitter& Emitter::Write(const char* str, std::size_t size) {
Emitter& Emitter::Write(const std::string& str) {
if (!good())
return *this;
StringEscaping::value stringEscaping = GetStringEscapingStyle(m_pState->GetOutputCharset());
const bool escapeNonAscii = m_pState->GetOutputCharset() == EscapeNonAscii;
const StringFormat::value strFormat =
Utils::ComputeStringFormat(str, size, m_pState->GetStringFormat(),
m_pState->CurGroupFlowType(), stringEscaping == StringEscaping::NonAscii);
Utils::ComputeStringFormat(str, m_pState->GetStringFormat(),
m_pState->CurGroupFlowType(), escapeNonAscii);
if (strFormat == StringFormat::Literal || size > 1024)
if (strFormat == StringFormat::Literal)
m_pState->SetMapKeyFormat(YAML::LongKey, FmtScope::Local);
PrepareNode(EmitterNodeType::Scalar);
switch (strFormat) {
case StringFormat::Plain:
m_stream.write(str, size);
m_stream << str;
break;
case StringFormat::SingleQuoted:
Utils::WriteSingleQuotedString(m_stream, str, size);
Utils::WriteSingleQuotedString(m_stream, str);
break;
case StringFormat::DoubleQuoted:
Utils::WriteDoubleQuotedString(m_stream, str, size, stringEscaping);
Utils::WriteDoubleQuotedString(m_stream, str, escapeNonAscii);
break;
case StringFormat::Literal:
Utils::WriteLiteralString(m_stream, str, size,
Utils::WriteLiteralString(m_stream, str,
m_pState->CurIndent() + m_pState->GetIndent());
break;
}
@@ -761,10 +707,6 @@ Emitter& Emitter::Write(const char* str, std::size_t size) {
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();
}
@@ -773,10 +715,6 @@ std::size_t Emitter::GetDoublePrecision() const {
return m_pState->GetDoublePrecision();
}
bool Emitter::GetShowTrailingZero() const {
return m_pState->GetShowTrailingZero();
}
const char* Emitter::ComputeFullBoolName(bool b) const {
const EMITTER_MANIP mainFmt = (m_pState->GetBoolLengthFormat() == ShortBool
? YesNoBool
@@ -826,21 +764,6 @@ const char* Emitter::ComputeFullBoolName(bool b) const {
// these answers
}
const char* Emitter::ComputeNullName() const {
switch (m_pState->GetNullFormat()) {
case LowerNull:
return "null";
case UpperNull:
return "NULL";
case CamelNull:
return "Null";
case TildeNull:
// fallthrough
default:
return "~";
}
}
Emitter& Emitter::Write(bool b) {
if (!good())
return *this;
@@ -862,10 +785,8 @@ Emitter& Emitter::Write(char ch) {
if (!good())
return *this;
PrepareNode(EmitterNodeType::Scalar);
Utils::WriteChar(m_stream, ch, GetStringEscapingStyle(m_pState->GetOutputCharset()));
Utils::WriteChar(m_stream, ch);
StartedScalar();
return *this;
@@ -882,15 +803,13 @@ Emitter& Emitter::Write(const _Alias& alias) {
PrepareNode(EmitterNodeType::Scalar);
if (!Utils::WriteAlias(m_stream, alias.content.data(), alias.content.size())) {
if (!Utils::WriteAlias(m_stream, alias.content)) {
m_pState->SetError(ErrorMsg::INVALID_ALIAS);
return *this;
}
StartedScalar();
m_pState->SetAlias();
return *this;
}
@@ -905,7 +824,7 @@ Emitter& Emitter::Write(const _Anchor& anchor) {
PrepareNode(EmitterNodeType::Property);
if (!Utils::WriteAnchor(m_stream, anchor.content.data(), anchor.content.size())) {
if (!Utils::WriteAnchor(m_stream, anchor.content)) {
m_pState->SetError(ErrorMsg::INVALID_ANCHOR);
return *this;
}
@@ -954,7 +873,7 @@ Emitter& Emitter::Write(const _Comment& comment) {
if (m_stream.col() > 0)
m_stream << Indentation(m_pState->GetPreCommentIndent());
Utils::WriteComment(m_stream, comment.content.data(), comment.content.size(),
Utils::WriteComment(m_stream, comment.content,
m_pState->GetPostCommentIndent());
m_pState->SetNonContent();
@@ -968,7 +887,7 @@ Emitter& Emitter::Write(const _Null& /*null*/) {
PrepareNode(EmitterNodeType::Scalar);
m_stream << ComputeNullName();
m_stream << "~";
StartedScalar();
@@ -981,33 +900,8 @@ Emitter& Emitter::Write(const Binary& binary) {
if (!good())
return *this;
const StringFormat::value strFormat =
Utils::ComputeBinaryFormat(binary, m_pState->GetStringFormat(),
m_pState->CurGroupFlowType());
if (strFormat == StringFormat::Literal)
m_pState->SetMapKeyFormat(YAML::LongKey, FmtScope::Local);
PrepareNode(EmitterNodeType::Scalar);
switch (strFormat) {
case StringFormat::SingleQuoted:
Utils::WriteSingleQuotedBinary(m_stream, binary);
break;
// For a long period of time, this function outputed the DoubleQuoted form
// regardless of the options. In order not to change the default behavior,
// when strFormat is Plain, it is still treated as DoubleQuoted.
case StringFormat::Plain:
case StringFormat::DoubleQuoted:
Utils::WriteBinary(m_stream, binary);
break;
case StringFormat::Literal:
Utils::WriteLiteralBinary(m_stream, binary,
m_pState->CurIndent() + m_pState->GetIndent(),
m_pState->GetWrap());
break;
}
Utils::WriteBinary(m_stream, binary);
StartedScalar();
return *this;
+10 -53
View File
@@ -13,30 +13,26 @@ EmitterState::EmitterState()
m_boolFmt(TrueFalseBool),
m_boolLengthFmt(LongBool),
m_boolCaseFmt(LowerCase),
m_nullFmt(TildeNull),
m_intFmt(Dec),
m_indent(2),
m_preCommentIndent(2),
m_postCommentIndent(1),
m_wrap(80),
m_seqFmt(Block),
m_mapFmt(Block),
m_mapKeyFmt(Auto),
m_floatPrecision(std::numeric_limits<float>::max_digits10),
m_doublePrecision(std::numeric_limits<double>::max_digits10),
m_showTrailingZero(false),
//
m_modifiedSettings{},
m_globalModifiedSettings{},
m_groups{},
m_curIndent(0),
m_hasAnchor(false),
m_hasAlias(false),
m_hasTag(false),
m_hasNonContent(false),
m_docCount(0) {}
EmitterState::~EmitterState() = default;
EmitterState::~EmitterState() {}
// SetLocalValue
// . We blindly tries to set all possible formatters to this value
@@ -47,7 +43,6 @@ void EmitterState::SetLocalValue(EMITTER_MANIP value) {
SetBoolFormat(value, FmtScope::Local);
SetBoolCaseFormat(value, FmtScope::Local);
SetBoolLengthFormat(value, FmtScope::Local);
SetNullFormat(value, FmtScope::Local);
SetIntFormat(value, FmtScope::Local);
SetFlowType(GroupType::Seq, value, FmtScope::Local);
SetFlowType(GroupType::Map, value, FmtScope::Local);
@@ -56,8 +51,6 @@ void EmitterState::SetLocalValue(EMITTER_MANIP value) {
void EmitterState::SetAnchor() { m_hasAnchor = true; }
void EmitterState::SetAlias() { m_hasAlias = true; }
void EmitterState::SetTag() { m_hasTag = true; }
void EmitterState::SetNonContent() { m_hasNonContent = true; }
@@ -92,7 +85,6 @@ void EmitterState::StartedNode() {
}
m_hasAnchor = false;
m_hasAlias = false;
m_hasTag = false;
m_hasNonContent = false;
}
@@ -102,13 +94,15 @@ EmitterNodeType::value EmitterState::NextGroupType(
if (type == GroupType::Seq) {
if (GetFlowType(type) == Block)
return EmitterNodeType::BlockSeq;
return EmitterNodeType::FlowSeq;
else
return EmitterNodeType::FlowSeq;
} else {
if (GetFlowType(type) == Block)
return EmitterNodeType::BlockMap;
else
return EmitterNodeType::FlowMap;
}
if (GetFlowType(type) == Block)
return EmitterNodeType::BlockMap;
return EmitterNodeType::FlowMap;
// can't happen
assert(false);
return EmitterNodeType::NoType;
@@ -162,15 +156,9 @@ void EmitterState::EndedGroup(GroupType::value type) {
if (m_groups.empty()) {
if (type == GroupType::Seq) {
return SetError(ErrorMsg::UNEXPECTED_END_SEQ);
} else {
return SetError(ErrorMsg::UNEXPECTED_END_MAP);
}
return SetError(ErrorMsg::UNEXPECTED_END_MAP);
}
if (m_hasTag) {
SetError(ErrorMsg::INVALID_TAG);
}
if (m_hasAnchor) {
SetError(ErrorMsg::INVALID_ANCHOR);
}
// get rid of the current group
@@ -192,9 +180,6 @@ void EmitterState::EndedGroup(GroupType::value type) {
m_globalModifiedSettings.restore();
ClearModifiedSettings();
m_hasAnchor = false;
m_hasTag = false;
m_hasNonContent = false;
}
EmitterNodeType::value EmitterState::CurGroupNodeType() const {
@@ -235,16 +220,11 @@ std::size_t EmitterState::LastIndent() const {
void EmitterState::ClearModifiedSettings() { m_modifiedSettings.clear(); }
void EmitterState::RestoreGlobalModifiedSettings() {
m_globalModifiedSettings.restore();
}
bool EmitterState::SetOutputCharset(EMITTER_MANIP value,
FmtScope::value scope) {
switch (value) {
case EmitNonAscii:
case EscapeNonAscii:
case EscapeAsJson:
_Set(m_charset, value, scope);
return true;
default:
@@ -302,19 +282,6 @@ bool EmitterState::SetBoolCaseFormat(EMITTER_MANIP value,
}
}
bool EmitterState::SetNullFormat(EMITTER_MANIP value, FmtScope::value scope) {
switch (value) {
case LowerNull:
case UpperNull:
case CamelNull:
case TildeNull:
_Set(m_nullFmt, value, scope);
return true;
default:
return false;
}
}
bool EmitterState::SetIntFormat(EMITTER_MANIP value, FmtScope::value scope) {
switch (value) {
case Dec:
@@ -353,11 +320,6 @@ bool EmitterState::SetPostCommentIndent(std::size_t value,
return true;
}
bool EmitterState::SetWrap(std::size_t value, FmtScope::value scope) {
_Set(m_wrap, value, scope);
return true;
}
bool EmitterState::SetFlowType(GroupType::value groupType, EMITTER_MANIP value,
FmtScope::value scope) {
switch (value) {
@@ -404,9 +366,4 @@ bool EmitterState::SetDoublePrecision(std::size_t value,
_Set(m_doublePrecision, value, scope);
return true;
}
bool EmitterState::SetShowTrailingZero(bool value, FmtScope::value scope) {
_Set(m_showTrailingZero, value, scope);
return true;
}
} // namespace YAML
-15
View File
@@ -43,7 +43,6 @@ class EmitterState {
// node handling
void SetAnchor();
void SetAlias();
void SetTag();
void SetNonContent();
void SetLongKey();
@@ -66,7 +65,6 @@ class EmitterState {
std::size_t LastIndent() const;
std::size_t CurIndent() const { return m_curIndent; }
bool HasAnchor() const { return m_hasAnchor; }
bool HasAlias() const { return m_hasAlias; }
bool HasTag() const { return m_hasTag; }
bool HasBegunNode() const {
return m_hasAnchor || m_hasTag || m_hasNonContent;
@@ -74,7 +72,6 @@ class EmitterState {
bool HasBegunContent() const { return m_hasAnchor || m_hasTag; }
void ClearModifiedSettings();
void RestoreGlobalModifiedSettings();
// formatters
void SetLocalValue(EMITTER_MANIP value);
@@ -94,9 +91,6 @@ class EmitterState {
bool SetBoolCaseFormat(EMITTER_MANIP value, FmtScope::value scope);
EMITTER_MANIP GetBoolCaseFormat() const { return m_boolCaseFmt.get(); }
bool SetNullFormat(EMITTER_MANIP value, FmtScope::value scope);
EMITTER_MANIP GetNullFormat() const { return m_nullFmt.get(); }
bool SetIntFormat(EMITTER_MANIP value, FmtScope::value scope);
EMITTER_MANIP GetIntFormat() const { return m_intFmt.get(); }
@@ -108,9 +102,6 @@ class EmitterState {
bool SetPostCommentIndent(std::size_t value, FmtScope::value scope);
std::size_t GetPostCommentIndent() const { return m_postCommentIndent.get(); }
bool SetWrap(std::size_t value, FmtScope::value scope);
std::size_t GetWrap() const { return m_wrap.get(); }
bool SetFlowType(GroupType::value groupType, EMITTER_MANIP value,
FmtScope::value scope);
EMITTER_MANIP GetFlowType(GroupType::value groupType) const;
@@ -122,8 +113,6 @@ class EmitterState {
std::size_t GetFloatPrecision() const { return m_floatPrecision.get(); }
bool SetDoublePrecision(std::size_t value, FmtScope::value scope);
std::size_t GetDoublePrecision() const { return m_doublePrecision.get(); }
bool SetShowTrailingZero(bool value, FmtScope::value scope);
bool GetShowTrailingZero() const { return m_showTrailingZero.get(); }
private:
template <typename T>
@@ -142,17 +131,14 @@ class EmitterState {
Setting<EMITTER_MANIP> m_boolFmt;
Setting<EMITTER_MANIP> m_boolLengthFmt;
Setting<EMITTER_MANIP> m_boolCaseFmt;
Setting<EMITTER_MANIP> m_nullFmt;
Setting<EMITTER_MANIP> m_intFmt;
Setting<std::size_t> m_indent;
Setting<std::size_t> m_preCommentIndent, m_postCommentIndent;
Setting<std::size_t> m_wrap; // applied to literal binary
Setting<EMITTER_MANIP> m_seqFmt;
Setting<EMITTER_MANIP> m_mapFmt;
Setting<EMITTER_MANIP> m_mapKeyFmt;
Setting<std::size_t> m_floatPrecision;
Setting<std::size_t> m_doublePrecision;
Setting<bool> m_showTrailingZero;
SettingChanges m_modifiedSettings;
SettingChanges m_globalModifiedSettings;
@@ -196,7 +182,6 @@ class EmitterState {
std::vector<std::unique_ptr<Group>> m_groups;
std::size_t m_curIndent;
bool m_hasAnchor;
bool m_hasAlias;
bool m_hasTag;
bool m_hasNonContent;
std::size_t m_docCount;
+73 -162
View File
@@ -1,5 +1,3 @@
#include <algorithm>
#include <cstdint>
#include <iomanip>
#include <sstream>
@@ -39,7 +37,7 @@ bool IsAnchorChar(int ch) { // test for ns-anchor-char
return false;
}
if (ch <= 0x7E) {
if (ch < 0x7E) {
return true;
}
@@ -89,8 +87,8 @@ int Utf8BytesIndicated(char ch) {
bool IsTrailingByte(char ch) { return (ch & 0xC0) == 0x80; }
bool GetNextCodePointAndAdvance(int& codePoint,
const char*& first,
const char* last) {
std::string::const_iterator& first,
std::string::const_iterator last) {
if (first == last)
return false;
@@ -153,39 +151,39 @@ void WriteCodePoint(ostream_wrapper& out, int codePoint) {
}
}
bool IsValidPlainScalar(const char* str, std::size_t size, FlowType::value flowType,
bool IsValidPlainScalar(const std::string& str, FlowType::value flowType,
bool allowOnlyAscii) {
// check against null
if (IsNullString(str, size)) {
if (IsNullString(str)) {
return false;
}
// check the start
const RegEx& start = (flowType == FlowType::Flow ? Exp::PlainScalarInFlow()
: Exp::PlainScalar());
if (!start.Matches(StringCharSource(str, size))) {
if (!start.Matches(str)) {
return false;
}
// and check the end for plain whitespace (which can't be faithfully kept in a
// plain scalar)
if (size != 0 && str[size - 1] == ' ') {
if (!str.empty() && *str.rbegin() == ' ') {
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 =
Exp::Tab();
static const RegEx& disallowed_block =
Exp::EndScalar() | (Exp::BlankOrBreak() + Exp::Comment()) |
Exp::NotPrintable() | Exp::Utf8_ByteOrderMark() | Exp::Break() |
Exp::Tab() | Exp::Ampersand();
Exp::Tab();
const RegEx& disallowed =
flowType == FlowType::Flow ? disallowed_flow : disallowed_block;
StringCharSource buffer(str, size);
StringCharSource buffer(str.c_str(), str.size());
while (buffer) {
if (disallowed.Matches(buffer)) {
return false;
@@ -199,54 +197,48 @@ bool IsValidPlainScalar(const char* str, std::size_t size, FlowType::value flowT
return true;
}
bool IsValidSingleQuotedScalar(const char* str, std::size_t size, bool escapeNonAscii) {
bool IsValidSingleQuotedScalar(const std::string& str, bool escapeNonAscii) {
// TODO: check for non-printable characters?
return std::none_of(str, str + size, [=](char ch) {
return (escapeNonAscii && (0x80 <= static_cast<unsigned char>(ch))) ||
(ch == '\n');
});
for (std::size_t i = 0; i < str.size(); i++) {
if (escapeNonAscii && (0x80 <= static_cast<unsigned char>(str[i]))) {
return false;
}
if (str[i] == '\n') {
return false;
}
}
return true;
}
bool IsValidLiteralScalar(const char* str, std::size_t size, FlowType::value flowType,
bool IsValidLiteralScalar(const std::string& str, FlowType::value flowType,
bool escapeNonAscii) {
if (flowType == FlowType::Flow) {
return false;
}
// TODO: check for non-printable characters?
return std::none_of(str, str + size, [=](char ch) {
return (escapeNonAscii && (0x80 <= static_cast<unsigned char>(ch)));
});
for (std::size_t i = 0; i < str.size(); i++) {
if (escapeNonAscii && (0x80 <= static_cast<unsigned char>(str[i]))) {
return false;
}
}
return true;
}
std::pair<uint16_t, uint16_t> EncodeUTF16SurrogatePair(int codePoint) {
const uint32_t leadOffset = 0xD800 - (0x10000 >> 10);
return {
leadOffset | (codePoint >> 10),
0xDC00 | (codePoint & 0x3FF),
};
}
void WriteDoubleQuoteEscapeSequence(ostream_wrapper& out, int codePoint, StringEscaping::value stringEscapingStyle) {
void WriteDoubleQuoteEscapeSequence(ostream_wrapper& out, int codePoint) {
static const char hexDigits[] = "0123456789abcdef";
out << "\\";
int digits = 8;
if (codePoint < 0xFF && stringEscapingStyle != StringEscaping::JSON) {
if (codePoint < 0xFF) {
out << "x";
digits = 2;
} else if (codePoint < 0xFFFF) {
out << "u";
digits = 4;
} else if (stringEscapingStyle != StringEscaping::JSON) {
} else {
out << "U";
digits = 8;
} else {
auto surrogatePair = EncodeUTF16SurrogatePair(codePoint);
WriteDoubleQuoteEscapeSequence(out, surrogatePair.first, stringEscapingStyle);
WriteDoubleQuoteEscapeSequence(out, surrogatePair.second, stringEscapingStyle);
return;
}
// Write digits into the escape sequence
@@ -254,10 +246,10 @@ void WriteDoubleQuoteEscapeSequence(ostream_wrapper& out, int codePoint, StringE
out << hexDigits[(codePoint >> (4 * (digits - 1))) & 0xF];
}
bool WriteAliasName(ostream_wrapper& out, const char* str, std::size_t size) {
bool WriteAliasName(ostream_wrapper& out, const std::string& str) {
int codePoint;
for (const char* i = str;
GetNextCodePointAndAdvance(codePoint, i, str + size);) {
for (std::string::const_iterator i = str.begin();
GetNextCodePointAndAdvance(codePoint, i, str.end());) {
if (!IsAnchorChar(codePoint)) {
return false;
}
@@ -268,25 +260,25 @@ bool WriteAliasName(ostream_wrapper& out, const char* str, std::size_t size) {
}
} // namespace
StringFormat::value ComputeStringFormat(const char* str, std::size_t size,
StringFormat::value ComputeStringFormat(const std::string& str,
EMITTER_MANIP strFormat,
FlowType::value flowType,
bool escapeNonAscii) {
switch (strFormat) {
case Auto:
if (IsValidPlainScalar(str, size, flowType, escapeNonAscii)) {
if (IsValidPlainScalar(str, flowType, escapeNonAscii)) {
return StringFormat::Plain;
}
return StringFormat::DoubleQuoted;
case SingleQuoted:
if (IsValidSingleQuotedScalar(str, size, escapeNonAscii)) {
if (IsValidSingleQuotedScalar(str, escapeNonAscii)) {
return StringFormat::SingleQuoted;
}
return StringFormat::DoubleQuoted;
case DoubleQuoted:
return StringFormat::DoubleQuoted;
case Literal:
if (IsValidLiteralScalar(str, size, flowType, escapeNonAscii)) {
if (IsValidLiteralScalar(str, flowType, escapeNonAscii)) {
return StringFormat::Literal;
}
return StringFormat::DoubleQuoted;
@@ -297,38 +289,11 @@ StringFormat::value ComputeStringFormat(const char* str, std::size_t size,
return StringFormat::DoubleQuoted;
}
StringFormat::value ComputeBinaryFormat(const Binary &bin,
EMITTER_MANIP strFormat,
FlowType::value flowType) {
// Equivalent to calling ComputeStringFormat with the base64
// encoded form of 'bin'.
switch (strFormat) {
case Auto:
if (bin.size() > 0u) {
return StringFormat::Plain;
}
return StringFormat::DoubleQuoted;
case SingleQuoted:
return StringFormat::SingleQuoted;
case DoubleQuoted:
return StringFormat::DoubleQuoted;
case Literal:
if (flowType == FlowType::Flow) {
return StringFormat::DoubleQuoted;
}
return StringFormat::Literal;
default:
break;
}
return StringFormat::DoubleQuoted;
}
bool WriteSingleQuotedString(ostream_wrapper& out, const char* str, std::size_t size) {
bool WriteSingleQuotedString(ostream_wrapper& out, const std::string& str) {
out << "'";
int codePoint;
for (const char* i = str;
GetNextCodePointAndAdvance(codePoint, i, str + size);) {
for (std::string::const_iterator i = str.begin();
GetNextCodePointAndAdvance(codePoint, i, str.end());) {
if (codePoint == '\n') {
return false; // We can't handle a new line and the attendant indentation
// yet
@@ -344,12 +309,12 @@ bool WriteSingleQuotedString(ostream_wrapper& out, const char* str, std::size_t
return true;
}
bool WriteDoubleQuotedString(ostream_wrapper& out, const char* str, std::size_t size,
StringEscaping::value stringEscaping) {
bool WriteDoubleQuotedString(ostream_wrapper& out, const std::string& str,
bool escapeNonAscii) {
out << "\"";
int codePoint;
for (const char* i = str;
GetNextCodePointAndAdvance(codePoint, i, str + size);) {
for (std::string::const_iterator i = str.begin();
GetNextCodePointAndAdvance(codePoint, i, str.end());) {
switch (codePoint) {
case '\"':
out << "\\\"";
@@ -369,19 +334,16 @@ bool WriteDoubleQuotedString(ostream_wrapper& out, const char* str, std::size_t
case '\b':
out << "\\b";
break;
case '\f':
out << "\\f";
break;
default:
if (codePoint < 0x20 ||
(codePoint >= 0x80 &&
codePoint <= 0xA0)) { // Control characters and non-breaking space
WriteDoubleQuoteEscapeSequence(out, codePoint, stringEscaping);
WriteDoubleQuoteEscapeSequence(out, codePoint);
} else if (codePoint == 0xFEFF) { // Byte order marks (ZWNS) should be
// escaped (YAML 1.2, sec. 5.2)
WriteDoubleQuoteEscapeSequence(out, codePoint, stringEscaping);
} else if (stringEscaping == StringEscaping::NonAscii && codePoint > 0x7E) {
WriteDoubleQuoteEscapeSequence(out, codePoint, stringEscaping);
WriteDoubleQuoteEscapeSequence(out, codePoint);
} else if (escapeNonAscii && codePoint > 0x7E) {
WriteDoubleQuoteEscapeSequence(out, codePoint);
} else {
WriteCodePoint(out, codePoint);
}
@@ -391,78 +353,53 @@ bool WriteDoubleQuotedString(ostream_wrapper& out, const char* str, std::size_t
return true;
}
bool WriteLiteralString(ostream_wrapper& out, const char* str, std::size_t size,
bool WriteLiteralString(ostream_wrapper& out, const std::string& str,
std::size_t indent) {
// depending on the numbers of new lines at the end of the string
// we need to use 'clip (-)', 'strip (default)' or 'keep' (+) annotation.
// if there is no newline at the end, we need 'clip'
// if there is single new line at the end, we need 'strip'
// otherwise 'keep'
//
// see YAML spec 1.2 chapter '8.1.1.2 Block Chomping Indicator' for more information
// https://yaml.org/spec/1.2.2/#8112-block-chomping-indicator
// The chomping depends on the number of new lines.
// The output following this 'WriteLiteralString' call will add an additional '\n',
// because of this we need to remove one in the case of 'strip' and 'keep'.
if (size == 0 || str[size-1] != '\n') { // clip
out << "|-\n";
} else if (size == 1 || str[size-2] != '\n') { // strip
out << "|\n";
size -= 1;
} else { // 'keep'
out << "|+\n";
size -= 1;
}
out << "|\n";
out << IndentTo(indent);
int codePoint;
for (const char* i = str;
GetNextCodePointAndAdvance(codePoint, i, str + size);) {
for (std::string::const_iterator i = str.begin();
GetNextCodePointAndAdvance(codePoint, i, str.end());) {
if (codePoint == '\n') {
out << "\n";
out << "\n" << IndentTo(indent);
} else {
out<< IndentTo(indent);
WriteCodePoint(out, codePoint);
}
}
return true;
}
bool WriteChar(ostream_wrapper& out, char ch, StringEscaping::value stringEscapingStyle) {
bool WriteChar(ostream_wrapper& out, char ch) {
if (('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z')) {
out << ch;
} else if (ch == '\"') {
out << R"("\"")";
out << "\"\\\"\"";
} else if (ch == '\t') {
out << R"("\t")";
out << "\"\\t\"";
} else if (ch == '\n') {
out << R"("\n")";
out << "\"\\n\"";
} else if (ch == '\b') {
out << R"("\b")";
} else if (ch == '\r') {
out << R"("\r")";
} else if (ch == '\f') {
out << R"("\f")";
out << "\"\\b\"";
} else if (ch == '\\') {
out << R"("\\")";
out << "\"\\\\\"";
} else if (0x20 <= ch && ch <= 0x7e) {
out << "\"" << ch << "\"";
} else {
out << "\"";
WriteDoubleQuoteEscapeSequence(out, ch, stringEscapingStyle);
WriteDoubleQuoteEscapeSequence(out, ch);
out << "\"";
}
return true;
}
bool WriteComment(ostream_wrapper& out, const char* str, std::size_t size,
bool WriteComment(ostream_wrapper& out, const std::string& str,
std::size_t postCommentIndent) {
const std::size_t curIndent = out.col();
out << "#" << Indentation(postCommentIndent);
out.set_comment();
int codePoint;
for (const char* i = str;
GetNextCodePointAndAdvance(codePoint, i, str + size);) {
for (std::string::const_iterator i = str.begin();
GetNextCodePointAndAdvance(codePoint, i, str.end());) {
if (codePoint == '\n') {
out << "\n"
<< IndentTo(curIndent) << "#" << Indentation(postCommentIndent);
@@ -474,14 +411,14 @@ bool WriteComment(ostream_wrapper& out, const char* str, std::size_t size,
return true;
}
bool WriteAlias(ostream_wrapper& out, const char* str, std::size_t size) {
bool WriteAlias(ostream_wrapper& out, const std::string& str) {
out << "*";
return WriteAliasName(out, str, size);
return WriteAliasName(out, str);
}
bool WriteAnchor(ostream_wrapper& out, const char* str, std::size_t size) {
bool WriteAnchor(ostream_wrapper& out, const std::string& str) {
out << "&";
return WriteAliasName(out, str, size);
return WriteAliasName(out, str);
}
bool WriteTag(ostream_wrapper& out, const std::string& str, bool verbatim) {
@@ -538,35 +475,9 @@ bool WriteTagWithPrefix(ostream_wrapper& out, const std::string& prefix,
}
bool WriteBinary(ostream_wrapper& out, const Binary& binary) {
std::string encoded = EncodeBase64(binary.data(), binary.size());
return WriteDoubleQuotedString(out, encoded.data(), encoded.size(),
StringEscaping::None);
WriteDoubleQuotedString(out, EncodeBase64(binary.data(), binary.size()),
false);
return true;
}
bool WriteLiteralBinary(ostream_wrapper& out, const Binary& binary, std::size_t indent, std::size_t wrap) {
std::string encoded = EncodeBase64(binary.data(), binary.size());
std::string wrapped = "";
if (wrap) {
if (wrap <= indent) return false;
wrap -= indent;
std::size_t point = wrap;
for (std::size_t i = 0; i < encoded.size(); i++) {
if (i == point) {
wrapped += '\n';
point += wrap;
}
wrapped += encoded[i];
}
}
else
wrapped = encoded;
return WriteLiteralString(out, wrapped.data(), wrapped.size(), indent);
}
bool WriteSingleQuotedBinary(ostream_wrapper& out, const Binary& binary) {
std::string encoded = EncodeBase64(binary.data(), binary.size());
return WriteSingleQuotedString(out, encoded.data(), encoded.size());
}
} // namespace Utils
} // namespace YAML
+9 -19
View File
@@ -24,36 +24,26 @@ struct StringFormat {
enum value { Plain, SingleQuoted, DoubleQuoted, Literal };
};
struct StringEscaping {
enum value { None, NonAscii, JSON };
};
namespace Utils {
StringFormat::value ComputeStringFormat(const char* str, std::size_t size,
StringFormat::value ComputeStringFormat(const std::string& str,
EMITTER_MANIP strFormat,
FlowType::value flowType,
bool escapeNonAscii);
StringFormat::value ComputeBinaryFormat(const Binary &bin,
EMITTER_MANIP strFormat,
FlowType::value flowType);
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 char* str, std::size_t size,
bool WriteSingleQuotedString(ostream_wrapper& out, const std::string& str);
bool WriteDoubleQuotedString(ostream_wrapper& out, const std::string& str,
bool escapeNonAscii);
bool WriteLiteralString(ostream_wrapper& out, const std::string& str,
std::size_t indent);
bool WriteChar(ostream_wrapper& out, char ch,
StringEscaping::value stringEscapingStyle);
bool WriteComment(ostream_wrapper& out, const char* str, std::size_t size,
bool WriteChar(ostream_wrapper& out, char ch);
bool WriteComment(ostream_wrapper& out, const std::string& str,
std::size_t postCommentIndent);
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 WriteAlias(ostream_wrapper& out, const std::string& str);
bool WriteAnchor(ostream_wrapper& out, const std::string& str);
bool WriteTag(ostream_wrapper& out, const std::string& str, bool verbatim);
bool WriteTagWithPrefix(ostream_wrapper& out, const std::string& prefix,
const std::string& tag);
bool WriteBinary(ostream_wrapper& out, const Binary& binary);
bool WriteSingleQuotedBinary(ostream_wrapper& out, const Binary& binary);
bool WriteLiteralBinary(ostream_wrapper& out, const Binary& binary, std::size_t indent, std::size_t wrap);
}
}
+26 -16
View File
@@ -1,21 +1,31 @@
#include "yaml-cpp/exceptions.h"
#include "yaml-cpp/noexcept.h"
// This is here for compatibility with older versions of Visual Studio
// which don't support noexcept
#if defined(_MSC_VER) && _MSC_VER < 1900
#define YAML_CPP_NOEXCEPT _NOEXCEPT
#else
#define YAML_CPP_NOEXCEPT noexcept
#endif
namespace YAML {
// These destructors are defined out-of-line so the vtable is only emitted once.
Exception::~Exception() YAML_CPP_NOEXCEPT = default;
ParserException::~ParserException() YAML_CPP_NOEXCEPT = default;
RepresentationException::~RepresentationException() YAML_CPP_NOEXCEPT = default;
InvalidScalar::~InvalidScalar() YAML_CPP_NOEXCEPT = default;
KeyNotFound::~KeyNotFound() YAML_CPP_NOEXCEPT = default;
InvalidNode::~InvalidNode() YAML_CPP_NOEXCEPT = default;
BadConversion::~BadConversion() YAML_CPP_NOEXCEPT = default;
BadDereference::~BadDereference() YAML_CPP_NOEXCEPT = default;
BadSubscript::~BadSubscript() YAML_CPP_NOEXCEPT = default;
BadPushback::~BadPushback() YAML_CPP_NOEXCEPT = default;
BadInsert::~BadInsert() YAML_CPP_NOEXCEPT = default;
EmitterException::~EmitterException() YAML_CPP_NOEXCEPT = default;
BadFile::~BadFile() YAML_CPP_NOEXCEPT = default;
NonUniqueMapKey::~NonUniqueMapKey() YAML_CPP_NOEXCEPT = default;
} // namespace YAML
Exception::~Exception() YAML_CPP_NOEXCEPT {}
ParserException::~ParserException() YAML_CPP_NOEXCEPT {}
RepresentationException::~RepresentationException() YAML_CPP_NOEXCEPT {}
InvalidScalar::~InvalidScalar() YAML_CPP_NOEXCEPT {}
KeyNotFound::~KeyNotFound() YAML_CPP_NOEXCEPT {}
InvalidNode::~InvalidNode() YAML_CPP_NOEXCEPT {}
BadConversion::~BadConversion() YAML_CPP_NOEXCEPT {}
BadDereference::~BadDereference() YAML_CPP_NOEXCEPT {}
BadSubscript::~BadSubscript() YAML_CPP_NOEXCEPT {}
BadPushback::~BadPushback() YAML_CPP_NOEXCEPT {}
BadInsert::~BadInsert() YAML_CPP_NOEXCEPT {}
EmitterException::~EmitterException() YAML_CPP_NOEXCEPT {}
BadFile::~BadFile() YAML_CPP_NOEXCEPT {}
}
#undef YAML_CPP_NOEXCEPT
+14 -15
View File
@@ -12,7 +12,8 @@ namespace YAML {
namespace Exp {
unsigned ParseHex(const std::string& str, const Mark& mark) {
unsigned value = 0;
for (char ch : str) {
for (std::size_t i = 0; i < str.size(); i++) {
char ch = str[i];
int digit = 0;
if ('a' <= ch && ch <= 'f')
digit = ch - 'a' + 10;
@@ -54,16 +55,14 @@ std::string Escape(Stream& in, int codeLength) {
// now break it up into chars
if (value <= 0x7F)
return Str(value);
if (value <= 0x7FF)
else if (value <= 0x7FF)
return Str(0xC0 + (value >> 6)) + Str(0x80 + (value & 0x3F));
if (value <= 0xFFFF)
else if (value <= 0xFFFF)
return Str(0xE0 + (value >> 12)) + Str(0x80 + ((value >> 6) & 0x3F)) +
Str(0x80 + (value & 0x3F));
return Str(0xF0 + (value >> 18)) + Str(0x80 + ((value >> 12) & 0x3F)) +
Str(0x80 + ((value >> 6) & 0x3F)) + Str(0x80 + (value & 0x3F));
else
return Str(0xF0 + (value >> 18)) + Str(0x80 + ((value >> 12) & 0x3F)) +
Str(0x80 + ((value >> 6) & 0x3F)) + Str(0x80 + (value & 0x3F));
}
// Escape
@@ -105,7 +104,7 @@ std::string Escape(Stream& in) {
case 'e':
return "\x1B";
case ' ':
return R"( )";
return "\x20";
case '\"':
return "\"";
case '\'':
@@ -115,13 +114,13 @@ std::string Escape(Stream& in) {
case '/':
return "/";
case 'N':
return "\xC2\x85"; // NEL (U+0085)
return "\x85";
case '_':
return "\xC2\xA0"; // NBSP (U+00A0)
return "\xA0";
case 'L':
return "\xE2\x80\xA8"; // LS (U+2028)
return "\xE2\x80\xA8"; // LS (#x2028)
case 'P':
return "\xE2\x80\xA9"; // PS (U+2029)
return "\xE2\x80\xA9"; // PS (#x2029)
case 'x':
return Escape(in, 2);
case 'u':
@@ -133,5 +132,5 @@ std::string Escape(Stream& in) {
std::stringstream msg;
throw ParserException(in.mark(), std::string(ErrorMsg::INVALID_ESCAPE) + ch);
}
} // namespace Exp
} // namespace YAML
}
}
+3 -7
View File
@@ -37,7 +37,7 @@ inline const RegEx& Blank() {
return e;
}
inline const RegEx& Break() {
static const RegEx e = RegEx('\n') | RegEx("\r\n") | RegEx('\r');
static const RegEx e = RegEx('\n') | RegEx("\r\n");
return e;
}
inline const RegEx& BlankOrBreak() {
@@ -110,17 +110,13 @@ inline const RegEx& Value() {
return e;
}
inline const RegEx& ValueInFlow() {
static const RegEx e = RegEx(':') + (BlankOrBreak() | RegEx(",]}", REGEX_OR));
static const RegEx e = RegEx(':') + (BlankOrBreak() | RegEx(",}", REGEX_OR));
return e;
}
inline const RegEx& ValueInJSONFlow() {
static const RegEx e = RegEx(':');
return e;
}
inline const RegEx& Ampersand() {
static const RegEx e = RegEx('&');
return e;
}
inline const RegEx Comment() {
static const RegEx e = RegEx('#');
return e;
@@ -159,7 +155,7 @@ inline const RegEx& PlainScalar() {
inline const RegEx& PlainScalarInFlow() {
static const RegEx e =
!(BlankOrBreak() | RegEx("?,[]{}#&*!|>\'\"%@`", REGEX_OR) |
(RegEx("-:", REGEX_OR) + (Blank() | RegEx())));
(RegEx("-:", REGEX_OR) + Blank()));
return e;
}
inline const RegEx& EndScalar() {
-256
View File
@@ -1,256 +0,0 @@
#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, uint64_t value, int width=1) {
// precondition of this function (will trigger in debug build)
assert(width >= 1);
assert(end >= begin); // end must be after begin
assert(end-begin >= width); // Buffer must be large enough
assert(end-begin >= 20); // 2^64 has 20digits, so at least 20 digits must be available
// defensive programming, abort if precondition are not met (will trigger in release build)
if (width < 1) {
return -1;
}
if (end < begin) {
return -1;
}
if (end-begin < width) {
return -1;
}
if (end-begin < 20) {
return -1;
}
// count number of digits, and fill digits array accordingly
int digits_ct{};
while (value > 0) {
char c = value % 10 + '0';
value = value / 10;
digits_ct += 1;
*(end-digits_ct) = c;
}
while(digits_ct < width) {
assert(digits_ct < 64);
digits_ct += 1;
*(end-digits_ct) = '0';
}
// move data to the front of the array
std::memmove(begin, end-digits_ct, digits_ct);
return digits_ct;
}
/**
* Converts a float or double to a string.
*
* converts a value 'v' to a string. Uses dragonbox for formatting.
*/
template <typename T>
std::string FpToString(T v, int precision = 0) {
// hard coded constant, at which exponent should switch to a scientific notation
int const lowerExponentThreshold = -5;
int const upperExponentThreshold = (precision==0)?6:precision;
if (precision == 0) {
precision = 6;
}
// dragonbox/to_decimal does not handle value 0, inf, NaN
if (v == 0 || std::isinf(v) || std::isnan(v)) {
std::stringstream ss;
ss.imbue(std::locale::classic());
ss << v;
return ss.str();
}
auto r = jkj::dragonbox::to_decimal(v);
auto digits = std::array<char, 20>{}; // max digits of size_t is 20.
auto digits_ct = ConvertToChars(digits.data(), digits.data() + digits.size(), r.significand);
// defensive programming, ConvertToChars arguments are invalid
if (digits_ct == -1) {
std::stringstream ss;
ss.imbue(std::locale::classic());
ss << v;
return ss.str();
}
// check if requested precision is lower than
// required digits for exact representation
if (digits_ct > precision) {
auto diff = digits_ct - precision;
r.exponent += diff;
digits_ct = precision;
// round numbers if required
if (digits[digits_ct] >= '5') {
int i{digits_ct-1};
digits[i] += 1;
while (digits[i] == '9'+1) {
digits_ct -= 1;
r.exponent += 1;
if (i > 0) {
digits[i-1] += 1;
i -= 1;
} else {
digits_ct = 1;
digits[0] = '1';
break;
}
}
}
}
// Case 1 - scientific notation: max digits of size_t plus sign, a dot and 2 letters for 'e+' or 'e-' and 4 letters for the exponent
// Case 2 - default notation: require up to precision number of digits and one for a potential sign
std::array<char, 28> output_buffer;
auto output_ptr = &output_buffer[0];
// Helper variable that in Case 2 counts the overflowing number of zeros that do not fit into the buffer.
int overflow_zeros = 0;
// print '-' symbol for negative numbers
if (r.is_negative) {
*(output_ptr++) = '-';
}
// exponent if only a single non-zero digit is before the decimal point
int const exponent = r.exponent + digits_ct - 1;
// case 1: scientific notation
if (exponent >= upperExponentThreshold || exponent <= lowerExponentThreshold) {
// print first digit
*(output_ptr++) = digits[0];
// print digits after decimal point
if (digits_ct > 1) {
*(output_ptr++) = '.';
// print significant numbers after decimal point
for (int i{1}; i < digits_ct; ++i) {
*(output_ptr++) = digits[i];
}
}
*(output_ptr++) = 'e';
*(output_ptr++) = (exponent>=0)?'+':'-';
auto exp_digits = std::array<char, 20>{};
auto exp_digits_ct = ConvertToChars(exp_digits.data(), exp_digits.data() + exp_digits.size(), std::abs(exponent), /*.precision=*/ 2);
// defensive programming, ConvertToChars arguments are invalid
if (exp_digits_ct == -1) {
std::stringstream ss;
ss.imbue(std::locale::classic());
ss << v;
return ss.str();
}
for (int i{0}; i < exp_digits_ct; ++i) {
*(output_ptr++) = exp_digits[i];
}
// case 2: default notation
} else {
auto const digits_end = digits.begin() + digits_ct;
auto digits_iter = digits.begin();
// print digits before point
int const before_decimal_digits = digits_ct + r.exponent;
if (before_decimal_digits > 0) {
// print non-zero digits before point
for (int i{0}; i < std::min(before_decimal_digits, digits_ct); ++i) {
*(output_ptr++) = *(digits_iter++);
}
// number of digits that have to be zero
int const zero_digits_ct = before_decimal_digits - digits_ct;
// space left in the output_buffer (-1 because we need it for null-termination)
int const buffer_empty_space = static_cast<int>(
output_buffer.data() + output_buffer.size() - output_ptr - 1);
// print all zeros not fitting into the buffer at the end of the function
overflow_zeros = std::max(0, zero_digits_ct - buffer_empty_space);
// print trailing zeros before point
for (int i{0}; i < zero_digits_ct - overflow_zeros; ++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';
auto ret_value = std::string{&output_buffer[0], output_ptr};
ret_value.resize(ret_value.size() + overflow_zeros, '0');
return ret_value;
}
}
}
std::string FpToString(float v, size_t precision) {
return detail::fp_formatting::FpToString(v, static_cast<int>(precision));
}
std::string FpToString(double v, size_t precision) {
return detail::fp_formatting::FpToString(v, static_cast<int>(precision));
}
/**
* dragonbox only works for floats/doubles not long double
*/
std::string FpToString(long double v, size_t precision) {
std::stringstream ss;
ss.imbue(std::locale::classic());
if (precision == 0) {
precision = std::numeric_limits<long double>::max_digits10;
}
ss.precision(precision);
ss << v;
return ss.str();
}
}
+1
View File
@@ -7,6 +7,7 @@
#pragma once
#endif
#include <iostream>
#include <cstddef>
#include "yaml-cpp/ostream_wrapper.h"
+2 -10
View File
@@ -9,16 +9,12 @@ void memory_holder::merge(memory_holder& rhs) {
if (m_pMemory == rhs.m_pMemory)
return;
if (m_pMemory->size() < rhs.m_pMemory->size()) {
std::swap(m_pMemory, rhs.m_pMemory);
}
m_pMemory->merge(*rhs.m_pMemory);
rhs.m_pMemory = m_pMemory;
}
node& memory::create_node() {
shared_node pNode(std::make_shared<node>());
shared_node pNode(new node);
m_nodes.insert(pNode);
return *pNode;
}
@@ -26,9 +22,5 @@ node& memory::create_node() {
void memory::merge(const memory& rhs) {
m_nodes.insert(rhs.m_nodes.begin(), rhs.m_nodes.end());
}
size_t memory::size() const {
return m_nodes.size();
}
} // namespace detail
} // namespace YAML
}
+1 -1
View File
@@ -9,4 +9,4 @@ Node Clone(const Node& node) {
events.Emit(builder);
return builder.Root();
}
} // namespace YAML
}
+35 -49
View File
@@ -1,5 +1,4 @@
#include <algorithm>
#include <cassert>
#include <assert.h>
#include <iterator>
#include <sstream>
@@ -13,7 +12,6 @@
namespace YAML {
namespace detail {
YAML_CPP_API std::atomic<size_t> node::m_amount{0};
const std::string& node_data::empty_scalar() {
static const std::string svalue;
@@ -110,9 +108,9 @@ void node_data::compute_seq_size() const {
}
void node_data::compute_map_size() const {
auto it = m_undefinedPairs.begin();
kv_pairs::iterator it = m_undefinedPairs.begin();
while (it != m_undefinedPairs.end()) {
auto jt = std::next(it);
kv_pairs::iterator jt = std::next(it);
if (it->first->is_defined() && it->second->is_defined())
m_undefinedPairs.erase(it);
it = jt;
@@ -121,7 +119,7 @@ void node_data::compute_map_size() const {
const_node_iterator node_data::begin() const {
if (!m_isDefined)
return {};
return const_node_iterator();
switch (m_type) {
case NodeType::Sequence:
@@ -129,13 +127,13 @@ const_node_iterator node_data::begin() const {
case NodeType::Map:
return const_node_iterator(m_map.begin(), m_map.end());
default:
return {};
return const_node_iterator();
}
}
node_iterator node_data::begin() {
if (!m_isDefined)
return {};
return node_iterator();
switch (m_type) {
case NodeType::Sequence:
@@ -143,13 +141,13 @@ node_iterator node_data::begin() {
case NodeType::Map:
return node_iterator(m_map.begin(), m_map.end());
default:
return {};
return node_iterator();
}
}
const_node_iterator node_data::end() const {
if (!m_isDefined)
return {};
return const_node_iterator();
switch (m_type) {
case NodeType::Sequence:
@@ -157,13 +155,13 @@ const_node_iterator node_data::end() const {
case NodeType::Map:
return const_node_iterator(m_map.end(), m_map.end());
default:
return {};
return const_node_iterator();
}
}
node_iterator node_data::end() {
if (!m_isDefined)
return {};
return node_iterator();
switch (m_type) {
case NodeType::Sequence:
@@ -171,13 +169,12 @@ node_iterator node_data::end() {
case NodeType::Map:
return node_iterator(m_map.end(), m_map.end());
default:
return {};
return node_iterator();
}
}
// sequence
void node_data::push_back(node& node,
const shared_memory_holder& /* pMemory */) {
void node_data::push_back(node& node, shared_memory_holder /* pMemory */) {
if (m_type == NodeType::Undefined || m_type == NodeType::Null) {
m_type = NodeType::Sequence;
reset_sequence();
@@ -189,8 +186,7 @@ void node_data::push_back(node& node,
m_sequence.push_back(&node);
}
void node_data::insert(node& key, node& value,
const shared_memory_holder& pMemory) {
void node_data::insert(node& key, node& value, shared_memory_holder pMemory) {
switch (m_type) {
case NodeType::Map:
break;
@@ -200,28 +196,27 @@ void node_data::insert(node& key, node& value,
convert_to_map(pMemory);
break;
case NodeType::Scalar:
throw BadSubscript(m_mark, key);
throw BadSubscript();
}
insert_map_pair(key, value);
}
// indexing
node* node_data::get(node& key,
const shared_memory_holder& /* pMemory */) const {
node* node_data::get(node& key, shared_memory_holder /* pMemory */) const {
if (m_type != NodeType::Map) {
return nullptr;
}
for (const auto& it : m_map) {
if (it.first->is(key))
return it.second;
for (node_map::const_iterator it = m_map.begin(); it != m_map.end(); ++it) {
if (it->first->is(key))
return it->second;
}
return nullptr;
}
node& node_data::get(node& key, const shared_memory_holder& pMemory) {
node& node_data::get(node& key, shared_memory_holder pMemory) {
switch (m_type) {
case NodeType::Map:
break;
@@ -231,12 +226,12 @@ node& node_data::get(node& key, const shared_memory_holder& pMemory) {
convert_to_map(pMemory);
break;
case NodeType::Scalar:
throw BadSubscript(m_mark, key);
throw BadSubscript();
}
for (const auto& it : m_map) {
if (it.first->is(key))
return *it.second;
for (node_map::const_iterator it = m_map.begin(); it != m_map.end(); ++it) {
if (it->first->is(key))
return *it->second;
}
node& value = pMemory->create_node();
@@ -244,26 +239,23 @@ node& node_data::get(node& key, const shared_memory_holder& pMemory) {
return value;
}
bool node_data::remove(node& key, const shared_memory_holder& /* pMemory */) {
bool node_data::remove(node& key, shared_memory_holder /* pMemory */) {
if (m_type != NodeType::Map)
return false;
for (auto it = m_undefinedPairs.begin(); it != m_undefinedPairs.end();) {
auto jt = std::next(it);
for (kv_pairs::iterator it = m_undefinedPairs.begin();
it != m_undefinedPairs.end();) {
kv_pairs::iterator jt = std::next(it);
if (it->first->is(key))
m_undefinedPairs.erase(it);
it = jt;
}
auto it =
std::find_if(m_map.begin(), m_map.end(),
[&](std::pair<YAML::detail::node*, YAML::detail::node*> j) {
return (j.first->is(key));
});
if (it != m_map.end()) {
m_map.erase(it);
return true;
for (node_map::iterator it = m_map.begin(); it != m_map.end(); ++it) {
if (it->first->is(key)) {
m_map.erase(it);
return true;
}
}
return false;
@@ -279,19 +271,14 @@ void node_data::reset_map() {
m_undefinedPairs.clear();
}
void node_data::insert_map_pair(node& key, node& value, bool force) {
if (!force && !key.scalar().empty())
for (const auto& mapEntry : m_map)
if (mapEntry.first->scalar() == key.scalar())
throw NonUniqueMapKey(m_mark, key);
void node_data::insert_map_pair(node& key, node& value) {
m_map.emplace_back(&key, &value);
if (!key.is_defined() || !value.is_defined())
m_undefinedPairs.emplace_back(&key, &value);
}
void node_data::convert_to_map(const shared_memory_holder& pMemory) {
void node_data::convert_to_map(shared_memory_holder pMemory) {
switch (m_type) {
case NodeType::Undefined:
case NodeType::Null:
@@ -309,13 +296,12 @@ void node_data::convert_to_map(const shared_memory_holder& pMemory) {
}
}
void node_data::convert_sequence_to_map(const shared_memory_holder& pMemory) {
void node_data::convert_sequence_to_map(shared_memory_holder pMemory) {
assert(m_type == NodeType::Sequence);
reset_map();
for (std::size_t i = 0; i < m_sequence.size(); i++) {
std::stringstream stream;
stream.imbue(std::locale::classic());
stream << i;
node& key = pMemory->create_node();
+4 -3
View File
@@ -1,3 +1,4 @@
#include <assert.h>
#include <cassert>
#include "nodebuilder.h"
@@ -10,7 +11,7 @@ namespace YAML {
struct Mark;
NodeBuilder::NodeBuilder()
: m_pMemory(std::make_shared<detail::memory_holder>()),
: m_pMemory(new detail::memory_holder),
m_pRoot(nullptr),
m_stack{},
m_anchors{},
@@ -19,7 +20,7 @@ NodeBuilder::NodeBuilder()
m_anchors.push_back(nullptr); // since the anchors start at 1
}
NodeBuilder::~NodeBuilder() = default;
NodeBuilder::~NodeBuilder() {}
Node NodeBuilder::Root() {
if (!m_pRoot)
@@ -92,7 +93,7 @@ void NodeBuilder::Push(detail::node& node) {
m_stack.push_back(&node);
if (needsKey)
m_keys.emplace_back(&node, false);
m_keys.push_back(PushedKey(&node, false));
}
void NodeBuilder::Pop() {
+15 -15
View File
@@ -31,25 +31,25 @@ class NodeBuilder : public EventHandler {
NodeBuilder(NodeBuilder&&) = delete;
NodeBuilder& operator=(const NodeBuilder&) = delete;
NodeBuilder& operator=(NodeBuilder&&) = delete;
~NodeBuilder() override;
virtual ~NodeBuilder();
Node Root();
void OnDocumentStart(const Mark& mark) override;
void OnDocumentEnd() override;
virtual void OnDocumentStart(const Mark& mark);
virtual void OnDocumentEnd();
void OnNull(const Mark& mark, anchor_t anchor) override;
void OnAlias(const Mark& mark, anchor_t anchor) override;
void OnScalar(const Mark& mark, const std::string& tag,
anchor_t anchor, const std::string& value) override;
virtual void OnNull(const Mark& mark, anchor_t anchor);
virtual void OnAlias(const Mark& mark, anchor_t anchor);
virtual void OnScalar(const Mark& mark, const std::string& tag,
anchor_t anchor, const std::string& value);
void OnSequenceStart(const Mark& mark, const std::string& tag,
anchor_t anchor, EmitterStyle::value style) override;
void OnSequenceEnd() override;
virtual void OnSequenceStart(const Mark& mark, const std::string& tag,
anchor_t anchor, EmitterStyle::value style);
virtual void OnSequenceEnd();
void OnMapStart(const Mark& mark, const std::string& tag,
anchor_t anchor, EmitterStyle::value style) override;
void OnMapEnd() override;
virtual void OnMapStart(const Mark& mark, const std::string& tag,
anchor_t anchor, EmitterStyle::value style);
virtual void OnMapEnd();
private:
detail::node& Push(const Mark& mark, anchor_t anchor);
@@ -61,11 +61,11 @@ class NodeBuilder : public EventHandler {
detail::shared_memory_holder m_pMemory;
detail::node* m_pRoot;
using Nodes = std::vector<detail::node *>;
typedef std::vector<detail::node*> Nodes;
Nodes m_stack;
Nodes m_anchors;
using PushedKey = std::pair<detail::node*, bool>;
typedef std::pair<detail::node*, bool> PushedKey;
std::vector<PushedKey> m_keys;
std::size_t m_mapDepth;
};
+19 -16
View File
@@ -13,7 +13,7 @@ void NodeEvents::AliasManager::RegisterReference(const detail::node& node) {
anchor_t NodeEvents::AliasManager::LookupAnchor(
const detail::node& node) const {
auto it = m_anchorByIdentity.find(node.ref());
AnchorByIdentity::const_iterator it = m_anchorByIdentity.find(node.ref());
if (it == m_anchorByIdentity.end())
return 0;
return it->second;
@@ -32,12 +32,13 @@ void NodeEvents::Setup(const detail::node& node) {
return;
if (node.type() == NodeType::Sequence) {
for (auto element : node)
Setup(*element);
for (detail::const_node_iterator it = node.begin(); it != node.end(); ++it)
Setup(**it);
} else if (node.type() == NodeType::Map) {
for (auto element : node) {
Setup(*element.first);
Setup(*element.second);
for (detail::const_node_iterator it = node.begin(); it != node.end();
++it) {
Setup(*it->first);
Setup(*it->second);
}
}
}
@@ -69,22 +70,24 @@ void NodeEvents::Emit(const detail::node& node, EventHandler& handler,
case NodeType::Undefined:
break;
case NodeType::Null:
handler.OnNull(node.mark(), anchor);
handler.OnNull(Mark(), anchor);
break;
case NodeType::Scalar:
handler.OnScalar(node.mark(), node.tag(), anchor, node.scalar());
handler.OnScalar(Mark(), node.tag(), anchor, node.scalar());
break;
case NodeType::Sequence:
handler.OnSequenceStart(node.mark(), node.tag(), anchor, node.style());
for (auto element : node)
Emit(*element, handler, am);
handler.OnSequenceStart(Mark(), node.tag(), anchor, node.style());
for (detail::const_node_iterator it = node.begin(); it != node.end();
++it)
Emit(**it, handler, am);
handler.OnSequenceEnd();
break;
case NodeType::Map:
handler.OnMapStart(node.mark(), node.tag(), anchor, node.style());
for (auto element : node) {
Emit(*element.first, handler, am);
Emit(*element.second, handler, am);
handler.OnMapStart(Mark(), node.tag(), anchor, node.style());
for (detail::const_node_iterator it = node.begin(); it != node.end();
++it) {
Emit(*it->first, handler, am);
Emit(*it->second, handler, am);
}
handler.OnMapEnd();
break;
@@ -92,7 +95,7 @@ void NodeEvents::Emit(const detail::node& node, EventHandler& handler,
}
bool NodeEvents::IsAliased(const detail::node& node) const {
auto it = m_refCount.find(node.ref());
RefCount::const_iterator it = m_refCount.find(node.ref());
return it != m_refCount.end() && it->second > 1;
}
} // namespace YAML
+2 -2
View File
@@ -45,7 +45,7 @@ class NodeEvents {
anchor_t _CreateNewAnchor() { return ++m_curAnchor; }
private:
using AnchorByIdentity = std::map<const detail::node_ref*, anchor_t>;
typedef std::map<const detail::node_ref*, anchor_t> AnchorByIdentity;
AnchorByIdentity m_anchorByIdentity;
anchor_t m_curAnchor;
@@ -60,7 +60,7 @@ class NodeEvents {
detail::shared_memory_holder m_pMemory;
detail::node* m_root;
using RefCount = std::map<const detail::node_ref*, int>;
typedef std::map<const detail::node_ref*, int> RefCount;
RefCount m_refCount;
};
} // namespace YAML
+3 -10
View File
@@ -1,17 +1,10 @@
#include "yaml-cpp/null.h"
#include <cstring>
namespace YAML {
_Null Null;
template <std::size_t N>
static bool same(const char* str, std::size_t size, const char (&literal)[N]) {
constexpr int literalSize = N - 1; // minus null terminator
return size == literalSize && std::strncmp(str, literal, literalSize) == 0;
bool IsNullString(const std::string& str) {
return str.empty() || str == "~" || str == "null" || str == "Null" ||
str == "NULL";
}
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
+4 -4
View File
@@ -2,7 +2,7 @@
#include <algorithm>
#include <cstring>
#include <ostream>
#include <iostream>
namespace YAML {
ostream_wrapper::ostream_wrapper()
@@ -21,7 +21,7 @@ ostream_wrapper::ostream_wrapper(std::ostream& stream)
m_col(0),
m_comment(false) {}
ostream_wrapper::~ostream_wrapper() = default;
ostream_wrapper::~ostream_wrapper() {}
void ostream_wrapper::write(const std::string& str) {
if (m_pStream) {
@@ -31,8 +31,8 @@ void ostream_wrapper::write(const std::string& str) {
std::copy(str.begin(), str.end(), m_buffer.begin() + m_pos);
}
for (char ch : str) {
update_pos(ch);
for (std::size_t i = 0; i < str.size(); i++) {
update_pos(str[i]);
}
}
+7 -7
View File
@@ -3,10 +3,10 @@
#include <fstream>
#include <sstream>
#include "nodebuilder.h"
#include "yaml-cpp/node/impl.h"
#include "yaml-cpp/node/node.h"
#include "yaml-cpp/node/impl.h"
#include "yaml-cpp/parser.h"
#include "nodebuilder.h"
namespace YAML {
Node Load(const std::string& input) {
@@ -30,9 +30,9 @@ Node Load(std::istream& input) {
}
Node LoadFile(const std::string& filename) {
std::ifstream fin(filename);
std::ifstream fin(filename.c_str());
if (!fin) {
throw BadFile(filename);
throw BadFile();
}
return Load(fin);
}
@@ -51,7 +51,7 @@ std::vector<Node> LoadAll(std::istream& input) {
std::vector<Node> docs;
Parser parser(input);
while (true) {
while (1) {
NodeBuilder builder;
if (!parser.HandleNextDocument(builder)) {
break;
@@ -63,9 +63,9 @@ std::vector<Node> LoadAll(std::istream& input) {
}
std::vector<Node> LoadAllFromFile(const std::string& filename) {
std::ifstream fin(filename);
std::ifstream fin(filename.c_str());
if (!fin) {
throw BadFile(filename);
throw BadFile();
}
return LoadAll(fin);
}
+17 -23
View File
@@ -15,9 +15,11 @@ Parser::Parser() : m_pScanner{}, m_pDirectives{} {}
Parser::Parser(std::istream& in) : Parser() { Load(in); }
Parser::~Parser() = default;
Parser::~Parser() {}
Parser::operator bool() const { return m_pScanner && !m_pScanner->empty(); }
Parser::operator bool() const {
return m_pScanner.get() && !m_pScanner->empty();
}
void Parser::Load(std::istream& in) {
m_pScanner.reset(new Scanner(in));
@@ -25,7 +27,7 @@ void Parser::Load(std::istream& in) {
}
bool Parser::HandleNextDocument(EventHandler& eventHandler) {
if (!m_pScanner)
if (!m_pScanner.get())
return false;
ParseDirectives();
@@ -33,30 +35,19 @@ bool Parser::HandleNextDocument(EventHandler& eventHandler) {
return false;
}
auto oldPos = m_pScanner->peek().mark.pos;
SingleDocParser sdp(*m_pScanner, *m_pDirectives);
sdp.HandleDocument(eventHandler);
// checks if progress was made
// 1. if scanner has no more tokens, progress was made
if (m_pScanner->empty()) {
return true;
}
// 2. if token position has changed, progress was made
auto newPos = m_pScanner->peek().mark.pos;
if (newPos != oldPos) {
return true;
}
// No progress was made, no further processing
return false;
return true;
}
void Parser::ParseDirectives() {
bool readDirective = false;
while (!m_pScanner->empty()) {
while (1) {
if (m_pScanner->empty()) {
break;
}
Token& token = m_pScanner->peek();
if (token.type != Token::DIRECTIVE) {
break;
@@ -92,7 +83,6 @@ void Parser::HandleYamlDirective(const Token& token) {
}
std::stringstream str(token.params[0]);
str.imbue(std::locale::classic());
str >> m_pDirectives->version.major;
str.get();
str >> m_pDirectives->version.minor;
@@ -123,11 +113,15 @@ void Parser::HandleTagDirective(const Token& token) {
}
void Parser::PrintTokens(std::ostream& out) {
if (!m_pScanner) {
if (!m_pScanner.get()) {
return;
}
while (!m_pScanner->empty()) {
while (1) {
if (m_pScanner->empty()) {
break;
}
out << m_pScanner->peek() << "\n";
m_pScanner->pop();
}
+1 -1
View File
@@ -34,7 +34,7 @@ class YAML_CPP_API RegEx {
explicit RegEx(char ch);
RegEx(char a, char z);
RegEx(const std::string& str, REGEX_OP op = REGEX_SEQ);
~RegEx() = default;
~RegEx() {}
friend YAML_CPP_API RegEx operator!(const RegEx& ex);
friend YAML_CPP_API RegEx operator|(const RegEx& ex1, const RegEx& ex2);
+12 -15
View File
@@ -8,8 +8,8 @@
#endif
#include "stream.h"
#include "streamcharsource.h"
#include "stringsource.h"
#include "streamcharsource.h"
namespace YAML {
// query matches
@@ -27,10 +27,6 @@ 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;
}
@@ -110,8 +106,9 @@ inline int RegEx::MatchOpEmpty(const Source& source) const {
template <>
inline int RegEx::MatchOpEmpty<StringCharSource>(
const StringCharSource& source) const {
return !source ? 0 : -1; // the empty regex only is successful on the empty
// string
return !source
? 0
: -1; // the empty regex only is successful on the empty string
}
// MatchOperator
@@ -133,8 +130,8 @@ inline int RegEx::MatchOpRange(const Source& source) const {
// OrOperator
template <typename Source>
inline int RegEx::MatchOpOr(const Source& source) const {
for (const RegEx& param : m_params) {
int n = param.MatchUnchecked(source);
for (std::size_t i = 0; i < m_params.size(); i++) {
int n = m_params[i].MatchUnchecked(source);
if (n >= 0)
return n;
}
@@ -172,11 +169,11 @@ inline int RegEx::MatchOpNot(const Source& source) const {
template <typename Source>
inline int RegEx::MatchOpSeq(const Source& source) const {
int offset = 0;
for (const RegEx& param : m_params) {
int n = param.Match(source + offset); // note Match, not
// MatchUnchecked because we
// need to check validity after
// the offset
for (std::size_t i = 0; i < m_params.size(); i++) {
int n = m_params[i].Match(source + offset); // note Match, not
// MatchUnchecked because we
// need to check validity after
// the offset
if (n == -1)
return -1;
offset += n;
@@ -184,6 +181,6 @@ inline int RegEx::MatchOpSeq(const Source& source) const {
return offset;
}
} // namespace YAML
}
#endif // REGEXIMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+4 -28
View File
@@ -13,14 +13,13 @@ Scanner::Scanner(std::istream& in)
m_startedStream(false),
m_endedStream(false),
m_simpleKeyAllowed(false),
m_scalarValueAllowed(false),
m_canBeJSONFlow(false),
m_simpleKeys{},
m_indents{},
m_indentRefs{},
m_flows{} {}
Scanner::~Scanner() = default;
Scanner::~Scanner() {}
bool Scanner::empty() {
EnsureTokensInQueue();
@@ -52,7 +51,7 @@ Token& Scanner::peek() {
Mark Scanner::mark() const { return INPUT.mark(); }
void Scanner::EnsureTokensInQueue() {
while (true) {
while (1) {
if (!m_tokens.empty()) {
Token& token = m_tokens.front();
@@ -89,7 +88,7 @@ void Scanner::ScanNextToken() {
return StartStream();
}
// get rid of whitespace, etc. (in between tokens it should be irrelevant)
// get rid of whitespace, etc. (in between tokens it should be irrelevent)
ScanToNextToken();
// maybe need to end some blocks
@@ -128,17 +127,6 @@ 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();
}
@@ -171,13 +159,6 @@ 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();
}
@@ -193,7 +174,7 @@ void Scanner::ScanNextToken() {
}
void Scanner::ScanToNextToken() {
while (true) {
while (1) {
// first eat whitespace
while (INPUT && IsWhitespaceToBeEaten(INPUT.peek())) {
if (InBlockContext() && Exp::Tab().Matches(INPUT)) {
@@ -222,9 +203,6 @@ 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;
@@ -267,7 +245,6 @@ 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));
@@ -284,7 +261,6 @@ void Scanner::EndStream() {
PopAllSimpleKeys();
m_simpleKeyAllowed = false;
m_scalarValueAllowed = false;
m_endedStream = true;
}
+2 -1
View File
@@ -9,7 +9,9 @@
#include <cstddef>
#include <ios>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
@@ -177,7 +179,6 @@ 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;
+3 -4
View File
@@ -47,8 +47,7 @@ std::string ScanScalar(Stream& INPUT, ScanScalarParams& params) {
if (INPUT.column() == 0 && Exp::DocIndicator().Matches(INPUT)) {
if (params.onDocIndicator == BREAK) {
break;
}
if (params.onDocIndicator == THROW) {
} else if (params.onDocIndicator == THROW) {
throw ParserException(INPUT.mark(), ErrorMsg::DOC_IN_SCALAR);
}
}
@@ -204,7 +203,7 @@ std::string ScanScalar(Stream& INPUT, ScanScalarParams& params) {
// post-processing
if (params.trimTrailingSpaces) {
std::size_t pos = scalar.find_last_not_of(" \t");
std::size_t pos = scalar.find_last_not_of(' ');
if (lastEscapedChar != std::string::npos) {
if (pos < lastEscapedChar || pos == std::string::npos) {
pos = lastEscapedChar;
@@ -248,4 +247,4 @@ std::string ScanScalar(Stream& INPUT, ScanScalarParams& params) {
return scalar;
}
} // namespace YAML
}
+1 -1
View File
@@ -57,7 +57,7 @@ struct ScanScalarParams {
bool leadingSpaces;
};
std::string ScanScalar(Stream& INPUT, ScanScalarParams& params);
std::string ScanScalar(Stream& INPUT, ScanScalarParams& info);
}
#endif // SCANSCALAR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
+1 -1
View File
@@ -78,4 +78,4 @@ const std::string ScanTagSuffix(Stream& INPUT) {
return tag;
}
} // namespace YAML
}
+3 -10
View File
@@ -37,7 +37,7 @@ void Scanner::ScanDirective() {
token.value += INPUT.get();
// read parameters
while (true) {
while (1) {
// first get rid of whitespace
while (Exp::Blank().Matches(INPUT))
INPUT.eat(1);
@@ -171,7 +171,7 @@ void Scanner::ScanBlockEntry() {
// Key
void Scanner::ScanKey() {
// handle keys differently in the block context (and manage indents)
// handle keys diffently in the block context (and manage indents)
if (InBlockContext()) {
if (!m_simpleKeyAllowed)
throw ParserException(INPUT.mark(), ErrorMsg::MAP_KEY);
@@ -199,7 +199,7 @@ void Scanner::ScanValue() {
// seems fine)
m_simpleKeyAllowed = false;
} else {
// handle values differently in the block context (and manage indents)
// handle values diffently in the block context (and manage indents)
if (InBlockContext()) {
if (!m_simpleKeyAllowed)
throw ParserException(INPUT.mark(), ErrorMsg::MAP_VALUE);
@@ -211,9 +211,6 @@ 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);
@@ -363,10 +360,6 @@ 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);
+29 -26
View File
@@ -7,18 +7,12 @@
#pragma once
#endif
#include "yaml-cpp/noexcept.h"
#include <memory>
#include <utility>
#include <vector>
namespace YAML {
class SettingChangeBase {
public:
virtual ~SettingChangeBase() = default;
virtual void pop() = 0;
};
class SettingChangeBase;
template <typename T>
class Setting {
@@ -34,6 +28,12 @@ class Setting {
T m_value;
};
class SettingChangeBase {
public:
virtual ~SettingChangeBase() {}
virtual void pop() = 0;
};
template <typename T>
class SettingChange : public SettingChangeBase {
public:
@@ -46,7 +46,7 @@ class SettingChange : public SettingChangeBase {
SettingChange& operator=(const SettingChange&) = delete;
SettingChange& operator=(SettingChange&&) = delete;
void pop() override { m_pCurSetting->restore(m_oldSetting); }
virtual void pop() { m_pCurSetting->restore(m_oldSetting); }
private:
Setting<T>* m_pCurSetting;
@@ -64,9 +64,27 @@ class SettingChanges {
public:
SettingChanges() : m_settingChanges{} {}
SettingChanges(const SettingChanges&) = delete;
SettingChanges(SettingChanges&&) YAML_CPP_NOEXCEPT = default;
SettingChanges(SettingChanges&&) = default;
SettingChanges& operator=(const SettingChanges&) = delete;
SettingChanges& operator=(SettingChanges&& rhs) YAML_CPP_NOEXCEPT {
~SettingChanges() { clear(); }
void clear() {
restore();
m_settingChanges.clear();
}
void restore() {
for (setting_changes::const_iterator it = m_settingChanges.begin();
it != m_settingChanges.end(); ++it)
(*it)->pop();
}
void push(std::unique_ptr<SettingChangeBase> pSettingChange) {
m_settingChanges.push_back(std::move(pSettingChange));
}
// like std::unique_ptr - assignment is transfer of ownership
SettingChanges& operator=(SettingChanges&& rhs) {
if (this == &rhs)
return *this;
@@ -75,24 +93,9 @@ class SettingChanges {
return *this;
}
~SettingChanges() { clear(); }
void clear() YAML_CPP_NOEXCEPT {
restore();
m_settingChanges.clear();
}
void restore() YAML_CPP_NOEXCEPT {
for (const auto& setting : m_settingChanges)
setting->pop();
}
void push(std::unique_ptr<SettingChangeBase> pSettingChange) {
m_settingChanges.push_back(std::move(pSettingChange));
}
private:
using setting_changes = std::vector<std::unique_ptr<SettingChangeBase>>;
typedef std::vector<std::unique_ptr<SettingChangeBase>> setting_changes;
setting_changes m_settingChanges;
};
} // namespace YAML
+2 -6
View File
@@ -5,11 +5,7 @@ namespace YAML {
struct Mark;
Scanner::SimpleKey::SimpleKey(const Mark& mark_, std::size_t flowLevel_)
: mark(mark_),
flowLevel(flowLevel_),
pIndent(nullptr),
pMapStart(nullptr),
pKey(nullptr) {}
: mark(mark_), flowLevel(flowLevel_), pIndent(nullptr), pMapStart(nullptr), pKey(nullptr) {}
void Scanner::SimpleKey::Validate() {
// Note: pIndent will *not* be garbage here;
@@ -129,4 +125,4 @@ void Scanner::PopAllSimpleKeys() {
while (!m_simpleKeys.empty())
m_simpleKeys.pop();
}
} // namespace YAML
}
+16 -33
View File
@@ -1,3 +1,4 @@
#include <algorithm>
#include <cstdio>
#include <sstream>
@@ -6,7 +7,6 @@
#include "singledocparser.h"
#include "tag.h"
#include "token.h"
#include "yaml-cpp/depthguard.h"
#include "yaml-cpp/emitterstyle.h"
#include "yaml-cpp/eventhandler.h"
#include "yaml-cpp/exceptions.h" // IWYU pragma: keep
@@ -21,7 +21,7 @@ SingleDocParser::SingleDocParser(Scanner& scanner, const Directives& directives)
m_anchors{},
m_curAnchor(0) {}
SingleDocParser::~SingleDocParser() = default;
SingleDocParser::~SingleDocParser() {}
// HandleDocument
// . Handles the next document
@@ -41,19 +41,12 @@ void SingleDocParser::HandleDocument(EventHandler& eventHandler) {
eventHandler.OnDocumentEnd();
// check if any tokens left after the text
if (!m_scanner.empty() && m_scanner.peek().type != Token::DOC_END
&& m_scanner.peek().type != Token::DOC_START)
throw ParserException(m_scanner.mark(), ErrorMsg::UNEXPECTED_TOKEN_AFTER_DOC);
// and finally eat any doc ends we see
if (!m_scanner.empty() && m_scanner.peek().type == Token::DOC_END)
while (!m_scanner.empty() && m_scanner.peek().type == Token::DOC_END)
m_scanner.pop();
}
void SingleDocParser::HandleNode(EventHandler& eventHandler) {
DepthGuard<500> depthguard(depth, m_scanner.mark(), ErrorMsg::BAD_FILE);
// an empty node *is* a possibility
if (m_scanner.empty()) {
eventHandler.OnNull(m_scanner.mark(), NullAnchor);
@@ -86,25 +79,18 @@ void SingleDocParser::HandleNode(EventHandler& eventHandler) {
if (!anchor_name.empty())
eventHandler.OnAnchor(mark, anchor_name);
// after parsing properties, an empty node is again a possibility
if (m_scanner.empty()) {
eventHandler.OnNull(mark, anchor);
return;
}
const Token& token = m_scanner.peek();
// add non-specific tags
if (tag.empty())
tag = (token.type == Token::NON_PLAIN_SCALAR ? "!" : "?");
if (token.type == Token::PLAIN_SCALAR
&& tag.compare("?") == 0 && IsNullString(token.value.data(), token.value.size())) {
if (token.type == Token::PLAIN_SCALAR && IsNullString(token.value)) {
eventHandler.OnNull(mark, anchor);
m_scanner.pop();
return;
}
// add non-specific tags
if (tag.empty())
tag = (token.type == Token::NON_PLAIN_SCALAR ? "!" : "?");
// now split based on what kind of node we should be
switch (token.type) {
case Token::PLAIN_SCALAR:
@@ -171,7 +157,7 @@ void SingleDocParser::HandleBlockSequence(EventHandler& eventHandler) {
m_scanner.pop();
m_pCollectionStack->PushCollectionType(CollectionType::BlockSeq);
while (true) {
while (1) {
if (m_scanner.empty())
throw ParserException(m_scanner.mark(), ErrorMsg::END_OF_SEQ);
@@ -204,7 +190,7 @@ void SingleDocParser::HandleFlowSequence(EventHandler& eventHandler) {
m_scanner.pop();
m_pCollectionStack->PushCollectionType(CollectionType::FlowSeq);
while (true) {
while (1) {
if (m_scanner.empty())
throw ParserException(m_scanner.mark(), ErrorMsg::END_OF_SEQ_FLOW);
@@ -257,7 +243,7 @@ void SingleDocParser::HandleBlockMap(EventHandler& eventHandler) {
m_scanner.pop();
m_pCollectionStack->PushCollectionType(CollectionType::BlockMap);
while (true) {
while (1) {
if (m_scanner.empty())
throw ParserException(m_scanner.mark(), ErrorMsg::END_OF_MAP);
@@ -296,7 +282,7 @@ void SingleDocParser::HandleFlowMap(EventHandler& eventHandler) {
m_scanner.pop();
m_pCollectionStack->PushCollectionType(CollectionType::FlowMap);
while (true) {
while (1) {
if (m_scanner.empty())
throw ParserException(m_scanner.mark(), ErrorMsg::END_OF_MAP_FLOW);
@@ -381,7 +367,7 @@ void SingleDocParser::ParseProperties(std::string& tag, anchor_t& anchor,
anchor_name.clear();
anchor = NullAnchor;
while (true) {
while (1) {
if (m_scanner.empty())
return;
@@ -427,12 +413,9 @@ anchor_t SingleDocParser::RegisterAnchor(const std::string& name) {
anchor_t SingleDocParser::LookupAnchor(const Mark& mark,
const std::string& name) const {
auto it = m_anchors.find(name);
if (it == m_anchors.end()) {
std::stringstream ss;
ss << ErrorMsg::UNKNOWN_ANCHOR << name;
throw ParserException(mark, ss.str());
}
Anchors::const_iterator it = m_anchors.find(name);
if (it == m_anchors.end())
throw ParserException(mark, ErrorMsg::UNKNOWN_ANCHOR);
return it->second;
}

Some files were not shown because too many files have changed in this diff Show More