mirror of
https://github.com/jbeder/yaml-cpp.git
synced 2025-09-09 20:51:16 +00:00
Compare commits
91 Commits
yaml-cpp-0
...
yaml-cpp-0
Author | SHA1 | Date | |
---|---|---|---|
![]() |
0579ae3d97 | ||
![]() |
9ee3928754 | ||
![]() |
a6bbe0e50a | ||
![]() |
98acc5a887 | ||
![]() |
1c9abc8fa4 | ||
![]() |
11917babc7 | ||
![]() |
c2793a36d5 | ||
![]() |
bc9874c9ff | ||
![]() |
06b99f53db | ||
![]() |
c3df6d87d4 | ||
![]() |
51ce663085 | ||
![]() |
33315286ab | ||
![]() |
4571e8177a | ||
![]() |
c82d3129dd | ||
![]() |
370aceeaf8 | ||
![]() |
6d5cfab5fd | ||
![]() |
026a53fbe1 | ||
![]() |
1c2e767347 | ||
![]() |
3f381f13a0 | ||
![]() |
08aa252611 | ||
![]() |
27d8a0e302 | ||
![]() |
97d1ae547c | ||
![]() |
5a9ab177ba | ||
![]() |
72fe73a104 | ||
![]() |
a7a7908dc5 | ||
![]() |
0b0bf35c48 | ||
![]() |
dbb385bdf5 | ||
![]() |
b2cd008717 | ||
![]() |
6387cbc0ca | ||
![]() |
1bf9540a7d | ||
![]() |
4c90f2962e | ||
![]() |
4f6d0733c9 | ||
![]() |
f05947ae59 | ||
![]() |
66171449d4 | ||
![]() |
33c9f6e062 | ||
![]() |
7e4f290ef9 | ||
![]() |
ae811c3d86 | ||
![]() |
41001d1bf9 | ||
![]() |
a808c1f44a | ||
![]() |
4dbfeb0bbc | ||
![]() |
33316d531b | ||
![]() |
6701275f19 | ||
![]() |
cb7bb9821d | ||
![]() |
f05b2577ad | ||
![]() |
d9c35b6079 | ||
![]() |
4b98aedc16 | ||
![]() |
a98b8af448 | ||
![]() |
9fb5153487 | ||
![]() |
513ee81fbf | ||
![]() |
9f2781b527 | ||
![]() |
7083db28b3 | ||
![]() |
2f00649291 | ||
![]() |
b35f2a86a6 | ||
![]() |
99222fc938 | ||
![]() |
4edff1fa5d | ||
![]() |
70205f5d88 | ||
![]() |
9b8f35093e | ||
![]() |
1d8542ad32 | ||
![]() |
6f7ead5171 | ||
![]() |
cf93f4c57b | ||
![]() |
26faac387c | ||
![]() |
120863ba5a | ||
![]() |
b2f89386d8 | ||
![]() |
1bfbd2be4c | ||
![]() |
de8253fcb0 | ||
![]() |
29dcf92f87 | ||
![]() |
ce056acab7 | ||
![]() |
9ab22ef493 | ||
![]() |
1928bca4a4 | ||
![]() |
c9460110e0 | ||
![]() |
3dca8668b1 | ||
![]() |
587b24e2ee | ||
![]() |
5b3e30bfe9 | ||
![]() |
72f699f5ce | ||
![]() |
a8ba6a8dca | ||
![]() |
14c87258cd | ||
![]() |
f531f8a8c3 | ||
![]() |
52a1378e48 | ||
![]() |
c9a0077024 | ||
![]() |
b650bc8287 | ||
![]() |
21d75fa4cd | ||
![]() |
848091124d | ||
![]() |
6e87b37034 | ||
![]() |
0fddd1e5bd | ||
![]() |
99d95d8edc | ||
![]() |
a6ed66abca | ||
![]() |
e6b3a92e67 | ||
![]() |
47d32aadf0 | ||
![]() |
9d7e556ed5 | ||
![]() |
62ff351432 | ||
![]() |
5e9cb0128d |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,2 +1,3 @@
|
||||
build/
|
||||
/tags
|
||||
/bazel-*
|
||||
|
51
.travis.yml
51
.travis.yml
@@ -1,28 +1,37 @@
|
||||
language: c++
|
||||
os:
|
||||
- linux
|
||||
- osx
|
||||
compiler:
|
||||
- clang
|
||||
- gcc
|
||||
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
|
||||
|
||||
matrix:
|
||||
include:
|
||||
- os: linux
|
||||
compiler: gcc
|
||||
- os: osx
|
||||
compiler: clang
|
||||
- os: osx
|
||||
compiler: gcc
|
||||
env:
|
||||
- CTEST_OUTPUT_ON_FAILURE=1
|
||||
|
||||
before_script:
|
||||
- mkdir build
|
||||
- cd build
|
||||
- cmake ..
|
||||
- cd ..
|
||||
script:
|
||||
- make
|
||||
- test/run-tests
|
||||
- cmake --build build
|
||||
- cmake --build build --target test
|
||||
|
||||
matrix:
|
||||
exclude:
|
||||
- os: linux
|
||||
compiler: clang
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- llvm-toolchain-precise-3.9
|
||||
packages:
|
||||
- g++-4.9
|
||||
- clang-3.9
|
||||
update: true
|
||||
homebrew:
|
||||
packages:
|
||||
- ccache
|
||||
- gcc@4.9
|
||||
- llvm@4
|
||||
update: true
|
||||
|
14
BUILD.bazel
Normal file
14
BUILD.bazel
Normal file
@@ -0,0 +1,14 @@
|
||||
cc_library(
|
||||
name = "yaml-cpp_internal",
|
||||
visibility = ["//:__subpackages__"],
|
||||
strip_include_prefix = "src",
|
||||
hdrs = glob(["src/**/*.h"]),
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "yaml-cpp",
|
||||
visibility = ["//visibility:public"],
|
||||
includes = ["include"],
|
||||
hdrs = glob(["include/**/*.h"]),
|
||||
srcs = glob(["src/**/*.cpp", "src/**/*.h"]),
|
||||
)
|
461
CMakeLists.txt
461
CMakeLists.txt
@@ -1,367 +1,174 @@
|
||||
###
|
||||
### CMake settings
|
||||
###
|
||||
# see http://www.cmake.org/Wiki/CMake_Policies
|
||||
cmake_minimum_required(VERSION 3.1)
|
||||
# 3.5 is actually available almost everywhere, but this a good minimum
|
||||
cmake_minimum_required(VERSION 3.4)
|
||||
|
||||
# enable MSVC_RUNTIME_LIBRARY target property
|
||||
# see https://cmake.org/cmake/help/latest/policy/CMP0091.html
|
||||
if(POLICY CMP0091)
|
||||
cmake_policy(SET CMP0091 NEW)
|
||||
endif()
|
||||
|
||||
project(YAML_CPP VERSION 0.7.0 LANGUAGES CXX)
|
||||
|
||||
include(CMakePackageConfigHelpers)
|
||||
include(CMakeDependentOption)
|
||||
include(CheckCXXCompilerFlag)
|
||||
include(GNUInstallDirs)
|
||||
include(CTest)
|
||||
|
||||
###
|
||||
### Project settings
|
||||
###
|
||||
project(YAML_CPP VERSION 0.6.3)
|
||||
find_program(YAML_CPP_CLANG_FORMAT_EXE NAMES clang-format)
|
||||
|
||||
###
|
||||
### Project options
|
||||
###
|
||||
## Project stuff
|
||||
option(YAML_CPP_BUILD_TESTS "Enable testing" ON)
|
||||
option(YAML_CPP_BUILD_CONTRIB "Enable yaml-cpp contrib in library" ON)
|
||||
option(YAML_CPP_BUILD_TOOLS "Enable parse tools" ON)
|
||||
option(YAML_CPP_BUILD_CONTRIB "Enable contrib stuff in library" ON)
|
||||
option(YAML_CPP_INSTALL "Enable generation of install target" ON)
|
||||
option(YAML_BUILD_SHARED_LIBS "Build yaml-cpp shared library" ${BUILD_SHARED_LIBS})
|
||||
|
||||
## 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(YAML_BUILD_SHARED_LIBS "Build Shared Libraries" OFF)
|
||||
cmake_dependent_option(YAML_CPP_BUILD_TESTS
|
||||
"Enable yaml-cpp tests" ON
|
||||
"BUILD_TESTING;CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR" OFF)
|
||||
cmake_dependent_option(YAML_CPP_INSTALL
|
||||
"Enable generation of yaml-cpp install targets" ON
|
||||
"CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR" OFF)
|
||||
cmake_dependent_option(YAML_MSVC_SHARED_RT
|
||||
"MSVC: Build yaml-cpp with shared runtime libs (/MD)" ON
|
||||
"MSVC" OFF)
|
||||
|
||||
# --> Apple
|
||||
if(APPLE)
|
||||
option(YAML_APPLE_UNIVERSAL_BIN "Apple: Build universal binary" OFF)
|
||||
set(yaml-cpp-type STATIC)
|
||||
set(yaml-cpp-label-postfix "static")
|
||||
if (YAML_BUILD_SHARED_LIBS)
|
||||
set(yaml-cpp-type SHARED)
|
||||
set(yaml-cpp-label-postfix "shared")
|
||||
endif()
|
||||
|
||||
# --> 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
|
||||
if(MSVC)
|
||||
option(YAML_MSVC_SHARED_RT "MSVC: Build with shared runtime libs (/MD)" ON)
|
||||
option(YAML_MSVC_STHREADED_RT "MSVC: Build with single-threaded static runtime libs (/ML until VS .NET 2003)" OFF)
|
||||
set(build-shared $<BOOL:${YAML_BUILD_SHARED_LIBS}>)
|
||||
set(build-windows-dll $<AND:$<BOOL:${CMAKE_HOST_WIN32}>,${build-shared}>)
|
||||
set(not-msvc $<NOT:$<CXX_COMPILER_ID:MSVC>>)
|
||||
set(msvc-shared_rt $<BOOL:${YAML_MSVC_SHARED_RT}>)
|
||||
|
||||
if (NOT DEFINED CMAKE_MSVC_RUNTIME_LIBRARY)
|
||||
set(CMAKE_MSVC_RUNTIME_LIBRARY
|
||||
MultiThreaded$<$<CONFIG:Debug>:Debug>$<${msvc-shared_rt}:DLL>)
|
||||
endif()
|
||||
|
||||
###
|
||||
### 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()
|
||||
add_definitions(-DYAML_CPP_NO_CONTRIB)
|
||||
set(contrib-pattern "src/contrib/*.cpp")
|
||||
set(src-pattern "src/*.cpp")
|
||||
if (CMAKE_VERSION VERSION_GREATER 3.12)
|
||||
list(INSERT contrib-pattern 0 CONFIGURE_DEPENDS)
|
||||
list(INSERT src-pattern 0 CONFIGURE_DEPENDS)
|
||||
endif()
|
||||
|
||||
set(library_sources
|
||||
${sources}
|
||||
${public_headers}
|
||||
${private_headers}
|
||||
${contrib_sources}
|
||||
${contrib_public_headers}
|
||||
${contrib_private_headers}
|
||||
)
|
||||
add_sources(${library_sources})
|
||||
file(GLOB yaml-cpp-contrib-sources ${contrib-pattern})
|
||||
file(GLOB yaml-cpp-sources ${src-pattern})
|
||||
|
||||
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}")
|
||||
set(msvc-rt $<TARGET_PROPERTY:MSVC_RUNTIME_LIBRARY>)
|
||||
|
||||
set(msvc-rt-mtd-static $<STREQUAL:${msvc-rt},MultiThreadedDebug>)
|
||||
set(msvc-rt-mt-static $<STREQUAL:${msvc-rt},MultiThreaded>)
|
||||
|
||||
set(msvc-rt-mtd-dll $<STREQUAL:${msvc-rt},MultiThreadedDebugDLL>)
|
||||
set(msvc-rt-mt-dll $<STREQUAL:${msvc-rt},MultiThreadedDLL>)
|
||||
|
||||
set(backport-msvc-runtime $<VERSION_LESS:${CMAKE_VERSION},3.15>)
|
||||
|
||||
add_library(yaml-cpp ${yaml-cpp-type} "")
|
||||
add_library(yaml-cpp::yaml-cpp ALIAS yaml-cpp)
|
||||
|
||||
set_property(TARGET yaml-cpp
|
||||
PROPERTY
|
||||
MSVC_RUNTIME_LIBRARY ${CMAKE_MSVC_RUNTIME_LIBRARY})
|
||||
set_property(TARGET yaml-cpp
|
||||
PROPERTY
|
||||
CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
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)
|
||||
endif()
|
||||
|
||||
if (CMAKE_VERSION VERSION_LESS 2.8.12)
|
||||
include_directories(${YAML_CPP_SOURCE_DIR}/src)
|
||||
include_directories(${YAML_CPP_SOURCE_DIR}/include)
|
||||
endif()
|
||||
target_compile_options(yaml-cpp
|
||||
PRIVATE
|
||||
$<${not-msvc}:-Wall -Wextra -Wshadow -Weffc++ -Wno-long-long>
|
||||
$<${not-msvc}:-pedantic -pedantic-errors>
|
||||
|
||||
$<$<AND:${backport-msvc-runtime},${msvc-rt-mtd-static}>:-MTd>
|
||||
$<$<AND:${backport-msvc-runtime},${msvc-rt-mt-static}>:-MT>
|
||||
$<$<AND:${backport-msvc-runtime},${msvc-rt-mtd-dll}>:-MDd>
|
||||
$<$<AND:${backport-msvc-runtime},${msvc-rt-mt-dll}>:-MD>
|
||||
|
||||
###
|
||||
### General compilation settings
|
||||
###
|
||||
set(yaml_c_flags ${CMAKE_C_FLAGS})
|
||||
set(yaml_cxx_flags ${CMAKE_CXX_FLAGS})
|
||||
# /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(YAML_BUILD_SHARED_LIBS)
|
||||
set(LABEL_SUFFIX "shared")
|
||||
else()
|
||||
set(LABEL_SUFFIX "static")
|
||||
endif()
|
||||
target_compile_definitions(yaml-cpp
|
||||
PRIVATE
|
||||
$<${build-windows-dll}:${PROJECT_NAME}_DLL>
|
||||
$<$<NOT:$<BOOL:${YAML_CPP_BUILD_CONTRIB}>>:YAML_CPP_NO_CONTRIB>)
|
||||
|
||||
if(APPLE)
|
||||
if(YAML_APPLE_UNIVERSAL_BIN)
|
||||
set(CMAKE_OSX_ARCHITECTURES ppc;i386)
|
||||
endif()
|
||||
endif()
|
||||
target_sources(yaml-cpp
|
||||
PRIVATE
|
||||
$<$<BOOL:${YAML_CPP_BUILD_CONTRIB}>:${yaml-cpp-contrib-sources}>
|
||||
${yaml-cpp-sources})
|
||||
|
||||
if(IPHONE)
|
||||
set(CMAKE_OSX_SYSROOT "iphoneos4.2")
|
||||
set(CMAKE_OSX_ARCHITECTURES "armv6;armv7")
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
if(YAML_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()
|
||||
|
||||
# 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")
|
||||
|
||||
### 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(YAML_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 YAML_MSVC_SHARED_RT) # User wants to have static runtime libraries (/MT, /ML)
|
||||
if(YAML_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 YAML_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
|
||||
###
|
||||
if(YAML_BUILD_SHARED_LIBS)
|
||||
add_library(yaml-cpp SHARED ${library_sources})
|
||||
else()
|
||||
add_library(yaml-cpp STATIC ${library_sources})
|
||||
endif()
|
||||
|
||||
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>)
|
||||
if (NOT DEFINED CMAKE_DEBUG_POSTFIX)
|
||||
set(CMAKE_DEBUG_POSTFIX "d")
|
||||
endif()
|
||||
|
||||
set_target_properties(yaml-cpp PROPERTIES
|
||||
CXX_STANDARD 11
|
||||
CXX_STANDARD_REQUIRED ON
|
||||
)
|
||||
VERSION "${PROJECT_VERSION}"
|
||||
SOVERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}"
|
||||
PROJECT_LABEL "yaml-cpp ${yaml-cpp-label-postfix}"
|
||||
DEBUG_POSTFIX "${CMAKE_DEBUG_POSTFIX}")
|
||||
|
||||
set_target_properties(yaml-cpp PROPERTIES
|
||||
COMPILE_FLAGS "${yaml_c_flags} ${yaml_cxx_flags}"
|
||||
)
|
||||
configure_package_config_file(
|
||||
"${PROJECT_SOURCE_DIR}/yaml-cpp-config.cmake.in"
|
||||
"${PROJECT_BINARY_DIR}/yaml-cpp-config.cmake"
|
||||
INSTALL_DESTINATION "${CMAKE_INSTALL_DATADIR}/cmake/yaml-cpp")
|
||||
|
||||
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()
|
||||
|
||||
if(MSVC)
|
||||
if(NOT YAML_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 ${_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)
|
||||
configure_file(yaml-cpp.pc.in yaml-cpp.pc @ONLY)
|
||||
|
||||
if (YAML_CPP_INSTALL)
|
||||
install(TARGETS yaml-cpp
|
||||
EXPORT yaml-cpp-targets
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||
install(DIRECTORY ${PROJECT_SOURCE_DIR}/include/
|
||||
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
|
||||
FILES_MATCHING PATTERN "*.h")
|
||||
install(EXPORT yaml-cpp-targets
|
||||
DESTINATION "${CMAKE_INSTALL_DATADIR}/cmake/yaml-cpp")
|
||||
install(FILES
|
||||
"${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/yaml-cpp-config.cmake"
|
||||
"${PROJECT_BINARY_DIR}/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()
|
||||
|
||||
DESTINATION "${CMAKE_INSTALL_DATADIR}/cmake/yaml-cpp")
|
||||
install(FILES "${PROJECT_BINARY_DIR}/yaml-cpp.pc"
|
||||
DESTINATION ${CMAKE_INSTALL_DATADIR}/pkgconfig)
|
||||
endif()
|
||||
|
||||
|
||||
###
|
||||
### Extras
|
||||
###
|
||||
if(YAML_CPP_BUILD_TESTS)
|
||||
enable_testing()
|
||||
add_subdirectory(test)
|
||||
endif()
|
||||
|
||||
if(YAML_CPP_BUILD_TOOLS)
|
||||
add_subdirectory(util)
|
||||
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)
|
||||
if (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"
|
||||
VERBATIM)
|
||||
endif()
|
||||
|
10
README.md
10
README.md
@@ -49,3 +49,13 @@ cmake [-G generator] [-DYAML_BUILD_SHARED_LIBS=ON|OFF] ..
|
||||
[yaml-cpp 0.3.0](https://github.com/jbeder/yaml-cpp/releases/tag/release-0.3.0) is still available if you want the old API.
|
||||
|
||||
**The old API will continue to be supported, and will still receive bugfixes!** The 0.3.x and 0.4.x versions will be old API releases, and 0.5.x and above will all be new API releases.
|
||||
|
||||
# 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)
|
||||
|
10
WORKSPACE
Normal file
10
WORKSPACE
Normal file
@@ -0,0 +1,10 @@
|
||||
workspace(name = "com_github_jbeder_yaml_cpp")
|
||||
|
||||
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
|
||||
|
||||
http_archive(
|
||||
name = "com_google_googletest",
|
||||
strip_prefix = "googletest-release-1.8.1",
|
||||
url = "https://github.com/google/googletest/archive/release-1.8.1.tar.gz",
|
||||
sha256 = "9bf1fe5182a604b4135edc1a425ae356c9ad15e9b23f9f12a02e80184c3a249c",
|
||||
)
|
28
appveyor.yml
Normal file
28
appveyor.yml
Normal file
@@ -0,0 +1,28 @@
|
||||
version: 1.0.{build}
|
||||
|
||||
environment:
|
||||
matrix:
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||
CMAKE_GENERATOR: Visual Studio 14 2015
|
||||
CMAKE_PLATFORM: win32
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||
CMAKE_GENERATOR: Visual Studio 14 2015
|
||||
CMAKE_PLATFORM: x64
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
CMAKE_GENERATOR: Visual Studio 15 2017
|
||||
CMAKE_PLATFORM: win32
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
CMAKE_GENERATOR: Visual Studio 15 2017
|
||||
CMAKE_PLATFORM: x64
|
||||
|
||||
before_build:
|
||||
- cmd: mkdir build
|
||||
- cmd: cd build
|
||||
- cmd: cmake .. -G "%CMAKE_GENERATOR%" -DCMAKE_GENERATOR_PLATFORM=%CMAKE_PLATFORM%
|
||||
- cmd: cd ..
|
||||
|
||||
build_script:
|
||||
- cmake --build build
|
||||
test_script:
|
||||
- cmd: cd build
|
||||
- ctest
|
52
docs/Breaking-Changes.md
Normal file
52
docs/Breaking-Changes.md
Normal file
@@ -0,0 +1,52 @@
|
||||
# The following is a list of breaking changes to yaml-cpp, by version #
|
||||
|
||||
# New API #
|
||||
|
||||
## HEAD ##
|
||||
|
||||
* Throws an exception when trying to parse a negative number as an unsigned integer.
|
||||
* Supports the `as<int8_t>`/`as<uint8_t>`, which throws an exception when the value exceeds the range of `int8_t`/`uint8_t`.
|
||||
|
||||
## 0.6.0 ##
|
||||
|
||||
* Requires C++11.
|
||||
|
||||
## 0.5.3 ##
|
||||
|
||||
_none_
|
||||
|
||||
## 0.5.2 ##
|
||||
|
||||
_none_
|
||||
|
||||
## 0.5.1 ##
|
||||
|
||||
* `Node::clear` was replaced by `Node::reset`, which takes an optional node, similar to smart pointers.
|
||||
|
||||
## 0.5.0 ##
|
||||
|
||||
Initial version of the new API.
|
||||
|
||||
# Old API #
|
||||
|
||||
## 0.3.0 ##
|
||||
|
||||
_none_
|
||||
|
||||
## 0.2.7 ##
|
||||
|
||||
* `YAML::Binary` now takes `const unsigned char *` for the binary data (instead of `const char *`).
|
||||
|
||||
## 0.2.6 ##
|
||||
|
||||
* `Node::GetType()` is now `Node::Type()`, and returns an enum `NodeType::value`, where:
|
||||
> > ` struct NodeType { enum value { Null, Scalar, Sequence, Map }; }; `
|
||||
* `Node::GetTag()` is now `Node::Tag()`
|
||||
* `Node::Identity()` is removed, and `Node::IsAlias()` and `Node::IsReferenced()` have been merged into `Node::IsAliased()`. The reason: there's no reason to distinguish an alias node from its anchor - whichever happens to be emitted first will be the anchor, and the rest will be aliases.
|
||||
* `Node::Read<T>` is now `Node::to<T>`. This wasn't a documented function, so it shouldn't break anything.
|
||||
* `Node`'s comparison operators (for example, `operator == (const Node&, const T&)`) have all been removed. These weren't documented either (they were just used for the tests), so this shouldn't break anything either.
|
||||
* The emitter no longer produces the document start by default - if you want it, you can supply it with the manipulator `YAML::BeginDoc`.
|
||||
|
||||
## 0.2.5 ##
|
||||
|
||||
This wiki was started with v0.2.5.
|
230
docs/How-To-Emit-YAML.md
Normal file
230
docs/How-To-Emit-YAML.md
Normal file
@@ -0,0 +1,230 @@
|
||||
## 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:
|
||||
|
||||
```cpp
|
||||
std::vector <int> squares;
|
||||
squares.push_back(1);
|
||||
squares.push_back(4);
|
||||
squares.push_back(9);
|
||||
squares.push_back(16);
|
||||
|
||||
std::map <std::string, int> ages;
|
||||
ages["Daniel"] = 26;
|
||||
ages["Jesse"] = 24;
|
||||
|
||||
YAML::Emitter out;
|
||||
out << YAML::BeginSeq;
|
||||
out << YAML::Flow << squares;
|
||||
out << ages;
|
||||
out << YAML::EndSeq;
|
||||
```
|
||||
|
||||
produces
|
||||
|
||||
```yaml
|
||||
- [1, 4, 9, 16]
|
||||
-
|
||||
Daniel: 26
|
||||
Jesse: 24
|
||||
```
|
||||
|
||||
Of course, you can overload `operator <<` for your own types:
|
||||
|
||||
```cpp
|
||||
struct Vec3 { int x; int y; int z; };
|
||||
YAML::Emitter& operator << (YAML::Emitter& out, const Vec3& v) {
|
||||
out << YAML::Flow;
|
||||
out << YAML::BeginSeq << v.x << v.y << v.z << YAML::EndSeq;
|
||||
return out;
|
||||
}
|
||||
```
|
||||
and it'll play nicely with everything else.
|
||||
|
||||
# Using Existing Nodes #
|
||||
|
||||
We also overload `operator << ` for `YAML::Node`s in both APIs, so you can output existing Nodes. Of course, Nodes in the old API are read-only, so it's tricky to emit them if you want to modify them. So use the new API!
|
||||
|
||||
# Output Encoding #
|
||||
|
||||
The output is always UTF-8. By default, yaml-cpp will output as much as it can without escaping any characters. If you want to restrict the output to ASCII, use the manipulator `YAML::EscapeNonAscii`:
|
||||
|
||||
```cpp
|
||||
emitter.SetOutputCharset(YAML::EscapeNonAscii);
|
||||
```
|
||||
|
||||
# Lifetime of Manipulators #
|
||||
|
||||
Manipulators affect the **next** output item in the stream. If that item is a `BeginSeq` or `BeginMap`, the manipulator lasts until the corresponding `EndSeq` or `EndMap`. (However, within that sequence or map, you can override the manipulator locally, etc.; in effect, there's a "manipulator stack" behind the scenes.)
|
||||
|
||||
If you want to permanently change a setting, there are global setters corresponding to each manipulator, e.g.:
|
||||
|
||||
```cpp
|
||||
YAML::Emitter out;
|
||||
out.SetIndent(4);
|
||||
out.SetMapStyle(YAML::Flow);
|
||||
```
|
||||
|
||||
# When Something Goes Wrong #
|
||||
|
||||
If something goes wrong when you're emitting a document, it must be something like forgetting a `YAML::EndSeq`, or a misplaced `YAML::Key`. In this case, emitting silently fails (no more output is emitted) and an error flag is set. For example:
|
||||
|
||||
```cpp
|
||||
YAML::Emitter out;
|
||||
assert(out.good());
|
||||
out << YAML::Key;
|
||||
assert(!out.good());
|
||||
std::cout << "Emitter error: " << out.GetLastError() << "\n";
|
||||
```
|
265
docs/How-To-Parse-A-Document-(Old-API).md
Normal file
265
docs/How-To-Parse-A-Document-(Old-API).md
Normal file
@@ -0,0 +1,265 @@
|
||||
_The following describes the old API. For the new API, see the [Tutorial](https://github.com/jbeder/yaml-cpp/wiki/Tutorial)._
|
||||
|
||||
## Contents ##
|
||||
|
||||
|
||||
# Basic Parsing #
|
||||
|
||||
The parser accepts streams, not file names, so you need to first load the file. Since a YAML file can contain many documents, you can grab them one-by-one. A simple way to parse a YAML file might be:
|
||||
|
||||
```
|
||||
#include <fstream>
|
||||
#include "yaml-cpp/yaml.h"
|
||||
|
||||
int main()
|
||||
{
|
||||
std::ifstream fin("test.yaml");
|
||||
YAML::Parser parser(fin);
|
||||
|
||||
YAML::Node doc;
|
||||
while(parser.GetNextDocument(doc)) {
|
||||
// ...
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
# Reading From the Document #
|
||||
|
||||
Suppose we have a document consisting only of a scalar. We can read that scalar like this:
|
||||
|
||||
```
|
||||
YAML::Node doc; // let's say we've already parsed this document
|
||||
std::string scalar;
|
||||
doc >> scalar;
|
||||
std::cout << "That scalar was: " << scalar << std::endl;
|
||||
```
|
||||
|
||||
How about sequences? Let's say our document now consists only of a sequences of scalars. We can use an iterator:
|
||||
|
||||
```
|
||||
YAML::Node doc; // already parsed
|
||||
for(YAML::Iterator it=doc.begin();it!=doc.end();++it) {
|
||||
std::string scalar;
|
||||
*it >> scalar;
|
||||
std::cout << "Found scalar: " << scalar << std::endl;
|
||||
}
|
||||
```
|
||||
|
||||
... or we can just loop through:
|
||||
|
||||
```
|
||||
YAML::Node doc; // already parsed
|
||||
for(unsigned i=0;i<doc.size();i++) {
|
||||
std::string scalar;
|
||||
doc[i] >> scalar;
|
||||
std::cout << "Found scalar: " << scalar << std::endl;
|
||||
}
|
||||
```
|
||||
|
||||
And finally maps. For now, let's say our document is a map with all keys/values being scalars. Again, we can iterate:
|
||||
|
||||
```
|
||||
YAML::Node doc; // already parsed
|
||||
for(YAML::Iterator it=doc.begin();it!=doc.end();++it) {
|
||||
std::string key, value;
|
||||
it.first() >> key;
|
||||
it.second() >> value;
|
||||
std::cout << "Key: " << key << ", value: " << value << std::endl;
|
||||
}
|
||||
```
|
||||
|
||||
Note that dereferencing a map iterator is undefined; instead, use the `first` and `second` methods to get the key and value nodes, respectively.
|
||||
|
||||
Alternatively, we can pick off the values one-by-one, if we know the keys:
|
||||
|
||||
```
|
||||
YAML::Node doc; // already parsed
|
||||
std::string name;
|
||||
doc["name"] >> name;
|
||||
int age;
|
||||
doc["age"] >> age;
|
||||
std::cout << "Found entry with name '" << name << "' and age '" << age << "'\n";
|
||||
```
|
||||
|
||||
One thing to be keep in mind: reading a map by key (as immediately above) requires looping through all entries until we find the right key, which is an O(n) operation. So if you're reading the entire map this way, it'll be O(n^2). For small n, this isn't a big deal, but I wouldn't recommend reading maps with a very large number of entries (>100, say) this way.
|
||||
|
||||
## Optional Keys ##
|
||||
|
||||
If you try to access a key that doesn't exist, `yaml-cpp` throws an exception (see [When Something Goes Wrong](https://github.com/jbeder/yaml-cpp/wiki/How-To-Parse-A-Document-(Old-API)#When_Something_Goes_Wrong). If you have optional keys, it's often easier to use `FindValue` instead of `operator[]`:
|
||||
|
||||
```
|
||||
YAML::Node doc; // already parsed
|
||||
if(const YAML::Node *pName = doc.FindValue("name")) {
|
||||
std::string name;
|
||||
*pName >> name;
|
||||
std::cout << "Key 'name' exists, with value '" << name << "'\n";
|
||||
} else {
|
||||
std::cout << "Key 'name' doesn't exist\n";
|
||||
}
|
||||
```
|
||||
|
||||
# Getting More Complicated #
|
||||
|
||||
The above three methods can be combined to read from an arbitrary document. But we can make life a lot easier. Suppose we're reading 3-vectors (i.e., vectors with three components), so we've got a structure looking like this:
|
||||
|
||||
```
|
||||
struct Vec3 {
|
||||
float x, y, z;
|
||||
};
|
||||
```
|
||||
|
||||
We can read this in one operation by overloading the extraction (>>) operator:
|
||||
|
||||
```
|
||||
void operator >> (const YAML::Node& node, Vec3& v)
|
||||
{
|
||||
node[0] >> v.x;
|
||||
node[1] >> v.y;
|
||||
node[2] >> v.z;
|
||||
}
|
||||
|
||||
// now it's a piece of cake to read it
|
||||
YAML::Node doc; // already parsed
|
||||
Vec3 v;
|
||||
doc >> v;
|
||||
std::cout << "Here's the vector: (" << v.x << ", " << v.y << ", " << v.z << ")\n";
|
||||
```
|
||||
|
||||
# A Complete Example #
|
||||
|
||||
Here's a complete example of how to parse a complex YAML file:
|
||||
|
||||
`monsters.yaml`
|
||||
|
||||
```
|
||||
- name: Ogre
|
||||
position: [0, 5, 0]
|
||||
powers:
|
||||
- name: Club
|
||||
damage: 10
|
||||
- name: Fist
|
||||
damage: 8
|
||||
- name: Dragon
|
||||
position: [1, 0, 10]
|
||||
powers:
|
||||
- name: Fire Breath
|
||||
damage: 25
|
||||
- name: Claws
|
||||
damage: 15
|
||||
- name: Wizard
|
||||
position: [5, -3, 0]
|
||||
powers:
|
||||
- name: Acid Rain
|
||||
damage: 50
|
||||
- name: Staff
|
||||
damage: 3
|
||||
```
|
||||
|
||||
`main.cpp`
|
||||
|
||||
```
|
||||
#include "yaml-cpp/yaml.h"
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
// our data types
|
||||
struct Vec3 {
|
||||
float x, y, z;
|
||||
};
|
||||
|
||||
struct Power {
|
||||
std::string name;
|
||||
int damage;
|
||||
};
|
||||
|
||||
struct Monster {
|
||||
std::string name;
|
||||
Vec3 position;
|
||||
std::vector <Power> powers;
|
||||
};
|
||||
|
||||
// now the extraction operators for these types
|
||||
void operator >> (const YAML::Node& node, Vec3& v) {
|
||||
node[0] >> v.x;
|
||||
node[1] >> v.y;
|
||||
node[2] >> v.z;
|
||||
}
|
||||
|
||||
void operator >> (const YAML::Node& node, Power& power) {
|
||||
node["name"] >> power.name;
|
||||
node["damage"] >> power.damage;
|
||||
}
|
||||
|
||||
void operator >> (const YAML::Node& node, Monster& monster) {
|
||||
node["name"] >> monster.name;
|
||||
node["position"] >> monster.position;
|
||||
const YAML::Node& powers = node["powers"];
|
||||
for(unsigned i=0;i<powers.size();i++) {
|
||||
Power power;
|
||||
powers[i] >> power;
|
||||
monster.powers.push_back(power);
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
std::ifstream fin("monsters.yaml");
|
||||
YAML::Parser parser(fin);
|
||||
YAML::Node doc;
|
||||
parser.GetNextDocument(doc);
|
||||
for(unsigned i=0;i<doc.size();i++) {
|
||||
Monster monster;
|
||||
doc[i] >> monster;
|
||||
std::cout << monster.name << "\n";
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
# When Something Goes Wrong #
|
||||
|
||||
... we throw an exception (all exceptions are derived from `YAML::Exception`). If there's a parsing exception (i.e., a malformed YAML document), we throw a `YAML::ParserException`:
|
||||
|
||||
```
|
||||
try {
|
||||
std::ifstream fin("test.yaml");
|
||||
YAML::Parser parser(fin);
|
||||
YAML::Node doc;
|
||||
parser.GetNextDocument(doc);
|
||||
// do stuff
|
||||
} catch(YAML::ParserException& e) {
|
||||
std::cout << e.what() << "\n";
|
||||
}
|
||||
```
|
||||
|
||||
If you make a programming error (say, trying to read a scalar from a sequence node, or grabbing a key that doesn't exist), we throw some kind of `YAML::RepresentationException`. To prevent this, you can check what kind of node something is:
|
||||
|
||||
```
|
||||
YAML::Node node;
|
||||
YAML::NodeType::value type = node.Type(); // should be:
|
||||
// YAML::NodeType::Null
|
||||
// YAML::NodeType::Scalar
|
||||
// YAML::NodeType::Sequence
|
||||
// YAML::NodeType::Map
|
||||
```
|
||||
|
||||
# Note about copying `YAML::Node` #
|
||||
|
||||
Currently `YAML::Node` is non-copyable, so you need to do something like
|
||||
|
||||
```
|
||||
const YAML::Node& node = doc["whatever"];
|
||||
```
|
||||
|
||||
This is intended behavior. If you want to copy a node, use the `Clone` function:
|
||||
|
||||
```
|
||||
std::auto_ptr<YAML::Node> pCopy = myOtherNode.Clone();
|
||||
```
|
||||
|
||||
The intent is that if you'd like to keep a `YAML::Node` around for longer than the document will stay in scope, you can clone it and store it as long as you like.
|
18
docs/Strings.md
Normal file
18
docs/Strings.md
Normal file
@@ -0,0 +1,18 @@
|
||||
# Encodings and `yaml-cpp` #
|
||||
|
||||
`yaml-cpp` will parse any file as specified by the [YAML 1.2 spec](http://www.yaml.org/spec/1.2/spec.html#id2570322). Internally, it stores all strings in UTF-8, and representation is done with UTF-8. This means that in
|
||||
|
||||
```
|
||||
std::string str;
|
||||
node >> str;
|
||||
```
|
||||
|
||||
`str` will be UTF-8. Similarly, if you're accessing a map by string key, you need to pass the key in UTF-8. If your application uses a different encoding, you need to convert to and from UTF-8 to work with `yaml-cpp`. (It's possible we'll add some small conversion functions, but for now it's restricted.)
|
||||
|
||||
---
|
||||
|
||||
For convenience, Richard Weeks has kindly provided a google gadget that converts Unicode to a string literal. It's a Google Gadget, so unfortunately it does not work on GitHub. Patches welcome to port it to a usable format here:
|
||||
|
||||
```
|
||||
<wiki:gadget url="http://hosting.gmodules.com/ig/gadgets/file/111180078345548400783/c-style-utf8-encoder.xml"/>
|
||||
```
|
201
docs/Tutorial.md
Normal file
201
docs/Tutorial.md
Normal file
@@ -0,0 +1,201 @@
|
||||
# Introduction #
|
||||
|
||||
A typical example, loading a configuration file, might look like this:
|
||||
|
||||
```cpp
|
||||
YAML::Node config = YAML::LoadFile("config.yaml");
|
||||
|
||||
if (config["lastLogin"]) {
|
||||
std::cout << "Last logged in: " << config["lastLogin"].as<DateTime>() << "\n";
|
||||
}
|
||||
|
||||
const std::string username = config["username"].as<std::string>();
|
||||
const std::string password = config["password"].as<std::string>();
|
||||
login(username, password);
|
||||
config["lastLogin"] = getCurrentDateTime();
|
||||
|
||||
std::ofstream fout("config.yaml");
|
||||
fout << config;
|
||||
```
|
||||
|
||||
# Basic Parsing and Node Editing #
|
||||
|
||||
All nodes in a YAML document (including the root) are represented by `YAML::Node`. You can check what kind it is:
|
||||
|
||||
```cpp
|
||||
YAML::Node node = YAML::Load("[1, 2, 3]");
|
||||
assert(node.Type() == YAML::NodeType::Sequence);
|
||||
assert(node.IsSequence()); // a shortcut!
|
||||
```
|
||||
|
||||
Collection nodes (sequences and maps) act somewhat like STL vectors and maps:
|
||||
|
||||
```cpp
|
||||
YAML::Node primes = YAML::Load("[2, 3, 5, 7, 11]");
|
||||
for (std::size_t i=0;i<primes.size();i++) {
|
||||
std::cout << primes[i].as<int>() << "\n";
|
||||
}
|
||||
// or:
|
||||
for (YAML::const_iterator it=primes.begin();it!=primes.end();++it) {
|
||||
std::cout << it->as<int>() << "\n";
|
||||
}
|
||||
|
||||
primes.push_back(13);
|
||||
assert(primes.size() == 6);
|
||||
```
|
||||
|
||||
and
|
||||
|
||||
```cpp
|
||||
YAML::Node lineup = YAML::Load("{1B: Prince Fielder, 2B: Rickie Weeks, LF: Ryan Braun}");
|
||||
for(YAML::const_iterator it=lineup.begin();it!=lineup.end();++it) {
|
||||
std::cout << "Playing at " << it->first.as<std::string>() << " is " << it->second.as<std::string>() << "\n";
|
||||
}
|
||||
|
||||
lineup["RF"] = "Corey Hart";
|
||||
lineup["C"] = "Jonathan Lucroy";
|
||||
assert(lineup.size() == 5);
|
||||
```
|
||||
|
||||
Querying for keys does **not** create them automatically (this makes handling optional map entries very easy)
|
||||
|
||||
```cpp
|
||||
YAML::Node node = YAML::Load("{name: Brewers, city: Milwaukee}");
|
||||
if (node["name"]) {
|
||||
std::cout << node["name"].as<std::string>() << "\n";
|
||||
}
|
||||
if (node["mascot"]) {
|
||||
std::cout << node["mascot"].as<std::string>() << "\n";
|
||||
}
|
||||
assert(node.size() == 2); // the previous call didn't create a node
|
||||
```
|
||||
|
||||
If you're not sure what kind of data you're getting, you can query the type of a node:
|
||||
|
||||
```cpp
|
||||
switch (node.Type()) {
|
||||
case Null: // ...
|
||||
case Scalar: // ...
|
||||
case Sequence: // ...
|
||||
case Map: // ...
|
||||
case Undefined: // ...
|
||||
}
|
||||
```
|
||||
|
||||
or ask directly whether it's a particular type, e.g.:
|
||||
|
||||
```cpp
|
||||
if (node.IsSequence()) {
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
# Building Nodes #
|
||||
|
||||
You can build `YAML::Node` from scratch:
|
||||
|
||||
```cpp
|
||||
YAML::Node node; // starts out as null
|
||||
node["key"] = "value"; // it now is a map node
|
||||
node["seq"].push_back("first element"); // node["seq"] automatically becomes a sequence
|
||||
node["seq"].push_back("second element");
|
||||
|
||||
node["mirror"] = node["seq"][0]; // this creates an alias
|
||||
node["seq"][0] = "1st element"; // this also changes node["mirror"]
|
||||
node["mirror"] = "element #1"; // and this changes node["seq"][0] - they're really the "same" node
|
||||
|
||||
node["self"] = node; // you can even create self-aliases
|
||||
node[node["mirror"]] = node["seq"]; // and strange loops :)
|
||||
```
|
||||
|
||||
The above node is now:
|
||||
|
||||
```yaml
|
||||
&1
|
||||
key: value
|
||||
&2 seq: [&3 "element #1", second element]
|
||||
mirror: *3
|
||||
self: *1
|
||||
*3 : *2
|
||||
```
|
||||
|
||||
# How Sequences Turn Into Maps #
|
||||
|
||||
Sequences can be turned into maps by asking for non-integer keys. For example,
|
||||
|
||||
```cpp
|
||||
YAML::Node node = YAML::Load("[1, 2, 3]");
|
||||
node[1] = 5; // still a sequence, [1, 5, 3]
|
||||
node.push_back(-3) // still a sequence, [1, 5, 3, -3]
|
||||
node["key"] = "value"; // now it's a map! {0: 1, 1: 5, 2: 3, 3: -3, key: value}
|
||||
```
|
||||
|
||||
Indexing a sequence node by an index that's not in its range will _usually_ turn it into a map, but if the index is one past the end of the sequence, then the sequence will grow by one to accommodate it. (That's the **only** exception to this rule.) For example,
|
||||
|
||||
```cpp
|
||||
YAML::Node node = YAML::Load("[1, 2, 3]");
|
||||
node[3] = 4; // still a sequence, [1, 2, 3, 4]
|
||||
node[10] = 10; // now it's a map! {0: 1, 1: 2, 2: 3, 3: 4, 10: 10}
|
||||
```
|
||||
|
||||
# Converting To/From Native Data Types #
|
||||
|
||||
Yaml-cpp has built-in conversion to and from most built-in data types, as well as `std::vector`, `std::list`, and `std::map`. The following examples demonstrate when those conversions are used:
|
||||
|
||||
```cpp
|
||||
YAML::Node node = YAML::Load("{pi: 3.14159, [0, 1]: integers}");
|
||||
|
||||
// this needs the conversion from Node to double
|
||||
double pi = node["pi"].as<double>();
|
||||
|
||||
// this needs the conversion from double to Node
|
||||
node["e"] = 2.71828;
|
||||
|
||||
// this needs the conversion from Node to std::vector<int> (*not* the other way around!)
|
||||
std::vector<int> v;
|
||||
v.push_back(0);
|
||||
v.push_back(1);
|
||||
std::string str = node[v].as<std::string>();
|
||||
```
|
||||
|
||||
To use yaml-cpp with your own data types, you need to specialize the YAML::convert<> template class. For example, suppose you had a simple `Vec3` class:
|
||||
|
||||
```cpp
|
||||
struct Vec3 { double x, y, z; /* etc - make sure you have overloaded operator== */ };
|
||||
```
|
||||
|
||||
You could write
|
||||
|
||||
```cpp
|
||||
namespace YAML {
|
||||
template<>
|
||||
struct convert<Vec3> {
|
||||
static Node encode(const Vec3& rhs) {
|
||||
Node node;
|
||||
node.push_back(rhs.x);
|
||||
node.push_back(rhs.y);
|
||||
node.push_back(rhs.z);
|
||||
return node;
|
||||
}
|
||||
|
||||
static bool decode(const Node& node, Vec3& rhs) {
|
||||
if(!node.IsSequence() || node.size() != 3) {
|
||||
return false;
|
||||
}
|
||||
|
||||
rhs.x = node[0].as<double>();
|
||||
rhs.y = node[1].as<double>();
|
||||
rhs.z = node[2].as<double>();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
Then you could use `Vec3` wherever you could use any other type:
|
||||
|
||||
```cpp
|
||||
YAML::Node node = YAML::Load("start: [1, 3, 0]");
|
||||
Vec3 v = node["start"].as<Vec3>();
|
||||
node["end"] = Vec3(2, -1, 0);
|
||||
```
|
1
docs/_config.yml
Normal file
1
docs/_config.yml
Normal file
@@ -0,0 +1 @@
|
||||
theme: jekyll-theme-slate
|
1
docs/index.md
Normal file
1
docs/index.md
Normal file
@@ -0,0 +1 @@
|
||||
To learn how to use the library, see the [Tutorial](https://github.com/jbeder/yaml-cpp/wiki/Tutorial) and [How To Emit YAML](https://github.com/jbeder/yaml-cpp/wiki/How-To-Emit-YAML)
|
@@ -10,7 +10,7 @@
|
||||
#include <cstddef>
|
||||
|
||||
namespace YAML {
|
||||
typedef std::size_t anchor_t;
|
||||
using anchor_t = std::size_t;
|
||||
const anchor_t NullAnchor = 0;
|
||||
}
|
||||
|
||||
|
@@ -15,7 +15,7 @@ class Parser;
|
||||
|
||||
// GraphBuilderInterface
|
||||
// . Abstraction of node creation
|
||||
// . pParentNode is always NULL or the return value of one of the NewXXX()
|
||||
// . pParentNode is always nullptr or the return value of one of the NewXXX()
|
||||
// functions.
|
||||
class GraphBuilderInterface {
|
||||
public:
|
||||
@@ -73,9 +73,9 @@ class GraphBuilder : public GraphBuilderInterface {
|
||||
typedef typename Impl::Map Map;
|
||||
|
||||
GraphBuilder(Impl &impl) : m_impl(impl) {
|
||||
Map *pMap = NULL;
|
||||
Sequence *pSeq = NULL;
|
||||
Node *pNode = NULL;
|
||||
Map *pMap = nullptr;
|
||||
Sequence *pSeq = nullptr;
|
||||
Node *pNode = nullptr;
|
||||
|
||||
// Type consistency checks
|
||||
pNode = pMap;
|
||||
|
77
include/yaml-cpp/depthguard.h
Normal file
77
include/yaml-cpp/depthguard.h
Normal file
@@ -0,0 +1,77 @@
|
||||
#ifndef DEPTH_GUARD_H_00000000000000000000000000000000000000000000000000000000
|
||||
#define DEPTH_GUARD_H_00000000000000000000000000000000000000000000000000000000
|
||||
|
||||
#if defined(_MSC_VER) || \
|
||||
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "exceptions.h"
|
||||
|
||||
namespace YAML {
|
||||
|
||||
/**
|
||||
* @brief The DeepRecursion class
|
||||
* An exception class which is thrown by DepthGuard. Ideally it should be
|
||||
* a member of DepthGuard. However, DepthGuard is a templated class which means
|
||||
* that any catch points would then need to know the template parameters. It is
|
||||
* simpler for clients to not have to know at the catch point what was the
|
||||
* maximum depth.
|
||||
*/
|
||||
class DeepRecursion : public ParserException {
|
||||
public:
|
||||
virtual ~DeepRecursion() = default;
|
||||
|
||||
DeepRecursion(int depth, const Mark& mark_, const std::string& msg_);
|
||||
|
||||
// Returns the recursion depth when the exception was thrown
|
||||
int depth() const {
|
||||
return m_depth;
|
||||
}
|
||||
|
||||
private:
|
||||
int m_depth = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The DepthGuard class
|
||||
* DepthGuard takes a reference to an integer. It increments the integer upon
|
||||
* construction of DepthGuard and decrements the integer upon destruction.
|
||||
*
|
||||
* If the integer would be incremented past max_depth, then an exception is
|
||||
* thrown. This is ideally geared toward guarding against deep recursion.
|
||||
*
|
||||
* @param max_depth
|
||||
* compile-time configurable maximum depth.
|
||||
*/
|
||||
template <int max_depth = 2000>
|
||||
class DepthGuard final {
|
||||
public:
|
||||
DepthGuard(int & depth_, const Mark& mark_, const std::string& msg_) : m_depth(depth_) {
|
||||
++m_depth;
|
||||
if ( max_depth <= m_depth ) {
|
||||
throw DeepRecursion{m_depth, mark_, msg_};
|
||||
}
|
||||
}
|
||||
|
||||
DepthGuard(const DepthGuard & copy_ctor) = delete;
|
||||
DepthGuard(DepthGuard && move_ctor) = delete;
|
||||
DepthGuard & operator=(const DepthGuard & copy_assign) = delete;
|
||||
DepthGuard & operator=(DepthGuard && move_assign) = delete;
|
||||
|
||||
~DepthGuard() {
|
||||
--m_depth;
|
||||
}
|
||||
|
||||
int current_depth() const {
|
||||
return m_depth;
|
||||
}
|
||||
|
||||
private:
|
||||
int & m_depth;
|
||||
};
|
||||
|
||||
} // namespace YAML
|
||||
|
||||
#endif // DEPTH_GUARD_H_00000000000000000000000000000000000000000000000000000000
|
@@ -24,21 +24,21 @@ class EmitFromEvents : public EventHandler {
|
||||
public:
|
||||
EmitFromEvents(Emitter& emitter);
|
||||
|
||||
virtual void OnDocumentStart(const Mark& mark);
|
||||
virtual void OnDocumentEnd();
|
||||
void OnDocumentStart(const Mark& mark) override;
|
||||
void OnDocumentEnd() 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 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 OnSequenceStart(const Mark& mark, const std::string& tag,
|
||||
anchor_t anchor, EmitterStyle::value style);
|
||||
virtual void OnSequenceEnd();
|
||||
void OnSequenceStart(const Mark& mark, const std::string& tag,
|
||||
anchor_t anchor, EmitterStyle::value style) override;
|
||||
void OnSequenceEnd() override;
|
||||
|
||||
virtual void OnMapStart(const Mark& mark, const std::string& tag,
|
||||
anchor_t anchor, EmitterStyle::value style);
|
||||
virtual void OnMapEnd();
|
||||
void OnMapStart(const Mark& mark, const std::string& tag,
|
||||
anchor_t anchor, EmitterStyle::value style) override;
|
||||
void OnMapEnd() override;
|
||||
|
||||
private:
|
||||
void BeginNode();
|
||||
|
@@ -50,6 +50,7 @@ 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);
|
||||
@@ -58,6 +59,7 @@ class YAML_CPP_API Emitter {
|
||||
bool SetPostCommentIndent(std::size_t n);
|
||||
bool SetFloatPrecision(std::size_t n);
|
||||
bool SetDoublePrecision(std::size_t n);
|
||||
void RestoreGlobalModifiedSettings();
|
||||
|
||||
// local setters
|
||||
Emitter& SetLocalValue(EMITTER_MANIP value);
|
||||
@@ -123,6 +125,7 @@ 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:
|
||||
@@ -164,13 +167,12 @@ inline Emitter& Emitter::WriteStreamable(T value) {
|
||||
std::isnan(value)) {
|
||||
special = true;
|
||||
stream << ".nan";
|
||||
} else if (std::numeric_limits<T>::has_infinity) {
|
||||
if (value == std::numeric_limits<T>::infinity()) {
|
||||
special = true;
|
||||
stream << ".inf";
|
||||
} else if (value == -std::numeric_limits<T>::infinity()) {
|
||||
special = true;
|
||||
} else if (std::numeric_limits<T>::has_infinity && std::isinf(value)) {
|
||||
special = true;
|
||||
if (std::signbit(value)) {
|
||||
stream << "-.inf";
|
||||
} else {
|
||||
stream << ".inf";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -19,6 +19,7 @@ enum EMITTER_MANIP {
|
||||
// output character set
|
||||
EmitNonAscii,
|
||||
EscapeNonAscii,
|
||||
EscapeAsJson,
|
||||
|
||||
// string manipulators
|
||||
// Auto, // duplicate
|
||||
@@ -26,6 +27,12 @@ enum EMITTER_MANIP {
|
||||
DoubleQuoted,
|
||||
Literal,
|
||||
|
||||
// null manipulators
|
||||
LowerNull,
|
||||
UpperNull,
|
||||
CamelNull,
|
||||
TildeNull,
|
||||
|
||||
// bool manipulators
|
||||
YesNoBool, // yes, no
|
||||
TrueFalseBool, // true, false
|
||||
@@ -74,14 +81,14 @@ struct _Alias {
|
||||
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 {
|
||||
@@ -96,11 +103,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);
|
||||
}
|
||||
|
||||
@@ -108,7 +115,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);
|
||||
}
|
||||
|
||||
@@ -117,7 +124,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_)
|
||||
|
@@ -17,7 +17,7 @@ struct Mark;
|
||||
|
||||
class EventHandler {
|
||||
public:
|
||||
virtual ~EventHandler() {}
|
||||
virtual ~EventHandler() = default;
|
||||
|
||||
virtual void OnDocumentStart(const Mark& mark) = 0;
|
||||
virtual void OnDocumentEnd() = 0;
|
||||
|
@@ -8,19 +8,12 @@
|
||||
#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 {
|
||||
@@ -107,6 +100,12 @@ 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) {
|
||||
@@ -127,6 +126,12 @@ inline const std::string BAD_SUBSCRIPT_WITH_KEY(const std::string& 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) {
|
||||
@@ -143,13 +148,13 @@ inline const std::string INVALID_NODE_WITH_KEY(const std::string& key) {
|
||||
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_) {}
|
||||
virtual ~Exception() YAML_CPP_NOEXCEPT;
|
||||
~Exception() YAML_CPP_NOEXCEPT override;
|
||||
|
||||
Exception(const Exception&) = default;
|
||||
|
||||
@@ -175,7 +180,7 @@ class YAML_CPP_API ParserException : public Exception {
|
||||
ParserException(const Mark& mark_, const std::string& msg_)
|
||||
: Exception(mark_, msg_) {}
|
||||
ParserException(const ParserException&) = default;
|
||||
virtual ~ParserException() YAML_CPP_NOEXCEPT;
|
||||
~ParserException() YAML_CPP_NOEXCEPT override;
|
||||
};
|
||||
|
||||
class YAML_CPP_API RepresentationException : public Exception {
|
||||
@@ -183,7 +188,7 @@ class YAML_CPP_API RepresentationException : public Exception {
|
||||
RepresentationException(const Mark& mark_, const std::string& msg_)
|
||||
: Exception(mark_, msg_) {}
|
||||
RepresentationException(const RepresentationException&) = default;
|
||||
virtual ~RepresentationException() YAML_CPP_NOEXCEPT;
|
||||
~RepresentationException() YAML_CPP_NOEXCEPT override;
|
||||
};
|
||||
|
||||
// representation exceptions
|
||||
@@ -192,7 +197,7 @@ class YAML_CPP_API InvalidScalar : public RepresentationException {
|
||||
InvalidScalar(const Mark& mark_)
|
||||
: RepresentationException(mark_, ErrorMsg::INVALID_SCALAR) {}
|
||||
InvalidScalar(const InvalidScalar&) = default;
|
||||
virtual ~InvalidScalar() YAML_CPP_NOEXCEPT;
|
||||
~InvalidScalar() YAML_CPP_NOEXCEPT override;
|
||||
};
|
||||
|
||||
class YAML_CPP_API KeyNotFound : public RepresentationException {
|
||||
@@ -202,7 +207,7 @@ class YAML_CPP_API KeyNotFound : public RepresentationException {
|
||||
: RepresentationException(mark_, ErrorMsg::KEY_NOT_FOUND_WITH_KEY(key_)) {
|
||||
}
|
||||
KeyNotFound(const KeyNotFound&) = default;
|
||||
virtual ~KeyNotFound() YAML_CPP_NOEXCEPT;
|
||||
~KeyNotFound() YAML_CPP_NOEXCEPT override;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
@@ -210,7 +215,7 @@ class YAML_CPP_API TypedKeyNotFound : public KeyNotFound {
|
||||
public:
|
||||
TypedKeyNotFound(const Mark& mark_, const T& key_)
|
||||
: KeyNotFound(mark_, key_), key(key_) {}
|
||||
virtual ~TypedKeyNotFound() YAML_CPP_NOEXCEPT {}
|
||||
~TypedKeyNotFound() YAML_CPP_NOEXCEPT override = default;
|
||||
|
||||
T key;
|
||||
};
|
||||
@@ -223,11 +228,11 @@ inline TypedKeyNotFound<T> MakeTypedKeyNotFound(const Mark& mark,
|
||||
|
||||
class YAML_CPP_API InvalidNode : public RepresentationException {
|
||||
public:
|
||||
InvalidNode(std::string key)
|
||||
InvalidNode(const std::string& key)
|
||||
: RepresentationException(Mark::null_mark(),
|
||||
ErrorMsg::INVALID_NODE_WITH_KEY(key)) {}
|
||||
InvalidNode(const InvalidNode&) = default;
|
||||
virtual ~InvalidNode() YAML_CPP_NOEXCEPT;
|
||||
~InvalidNode() YAML_CPP_NOEXCEPT override;
|
||||
};
|
||||
|
||||
class YAML_CPP_API BadConversion : public RepresentationException {
|
||||
@@ -235,7 +240,7 @@ class YAML_CPP_API BadConversion : public RepresentationException {
|
||||
explicit BadConversion(const Mark& mark_)
|
||||
: RepresentationException(mark_, ErrorMsg::BAD_CONVERSION) {}
|
||||
BadConversion(const BadConversion&) = default;
|
||||
virtual ~BadConversion() YAML_CPP_NOEXCEPT;
|
||||
~BadConversion() YAML_CPP_NOEXCEPT override;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
@@ -249,17 +254,16 @@ class YAML_CPP_API BadDereference : public RepresentationException {
|
||||
BadDereference()
|
||||
: RepresentationException(Mark::null_mark(), ErrorMsg::BAD_DEREFERENCE) {}
|
||||
BadDereference(const BadDereference&) = default;
|
||||
virtual ~BadDereference() YAML_CPP_NOEXCEPT;
|
||||
~BadDereference() YAML_CPP_NOEXCEPT override;
|
||||
};
|
||||
|
||||
class YAML_CPP_API BadSubscript : public RepresentationException {
|
||||
public:
|
||||
template <typename Key>
|
||||
BadSubscript(const Key& key)
|
||||
: RepresentationException(Mark::null_mark(),
|
||||
ErrorMsg::BAD_SUBSCRIPT_WITH_KEY(key)) {}
|
||||
BadSubscript(const Mark& mark_, const Key& key)
|
||||
: RepresentationException(mark_, ErrorMsg::BAD_SUBSCRIPT_WITH_KEY(key)) {}
|
||||
BadSubscript(const BadSubscript&) = default;
|
||||
virtual ~BadSubscript() YAML_CPP_NOEXCEPT;
|
||||
~BadSubscript() YAML_CPP_NOEXCEPT override;
|
||||
};
|
||||
|
||||
class YAML_CPP_API BadPushback : public RepresentationException {
|
||||
@@ -267,7 +271,7 @@ class YAML_CPP_API BadPushback : public RepresentationException {
|
||||
BadPushback()
|
||||
: RepresentationException(Mark::null_mark(), ErrorMsg::BAD_PUSHBACK) {}
|
||||
BadPushback(const BadPushback&) = default;
|
||||
virtual ~BadPushback() YAML_CPP_NOEXCEPT;
|
||||
~BadPushback() YAML_CPP_NOEXCEPT override;
|
||||
};
|
||||
|
||||
class YAML_CPP_API BadInsert : public RepresentationException {
|
||||
@@ -275,7 +279,7 @@ class YAML_CPP_API BadInsert : public RepresentationException {
|
||||
BadInsert()
|
||||
: RepresentationException(Mark::null_mark(), ErrorMsg::BAD_INSERT) {}
|
||||
BadInsert(const BadInsert&) = default;
|
||||
virtual ~BadInsert() YAML_CPP_NOEXCEPT;
|
||||
~BadInsert() YAML_CPP_NOEXCEPT override;
|
||||
};
|
||||
|
||||
class YAML_CPP_API EmitterException : public Exception {
|
||||
@@ -283,17 +287,17 @@ class YAML_CPP_API EmitterException : public Exception {
|
||||
EmitterException(const std::string& msg_)
|
||||
: Exception(Mark::null_mark(), msg_) {}
|
||||
EmitterException(const EmitterException&) = default;
|
||||
virtual ~EmitterException() YAML_CPP_NOEXCEPT;
|
||||
~EmitterException() YAML_CPP_NOEXCEPT override;
|
||||
};
|
||||
|
||||
class YAML_CPP_API BadFile : public Exception {
|
||||
public:
|
||||
BadFile() : Exception(Mark::null_mark(), ErrorMsg::BAD_FILE) {}
|
||||
explicit BadFile(const std::string& filename)
|
||||
: Exception(Mark::null_mark(),
|
||||
std::string(ErrorMsg::BAD_FILE) + ": " + filename) {}
|
||||
BadFile(const BadFile&) = default;
|
||||
virtual ~BadFile() YAML_CPP_NOEXCEPT;
|
||||
~BadFile() YAML_CPP_NOEXCEPT override;
|
||||
};
|
||||
}
|
||||
|
||||
#undef YAML_CPP_NOEXCEPT
|
||||
} // namespace YAML
|
||||
|
||||
#endif // EXCEPTIONS_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
|
@@ -8,10 +8,12 @@
|
||||
#endif
|
||||
|
||||
#include <array>
|
||||
#include <cmath>
|
||||
#include <limits>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <sstream>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
|
||||
#include "yaml-cpp/binary.h"
|
||||
@@ -21,6 +23,7 @@
|
||||
#include "yaml-cpp/node/type.h"
|
||||
#include "yaml-cpp/null.h"
|
||||
|
||||
|
||||
namespace YAML {
|
||||
class Binary;
|
||||
struct _Null;
|
||||
@@ -71,12 +74,17 @@ struct convert<std::string> {
|
||||
// C-strings can only be encoded
|
||||
template <>
|
||||
struct convert<const char*> {
|
||||
static Node encode(const char*& rhs) { return Node(rhs); }
|
||||
static Node encode(const char* rhs) { return Node(rhs); }
|
||||
};
|
||||
|
||||
template <>
|
||||
struct convert<char*> {
|
||||
static Node encode(const char* rhs) { return Node(rhs); }
|
||||
};
|
||||
|
||||
template <std::size_t N>
|
||||
struct convert<const char[N]> {
|
||||
static Node encode(const char(&rhs)[N]) { return Node(rhs); }
|
||||
struct convert<char[N]> {
|
||||
static Node encode(const char* rhs) { return Node(rhs); }
|
||||
};
|
||||
|
||||
template <>
|
||||
@@ -88,43 +96,98 @@ struct convert<_Null> {
|
||||
}
|
||||
};
|
||||
|
||||
#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; \
|
||||
} \
|
||||
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 << rhs;
|
||||
}
|
||||
}
|
||||
|
||||
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 = (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;
|
||||
}
|
||||
}
|
||||
|
||||
#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); \
|
||||
conversion::inner_encode(rhs, stream); \
|
||||
return Node(stream.str()); \
|
||||
} \
|
||||
\
|
||||
static bool decode(const Node& node, type& rhs) { \
|
||||
if (node.Type() != NodeType::Scalar) { \
|
||||
return false; \
|
||||
} \
|
||||
const std::string& input = node.Scalar(); \
|
||||
std::stringstream stream(input); \
|
||||
stream.unsetf(std::ios::dec); \
|
||||
if ((stream.peek() == '-') && std::is_unsigned<type>::value) { \
|
||||
return false; \
|
||||
} \
|
||||
if (conversion::ConvertStreamTo(stream, rhs)) { \
|
||||
return true; \
|
||||
} \
|
||||
if (std::numeric_limits<type>::has_infinity) { \
|
||||
if (conversion::IsInfinity(input)) { \
|
||||
rhs = std::numeric_limits<type>::infinity(); \
|
||||
return true; \
|
||||
} else if (conversion::IsNegativeInfinity(input)) { \
|
||||
rhs = negative_op std::numeric_limits<type>::infinity(); \
|
||||
return true; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
if (std::numeric_limits<type>::has_quiet_NaN) { \
|
||||
if (conversion::IsNaN(input)) { \
|
||||
rhs = std::numeric_limits<type>::quiet_NaN(); \
|
||||
return true; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
return false; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define YAML_DEFINE_CONVERT_STREAMABLE_SIGNED(type) \
|
||||
@@ -163,81 +226,78 @@ struct convert<bool> {
|
||||
};
|
||||
|
||||
// std::map
|
||||
template <typename K, typename V>
|
||||
struct convert<std::map<K, V>> {
|
||||
static Node encode(const std::map<K, V>& rhs) {
|
||||
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) {
|
||||
Node node(NodeType::Map);
|
||||
for (typename std::map<K, V>::const_iterator it = rhs.begin();
|
||||
it != rhs.end(); ++it)
|
||||
node.force_insert(it->first, it->second);
|
||||
for (const auto& element : rhs)
|
||||
node.force_insert(element.first, element.second);
|
||||
return node;
|
||||
}
|
||||
|
||||
static bool decode(const Node& node, std::map<K, V>& rhs) {
|
||||
static bool decode(const Node& node, std::map<K, V, C, A>& rhs) {
|
||||
if (!node.IsMap())
|
||||
return false;
|
||||
|
||||
rhs.clear();
|
||||
for (const_iterator it = node.begin(); it != node.end(); ++it)
|
||||
for (const auto& element : node)
|
||||
#if defined(__GNUC__) && __GNUC__ < 4
|
||||
// workaround for GCC 3:
|
||||
rhs[it->first.template as<K>()] = it->second.template as<V>();
|
||||
rhs[element.first.template as<K>()] = element.second.template as<V>();
|
||||
#else
|
||||
rhs[it->first.as<K>()] = it->second.as<V>();
|
||||
rhs[element.first.as<K>()] = element.second.as<V>();
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
// std::vector
|
||||
template <typename T>
|
||||
struct convert<std::vector<T>> {
|
||||
static Node encode(const std::vector<T>& rhs) {
|
||||
template <typename T, typename A>
|
||||
struct convert<std::vector<T, A>> {
|
||||
static Node encode(const std::vector<T, A>& rhs) {
|
||||
Node node(NodeType::Sequence);
|
||||
for (typename std::vector<T>::const_iterator it = rhs.begin();
|
||||
it != rhs.end(); ++it)
|
||||
node.push_back(*it);
|
||||
for (const auto& element : rhs)
|
||||
node.push_back(element);
|
||||
return node;
|
||||
}
|
||||
|
||||
static bool decode(const Node& node, std::vector<T>& rhs) {
|
||||
static bool decode(const Node& node, std::vector<T, A>& rhs) {
|
||||
if (!node.IsSequence())
|
||||
return false;
|
||||
|
||||
rhs.clear();
|
||||
for (const_iterator it = node.begin(); it != node.end(); ++it)
|
||||
for (const auto& element : node)
|
||||
#if defined(__GNUC__) && __GNUC__ < 4
|
||||
// workaround for GCC 3:
|
||||
rhs.push_back(it->template as<T>());
|
||||
rhs.push_back(element.template as<T>());
|
||||
#else
|
||||
rhs.push_back(it->as<T>());
|
||||
rhs.push_back(element.as<T>());
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
// std::list
|
||||
template <typename T>
|
||||
struct convert<std::list<T>> {
|
||||
static Node encode(const std::list<T>& rhs) {
|
||||
template <typename T, typename A>
|
||||
struct convert<std::list<T,A>> {
|
||||
static Node encode(const std::list<T,A>& rhs) {
|
||||
Node node(NodeType::Sequence);
|
||||
for (typename std::list<T>::const_iterator it = rhs.begin();
|
||||
it != rhs.end(); ++it)
|
||||
node.push_back(*it);
|
||||
for (const auto& element : rhs)
|
||||
node.push_back(element);
|
||||
return node;
|
||||
}
|
||||
|
||||
static bool decode(const Node& node, std::list<T>& rhs) {
|
||||
static bool decode(const Node& node, std::list<T,A>& rhs) {
|
||||
if (!node.IsSequence())
|
||||
return false;
|
||||
|
||||
rhs.clear();
|
||||
for (const_iterator it = node.begin(); it != node.end(); ++it)
|
||||
for (const auto& element : node)
|
||||
#if defined(__GNUC__) && __GNUC__ < 4
|
||||
// workaround for GCC 3:
|
||||
rhs.push_back(it->template as<T>());
|
||||
rhs.push_back(element.template as<T>());
|
||||
#else
|
||||
rhs.push_back(it->as<T>());
|
||||
rhs.push_back(element.as<T>());
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
@@ -1,26 +0,0 @@
|
||||
#ifndef NODE_DETAIL_BOOL_TYPE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
#define NODE_DETAIL_BOOL_TYPE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
|
||||
#if defined(_MSC_VER) || \
|
||||
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
namespace YAML {
|
||||
namespace detail {
|
||||
struct unspecified_bool {
|
||||
struct NOT_ALLOWED;
|
||||
static void true_value(NOT_ALLOWED*) {}
|
||||
};
|
||||
typedef void (*unspecified_bool_type)(unspecified_bool::NOT_ALLOWED*);
|
||||
}
|
||||
}
|
||||
|
||||
#define YAML_CPP_OPERATOR_BOOL() \
|
||||
operator YAML::detail::unspecified_bool_type() const { \
|
||||
return this->operator!() ? 0 \
|
||||
: &YAML::detail::unspecified_bool::true_value; \
|
||||
}
|
||||
|
||||
#endif // NODE_DETAIL_BOOL_TYPE_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
@@ -9,6 +9,8 @@
|
||||
|
||||
#include "yaml-cpp/node/detail/node.h"
|
||||
#include "yaml-cpp/node/detail/node_data.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <type_traits>
|
||||
|
||||
namespace YAML {
|
||||
@@ -33,7 +35,7 @@ struct get_idx<Key,
|
||||
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 0;
|
||||
return nullptr;
|
||||
if (key == sequence.size())
|
||||
sequence.push_back(&pMemory->create_node());
|
||||
return sequence[key];
|
||||
@@ -58,7 +60,9 @@ struct get_idx<Key, typename std::enable_if<std::is_signed<Key>::value>::type> {
|
||||
|
||||
template <typename Key, typename Enable = void>
|
||||
struct remove_idx {
|
||||
static bool remove(std::vector<node*>&, const Key&) { return false; }
|
||||
static bool remove(std::vector<node*>&, const Key&, std::size_t&) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Key>
|
||||
@@ -66,11 +70,15 @@ 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) {
|
||||
static bool remove(std::vector<node*>& sequence, const Key& key,
|
||||
std::size_t& seqSize) {
|
||||
if (key >= sequence.size()) {
|
||||
return false;
|
||||
} else {
|
||||
sequence.erase(sequence.begin() + key);
|
||||
if (seqSize > key) {
|
||||
--seqSize;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -80,9 +88,10 @@ 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) {
|
||||
static bool remove(std::vector<node*>& sequence, const Key& key,
|
||||
std::size_t& seqSize) {
|
||||
return key >= 0 ? remove_idx<std::size_t>::remove(
|
||||
sequence, static_cast<std::size_t>(key))
|
||||
sequence, static_cast<std::size_t>(key), seqSize)
|
||||
: false;
|
||||
}
|
||||
};
|
||||
@@ -97,7 +106,11 @@ inline bool node::equals(const T& rhs, shared_memory_holder pMemory) {
|
||||
}
|
||||
|
||||
inline bool node::equals(const char* rhs, shared_memory_holder pMemory) {
|
||||
return equals<std::string>(rhs, pMemory);
|
||||
std::string lhs;
|
||||
if (convert<std::string>::decode(Node(*this, std::move(pMemory)), lhs)) {
|
||||
return lhs == rhs;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// indexing
|
||||
@@ -115,16 +128,14 @@ inline node* node_data::get(const Key& key,
|
||||
return pNode;
|
||||
return nullptr;
|
||||
case NodeType::Scalar:
|
||||
throw BadSubscript(key);
|
||||
throw BadSubscript(m_mark, key);
|
||||
}
|
||||
|
||||
for (node_map::const_iterator it = m_map.begin(); it != m_map.end(); ++it) {
|
||||
if (it->first->equals(key, pMemory)) {
|
||||
return it->second;
|
||||
}
|
||||
}
|
||||
auto it = std::find_if(m_map.begin(), m_map.end(), [&](const kv_pair m) {
|
||||
return m.first->equals(key, pMemory);
|
||||
});
|
||||
|
||||
return nullptr;
|
||||
return it != m_map.end() ? it->second : nullptr;
|
||||
}
|
||||
|
||||
template <typename Key>
|
||||
@@ -143,13 +154,15 @@ inline node& node_data::get(const Key& key, shared_memory_holder pMemory) {
|
||||
convert_to_map(pMemory);
|
||||
break;
|
||||
case NodeType::Scalar:
|
||||
throw BadSubscript(key);
|
||||
throw BadSubscript(m_mark, key);
|
||||
}
|
||||
|
||||
for (node_map::const_iterator it = m_map.begin(); it != m_map.end(); ++it) {
|
||||
if (it->first->equals(key, pMemory)) {
|
||||
return *it->second;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
node& k = convert_to_node(key, pMemory);
|
||||
@@ -161,8 +174,10 @@ 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);
|
||||
} else if (m_type == NodeType::Map) {
|
||||
return remove_idx<Key>::remove(m_sequence, key, m_seqSize);
|
||||
}
|
||||
|
||||
if (m_type == NodeType::Map) {
|
||||
kv_pairs::iterator it = m_undefinedPairs.begin();
|
||||
while (it != m_undefinedPairs.end()) {
|
||||
kv_pairs::iterator jt = std::next(it);
|
||||
@@ -172,11 +187,13 @@ inline bool node_data::remove(const Key& key, shared_memory_holder pMemory) {
|
||||
it = jt;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -26,7 +26,7 @@ class iterator_base {
|
||||
template <typename>
|
||||
friend class iterator_base;
|
||||
struct enabler {};
|
||||
typedef node_iterator base_type;
|
||||
using base_type = node_iterator;
|
||||
|
||||
struct proxy {
|
||||
explicit proxy(const V& x) : m_ref(x) {}
|
||||
|
@@ -20,8 +20,8 @@ template <typename V>
|
||||
class iterator_base;
|
||||
}
|
||||
|
||||
typedef detail::iterator_base<detail::iterator_value> iterator;
|
||||
typedef detail::iterator_base<const detail::iterator_value> const_iterator;
|
||||
using iterator = detail::iterator_base<detail::iterator_value>;
|
||||
using const_iterator = detail::iterator_base<const detail::iterator_value>;
|
||||
}
|
||||
|
||||
#endif // VALUE_DETAIL_ITERATOR_FWD_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
|
@@ -27,7 +27,7 @@ class YAML_CPP_API memory {
|
||||
void merge(const memory& rhs);
|
||||
|
||||
private:
|
||||
typedef std::set<shared_node> Nodes;
|
||||
using Nodes = std::set<shared_node>;
|
||||
Nodes m_nodes;
|
||||
};
|
||||
|
||||
|
@@ -13,12 +13,18 @@
|
||||
#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(new node_ref), m_dependencies{} {}
|
||||
node() : m_pRef(new node_ref), m_dependencies{}, m_index{} {}
|
||||
node(const node&) = delete;
|
||||
node& operator=(const node&) = delete;
|
||||
|
||||
@@ -42,9 +48,8 @@ class node {
|
||||
return;
|
||||
|
||||
m_pRef->mark_defined();
|
||||
for (nodes::iterator it = m_dependencies.begin();
|
||||
it != m_dependencies.end(); ++it)
|
||||
(*it)->mark_defined();
|
||||
for (node* dependency : m_dependencies)
|
||||
dependency->mark_defined();
|
||||
m_dependencies.clear();
|
||||
}
|
||||
|
||||
@@ -109,6 +114,7 @@ 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);
|
||||
@@ -120,7 +126,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 NULL (if there is no such
|
||||
// it, and returns a pointer so that it can be nullptr (if there is no such
|
||||
// key).
|
||||
return static_cast<const node_ref&>(*m_pRef).get(key, pMemory);
|
||||
}
|
||||
@@ -137,7 +143,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 NULL (if there is no such
|
||||
// it, and returns a pointer so that it can be nullptr (if there is no such
|
||||
// key).
|
||||
return static_cast<const node_ref&>(*m_pRef).get(key, pMemory);
|
||||
}
|
||||
@@ -160,8 +166,10 @@ class node {
|
||||
|
||||
private:
|
||||
shared_node_ref m_pRef;
|
||||
typedef std::set<node*> nodes;
|
||||
using nodes = std::set<node*, less>;
|
||||
nodes m_dependencies;
|
||||
size_t m_index;
|
||||
static std::atomic<size_t> m_amount;
|
||||
};
|
||||
} // namespace detail
|
||||
} // namespace YAML
|
||||
|
@@ -60,8 +60,8 @@ class YAML_CPP_API node_data {
|
||||
node_iterator end();
|
||||
|
||||
// sequence
|
||||
void push_back(node& node, shared_memory_holder pMemory);
|
||||
void insert(node& key, node& value, shared_memory_holder pMemory);
|
||||
void push_back(node& node, const shared_memory_holder& pMemory);
|
||||
void insert(node& key, node& value, const 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, shared_memory_holder pMemory) const;
|
||||
node& get(node& key, shared_memory_holder pMemory);
|
||||
bool remove(node& 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);
|
||||
|
||||
// map
|
||||
template <typename Key, typename Value>
|
||||
@@ -91,8 +91,8 @@ class YAML_CPP_API node_data {
|
||||
void reset_map();
|
||||
|
||||
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);
|
||||
void convert_to_map(const shared_memory_holder& pMemory);
|
||||
void convert_sequence_to_map(const 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
|
||||
typedef std::vector<node*> node_seq;
|
||||
using node_seq = std::vector<node *>;
|
||||
node_seq m_sequence;
|
||||
|
||||
mutable std::size_t m_seqSize;
|
||||
|
||||
// map
|
||||
typedef std::vector<std::pair<node*, node*>> node_map;
|
||||
using node_map = std::vector<std::pair<node*, node*>>;
|
||||
node_map m_map;
|
||||
|
||||
typedef std::pair<node*, node*> kv_pair;
|
||||
typedef std::list<kv_pair> kv_pairs;
|
||||
using kv_pair = std::pair<node*, node*>;
|
||||
using kv_pairs = std::list<kv_pair>;
|
||||
mutable kv_pairs m_undefinedPairs;
|
||||
};
|
||||
}
|
||||
|
@@ -24,7 +24,7 @@ struct iterator_type {
|
||||
|
||||
template <typename V>
|
||||
struct node_iterator_value : public std::pair<V*, V*> {
|
||||
typedef std::pair<V*, V*> kv;
|
||||
using kv = std::pair<V*, V*>;
|
||||
|
||||
node_iterator_value() : kv(), pNode(nullptr) {}
|
||||
explicit node_iterator_value(V& rhs) : kv(), pNode(&rhs) {}
|
||||
@@ -36,26 +36,23 @@ struct node_iterator_value : public std::pair<V*, V*> {
|
||||
V* pNode;
|
||||
};
|
||||
|
||||
typedef std::vector<node*> node_seq;
|
||||
typedef std::vector<std::pair<node*, node*>> node_map;
|
||||
using node_seq = std::vector<node *>;
|
||||
using node_map = std::vector<std::pair<node*, node*>>;
|
||||
|
||||
template <typename V>
|
||||
struct node_iterator_type {
|
||||
typedef node_seq::iterator seq;
|
||||
typedef node_map::iterator map;
|
||||
using seq = node_seq::iterator;
|
||||
using map = node_map::iterator;
|
||||
};
|
||||
|
||||
template <typename V>
|
||||
struct node_iterator_type<const V> {
|
||||
typedef node_seq::const_iterator seq;
|
||||
typedef node_map::const_iterator map;
|
||||
using seq = node_seq::const_iterator;
|
||||
using map = node_map::const_iterator;
|
||||
};
|
||||
|
||||
template <typename V>
|
||||
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>> {
|
||||
class node_iterator_base {
|
||||
private:
|
||||
struct enabler {};
|
||||
|
||||
@@ -68,9 +65,13 @@ class node_iterator_base
|
||||
};
|
||||
|
||||
public:
|
||||
typedef typename node_iterator_type<V>::seq SeqIter;
|
||||
typedef typename node_iterator_type<V>::map MapIter;
|
||||
typedef node_iterator_value<V> value_type;
|
||||
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;
|
||||
|
||||
node_iterator_base()
|
||||
: m_type(iterator_type::NoneType), m_seqIt(), m_mapIt(), m_mapEnd() {}
|
||||
@@ -172,8 +173,8 @@ class node_iterator_base
|
||||
MapIter m_mapIt, m_mapEnd;
|
||||
};
|
||||
|
||||
typedef node_iterator_base<node> node_iterator;
|
||||
typedef node_iterator_base<const node> const_node_iterator;
|
||||
using node_iterator = node_iterator_base<node>;
|
||||
using const_node_iterator = node_iterator_base<const node>;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -42,11 +42,7 @@ inline Node::Node(const detail::iterator_value& rhs)
|
||||
m_pMemory(rhs.m_pMemory),
|
||||
m_pNode(rhs.m_pNode) {}
|
||||
|
||||
inline Node::Node(const Node& 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& rhs) = default;
|
||||
|
||||
inline Node::Node(Zombie)
|
||||
: m_isValid(false), m_invalidKey{}, m_pMemory{}, m_pNode(nullptr) {}
|
||||
@@ -57,7 +53,7 @@ inline Node::Node(Zombie, const std::string& key)
|
||||
inline Node::Node(detail::node& node, detail::shared_memory_holder pMemory)
|
||||
: m_isValid(true), m_invalidKey{}, m_pMemory(pMemory), m_pNode(&node) {}
|
||||
|
||||
inline Node::~Node() {}
|
||||
inline Node::~Node() = default;
|
||||
|
||||
inline void Node::EnsureNodeExists() const {
|
||||
if (!m_isValid)
|
||||
@@ -114,6 +110,8 @@ 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();
|
||||
@@ -142,6 +140,8 @@ struct as_if<std::string, void> {
|
||||
const Node& node;
|
||||
|
||||
std::string operator()() const {
|
||||
if (node.Type() == NodeType::Null)
|
||||
return "null";
|
||||
if (node.Type() != NodeType::Scalar)
|
||||
throw TypedBadConversion<std::string>(node.Mark());
|
||||
return node.Scalar();
|
||||
@@ -176,8 +176,6 @@ inline const std::string& Node::Tag() const {
|
||||
}
|
||||
|
||||
inline void Node::SetTag(const std::string& tag) {
|
||||
if (!m_isValid)
|
||||
throw InvalidNode(m_invalidKey);
|
||||
EnsureNodeExists();
|
||||
m_pNode->set_tag(tag);
|
||||
}
|
||||
@@ -189,8 +187,6 @@ inline EmitterStyle::value Node::Style() const {
|
||||
}
|
||||
|
||||
inline void Node::SetStyle(EmitterStyle::value style) {
|
||||
if (!m_isValid)
|
||||
throw InvalidNode(m_invalidKey);
|
||||
EnsureNodeExists();
|
||||
m_pNode->set_style(style);
|
||||
}
|
||||
@@ -206,15 +202,11 @@ inline bool Node::is(const Node& rhs) const {
|
||||
|
||||
template <typename T>
|
||||
inline Node& Node::operator=(const T& rhs) {
|
||||
if (!m_isValid)
|
||||
throw InvalidNode(m_invalidKey);
|
||||
Assign(rhs);
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Node& Node::operator=(const Node& rhs) {
|
||||
if (!m_isValid || !rhs.m_isValid)
|
||||
throw InvalidNode(m_invalidKey);
|
||||
if (is(rhs))
|
||||
return *this;
|
||||
AssignNode(rhs);
|
||||
@@ -237,29 +229,21 @@ inline void Node::Assign(const T& rhs) {
|
||||
|
||||
template <>
|
||||
inline void Node::Assign(const std::string& rhs) {
|
||||
if (!m_isValid)
|
||||
throw InvalidNode(m_invalidKey);
|
||||
EnsureNodeExists();
|
||||
m_pNode->set_scalar(rhs);
|
||||
}
|
||||
|
||||
inline void Node::Assign(const char* rhs) {
|
||||
if (!m_isValid)
|
||||
throw InvalidNode(m_invalidKey);
|
||||
EnsureNodeExists();
|
||||
m_pNode->set_scalar(rhs);
|
||||
}
|
||||
|
||||
inline void Node::Assign(char* rhs) {
|
||||
if (!m_isValid)
|
||||
throw InvalidNode(m_invalidKey);
|
||||
EnsureNodeExists();
|
||||
m_pNode->set_scalar(rhs);
|
||||
}
|
||||
|
||||
inline void Node::AssignData(const Node& rhs) {
|
||||
if (!m_isValid || !rhs.m_isValid)
|
||||
throw InvalidNode(m_invalidKey);
|
||||
EnsureNodeExists();
|
||||
rhs.EnsureNodeExists();
|
||||
|
||||
@@ -268,7 +252,7 @@ inline void Node::AssignData(const Node& rhs) {
|
||||
}
|
||||
|
||||
inline void Node::AssignNode(const Node& rhs) {
|
||||
if (!m_isValid || !rhs.m_isValid)
|
||||
if (!m_isValid)
|
||||
throw InvalidNode(m_invalidKey);
|
||||
rhs.EnsureNodeExists();
|
||||
|
||||
@@ -324,8 +308,6 @@ inline void Node::push_back(const T& rhs) {
|
||||
}
|
||||
|
||||
inline void Node::push_back(const Node& rhs) {
|
||||
if (!m_isValid || !rhs.m_isValid)
|
||||
throw InvalidNode(m_invalidKey);
|
||||
EnsureNodeExists();
|
||||
rhs.EnsureNodeExists();
|
||||
|
||||
@@ -333,51 +315,6 @@ inline void Node::push_back(const Node& rhs) {
|
||||
m_pMemory->merge(*rhs.m_pMemory);
|
||||
}
|
||||
|
||||
// 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
|
||||
|
||||
template<typename Key>
|
||||
std::string key_to_string(const Key& key) {
|
||||
return streamable_to_string<Key, is_streamable<std::stringstream, Key>::value>().impl(key);
|
||||
@@ -386,11 +323,9 @@ std::string key_to_string(const Key& key) {
|
||||
// indexing
|
||||
template <typename Key>
|
||||
inline const Node Node::operator[](const Key& key) const {
|
||||
if (!m_isValid)
|
||||
throw InvalidNode(m_invalidKey);
|
||||
EnsureNodeExists();
|
||||
detail::node* value = static_cast<const detail::node&>(*m_pNode).get(
|
||||
detail::to_value(key), m_pMemory);
|
||||
detail::node* value =
|
||||
static_cast<const detail::node&>(*m_pNode).get(key, m_pMemory);
|
||||
if (!value) {
|
||||
return Node(ZombieNode, key_to_string(key));
|
||||
}
|
||||
@@ -399,24 +334,18 @@ inline const Node Node::operator[](const Key& key) const {
|
||||
|
||||
template <typename Key>
|
||||
inline Node Node::operator[](const Key& key) {
|
||||
if (!m_isValid)
|
||||
throw InvalidNode(m_invalidKey);
|
||||
EnsureNodeExists();
|
||||
detail::node& value = m_pNode->get(detail::to_value(key), m_pMemory);
|
||||
detail::node& value = m_pNode->get(key, m_pMemory);
|
||||
return Node(value, m_pMemory);
|
||||
}
|
||||
|
||||
template <typename Key>
|
||||
inline bool Node::remove(const Key& key) {
|
||||
if (!m_isValid)
|
||||
throw InvalidNode(m_invalidKey);
|
||||
EnsureNodeExists();
|
||||
return m_pNode->remove(detail::to_value(key), m_pMemory);
|
||||
return m_pNode->remove(key, m_pMemory);
|
||||
}
|
||||
|
||||
inline const Node Node::operator[](const Node& key) const {
|
||||
if (!m_isValid || !key.m_isValid)
|
||||
throw InvalidNode(m_invalidKey);
|
||||
EnsureNodeExists();
|
||||
key.EnsureNodeExists();
|
||||
m_pMemory->merge(*key.m_pMemory);
|
||||
@@ -429,8 +358,6 @@ inline const Node Node::operator[](const Node& key) const {
|
||||
}
|
||||
|
||||
inline Node Node::operator[](const Node& key) {
|
||||
if (!m_isValid || !key.m_isValid)
|
||||
throw InvalidNode(m_invalidKey);
|
||||
EnsureNodeExists();
|
||||
key.EnsureNodeExists();
|
||||
m_pMemory->merge(*key.m_pMemory);
|
||||
@@ -439,8 +366,6 @@ inline Node Node::operator[](const Node& key) {
|
||||
}
|
||||
|
||||
inline bool Node::remove(const Node& key) {
|
||||
if (!m_isValid || !key.m_isValid)
|
||||
throw InvalidNode(m_invalidKey);
|
||||
EnsureNodeExists();
|
||||
key.EnsureNodeExists();
|
||||
return m_pNode->remove(*key.m_pNode, m_pMemory);
|
||||
@@ -449,11 +374,8 @@ inline bool Node::remove(const Node& key) {
|
||||
// map
|
||||
template <typename Key, typename Value>
|
||||
inline void Node::force_insert(const Key& key, const Value& value) {
|
||||
if (!m_isValid)
|
||||
throw InvalidNode(m_invalidKey);
|
||||
EnsureNodeExists();
|
||||
m_pNode->force_insert(detail::to_value(key), detail::to_value(value),
|
||||
m_pMemory);
|
||||
m_pNode->force_insert(key, value, m_pMemory);
|
||||
}
|
||||
|
||||
// free functions
|
||||
|
@@ -18,7 +18,7 @@
|
||||
namespace YAML {
|
||||
namespace detail {
|
||||
struct iterator_value : public Node, std::pair<Node, Node> {
|
||||
iterator_value() {}
|
||||
iterator_value() = default;
|
||||
explicit iterator_value(const Node& rhs)
|
||||
: Node(rhs),
|
||||
std::pair<Node, Node>(Node(Node::ZombieNode), Node(Node::ZombieNode)) {}
|
||||
|
@@ -13,7 +13,6 @@
|
||||
#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"
|
||||
@@ -39,8 +38,8 @@ class YAML_CPP_API Node {
|
||||
template <typename T, typename S>
|
||||
friend struct as_if;
|
||||
|
||||
typedef YAML::iterator iterator;
|
||||
typedef YAML::const_iterator const_iterator;
|
||||
using iterator = YAML::iterator;
|
||||
using const_iterator = YAML::const_iterator;
|
||||
|
||||
Node();
|
||||
explicit Node(NodeType::value type);
|
||||
@@ -59,7 +58,7 @@ class YAML_CPP_API Node {
|
||||
bool IsMap() const { return Type() == NodeType::Map; }
|
||||
|
||||
// bool conversions
|
||||
YAML_CPP_OPERATOR_BOOL()
|
||||
explicit operator bool() const { return IsDefined(); }
|
||||
bool operator!() const { return !IsDefined(); }
|
||||
|
||||
// access
|
||||
|
@@ -18,11 +18,11 @@ class node_data;
|
||||
class memory;
|
||||
class memory_holder;
|
||||
|
||||
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;
|
||||
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>;
|
||||
}
|
||||
}
|
||||
|
||||
|
18
include/yaml-cpp/noexcept.h
Normal file
18
include/yaml-cpp/noexcept.h
Normal file
@@ -0,0 +1,18 @@
|
||||
#ifndef NOEXCEPT_H_768872DA_476C_11EA_88B8_90B11C0C0FF8
|
||||
#define NOEXCEPT_H_768872DA_476C_11EA_88B8_90B11C0C0FF8
|
||||
|
||||
#if defined(_MSC_VER) || \
|
||||
(defined(__GNUC__) && (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || \
|
||||
(__GNUC__ >= 4)) // GCC supports "pragma once" correctly since 3.4
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
// This is here for compatibility with older versions of Visual Studio
|
||||
// which don't support noexcept.
|
||||
#if defined(_MSC_VER) && _MSC_VER < 1900
|
||||
#define YAML_CPP_NOEXCEPT _NOEXCEPT
|
||||
#else
|
||||
#define YAML_CPP_NOEXCEPT noexcept
|
||||
#endif
|
||||
|
||||
#endif
|
@@ -16,8 +16,8 @@ namespace YAML {
|
||||
template <typename Seq>
|
||||
inline Emitter& EmitSeq(Emitter& emitter, const Seq& seq) {
|
||||
emitter << BeginSeq;
|
||||
for (typename Seq::const_iterator it = seq.begin(); it != seq.end(); ++it)
|
||||
emitter << *it;
|
||||
for (const auto& v : seq)
|
||||
emitter << v;
|
||||
emitter << EndSeq;
|
||||
return emitter;
|
||||
}
|
||||
@@ -39,10 +39,9 @@ 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 (typename map::const_iterator it = m.begin(); it != m.end(); ++it)
|
||||
emitter << Key << it->first << Value << it->second;
|
||||
for (const auto& v : m)
|
||||
emitter << Key << v.first << Value << v.second;
|
||||
emitter << EndMap;
|
||||
return emitter;
|
||||
}
|
||||
|
@@ -84,7 +84,7 @@ struct is_numeric<long double> {
|
||||
|
||||
template <bool, class T = void>
|
||||
struct enable_if_c {
|
||||
typedef T type;
|
||||
using type = T;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
@@ -95,7 +95,7 @@ struct enable_if : public enable_if_c<Cond::value, T> {};
|
||||
|
||||
template <bool, class T = void>
|
||||
struct disable_if_c {
|
||||
typedef T type;
|
||||
using type = T;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
|
@@ -66,7 +66,7 @@ static const unsigned char decoding[] = {
|
||||
};
|
||||
|
||||
std::vector<unsigned char> DecodeBase64(const std::string &input) {
|
||||
typedef std::vector<unsigned char> ret_type;
|
||||
using ret_type = std::vector<unsigned char>;
|
||||
if (input.empty())
|
||||
return ret_type();
|
||||
|
||||
@@ -97,4 +97,4 @@ std::vector<unsigned char> DecodeBase64(const std::string &input) {
|
||||
ret.resize(out - &ret[0]);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
} // namespace YAML
|
||||
|
@@ -10,8 +10,7 @@ void* BuildGraphOfNextDocument(Parser& parser,
|
||||
GraphBuilderAdapter eventHandler(graphBuilder);
|
||||
if (parser.HandleNextDocument(eventHandler)) {
|
||||
return eventHandler.RootNode();
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
} // namespace YAML
|
||||
|
@@ -91,4 +91,4 @@ void GraphBuilderAdapter::DispositionNode(void *pNode) {
|
||||
m_builder.AppendToSequence(pContainer, pNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace YAML
|
||||
|
@@ -16,11 +16,7 @@ std::string tolower(const std::string& str) {
|
||||
|
||||
template <typename T>
|
||||
bool IsEntirely(const std::string& str, T func) {
|
||||
for (std::size_t i = 0; i < str.size(); i++)
|
||||
if (!func(str[i]))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
return std::all_of(str.begin(), str.end(), [=](char ch) { return func(ch); });
|
||||
}
|
||||
|
||||
// IsFlexibleCase
|
||||
@@ -39,7 +35,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) {
|
||||
@@ -52,19 +48,22 @@ 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 (unsigned i = 0; i < sizeof(names) / sizeof(names[0]); i++) {
|
||||
if (names[i].truename == tolower(node.Scalar())) {
|
||||
for (const auto& name : names) {
|
||||
if (name.truename == tolower(node.Scalar())) {
|
||||
rhs = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (names[i].falsename == tolower(node.Scalar())) {
|
||||
if (name.falsename == tolower(node.Scalar())) {
|
||||
rhs = false;
|
||||
return true;
|
||||
}
|
||||
@@ -72,4 +71,4 @@ bool convert<bool>::decode(const Node& node, bool& rhs) {
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} // namespace YAML
|
||||
|
9
src/depthguard.cpp
Normal file
9
src/depthguard.cpp
Normal file
@@ -0,0 +1,9 @@
|
||||
#include "yaml-cpp/depthguard.h"
|
||||
|
||||
namespace YAML {
|
||||
|
||||
DeepRecursion::DeepRecursion(int depth, const Mark& mark_,
|
||||
const std::string& msg_)
|
||||
: ParserException(mark_, msg_), m_depth(depth) {}
|
||||
|
||||
} // namespace YAML
|
@@ -5,7 +5,7 @@ Directives::Directives() : version{true, 1, 2}, tags{} {}
|
||||
|
||||
const std::string Directives::TranslateTagHandle(
|
||||
const std::string& handle) const {
|
||||
std::map<std::string, std::string>::const_iterator it = tags.find(handle);
|
||||
auto it = tags.find(handle);
|
||||
if (it == tags.end()) {
|
||||
if (handle == "!!")
|
||||
return "tag:yaml.org,2002:";
|
||||
|
@@ -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) {
|
||||
|
@@ -59,6 +59,8 @@ 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);
|
||||
}
|
||||
@@ -83,6 +85,8 @@ 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);
|
||||
}
|
||||
|
@@ -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() {}
|
||||
Emitter::~Emitter() = default;
|
||||
|
||||
const char* Emitter::c_str() const { return m_stream.str(); }
|
||||
|
||||
@@ -49,6 +49,10 @@ 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);
|
||||
}
|
||||
@@ -86,6 +90,10 @@ bool Emitter::SetDoublePrecision(std::size_t n) {
|
||||
return m_pState->SetDoublePrecision(n, 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) {
|
||||
@@ -197,6 +205,7 @@ void Emitter::EmitBeginSeq() {
|
||||
void Emitter::EmitEndSeq() {
|
||||
if (!good())
|
||||
return;
|
||||
FlowType::value originalType = m_pState->CurGroupFlowType();
|
||||
|
||||
if (m_pState->CurGroupChildCount() == 0)
|
||||
m_pState->ForceFlow();
|
||||
@@ -205,8 +214,12 @@ void Emitter::EmitEndSeq() {
|
||||
if (m_stream.comment())
|
||||
m_stream << "\n";
|
||||
m_stream << IndentTo(m_pState->CurIndent());
|
||||
if (m_pState->CurGroupChildCount() == 0)
|
||||
if (originalType == FlowType::Block) {
|
||||
m_stream << "[";
|
||||
} else {
|
||||
if (m_pState->CurGroupChildCount() == 0 && !m_pState->HasBegunNode())
|
||||
m_stream << "[";
|
||||
}
|
||||
m_stream << "]";
|
||||
}
|
||||
|
||||
@@ -227,6 +240,7 @@ void Emitter::EmitBeginMap() {
|
||||
void Emitter::EmitEndMap() {
|
||||
if (!good())
|
||||
return;
|
||||
FlowType::value originalType = m_pState->CurGroupFlowType();
|
||||
|
||||
if (m_pState->CurGroupChildCount() == 0)
|
||||
m_pState->ForceFlow();
|
||||
@@ -235,8 +249,12 @@ void Emitter::EmitEndMap() {
|
||||
if (m_stream.comment())
|
||||
m_stream << "\n";
|
||||
m_stream << IndentTo(m_pState->CurIndent());
|
||||
if (m_pState->CurGroupChildCount() == 0)
|
||||
if (originalType == FlowType::Block) {
|
||||
m_stream << "{";
|
||||
} else {
|
||||
if (m_pState->CurGroupChildCount() == 0 && !m_pState->HasBegunNode())
|
||||
m_stream << "{";
|
||||
}
|
||||
m_stream << "}";
|
||||
}
|
||||
|
||||
@@ -486,6 +504,9 @@ 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 << ":";
|
||||
}
|
||||
|
||||
@@ -556,6 +577,8 @@ void Emitter::BlockMapPrepareLongKey(EmitterNodeType::value child) {
|
||||
break;
|
||||
case EmitterNodeType::BlockSeq:
|
||||
case EmitterNodeType::BlockMap:
|
||||
if (m_pState->HasBegunContent())
|
||||
m_stream << "\n";
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -579,8 +602,12 @@ 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;
|
||||
}
|
||||
@@ -619,6 +646,9 @@ 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 << ":";
|
||||
}
|
||||
|
||||
@@ -672,16 +702,29 @@ 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 std::string& str) {
|
||||
if (!good())
|
||||
return *this;
|
||||
|
||||
const bool escapeNonAscii = m_pState->GetOutputCharset() == EscapeNonAscii;
|
||||
StringEscaping::value stringEscaping = GetStringEscapingStyle(m_pState->GetOutputCharset());
|
||||
|
||||
const StringFormat::value strFormat =
|
||||
Utils::ComputeStringFormat(str, m_pState->GetStringFormat(),
|
||||
m_pState->CurGroupFlowType(), escapeNonAscii);
|
||||
m_pState->CurGroupFlowType(), stringEscaping == StringEscaping::NonAscii);
|
||||
|
||||
if (strFormat == StringFormat::Literal)
|
||||
if (strFormat == StringFormat::Literal || str.size() > 1024)
|
||||
m_pState->SetMapKeyFormat(YAML::LongKey, FmtScope::Local);
|
||||
|
||||
PrepareNode(EmitterNodeType::Scalar);
|
||||
@@ -694,7 +737,7 @@ Emitter& Emitter::Write(const std::string& str) {
|
||||
Utils::WriteSingleQuotedString(m_stream, str);
|
||||
break;
|
||||
case StringFormat::DoubleQuoted:
|
||||
Utils::WriteDoubleQuotedString(m_stream, str, escapeNonAscii);
|
||||
Utils::WriteDoubleQuotedString(m_stream, str, stringEscaping);
|
||||
break;
|
||||
case StringFormat::Literal:
|
||||
Utils::WriteLiteralString(m_stream, str,
|
||||
@@ -764,6 +807,21 @@ 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;
|
||||
@@ -785,8 +843,10 @@ Emitter& Emitter::Write(char ch) {
|
||||
if (!good())
|
||||
return *this;
|
||||
|
||||
|
||||
|
||||
PrepareNode(EmitterNodeType::Scalar);
|
||||
Utils::WriteChar(m_stream, ch);
|
||||
Utils::WriteChar(m_stream, ch, GetStringEscapingStyle(m_pState->GetOutputCharset()));
|
||||
StartedScalar();
|
||||
|
||||
return *this;
|
||||
@@ -810,6 +870,8 @@ Emitter& Emitter::Write(const _Alias& alias) {
|
||||
|
||||
StartedScalar();
|
||||
|
||||
m_pState->SetAlias();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -887,7 +949,7 @@ Emitter& Emitter::Write(const _Null& /*null*/) {
|
||||
|
||||
PrepareNode(EmitterNodeType::Scalar);
|
||||
|
||||
m_stream << "~";
|
||||
m_stream << ComputeNullName();
|
||||
|
||||
StartedScalar();
|
||||
|
||||
|
@@ -13,6 +13,7 @@ EmitterState::EmitterState()
|
||||
m_boolFmt(TrueFalseBool),
|
||||
m_boolLengthFmt(LongBool),
|
||||
m_boolCaseFmt(LowerCase),
|
||||
m_nullFmt(TildeNull),
|
||||
m_intFmt(Dec),
|
||||
m_indent(2),
|
||||
m_preCommentIndent(2),
|
||||
@@ -28,11 +29,12 @@ EmitterState::EmitterState()
|
||||
m_groups{},
|
||||
m_curIndent(0),
|
||||
m_hasAnchor(false),
|
||||
m_hasAlias(false),
|
||||
m_hasTag(false),
|
||||
m_hasNonContent(false),
|
||||
m_docCount(0) {}
|
||||
|
||||
EmitterState::~EmitterState() {}
|
||||
EmitterState::~EmitterState() = default;
|
||||
|
||||
// SetLocalValue
|
||||
// . We blindly tries to set all possible formatters to this value
|
||||
@@ -43,6 +45,7 @@ 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);
|
||||
@@ -51,6 +54,8 @@ 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; }
|
||||
@@ -85,6 +90,7 @@ void EmitterState::StartedNode() {
|
||||
}
|
||||
|
||||
m_hasAnchor = false;
|
||||
m_hasAlias = false;
|
||||
m_hasTag = false;
|
||||
m_hasNonContent = false;
|
||||
}
|
||||
@@ -94,15 +100,13 @@ EmitterNodeType::value EmitterState::NextGroupType(
|
||||
if (type == GroupType::Seq) {
|
||||
if (GetFlowType(type) == Block)
|
||||
return EmitterNodeType::BlockSeq;
|
||||
else
|
||||
return EmitterNodeType::FlowSeq;
|
||||
} else {
|
||||
if (GetFlowType(type) == Block)
|
||||
return EmitterNodeType::BlockMap;
|
||||
else
|
||||
return EmitterNodeType::FlowMap;
|
||||
return EmitterNodeType::FlowSeq;
|
||||
}
|
||||
|
||||
if (GetFlowType(type) == Block)
|
||||
return EmitterNodeType::BlockMap;
|
||||
return EmitterNodeType::FlowMap;
|
||||
|
||||
// can't happen
|
||||
assert(false);
|
||||
return EmitterNodeType::NoType;
|
||||
@@ -156,9 +160,15 @@ 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
|
||||
@@ -180,6 +190,9 @@ void EmitterState::EndedGroup(GroupType::value type) {
|
||||
m_globalModifiedSettings.restore();
|
||||
|
||||
ClearModifiedSettings();
|
||||
m_hasAnchor = false;
|
||||
m_hasTag = false;
|
||||
m_hasNonContent = false;
|
||||
}
|
||||
|
||||
EmitterNodeType::value EmitterState::CurGroupNodeType() const {
|
||||
@@ -220,11 +233,16 @@ 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:
|
||||
@@ -282,6 +300,19 @@ bool EmitterState::SetBoolCaseFormat(EMITTER_MANIP value,
|
||||
}
|
||||
}
|
||||
|
||||
bool EmitterState::SetNullFormat(EMITTER_MANIP value, FmtScope::value scope) {
|
||||
switch (value) {
|
||||
case LowerNull:
|
||||
case UpperNull:
|
||||
case CamelNull:
|
||||
case TildeNull:
|
||||
_Set(m_nullFmt, value, scope);
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool EmitterState::SetIntFormat(EMITTER_MANIP value, FmtScope::value scope) {
|
||||
switch (value) {
|
||||
case Dec:
|
||||
|
@@ -43,6 +43,7 @@ class EmitterState {
|
||||
|
||||
// node handling
|
||||
void SetAnchor();
|
||||
void SetAlias();
|
||||
void SetTag();
|
||||
void SetNonContent();
|
||||
void SetLongKey();
|
||||
@@ -65,6 +66,7 @@ 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;
|
||||
@@ -72,6 +74,7 @@ class EmitterState {
|
||||
bool HasBegunContent() const { return m_hasAnchor || m_hasTag; }
|
||||
|
||||
void ClearModifiedSettings();
|
||||
void RestoreGlobalModifiedSettings();
|
||||
|
||||
// formatters
|
||||
void SetLocalValue(EMITTER_MANIP value);
|
||||
@@ -91,6 +94,9 @@ 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(); }
|
||||
|
||||
@@ -131,6 +137,7 @@ 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;
|
||||
@@ -182,6 +189,7 @@ 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;
|
||||
|
@@ -1,3 +1,4 @@
|
||||
#include <algorithm>
|
||||
#include <iomanip>
|
||||
#include <sstream>
|
||||
|
||||
@@ -199,15 +200,10 @@ bool IsValidPlainScalar(const std::string& str, FlowType::value flowType,
|
||||
|
||||
bool IsValidSingleQuotedScalar(const std::string& str, bool escapeNonAscii) {
|
||||
// TODO: check for non-printable characters?
|
||||
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;
|
||||
return std::none_of(str.begin(), str.end(), [=](char ch) {
|
||||
return (escapeNonAscii && (0x80 <= static_cast<unsigned char>(ch))) ||
|
||||
(ch == '\n');
|
||||
});
|
||||
}
|
||||
|
||||
bool IsValidLiteralScalar(const std::string& str, FlowType::value flowType,
|
||||
@@ -217,28 +213,39 @@ bool IsValidLiteralScalar(const std::string& str, FlowType::value flowType,
|
||||
}
|
||||
|
||||
// TODO: check for non-printable characters?
|
||||
for (std::size_t i = 0; i < str.size(); i++) {
|
||||
if (escapeNonAscii && (0x80 <= static_cast<unsigned char>(str[i]))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
return std::none_of(str.begin(), str.end(), [=](char ch) {
|
||||
return (escapeNonAscii && (0x80 <= static_cast<unsigned char>(ch)));
|
||||
});
|
||||
}
|
||||
|
||||
void WriteDoubleQuoteEscapeSequence(ostream_wrapper& out, int codePoint) {
|
||||
std::pair<uint16_t, uint16_t> EncodeUTF16SurrogatePair(int codePoint) {
|
||||
const uint32_t leadOffset = 0xD800 - (0x10000 >> 10);
|
||||
|
||||
return {
|
||||
leadOffset | (codePoint >> 10),
|
||||
0xDC00 | (codePoint & 0x3FF),
|
||||
};
|
||||
}
|
||||
|
||||
void WriteDoubleQuoteEscapeSequence(ostream_wrapper& out, int codePoint, StringEscaping::value stringEscapingStyle) {
|
||||
static const char hexDigits[] = "0123456789abcdef";
|
||||
|
||||
out << "\\";
|
||||
int digits = 8;
|
||||
if (codePoint < 0xFF) {
|
||||
if (codePoint < 0xFF && stringEscapingStyle != StringEscaping::JSON) {
|
||||
out << "x";
|
||||
digits = 2;
|
||||
} else if (codePoint < 0xFFFF) {
|
||||
out << "u";
|
||||
digits = 4;
|
||||
} else {
|
||||
} else if (stringEscapingStyle != StringEscaping::JSON) {
|
||||
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
|
||||
@@ -310,7 +317,7 @@ bool WriteSingleQuotedString(ostream_wrapper& out, const std::string& str) {
|
||||
}
|
||||
|
||||
bool WriteDoubleQuotedString(ostream_wrapper& out, const std::string& str,
|
||||
bool escapeNonAscii) {
|
||||
StringEscaping::value stringEscaping) {
|
||||
out << "\"";
|
||||
int codePoint;
|
||||
for (std::string::const_iterator i = str.begin();
|
||||
@@ -334,16 +341,19 @@ bool WriteDoubleQuotedString(ostream_wrapper& out, const std::string& str,
|
||||
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);
|
||||
WriteDoubleQuoteEscapeSequence(out, codePoint, stringEscaping);
|
||||
} else if (codePoint == 0xFEFF) { // Byte order marks (ZWNS) should be
|
||||
// escaped (YAML 1.2, sec. 5.2)
|
||||
WriteDoubleQuoteEscapeSequence(out, codePoint);
|
||||
} else if (escapeNonAscii && codePoint > 0x7E) {
|
||||
WriteDoubleQuoteEscapeSequence(out, codePoint);
|
||||
WriteDoubleQuoteEscapeSequence(out, codePoint, stringEscaping);
|
||||
} else if (stringEscaping == StringEscaping::NonAscii && codePoint > 0x7E) {
|
||||
WriteDoubleQuoteEscapeSequence(out, codePoint, stringEscaping);
|
||||
} else {
|
||||
WriteCodePoint(out, codePoint);
|
||||
}
|
||||
@@ -356,37 +366,41 @@ bool WriteDoubleQuotedString(ostream_wrapper& out, const std::string& str,
|
||||
bool WriteLiteralString(ostream_wrapper& out, const std::string& str,
|
||||
std::size_t indent) {
|
||||
out << "|\n";
|
||||
out << IndentTo(indent);
|
||||
int codePoint;
|
||||
for (std::string::const_iterator i = str.begin();
|
||||
GetNextCodePointAndAdvance(codePoint, i, str.end());) {
|
||||
if (codePoint == '\n') {
|
||||
out << "\n" << IndentTo(indent);
|
||||
out << "\n";
|
||||
} else {
|
||||
out<< IndentTo(indent);
|
||||
WriteCodePoint(out, codePoint);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WriteChar(ostream_wrapper& out, char ch) {
|
||||
bool WriteChar(ostream_wrapper& out, char ch, StringEscaping::value stringEscapingStyle) {
|
||||
if (('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z')) {
|
||||
out << ch;
|
||||
} else if (ch == '\"') {
|
||||
out << "\"\\\"\"";
|
||||
out << R"("\"")";
|
||||
} else if (ch == '\t') {
|
||||
out << "\"\\t\"";
|
||||
out << R"("\t")";
|
||||
} else if (ch == '\n') {
|
||||
out << "\"\\n\"";
|
||||
out << R"("\n")";
|
||||
} else if (ch == '\b') {
|
||||
out << "\"\\b\"";
|
||||
out << R"("\b")";
|
||||
} else if (ch == '\r') {
|
||||
out << R"("\r")";
|
||||
} else if (ch == '\f') {
|
||||
out << R"("\f")";
|
||||
} else if (ch == '\\') {
|
||||
out << "\"\\\\\"";
|
||||
out << R"("\\")";
|
||||
} else if (0x20 <= ch && ch <= 0x7e) {
|
||||
out << "\"" << ch << "\"";
|
||||
} else {
|
||||
out << "\"";
|
||||
WriteDoubleQuoteEscapeSequence(out, ch);
|
||||
WriteDoubleQuoteEscapeSequence(out, ch, stringEscapingStyle);
|
||||
out << "\"";
|
||||
}
|
||||
return true;
|
||||
@@ -476,7 +490,7 @@ bool WriteTagWithPrefix(ostream_wrapper& out, const std::string& prefix,
|
||||
|
||||
bool WriteBinary(ostream_wrapper& out, const Binary& binary) {
|
||||
WriteDoubleQuotedString(out, EncodeBase64(binary.data(), binary.size()),
|
||||
false);
|
||||
StringEscaping::None);
|
||||
return true;
|
||||
}
|
||||
} // namespace Utils
|
||||
|
@@ -24,6 +24,10 @@ struct StringFormat {
|
||||
enum value { Plain, SingleQuoted, DoubleQuoted, Literal };
|
||||
};
|
||||
|
||||
struct StringEscaping {
|
||||
enum value { None, NonAscii, JSON };
|
||||
};
|
||||
|
||||
namespace Utils {
|
||||
StringFormat::value ComputeStringFormat(const std::string& str,
|
||||
EMITTER_MANIP strFormat,
|
||||
@@ -32,10 +36,11 @@ StringFormat::value ComputeStringFormat(const std::string& str,
|
||||
|
||||
bool WriteSingleQuotedString(ostream_wrapper& out, const std::string& str);
|
||||
bool WriteDoubleQuotedString(ostream_wrapper& out, const std::string& str,
|
||||
bool escapeNonAscii);
|
||||
StringEscaping::value stringEscaping);
|
||||
bool WriteLiteralString(ostream_wrapper& out, const std::string& str,
|
||||
std::size_t indent);
|
||||
bool WriteChar(ostream_wrapper& out, char ch);
|
||||
bool WriteChar(ostream_wrapper& out, char ch,
|
||||
StringEscaping::value stringEscapingStyle);
|
||||
bool WriteComment(ostream_wrapper& out, const std::string& str,
|
||||
std::size_t postCommentIndent);
|
||||
bool WriteAlias(ostream_wrapper& out, const std::string& str);
|
||||
|
@@ -1,31 +1,20 @@
|
||||
#include "yaml-cpp/exceptions.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
|
||||
#include "yaml-cpp/noexcept.h"
|
||||
|
||||
namespace YAML {
|
||||
|
||||
// These destructors are defined out-of-line so the vtable is only emitted once.
|
||||
Exception::~Exception() YAML_CPP_NOEXCEPT {}
|
||||
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
|
||||
|
||||
|
||||
Exception::~Exception() YAML_CPP_NOEXCEPT = default;
|
||||
ParserException::~ParserException() YAML_CPP_NOEXCEPT = default;
|
||||
RepresentationException::~RepresentationException() YAML_CPP_NOEXCEPT = default;
|
||||
InvalidScalar::~InvalidScalar() YAML_CPP_NOEXCEPT = default;
|
||||
KeyNotFound::~KeyNotFound() YAML_CPP_NOEXCEPT = default;
|
||||
InvalidNode::~InvalidNode() YAML_CPP_NOEXCEPT = default;
|
||||
BadConversion::~BadConversion() YAML_CPP_NOEXCEPT = default;
|
||||
BadDereference::~BadDereference() YAML_CPP_NOEXCEPT = default;
|
||||
BadSubscript::~BadSubscript() YAML_CPP_NOEXCEPT = default;
|
||||
BadPushback::~BadPushback() YAML_CPP_NOEXCEPT = default;
|
||||
BadInsert::~BadInsert() YAML_CPP_NOEXCEPT = default;
|
||||
EmitterException::~EmitterException() YAML_CPP_NOEXCEPT = default;
|
||||
BadFile::~BadFile() YAML_CPP_NOEXCEPT = default;
|
||||
} // namespace YAML
|
||||
|
21
src/exp.cpp
21
src/exp.cpp
@@ -12,8 +12,7 @@ namespace YAML {
|
||||
namespace Exp {
|
||||
unsigned ParseHex(const std::string& str, const Mark& mark) {
|
||||
unsigned value = 0;
|
||||
for (std::size_t i = 0; i < str.size(); i++) {
|
||||
char ch = str[i];
|
||||
for (char ch : str) {
|
||||
int digit = 0;
|
||||
if ('a' <= ch && ch <= 'f')
|
||||
digit = ch - 'a' + 10;
|
||||
@@ -55,14 +54,16 @@ std::string Escape(Stream& in, int codeLength) {
|
||||
// now break it up into chars
|
||||
if (value <= 0x7F)
|
||||
return Str(value);
|
||||
else if (value <= 0x7FF)
|
||||
|
||||
if (value <= 0x7FF)
|
||||
return Str(0xC0 + (value >> 6)) + Str(0x80 + (value & 0x3F));
|
||||
else if (value <= 0xFFFF)
|
||||
|
||||
if (value <= 0xFFFF)
|
||||
return Str(0xE0 + (value >> 12)) + Str(0x80 + ((value >> 6) & 0x3F)) +
|
||||
Str(0x80 + (value & 0x3F));
|
||||
else
|
||||
return Str(0xF0 + (value >> 18)) + Str(0x80 + ((value >> 12) & 0x3F)) +
|
||||
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));
|
||||
}
|
||||
|
||||
// Escape
|
||||
@@ -104,7 +105,7 @@ std::string Escape(Stream& in) {
|
||||
case 'e':
|
||||
return "\x1B";
|
||||
case ' ':
|
||||
return "\x20";
|
||||
return R"( )";
|
||||
case '\"':
|
||||
return "\"";
|
||||
case '\'':
|
||||
@@ -132,5 +133,5 @@ std::string Escape(Stream& in) {
|
||||
std::stringstream msg;
|
||||
throw ParserException(in.mark(), std::string(ErrorMsg::INVALID_ESCAPE) + ch);
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace Exp
|
||||
} // namespace YAML
|
||||
|
@@ -110,7 +110,7 @@ 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() {
|
||||
@@ -155,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_OR) + (Blank() | RegEx())));
|
||||
return e;
|
||||
}
|
||||
inline const RegEx& EndScalar() {
|
||||
|
@@ -22,5 +22,5 @@ node& memory::create_node() {
|
||||
void memory::merge(const memory& rhs) {
|
||||
m_nodes.insert(rhs.m_nodes.begin(), rhs.m_nodes.end());
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace detail
|
||||
} // namespace YAML
|
||||
|
@@ -9,4 +9,4 @@ Node Clone(const Node& node) {
|
||||
events.Emit(builder);
|
||||
return builder.Root();
|
||||
}
|
||||
}
|
||||
} // namespace YAML
|
||||
|
@@ -1,4 +1,5 @@
|
||||
#include <assert.h>
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <iterator>
|
||||
#include <sstream>
|
||||
|
||||
@@ -12,6 +13,7 @@
|
||||
|
||||
namespace YAML {
|
||||
namespace detail {
|
||||
std::atomic<size_t> node::m_amount{0};
|
||||
|
||||
const std::string& node_data::empty_scalar() {
|
||||
static const std::string svalue;
|
||||
@@ -108,9 +110,9 @@ void node_data::compute_seq_size() const {
|
||||
}
|
||||
|
||||
void node_data::compute_map_size() const {
|
||||
kv_pairs::iterator it = m_undefinedPairs.begin();
|
||||
auto it = m_undefinedPairs.begin();
|
||||
while (it != m_undefinedPairs.end()) {
|
||||
kv_pairs::iterator jt = std::next(it);
|
||||
auto jt = std::next(it);
|
||||
if (it->first->is_defined() && it->second->is_defined())
|
||||
m_undefinedPairs.erase(it);
|
||||
it = jt;
|
||||
@@ -119,7 +121,7 @@ void node_data::compute_map_size() const {
|
||||
|
||||
const_node_iterator node_data::begin() const {
|
||||
if (!m_isDefined)
|
||||
return const_node_iterator();
|
||||
return {};
|
||||
|
||||
switch (m_type) {
|
||||
case NodeType::Sequence:
|
||||
@@ -127,13 +129,13 @@ const_node_iterator node_data::begin() const {
|
||||
case NodeType::Map:
|
||||
return const_node_iterator(m_map.begin(), m_map.end());
|
||||
default:
|
||||
return const_node_iterator();
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
node_iterator node_data::begin() {
|
||||
if (!m_isDefined)
|
||||
return node_iterator();
|
||||
return {};
|
||||
|
||||
switch (m_type) {
|
||||
case NodeType::Sequence:
|
||||
@@ -141,13 +143,13 @@ node_iterator node_data::begin() {
|
||||
case NodeType::Map:
|
||||
return node_iterator(m_map.begin(), m_map.end());
|
||||
default:
|
||||
return node_iterator();
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
const_node_iterator node_data::end() const {
|
||||
if (!m_isDefined)
|
||||
return const_node_iterator();
|
||||
return {};
|
||||
|
||||
switch (m_type) {
|
||||
case NodeType::Sequence:
|
||||
@@ -155,13 +157,13 @@ const_node_iterator node_data::end() const {
|
||||
case NodeType::Map:
|
||||
return const_node_iterator(m_map.end(), m_map.end());
|
||||
default:
|
||||
return const_node_iterator();
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
node_iterator node_data::end() {
|
||||
if (!m_isDefined)
|
||||
return node_iterator();
|
||||
return {};
|
||||
|
||||
switch (m_type) {
|
||||
case NodeType::Sequence:
|
||||
@@ -169,12 +171,13 @@ node_iterator node_data::end() {
|
||||
case NodeType::Map:
|
||||
return node_iterator(m_map.end(), m_map.end());
|
||||
default:
|
||||
return node_iterator();
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
// sequence
|
||||
void node_data::push_back(node& node, shared_memory_holder /* pMemory */) {
|
||||
void node_data::push_back(node& node,
|
||||
const shared_memory_holder& /* pMemory */) {
|
||||
if (m_type == NodeType::Undefined || m_type == NodeType::Null) {
|
||||
m_type = NodeType::Sequence;
|
||||
reset_sequence();
|
||||
@@ -186,7 +189,8 @@ void node_data::push_back(node& node, shared_memory_holder /* pMemory */) {
|
||||
m_sequence.push_back(&node);
|
||||
}
|
||||
|
||||
void node_data::insert(node& key, node& value, shared_memory_holder pMemory) {
|
||||
void node_data::insert(node& key, node& value,
|
||||
const shared_memory_holder& pMemory) {
|
||||
switch (m_type) {
|
||||
case NodeType::Map:
|
||||
break;
|
||||
@@ -196,27 +200,28 @@ void node_data::insert(node& key, node& value, shared_memory_holder pMemory) {
|
||||
convert_to_map(pMemory);
|
||||
break;
|
||||
case NodeType::Scalar:
|
||||
throw BadSubscript(key);
|
||||
throw BadSubscript(m_mark, key);
|
||||
}
|
||||
|
||||
insert_map_pair(key, value);
|
||||
}
|
||||
|
||||
// indexing
|
||||
node* node_data::get(node& key, shared_memory_holder /* pMemory */) const {
|
||||
node* node_data::get(node& key,
|
||||
const shared_memory_holder& /* pMemory */) const {
|
||||
if (m_type != NodeType::Map) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
for (node_map::const_iterator it = m_map.begin(); it != m_map.end(); ++it) {
|
||||
if (it->first->is(key))
|
||||
return it->second;
|
||||
for (const auto& it : m_map) {
|
||||
if (it.first->is(key))
|
||||
return it.second;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
node& node_data::get(node& key, shared_memory_holder pMemory) {
|
||||
node& node_data::get(node& key, const shared_memory_holder& pMemory) {
|
||||
switch (m_type) {
|
||||
case NodeType::Map:
|
||||
break;
|
||||
@@ -226,12 +231,12 @@ node& node_data::get(node& key, shared_memory_holder pMemory) {
|
||||
convert_to_map(pMemory);
|
||||
break;
|
||||
case NodeType::Scalar:
|
||||
throw BadSubscript(key);
|
||||
throw BadSubscript(m_mark, key);
|
||||
}
|
||||
|
||||
for (node_map::const_iterator it = m_map.begin(); it != m_map.end(); ++it) {
|
||||
if (it->first->is(key))
|
||||
return *it->second;
|
||||
for (const auto& it : m_map) {
|
||||
if (it.first->is(key))
|
||||
return *it.second;
|
||||
}
|
||||
|
||||
node& value = pMemory->create_node();
|
||||
@@ -239,23 +244,26 @@ node& node_data::get(node& key, shared_memory_holder pMemory) {
|
||||
return value;
|
||||
}
|
||||
|
||||
bool node_data::remove(node& key, shared_memory_holder /* pMemory */) {
|
||||
bool node_data::remove(node& key, const shared_memory_holder& /* pMemory */) {
|
||||
if (m_type != NodeType::Map)
|
||||
return false;
|
||||
|
||||
for (kv_pairs::iterator it = m_undefinedPairs.begin();
|
||||
it != m_undefinedPairs.end();) {
|
||||
kv_pairs::iterator jt = std::next(it);
|
||||
for (auto it = m_undefinedPairs.begin(); it != m_undefinedPairs.end();) {
|
||||
auto jt = std::next(it);
|
||||
if (it->first->is(key))
|
||||
m_undefinedPairs.erase(it);
|
||||
it = jt;
|
||||
}
|
||||
|
||||
for (node_map::iterator it = m_map.begin(); it != m_map.end(); ++it) {
|
||||
if (it->first->is(key)) {
|
||||
m_map.erase(it);
|
||||
return true;
|
||||
}
|
||||
auto it =
|
||||
std::find_if(m_map.begin(), m_map.end(),
|
||||
[&](std::pair<YAML::detail::node*, YAML::detail::node*> j) {
|
||||
return (j.first->is(key));
|
||||
});
|
||||
|
||||
if (it != m_map.end()) {
|
||||
m_map.erase(it);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -278,7 +286,7 @@ void node_data::insert_map_pair(node& key, node& value) {
|
||||
m_undefinedPairs.emplace_back(&key, &value);
|
||||
}
|
||||
|
||||
void node_data::convert_to_map(shared_memory_holder pMemory) {
|
||||
void node_data::convert_to_map(const shared_memory_holder& pMemory) {
|
||||
switch (m_type) {
|
||||
case NodeType::Undefined:
|
||||
case NodeType::Null:
|
||||
@@ -296,7 +304,7 @@ void node_data::convert_to_map(shared_memory_holder pMemory) {
|
||||
}
|
||||
}
|
||||
|
||||
void node_data::convert_sequence_to_map(shared_memory_holder pMemory) {
|
||||
void node_data::convert_sequence_to_map(const shared_memory_holder& pMemory) {
|
||||
assert(m_type == NodeType::Sequence);
|
||||
|
||||
reset_map();
|
||||
|
@@ -1,4 +1,3 @@
|
||||
#include <assert.h>
|
||||
#include <cassert>
|
||||
|
||||
#include "nodebuilder.h"
|
||||
@@ -20,7 +19,7 @@ NodeBuilder::NodeBuilder()
|
||||
m_anchors.push_back(nullptr); // since the anchors start at 1
|
||||
}
|
||||
|
||||
NodeBuilder::~NodeBuilder() {}
|
||||
NodeBuilder::~NodeBuilder() = default;
|
||||
|
||||
Node NodeBuilder::Root() {
|
||||
if (!m_pRoot)
|
||||
@@ -93,7 +92,7 @@ void NodeBuilder::Push(detail::node& node) {
|
||||
|
||||
m_stack.push_back(&node);
|
||||
if (needsKey)
|
||||
m_keys.push_back(PushedKey(&node, false));
|
||||
m_keys.emplace_back(&node, false);
|
||||
}
|
||||
|
||||
void NodeBuilder::Pop() {
|
||||
|
@@ -31,25 +31,25 @@ class NodeBuilder : public EventHandler {
|
||||
NodeBuilder(NodeBuilder&&) = delete;
|
||||
NodeBuilder& operator=(const NodeBuilder&) = delete;
|
||||
NodeBuilder& operator=(NodeBuilder&&) = delete;
|
||||
virtual ~NodeBuilder();
|
||||
~NodeBuilder() override;
|
||||
|
||||
Node Root();
|
||||
|
||||
virtual void OnDocumentStart(const Mark& mark);
|
||||
virtual void OnDocumentEnd();
|
||||
void OnDocumentStart(const Mark& mark) override;
|
||||
void OnDocumentEnd() 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 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 OnSequenceStart(const Mark& mark, const std::string& tag,
|
||||
anchor_t anchor, EmitterStyle::value style);
|
||||
virtual void OnSequenceEnd();
|
||||
void OnSequenceStart(const Mark& mark, const std::string& tag,
|
||||
anchor_t anchor, EmitterStyle::value style) override;
|
||||
void OnSequenceEnd() override;
|
||||
|
||||
virtual void OnMapStart(const Mark& mark, const std::string& tag,
|
||||
anchor_t anchor, EmitterStyle::value style);
|
||||
virtual void OnMapEnd();
|
||||
void OnMapStart(const Mark& mark, const std::string& tag,
|
||||
anchor_t anchor, EmitterStyle::value style) override;
|
||||
void OnMapEnd() override;
|
||||
|
||||
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;
|
||||
|
||||
typedef std::vector<detail::node*> Nodes;
|
||||
using Nodes = std::vector<detail::node *>;
|
||||
Nodes m_stack;
|
||||
Nodes m_anchors;
|
||||
|
||||
typedef std::pair<detail::node*, bool> PushedKey;
|
||||
using PushedKey = std::pair<detail::node*, bool>;
|
||||
std::vector<PushedKey> m_keys;
|
||||
std::size_t m_mapDepth;
|
||||
};
|
||||
|
@@ -13,7 +13,7 @@ void NodeEvents::AliasManager::RegisterReference(const detail::node& node) {
|
||||
|
||||
anchor_t NodeEvents::AliasManager::LookupAnchor(
|
||||
const detail::node& node) const {
|
||||
AnchorByIdentity::const_iterator it = m_anchorByIdentity.find(node.ref());
|
||||
auto it = m_anchorByIdentity.find(node.ref());
|
||||
if (it == m_anchorByIdentity.end())
|
||||
return 0;
|
||||
return it->second;
|
||||
@@ -32,13 +32,12 @@ void NodeEvents::Setup(const detail::node& node) {
|
||||
return;
|
||||
|
||||
if (node.type() == NodeType::Sequence) {
|
||||
for (detail::const_node_iterator it = node.begin(); it != node.end(); ++it)
|
||||
Setup(**it);
|
||||
for (auto element : node)
|
||||
Setup(*element);
|
||||
} else if (node.type() == NodeType::Map) {
|
||||
for (detail::const_node_iterator it = node.begin(); it != node.end();
|
||||
++it) {
|
||||
Setup(*it->first);
|
||||
Setup(*it->second);
|
||||
for (auto element : node) {
|
||||
Setup(*element.first);
|
||||
Setup(*element.second);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -77,17 +76,15 @@ void NodeEvents::Emit(const detail::node& node, EventHandler& handler,
|
||||
break;
|
||||
case NodeType::Sequence:
|
||||
handler.OnSequenceStart(Mark(), node.tag(), anchor, node.style());
|
||||
for (detail::const_node_iterator it = node.begin(); it != node.end();
|
||||
++it)
|
||||
Emit(**it, handler, am);
|
||||
for (auto element : node)
|
||||
Emit(*element, handler, am);
|
||||
handler.OnSequenceEnd();
|
||||
break;
|
||||
case NodeType::Map:
|
||||
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);
|
||||
for (auto element : node) {
|
||||
Emit(*element.first, handler, am);
|
||||
Emit(*element.second, handler, am);
|
||||
}
|
||||
handler.OnMapEnd();
|
||||
break;
|
||||
@@ -95,7 +92,7 @@ void NodeEvents::Emit(const detail::node& node, EventHandler& handler,
|
||||
}
|
||||
|
||||
bool NodeEvents::IsAliased(const detail::node& node) const {
|
||||
RefCount::const_iterator it = m_refCount.find(node.ref());
|
||||
auto it = m_refCount.find(node.ref());
|
||||
return it != m_refCount.end() && it->second > 1;
|
||||
}
|
||||
} // namespace YAML
|
||||
|
@@ -45,7 +45,7 @@ class NodeEvents {
|
||||
anchor_t _CreateNewAnchor() { return ++m_curAnchor; }
|
||||
|
||||
private:
|
||||
typedef std::map<const detail::node_ref*, anchor_t> AnchorByIdentity;
|
||||
using AnchorByIdentity = std::map<const detail::node_ref*, anchor_t>;
|
||||
AnchorByIdentity m_anchorByIdentity;
|
||||
|
||||
anchor_t m_curAnchor;
|
||||
@@ -60,7 +60,7 @@ class NodeEvents {
|
||||
detail::shared_memory_holder m_pMemory;
|
||||
detail::node* m_root;
|
||||
|
||||
typedef std::map<const detail::node_ref*, int> RefCount;
|
||||
using RefCount = std::map<const detail::node_ref*, int>;
|
||||
RefCount m_refCount;
|
||||
};
|
||||
} // namespace YAML
|
||||
|
@@ -7,4 +7,4 @@ bool IsNullString(const std::string& str) {
|
||||
return str.empty() || str == "~" || str == "null" || str == "Null" ||
|
||||
str == "NULL";
|
||||
}
|
||||
}
|
||||
} // namespace YAML
|
||||
|
@@ -21,7 +21,7 @@ ostream_wrapper::ostream_wrapper(std::ostream& stream)
|
||||
m_col(0),
|
||||
m_comment(false) {}
|
||||
|
||||
ostream_wrapper::~ostream_wrapper() {}
|
||||
ostream_wrapper::~ostream_wrapper() = default;
|
||||
|
||||
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 (std::size_t i = 0; i < str.size(); i++) {
|
||||
update_pos(str[i]);
|
||||
for (char ch : str) {
|
||||
update_pos(ch);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -3,10 +3,10 @@
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
|
||||
#include "yaml-cpp/node/node.h"
|
||||
#include "yaml-cpp/node/impl.h"
|
||||
#include "yaml-cpp/parser.h"
|
||||
#include "nodebuilder.h"
|
||||
#include "yaml-cpp/node/impl.h"
|
||||
#include "yaml-cpp/node/node.h"
|
||||
#include "yaml-cpp/parser.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.c_str());
|
||||
std::ifstream fin(filename);
|
||||
if (!fin) {
|
||||
throw BadFile();
|
||||
throw BadFile(filename);
|
||||
}
|
||||
return Load(fin);
|
||||
}
|
||||
@@ -51,7 +51,7 @@ std::vector<Node> LoadAll(std::istream& input) {
|
||||
std::vector<Node> docs;
|
||||
|
||||
Parser parser(input);
|
||||
while (1) {
|
||||
while (true) {
|
||||
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.c_str());
|
||||
std::ifstream fin(filename);
|
||||
if (!fin) {
|
||||
throw BadFile();
|
||||
throw BadFile(filename);
|
||||
}
|
||||
return LoadAll(fin);
|
||||
}
|
||||
|
@@ -15,11 +15,9 @@ Parser::Parser() : m_pScanner{}, m_pDirectives{} {}
|
||||
|
||||
Parser::Parser(std::istream& in) : Parser() { Load(in); }
|
||||
|
||||
Parser::~Parser() {}
|
||||
Parser::~Parser() = default;
|
||||
|
||||
Parser::operator bool() const {
|
||||
return m_pScanner.get() && !m_pScanner->empty();
|
||||
}
|
||||
Parser::operator bool() const { return m_pScanner && !m_pScanner->empty(); }
|
||||
|
||||
void Parser::Load(std::istream& in) {
|
||||
m_pScanner.reset(new Scanner(in));
|
||||
@@ -27,7 +25,7 @@ void Parser::Load(std::istream& in) {
|
||||
}
|
||||
|
||||
bool Parser::HandleNextDocument(EventHandler& eventHandler) {
|
||||
if (!m_pScanner.get())
|
||||
if (!m_pScanner)
|
||||
return false;
|
||||
|
||||
ParseDirectives();
|
||||
@@ -43,11 +41,7 @@ bool Parser::HandleNextDocument(EventHandler& eventHandler) {
|
||||
void Parser::ParseDirectives() {
|
||||
bool readDirective = false;
|
||||
|
||||
while (1) {
|
||||
if (m_pScanner->empty()) {
|
||||
break;
|
||||
}
|
||||
|
||||
while (!m_pScanner->empty()) {
|
||||
Token& token = m_pScanner->peek();
|
||||
if (token.type != Token::DIRECTIVE) {
|
||||
break;
|
||||
@@ -113,15 +107,11 @@ void Parser::HandleTagDirective(const Token& token) {
|
||||
}
|
||||
|
||||
void Parser::PrintTokens(std::ostream& out) {
|
||||
if (!m_pScanner.get()) {
|
||||
if (!m_pScanner) {
|
||||
return;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
if (m_pScanner->empty()) {
|
||||
break;
|
||||
}
|
||||
|
||||
while (!m_pScanner->empty()) {
|
||||
out << m_pScanner->peek() << "\n";
|
||||
m_pScanner->pop();
|
||||
}
|
||||
|
@@ -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() {}
|
||||
~RegEx() = default;
|
||||
|
||||
friend YAML_CPP_API RegEx operator!(const RegEx& ex);
|
||||
friend YAML_CPP_API RegEx operator|(const RegEx& ex1, const RegEx& ex2);
|
||||
|
@@ -8,8 +8,8 @@
|
||||
#endif
|
||||
|
||||
#include "stream.h"
|
||||
#include "stringsource.h"
|
||||
#include "streamcharsource.h"
|
||||
#include "stringsource.h"
|
||||
|
||||
namespace YAML {
|
||||
// query matches
|
||||
@@ -106,9 +106,8 @@ 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
|
||||
@@ -130,8 +129,8 @@ inline int RegEx::MatchOpRange(const Source& source) const {
|
||||
// OrOperator
|
||||
template <typename Source>
|
||||
inline int RegEx::MatchOpOr(const Source& source) const {
|
||||
for (std::size_t i = 0; i < m_params.size(); i++) {
|
||||
int n = m_params[i].MatchUnchecked(source);
|
||||
for (const RegEx& param : m_params) {
|
||||
int n = param.MatchUnchecked(source);
|
||||
if (n >= 0)
|
||||
return n;
|
||||
}
|
||||
@@ -169,11 +168,11 @@ inline int RegEx::MatchOpNot(const Source& source) const {
|
||||
template <typename Source>
|
||||
inline int RegEx::MatchOpSeq(const Source& source) const {
|
||||
int offset = 0;
|
||||
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
|
||||
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
|
||||
if (n == -1)
|
||||
return -1;
|
||||
offset += n;
|
||||
@@ -181,6 +180,6 @@ inline int RegEx::MatchOpSeq(const Source& source) const {
|
||||
|
||||
return offset;
|
||||
}
|
||||
}
|
||||
} // namespace YAML
|
||||
|
||||
#endif // REGEXIMPL_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
|
@@ -19,7 +19,7 @@ Scanner::Scanner(std::istream& in)
|
||||
m_indentRefs{},
|
||||
m_flows{} {}
|
||||
|
||||
Scanner::~Scanner() {}
|
||||
Scanner::~Scanner() = default;
|
||||
|
||||
bool Scanner::empty() {
|
||||
EnsureTokensInQueue();
|
||||
@@ -51,7 +51,7 @@ Token& Scanner::peek() {
|
||||
Mark Scanner::mark() const { return INPUT.mark(); }
|
||||
|
||||
void Scanner::EnsureTokensInQueue() {
|
||||
while (1) {
|
||||
while (true) {
|
||||
if (!m_tokens.empty()) {
|
||||
Token& token = m_tokens.front();
|
||||
|
||||
@@ -88,7 +88,7 @@ void Scanner::ScanNextToken() {
|
||||
return StartStream();
|
||||
}
|
||||
|
||||
// get rid of whitespace, etc. (in between tokens it should be irrelevent)
|
||||
// get rid of whitespace, etc. (in between tokens it should be irrelevant)
|
||||
ScanToNextToken();
|
||||
|
||||
// maybe need to end some blocks
|
||||
@@ -174,7 +174,7 @@ void Scanner::ScanNextToken() {
|
||||
}
|
||||
|
||||
void Scanner::ScanToNextToken() {
|
||||
while (1) {
|
||||
while (true) {
|
||||
// first eat whitespace
|
||||
while (INPUT && IsWhitespaceToBeEaten(INPUT.peek())) {
|
||||
if (InBlockContext() && Exp::Tab().Matches(INPUT)) {
|
||||
|
@@ -47,7 +47,8 @@ std::string ScanScalar(Stream& INPUT, ScanScalarParams& params) {
|
||||
if (INPUT.column() == 0 && Exp::DocIndicator().Matches(INPUT)) {
|
||||
if (params.onDocIndicator == BREAK) {
|
||||
break;
|
||||
} else if (params.onDocIndicator == THROW) {
|
||||
}
|
||||
if (params.onDocIndicator == THROW) {
|
||||
throw ParserException(INPUT.mark(), ErrorMsg::DOC_IN_SCALAR);
|
||||
}
|
||||
}
|
||||
@@ -203,7 +204,7 @@ std::string ScanScalar(Stream& INPUT, ScanScalarParams& params) {
|
||||
|
||||
// post-processing
|
||||
if (params.trimTrailingSpaces) {
|
||||
std::size_t pos = scalar.find_last_not_of(' ');
|
||||
std::size_t pos = scalar.find_last_not_of(" \t");
|
||||
if (lastEscapedChar != std::string::npos) {
|
||||
if (pos < lastEscapedChar || pos == std::string::npos) {
|
||||
pos = lastEscapedChar;
|
||||
@@ -247,4 +248,4 @@ std::string ScanScalar(Stream& INPUT, ScanScalarParams& params) {
|
||||
|
||||
return scalar;
|
||||
}
|
||||
}
|
||||
} // namespace YAML
|
||||
|
@@ -57,7 +57,7 @@ struct ScanScalarParams {
|
||||
bool leadingSpaces;
|
||||
};
|
||||
|
||||
std::string ScanScalar(Stream& INPUT, ScanScalarParams& info);
|
||||
std::string ScanScalar(Stream& INPUT, ScanScalarParams& params);
|
||||
}
|
||||
|
||||
#endif // SCANSCALAR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
|
||||
|
@@ -78,4 +78,4 @@ const std::string ScanTagSuffix(Stream& INPUT) {
|
||||
|
||||
return tag;
|
||||
}
|
||||
}
|
||||
} // namespace YAML
|
||||
|
@@ -37,7 +37,7 @@ void Scanner::ScanDirective() {
|
||||
token.value += INPUT.get();
|
||||
|
||||
// read parameters
|
||||
while (1) {
|
||||
while (true) {
|
||||
// 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 diffently in the block context (and manage indents)
|
||||
// handle keys differently 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 diffently in the block context (and manage indents)
|
||||
// handle values differently in the block context (and manage indents)
|
||||
if (InBlockContext()) {
|
||||
if (!m_simpleKeyAllowed)
|
||||
throw ParserException(INPUT.mark(), ErrorMsg::MAP_VALUE);
|
||||
|
@@ -7,12 +7,18 @@
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "yaml-cpp/noexcept.h"
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace YAML {
|
||||
class SettingChangeBase;
|
||||
|
||||
class SettingChangeBase {
|
||||
public:
|
||||
virtual ~SettingChangeBase() = default;
|
||||
virtual void pop() = 0;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class Setting {
|
||||
@@ -28,12 +34,6 @@ 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;
|
||||
|
||||
virtual void pop() { m_pCurSetting->restore(m_oldSetting); }
|
||||
void pop() override { m_pCurSetting->restore(m_oldSetting); }
|
||||
|
||||
private:
|
||||
Setting<T>* m_pCurSetting;
|
||||
@@ -64,27 +64,9 @@ class SettingChanges {
|
||||
public:
|
||||
SettingChanges() : m_settingChanges{} {}
|
||||
SettingChanges(const SettingChanges&) = delete;
|
||||
SettingChanges(SettingChanges&&) = default;
|
||||
SettingChanges(SettingChanges&&) YAML_CPP_NOEXCEPT = default;
|
||||
SettingChanges& operator=(const SettingChanges&) = delete;
|
||||
~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) {
|
||||
SettingChanges& operator=(SettingChanges&& rhs) YAML_CPP_NOEXCEPT {
|
||||
if (this == &rhs)
|
||||
return *this;
|
||||
|
||||
@@ -93,9 +75,24 @@ 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:
|
||||
typedef std::vector<std::unique_ptr<SettingChangeBase>> setting_changes;
|
||||
using setting_changes = std::vector<std::unique_ptr<SettingChangeBase>>;
|
||||
setting_changes m_settingChanges;
|
||||
};
|
||||
} // namespace YAML
|
||||
|
@@ -5,7 +5,11 @@ 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;
|
||||
@@ -125,4 +129,4 @@ void Scanner::PopAllSimpleKeys() {
|
||||
while (!m_simpleKeys.empty())
|
||||
m_simpleKeys.pop();
|
||||
}
|
||||
}
|
||||
} // namespace YAML
|
||||
|
@@ -7,6 +7,7 @@
|
||||
#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 +22,7 @@ SingleDocParser::SingleDocParser(Scanner& scanner, const Directives& directives)
|
||||
m_anchors{},
|
||||
m_curAnchor(0) {}
|
||||
|
||||
SingleDocParser::~SingleDocParser() {}
|
||||
SingleDocParser::~SingleDocParser() = default;
|
||||
|
||||
// HandleDocument
|
||||
// . Handles the next document
|
||||
@@ -47,6 +48,8 @@ void SingleDocParser::HandleDocument(EventHandler& eventHandler) {
|
||||
}
|
||||
|
||||
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);
|
||||
@@ -79,17 +82,24 @@ void SingleDocParser::HandleNode(EventHandler& eventHandler) {
|
||||
if (!anchor_name.empty())
|
||||
eventHandler.OnAnchor(mark, anchor_name);
|
||||
|
||||
const Token& token = m_scanner.peek();
|
||||
|
||||
if (token.type == Token::PLAIN_SCALAR && IsNullString(token.value)) {
|
||||
// after parsing properties, an empty node is again a possibility
|
||||
if (m_scanner.empty()) {
|
||||
eventHandler.OnNull(mark, anchor);
|
||||
m_scanner.pop();
|
||||
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)) {
|
||||
eventHandler.OnNull(mark, anchor);
|
||||
m_scanner.pop();
|
||||
return;
|
||||
}
|
||||
|
||||
// now split based on what kind of node we should be
|
||||
switch (token.type) {
|
||||
@@ -157,7 +167,7 @@ void SingleDocParser::HandleBlockSequence(EventHandler& eventHandler) {
|
||||
m_scanner.pop();
|
||||
m_pCollectionStack->PushCollectionType(CollectionType::BlockSeq);
|
||||
|
||||
while (1) {
|
||||
while (true) {
|
||||
if (m_scanner.empty())
|
||||
throw ParserException(m_scanner.mark(), ErrorMsg::END_OF_SEQ);
|
||||
|
||||
@@ -190,7 +200,7 @@ void SingleDocParser::HandleFlowSequence(EventHandler& eventHandler) {
|
||||
m_scanner.pop();
|
||||
m_pCollectionStack->PushCollectionType(CollectionType::FlowSeq);
|
||||
|
||||
while (1) {
|
||||
while (true) {
|
||||
if (m_scanner.empty())
|
||||
throw ParserException(m_scanner.mark(), ErrorMsg::END_OF_SEQ_FLOW);
|
||||
|
||||
@@ -243,7 +253,7 @@ void SingleDocParser::HandleBlockMap(EventHandler& eventHandler) {
|
||||
m_scanner.pop();
|
||||
m_pCollectionStack->PushCollectionType(CollectionType::BlockMap);
|
||||
|
||||
while (1) {
|
||||
while (true) {
|
||||
if (m_scanner.empty())
|
||||
throw ParserException(m_scanner.mark(), ErrorMsg::END_OF_MAP);
|
||||
|
||||
@@ -282,7 +292,7 @@ void SingleDocParser::HandleFlowMap(EventHandler& eventHandler) {
|
||||
m_scanner.pop();
|
||||
m_pCollectionStack->PushCollectionType(CollectionType::FlowMap);
|
||||
|
||||
while (1) {
|
||||
while (true) {
|
||||
if (m_scanner.empty())
|
||||
throw ParserException(m_scanner.mark(), ErrorMsg::END_OF_MAP_FLOW);
|
||||
|
||||
@@ -367,7 +377,7 @@ void SingleDocParser::ParseProperties(std::string& tag, anchor_t& anchor,
|
||||
anchor_name.clear();
|
||||
anchor = NullAnchor;
|
||||
|
||||
while (1) {
|
||||
while (true) {
|
||||
if (m_scanner.empty())
|
||||
return;
|
||||
|
||||
@@ -413,7 +423,7 @@ anchor_t SingleDocParser::RegisterAnchor(const std::string& name) {
|
||||
|
||||
anchor_t SingleDocParser::LookupAnchor(const Mark& mark,
|
||||
const std::string& name) const {
|
||||
Anchors::const_iterator it = m_anchors.find(name);
|
||||
auto it = m_anchors.find(name);
|
||||
if (it == m_anchors.end())
|
||||
throw ParserException(mark, ErrorMsg::UNKNOWN_ANCHOR);
|
||||
|
||||
|
@@ -15,6 +15,7 @@
|
||||
|
||||
namespace YAML {
|
||||
class CollectionStack;
|
||||
template <int> class DepthGuard; // depthguard.h
|
||||
class EventHandler;
|
||||
class Node;
|
||||
class Scanner;
|
||||
@@ -55,11 +56,12 @@ class SingleDocParser {
|
||||
anchor_t LookupAnchor(const Mark& mark, const std::string& name) const;
|
||||
|
||||
private:
|
||||
int depth = 0;
|
||||
Scanner& m_scanner;
|
||||
const Directives& m_directives;
|
||||
std::unique_ptr<CollectionStack> m_pCollectionStack;
|
||||
|
||||
typedef std::map<std::string, anchor_t> Anchors;
|
||||
using Anchors = std::map<std::string, anchor_t>;
|
||||
Anchors m_anchors;
|
||||
|
||||
anchor_t m_curAnchor;
|
||||
|
@@ -151,7 +151,8 @@ inline UtfIntroCharType IntroCharTypeOf(std::istream::int_type ch) {
|
||||
|
||||
inline char Utf8Adjust(unsigned long ch, unsigned char lead_bits,
|
||||
unsigned char rshift) {
|
||||
const unsigned char header = ((1 << lead_bits) - 1) << (8 - lead_bits);
|
||||
const unsigned char header =
|
||||
static_cast<unsigned char>(((1 << lead_bits) - 1) << (8 - lead_bits));
|
||||
const unsigned char mask = (0xFF >> (lead_bits + 1));
|
||||
return static_cast<char>(
|
||||
static_cast<unsigned char>(header | ((ch >> rshift) & mask)));
|
||||
@@ -189,14 +190,14 @@ Stream::Stream(std::istream& input)
|
||||
m_pPrefetched(new unsigned char[YAML_PREFETCH_SIZE]),
|
||||
m_nPrefetchedAvailable(0),
|
||||
m_nPrefetchedUsed(0) {
|
||||
typedef std::istream::traits_type char_traits;
|
||||
using char_traits = std::istream::traits_type;
|
||||
|
||||
if (!input)
|
||||
return;
|
||||
|
||||
// Determine (or guess) the character-set by reading the BOM, if any. See
|
||||
// the YAML specification for the determination algorithm.
|
||||
char_traits::int_type intro[4];
|
||||
char_traits::int_type intro[4]{};
|
||||
int nIntroUsed = 0;
|
||||
UtfIntroState state = uis_start;
|
||||
for (; !s_introFinalState[state];) {
|
||||
@@ -273,9 +274,11 @@ char Stream::get() {
|
||||
// . Extracts 'n' characters from the stream and updates our position
|
||||
std::string Stream::get(int n) {
|
||||
std::string ret;
|
||||
ret.reserve(n);
|
||||
for (int i = 0; i < n; i++)
|
||||
ret += get();
|
||||
if (n > 0) {
|
||||
ret.reserve(static_cast<std::string::size_type>(n));
|
||||
for (int i = 0; i < n; i++)
|
||||
ret += get();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -326,7 +329,7 @@ bool Stream::_ReadAheadTo(size_t i) const {
|
||||
void Stream::StreamInUtf8() const {
|
||||
unsigned char b = GetNextByte();
|
||||
if (m_input.good()) {
|
||||
m_readahead.push_back(b);
|
||||
m_readahead.push_back(static_cast<char>(b));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -347,7 +350,9 @@ void Stream::StreamInUtf16() const {
|
||||
// Trailing (low) surrogate...ugh, wrong order
|
||||
QueueUnicodeCodepoint(m_readahead, CP_REPLACEMENT_CHARACTER);
|
||||
return;
|
||||
} else if (ch >= 0xD800 && ch < 0xDC00) {
|
||||
}
|
||||
|
||||
if (ch >= 0xD800 && ch < 0xDC00) {
|
||||
// ch is a leading (high) surrogate
|
||||
|
||||
// Four byte UTF-8 code point
|
||||
@@ -372,11 +377,10 @@ void Stream::StreamInUtf16() const {
|
||||
// Easiest case: queue the codepoint and return
|
||||
QueueUnicodeCodepoint(m_readahead, ch);
|
||||
return;
|
||||
} else {
|
||||
// Start the loop over with the new high surrogate
|
||||
ch = chLow;
|
||||
continue;
|
||||
}
|
||||
// Start the loop over with the new high surrogate
|
||||
ch = chLow;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Select the payload bits from the high surrogate
|
||||
|
@@ -16,6 +16,9 @@
|
||||
#include <string>
|
||||
|
||||
namespace YAML {
|
||||
|
||||
class StreamCharSource;
|
||||
|
||||
class Stream {
|
||||
public:
|
||||
friend class StreamCharSource;
|
||||
|
@@ -7,18 +7,20 @@
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "yaml-cpp/noexcept.h"
|
||||
#include "stream.h"
|
||||
#include <cstddef>
|
||||
|
||||
namespace YAML {
|
||||
|
||||
class StreamCharSource {
|
||||
public:
|
||||
StreamCharSource(const Stream& stream) : m_offset(0), m_stream(stream) {}
|
||||
StreamCharSource(const StreamCharSource& source)
|
||||
: m_offset(source.m_offset), m_stream(source.m_stream) {}
|
||||
StreamCharSource(StreamCharSource&&) = default;
|
||||
StreamCharSource(const StreamCharSource& source) = default;
|
||||
StreamCharSource(StreamCharSource&&) YAML_CPP_NOEXCEPT = default;
|
||||
StreamCharSource& operator=(const StreamCharSource&) = delete;
|
||||
StreamCharSource& operator=(StreamCharSource&&) = delete;
|
||||
~StreamCharSource() {}
|
||||
~StreamCharSource() = default;
|
||||
|
||||
operator bool() const;
|
||||
char operator[](std::size_t i) const { return m_stream.CharAt(m_offset + i); }
|
||||
@@ -38,7 +40,7 @@ inline StreamCharSource::operator bool() const {
|
||||
inline const StreamCharSource StreamCharSource::operator+(int i) const {
|
||||
StreamCharSource source(*this);
|
||||
if (static_cast<int>(source.m_offset) + i >= 0)
|
||||
source.m_offset += i;
|
||||
source.m_offset += static_cast<std::size_t>(i);
|
||||
else
|
||||
source.m_offset = 0;
|
||||
return source;
|
||||
|
@@ -53,8 +53,8 @@ struct Token {
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& out, const Token& token) {
|
||||
out << TokenNames[token.type] << std::string(": ") << token.value;
|
||||
for (std::size_t i = 0; i < token.params.size(); i++)
|
||||
out << std::string(" ") << token.params[i];
|
||||
for (const std::string& param : token.params)
|
||||
out << std::string(" ") << param;
|
||||
return out;
|
||||
}
|
||||
|
||||
|
14
test/BUILD.bazel
Normal file
14
test/BUILD.bazel
Normal file
@@ -0,0 +1,14 @@
|
||||
cc_test(
|
||||
name = "test",
|
||||
srcs = glob([
|
||||
"*.cpp",
|
||||
"*.h",
|
||||
"integrations/*.cpp",
|
||||
"node/*.cpp",
|
||||
]),
|
||||
deps = [
|
||||
"//:yaml-cpp",
|
||||
"//:yaml-cpp_internal",
|
||||
"@com_google_googletest//:gtest_main",
|
||||
],
|
||||
)
|
@@ -1,69 +1,49 @@
|
||||
include(ExternalProject)
|
||||
find_package(Threads REQUIRED)
|
||||
|
||||
if(MSVC)
|
||||
# MS Visual Studio expects lib prefix on static libraries,
|
||||
# but CMake compiles them without prefix
|
||||
# See https://gitlab.kitware.com/cmake/cmake/issues/17338
|
||||
set(CMAKE_STATIC_LIBRARY_PREFIX "")
|
||||
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
|
||||
set(BUILD_MOCK ON CACHE BOOL "" FORCE)
|
||||
set(CMAKE_POLICY_DEFAULT_CMP0048 NEW)
|
||||
|
||||
add_subdirectory(
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/gtest-1.10.0"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/prefix")
|
||||
|
||||
include_directories(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/gtest-1.10.0/googletest/include")
|
||||
|
||||
set(test-new-api-pattern "new-api/*.cpp")
|
||||
set(test-source-pattern "*.cpp" "integration/*.cpp" "node/*.cpp")
|
||||
if (CMAKE_VERSION VERSION_GREATER 3.11)
|
||||
list(INSERT test-new-api-pattern 0 CONFIGURE_DEPENDS)
|
||||
list(INSERT test-source-pattern 0 CONFIGURE_DEPENDS)
|
||||
endif()
|
||||
|
||||
ExternalProject_Add(
|
||||
googletest_project
|
||||
SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/gtest-1.8.0"
|
||||
INSTALL_DIR "${CMAKE_CURRENT_BINARY_DIR}/prefix"
|
||||
CMAKE_ARGS
|
||||
-DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR>
|
||||
-DBUILD_GMOCK=ON
|
||||
-Dgtest_force_shared_crt=ON
|
||||
)
|
||||
file(GLOB test-new-api-sources ${test-new-api-pattern})
|
||||
file(GLOB test-sources ${test-source-pattern})
|
||||
|
||||
add_library(gmock UNKNOWN IMPORTED)
|
||||
set_target_properties(gmock PROPERTIES
|
||||
IMPORTED_LOCATION
|
||||
${PROJECT_BINARY_DIR}/test/prefix/lib/${CMAKE_STATIC_LIBRARY_PREFIX}gmock${CMAKE_STATIC_LIBRARY_SUFFIX}
|
||||
)
|
||||
|
||||
find_package(Threads)
|
||||
|
||||
include_directories(SYSTEM "${PROJECT_BINARY_DIR}/test/prefix/include")
|
||||
|
||||
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU" OR
|
||||
CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
set(yaml_test_flags "-Wno-variadic-macros -Wno-sign-compare")
|
||||
|
||||
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
set(yaml_test_flags "${yaml_test_flags} -Wno-c99-extensions")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
file(GLOB test_headers [a-z_]*.h)
|
||||
file(GLOB test_sources [a-z_]*.cpp integration/[a-z_]*.cpp node/[a-z_]*.cpp)
|
||||
file(GLOB test_new_api_sources new-api/[a-z]*.cpp)
|
||||
|
||||
list(APPEND test_sources ${test_new_api_sources})
|
||||
add_sources(${test_sources} ${test_headers})
|
||||
|
||||
include_directories(${YAML_CPP_SOURCE_DIR}/src)
|
||||
include_directories(${YAML_CPP_SOURCE_DIR}/test)
|
||||
|
||||
add_executable(run-tests
|
||||
${test_sources}
|
||||
${test_headers}
|
||||
)
|
||||
|
||||
set_target_properties(run-tests PROPERTIES
|
||||
CXX_STANDARD 11
|
||||
CXX_STANDARD_REQUIRED ON
|
||||
)
|
||||
|
||||
add_dependencies(run-tests googletest_project)
|
||||
|
||||
set_target_properties(run-tests PROPERTIES
|
||||
COMPILE_FLAGS "${yaml_c_flags} ${yaml_cxx_flags} ${yaml_test_flags}"
|
||||
)
|
||||
target_link_libraries(run-tests
|
||||
add_executable(yaml-cpp-tests "")
|
||||
target_sources(yaml-cpp-tests
|
||||
PRIVATE
|
||||
${test-new-api-sources}
|
||||
${test-sources})
|
||||
target_include_directories(yaml-cpp-tests
|
||||
PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/integration
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${PROJECT_SOURCE_DIR}/src)
|
||||
target_compile_options(yaml-cpp-tests
|
||||
PRIVATE
|
||||
$<$<CXX_COMPILER_ID:Clang>:-Wno-c99-extensions -Wno-variadic-macros -Wno-sign-compare>
|
||||
$<$<CXX_COMPILER_ID:GNU>:-Wno-variadic-macros -Wno-sign-compare>)
|
||||
target_link_libraries(yaml-cpp-tests
|
||||
PRIVATE
|
||||
Threads::Threads
|
||||
yaml-cpp
|
||||
gmock
|
||||
${CMAKE_THREAD_LIBS_INIT})
|
||||
gmock)
|
||||
|
||||
add_test(yaml-test ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/run-tests)
|
||||
set_property(TARGET yaml-cpp-tests PROPERTY CXX_STANDARD_REQUIRED ON)
|
||||
if (NOT DEFINED CMAKE_CXX_STANDARD)
|
||||
set_target_properties(yaml-cpp-tests PROPERTIES CXX_STANDARD 11)
|
||||
endif()
|
||||
|
||||
|
||||
add_test(yaml-cpp::test yaml-cpp-tests)
|
||||
|
4
test/gtest-1.10.0/.clang-format
Normal file
4
test/gtest-1.10.0/.clang-format
Normal file
@@ -0,0 +1,4 @@
|
||||
# Run manually to reformat a file:
|
||||
# clang-format -i --style=file <file>
|
||||
Language: Cpp
|
||||
BasedOnStyle: Google
|
84
test/gtest-1.10.0/.gitignore
vendored
Normal file
84
test/gtest-1.10.0/.gitignore
vendored
Normal file
@@ -0,0 +1,84 @@
|
||||
# Ignore CI build directory
|
||||
build/
|
||||
xcuserdata
|
||||
cmake-build-debug/
|
||||
.idea/
|
||||
bazel-bin
|
||||
bazel-genfiles
|
||||
bazel-googletest
|
||||
bazel-out
|
||||
bazel-testlogs
|
||||
# python
|
||||
*.pyc
|
||||
|
||||
# Visual Studio files
|
||||
.vs
|
||||
*.sdf
|
||||
*.opensdf
|
||||
*.VC.opendb
|
||||
*.suo
|
||||
*.user
|
||||
_ReSharper.Caches/
|
||||
Win32-Debug/
|
||||
Win32-Release/
|
||||
x64-Debug/
|
||||
x64-Release/
|
||||
|
||||
# Ignore autoconf / automake files
|
||||
Makefile.in
|
||||
aclocal.m4
|
||||
configure
|
||||
build-aux/
|
||||
autom4te.cache/
|
||||
googletest/m4/libtool.m4
|
||||
googletest/m4/ltoptions.m4
|
||||
googletest/m4/ltsugar.m4
|
||||
googletest/m4/ltversion.m4
|
||||
googletest/m4/lt~obsolete.m4
|
||||
googlemock/m4
|
||||
|
||||
# Ignore generated directories.
|
||||
googlemock/fused-src/
|
||||
googletest/fused-src/
|
||||
|
||||
# macOS files
|
||||
.DS_Store
|
||||
googletest/.DS_Store
|
||||
googletest/xcode/.DS_Store
|
||||
|
||||
# Ignore cmake generated directories and files.
|
||||
CMakeFiles
|
||||
CTestTestfile.cmake
|
||||
Makefile
|
||||
cmake_install.cmake
|
||||
googlemock/CMakeFiles
|
||||
googlemock/CTestTestfile.cmake
|
||||
googlemock/Makefile
|
||||
googlemock/cmake_install.cmake
|
||||
googlemock/gtest
|
||||
/bin
|
||||
/googlemock/gmock.dir
|
||||
/googlemock/gmock_main.dir
|
||||
/googlemock/RUN_TESTS.vcxproj.filters
|
||||
/googlemock/RUN_TESTS.vcxproj
|
||||
/googlemock/INSTALL.vcxproj.filters
|
||||
/googlemock/INSTALL.vcxproj
|
||||
/googlemock/gmock_main.vcxproj.filters
|
||||
/googlemock/gmock_main.vcxproj
|
||||
/googlemock/gmock.vcxproj.filters
|
||||
/googlemock/gmock.vcxproj
|
||||
/googlemock/gmock.sln
|
||||
/googlemock/ALL_BUILD.vcxproj.filters
|
||||
/googlemock/ALL_BUILD.vcxproj
|
||||
/lib
|
||||
/Win32
|
||||
/ZERO_CHECK.vcxproj.filters
|
||||
/ZERO_CHECK.vcxproj
|
||||
/RUN_TESTS.vcxproj.filters
|
||||
/RUN_TESTS.vcxproj
|
||||
/INSTALL.vcxproj.filters
|
||||
/INSTALL.vcxproj
|
||||
/googletest-distribution.sln
|
||||
/CMakeCache.txt
|
||||
/ALL_BUILD.vcxproj.filters
|
||||
/ALL_BUILD.vcxproj
|
73
test/gtest-1.10.0/.travis.yml
Normal file
73
test/gtest-1.10.0/.travis.yml
Normal file
@@ -0,0 +1,73 @@
|
||||
# Build matrix / environment variable are explained on:
|
||||
# https://docs.travis-ci.com/user/customizing-the-build/
|
||||
# This file can be validated on:
|
||||
# http://lint.travis-ci.org/
|
||||
|
||||
language: cpp
|
||||
|
||||
# Define the matrix explicitly, manually expanding the combinations of (os, compiler, env).
|
||||
# It is more tedious, but grants us far more flexibility.
|
||||
matrix:
|
||||
include:
|
||||
- os: linux
|
||||
before_install: chmod -R +x ./ci/*platformio.sh
|
||||
install: ./ci/install-platformio.sh
|
||||
script: ./ci/build-platformio.sh
|
||||
- os: linux
|
||||
dist: xenial
|
||||
compiler: gcc
|
||||
install: ./ci/install-linux.sh && ./ci/log-config.sh
|
||||
script: ./ci/build-linux-bazel.sh
|
||||
- os: linux
|
||||
dist: xenial
|
||||
compiler: clang
|
||||
install: ./ci/install-linux.sh && ./ci/log-config.sh
|
||||
script: ./ci/build-linux-bazel.sh
|
||||
- os: linux
|
||||
compiler: gcc
|
||||
env: BUILD_TYPE=Debug VERBOSE=1 CXX_FLAGS=-std=c++11
|
||||
- os: linux
|
||||
compiler: clang
|
||||
env: BUILD_TYPE=Release VERBOSE=1 CXX_FLAGS=-std=c++11 -Wgnu-zero-variadic-macro-arguments
|
||||
- os: linux
|
||||
compiler: clang
|
||||
env: BUILD_TYPE=Release VERBOSE=1 CXX_FLAGS=-std=c++11 NO_EXCEPTION=ON NO_RTTI=ON COMPILER_IS_GNUCXX=ON
|
||||
- os: osx
|
||||
compiler: gcc
|
||||
env: BUILD_TYPE=Release VERBOSE=1 CXX_FLAGS=-std=c++11 HOMEBREW_LOGS=~/homebrew-logs HOMEBREW_TEMP=~/homebrew-temp
|
||||
- os: osx
|
||||
compiler: clang
|
||||
env: BUILD_TYPE=Release VERBOSE=1 CXX_FLAGS=-std=c++11 HOMEBREW_LOGS=~/homebrew-logs HOMEBREW_TEMP=~/homebrew-temp
|
||||
|
||||
# These are the install and build (script) phases for the most common entries in the matrix. They could be included
|
||||
# in each entry in the matrix, but that is just repetitive.
|
||||
install:
|
||||
- ./ci/install-${TRAVIS_OS_NAME}.sh
|
||||
- . ./ci/env-${TRAVIS_OS_NAME}.sh
|
||||
- ./ci/log-config.sh
|
||||
|
||||
script: ./ci/travis.sh
|
||||
|
||||
# This section installs the necessary dependencies.
|
||||
addons:
|
||||
apt:
|
||||
# List of whitelisted in travis packages for ubuntu-precise can be found here:
|
||||
# https://github.com/travis-ci/apt-package-whitelist/blob/master/ubuntu-precise
|
||||
# List of whitelisted in travis apt-sources:
|
||||
# https://github.com/travis-ci/apt-source-whitelist/blob/master/ubuntu.json
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- llvm-toolchain-precise-3.9
|
||||
packages:
|
||||
- g++-4.9
|
||||
- clang-3.9
|
||||
update: true
|
||||
homebrew:
|
||||
packages:
|
||||
- ccache
|
||||
- gcc@4.9
|
||||
- llvm@4
|
||||
update: true
|
||||
|
||||
notifications:
|
||||
email: false
|
179
test/gtest-1.10.0/BUILD.bazel
Normal file
179
test/gtest-1.10.0/BUILD.bazel
Normal file
@@ -0,0 +1,179 @@
|
||||
# Copyright 2017 Google Inc.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above
|
||||
# copyright notice, this list of conditions and the following disclaimer
|
||||
# in the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
# * Neither the name of Google Inc. nor the names of its
|
||||
# contributors may be used to endorse or promote products derived from
|
||||
# this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
# Bazel Build for Google C++ Testing Framework(Google Test)
|
||||
|
||||
load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test")
|
||||
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
config_setting(
|
||||
name = "windows",
|
||||
constraint_values = ["@bazel_tools//platforms:windows"],
|
||||
)
|
||||
|
||||
config_setting(
|
||||
name = "has_absl",
|
||||
values = {"define": "absl=1"},
|
||||
)
|
||||
|
||||
# Library that defines the FRIEND_TEST macro.
|
||||
cc_library(
|
||||
name = "gtest_prod",
|
||||
hdrs = ["googletest/include/gtest/gtest_prod.h"],
|
||||
includes = ["googletest/include"],
|
||||
)
|
||||
|
||||
# Google Test including Google Mock
|
||||
cc_library(
|
||||
name = "gtest",
|
||||
srcs = glob(
|
||||
include = [
|
||||
"googletest/src/*.cc",
|
||||
"googletest/src/*.h",
|
||||
"googletest/include/gtest/**/*.h",
|
||||
"googlemock/src/*.cc",
|
||||
"googlemock/include/gmock/**/*.h",
|
||||
],
|
||||
exclude = [
|
||||
"googletest/src/gtest-all.cc",
|
||||
"googletest/src/gtest_main.cc",
|
||||
"googlemock/src/gmock-all.cc",
|
||||
"googlemock/src/gmock_main.cc",
|
||||
],
|
||||
),
|
||||
hdrs = glob([
|
||||
"googletest/include/gtest/*.h",
|
||||
"googlemock/include/gmock/*.h",
|
||||
]),
|
||||
copts = select({
|
||||
":windows": [],
|
||||
"//conditions:default": ["-pthread"],
|
||||
}),
|
||||
defines = select({
|
||||
":has_absl": ["GTEST_HAS_ABSL=1"],
|
||||
"//conditions:default": [],
|
||||
}),
|
||||
features = select({
|
||||
":windows": ["windows_export_all_symbols"],
|
||||
"//conditions:default": [],
|
||||
}),
|
||||
includes = [
|
||||
"googlemock",
|
||||
"googlemock/include",
|
||||
"googletest",
|
||||
"googletest/include",
|
||||
],
|
||||
linkopts = select({
|
||||
":windows": [],
|
||||
"//conditions:default": ["-pthread"],
|
||||
}),
|
||||
deps = select({
|
||||
":has_absl": [
|
||||
"@com_google_absl//absl/debugging:failure_signal_handler",
|
||||
"@com_google_absl//absl/debugging:stacktrace",
|
||||
"@com_google_absl//absl/debugging:symbolize",
|
||||
"@com_google_absl//absl/strings",
|
||||
"@com_google_absl//absl/types:optional",
|
||||
"@com_google_absl//absl/types:variant",
|
||||
],
|
||||
"//conditions:default": [],
|
||||
}),
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "gtest_main",
|
||||
srcs = ["googlemock/src/gmock_main.cc"],
|
||||
features = select({
|
||||
":windows": ["windows_export_all_symbols"],
|
||||
"//conditions:default": [],
|
||||
}),
|
||||
deps = [":gtest"],
|
||||
)
|
||||
|
||||
# The following rules build samples of how to use gTest.
|
||||
cc_library(
|
||||
name = "gtest_sample_lib",
|
||||
srcs = [
|
||||
"googletest/samples/sample1.cc",
|
||||
"googletest/samples/sample2.cc",
|
||||
"googletest/samples/sample4.cc",
|
||||
],
|
||||
hdrs = [
|
||||
"googletest/samples/prime_tables.h",
|
||||
"googletest/samples/sample1.h",
|
||||
"googletest/samples/sample2.h",
|
||||
"googletest/samples/sample3-inl.h",
|
||||
"googletest/samples/sample4.h",
|
||||
],
|
||||
features = select({
|
||||
":windows": ["windows_export_all_symbols"],
|
||||
"//conditions:default": [],
|
||||
}),
|
||||
)
|
||||
|
||||
cc_test(
|
||||
name = "gtest_samples",
|
||||
size = "small",
|
||||
# All Samples except:
|
||||
# sample9 (main)
|
||||
# sample10 (main and takes a command line option and needs to be separate)
|
||||
srcs = [
|
||||
"googletest/samples/sample1_unittest.cc",
|
||||
"googletest/samples/sample2_unittest.cc",
|
||||
"googletest/samples/sample3_unittest.cc",
|
||||
"googletest/samples/sample4_unittest.cc",
|
||||
"googletest/samples/sample5_unittest.cc",
|
||||
"googletest/samples/sample6_unittest.cc",
|
||||
"googletest/samples/sample7_unittest.cc",
|
||||
"googletest/samples/sample8_unittest.cc",
|
||||
],
|
||||
linkstatic = 0,
|
||||
deps = [
|
||||
"gtest_sample_lib",
|
||||
":gtest_main",
|
||||
],
|
||||
)
|
||||
|
||||
cc_test(
|
||||
name = "sample9_unittest",
|
||||
size = "small",
|
||||
srcs = ["googletest/samples/sample9_unittest.cc"],
|
||||
deps = [":gtest"],
|
||||
)
|
||||
|
||||
cc_test(
|
||||
name = "sample10_unittest",
|
||||
size = "small",
|
||||
srcs = ["googletest/samples/sample10_unittest.cc"],
|
||||
deps = [":gtest"],
|
||||
)
|
36
test/gtest-1.10.0/CMakeLists.txt
Normal file
36
test/gtest-1.10.0/CMakeLists.txt
Normal file
@@ -0,0 +1,36 @@
|
||||
# Note: CMake support is community-based. The maintainers do not use CMake
|
||||
# internally.
|
||||
|
||||
cmake_minimum_required(VERSION 2.8.8)
|
||||
|
||||
if (POLICY CMP0048)
|
||||
cmake_policy(SET CMP0048 NEW)
|
||||
endif (POLICY CMP0048)
|
||||
|
||||
project(googletest-distribution)
|
||||
set(GOOGLETEST_VERSION 1.10.0)
|
||||
|
||||
if (CMAKE_VERSION VERSION_LESS "3.1")
|
||||
add_definitions(-std=c++11)
|
||||
else()
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
if(NOT CYGWIN)
|
||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
enable_testing()
|
||||
|
||||
include(CMakeDependentOption)
|
||||
include(GNUInstallDirs)
|
||||
|
||||
#Note that googlemock target already builds googletest
|
||||
option(BUILD_GMOCK "Builds the googlemock subproject" ON)
|
||||
option(INSTALL_GTEST "Enable installation of googletest. (Projects embedding googletest may want to turn this OFF.)" ON)
|
||||
|
||||
if(BUILD_GMOCK)
|
||||
add_subdirectory( googlemock )
|
||||
else()
|
||||
add_subdirectory( googletest )
|
||||
endif()
|
142
test/gtest-1.10.0/CONTRIBUTING.md
Normal file
142
test/gtest-1.10.0/CONTRIBUTING.md
Normal file
@@ -0,0 +1,142 @@
|
||||
# How to become a contributor and submit your own code
|
||||
|
||||
## Contributor License Agreements
|
||||
|
||||
We'd love to accept your patches! Before we can take them, we have to jump a
|
||||
couple of legal hurdles.
|
||||
|
||||
Please fill out either the individual or corporate Contributor License Agreement
|
||||
(CLA).
|
||||
|
||||
* If you are an individual writing original source code and you're sure you
|
||||
own the intellectual property, then you'll need to sign an
|
||||
[individual CLA](https://developers.google.com/open-source/cla/individual).
|
||||
* If you work for a company that wants to allow you to contribute your work,
|
||||
then you'll need to sign a
|
||||
[corporate CLA](https://developers.google.com/open-source/cla/corporate).
|
||||
|
||||
Follow either of the two links above to access the appropriate CLA and
|
||||
instructions for how to sign and return it. Once we receive it, we'll be able to
|
||||
accept your pull requests.
|
||||
|
||||
## Are you a Googler?
|
||||
|
||||
If you are a Googler, please make an attempt to submit an internal change rather
|
||||
than a GitHub Pull Request. If you are not able to submit an internal change a
|
||||
PR is acceptable as an alternative.
|
||||
|
||||
## Contributing A Patch
|
||||
|
||||
1. Submit an issue describing your proposed change to the
|
||||
[issue tracker](https://github.com/google/googletest).
|
||||
2. Please don't mix more than one logical change per submittal, because it
|
||||
makes the history hard to follow. If you want to make a change that doesn't
|
||||
have a corresponding issue in the issue tracker, please create one.
|
||||
3. Also, coordinate with team members that are listed on the issue in question.
|
||||
This ensures that work isn't being duplicated and communicating your plan
|
||||
early also generally leads to better patches.
|
||||
4. If your proposed change is accepted, and you haven't already done so, sign a
|
||||
Contributor License Agreement (see details above).
|
||||
5. Fork the desired repo, develop and test your code changes.
|
||||
6. Ensure that your code adheres to the existing style in the sample to which
|
||||
you are contributing.
|
||||
7. Ensure that your code has an appropriate set of unit tests which all pass.
|
||||
8. Submit a pull request.
|
||||
|
||||
## The Google Test and Google Mock Communities
|
||||
|
||||
The Google Test community exists primarily through the
|
||||
[discussion group](http://groups.google.com/group/googletestframework) and the
|
||||
GitHub repository. Likewise, the Google Mock community exists primarily through
|
||||
their own [discussion group](http://groups.google.com/group/googlemock). You are
|
||||
definitely encouraged to contribute to the discussion and you can also help us
|
||||
to keep the effectiveness of the group high by following and promoting the
|
||||
guidelines listed here.
|
||||
|
||||
### Please Be Friendly
|
||||
|
||||
Showing courtesy and respect to others is a vital part of the Google culture,
|
||||
and we strongly encourage everyone participating in Google Test development to
|
||||
join us in accepting nothing less. Of course, being courteous is not the same as
|
||||
failing to constructively disagree with each other, but it does mean that we
|
||||
should be respectful of each other when enumerating the 42 technical reasons
|
||||
that a particular proposal may not be the best choice. There's never a reason to
|
||||
be antagonistic or dismissive toward anyone who is sincerely trying to
|
||||
contribute to a discussion.
|
||||
|
||||
Sure, C++ testing is serious business and all that, but it's also a lot of fun.
|
||||
Let's keep it that way. Let's strive to be one of the friendliest communities in
|
||||
all of open source.
|
||||
|
||||
As always, discuss Google Test in the official GoogleTest discussion group. You
|
||||
don't have to actually submit code in order to sign up. Your participation
|
||||
itself is a valuable contribution.
|
||||
|
||||
## Style
|
||||
|
||||
To keep the source consistent, readable, diffable and easy to merge, we use a
|
||||
fairly rigid coding style, as defined by the
|
||||
[google-styleguide](https://github.com/google/styleguide) project. All patches
|
||||
will be expected to conform to the style outlined
|
||||
[here](https://google.github.io/styleguide/cppguide.html). Use
|
||||
[.clang-format](https://github.com/google/googletest/blob/master/.clang-format)
|
||||
to check your formatting
|
||||
|
||||
## Requirements for Contributors
|
||||
|
||||
If you plan to contribute a patch, you need to build Google Test, Google Mock,
|
||||
and their own tests from a git checkout, which has further requirements:
|
||||
|
||||
* [Python](https://www.python.org/) v2.3 or newer (for running some of the
|
||||
tests and re-generating certain source files from templates)
|
||||
* [CMake](https://cmake.org/) v2.6.4 or newer
|
||||
|
||||
## Developing Google Test and Google Mock
|
||||
|
||||
This section discusses how to make your own changes to the Google Test project.
|
||||
|
||||
### Testing Google Test and Google Mock Themselves
|
||||
|
||||
To make sure your changes work as intended and don't break existing
|
||||
functionality, you'll want to compile and run Google Test and GoogleMock's own
|
||||
tests. For that you can use CMake:
|
||||
|
||||
mkdir mybuild
|
||||
cd mybuild
|
||||
cmake -Dgtest_build_tests=ON -Dgmock_build_tests=ON ${GTEST_REPO_DIR}
|
||||
|
||||
To choose between building only Google Test or Google Mock, you may modify your
|
||||
cmake command to be one of each
|
||||
|
||||
cmake -Dgtest_build_tests=ON ${GTEST_DIR} # sets up Google Test tests
|
||||
cmake -Dgmock_build_tests=ON ${GMOCK_DIR} # sets up Google Mock tests
|
||||
|
||||
Make sure you have Python installed, as some of Google Test's tests are written
|
||||
in Python. If the cmake command complains about not being able to find Python
|
||||
(`Could NOT find PythonInterp (missing: PYTHON_EXECUTABLE)`), try telling it
|
||||
explicitly where your Python executable can be found:
|
||||
|
||||
cmake -DPYTHON_EXECUTABLE=path/to/python ...
|
||||
|
||||
Next, you can build Google Test and / or Google Mock and all desired tests. On
|
||||
\*nix, this is usually done by
|
||||
|
||||
make
|
||||
|
||||
To run the tests, do
|
||||
|
||||
make test
|
||||
|
||||
All tests should pass.
|
||||
|
||||
### Regenerating Source Files
|
||||
|
||||
Some of Google Test's source files are generated from templates (not in the C++
|
||||
sense) using a script. For example, the file
|
||||
include/gtest/internal/gtest-type-util.h.pump is used to generate
|
||||
gtest-type-util.h in the same directory.
|
||||
|
||||
You don't need to worry about regenerating the source files unless you need to
|
||||
modify them. You would then modify the corresponding `.pump` files and run the
|
||||
'[pump.py](googletest/scripts/pump.py)' generator script. See the
|
||||
[Pump Manual](googletest/docs/pump_manual.md).
|
134
test/gtest-1.10.0/README.md
Normal file
134
test/gtest-1.10.0/README.md
Normal file
@@ -0,0 +1,134 @@
|
||||
# Google Test
|
||||
|
||||
#### OSS Builds Status:
|
||||
|
||||
[](https://travis-ci.org/google/googletest)
|
||||
[](https://ci.appveyor.com/project/GoogleTestAppVeyor/googletest/branch/master)
|
||||
|
||||
### Future Plans
|
||||
|
||||
#### 1.8.x Release:
|
||||
|
||||
[the 1.8.x](https://github.com/google/googletest/releases/tag/release-1.8.1) is
|
||||
the last release that works with pre-C++11 compilers. The 1.8.x will not accept
|
||||
any requests for any new features and any bugfix requests will only be accepted
|
||||
if proven "critical"
|
||||
|
||||
#### Post 1.8.x:
|
||||
|
||||
On-going work to improve/cleanup/pay technical debt. When this work is completed
|
||||
there will be a 1.9.x tagged release
|
||||
|
||||
#### Post 1.9.x
|
||||
|
||||
Post 1.9.x googletest will follow
|
||||
[Abseil Live at Head philosophy](https://abseil.io/about/philosophy)
|
||||
|
||||
## Welcome to **Google Test**, Google's C++ test framework!
|
||||
|
||||
This repository is a merger of the formerly separate GoogleTest and GoogleMock
|
||||
projects. These were so closely related that it makes sense to maintain and
|
||||
release them together.
|
||||
|
||||
Please subscribe to the mailing list at googletestframework@googlegroups.com for
|
||||
questions, discussions, and development.
|
||||
|
||||
### Getting started:
|
||||
|
||||
The information for **Google Test** is available in the
|
||||
[Google Test Primer](googletest/docs/primer.md) documentation.
|
||||
|
||||
**Google Mock** is an extension to Google Test for writing and using C++ mock
|
||||
classes. See the separate [Google Mock documentation](googlemock/README.md).
|
||||
|
||||
More detailed documentation for googletest is in its interior
|
||||
[googletest/README.md](googletest/README.md) file.
|
||||
|
||||
## Features
|
||||
|
||||
* An [xUnit](https://en.wikipedia.org/wiki/XUnit) test framework.
|
||||
* Test discovery.
|
||||
* A rich set of assertions.
|
||||
* User-defined assertions.
|
||||
* Death tests.
|
||||
* Fatal and non-fatal failures.
|
||||
* Value-parameterized tests.
|
||||
* Type-parameterized tests.
|
||||
* Various options for running the tests.
|
||||
* XML test report generation.
|
||||
|
||||
## Platforms
|
||||
|
||||
Google test has been used on a variety of platforms:
|
||||
|
||||
* Linux
|
||||
* Mac OS X
|
||||
* Windows
|
||||
* Cygwin
|
||||
* MinGW
|
||||
* Windows Mobile
|
||||
* Symbian
|
||||
* PlatformIO
|
||||
|
||||
## Who Is Using Google Test?
|
||||
|
||||
In addition to many internal projects at Google, Google Test is also used by the
|
||||
following notable projects:
|
||||
|
||||
* The [Chromium projects](http://www.chromium.org/) (behind the Chrome browser
|
||||
and Chrome OS).
|
||||
* The [LLVM](http://llvm.org/) compiler.
|
||||
* [Protocol Buffers](https://github.com/google/protobuf), Google's data
|
||||
interchange format.
|
||||
* The [OpenCV](http://opencv.org/) computer vision library.
|
||||
* [tiny-dnn](https://github.com/tiny-dnn/tiny-dnn): header only,
|
||||
dependency-free deep learning framework in C++11.
|
||||
|
||||
## Related Open Source Projects
|
||||
|
||||
[GTest Runner](https://github.com/nholthaus/gtest-runner) is a Qt5 based
|
||||
automated test-runner and Graphical User Interface with powerful features for
|
||||
Windows and Linux platforms.
|
||||
|
||||
[Google Test UI](https://github.com/ospector/gtest-gbar) is test runner that
|
||||
runs your test binary, allows you to track its progress via a progress bar, and
|
||||
displays a list of test failures. Clicking on one shows failure text. Google
|
||||
Test UI is written in C#.
|
||||
|
||||
[GTest TAP Listener](https://github.com/kinow/gtest-tap-listener) is an event
|
||||
listener for Google Test that implements the
|
||||
[TAP protocol](https://en.wikipedia.org/wiki/Test_Anything_Protocol) for test
|
||||
result output. If your test runner understands TAP, you may find it useful.
|
||||
|
||||
[gtest-parallel](https://github.com/google/gtest-parallel) is a test runner that
|
||||
runs tests from your binary in parallel to provide significant speed-up.
|
||||
|
||||
[GoogleTest Adapter](https://marketplace.visualstudio.com/items?itemName=DavidSchuldenfrei.gtest-adapter)
|
||||
is a VS Code extension allowing to view Google Tests in a tree view, and
|
||||
run/debug your tests.
|
||||
|
||||
## Requirements
|
||||
|
||||
Google Test is designed to have fairly minimal requirements to build and use
|
||||
with your projects, but there are some. If you notice any problems on your
|
||||
platform, please notify
|
||||
[googletestframework@googlegroups.com](https://groups.google.com/forum/#!forum/googletestframework).
|
||||
Patches for fixing them are welcome!
|
||||
|
||||
### Build Requirements
|
||||
|
||||
These are the base requirements to build and use Google Test from a source
|
||||
package:
|
||||
|
||||
* [Bazel](https://bazel.build/) or [CMake](https://cmake.org/). NOTE: Bazel is
|
||||
the build system that googletest is using internally and tests against.
|
||||
CMake is community-supported.
|
||||
|
||||
* a C++11-standard-compliant compiler
|
||||
|
||||
## Contributing change
|
||||
|
||||
Please read the [`CONTRIBUTING.md`](CONTRIBUTING.md) for details on how to
|
||||
contribute to this project.
|
||||
|
||||
Happy testing!
|
23
test/gtest-1.10.0/WORKSPACE
Normal file
23
test/gtest-1.10.0/WORKSPACE
Normal file
@@ -0,0 +1,23 @@
|
||||
workspace(name = "com_google_googletest")
|
||||
|
||||
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
|
||||
|
||||
# Abseil
|
||||
http_archive(
|
||||
name = "com_google_absl",
|
||||
urls = ["https://github.com/abseil/abseil-cpp/archive/master.zip"],
|
||||
strip_prefix = "abseil-cpp-master",
|
||||
)
|
||||
|
||||
http_archive(
|
||||
name = "rules_cc",
|
||||
strip_prefix = "rules_cc-master",
|
||||
urls = ["https://github.com/bazelbuild/rules_cc/archive/master.zip"],
|
||||
)
|
||||
|
||||
http_archive(
|
||||
name = "rules_python",
|
||||
strip_prefix = "rules_python-master",
|
||||
urls = ["https://github.com/bazelbuild/rules_python/archive/master.zip"],
|
||||
)
|
||||
|
154
test/gtest-1.10.0/appveyor.yml
Normal file
154
test/gtest-1.10.0/appveyor.yml
Normal file
@@ -0,0 +1,154 @@
|
||||
version: '{build}'
|
||||
|
||||
os: Visual Studio 2015
|
||||
|
||||
environment:
|
||||
matrix:
|
||||
- compiler: msvc-15-seh
|
||||
generator: "Visual Studio 15 2017"
|
||||
build_system: cmake
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
|
||||
- compiler: msvc-15-seh
|
||||
generator: "Visual Studio 15 2017 Win64"
|
||||
build_system: cmake
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
enabled_on_pr: yes
|
||||
|
||||
- compiler: msvc-15-seh
|
||||
build_system: bazel
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
enabled_on_pr: yes
|
||||
|
||||
- compiler: msvc-14-seh
|
||||
build_system: cmake
|
||||
generator: "Visual Studio 14 2015"
|
||||
enabled_on_pr: yes
|
||||
|
||||
- compiler: msvc-14-seh
|
||||
build_system: cmake
|
||||
generator: "Visual Studio 14 2015 Win64"
|
||||
|
||||
- compiler: gcc-6.3.0-posix
|
||||
build_system: cmake
|
||||
generator: "MinGW Makefiles"
|
||||
cxx_path: 'C:\mingw-w64\i686-6.3.0-posix-dwarf-rt_v5-rev1\mingw32\bin'
|
||||
enabled_on_pr: yes
|
||||
|
||||
configuration:
|
||||
- Debug
|
||||
|
||||
build:
|
||||
verbosity: minimal
|
||||
|
||||
install:
|
||||
- ps: |
|
||||
Write-Output "Compiler: $env:compiler"
|
||||
Write-Output "Generator: $env:generator"
|
||||
Write-Output "Env:Configuation: $env:configuration"
|
||||
Write-Output "Env: $env"
|
||||
if (-not (Test-Path env:APPVEYOR_PULL_REQUEST_NUMBER)) {
|
||||
Write-Output "This is *NOT* a pull request build"
|
||||
} else {
|
||||
Write-Output "This is a pull request build"
|
||||
if (-not (Test-Path env:enabled_on_pr) -or $env:enabled_on_pr -ne "yes") {
|
||||
Write-Output "PR builds are *NOT* explicitly enabled"
|
||||
}
|
||||
}
|
||||
|
||||
# install Bazel
|
||||
if ($env:build_system -eq "bazel") {
|
||||
appveyor DownloadFile https://github.com/bazelbuild/bazel/releases/download/0.28.1/bazel-0.28.1-windows-x86_64.exe -FileName bazel.exe
|
||||
}
|
||||
|
||||
if ($env:build_system -eq "cmake") {
|
||||
# git bash conflicts with MinGW makefiles
|
||||
if ($env:generator -eq "MinGW Makefiles") {
|
||||
$env:path = $env:path.replace("C:\Program Files\Git\usr\bin;", "")
|
||||
if ($env:cxx_path -ne "") {
|
||||
$env:path += ";$env:cxx_path"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
before_build:
|
||||
- ps: |
|
||||
$env:root=$env:APPVEYOR_BUILD_FOLDER
|
||||
Write-Output "env:root: $env:root"
|
||||
|
||||
build_script:
|
||||
- ps: |
|
||||
# Only enable some builds for pull requests, the AppVeyor queue is too long.
|
||||
if ((Test-Path env:APPVEYOR_PULL_REQUEST_NUMBER) -And (-not (Test-Path env:enabled_on_pr) -or $env:enabled_on_pr -ne "yes")) {
|
||||
return
|
||||
} else {
|
||||
# special case - build with Bazel
|
||||
if ($env:build_system -eq "bazel") {
|
||||
& $env:root\bazel.exe build -c opt //:gtest_samples
|
||||
if ($LastExitCode -eq 0) { # bazel writes to StdErr and PowerShell interprets it as an error
|
||||
$host.SetShouldExit(0)
|
||||
} else { # a real error
|
||||
throw "Exec: $ErrorMessage"
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
# by default build with CMake
|
||||
md _build -Force | Out-Null
|
||||
cd _build
|
||||
|
||||
$conf = if ($env:generator -eq "MinGW Makefiles") {"-DCMAKE_BUILD_TYPE=$env:configuration"} else {"-DCMAKE_CONFIGURATION_TYPES=Debug;Release"}
|
||||
# Disable test for MinGW (gtest tests fail, gmock tests can not build)
|
||||
$gtest_build_tests = if ($env:generator -eq "MinGW Makefiles") {"-Dgtest_build_tests=OFF"} else {"-Dgtest_build_tests=ON"}
|
||||
$gmock_build_tests = if ($env:generator -eq "MinGW Makefiles") {"-Dgmock_build_tests=OFF"} else {"-Dgmock_build_tests=ON"}
|
||||
& cmake -G "$env:generator" $conf -Dgtest_build_samples=ON $gtest_build_tests $gmock_build_tests ..
|
||||
if ($LastExitCode -ne 0) {
|
||||
throw "Exec: $ErrorMessage"
|
||||
}
|
||||
$cmake_parallel = if ($env:generator -eq "MinGW Makefiles") {"-j2"} else {"/m"}
|
||||
& cmake --build . --config $env:configuration -- $cmake_parallel
|
||||
if ($LastExitCode -ne 0) {
|
||||
throw "Exec: $ErrorMessage"
|
||||
}
|
||||
|
||||
|
||||
skip_commits:
|
||||
files:
|
||||
- '**/*.md'
|
||||
|
||||
test_script:
|
||||
- ps: |
|
||||
# Only enable some builds for pull requests, the AppVeyor queue is too long.
|
||||
if ((Test-Path env:APPVEYOR_PULL_REQUEST_NUMBER) -And (-not (Test-Path env:enabled_on_pr) -or $env:enabled_on_pr -ne "yes")) {
|
||||
return
|
||||
}
|
||||
if ($env:build_system -eq "bazel") {
|
||||
# special case - testing with Bazel
|
||||
& $env:root\bazel.exe test //:gtest_samples
|
||||
if ($LastExitCode -eq 0) { # bazel writes to StdErr and PowerShell interprets it as an error
|
||||
$host.SetShouldExit(0)
|
||||
} else { # a real error
|
||||
throw "Exec: $ErrorMessage"
|
||||
}
|
||||
}
|
||||
if ($env:build_system -eq "cmake") {
|
||||
# built with CMake - test with CTest
|
||||
if ($env:generator -eq "MinGW Makefiles") {
|
||||
return # No test available for MinGW
|
||||
}
|
||||
|
||||
& ctest -C $env:configuration --timeout 600 --output-on-failure
|
||||
if ($LastExitCode -ne 0) {
|
||||
throw "Exec: $ErrorMessage"
|
||||
}
|
||||
}
|
||||
|
||||
artifacts:
|
||||
- path: '_build/CMakeFiles/*.log'
|
||||
name: logs
|
||||
- path: '_build/Testing/**/*.xml'
|
||||
name: test_results
|
||||
- path: 'bazel-testlogs/**/test.log'
|
||||
name: test_logs
|
||||
- path: 'bazel-testlogs/**/test.xml'
|
||||
name: test_results
|
37
test/gtest-1.10.0/ci/build-linux-bazel.sh
Normal file
37
test/gtest-1.10.0/ci/build-linux-bazel.sh
Normal file
@@ -0,0 +1,37 @@
|
||||
#!/usr/bin/env bash
|
||||
# Copyright 2017 Google Inc.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above
|
||||
# copyright notice, this list of conditions and the following disclaimer
|
||||
# in the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
# * Neither the name of Google Inc. nor the names of its
|
||||
# contributors may be used to endorse or promote products derived from
|
||||
# this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
set -e
|
||||
|
||||
bazel version
|
||||
bazel build --curses=no //...:all
|
||||
bazel test --curses=no //...:all
|
||||
bazel test --curses=no //...:all --define absl=1
|
2
test/gtest-1.10.0/ci/build-platformio.sh
Normal file
2
test/gtest-1.10.0/ci/build-platformio.sh
Normal file
@@ -0,0 +1,2 @@
|
||||
# run PlatformIO builds
|
||||
platformio run
|
41
test/gtest-1.10.0/ci/env-linux.sh
Normal file
41
test/gtest-1.10.0/ci/env-linux.sh
Normal file
@@ -0,0 +1,41 @@
|
||||
#!/usr/bin/env bash
|
||||
# Copyright 2017 Google Inc.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above
|
||||
# copyright notice, this list of conditions and the following disclaimer
|
||||
# in the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
# * Neither the name of Google Inc. nor the names of its
|
||||
# contributors may be used to endorse or promote products derived from
|
||||
# this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#
|
||||
# This file should be sourced, and not executed as a standalone script.
|
||||
#
|
||||
|
||||
# TODO() - we can check if this is being sourced using $BASH_VERSION and $BASH_SOURCE[0] != ${0}.
|
||||
|
||||
if [ "${TRAVIS_OS_NAME}" = "linux" ]; then
|
||||
if [ "$CXX" = "g++" ]; then export CXX="g++-4.9" CC="gcc-4.9"; fi
|
||||
if [ "$CXX" = "clang++" ]; then export CXX="clang++-3.9" CC="clang-3.9"; fi
|
||||
fi
|
@@ -1,7 +1,7 @@
|
||||
#!/bin/bash
|
||||
#!/usr/bin/env bash
|
||||
# Copyright 2017 Google Inc.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Copyright 2008, Google Inc.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
@@ -29,34 +29,19 @@
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
# Executes the samples and tests for the Google Test Framework.
|
||||
#
|
||||
# This file should be sourced, and not executed as a standalone script.
|
||||
#
|
||||
|
||||
# Help the dynamic linker find the path to the libraries.
|
||||
export DYLD_FRAMEWORK_PATH=$BUILT_PRODUCTS_DIR
|
||||
export DYLD_LIBRARY_PATH=$BUILT_PRODUCTS_DIR
|
||||
# TODO() - we can check if this is being sourced using $BASH_VERSION and $BASH_SOURCE[0] != ${0}.
|
||||
#
|
||||
|
||||
# Create some executables.
|
||||
test_executables=$@
|
||||
|
||||
# Now execute each one in turn keeping track of how many succeeded and failed.
|
||||
succeeded=0
|
||||
failed=0
|
||||
failed_list=()
|
||||
for test in ${test_executables[*]}; do
|
||||
"$test"
|
||||
result=$?
|
||||
if [ $result -eq 0 ]; then
|
||||
succeeded=$(( $succeeded + 1 ))
|
||||
else
|
||||
failed=$(( failed + 1 ))
|
||||
failed_list="$failed_list $test"
|
||||
fi
|
||||
done
|
||||
|
||||
# Report the successes and failures to the console.
|
||||
echo "Tests complete with $succeeded successes and $failed failures."
|
||||
if [ $failed -ne 0 ]; then
|
||||
echo "The following tests failed:"
|
||||
echo $failed_list
|
||||
if [ "${TRAVIS_OS_NAME}" = "osx" ]; then
|
||||
if [ "$CXX" = "clang++" ]; then
|
||||
# $PATH needs to be adjusted because the llvm tap doesn't install the
|
||||
# package to /usr/local/bin, etc, like the gcc tap does.
|
||||
# See: https://github.com/Homebrew/legacy-homebrew/issues/29733
|
||||
clang_version=3.9
|
||||
export PATH="/usr/local/opt/llvm@${clang_version}/bin:$PATH";
|
||||
fi
|
||||
fi
|
||||
exit $failed
|
48
test/gtest-1.10.0/ci/get-nprocessors.sh
Normal file
48
test/gtest-1.10.0/ci/get-nprocessors.sh
Normal file
@@ -0,0 +1,48 @@
|
||||
#!/usr/bin/env bash
|
||||
# Copyright 2017 Google Inc.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above
|
||||
# copyright notice, this list of conditions and the following disclaimer
|
||||
# in the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
# * Neither the name of Google Inc. nor the names of its
|
||||
# contributors may be used to endorse or promote products derived from
|
||||
# this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
# This file is typically sourced by another script.
|
||||
# if possible, ask for the precise number of processors,
|
||||
# otherwise take 2 processors as reasonable default; see
|
||||
# https://docs.travis-ci.com/user/speeding-up-the-build/#Makefile-optimization
|
||||
if [ -x /usr/bin/getconf ]; then
|
||||
NPROCESSORS=$(/usr/bin/getconf _NPROCESSORS_ONLN)
|
||||
else
|
||||
NPROCESSORS=2
|
||||
fi
|
||||
|
||||
# as of 2017-09-04 Travis CI reports 32 processors, but GCC build
|
||||
# crashes if parallelized too much (maybe memory consumption problem),
|
||||
# so limit to 4 processors for the time being.
|
||||
if [ $NPROCESSORS -gt 4 ] ; then
|
||||
echo "$0:Note: Limiting processors to use by make from $NPROCESSORS to 4."
|
||||
NPROCESSORS=4
|
||||
fi
|
49
test/gtest-1.10.0/ci/install-linux.sh
Normal file
49
test/gtest-1.10.0/ci/install-linux.sh
Normal file
@@ -0,0 +1,49 @@
|
||||
#!/usr/bin/env bash
|
||||
# Copyright 2017 Google Inc.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above
|
||||
# copyright notice, this list of conditions and the following disclaimer
|
||||
# in the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
# * Neither the name of Google Inc. nor the names of its
|
||||
# contributors may be used to endorse or promote products derived from
|
||||
# this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
set -eu
|
||||
|
||||
if [ "${TRAVIS_OS_NAME}" != linux ]; then
|
||||
echo "Not a Linux build; skipping installation"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
|
||||
if [ "${TRAVIS_SUDO}" = "true" ]; then
|
||||
echo "deb [arch=amd64] http://storage.googleapis.com/bazel-apt stable jdk1.8" | \
|
||||
sudo tee /etc/apt/sources.list.d/bazel.list
|
||||
curl https://bazel.build/bazel-release.pub.gpg | sudo apt-key add -
|
||||
sudo apt-get update && sudo apt-get install -y bazel gcc-4.9 g++-4.9 clang-3.9
|
||||
elif [ "${CXX}" = "clang++" ]; then
|
||||
# Use ccache, assuming $HOME/bin is in the path, which is true in the Travis build environment.
|
||||
ln -sf /usr/bin/ccache $HOME/bin/${CXX};
|
||||
ln -sf /usr/bin/ccache $HOME/bin/${CC};
|
||||
fi
|
40
test/gtest-1.10.0/ci/install-osx.sh
Normal file
40
test/gtest-1.10.0/ci/install-osx.sh
Normal file
@@ -0,0 +1,40 @@
|
||||
#!/usr/bin/env bash
|
||||
# Copyright 2017 Google Inc.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above
|
||||
# copyright notice, this list of conditions and the following disclaimer
|
||||
# in the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
# * Neither the name of Google Inc. nor the names of its
|
||||
# contributors may be used to endorse or promote products derived from
|
||||
# this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
set -eu
|
||||
|
||||
if [ "${TRAVIS_OS_NAME}" != "osx" ]; then
|
||||
echo "Not a macOS build; skipping installation"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
brew update
|
||||
brew install ccache gcc@4.9
|
5
test/gtest-1.10.0/ci/install-platformio.sh
Normal file
5
test/gtest-1.10.0/ci/install-platformio.sh
Normal file
@@ -0,0 +1,5 @@
|
||||
# install PlatformIO
|
||||
sudo pip install -U platformio
|
||||
|
||||
# update PlatformIO
|
||||
platformio update
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user