diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 581c559..a408a9d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -5,9 +5,11 @@ on: pull_request: branches: [ master ] workflow_dispatch: +permissions: read-all jobs: cmake-build: strategy: + fail-fast: false matrix: os: [ubuntu-latest, windows-latest, macos-latest] build: [static, shared] @@ -21,6 +23,7 @@ jobs: generator: "MinGW Makefiles" env: YAML_BUILD_SHARED_LIBS: ${{ matrix.build == 'shared' && 'ON' || 'OFF' }} + YAML_CPP_BUILD_TESTS: 'ON' CMAKE_GENERATOR: >- ${{format(matrix.generator != 'Default Generator' && '-G "{0}"' || '', matrix.generator)}} runs-on: ${{ matrix.os }} @@ -35,10 +38,17 @@ jobs: run: | cmake ${{ env.CMAKE_GENERATOR }} -S "${{ github.workspace }}" -B build -DYAML_BUILD_SHARED_LIBS=${{ env.YAML_BUILD_SHARED_LIBS }} cd build && cmake --build . --parallel ${{ steps.cpu-cores.outputs.count }} - - - name: Test + + - name: Build Tests shell: bash - run: cd build && ctest --output-on-failure + run: | + cmake ${{ env.CMAKE_GENERATOR }} -S "${{ github.workspace }}" -B build -DYAML_BUILD_SHARED_LIBS=${{ env.YAML_BUILD_SHARED_LIBS }} -DYAML_CPP_BUILD_TESTS=${{ env.YAML_CPP_BUILD_TESTS }} + cd build && cmake --build . --parallel ${{ steps.cpu-cores.outputs.count }} + + - name: Run Tests + shell: bash + run: | + cd build && ctest -C Debug --output-on-failure --verbose bazel-build: strategy: diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 46beb1d..0000000 --- a/.travis.yml +++ /dev/null @@ -1,37 +0,0 @@ -language: c++ - -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: - - cmake --build build - - cmake --build build --target test - -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 diff --git a/CMakeLists.txt b/CMakeLists.txt index afd5409..6ef6e8a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,27 +18,23 @@ include(CMakePackageConfigHelpers) include(CMakeDependentOption) include(CheckCXXCompilerFlag) include(GNUInstallDirs) +include(CTest) option(YAML_CPP_BUILD_CONTRIB "Enable yaml-cpp contrib in library" ON) option(YAML_CPP_BUILD_TOOLS "Enable parse tools" ON) option(YAML_BUILD_SHARED_LIBS "Build yaml-cpp shared library" ${BUILD_SHARED_LIBS}) option(YAML_CPP_INSTALL "Enable generation of yaml-cpp install targets" ${YAML_CPP_MAIN_PROJECT}) option(YAML_CPP_FORMAT_SOURCE "Format source" ON) - -if (YAML_CPP_BUILD_TESTS) - include(CTest) -endif() - -if (YAML_CPP_FORMAT_SOURCE) - find_program(YAML_CPP_CLANG_FORMAT_EXE NAMES clang-format) -endif() - cmake_dependent_option(YAML_CPP_BUILD_TESTS - "Enable yaml-cpp tests" ON - "BUILD_TESTING;CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR" OFF) + "Enable yaml-cpp tests" OFF + "BUILD_TESTING;YAML_CPP_MAIN_PROJECT" OFF) cmake_dependent_option(YAML_MSVC_SHARED_RT "MSVC: Build yaml-cpp with shared runtime libs (/MD)" ON "CMAKE_SYSTEM_NAME MATCHES Windows" OFF) + +if (YAML_CPP_FORMAT_SOURCE) + find_program(YAML_CPP_CLANG_FORMAT_EXE NAMES clang-format) +endif() if (YAML_BUILD_SHARED_LIBS) set(yaml-cpp-type SHARED) @@ -46,7 +42,6 @@ if (YAML_BUILD_SHARED_LIBS) else() set(yaml-cpp-type STATIC) set(yaml-cpp-label-postfix "static") - add_definitions(-DYAML_CPP_STATIC_DEFINE) endif() set(build-shared $) @@ -106,11 +101,15 @@ if (NOT DEFINED CMAKE_CXX_STANDARD) CXX_STANDARD 11) endif() +if(YAML_CPP_MAIN_PROJECT) + target_compile_options(yaml-cpp + PRIVATE + $<${not-msvc}:-Wall -Wextra -Wshadow -Weffc++ -Wno-long-long> + $<${not-msvc}:-pedantic -pedantic-errors>) +endif() + target_compile_options(yaml-cpp PRIVATE - $<${not-msvc}:-Wall -Wextra -Wshadow -Weffc++ -Wno-long-long> - $<${not-msvc}:-pedantic -pedantic-errors> - $<$:-MTd> $<$:-MT> $<$:-MDd> @@ -123,6 +122,8 @@ target_compile_options(yaml-cpp $<$:/W3 /wd4127 /wd4355>) target_compile_definitions(yaml-cpp + PUBLIC + $<$>:YAML_CPP_STATIC_DEFINE> PRIVATE $<${build-windows-dll}:${PROJECT_NAME}_DLL> $<$>:YAML_CPP_NO_CONTRIB>) @@ -142,15 +143,13 @@ set_target_properties(yaml-cpp PROPERTIES PROJECT_LABEL "yaml-cpp ${yaml-cpp-label-postfix}" DEBUG_POSTFIX "${CMAKE_DEBUG_POSTFIX}") -# FIXME(felix2012): A more common place for the cmake export would be -# `CMAKE_INSTALL_LIBDIR`, as e.g. done in ubuntu or in this project for GTest -set(CONFIG_EXPORT_DIR "${CMAKE_INSTALL_DATADIR}/cmake/yaml-cpp") +set(CONFIG_EXPORT_DIR "${CMAKE_INSTALL_LIBDIR}/cmake/yaml-cpp") set(EXPORT_TARGETS yaml-cpp) configure_package_config_file( "${PROJECT_SOURCE_DIR}/yaml-cpp-config.cmake.in" "${PROJECT_BINARY_DIR}/yaml-cpp-config.cmake" INSTALL_DESTINATION "${CONFIG_EXPORT_DIR}" - PATH_VARS CMAKE_INSTALL_INCLUDEDIR CONFIG_EXPORT_DIR) + PATH_VARS CMAKE_INSTALL_INCLUDEDIR CMAKE_INSTALL_LIBDIR CONFIG_EXPORT_DIR YAML_BUILD_SHARED_LIBS) unset(EXPORT_TARGETS) write_basic_package_version_file( @@ -175,7 +174,7 @@ if (YAML_CPP_INSTALL) "${PROJECT_BINARY_DIR}/yaml-cpp-config-version.cmake" DESTINATION "${CONFIG_EXPORT_DIR}") install(FILES "${PROJECT_BINARY_DIR}/yaml-cpp.pc" - DESTINATION ${CMAKE_INSTALL_DATADIR}/pkgconfig) + DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig) endif() unset(CONFIG_EXPORT_DIR) @@ -194,3 +193,14 @@ if (YAML_CPP_FORMAT_SOURCE AND YAML_CPP_CLANG_FORMAT_EXE) COMMENT "Running clang-format" VERBATIM) endif() + +# uninstall target +if(NOT TARGET uninstall) + configure_file( + "${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake.in" + "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" + IMMEDIATE @ONLY) + + add_custom_target(uninstall + COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake) +endif() diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index cd09a1a..5705fe2 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -17,7 +17,7 @@ Commit messages should be in the imperative mood, as described in the [Git contr # Tests -Please verify the tests pass by running the target `tests/run_tests`. +Please verify the tests pass by running the target `test/yaml-cpp-tests`. If you are adding functionality, add tests accordingly. diff --git a/appveyor.yml b/appveyor.yml deleted file mode 100644 index 54bcc80..0000000 --- a/appveyor.yml +++ /dev/null @@ -1,28 +0,0 @@ -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 diff --git a/cmake_uninstall.cmake.in b/cmake_uninstall.cmake.in new file mode 100644 index 0000000..c2d34d4 --- /dev/null +++ b/cmake_uninstall.cmake.in @@ -0,0 +1,21 @@ +if(NOT EXISTS "@CMAKE_BINARY_DIR@/install_manifest.txt") + message(FATAL_ERROR "Cannot find install manifest: @CMAKE_BINARY_DIR@/install_manifest.txt") +endif() + +file(READ "@CMAKE_BINARY_DIR@/install_manifest.txt" files) +string(REGEX REPLACE "\n" ";" files "${files}") +foreach(file ${files}) + message(STATUS "Uninstalling $ENV{DESTDIR}${file}") + if(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}") + exec_program( + "@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\"" + OUTPUT_VARIABLE rm_out + RETURN_VALUE rm_retval + ) + if(NOT "${rm_retval}" STREQUAL 0) + message(FATAL_ERROR "Problem when removing $ENV{DESTDIR}${file}") + endif() + else(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}") + message(STATUS "File $ENV{DESTDIR}${file} does not exist.") + endif() +endforeach() diff --git a/include/yaml-cpp/node/convert.h b/include/yaml-cpp/node/convert.h index 8ab0cd4..292c5d3 100644 --- a/include/yaml-cpp/node/convert.h +++ b/include/yaml-cpp/node/convert.h @@ -15,6 +15,7 @@ #include #include #include +#include #include #include "yaml-cpp/binary.h" @@ -363,6 +364,37 @@ struct convert> { } }; + +// std::valarray +template +struct convert> { + static Node encode(const std::valarray& rhs) { + Node node(NodeType::Sequence); + for (const auto& element : rhs) { + node.push_back(element); + } + return node; + } + + static bool decode(const Node& node, std::valarray& rhs) { + if (!node.IsSequence()) { + return false; + } + + rhs.resize(node.size()); + for (auto i = 0u; i < node.size(); ++i) { +#if defined(__GNUC__) && __GNUC__ < 4 + // workaround for GCC 3: + rhs[i] = node[i].template as(); +#else + rhs[i] = node[i].as(); +#endif + } + return true; + } +}; + + // std::pair template struct convert> { diff --git a/include/yaml-cpp/traits.h b/include/yaml-cpp/traits.h index 9a62db2..ffe9999 100644 --- a/include/yaml-cpp/traits.h +++ b/include/yaml-cpp/traits.h @@ -107,9 +107,9 @@ struct disable_if : public disable_if_c {}; template struct is_streamable { - template + template static auto test(int) - -> decltype(std::declval() << std::declval(), std::true_type()); + -> decltype(std::declval() << std::declval(), std::true_type()); template static auto test(...) -> std::false_type; diff --git a/src/emitter.cpp b/src/emitter.cpp index 6924bea..b0b730e 100644 --- a/src/emitter.cpp +++ b/src/emitter.cpp @@ -533,7 +533,8 @@ void Emitter::BlockMapPrepareNode(EmitterNodeType::value child) { if (m_pState->GetMapKeyFormat() == LongKey) m_pState->SetLongKey(); if (child == EmitterNodeType::BlockSeq || - child == EmitterNodeType::BlockMap) + child == EmitterNodeType::BlockMap || + child == EmitterNodeType::Property) m_pState->SetLongKey(); if (m_pState->CurGroupLongKey()) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 6735d35..351b03f 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -46,7 +46,7 @@ if (NOT DEFINED CMAKE_CXX_STANDARD) endif() -add_test(yaml-cpp::test yaml-cpp-tests) +add_test(NAME yaml-cpp::test COMMAND yaml-cpp-tests) if (build-windows-dll) add_custom_command( diff --git a/test/integration/emitter_test.cpp b/test/integration/emitter_test.cpp index 53407c9..b277d57 100644 --- a/test/integration/emitter_test.cpp +++ b/test/integration/emitter_test.cpp @@ -431,6 +431,38 @@ TEST_F(EmitterTest, BlockMapAsKey) { ExpectEmit("? key: value\n next key: next value\n: total value"); } +TEST_F(EmitterTest, TaggedBlockMapAsKey) { + out << BeginMap; + out << Key; + out << LocalTag("innerMap"); + out << BeginMap; + out << Key << "key" << Value << "value"; + out << EndMap; + out << Value; + out << "outerValue"; + out << EndMap; + + ExpectEmit(R"(? !innerMap + key: value +: outerValue)"); +} + +TEST_F(EmitterTest, TaggedBlockListAsKey) { + out << BeginMap; + out << Key; + out << LocalTag("innerList"); + out << BeginSeq; + out << "listItem"; + out << EndSeq; + out << Value; + out << "outerValue"; + out << EndMap; + + ExpectEmit(R"(? !innerList + - listItem +: outerValue)"); +} + TEST_F(EmitterTest, AliasAndAnchor) { out << BeginSeq; out << Anchor("fred"); @@ -520,7 +552,7 @@ TEST_F(EmitterTest, VerbatimTagInBlockMap) { out << Value << VerbatimTag("!waz") << "baz"; out << EndMap; - ExpectEmit("! bar: ! baz"); + ExpectEmit("? ! bar\n: ! baz"); } TEST_F(EmitterTest, VerbatimTagInFlowMap) { diff --git a/test/node/node_test.cpp b/test/node/node_test.cpp index d4367c5..ff3d799 100644 --- a/test/node/node_test.cpp +++ b/test/node/node_test.cpp @@ -323,6 +323,38 @@ TEST(NodeTest, IteratorOnConstUndefinedNode) { } EXPECT_EQ(0, count); } + +TEST(NodeTest, InteratorOnSequence) { + Node node; + node[0] = "a"; + node[1] = "b"; + node[2] = "c"; + EXPECT_TRUE(node.IsSequence()); + + std::size_t count = 0; + for (iterator it = node.begin(); it != node.end(); ++it) + { + EXPECT_FALSE(it->IsNull()); + count++; + } + EXPECT_EQ(3, count); +} + +TEST(NodeTest, ConstInteratorOnSequence) { + Node node; + node[0] = "a"; + node[1] = "b"; + node[2] = "c"; + EXPECT_TRUE(node.IsSequence()); + + std::size_t count = 0; + for (const_iterator it = node.begin(); it != node.end(); ++it) + { + EXPECT_FALSE(it->IsNull()); + count++; + } + EXPECT_EQ(3, count); +} TEST(NodeTest, SimpleSubkeys) { Node node; @@ -352,6 +384,16 @@ TEST(NodeTest, StdArrayWrongSize) { (node["evens"].as>()), ErrorMsg::BAD_CONVERSION); } +TEST(NodeTest, StdValrray) { + std::valarray evens{{2, 4, 6, 8, 10}}; + Node node; + node["evens"] = evens; + std::valarray actualEvens = node["evens"].as>(); + for (int i = 0; i < evens.size(); ++i) { + EXPECT_EQ(evens[i], actualEvens[i]); + } +} + TEST(NodeTest, StdVector) { std::vector primes; primes.push_back(2); diff --git a/yaml-cpp-config.cmake.in b/yaml-cpp-config.cmake.in index a7ace3d..799b9b4 100644 --- a/yaml-cpp-config.cmake.in +++ b/yaml-cpp-config.cmake.in @@ -1,11 +1,17 @@ # - Config file for the yaml-cpp package # It defines the following variables -# YAML_CPP_INCLUDE_DIR - include directory -# YAML_CPP_LIBRARIES - libraries to link against +# YAML_CPP_INCLUDE_DIR - include directory +# YAML_CPP_LIBRARY_DIR - directory containing libraries +# YAML_CPP_SHARED_LIBS_BUILT - whether we have built shared libraries or not +# YAML_CPP_LIBRARIES - libraries to link against @PACKAGE_INIT@ set_and_check(YAML_CPP_INCLUDE_DIR "@PACKAGE_CMAKE_INSTALL_INCLUDEDIR@") +set_and_check(YAML_CPP_LIBRARY_DIR "@PACKAGE_CMAKE_INSTALL_LIBDIR@") + +# Are we building shared libraries? +set(YAML_CPP_SHARED_LIBS_BUILT "@PACKAGE_YAML_BUILD_SHARED_LIBS@") # Our library dependencies (contains definitions for IMPORTED targets) include(@PACKAGE_CONFIG_EXPORT_DIR@/yaml-cpp-targets.cmake)