From 18779c70c36629a9d44bb3f5a92e6471a7a1f50b Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Fri, 4 Mar 2022 17:02:24 +0100 Subject: [PATCH 001/107] Use the windows-2019 image for VS 2019 CI windows-latest was moved to windows-2022 which does not have VS 2019 --- .github/workflows/ci_tests.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci_tests.yml b/.github/workflows/ci_tests.yml index 4a01dc37..ea55ccb1 100644 --- a/.github/workflows/ci_tests.yml +++ b/.github/workflows/ci_tests.yml @@ -1,4 +1,4 @@ -# Copyright 2019 - 2021 Alexander Grund +# Copyright 2019 - 2022 Alexander Grund # Distributed under the Boost Software License, Version 1.0. # (See accompanying file LICENSE or copy at http://boost.org/LICENSE_1_0.txt) @@ -28,7 +28,7 @@ jobs: shell: bash strategy: matrix: - os: [ubuntu-18.04, windows-latest] + os: [ubuntu-18.04, windows-2019] buildType: [Debug, Release] standalone: [Boost, Standalone] shared_lib: [ON, OFF] From df2ca9eee5a9377f96d32de25752db946ce7f97e Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Fri, 4 Mar 2022 17:38:39 +0100 Subject: [PATCH 002/107] Add test defining BOOST_USE_WINDOWS_H Also add test of this in combination with WIN32_LEAN_AND_MEAN. Checks for missing includes, such as shellapi.h --- test/CMakeLists.txt | 2 ++ test/Jamfile.v2 | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index de7fd653..5b34e3fb 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -50,6 +50,8 @@ boost_nowide_add_test(test_stdio) boost_nowide_add_test(test_system_n SRC test_system.cpp DEFINITIONS BOOST_NOWIDE_TEST_USE_NARROW=1) if(WIN32) boost_nowide_add_test(test_system_w SRC test_system.cpp DEFINITIONS BOOST_NOWIDE_TEST_USE_NARROW=0) + boost_nowide_add_test(test_system_use_windows_h SRC test_system.cpp DEFINITIONS BOOST_NOWIDE_TEST_USE_NARROW=0 BOOST_USE_WINDOWS_H) + boost_nowide_add_test(test_system_use_windows_h_lean SRC test_system.cpp DEFINITIONS BOOST_NOWIDE_TEST_USE_NARROW=0 BOOST_USE_WINDOWS_H WIN32_LEAN_AND_MEAN) else() foreach(test test_filebuf test_ifstream test_ofstream test_fstream test_fstream_special) boost_nowide_add_test(${test}_internal SRC ${test}.cpp DEFINITIONS BOOST_NOWIDE_USE_FILEBUF_REPLACEMENT=1 LIBRARIES boost_nowide_file_test_helpers) diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 718c999e..adb34c4b 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -64,7 +64,9 @@ run test_stackstring.cpp ; run test_stat.cpp ; run test_stdio.cpp ; run test_system.cpp : : : BOOST_NOWIDE_TEST_USE_NARROW=1 windows:shell32 darwin,shared:no : test_system_n ; -run test_system.cpp : : : BOOST_NOWIDE_TEST_USE_NARROW=0 windows:shell32 @require-windows : test_system_w ; +run test_system.cpp : : : BOOST_NOWIDE_TEST_USE_NARROW=0 shell32 @require-windows : test_system_w ; +run test_system.cpp : : : BOOST_NOWIDE_TEST_USE_NARROW=0 BOOST_USE_WINDOWS_H shell32 @require-windows : test_system_use_windows_h ; +run test_system.cpp : : : BOOST_NOWIDE_TEST_USE_NARROW=0 BOOST_USE_WINDOWS_H WIN32_LEAN_AND_MEAN shell32 @require-windows : test_system_use_windows_h_lean ; run test_traits.cpp : : : BOOST_NOWIDE_TEST_BFS_PATH /boost/filesystem//boost_filesystem/off ; compile benchmark_fstream.cpp : BOOST_NOWIDE_USE_WIN_FSTREAM=1 [ requires cxx11_hdr_chrono ] ; From b54d1c24b99255e8679d515fae24cb3014cc8e26 Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Fri, 4 Mar 2022 17:39:55 +0100 Subject: [PATCH 003/107] Protect test code against min/max macros --- test/test.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test.hpp b/test/test.hpp index 31dc7f56..b8ca5b48 100644 --- a/test/test.hpp +++ b/test/test.hpp @@ -72,7 +72,7 @@ namespace nowide { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wtautological-constant-out-of-range-compare" #endif - if(c >= std::numeric_limits::min() && c <= std::numeric_limits::max()) + if(c >= (std::numeric_limits::min)() && c <= (std::numeric_limits::max)()) ss << static_cast(c); else ss << "\\" << std::setw(sizeof(wchar_t) * 2) << static_cast(c) << std::setw(defWidth); From 365013b9fdf928414dfcad471b07e787a7d69609 Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Sun, 6 Mar 2022 12:36:22 +0100 Subject: [PATCH 004/107] Add missing include: shellapi.h CommandLineToArgvW is defined in shellapi.h not windows.h although the former is usually included by the latter unless e.g. WIN32_LEAN_AND_MEAN is defined. --- include/boost/nowide/windows.hpp | 15 +++++++++++---- test/test_system.cpp | 3 +-- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/include/boost/nowide/windows.hpp b/include/boost/nowide/windows.hpp index a5810be8..e7c37f4f 100644 --- a/include/boost/nowide/windows.hpp +++ b/include/boost/nowide/windows.hpp @@ -1,5 +1,6 @@ // // Copyright (c) 2012 Artyom Beilis (Tonkikh) +// Copyright (c) 2022 Alexander Grund // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE or copy at @@ -10,21 +11,27 @@ #ifdef BOOST_USE_WINDOWS_H #include +// (Usually) included by windows.h +#include #else -// -// These are function prototypes... Allow to avoid including windows.h -// +// When BOOST_USE_WINDOWS_H is not defined we declare the function prototypes to avoid including windows.h + extern "C" { +// From windows.h + __declspec(dllimport) wchar_t* __stdcall GetEnvironmentStringsW(void); __declspec(dllimport) int __stdcall FreeEnvironmentStringsW(wchar_t*); __declspec(dllimport) wchar_t* __stdcall GetCommandLineW(void); -__declspec(dllimport) wchar_t** __stdcall CommandLineToArgvW(const wchar_t*, int*); __declspec(dllimport) unsigned long __stdcall GetLastError(); __declspec(dllimport) void* __stdcall LocalFree(void*); __declspec(dllimport) int __stdcall SetEnvironmentVariableW(const wchar_t*, const wchar_t*); __declspec(dllimport) unsigned long __stdcall GetEnvironmentVariableW(const wchar_t*, wchar_t*, unsigned long); + +// From shellapi.h + +__declspec(dllimport) wchar_t** __stdcall CommandLineToArgvW(const wchar_t*, int*); } #endif diff --git a/test/test_system.cpp b/test/test_system.cpp index e003f0b1..170c74bd 100644 --- a/test/test_system.cpp +++ b/test/test_system.cpp @@ -9,9 +9,8 @@ #define _CRT_SECURE_NO_WARNINGS #endif -#include - #include +#include #include #include #include "test.hpp" From 40c8a79ba8cf2ceb7e3dcefe1cff36dab86a261f Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Thu, 3 Mar 2022 18:45:16 +0100 Subject: [PATCH 005/107] Sync GHA CI config with boostorg to include MSYS tests --- .github/workflows/ci.yml | 102 ++++++++++++++++++++++++++++++--- .github/workflows/ci_tests.yml | 3 + 2 files changed, 97 insertions(+), 8 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e0113d82..a6eacc7e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,10 +1,11 @@ # Copyright 2020-2021 Peter Dimov # Copyright 2021 Andrey Semashev # Copyright 2021 Alexander Grund +# Copyright 2022 James E. King III # # Distributed under the Boost Software License, Version 1.0. # (See accompanying file LICENSE_1_0.txt or copy at http://boost.org/LICENSE_1_0.txt) - +--- name: CI on: @@ -13,7 +14,10 @@ on: branches: - master - develop + - bugfix/** - feature/** + - fix/** + - pr/** concurrency: group: ${{format('{0}:{1}', github.repository, github.ref)}} @@ -66,13 +70,14 @@ jobs: - { compiler: clang-5.0, cxxstd: '03,11,14,1z', os: ubuntu-18.04 } - { compiler: clang-6.0, cxxstd: '03,11,14,17', os: ubuntu-18.04 } - { compiler: clang-7, cxxstd: '03,11,14,17', os: ubuntu-18.04 } - # Note: clang-8 does not fully support C++20, so it is not compatible with some libstdc++ versions in this mode + # Note: clang-8 does not fully support C++20, so it is not compatible with some libstdc++ versions in this mode - { compiler: clang-8, cxxstd: '03,11,14,17,2a', os: ubuntu-18.04, install: 'clang-8 g++-7', gcc_toolchain: 7 } - { compiler: clang-9, cxxstd: '03,11,14,17,2a', os: ubuntu-20.04 } - { compiler: clang-10, cxxstd: '03,11,14,17,20', os: ubuntu-20.04 } - { compiler: clang-11, cxxstd: '03,11,14,17,20', os: ubuntu-20.04 } - { compiler: clang-12, cxxstd: '03,11,14,17,20', os: ubuntu-20.04 } - # libc++ + + # libc++ - { compiler: clang-6.0, cxxstd: '03,11,14', os: ubuntu-18.04, stdlib: libc++, install: 'clang-6.0 libc++-dev libc++abi-dev' } - { compiler: clang-12, cxxstd: '03,11,14,17,20', os: ubuntu-20.04, stdlib: libc++, install: 'clang-12 libc++-12-dev libc++abi-12-dev' } - { name: Clang w/ sanitizers, sanitize: yes, @@ -96,23 +101,27 @@ jobs: if [ -n "${{matrix.container}}" ] && [ -f "/etc/debian_version" ]; then apt-get -o Acquire::Retries=$NET_RETRY_COUNT update apt-get -o Acquire::Retries=$NET_RETRY_COUNT install -y sudo software-properties-common - # Need (newer) git + # Need (newer) git, and the older Ubuntu container may require requesting the key manually using port 80 + apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys E1DD270288B4E6030699E45FA1715D88E1DF1F24 for i in {1..${NET_RETRY_COUNT:-3}}; do sudo -E add-apt-repository -y ppa:git-core/ppa && break || sleep 10; done apt-get -o Acquire::Retries=$NET_RETRY_COUNT update apt-get -o Acquire::Retries=$NET_RETRY_COUNT install -y g++ python libpython-dev git fi + # multiple job types are not compatible with ccache, they use "ccache: no" in the matrix + if [[ "${{ matrix.ccache }}" == "no" ]]; then + echo "B2_USE_CCACHE=0" >> $GITHUB_ENV + fi git config --global pack.threads 0 ! command -v cmake &> /dev/null || echo "B2_FLAGS=--nowide-enable-cmake" >> $GITHUB_ENV - uses: actions/checkout@v2 - if: '!matrix.coverage' - - uses: actions/checkout@v2 - if: 'matrix.coverage' with: - fetch-depth: 0 + # For coverage builds fetch the whole history, else only 1 commit using a 'fake ternary' + fetch-depth: ${{ matrix.coverage && '0' || '1' }} - name: Cache ccache uses: actions/cache@v2 + if: env.B2_USE_CCACHE with: path: ~/.ccache key: ${{matrix.os}}-${{matrix.container}}-${{matrix.compiler}} @@ -123,6 +132,7 @@ jobs: repository: boostorg/boost-ci ref: master path: boost-ci-cloned + - name: Get CI scripts folder run: | # Copy ci folder if not testing Boost.CI @@ -167,6 +177,18 @@ jobs: mkdir -p "$GCC_TOOLCHAIN_ROOT/lib/gcc/$MULTIARCH_TRIPLET" ln -s "/usr/lib/gcc/$MULTIARCH_TRIPLET/${{matrix.gcc_toolchain}}" "$GCC_TOOLCHAIN_ROOT/lib/gcc/$MULTIARCH_TRIPLET/${{matrix.gcc_toolchain}}" + - name: Setup multiarch + if: matrix.multiarch + run: | + sudo apt-get install --no-install-recommends -y binfmt-support qemu-user-static + sudo docker run --rm --privileged multiarch/qemu-user-static --reset -p yes + git clone https://github.com/jeking3/bdde.git + echo "$(pwd)/bdde/bin/linux" >> ${GITHUB_PATH} + echo "BDDE_DISTRO=${{ matrix.distro }}" >> ${GITHUB_ENV} + echo "BDDE_EDITION=${{ matrix.edition }}" >> ${GITHUB_ENV} + echo "BDDE_ARCH=${{ matrix.arch }}" >> ${GITHUB_ENV} + echo "B2_WRAPPER=bdde" >> ${GITHUB_ENV} + - name: Setup Boost env: B2_ADDRESS_MODEL: ${{matrix.address-model}} @@ -181,6 +203,7 @@ jobs: run: ci/github/codecov.sh "setup" - name: Run tests + if: '!matrix.coverity' run: ci/build.sh - name: Run tests with simulated no LFS support @@ -192,6 +215,69 @@ jobs: if: matrix.coverage run: ci/codecov.sh "upload" + - name: Run coverity + if: matrix.coverity && github.event_name == 'push' && (github.ref_name == 'develop' || github.ref_name == 'master') + run: ci/github/coverity.sh + env: + COVERITY_SCAN_NOTIFICATION_EMAIL: ${{ secrets.COVERITY_SCAN_NOTIFICATION_EMAIL }} + COVERITY_SCAN_TOKEN: ${{ secrets.COVERITY_SCAN_TOKEN }} + + MSYS2: + defaults: + run: + shell: msys2 {0} + strategy: + fail-fast: false + matrix: + include: + - { sys: MINGW32, compiler: gcc, cxxstd: '03,11,17,20' } + - { sys: MINGW64, compiler: gcc, cxxstd: '03,11,17,20' } + + runs-on: windows-latest + + steps: + - uses: actions/checkout@v2 + + - name: Setup MSYS2 environment + uses: msys2/setup-msys2@v2 + with: + msystem: ${{matrix.sys}} + update: true + install: git python + pacboy: gcc:p cmake:p ninja:p + + - name: Fetch Boost.CI + uses: actions/checkout@v2 + with: + repository: boostorg/boost-ci + ref: master + path: boost-ci-cloned + - name: Get CI scripts folder + run: | + # Copy ci folder if not testing Boost.CI + [[ "$GITHUB_REPOSITORY" =~ "boost-ci" ]] || cp -r boost-ci-cloned/ci . + rm -rf boost-ci-cloned + + - name: Setup Boost + env: + B2_COMPILER: ${{matrix.compiler}} + B2_CXXSTD: ${{matrix.cxxstd}} + B2_SANITIZE: ${{matrix.sanitize}} + B2_STDLIB: ${{matrix.stdlib}} + run: ci/github/install.sh + + - name: Run tests + run: ci/build.sh + + # Run also the CMake tests to avoid having to setup another matrix for CMake on MSYS + - name: Run CMake tests + run: | + cd "$BOOST_ROOT" + mkdir __build_cmake_test__ && cd __build_cmake_test__ + cmake -G Ninja -DCMAKE_BUILD_TYPE=Debug -DBOOST_INCLUDE_LIBRARIES=$SELF -DBUILD_SHARED_LIBS=ON -DBUILD_TESTING=ON -DBoost_VERBOSE=ON .. + cmake --build . --target tests --config Debug + ctest --output-on-failure --build-config Debug + CMake: defaults: run: diff --git a/.github/workflows/ci_tests.yml b/.github/workflows/ci_tests.yml index 4a01dc37..9ae459af 100644 --- a/.github/workflows/ci_tests.yml +++ b/.github/workflows/ci_tests.yml @@ -10,7 +10,10 @@ on: branches: - master - develop + - bugfix/** - feature/** + - fix/** + - pr/** concurrency: group: ${{format('ci_tests{0}:{1}', github.repository, github.ref)}} From 573b108ae62178bd590197d7fb22c097689c9299 Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Fri, 4 Mar 2022 17:02:24 +0100 Subject: [PATCH 006/107] Use the windows-2019 image for VS 2019 CI windows-latest was moved to windows-2022 which does not have VS 2019 --- .github/workflows/ci_tests.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci_tests.yml b/.github/workflows/ci_tests.yml index 9ae459af..28c3656c 100644 --- a/.github/workflows/ci_tests.yml +++ b/.github/workflows/ci_tests.yml @@ -1,4 +1,4 @@ -# Copyright 2019 - 2021 Alexander Grund +# Copyright 2019 - 2022 Alexander Grund # Distributed under the Boost Software License, Version 1.0. # (See accompanying file LICENSE or copy at http://boost.org/LICENSE_1_0.txt) @@ -31,7 +31,7 @@ jobs: shell: bash strategy: matrix: - os: [ubuntu-18.04, windows-latest] + os: [ubuntu-18.04, windows-2019] buildType: [Debug, Release] standalone: [Boost, Standalone] shared_lib: [ON, OFF] From ea13916d557564d6dc36f81f6725285ab9da5c8f Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Fri, 4 Mar 2022 12:18:27 +0100 Subject: [PATCH 007/107] Improve compatibility for recent Cygwin compilers Undefining __STRICT_ANSI__ to enable GNU extensions is no longer allowed. As on Cygwin the native/standard functions are used, we don't need the wide-API extension functions. Only remaining extensions used are the stdlib.h setenv functions, so enable those via the macro _GNU_SOURCE --- src/cstdio.cpp | 4 ++-- src/cstdlib.cpp | 7 +++++-- src/stat.cpp | 4 ++-- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/cstdio.cpp b/src/cstdio.cpp index 1e1672c6..684a0b68 100644 --- a/src/cstdio.cpp +++ b/src/cstdio.cpp @@ -11,8 +11,8 @@ #ifdef _MSC_VER #define _CRT_SECURE_NO_WARNINGS -#elif(defined(__MINGW32__) || defined(__CYGWIN__)) && defined(__STRICT_ANSI__) -// Need the _w* functions which are extensions on MinGW/Cygwin +#elif defined(__MINGW32__) && defined(__STRICT_ANSI__) +// Need the _w* functions which are extensions on MinGW #undef __STRICT_ANSI__ #endif diff --git a/src/cstdlib.cpp b/src/cstdlib.cpp index 067d389a..1cdc6194 100644 --- a/src/cstdlib.cpp +++ b/src/cstdlib.cpp @@ -11,9 +11,12 @@ #ifdef _MSC_VER #define _CRT_SECURE_NO_WARNINGS -#elif(defined(__MINGW32__) || defined(__CYGWIN__)) && defined(__STRICT_ANSI__) -// Need the _w* functions which are extensions on MinGW/Cygwin +#elif defined(__MINGW32__) && defined(__STRICT_ANSI__) +// Need the _w* functions which are extensions on MinGW #undef __STRICT_ANSI__ +#elif defined(__CYGWIN__) && !defined(_GNU_SOURCE) +// The setenv family of functions is an extension on Cygwin +#define _GNU_SOURCE 1 #endif #include diff --git a/src/stat.cpp b/src/stat.cpp index de1fa903..f9c0375a 100644 --- a/src/stat.cpp +++ b/src/stat.cpp @@ -7,8 +7,8 @@ #define BOOST_NOWIDE_SOURCE -#if(defined(__MINGW32__) || defined(__CYGWIN__)) && defined(__STRICT_ANSI__) -// Need the _w* functions which are extensions on MinGW/Cygwin +#if defined(__MINGW32__) && defined(__STRICT_ANSI__) +// Need the _w* functions which are extensions on MinGW #undef __STRICT_ANSI__ #endif From 85bcb2543523f96453e1f8299a7b919a1dadb3c2 Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Fri, 4 Mar 2022 16:29:21 +0100 Subject: [PATCH 008/107] Improve compatibility for recent MinGW-w64 compilers Undefining __STRICT_ANSI__ is no longer supported and is only required for the MinGW compilers, not the MinGW-w64 ones --- src/cstdio.cpp | 7 +++++-- src/cstdlib.cpp | 9 ++++++--- src/stat.cpp | 9 ++++++--- 3 files changed, 17 insertions(+), 8 deletions(-) diff --git a/src/cstdio.cpp b/src/cstdio.cpp index 684a0b68..d28ae52c 100644 --- a/src/cstdio.cpp +++ b/src/cstdio.cpp @@ -1,6 +1,6 @@ // // Copyright (c) 2012 Artyom Beilis (Tonkikh) -// Copyright (c) 2020 Alexander Grund +// Copyright (c) 2020-2022 Alexander Grund // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE or copy at @@ -12,9 +12,12 @@ #ifdef _MSC_VER #define _CRT_SECURE_NO_WARNINGS #elif defined(__MINGW32__) && defined(__STRICT_ANSI__) -// Need the _w* functions which are extensions on MinGW +// Need the _w* functions which are extensions on MinGW but not on MinGW-w64 +#include <_mingw.h> +#ifndef __MINGW64_VERSION_MAJOR #undef __STRICT_ANSI__ #endif +#endif #include #include diff --git a/src/cstdlib.cpp b/src/cstdlib.cpp index 1cdc6194..5a484374 100644 --- a/src/cstdlib.cpp +++ b/src/cstdlib.cpp @@ -1,6 +1,6 @@ // // Copyright (c) 2012 Artyom Beilis (Tonkikh) -// Copyright (c) 2020 Alexander Grund +// Copyright (c) 2020-2022 Alexander Grund // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE or copy at @@ -12,8 +12,11 @@ #ifdef _MSC_VER #define _CRT_SECURE_NO_WARNINGS #elif defined(__MINGW32__) && defined(__STRICT_ANSI__) -// Need the _w* functions which are extensions on MinGW +// Need the _w* functions which are extensions on MinGW but not on MinGW-w64 +#include <_mingw.h> +#ifndef __MINGW64_VERSION_MAJOR #undef __STRICT_ANSI__ +#endif #elif defined(__CYGWIN__) && !defined(_GNU_SOURCE) // The setenv family of functions is an extension on Cygwin #define _GNU_SOURCE 1 @@ -21,7 +24,7 @@ #include -#if !defined(BOOST_WINDOWS) +#ifndef BOOST_WINDOWS namespace boost { namespace nowide { int setenv(const char* key, const char* value, int overwrite) diff --git a/src/stat.cpp b/src/stat.cpp index f9c0375a..034d56ca 100644 --- a/src/stat.cpp +++ b/src/stat.cpp @@ -1,5 +1,5 @@ // -// Copyright (c) 2020 Alexander Grund +// Copyright (c) 2020-2022 Alexander Grund // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -8,13 +8,16 @@ #define BOOST_NOWIDE_SOURCE #if defined(__MINGW32__) && defined(__STRICT_ANSI__) -// Need the _w* functions which are extensions on MinGW +// Need the _w* functions which are extensions on MinGW but not on MinGW-w64 +#include <_mingw.h> +#ifndef __MINGW64_VERSION_MAJOR #undef __STRICT_ANSI__ #endif +#endif #include -#if defined(BOOST_WINDOWS) +#ifdef BOOST_WINDOWS #include #include From c675e5eb4725f71226feab7c889131b94cfde676 Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Fri, 4 Mar 2022 16:45:00 +0100 Subject: [PATCH 009/107] Add size-check to the stat_t-using stat function Same as for the posix_stat_t: Ensure that the definitions of that struct hasn't changed between compiling and using the library. --- include/boost/nowide/stat.hpp | 12 ++++++++---- src/stat.cpp | 15 ++++++++++----- test/test_stat.cpp | 4 ++++ 3 files changed, 22 insertions(+), 9 deletions(-) diff --git a/include/boost/nowide/stat.hpp b/include/boost/nowide/stat.hpp index 4a55401d..351a731b 100644 --- a/include/boost/nowide/stat.hpp +++ b/include/boost/nowide/stat.hpp @@ -29,8 +29,8 @@ namespace nowide { using ::stat; #else /// \brief Typedef for the file info structure. - /// Able to hold 64 bit filesize and timestamps on Windows and usually also on other 64 Bit systems - /// This allows to write portable code with option LFS support + /// Able to hold 64 bit file size and timestamps on Windows and usually also on other 64 Bit systems + /// This allows to write portable code with optional LFS support typedef struct ::__stat64 stat_t; /// \brief Typedef for the file info structure used in the POSIX stat call /// Resolves to `struct _stat` on Windows and `struct stat` otherwise @@ -39,8 +39,9 @@ namespace nowide { /// \cond INTERNAL namespace detail { + BOOST_NOWIDE_DECL int stat(const char* path, stat_t* buffer, size_t buffer_size); BOOST_NOWIDE_DECL int stat(const char* path, posix_stat_t* buffer, size_t buffer_size); - } + } // namespace detail /// \endcond /// @@ -48,7 +49,10 @@ namespace nowide { /// /// Return information about a file from an UTF-8 encoded path /// - BOOST_NOWIDE_DECL int stat(const char* path, stat_t* buffer); + inline int stat(const char* path, stat_t* buffer) + { + return detail::stat(path, buffer, sizeof(*buffer)); + } /// /// \brief UTF-8 aware stat function, returns 0 on success /// diff --git a/src/stat.cpp b/src/stat.cpp index 034d56ca..aac6f251 100644 --- a/src/stat.cpp +++ b/src/stat.cpp @@ -36,12 +36,17 @@ namespace nowide { const wstackstring wpath(path); return _wstat(wpath.get(), buffer); } + int stat(const char* path, stat_t* buffer, size_t buffer_size) + { + if(sizeof(*buffer) != buffer_size) + { + errno = EINVAL; + return EINVAL; + } + const wstackstring wpath(path); + return _wstat64(wpath.get(), buffer); + } } // namespace detail - int stat(const char* path, stat_t* buffer) - { - const wstackstring wpath(path); - return _wstat64(wpath.get(), buffer); - } } // namespace nowide } // namespace boost diff --git a/test/test_stat.cpp b/test/test_stat.cpp index 18430336..10acde0a 100644 --- a/test/test_stat.cpp +++ b/test/test_stat.cpp @@ -62,6 +62,10 @@ void test_main(int, char** argv, char**) // Need to use the detail function directly TEST_EQ(boost::nowide::detail::stat(filename.c_str(), &stdStat, sizeof(stdStat) - 4u), EINVAL); TEST_EQ(errno, EINVAL); + // Same for our stat_t + boost::nowide::stat_t boostStat; + TEST_EQ(boost::nowide::detail::stat(filename.c_str(), &boostStat, sizeof(boostStat) - 4u), EINVAL); + TEST_EQ(errno, EINVAL); } #endif From 9922eaae71ac8121a5b8a6d6ef59d143087bd897 Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Mon, 7 Mar 2022 16:37:26 +0100 Subject: [PATCH 010/107] Bump version to 11.1.4 and update docu --- CMakeLists.txt | 2 +- doc/changelog.dox | 13 +++++++++---- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e1d9d1e2..7ff52fe5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,7 +15,7 @@ cmake_minimum_required(VERSION 3.9) # Version number starts at 10 to avoid conflicts with Boost version -set(_version 11.1.3) +set(_version 11.1.4) if(BOOST_SUPERPROJECT_SOURCE_DIR) set(_version ${BOOST_SUPERPROJECT_VERSION}) endif() diff --git a/doc/changelog.dox b/doc/changelog.dox index 1b5627ea..7aabaf51 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -10,14 +10,19 @@ \section changelog Changelog -\subsection changelog_next Next release +\subsection changelog_11_1_4 Nowide 11.1.4 +- Fix possible redefinition of `_LARGEFILE_SOURCE` +- Fix missing include when `BOOST_USE_WINDOWS_H` and `WIN32_LEAN_AND_MEAN` are defined. +- Fix compile failures on recent MinGW-w64 compilers +- Add sanity checking of the buffer size passed to the (possibly) 64 bit `stat` function +- Known issues: Read performance for text files is possibly worse than the `std` streams. Binary files and writing is unaffected. -- Fix possible double-free when setting a custom buffer (`setbuf`) after filebuf already allocated an internal buffer -- Handle some warnings (mostly on MSVC) -\subsection changelog_11_1_3 Nowide 11.1.3 +\subsection changelog_11_1_3 Nowide 11.1.3 (Boost 1.78) - Fix missing config file in release +- Fix possible double-free when setting a custom buffer (`setbuf`) after filebuf already allocated an internal buffer +- Handle some warnings (mostly on MSVC) - Known issues: Read performance for text files is degraded. Binary files and writing is unaffected. \subsection changelog_11_1_2 Nowide 11.1.2 (Boost 1.76) From 8d259f16b3ec11d23835538f0656176487c5fe7d Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Tue, 8 Mar 2022 18:09:53 +0100 Subject: [PATCH 011/107] Enhance CTRL+Z iostream test Output random seed and progress indicator to be able to reproduce failures --- test/file_test_helpers.cpp | 10 +++++++++- test/test_iostream.cpp | 3 +++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/test/file_test_helpers.cpp b/test/file_test_helpers.cpp index 3835d4a3..36de84a3 100644 --- a/test/file_test_helpers.cpp +++ b/test/file_test_helpers.cpp @@ -10,6 +10,7 @@ #include #include "test.hpp" #include +#include #include #include #include @@ -76,9 +77,16 @@ namespace nowide { return result; } + static std::minstd_rand make_rand_engine() + { + const auto seed = std::random_device{}(); + std::cout << "RNG seed: " << seed << std::endl; + return std::minstd_rand(seed); + } + std::string create_random_data(size_t num_chars, data_type type) { - static std::minstd_rand rng(std::random_device{}()); + static std::minstd_rand rng = make_rand_engine(); std::string result(num_chars, '\0'); if(type == data_type::binary) { diff --git a/test/test_iostream.cpp b/test/test_iostream.cpp index 2b0e8233..ec84241e 100644 --- a/test/test_iostream.cpp +++ b/test/test_iostream.cpp @@ -349,13 +349,16 @@ void test_ctrl_z_is_eof() TEST_MOCKED(value == "Reached after clear()"); #ifndef BOOST_NOWIDE_TEST_INTERACTIVE // CTRL+Z anywhere else but at the start of a line does not matter + nw::cout << "CTRL+Z Test:"; for(int i = 1; i <= 1100; i++) { + nw::cout << '.' << std::flush; // Progress indicator const std::string expected = create_random_one_line_string(i) + "\x1a"; mock_buf.inputs.push(std::wstring(expected.begin(), expected.end()) + L"\r\n"); TEST(std::getline(nw::cin, value)); TEST_EQ(value, expected); } + nw::cout << std::endl; #endif } From 09f81674ecbdf256d4b64827b587d95d856c029a Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Tue, 8 Mar 2022 19:49:45 +0100 Subject: [PATCH 012/107] Docu update especially related to filesystem::path Mention `setlocale` to use an UTF-8 codepage on Windows. Refer to `u8path` and `u8string` functions for std::filesystem::path --- doc/main.dox | 14 ++++++++++++-- include/boost/nowide/filesystem.hpp | 4 +++- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/doc/main.dox b/doc/main.dox index 2d34c5f2..0b11cfca 100644 --- a/doc/main.dox +++ b/doc/main.dox @@ -143,6 +143,11 @@ Hence it is only usable if the targetted system is Windows 10 after May 2019. The second method relies on user interaction prior to starting the program. Obviously this is not reliable when expecting only UTF-8 in the code. +Also since Windows 10 1803 (i.e. since April 2018) it is possible to programmatically set the current code page to UTF-8 with e.g. `setlocale(LC_ALL, ".UTF8");`. +This makes many functions accept or produce UTF-8 encoded strings which is especially useful for `std::filesystem::path` and its `string()` function. +See the documentation for details. +While this works for most functions, it doesn't work for e.g. the program arguments (`argv` and `env` parameters of `main`). + Hence under some circumstances (and hopefully always somewhen in the future) this library will not be required and even Windows I/O can be used with UTF-8 encoded text. \subsection main_reading Further Reading @@ -255,7 +260,7 @@ The example above could be rewritten as: \code boost::nowide::basic_stackstring wexisting_file(existing_file), wnew_file(new_file); -CopyFileW(wexisting_file.c_str(),wnew_file.c_str(),TRUE); +CopyFileW(wexisting_file.c_str(), wnew_file.c_str(), TRUE); \endcode \note There are a few convenience typedefs: \c stackstring and \c wstackstring using @@ -276,12 +281,17 @@ Boost.Filesystem supports selection of narrow encoding. Unfortunatelly the default narrow encoding on Windows isn't UTF-8. But you can enable UTF-8 as default encoding on Boost.Filesystem by calling `boost::nowide::nowide_filesystem()` in the beginning of your program which -imbues a locale with a UTF-8 conversion facet to convert between \c char \c wchar_t. +imbues a locale with a UTF-8 conversion facet to convert between \c char and \c wchar_t. This interprets all narrow strings passed to and from \c boost::filesystem::path as UTF-8 when converting them to wide strings (as required for internal storage). On POSIX this has usually no effect, as no conversion is done due to narrow strings being used as the storage format. +For `std::filesystem::path` available since C++17 there is no way to imbue a locale. +However the `u8string()` member function can be used to obtain an UTF-8 encoded string from a `path`. +And to optain a `path` from an UTF-8 encoded string you may use `std::filesystem::u8path` +or since C++20 one of the `path` constructors taking a `char8_t`-type input. + \section technical Technical Details \subsection technical_imple Windows vs POSIX diff --git a/include/boost/nowide/filesystem.hpp b/include/boost/nowide/filesystem.hpp index 68e398d7..1df0c945 100644 --- a/include/boost/nowide/filesystem.hpp +++ b/include/boost/nowide/filesystem.hpp @@ -14,7 +14,9 @@ namespace boost { namespace nowide { /// - /// Install utf8_codecvt facet into boost::filesystem::path such all char strings are interpreted as utf-8 strings + /// Install utf8_codecvt facet into boost::filesystem::path + /// such that all char strings are interpreted as UTF-8 strings + /// \return The previous imbued path locale. /// inline std::locale nowide_filesystem() { From e82c2aced25f1ddb8196d3b7935b60f71998dfaa Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Wed, 9 Mar 2022 10:49:05 +0100 Subject: [PATCH 013/107] Use std::cout for test status data --- test/test_iostream.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/test/test_iostream.cpp b/test/test_iostream.cpp index ec84241e..d4200475 100644 --- a/test/test_iostream.cpp +++ b/test/test_iostream.cpp @@ -408,7 +408,7 @@ class RedirectStdio CONSOLE_SCREEN_BUFFER_INFO info; TEST(GetConsoleScreenBufferInfo(h, &info)); TEST(info.dwSize.X > 0 && info.dwSize.Y > 0); - nw::cout << "Mock console buffer size: " << info.dwSize.X << "x" << info.dwSize.Y << "\n"; + std::cout << "Mock console buffer size: " << info.dwSize.X << "x" << info.dwSize.Y << "\n"; std::wstring result; std::vector buffer(info.dwSize.X); @@ -426,7 +426,7 @@ class RedirectStdio return result; } - void setBufferData(std::wstring data, int) + void setBufferData(const std::wstring& data) { std::vector buffer; buffer.reserve(data.size() * 2 + 2); @@ -460,7 +460,7 @@ class RedirectStdio void test_console() { - // cin + std::cout << "Test cin console" << std::endl; { RedirectStdio stdinHandle(STD_INPUT_HANDLE); // Recreate to react on redirected streams @@ -468,14 +468,14 @@ void test_console() TEST(cin.rdbuf() != std::cin.rdbuf()); const std::string testStringIn1 = "Hello std in "; const std::string testStringIn2 = "\xc3\xa4 - \xc3\xb6 - \xc3\xbc - \xd0\xbc - \xce\xbd"; - stdinHandle.setBufferData(nw::widen(testStringIn1 + "\n" + testStringIn2 + "\n"), 0); + stdinHandle.setBufferData(nw::widen(testStringIn1 + "\n" + testStringIn2 + "\n")); std::string line; TEST(std::getline(cin, line)); TEST_EQ(line, testStringIn1); TEST(std::getline(cin, line)); TEST_EQ(line, testStringIn2); } - // cout + std::cout << "Test cout console" << std::endl; { RedirectStdio stdoutHandle(STD_OUTPUT_HANDLE); decltype(nw::cout) cout(true, nullptr); @@ -487,7 +487,7 @@ void test_console() const auto data = stdoutHandle.getBufferData(); TEST_EQ(data, nw::widen(testString)); } - // cerr + std::cout << "Test cerr console" << std::endl; { RedirectStdio stderrHandle(STD_ERROR_HANDLE); @@ -500,6 +500,7 @@ void test_console() const auto data = stderrHandle.getBufferData(); TEST_EQ(data, nw::widen(testString)); } + std::cout << "Console tests done" << std::endl; } #else From 5c46488d7aa41ef1a948ce1e396befa389404974 Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Wed, 9 Mar 2022 16:04:23 +0100 Subject: [PATCH 014/107] Add more status messages to test_iostream Help to debug random timeouts on Appveyor --- test/test_iostream.cpp | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/test/test_iostream.cpp b/test/test_iostream.cpp index d4200475..343d66f4 100644 --- a/test/test_iostream.cpp +++ b/test/test_iostream.cpp @@ -381,7 +381,13 @@ class RedirectStdio { if(handleType == STD_INPUT_HANDLE) { - h = CreateFile("CONIN$", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0); + h = CreateFile("CONIN$", + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + nullptr, + OPEN_EXISTING, + 0, + 0); } else { h = CreateConsoleScreenBuffer(GENERIC_READ | GENERIC_WRITE, @@ -460,19 +466,26 @@ class RedirectStdio void test_console() { - std::cout << "Test cin console" << std::endl; + std::cout << "Test cin console: " << std::flush; { RedirectStdio stdinHandle(STD_INPUT_HANDLE); + std::cout << "stdin redirected, " << std::flush; // Recreate to react on redirected streams decltype(nw::cin) cin(nullptr); + std::cout << "cin recreated " << std::flush; TEST(cin.rdbuf() != std::cin.rdbuf()); + std::cout << "and validated" << std::endl; const std::string testStringIn1 = "Hello std in "; const std::string testStringIn2 = "\xc3\xa4 - \xc3\xb6 - \xc3\xbc - \xd0\xbc - \xce\xbd"; + std::cout << "Setting mock buffer data" << std::endl; stdinHandle.setBufferData(nw::widen(testStringIn1 + "\n" + testStringIn2 + "\n")); + std::cout << "Done" << std::endl; std::string line; TEST(std::getline(cin, line)); + std::cout << "ASCII line read" << std::endl; TEST_EQ(line, testStringIn1); TEST(std::getline(cin, line)); + std::cout << "UTF-8 line read" << std::endl; TEST_EQ(line, testStringIn2); } std::cout << "Test cout console" << std::endl; From 2c446d16a5325cd49a68f5b6ef94ead9f1812e9c Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Wed, 9 Mar 2022 10:50:35 +0100 Subject: [PATCH 015/107] CI: Update checkout action to v3 --- .github/workflows/ci.yml | 12 ++++++------ .github/workflows/ci_tests.yml | 10 +++++----- .github/workflows/release.yml | 2 +- .github/workflows/update_standalone.yml | 2 +- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a6eacc7e..bef90b12 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -114,7 +114,7 @@ jobs: git config --global pack.threads 0 ! command -v cmake &> /dev/null || echo "B2_FLAGS=--nowide-enable-cmake" >> $GITHUB_ENV - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 with: # For coverage builds fetch the whole history, else only 1 commit using a 'fake ternary' fetch-depth: ${{ matrix.coverage && '0' || '1' }} @@ -127,7 +127,7 @@ jobs: key: ${{matrix.os}}-${{matrix.container}}-${{matrix.compiler}} - name: Fetch Boost.CI - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: repository: boostorg/boost-ci ref: master @@ -236,7 +236,7 @@ jobs: runs-on: windows-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Setup MSYS2 environment uses: msys2/setup-msys2@v2 @@ -247,7 +247,7 @@ jobs: pacboy: gcc:p cmake:p ninja:p - name: Fetch Boost.CI - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: repository: boostorg/boost-ci ref: master @@ -296,9 +296,9 @@ jobs: runs-on: ${{matrix.os}} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Fetch Boost.CI - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: repository: boostorg/boost-ci ref: master diff --git a/.github/workflows/ci_tests.yml b/.github/workflows/ci_tests.yml index 28c3656c..5b70f2d3 100644 --- a/.github/workflows/ci_tests.yml +++ b/.github/workflows/ci_tests.yml @@ -48,7 +48,7 @@ jobs: DEP_DIR: ${{github.workspace}}/dependencies BOOST_VERSION: 1.56.0 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Sanity check version run: grep -E 'set\(_version [0-9]' CMakeLists.txt - uses: actions/cache@v1 @@ -64,7 +64,7 @@ jobs: if: matrix.standalone == 'Boost' run: echo "BOOST_ROOT=${DEP_DIR//\\/\/}/boost_${BOOST_VERSION//./_}" >> $GITHUB_ENV # Install Boost - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 if: matrix.standalone == 'Boost' && steps.cache-boost.outputs.cache-hit != 'true' with: repository: boostorg/boost @@ -128,9 +128,9 @@ jobs: CreateBoostDocuTest: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Fetch Boost.CI - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: repository: boostorg/boost-ci ref: master @@ -147,7 +147,7 @@ jobs: CheckFormatting: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: DoozyX/clang-format-lint-action@v0.11 with: exclude: './doc' diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 53ceb83b..a0b253f0 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -18,7 +18,7 @@ jobs: DEP_DIR: ${{github.workspace}}/dependencies BOOST_VERSION: 1.56.0 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Extract tag name id: get_tag run: | diff --git a/.github/workflows/update_standalone.yml b/.github/workflows/update_standalone.yml index 6e4c45e7..b74a818d 100644 --- a/.github/workflows/update_standalone.yml +++ b/.github/workflows/update_standalone.yml @@ -16,7 +16,7 @@ jobs: name: Update standalone branch runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Setup git run: | git config --global user.email "$GITHUB_ACTOR@users.noreply.github.com" From 27de233d30852c105236f4f55961863c8ad061ab Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Wed, 9 Mar 2022 10:53:36 +0100 Subject: [PATCH 016/107] CI: Add VS 2022 CMake test --- .appveyor.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.appveyor.yml b/.appveyor.yml index a5c4f280..25280cc9 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -125,6 +125,11 @@ environment: GENERATOR: Visual Studio 16 2019 configuration: Debug BOOST_ROOT: C:\Libraries\boost_1_73_0 + - CMAKE: true + APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022 + GENERATOR: Visual Studio 17 2022 + configuration: Debug + BOOST_ROOT: C:\Libraries\boost_1_77_0 # Coverity - COVERITY: true From 1e6badc0c1a0929463187c560f238e0a7ef22caf Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Wed, 9 Mar 2022 18:53:59 +0100 Subject: [PATCH 017/107] CI: Remove Visual Studio 2019 CMake test The cin emulation in the test fails on this image. --- .appveyor.yml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index 25280cc9..8c11fd05 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -120,11 +120,6 @@ environment: GENERATOR: Visual Studio 14 2015 Win64 configuration: Debug BOOST_ROOT: C:\Libraries\boost_1_60_0 - - CMAKE: true - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 - GENERATOR: Visual Studio 16 2019 - configuration: Debug - BOOST_ROOT: C:\Libraries\boost_1_73_0 - CMAKE: true APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022 GENERATOR: Visual Studio 17 2022 From b88a6d599e1a27e85e40a601cc2c31534744fc04 Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Wed, 16 Mar 2022 17:24:30 +0100 Subject: [PATCH 018/107] Compile and run test_traits only once Combine the with and without Boost.Filesystem cases into 1 test --- test/CMakeLists.txt | 12 ++++++------ test/test_traits.cpp | 4 ++-- tools/create_standalone.sh | 1 + 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 5b34e3fb..d796ad7e 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -13,6 +13,10 @@ if(NOT TARGET tests) add_custom_target(tests) endif() +if(NOT BOOST_SUPERPROJECT_SOURCE_DIR) + find_package(Boost 1.56 REQUIRED COMPONENTS filesystem system) +endif() + function(boost_nowide_add_test name) cmake_parse_arguments(PARSE_ARGV 1 ARG "COMPILE_ONLY" "SRC" "LIBRARIES;DEFINITIONS;ARGS") if(NOT ARG_SRC) @@ -37,6 +41,7 @@ boost_nowide_add_test(test_codecvt) boost_nowide_add_test(test_convert) boost_nowide_add_test(test_env) boost_nowide_add_test(test_env_win SRC test_env.cpp DEFINITIONS BOOST_NOWIDE_TEST_INCLUDE_WINDOWS) +boost_nowide_add_test(test_fs LIBRARIES Boost::filesystem) boost_nowide_add_test(test_filebuf LIBRARIES boost_nowide_file_test_helpers) boost_nowide_add_test(test_ifstream LIBRARIES boost_nowide_file_test_helpers) boost_nowide_add_test(test_ofstream LIBRARIES boost_nowide_file_test_helpers) @@ -57,7 +62,7 @@ else() boost_nowide_add_test(${test}_internal SRC ${test}.cpp DEFINITIONS BOOST_NOWIDE_USE_FILEBUF_REPLACEMENT=1 LIBRARIES boost_nowide_file_test_helpers) endforeach() endif() -boost_nowide_add_test(test_traits) +boost_nowide_add_test(test_traits DEFINITIONS BOOST_NOWIDE_TEST_BFS_PATH LIBRARIES Boost::filesystem) # Test that passthrough writes everything from stdin to stdout # Needs to be done with CMake as the test driver to write any input to stdin and check output @@ -68,9 +73,4 @@ add_test( -P ${CMAKE_CURRENT_SOURCE_DIR}/test_iostream_passthrough.cmake ) -if(NOT BOOST_SUPERPROJECT_SOURCE_DIR) - find_package(Boost 1.56 REQUIRED COMPONENTS filesystem system) -endif() -boost_nowide_add_test(test_fs LIBRARIES Boost::filesystem) -boost_nowide_add_test(test_traits_fs SRC test_traits.cpp LIBRARIES Boost::filesystem DEFINITIONS BOOST_NOWIDE_TEST_BFS_PATH) boost_nowide_add_test(benchmark_fstream COMPILE_ONLY DEFINITIONS BOOST_NOWIDE_USE_FILEBUF_REPLACEMENT=1) diff --git a/test/test_traits.cpp b/test/test_traits.cpp index b2e0a2e3..09cae0c3 100644 --- a/test/test_traits.cpp +++ b/test/test_traits.cpp @@ -26,7 +26,7 @@ // Exclude apple as support there is target level specific -.- #if defined(__cpp_lib_filesystem) && !defined(__APPLE__) #include -#define BOOST_NOWIDE_TEST_SFS_PATH +#define BOOST_NOWIDE_TEST_STD_PATH #endif #ifdef BOOST_NOWIDE_TEST_BFS_PATH @@ -63,7 +63,7 @@ void test_main(int, char**, char**) static_assert(is_string_container::value, "!"); static_assert(is_string_container::value, "!"); #endif -#ifdef BOOST_NOWIDE_TEST_SFS_PATH +#ifdef BOOST_NOWIDE_TEST_STD_PATH std::cout << "Testing std::filesystem::path" << std::endl; static_assert(boost::nowide::detail::is_path::value, "!"); #endif diff --git a/tools/create_standalone.sh b/tools/create_standalone.sh index aa218780..b13c8948 100644 --- a/tools/create_standalone.sh +++ b/tools/create_standalone.sh @@ -63,6 +63,7 @@ sed '/^if(NOT BOOST_SUPERPROJECT_SOURCE_DIR)/,/^endif/{/^if/d;/^endif/d}' -i "$t sed 's/NAMESPACE Nowide CONFIG_FILE.*$/NAMESPACE nowide)/' -i "$targetFolder/CMakeLists.txt" sed '/^if(NOT BOOST_SUPERPROJECT_SOURCE_DIR)/,/^endif/d' -i "$targetFolder/test/CMakeLists.txt" +sed 's/ DEFINITIONS NOWIDE_TEST_BFS_PATH.*)/)/' -i "$targetFolder/test/CMakeLists.txt" sed '/Nowide::filesystem/d' -i "$targetFolder/test/CMakeLists.txt" sed '/^# Those 2 should work the same/,/^elseif/d' -i "$targetFolder/test/cmake_test/CMakeLists.txt" From d0c9fea797a3c6718aa98a3da692b955145dfaeb Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Wed, 16 Mar 2022 12:01:18 +0100 Subject: [PATCH 019/107] Add test reopening an ofstream after close() Based on code reported at #150 --- include/boost/nowide/filebuf.hpp | 1 + test/test_ofstream.cpp | 33 ++++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/include/boost/nowide/filebuf.hpp b/include/boost/nowide/filebuf.hpp index 44c7a513..909a0a01 100644 --- a/include/boost/nowide/filebuf.hpp +++ b/include/boost/nowide/filebuf.hpp @@ -235,6 +235,7 @@ namespace nowide { { if(std::fwrite(pbase(), 1, n, file_) != n) return EOF; + assert(buffer_); setp(buffer_, buffer_ + buffer_size_); if(c != EOF) { diff --git a/test/test_ofstream.cpp b/test/test_ofstream.cpp index 6d9f4c66..e5c0c826 100644 --- a/test/test_ofstream.cpp +++ b/test/test_ofstream.cpp @@ -170,6 +170,38 @@ void test_move_and_swap(const std::string& filename) TEST_EQ(read_file(filename2), "Foo Bar"); } +// Based on bug reported in #150 +void test_reopen(const std::string& filename) +{ + const std::string filename2 = filename + ".2"; + const std::string filename3 = filename + ".3"; + remove_file_at_exit _(filename); + remove_file_at_exit _2(filename2); + remove_file_at_exit _3(filename3); + + nw::ofstream f(filename, std::ios_base::binary); + using nw::test::data_type; + // Data sizes were randomly selected but above the usual default buffer size of 512 + const std::string testData = nw::test::create_random_data(613, data_type::binary); + TEST(f.write(testData.c_str(), testData.size())); + f.close(); + TEST_EQ(read_file(filename, data_type::binary), testData); + + // Reopen via open-function + f.open(filename2, std::ios_base::binary); + const std::string testData2 = nw::test::create_random_data(523, data_type::binary); + TEST(f.write(testData2.c_str(), testData2.size())); + f.close(); + TEST_EQ(read_file(filename2, data_type::binary), testData2); + + // Reopen via move-assign + f = nw::ofstream(filename3, std::ios_base::binary); + const std::string testData3 = nw::test::create_random_data(795, data_type::binary); + TEST(f.write(testData3.c_str(), testData3.size())); + f.close(); + TEST_EQ(read_file(filename3, data_type::binary), testData3); +} + // coverity [root_function] void test_main(int, char** argv, char**) { @@ -180,4 +212,5 @@ void test_main(int, char** argv, char**) test_open(exampleFilename.c_str()); test_open(exampleFilename); test_move_and_swap(exampleFilename); + test_reopen(exampleFilename); } From fe2c27917edd9337d7c3c26707bd0f822466b6f0 Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Wed, 16 Mar 2022 16:20:13 +0100 Subject: [PATCH 020/107] SetConsoleMode for StdIn in iostream integration test Some modes seem to be incompatible with certain CI environments, e.g. newer Appveyor images making test fail sometimes. Set a known "good" mode to avoid this. --- test/test_iostream.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/test_iostream.cpp b/test/test_iostream.cpp index 343d66f4..2486ebd4 100644 --- a/test/test_iostream.cpp +++ b/test/test_iostream.cpp @@ -398,7 +398,9 @@ class RedirectStdio } TEST(h != INVALID_HANDLE_VALUE); TEST(SetStdHandle(handleType, h)); - if(handleType != STD_INPUT_HANDLE) + if(handleType == STD_INPUT_HANDLE) + TEST(SetConsoleMode(h, ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT | ENABLE_EXTENDED_FLAGS)); + else TEST(SetConsoleActiveScreenBuffer(h)); } ~RedirectStdio() From dbb224a4abbe79ca8384afa6b675164504c0dad5 Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Wed, 16 Mar 2022 17:42:31 +0100 Subject: [PATCH 021/107] Add explicit CXX standard to Appveyor CMake tests This enables e.g. the std::filesystem::path traits test --- .appveyor.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index 8c11fd05..99c71617 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -117,11 +117,13 @@ environment: # CMake builds using preinstalled Boost - CMAKE: true APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 + CXXSTD: 14 GENERATOR: Visual Studio 14 2015 Win64 configuration: Debug BOOST_ROOT: C:\Libraries\boost_1_60_0 - CMAKE: true APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022 + CXXSTD: 17 GENERATOR: Visual Studio 17 2022 configuration: Debug BOOST_ROOT: C:\Libraries\boost_1_77_0 @@ -162,7 +164,7 @@ for: - if exist %INSTALL_DIR%\ (rmdir /S /Q %INSTALL_DIR%) - mkdir __build_cmake_test__ - cd __build_cmake_test__ - - cmake -G "%GENERATOR%" -DCMAKE_INSTALL_PREFIX=%INSTALL_DIR% .. + - cmake -G "%GENERATOR%" -DCMAKE_CXX_STANDARD=%CXXSTD% -DCMAKE_INSTALL_PREFIX=%INSTALL_DIR% .. build_script: cmake --build . --config %configuration% --parallel 4 test_script: - ctest --output-on-failure -C %configuration% --parallel 4 @@ -173,7 +175,7 @@ for: # Build consumer example test - cmake --build . --config %configuration% --target install - del /F /S /Q * - - cmake -DBOOST_NOWIDE_INSTALL_TEST=ON -G "%GENERATOR%" -DCMAKE_PREFIX_PATH=%APPVEYOR_BUILD_FOLDER%\installed ../test/cmake_test + - cmake -DBOOST_NOWIDE_INSTALL_TEST=ON -G "%GENERATOR%" -DCMAKE_CXX_STANDARD=%CXXSTD% -DCMAKE_PREFIX_PATH=%APPVEYOR_BUILD_FOLDER%\installed ../test/cmake_test - cmake --build . --config %configuration% - ctest --output-on-failure -C %configuration% --parallel 4 From b8cb76291dbec649b28235f3f77ff49ade9616c2 Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Thu, 17 Mar 2022 11:33:50 +0100 Subject: [PATCH 022/107] CI: Skip flaky test-part on affected Appveyor images Creating console input events fails sporadically on recent Appveyor images when using CMake/CTest. Add an option to disable that and use it for the recent Appveyor image --- .appveyor.yml | 6 ++++-- test/CMakeLists.txt | 6 ++++++ test/test_iostream.cpp | 2 ++ 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index 99c71617..1ac14278 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -124,6 +124,8 @@ environment: - CMAKE: true APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022 CXXSTD: 17 + # This test sometimes fails on recent images when using CMake + CXX_FLAGS: -DNOWIDE_DISABLE_CIN_TEST=ON GENERATOR: Visual Studio 17 2022 configuration: Debug BOOST_ROOT: C:\Libraries\boost_1_77_0 @@ -164,7 +166,7 @@ for: - if exist %INSTALL_DIR%\ (rmdir /S /Q %INSTALL_DIR%) - mkdir __build_cmake_test__ - cd __build_cmake_test__ - - cmake -G "%GENERATOR%" -DCMAKE_CXX_STANDARD=%CXXSTD% -DCMAKE_INSTALL_PREFIX=%INSTALL_DIR% .. + - cmake -G "%GENERATOR%" -DCMAKE_CXX_STANDARD=%CXXSTD% %CXX_FLAGS% -DCMAKE_INSTALL_PREFIX=%INSTALL_DIR% .. build_script: cmake --build . --config %configuration% --parallel 4 test_script: - ctest --output-on-failure -C %configuration% --parallel 4 @@ -175,7 +177,7 @@ for: # Build consumer example test - cmake --build . --config %configuration% --target install - del /F /S /Q * - - cmake -DBOOST_NOWIDE_INSTALL_TEST=ON -G "%GENERATOR%" -DCMAKE_CXX_STANDARD=%CXXSTD% -DCMAKE_PREFIX_PATH=%APPVEYOR_BUILD_FOLDER%\installed ../test/cmake_test + - cmake -DBOOST_NOWIDE_INSTALL_TEST=ON -G "%GENERATOR%" -DCMAKE_CXX_STANDARD=%CXXSTD% %CXX_FLAGS% -DCMAKE_PREFIX_PATH=%APPVEYOR_BUILD_FOLDER%\installed ../test/cmake_test - cmake --build . --config %configuration% - ctest --output-on-failure -C %configuration% --parallel 4 diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index d796ad7e..6f91fc2b 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -17,6 +17,9 @@ if(NOT BOOST_SUPERPROJECT_SOURCE_DIR) find_package(Boost 1.56 REQUIRED COMPONENTS filesystem system) endif() +# In some environments this test (part) may fail, so allow to disable it +option(BOOST_NOWIDE_DISABLE_CIN_TEST "Disable integration test using console input" OFF) + function(boost_nowide_add_test name) cmake_parse_arguments(PARSE_ARGV 1 ARG "COMPILE_ONLY" "SRC" "LIBRARIES;DEFINITIONS;ARGS") if(NOT ARG_SRC) @@ -48,6 +51,9 @@ boost_nowide_add_test(test_ofstream LIBRARIES boost_nowide_file_test_helpers) boost_nowide_add_test(test_fstream LIBRARIES boost_nowide_file_test_helpers) boost_nowide_add_test(test_fstream_special LIBRARIES boost_nowide_file_test_helpers) boost_nowide_add_test(test_iostream LIBRARIES boost_nowide_file_test_helpers) +if(BOOST_NOWIDE_DISABLE_CIN_TEST) + target_compile_definitions(${PROJECT_NAME}-test_iostream PRIVATE BOOST_NOWIDE_DISABLE_CIN_TEST) +endif() boost_nowide_add_test(test_iostream_interactive COMPILE_ONLY SRC test_iostream.cpp DEFINITIONS BOOST_NOWIDE_TEST_INTERACTIVE LIBRARIES boost_nowide_file_test_helpers) boost_nowide_add_test(test_stackstring) boost_nowide_add_test(test_stat) diff --git a/test/test_iostream.cpp b/test/test_iostream.cpp index 2486ebd4..5220b92c 100644 --- a/test/test_iostream.cpp +++ b/test/test_iostream.cpp @@ -468,6 +468,7 @@ class RedirectStdio void test_console() { +#ifndef BOOST_NOWIDE_DISABLE_CIN_TEST std::cout << "Test cin console: " << std::flush; { RedirectStdio stdinHandle(STD_INPUT_HANDLE); @@ -490,6 +491,7 @@ void test_console() std::cout << "UTF-8 line read" << std::endl; TEST_EQ(line, testStringIn2); } +#endif std::cout << "Test cout console" << std::endl; { RedirectStdio stdoutHandle(STD_OUTPUT_HANDLE); From 0987b8d7af20497893afc8c8745ebf30be0c24ce Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Thu, 17 Mar 2022 16:05:49 +0100 Subject: [PATCH 023/107] Consistently use nullptr instead of NULL/0 --- include/boost/nowide/args.hpp | 2 +- include/boost/nowide/filebuf.hpp | 53 +++++++++++----------------- include/boost/nowide/stackstring.hpp | 16 ++++----- include/boost/nowide/utf/convert.hpp | 2 +- test/test_fstream_special.cpp | 2 +- test/test_stackstring.cpp | 30 ++++++++-------- test/test_stdio.cpp | 4 +-- test/test_system.cpp | 4 +-- 8 files changed, 51 insertions(+), 62 deletions(-) diff --git a/include/boost/nowide/args.hpp b/include/boost/nowide/args.hpp index e11b72cf..3c7a47ce 100644 --- a/include/boost/nowide/args.hpp +++ b/include/boost/nowide/args.hpp @@ -113,7 +113,7 @@ namespace nowide { } operator bool() const { - return p != NULL; + return p != nullptr; } const wchar_t* operator[](size_t i) const { diff --git a/include/boost/nowide/filebuf.hpp b/include/boost/nowide/filebuf.hpp index 909a0a01..4011df5f 100644 --- a/include/boost/nowide/filebuf.hpp +++ b/include/boost/nowide/filebuf.hpp @@ -66,11 +66,11 @@ namespace nowide { /// Creates new filebuf /// basic_filebuf() : - buffer_size_(BUFSIZ), buffer_(0), file_(0), owns_buffer_(false), last_char_(), + buffer_size_(BUFSIZ), buffer_(nullptr), file_(nullptr), owns_buffer_(false), last_char_(), mode_(std::ios_base::openmode(0)) { - setg(0, 0, 0); - setp(0, 0); + setg(nullptr, nullptr, nullptr); + setp(nullptr, nullptr); } #ifdef BOOST_MSVC #pragma warning(pop) @@ -138,21 +138,21 @@ namespace nowide { basic_filebuf* open(const wchar_t* s, std::ios_base::openmode mode) { if(is_open()) - return NULL; + return nullptr; validate_cvt(this->getloc()); const bool ate = (mode & std::ios_base::ate) != 0; if(ate) mode &= ~std::ios_base::ate; const wchar_t* smode = get_mode(mode); if(!smode) - return 0; + return nullptr; file_ = detail::wfopen(s, smode); if(!file_) - return 0; + return nullptr; if(ate && detail::fseek(file_, 0, SEEK_END) != 0) { close(); - return 0; + return nullptr; } mode_ = mode; return this; @@ -163,28 +163,28 @@ namespace nowide { basic_filebuf* close() { if(!is_open()) - return NULL; + return nullptr; bool res = sync() == 0; if(std::fclose(file_) != 0) res = false; - file_ = NULL; + file_ = nullptr; mode_ = std::ios_base::openmode(0); if(owns_buffer_) { delete[] buffer_; - buffer_ = NULL; + buffer_ = nullptr; owns_buffer_ = false; } - setg(0, 0, 0); - setp(0, 0); - return res ? this : NULL; + setg(nullptr, nullptr, nullptr); + setp(nullptr, nullptr); + return res ? this : nullptr; } /// /// Same as std::filebuf::is_open() /// bool is_open() const { - return file_ != NULL; + return file_ != nullptr; } private: @@ -210,8 +210,8 @@ namespace nowide { assert(n >= 0); // Maximum compatibility: Discard all local buffers and use user-provided values // Users should call sync() before or better use it before any IO is done or any file is opened - setg(NULL, NULL, NULL); - setp(NULL, NULL); + setg(nullptr, nullptr, nullptr); + setp(nullptr, nullptr); if(owns_buffer_) { delete[] buffer_; @@ -368,13 +368,13 @@ namespace nowide { private: /// Stop reading adjusting the file pointer if necessary - /// Postcondition: gptr() == NULL + /// Postcondition: gptr() == nullptr bool stop_reading() { if(!gptr()) return true; const auto off = gptr() - egptr(); - setg(0, 0, 0); + setg(nullptr, nullptr, nullptr); if(!off) return true; #if defined(__clang__) @@ -391,31 +391,20 @@ namespace nowide { } /// Stop writing. If any bytes are to be written, writes them to file - /// Postcondition: pptr() == NULL + /// Postcondition: pptr() == nullptr bool stop_writing() { if(pptr()) { const char* const base = pbase(); const size_t n = pptr() - base; - setp(0, 0); + setp(nullptr, nullptr); if(n && std::fwrite(base, 1, n, file_) != n) return false; } return true; } - void reset(FILE* f = 0) - { - sync(); - if(file_) - { - fclose(file_); - file_ = 0; - } - file_ = f; - } - static const wchar_t* get_mode(std::ios_base::openmode mode) { // @@ -460,7 +449,7 @@ namespace nowide { return L"a+b"; if(mode == (std::ios_base::binary | std::ios_base::in | std::ios_base::app)) return L"a+b"; - return 0; + return nullptr; } size_t buffer_size_; diff --git a/include/boost/nowide/stackstring.hpp b/include/boost/nowide/stackstring.hpp index 129de78d..7dd336d0 100644 --- a/include/boost/nowide/stackstring.hpp +++ b/include/boost/nowide/stackstring.hpp @@ -26,7 +26,7 @@ namespace nowide { /// Invalid UTF characters are replaced by the substitution character, see #BOOST_NOWIDE_REPLACEMENT_CHARACTER /// /// If a NULL pointer is passed to the constructor or convert method, NULL will be returned by c_str. - /// Similarily a default constructed stackstring will return NULL on calling c_str. + /// Similarly a default constructed stackstring will return NULL on calling c_str. /// template class basic_stackstring @@ -40,24 +40,24 @@ namespace nowide { using input_char = CharIn; /// Creates a NULL stackstring - basic_stackstring() : data_(NULL) + basic_stackstring() { buffer_[0] = 0; } /// Convert the NULL terminated string input and store in internal buffer /// If input is NULL, nothing will be stored - explicit basic_stackstring(const input_char* input) : data_(NULL) + explicit basic_stackstring(const input_char* input) { convert(input); } /// Convert the sequence [begin, end) and store in internal buffer /// If begin is NULL, nothing will be stored - basic_stackstring(const input_char* begin, const input_char* end) : data_(NULL) + basic_stackstring(const input_char* begin, const input_char* end) { convert(begin, end); } /// Copy construct from other - basic_stackstring(const basic_stackstring& other) : data_(NULL) + basic_stackstring(const basic_stackstring& other) { *this = other; } @@ -74,7 +74,7 @@ namespace nowide { data_ = new output_char[len + 1]; else { - data_ = NULL; + data_ = nullptr; return *this; } std::memcpy(data_, other.data_, sizeof(output_char) * (len + 1)); @@ -138,7 +138,7 @@ namespace nowide { { if(!uses_stack_memory()) delete[] data_; - data_ = NULL; + data_ = nullptr; } /// Swap lhs with rhs friend void swap(basic_stackstring& lhs, basic_stackstring& rhs) @@ -186,7 +186,7 @@ namespace nowide { private: output_char buffer_[buffer_size]; - output_char* data_; + output_char* data_ = nullptr; }; // basic_stackstring /// diff --git a/include/boost/nowide/utf/convert.hpp b/include/boost/nowide/utf/convert.hpp index 242b7d12..ecd540de 100644 --- a/include/boost/nowide/utf/convert.hpp +++ b/include/boost/nowide/utf/convert.hpp @@ -56,7 +56,7 @@ namespace nowide { size_t width = utf_traits::width(c); if(buffer_size < width) { - rv = NULL; + rv = nullptr; break; } buffer = utf_traits::encode(c, buffer); diff --git a/test/test_fstream_special.cpp b/test/test_fstream_special.cpp index 03e22dbd..d3a15b5a 100644 --- a/test/test_fstream_special.cpp +++ b/test/test_fstream_special.cpp @@ -34,7 +34,7 @@ void test_with_different_buffer_sizes(const char* filepath) nw::fstream f; // Different conditions when setbuf might be called: Usually before opening a file is OK if(i >= 0) - f.rdbuf()->pubsetbuf((i == 0) ? NULL : buf, i); + f.rdbuf()->pubsetbuf((i == 0) ? nullptr : buf, i); f.open(filepath, std::ios::in | std::ios::out | std::ios::trunc | std::ios::binary); TEST(f); remove_file_at_exit _(filepath); diff --git a/test/test_stackstring.cpp b/test/test_stackstring.cpp index c0cd882b..0685db5e 100644 --- a/test/test_stackstring.cpp +++ b/test/test_stackstring.cpp @@ -72,25 +72,25 @@ void test_main(int, char**, char**) { std::cout << "-- Default constructed string is NULL" << std::endl; const boost::nowide::short_stackstring s; - TEST(s.get() == NULL); + TEST(s.get() == nullptr); } { - std::cout << "-- NULL ptr passed to ctor results in NULL" << std::endl; - const boost::nowide::short_stackstring s(NULL); - TEST(s.get() == NULL); - const boost::nowide::short_stackstring s2(NULL, NULL); - TEST(s2.get() == NULL); + std::cout << "-- nullptr passed to ctor results in NULL" << std::endl; + const boost::nowide::short_stackstring s(nullptr); + TEST(s.get() == nullptr); + const boost::nowide::short_stackstring s2(nullptr, nullptr); + TEST(s2.get() == nullptr); } { - std::cout << "-- NULL ptr passed to convert results in NULL" << std::endl; + std::cout << "-- nullptr passed to convert results in NULL" << std::endl; boost::nowide::short_stackstring s(L"foo"); TEST(s.get() == std::string("foo")); - s.convert(NULL); - TEST(s.get() == NULL); + s.convert(nullptr); + TEST(s.get() == nullptr); boost::nowide::short_stackstring s2(L"foo"); TEST(s2.get() == std::string("foo")); - s2.convert(NULL, NULL); - TEST(s2.get() == NULL); + s2.convert(nullptr, nullptr); + TEST(s2.get() == nullptr); } { std::cout << "-- An empty string is accepted" << std::endl; @@ -168,7 +168,7 @@ void test_main(int, char**, char**) TEST(sw3.get() == heapVal); // Assign empty sw3 = sEmpty; //-V820 - TEST(sw3.get() == NULL); + TEST(sw3.get() == nullptr); } { stackstring sw2(stack), sw3, sEmpty; @@ -180,7 +180,7 @@ void test_main(int, char**, char**) TEST(sw3.get() == stackVal); // Assign empty sw3 = sEmpty; //-V820 - TEST(sw3.get() == NULL); + TEST(sw3.get() == nullptr); } { stackstring sw2(stack); @@ -202,10 +202,10 @@ void test_main(int, char**, char**) TEST(sw3.get() == stackVal); swap(sw2, sEmpty1); TEST(sEmpty1.get() == heapVal); - TEST(sw2.get() == NULL); + TEST(sw2.get() == nullptr); swap(sw3, sEmpty2); TEST(sEmpty2.get() == stackVal); - TEST(sw3.get() == NULL); + TEST(sw3.get() == nullptr); } { stackstring sw2(heap), sw3(heap); diff --git a/test/test_stdio.cpp b/test/test_stdio.cpp index 95c35d57..aa775f59 100644 --- a/test/test_stdio.cpp +++ b/test/test_stdio.cpp @@ -80,7 +80,7 @@ void test_main(int, char** argv, char**) { boost::nowide::remove(filename.c_str()); TEST(!file_exists(filename)); - TEST(boost::nowide::fopen(filename.c_str(), "r") == NULL); + TEST(boost::nowide::fopen(filename.c_str(), "r") == nullptr); TEST(!file_exists(filename)); } std::cout << " -- freopen" << std::endl; @@ -99,7 +99,7 @@ void test_main(int, char** argv, char**) // Reopen in read mode // Note that changing the mode is not possibly on all implementations // E.g. MSVC disallows NULL completely as the file parameter - FILE* f2 = boost::nowide::freopen(NULL, "r", f); + FILE* f2 = boost::nowide::freopen(nullptr, "r", f); if(!f2) f2 = boost::nowide::freopen(filename.c_str(), "r", f); std::cout << " -- no write possible" << std::endl; diff --git a/test/test_system.cpp b/test/test_system.cpp index 170c74bd..d7eab437 100644 --- a/test/test_system.cpp +++ b/test/test_system.cpp @@ -95,12 +95,12 @@ void run_child(int argc, char** argv, char** env) // Test arguments TEST_EQ(argc, 2); TEST_EQ(argv[1], example); - TEST(argv[2] == NULL); + TEST(argv[2] == nullptr); // Test getenv TEST(boost::nowide::getenv("BOOST_NOWIDE_TEST")); TEST_EQ(boost::nowide::getenv("BOOST_NOWIDE_TEST"), example); - TEST(boost::nowide::getenv("BOOST_NOWIDE_TEST_NONE") == NULL); + TEST(!boost::nowide::getenv("BOOST_NOWIDE_TEST_NONE")); // Empty variables are unreliable on windows, hence skip. E.g. using "set FOO=" unsets FOO #ifndef BOOST_WINDOWS TEST(boost::nowide::getenv("BOOST_NOWIDE_EMPTY")); From 1f6e9600a9c78ec27f180f13d7ed3c2b001d37b0 Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Thu, 17 Mar 2022 19:01:45 +0100 Subject: [PATCH 024/107] Fix return value of sync() when fflush fails It incorrectly returned 0 instead of -1 --- include/boost/nowide/filebuf.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/nowide/filebuf.hpp b/include/boost/nowide/filebuf.hpp index 4011df5f..a695ba14 100644 --- a/include/boost/nowide/filebuf.hpp +++ b/include/boost/nowide/filebuf.hpp @@ -272,7 +272,7 @@ namespace nowide { result = overflow() != EOF; // Only flush if anything was written, otherwise behavior of fflush is undefined if(std::fflush(file_) != 0) - return result = false; + result = false; } else result = stop_reading(); return result ? 0 : -1; From df1591ca3ce1063e9b9a006da8ab3cd4abee022d Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Sat, 26 Mar 2022 11:30:27 +0100 Subject: [PATCH 025/107] Enable -Wundef warning on CI Find missing defines especially in standalone mode. See #152 --- .github/workflows/ci_tests.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci_tests.yml b/.github/workflows/ci_tests.yml index 5b70f2d3..d707372a 100644 --- a/.github/workflows/ci_tests.yml +++ b/.github/workflows/ci_tests.yml @@ -95,7 +95,13 @@ jobs: mkdir build - name: Configure working-directory: build - run: cmake -DBoost_DEBUG=ON -DCMAKE_BUILD_TYPE=${{matrix.buildType}} -DBUILD_SHARED_LIBS=${{matrix.shared_lib}} -DCMAKE_INSTALL_PREFIX=~/.local -G "${{matrix.generator}}" -DBoost_NO_BOOST_CMAKE=ON .. + run: | + extraFlags="-DBoost_DEBUG=ON -DBoost_NO_BOOST_CMAKE=ON -DCMAKE_INSTALL_PREFIX=~/.local" + if ! [[ "${{matrix.generator}}" =~ "Visual Studio" ]]; then + # Enable warning to find missing defines, especially important for the standalone version + extraFlags="$extraFlags -DCMAKE_CXX_FLAGS=-Wundef" + fi + cmake -DCMAKE_BUILD_TYPE=${{matrix.buildType}} -DBUILD_SHARED_LIBS=${{matrix.shared_lib}} -G "${{matrix.generator}}" $extraFlags .. - name: Build & Install run: cmake --build build --config ${{matrix.buildType}} --target install From 0a3db91f9804b98daf102c756d7c6949358618c3 Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Sat, 26 Mar 2022 11:40:47 +0100 Subject: [PATCH 026/107] Fix -Wundef warnings --- test/test_stdio.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/test_stdio.cpp b/test/test_stdio.cpp index aa775f59..1ca8c10c 100644 --- a/test/test_stdio.cpp +++ b/test/test_stdio.cpp @@ -43,7 +43,7 @@ void create_test_file(const std::string& filename) std::fclose(f); } -#if BOOST_MSVC +#ifdef BOOST_MSVC #include // For _CrtSetReportMode void noop_invalid_param_handler(const wchar_t*, const wchar_t*, const wchar_t*, unsigned, uintptr_t) {} // LCOV_EXCL_LINE @@ -54,7 +54,7 @@ void test_main(int, char** argv, char**) { const std::string prefix = argv[0]; const std::string filename = prefix + "\xd7\xa9-\xd0\xbc-\xce\xbd.txt"; -#if BOOST_MSVC +#ifdef BOOST_MSVC // Prevent abort on freopen(NULL, ...) _set_invalid_parameter_handler(noop_invalid_param_handler); #endif From a4f3cb816d025351ccf32142a5566cc207f97daa Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Sat, 26 Mar 2022 13:28:42 +0100 Subject: [PATCH 027/107] Generate standalone config.hpp from regular config.hpp To avoid that the standalong config.hpp becomes outdated, missing defines etc., the standalone/config.hpp is repurposed as a replacement for and basically pasted where that would be included in the nowide/config.hpp. Fixes the missing define as reported in #152. --- include/boost/nowide/config.hpp | 8 ++-- standalone/config.hpp | 67 +++++---------------------------- tools/create_standalone.sh | 18 ++++++++- 3 files changed, 29 insertions(+), 64 deletions(-) diff --git a/include/boost/nowide/config.hpp b/include/boost/nowide/config.hpp index be7dc611..3024fbad 100644 --- a/include/boost/nowide/config.hpp +++ b/include/boost/nowide/config.hpp @@ -1,6 +1,6 @@ // // Copyright (c) 2012 Artyom Beilis (Tonkikh) -// Copyright (c) 2019 - 2020 Alexander Grund +// Copyright (c) 2019 - 2022 Alexander Grund // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE or copy at @@ -27,9 +27,7 @@ #define BOOST_NOWIDE_DECL #endif // BOOST_NOWIDE_DYN_LINK -// // Automatically link to the correct build variant where possible. -// #if !defined(BOOST_ALL_NO_LIB) && !defined(BOOST_NOWIDE_NO_LIB) && !defined(BOOST_NOWIDE_SOURCE) // // Set the name of our library, this will get undef'ed by auto_link.hpp @@ -79,7 +77,7 @@ //! @cond Doxygen_Suppress -#if BOOST_VERSION < 106500 && defined(BOOST_GCC) && __GNUC__ >= 7 +#if BOOST_VERSION < 106500 && defined(__GNUC__) && __GNUC__ >= 7 #define BOOST_NOWIDE_FALLTHROUGH __attribute__((fallthrough)) #else #define BOOST_NOWIDE_FALLTHROUGH BOOST_FALLTHROUGH @@ -115,4 +113,4 @@ namespace boost { namespace nowide {} } // namespace boost -#endif // boost/nowide/config.hpp +#endif diff --git a/standalone/config.hpp b/standalone/config.hpp index 2800da02..bf3afac3 100644 --- a/standalone/config.hpp +++ b/standalone/config.hpp @@ -1,22 +1,19 @@ // // Copyright (c) 2012 Artyom Beilis (Tonkikh) -// Copyright (c) 2020 Alexander Grund +// Copyright (c) 2020 - 2022 Alexander Grund // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE or copy at // http://www.boost.org/LICENSE_1_0.txt) // -#ifndef NOWIDE_CONFIG_HPP_INCLUDED -#define NOWIDE_CONFIG_HPP_INCLUDED +// Defines macros which otherwise get defined by including -#include - -#if(defined(__WIN32) || defined(_WIN32) || defined(WIN32)) && !defined(__CYGWIN__) -#define NOWIDE_WINDOWS +#if(defined(_WIN32) || defined(__WIN32__) || defined(WIN32)) && !defined(__CYGWIN__) +#define BOOST_WINDOWS #endif #ifdef _MSC_VER -#define NOWIDE_MSVC _MSC_VER +#define BOOST_MSVC _MSC_VER #endif #ifdef __GNUC__ @@ -27,43 +24,17 @@ #define BOOST_SYMBOL_VISIBLE #endif -#ifdef NOWIDE_WINDOWS +#ifdef BOOST_WINDOWS #define BOOST_SYMBOL_EXPORT __declspec(dllexport) #define BOOST_SYMBOL_IMPORT __declspec(dllimport) +#elif defined(__CYGWIN__) && defined(__GNUC__) && (__GNUC__ >= 4) +#define BOOST_SYMBOL_EXPORT __attribute__((__dllexport__)) +#define BOOST_SYMBOL_IMPORT __attribute__((__dllimport__)) #else #define BOOST_SYMBOL_EXPORT BOOST_SYMBOL_VISIBLE #define BOOST_SYMBOL_IMPORT #endif -#if defined(BOOST_NOWIDE_DYN_LINK) -#ifdef BOOST_NOWIDE_SOURCE -#define BOOST_NOWIDE_DECL BOOST_SYMBOL_EXPORT -#else -#define BOOST_NOWIDE_DECL BOOST_SYMBOL_IMPORT -#endif // BOOST_NOWIDE_SOURCE -#else -#define BOOST_NOWIDE_DECL -#endif // BOOST_NOWIDE_DYN_LINK - -#ifndef NOWIDE_DECL -#define NOWIDE_DECL -#endif - -#if defined(NOWIDE_WINDOWS) -#ifdef BOOST_NOWIDE_USE_FILEBUF_REPLACEMENT -#undef BOOST_NOWIDE_USE_FILEBUF_REPLACEMENT -#endif -#define BOOST_NOWIDE_USE_FILEBUF_REPLACEMENT 1 -#elif !defined(BOOST_NOWIDE_USE_FILEBUF_REPLACEMENT) -#define BOOST_NOWIDE_USE_FILEBUF_REPLACEMENT 0 -#endif - -#if defined(__GNUC__) && __GNUC__ >= 7 -#define BOOST_NOWIDE_FALLTHROUGH __attribute__((fallthrough)) -#else -#define BOOST_NOWIDE_FALLTHROUGH -#endif - #if defined __GNUC__ #define BOOST_LIKELY(x) __builtin_expect(x, 1) #define BOOST_UNLIKELY(x) __builtin_expect(x, 0) @@ -75,23 +46,3 @@ #define BOOST_UNLIKELY(x) x #endif #endif - -// The std::codecvt are deprecated in C++20 -// These macros can suppress this warning -#if defined(_MSC_VER) -#define BOOST_NOWIDE_SUPPRESS_UTF_CODECVT_DEPRECATION_BEGIN __pragma(warning(push)) __pragma(warning(disable : 4996)) -#define BOOST_NOWIDE_SUPPRESS_UTF_CODECVT_DEPRECATION_END __pragma(warning(pop)) -#elif(__cplusplus >= 202002L) && defined(__clang__) -#define BOOST_NOWIDE_SUPPRESS_UTF_CODECVT_DEPRECATION_BEGIN \ - _Pragma("clang diagnostic push") _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"") -#define BOOST_NOWIDE_SUPPRESS_UTF_CODECVT_DEPRECATION_END _Pragma("clang diagnostic pop") -#elif(__cplusplus >= 202002L) && defined(__GNUC__) -#define BOOST_NOWIDE_SUPPRESS_UTF_CODECVT_DEPRECATION_BEGIN \ - _Pragma("GCC diagnostic push") _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") -#define BOOST_NOWIDE_SUPPRESS_UTF_CODECVT_DEPRECATION_END _Pragma("GCC diagnostic pop") -#else -#define BOOST_NOWIDE_SUPPRESS_UTF_CODECVT_DEPRECATION_BEGIN -#define BOOST_NOWIDE_SUPPRESS_UTF_CODECVT_DEPRECATION_END -#endif - -#endif diff --git a/tools/create_standalone.sh b/tools/create_standalone.sh index b13c8948..568df563 100644 --- a/tools/create_standalone.sh +++ b/tools/create_standalone.sh @@ -29,10 +29,26 @@ mkdir -p "$targetFolder"/include cp -r include/boost/nowide "$targetFolder"/include cp -r config src test cmake CMakeLists.txt LICENSE README.md "$targetFolder" -cp standalone/*.hpp "$targetFolder"/include/nowide mv "$targetFolder/cmake/BoostAddWarnings.cmake" "$targetFolder/cmake/NowideAddWarnings.cmake" find "$targetFolder" -name 'Jamfile*' -delete +# Stitch config header together +# Remove the boost headers, the important parts of config.hpp will be put in later +config_hpp="$targetFolder/include/nowide/config.hpp" +sed -E '//d' -i "$config_hpp" +# Put config replacement header below the doxygen marker +lineTarget=$(grep -m 1 -n '//! @cond Doxygen_Suppress' "$config_hpp" | cut -d ":" -f 1) +lineSrc=$(grep -n 'boost/config.hpp' "standalone/config.hpp" | cut -d ":" -f 1) # Skip the file header +{ head -n $lineTarget "$config_hpp"; tail -n +$((lineSrc+2)) standalone/config.hpp; tail -n +$((lineTarget+1)) "$config_hpp"; } > "$config_hpp".new +mv "$config_hpp".new "$config_hpp" +sed -e '/Automatically link/,/auto-linking disabled/d' \ + -e 's/defined(BOOST_ALL_DYN_LINK) || //' \ + -e '/namespace boost/d' \ + -e 's/ BOOST_FALLTHROUGH//' \ + -i "$config_hpp" +sed -E 's/BOOST_VERSION . [0-9]+ && //g' -i "$config_hpp" # Checks against BOOST_VERSION + + SOURCES=$(find "$targetFolder" -name '*.hpp' -or -name '*.cpp') SOURCES_NO_BOOST=$(echo "$SOURCES" | grep -v 'filesystem.hpp') From a906c3bf6dd830cf0847f98c13d4589168526328 Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Sat, 26 Mar 2022 15:01:36 +0100 Subject: [PATCH 028/107] Don't force using the custom filebuf (especially on Cygwin) For non-Windows platforms which includes Cygwin default the value of `BOOST_NOWIDE_USE_FILEBUF_REPLACEMENT` to that of `BOOST_NOWIDE_USE_WCHAR_OVERLOADS`. Also allow overwriting the value of `BOOST_NOWIDE_USE_WCHAR_OVERLOADS`. Especially with C++17 it may be useful to _not_ use the custom `filebuf`. Hence give users more control over this, although this risks ODR violations. --- include/boost/nowide/config.hpp | 20 ++++++++++++-------- include/boost/nowide/filebuf.hpp | 8 +++++--- include/boost/nowide/fstream.hpp | 4 +++- 3 files changed, 20 insertions(+), 12 deletions(-) diff --git a/include/boost/nowide/config.hpp b/include/boost/nowide/config.hpp index 3024fbad..f18e69b6 100644 --- a/include/boost/nowide/config.hpp +++ b/include/boost/nowide/config.hpp @@ -49,30 +49,34 @@ //! @endcond /// @def BOOST_NOWIDE_USE_WCHAR_OVERLOADS -/// @brief Whether to use the wchar_t* overloads in fstream/filebuf -/// Enabled on Windows and Cygwin as the latter may use wchar_t in filesystem::path -#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) +/// @brief Whether to use the wchar_t* overloads in fstream-classes. +/// +/// Enabled by default on Windows and Cygwin as the latter may use wchar_t in filesystem::path. +#ifndef BOOST_NOWIDE_USE_WCHAR_OVERLOADS +#if defined(BOOST_WINDOWS) || defined(__CYGWIN__) || defined(BOOST_NOWIDE_DOXYGEN) #define BOOST_NOWIDE_USE_WCHAR_OVERLOADS 1 #else #define BOOST_NOWIDE_USE_WCHAR_OVERLOADS 0 #endif +#endif /// @def BOOST_NOWIDE_USE_FILEBUF_REPLACEMENT -/// @brief Define to 1 to use internal class from filebuf.hpp +/// @brief Define to 1 to use the class from that is used on Windows. /// -/// - On Non-Windows platforms: Define to 1 to use the same class from header -/// that is used on Windows. /// - On Windows: No effect, always overwritten to 1 +/// - Others (including Cygwin): Defaults to the value of #BOOST_NOWIDE_USE_WCHAR_OVERLOADS if not set. +/// +/// When set to 0 boost::nowide::basic_filebuf will be an alias for std::basic_filebuf. /// /// Affects boost::nowide::basic_filebuf, /// boost::nowide::basic_ofstream, boost::nowide::basic_ifstream, boost::nowide::basic_fstream -#if defined(BOOST_WINDOWS) || BOOST_NOWIDE_USE_WCHAR_OVERLOADS +#if defined(BOOST_WINDOWS) || defined(BOOST_NOWIDE_DOXYGEN) #ifdef BOOST_NOWIDE_USE_FILEBUF_REPLACEMENT #undef BOOST_NOWIDE_USE_FILEBUF_REPLACEMENT #endif #define BOOST_NOWIDE_USE_FILEBUF_REPLACEMENT 1 #elif !defined(BOOST_NOWIDE_USE_FILEBUF_REPLACEMENT) -#define BOOST_NOWIDE_USE_FILEBUF_REPLACEMENT 0 +#define BOOST_NOWIDE_USE_FILEBUF_REPLACEMENT BOOST_NOWIDE_USE_WCHAR_OVERLOADS #endif //! @cond Doxygen_Suppress diff --git a/include/boost/nowide/filebuf.hpp b/include/boost/nowide/filebuf.hpp index a695ba14..1ff66f5e 100644 --- a/include/boost/nowide/filebuf.hpp +++ b/include/boost/nowide/filebuf.hpp @@ -38,9 +38,10 @@ namespace nowide { using std::filebuf; #else // Windows /// - /// \brief This forward declaration defines the basic_filebuf type. + /// \brief This forward declaration defines the basic_filebuf type + /// which is used when #BOOST_NOWIDE_USE_FILEBUF_REPLACEMENT is set, e.g. on Windows. /// - /// it is implemented and specialized for CharType = char, it + /// It is implemented and specialized for CharType = char, it /// implements std::filebuf over standard C I/O /// template> @@ -48,8 +49,9 @@ namespace nowide { /// /// \brief This is the implementation of std::filebuf + /// which is used when #BOOST_NOWIDE_USE_FILEBUF_REPLACEMENT is set, e.g. on Windows. /// - /// it is implemented and specialized for CharType = char, it + /// It is implemented and specialized for CharType = char, it /// implements std::filebuf over standard C I/O /// template<> diff --git a/include/boost/nowide/fstream.hpp b/include/boost/nowide/fstream.hpp index ca946f31..1829ff42 100644 --- a/include/boost/nowide/fstream.hpp +++ b/include/boost/nowide/fstream.hpp @@ -68,6 +68,7 @@ namespace nowide { /// /// \brief Same as std::basic_ifstream but accepts UTF-8 strings under Windows /// + /// Affected by #BOOST_NOWIDE_USE_FILEBUF_REPLACEMENT and #BOOST_NOWIDE_USE_WCHAR_OVERLOADS template> class basic_ifstream : public detail::fstream_impl { @@ -118,7 +119,7 @@ namespace nowide { /// /// \brief Same as std::basic_ofstream but accepts UTF-8 strings under Windows /// - + /// Affected by #BOOST_NOWIDE_USE_FILEBUF_REPLACEMENT and #BOOST_NOWIDE_USE_WCHAR_OVERLOADS template> class basic_ofstream : public detail::fstream_impl { @@ -171,6 +172,7 @@ namespace nowide { /// /// \brief Same as std::basic_fstream but accepts UTF-8 strings under Windows /// + /// Affected by #BOOST_NOWIDE_USE_FILEBUF_REPLACEMENT and #BOOST_NOWIDE_USE_WCHAR_OVERLOADS template> class basic_fstream : public detail::fstream_impl { From 9acb7854997fa56efecaf34f2d642161b8626e47 Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Mon, 21 Mar 2022 17:23:06 +0100 Subject: [PATCH 029/107] Reenable fstream benchmark code Was accidentally left commented out --- test/benchmark_fstream.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/test/benchmark_fstream.cpp b/test/benchmark_fstream.cpp index 0acf7081..5e8d6c2d 100644 --- a/test/benchmark_fstream.cpp +++ b/test/benchmark_fstream.cpp @@ -249,8 +249,6 @@ void print_perf_data(const blocksize_to_performance& stdio_data, void test_perf(const char* file) { - perf_data nowide_data_txt2 = test_io_driver>(file, "std::fstream", false); - /* perf_data stdio_data = test_io_driver(file, "stdio", true); perf_data std_data = test_io_driver>(file, "std::fstream", true); perf_data nowide_data = test_io_driver>(file, "nowide::fstream", true); @@ -265,7 +263,6 @@ void test_perf(const char* file) print_perf_data(stdio_data_txt.read, std_data_txt.read, nowide_data_txt.read); std::cout << "================== Write performance (text) ===================" << std::endl; print_perf_data(stdio_data_txt.write, std_data_txt.write, nowide_data_txt.write); - */ } int main(int argc, char** argv) From c28aef3213f400bab268c5305bd8426cdd74840d Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Mon, 21 Mar 2022 19:22:12 +0100 Subject: [PATCH 030/107] Fix sign confusion in filebuf sanity check The offset in stop_reading is the *negated* amount of chars left in the read buffer which yields the seek offset. So compare against the min-value. --- include/boost/nowide/filebuf.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/nowide/filebuf.hpp b/include/boost/nowide/filebuf.hpp index 1ff66f5e..4d63ed86 100644 --- a/include/boost/nowide/filebuf.hpp +++ b/include/boost/nowide/filebuf.hpp @@ -384,7 +384,7 @@ namespace nowide { #pragma clang diagnostic ignored "-Wtautological-constant-out-of-range-compare" #endif // coverity[result_independent_of_operands] - if(off > std::numeric_limits::max()) + if(off < std::numeric_limits::min()) return false; #if defined(__clang__) #pragma clang diagnostic pop From 4cea2fff0c446b5f88a992e06d108855d2f35753 Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Mon, 23 May 2022 17:06:22 +0200 Subject: [PATCH 031/107] Fix MSYS2 builds --- test/test_system.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/test_system.cpp b/test/test_system.cpp index d7eab437..70c1dc4f 100644 --- a/test/test_system.cpp +++ b/test/test_system.cpp @@ -120,10 +120,10 @@ void run_child(int argc, char** argv, char** env) std::cout << "Subprocess ok" << std::endl; } -void run_parent(const char* exe_path) +void run_parent(const std::string& exe_path) { TEST(boost::nowide::system(nullptr) != 0); - const std::string command = "\"" + std::string(exe_path) + "\" " + example; + const std::string command = "\"" + exe_path + "\" " + example; #if BOOST_NOWIDE_TEST_USE_NARROW TEST_EQ(boost::nowide::setenv("BOOST_NOWIDE_TEST", example.c_str(), 1), 0); TEST_EQ(boost::nowide::setenv("BOOST_NOWIDE_TEST_NONE", example.c_str(), 1), 0); From 206cb43340a4500ee05d346bb0d1ad9a99cb6f10 Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Mon, 23 May 2022 17:06:22 +0200 Subject: [PATCH 032/107] Fix MSYS2 builds --- test/test_codecvt.cpp | 4 ++-- test/test_system.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/test/test_codecvt.cpp b/test/test_codecvt.cpp index a793299a..8f5e8751 100644 --- a/test/test_codecvt.cpp +++ b/test/test_codecvt.cpp @@ -334,7 +334,7 @@ void test_codecvt_err() char* to = buf; char* to_end = buf + 32; char* to_next = to; - wchar_t err_buf[3] = {'1', 0xDC9E, 0}; // second surrogate not works both for UTF-16 and 32 + wchar_t err_buf[] = {'1', 0xDC9E, 0}; // second value is invalid for UTF-16 and 32 const wchar_t* err_utf = err_buf; { std::mbstate_t mb{}; @@ -344,7 +344,7 @@ void test_codecvt_err() TEST_EQ(cvt.out(mb, from, from_end, from_next, to, to_end, to_next), cvt_type::ok); TEST(from_next == from + 2); TEST(to_next == to + 4); - TEST_EQ(std::string(to, to_next), "1" + boost::nowide::narrow(wreplacement_str)); + TEST_EQ(std::string(to, to_next), boost::nowide::narrow(err_buf)); } } } diff --git a/test/test_system.cpp b/test/test_system.cpp index d7eab437..70c1dc4f 100644 --- a/test/test_system.cpp +++ b/test/test_system.cpp @@ -120,10 +120,10 @@ void run_child(int argc, char** argv, char** env) std::cout << "Subprocess ok" << std::endl; } -void run_parent(const char* exe_path) +void run_parent(const std::string& exe_path) { TEST(boost::nowide::system(nullptr) != 0); - const std::string command = "\"" + std::string(exe_path) + "\" " + example; + const std::string command = "\"" + exe_path + "\" " + example; #if BOOST_NOWIDE_TEST_USE_NARROW TEST_EQ(boost::nowide::setenv("BOOST_NOWIDE_TEST", example.c_str(), 1), 0); TEST_EQ(boost::nowide::setenv("BOOST_NOWIDE_TEST_NONE", example.c_str(), 1), 0); From 506e899b2ed9bbd108fbf3f15910d877c54fb11a Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Tue, 22 Mar 2022 14:35:27 +0100 Subject: [PATCH 033/107] Tests: Add TEST_CONTEXT --- test/test.hpp | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/test/test.hpp b/test/test.hpp index b8ca5b48..9bc88524 100644 --- a/test/test.hpp +++ b/test/test.hpp @@ -42,17 +42,33 @@ namespace nowide { _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR); #endif } + std::string context; }; inline test_monitor& test_mon() { static test_monitor instance; return instance; } + struct context + { + std::string oldCtx; + context(std::string ctx) : oldCtx(std::move(test_mon().context)) + { + test_mon().context = std::move(ctx); + } + ~context() + { + test_mon().context = std::move(oldCtx); + } + }; /// Function called when a test failed to be able set a breakpoint for debugging inline void test_failed(const char* expr, const char* file, const int line, const char* function) { std::ostringstream ss; ss << expr << " at " << file << ':' << line << " in " << function; + std::string& ctx = test_mon().context; + if(!ctx.empty()) + ss << " context: " << ctx; throw test_error(ss.str()); } @@ -139,6 +155,10 @@ namespace nowide { DISABLE_CONST_EXPR_DETECTED \ } while(0) DISABLE_CONST_EXPR_DETECTED_POP +#define TEST_CONTEXT(expr) \ + boost::nowide::test::context _##__COUNTER__( \ + static_cast(std::stringstream{} << expr).str()) + #ifndef BOOST_NOWIDE_TEST_NO_MAIN // Tests should implement this void test_main(int argc, char** argv, char** env); From 97fa18f156159bedaa250ef8281ab7d540a043f8 Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Tue, 22 Mar 2022 14:36:38 +0100 Subject: [PATCH 034/107] Add more tests for filebuf --- test/test_filebuf.cpp | 203 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 202 insertions(+), 1 deletion(-) diff --git a/test/test_filebuf.cpp b/test/test_filebuf.cpp index 6a47db30..f4b9e327 100644 --- a/test/test_filebuf.cpp +++ b/test/test_filebuf.cpp @@ -9,10 +9,12 @@ #include "file_test_helpers.hpp" #include "test.hpp" +#include #include #include #include #include +#include namespace nw = boost::nowide; using namespace boost::nowide::test; @@ -171,6 +173,200 @@ void test_64_bit_seek(const std::string& filepath) } } +void test_read_write_switch(const std::string& filepath, bool binary) +{ + // Switching between read and write requires a seek or (for W->R) a sync + remove_file_at_exit _(filepath); + const std::string data = "1234567890"; + auto flags = std::ios_base::in | std::ios_base::out | std::ios_base::trunc; + if(binary) + flags |= std::ios_base::binary; + nw::filebuf buf; + TEST(buf.open(filepath, flags)); + TEST_EQ(buf.sputn(data.data(), data.size()), static_cast(data.size())); + // W->R via seek + buf.pubseekpos(0); + TEST_EQ(buf.sbumpc(), '1'); + // R->W via seek + const auto pos = buf.pubseekoff(0, std::ios_base::cur); + TEST(pos != std::streampos(-1)); + buf.sputc('b'); + // W->R via sync + TEST(buf.pubsync() == 0); + TEST_EQ(buf.sbumpc(), '3'); + // R->W via seek + const auto pos2 = buf.pubseekoff(0, std::ios_base::cur); + buf.sputc('c'); + // Read right back + TEST_EQ(buf.pubseekpos(pos2), pos2); + TEST_EQ(buf.sbumpc(), 'c'); + // R->W + buf.pubseekoff(0, std::ios_base::cur); + buf.sputc('d'); + // Sync & seek + TEST(buf.pubsync() == 0); + TEST(buf.pubseekoff(0, std::ios_base::cur) != std::streampos(-1)); + TEST_EQ(buf.sbumpc(), '6'); + // R->W + buf.pubseekoff(0, std::ios_base::cur); + buf.sputc('e'); + // Seek & sync + TEST(buf.pubseekoff(0, std::ios_base::cur) != std::streampos(-1)); + TEST(buf.pubsync() == 0); + TEST_EQ(buf.sbumpc(), '8'); + + buf.close(); + TEST_EQ(read_file(filepath), "1b3cd6e890"); +} + +void subtest_sync(const std::string& filepath, bool binary, const std::string& data) +{ + nw::filebuf buf; + // Use a small buffer to force filling it up w/o requiring to write lot's of data + char buffer[3]; + buf.pubsetbuf(buffer, sizeof(buffer)); + auto flags = std::ios_base::out | std::ios_base::trunc; + if(binary) + flags |= std::ios_base::binary; + + // Do a series of single-char and multi-char writes with varying size combinations + // Especially test the case of only single-char and only multi-char ops + for(unsigned singleCharOps = 0; singleCharOps <= 3; ++singleCharOps) + { + // Write less than buffer size, 1 or 2 buffers or even more, assuming buffer size of 3 + for(size_t bufSize : {0, 2, 3, 6, 7}) + { + if(singleCharOps + bufSize == 0u) + continue; + TEST(buf.open(filepath, flags)); + for(size_t i = 0; i < data.size();) + { + TEST_CONTEXT("sc:" << singleCharOps << " buf:" << bufSize << " i:" << i); + for(unsigned j = 0; j < singleCharOps && i < data.size(); ++j, ++i) + { + using CharTraits = nw::filebuf::traits_type; + TEST_EQ(buf.sputc(data[i]), CharTraits::to_int_type(data[i])); + } + if(bufSize != 0u) + { + const auto remainSize = static_cast(std::min(data.size() - i, bufSize)); + TEST_EQ(buf.sputn(&data[i], remainSize), remainSize); + i += static_cast(remainSize); + } + TEST_EQ(buf.pubsync(), 0); + TEST_EQ(read_file(filepath, binary ? data_type::binary : data_type::text), data.substr(0, i)); + } + TEST(buf.close()); + TEST_EQ(read_file(filepath, binary ? data_type::binary : data_type::text), data); + } + } +} + +void subtest_singlechar_positioning(const std::string& filepath, bool binary, const std::string& data) +{ + nw::filebuf buf; + // Use a small buffer to force filling it up w/o requiring to write lot's of data + char buffer[3]; + buf.pubsetbuf(buffer, sizeof(buffer)); + auto flags = std::ios_base::in | std::ios_base::out | std::ios_base::trunc; + if(binary) + flags |= std::ios_base::binary; + TEST(buf.open(filepath, flags)); + + // Put each char and record its position + std::vector pos(data.size()); + for(unsigned i = 0; i < data.size(); ++i) + { + buf.sputc(data[i]); + pos[i] = buf.pubseekoff(0, std::ios_base::cur); + } + // Go back to start and verify reading yields the same data and positions + buf.pubseekoff(0, std::ios_base::beg); + for(unsigned i = 0; i < data.size(); ++i) + { + TEST_CONTEXT("Position " << i); + using CharTraits = nw::filebuf::traits_type; + TEST_EQ(buf.sbumpc(), CharTraits::to_int_type(data[i])); + TEST_EQ(buf.pubseekoff(0, std::ios_base::cur), pos[i]); + } +} + +void subtest_singlechar_multichar_reads(const std::string& filepath, bool binary, const std::string& data) +{ + create_file(filepath, data, binary ? data_type::binary : data_type::text); + nw::filebuf buf; + // Use a small buffer to force filling it up w/o requiring to write lot's of data + char buffer[3]; + buf.pubsetbuf(buffer, sizeof(buffer)); + std::ios_base::openmode flags = std::ios_base::in; + if(binary) + flags |= std::ios_base::binary; + TEST(buf.open(filepath, flags)); + + // Do a series of single-char and multi-char reads with varying size combinations + // Especially test the case of only single-char and only multi-char ops + for(unsigned singleCharOps = 0; singleCharOps <= 3; ++singleCharOps) + { + // Read less than buffer size, 1 or 2 buffers or even more, assuming buffer size of 3 + for(size_t bufSize : {0, 2, 3, 6, 7}) + { + if(singleCharOps + bufSize == 0u) + continue; + + std::string outBuf(bufSize, '\0'); + buf.pubseekoff(0, std::ios_base::beg); + for(size_t i = 0; i < data.size();) + { + TEST_CONTEXT("sc:" << singleCharOps << " buf:" << bufSize << " i:" << i); + for(unsigned j = 0; j < singleCharOps && i < data.size(); ++j, ++i) + { + using CharTraits = nw::filebuf::traits_type; + TEST_EQ(buf.sbumpc(), CharTraits::to_int_type(data[i])); + } + if(bufSize == 0u) + continue; + const size_t readSize = std::min(data.size() - i, bufSize); + TEST_EQ(buf.sgetn(&outBuf.front(), bufSize), static_cast(readSize)); + if(readSize < bufSize) + outBuf.resize(readSize); + TEST_EQ(outBuf, data.substr(i, readSize)); + i += bufSize; + } + } + } +} + +void test_textmode(const std::string& filepath) +{ + remove_file_at_exit _(filepath); + // Test input, output and getting the file position works for text files with newlines + const std::string data = []() { + // Some simple test data + std::string result = "1234567890"; + // Line break after every char + result.reserve(result.size() + 27 * 2); + for(char c = 'a'; c <= 'z'; ++c) + (result += c) += '\n'; + // Some continuous line breaks + result.append(4, '\n'); + return result; + }(); + subtest_singlechar_positioning(filepath, false, data); + subtest_singlechar_multichar_reads(filepath, false, data); + subtest_sync(filepath, false, data); +} + +// Almost the same test as test_textmode but uses a binary stream. +// Useful as the buffer handling is very different +void test_binarymode(const std::string& filepath) +{ + remove_file_at_exit _(filepath); + const std::string data = "123" + create_random_data(65, data_type::binary); + subtest_singlechar_positioning(filepath, true, data); + subtest_singlechar_multichar_reads(filepath, true, data); + subtest_sync(filepath, true, data); +} + void test_swap(const std::string& filepath) { const std::string filepath2 = filepath + ".2"; @@ -305,11 +501,16 @@ void test_swap(const std::string& filepath) void test_main(int, char** argv, char**) { const std::string exampleFilename = std::string(argv[0]) + "-\xd7\xa9-\xd0\xbc-\xce\xbd.txt"; - test_open_close(exampleFilename); test_pubseekpos(exampleFilename); test_pubseekoff(exampleFilename); test_64_bit_seek(exampleFilename); + std::cout << "Testing text mode\n"; + test_read_write_switch(exampleFilename, false); + test_textmode(exampleFilename); + std::cout << "Testing binary mode\n"; + test_read_write_switch(exampleFilename, true); + test_binarymode(exampleFilename); // These tests are only useful for the nowide filebuf and are known to fail for // std::filebuf due to bugs in libc++ #if BOOST_NOWIDE_USE_FILEBUF_REPLACEMENT From c16c196956d294f80e5282df3765d2d4b392d614 Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Tue, 22 Mar 2022 19:36:36 +0100 Subject: [PATCH 035/107] Only call fflush after actual output The function is (sometimes?) described as > For input streams (and for update streams on which the last operation was input), the behavior is undefined. --- include/boost/nowide/filebuf.hpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/include/boost/nowide/filebuf.hpp b/include/boost/nowide/filebuf.hpp index 4d63ed86..18cd13e0 100644 --- a/include/boost/nowide/filebuf.hpp +++ b/include/boost/nowide/filebuf.hpp @@ -271,9 +271,12 @@ namespace nowide { bool result; if(pptr()) { + // Only flush if anything was written, otherwise behavior of fflush is undefined. I.e.: + // - Buffered mode: pptr was set to buffer_ and advanced + // - Unbuffered mode: pptr set to last_char_ + const bool has_prev_write = pptr() != buffer_; result = overflow() != EOF; - // Only flush if anything was written, otherwise behavior of fflush is undefined - if(std::fflush(file_) != 0) + if(has_prev_write && std::fflush(file_) != 0) result = false; } else result = stop_reading(); From 0e347fdfc85f260f453381842686e355a4254191 Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Fri, 4 Mar 2022 16:06:30 +0100 Subject: [PATCH 036/107] Add CI using Cygwin 3.1.7 on Appveyor --- .appveyor.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.appveyor.yml b/.appveyor.yml index 1ac14278..8bce0082 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -89,6 +89,13 @@ environment: B2_CXXSTD: 03,11,14,1z B2_TOOLSET: gcc + - FLAVOR: cygwin (64-bit, latest) + APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022 + ADDPATH: C:\cygwin64\bin; + B2_ADDRESS_MODEL: 64 + B2_CXXSTD: 03,11,14,1z + B2_TOOLSET: gcc + - FLAVOR: mingw32 APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 B2_ADDRESS_MODEL: 32 From d078cfe3acf42d14fe87a1322e3492ee7636ca84 Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Sun, 6 Mar 2022 13:24:39 +0100 Subject: [PATCH 037/107] Add search paths for relative includes Required for e.g. recent Cygwin where the current source files path is not added to the search path automatically. --- build/Jamfile.v2 | 1 + test/Jamfile.v2 | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/build/Jamfile.v2 b/build/Jamfile.v2 index e1822798..3cf8988b 100644 --- a/build/Jamfile.v2 +++ b/build/Jamfile.v2 @@ -37,6 +37,7 @@ local SOURCES = console_buffer cstdio cstdlib filebuf iostream stat ; lib boost_nowide : $(SOURCES).cpp + : ../src ; boost-install boost_nowide ; diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index adb34c4b..0db56fea 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -2,7 +2,7 @@ # Copyright (c) 2003, 2006 Beman Dawes # Copyright (c) 2012 Artyom Beilis (Tonkikh) -# Copyright (c) 2020-2021 Alexander Grund +# Copyright (c) 2020-2022 Alexander Grund # # Distributed under the Boost Software License, Version 1.0. # (See accompanying file LICENSE or www.boost.org/LICENSE_1_0.txt) @@ -23,6 +23,7 @@ rule require-windows ( properties * ) project : requirements /boost/nowide//boost_nowide + . pedantic on [ requires From 1b9a56a298fcafd8b8b3007743e9bad0419434f1 Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Sat, 4 Jun 2022 13:26:03 +0200 Subject: [PATCH 038/107] Update CI from Boost.CI --- .appveyor.yml | 50 +++++++++++----------- .azure-pipelines.yml | 91 ++++++++++++++++------------------------ .github/workflows/ci.yml | 26 +++++++----- 3 files changed, 78 insertions(+), 89 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index 8bce0082..5e82eda2 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -1,12 +1,12 @@ # Copyright 2016, 2017 Peter Dimov # Copyright 2017 - 2019 James E. King III -# Copyright 2019 - 2020 Alexander Grund +# Copyright 2019 - 2022 Alexander Grund # Distributed under the Boost Software License, Version 1.0. # (See accompanying file LICENSE or copy at http://boost.org/LICENSE_1_0.txt) version: 1.0.{build}-{branch} -shallow_clone: false +shallow_clone: true branches: only: @@ -37,11 +37,25 @@ environment: B2_VARIANT: release,debug matrix: - - FLAVOR: Visual Studio 2022 - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022 + - FLAVOR: Visual Studio 2008, 2010, 2012 + APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 + B2_TOOLSET: msvc-9.0,msvc-10.0,msvc-11.0 + B2_ADDRESS_MODEL: 32 # No 64bit support + + - FLAVOR: Visual Studio 2013, 2015 + APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 + B2_TOOLSET: msvc-12.0,msvc-14.0 + + - FLAVOR: Visual Studio 2017 C++14/17 + APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 + B2_CXXSTD: 14,17 + B2_TOOLSET: msvc-14.1 + + - FLAVOR: Visual Studio 2017 C++2a Strict + APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 B2_CXXFLAGS: -permissive- - B2_CXXSTD: 14,17,20 - B2_TOOLSET: msvc-14.3 + B2_CXXSTD: 2a + B2_TOOLSET: msvc-14.1 - FLAVOR: Visual Studio 2019 APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 @@ -49,16 +63,11 @@ environment: B2_CXXSTD: 14,17,2a B2_TOOLSET: msvc-14.2 - - FLAVOR: Visual Studio 2017 C++2a Strict - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 + - FLAVOR: Visual Studio 2022 + APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022 B2_CXXFLAGS: -permissive- - B2_CXXSTD: 2a - B2_TOOLSET: msvc-14.1 - - - FLAVOR: Visual Studio 2017 C++14/17 - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 - B2_CXXSTD: 14,17 - B2_TOOLSET: msvc-14.1 + B2_CXXSTD: 14,17,20 + B2_TOOLSET: msvc-14.3 - FLAVOR: clang-cl APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 @@ -66,15 +75,6 @@ environment: B2_CXXSTD: 11,14,17 B2_TOOLSET: clang-win - - FLAVOR: Visual Studio 2015, 2013 - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 - B2_TOOLSET: msvc-12.0,msvc-14.0 - - - FLAVOR: Visual Studio 2008, 2010, 2012 - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 - B2_TOOLSET: msvc-9.0,msvc-10.0,msvc-11.0 - B2_ADDRESS_MODEL: 32 # No 64bit support - - FLAVOR: cygwin (32-bit) APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 ADDPATH: C:\cygwin\bin; @@ -89,6 +89,8 @@ environment: B2_CXXSTD: 03,11,14,1z B2_TOOLSET: gcc + # (Currently) the images up to 2017 use an older Cygwin + # This tests that the library works with more recent versions - FLAVOR: cygwin (64-bit, latest) APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022 ADDPATH: C:\cygwin64\bin; diff --git a/.azure-pipelines.yml b/.azure-pipelines.yml index 7844c75a..6796e039 100644 --- a/.azure-pipelines.yml +++ b/.azure-pipelines.yml @@ -44,44 +44,44 @@ parameters: - name: jobs type: object default: - - { compiler: gcc-11, cxxstd: '14,17,20', os: ubuntu-20.04 } - - { compiler: gcc-10, cxxstd: '14,17,20', os: ubuntu-20.04 } - - { compiler: gcc-9, cxxstd: '14,17,2a', os: ubuntu-20.04 } - - { compiler: gcc-8, cxxstd: '14,17,2a', os: ubuntu-20.04 } - - { compiler: gcc-7, cxxstd: '11,14,17', os: ubuntu-18.04 } - - { compiler: gcc-6, cxxstd: '11,14', os: ubuntu-18.04 } - - { compiler: gcc-5, cxxstd: '11', os: ubuntu-18.04 } - - { compiler: gcc-4.9, cxxstd: '11', os: ubuntu-18.04, container: 'ubuntu:16.04' } - { compiler: gcc-4.8, cxxstd: '11', os: ubuntu-18.04 } - - { compiler: clang-12, cxxstd: '14,17,20', os: ubuntu-20.04 } - - { compiler: clang-11, cxxstd: '14,17,20', os: ubuntu-20.04 } - - { compiler: clang-10, cxxstd: '14,17,20', os: ubuntu-20.04 } - - { compiler: clang-9, cxxstd: '14,17,2a', os: ubuntu-20.04 } - - { compiler: clang-8, cxxstd: '14,17', os: ubuntu-18.04, install: 'clang-8 libc6-dbg libc++-dev libstdc++-8-dev' } - - { compiler: clang-7, cxxstd: '14,17', os: ubuntu-18.04, install: 'clang-7 libc6-dbg libc++-dev libstdc++-8-dev' } + - { compiler: gcc-4.9, cxxstd: '11', os: ubuntu-18.04, container: 'ubuntu:16.04' } + - { compiler: gcc-5, cxxstd: '11', os: ubuntu-18.04 } + - { compiler: gcc-6, cxxstd: '11,14', os: ubuntu-18.04 } + - { compiler: gcc-7, cxxstd: '11,14,17', os: ubuntu-18.04 } + - { compiler: gcc-8, cxxstd: '14,17,2a', os: ubuntu-20.04 } + - { compiler: gcc-9, cxxstd: '14,17,2a', os: ubuntu-20.04 } + - { compiler: gcc-10, cxxstd: '14,17,20', os: ubuntu-20.04 } + - { compiler: gcc-11, cxxstd: '14,17,20', os: ubuntu-20.04 } + - { compiler: clang-3.5, cxxstd: '11', os: ubuntu-18.04, container: 'ubuntu:16.04' } + - { compiler: clang-3.6, cxxstd: '11', os: ubuntu-18.04, container: 'ubuntu:16.04' } + - { compiler: clang-3.7, cxxstd: '11', os: ubuntu-18.04, container: 'ubuntu:16.04' } + - { compiler: clang-3.8, cxxstd: '11,14', os: ubuntu-18.04, container: 'ubuntu:16.04' } + - { compiler: clang-3.9, cxxstd: '11,14', os: ubuntu-18.04 } + - { compiler: clang-4.0, cxxstd: '11,14', os: ubuntu-18.04 } + - { compiler: clang-5.0, cxxstd: '11,14,17', os: ubuntu-18.04 } - { compiler: clang-6.0, cxxstd: '11,14,17', os: ubuntu-18.04, install: 'clang-6.0 libc6-dbg libc++-dev libc++abi-dev libstdc++-8-dev' } + - { compiler: clang-7, cxxstd: '14,17', os: ubuntu-18.04, install: 'clang-7 libc6-dbg libc++-dev libstdc++-8-dev' } + - { compiler: clang-8, cxxstd: '14,17', os: ubuntu-18.04, install: 'clang-8 libc6-dbg libc++-dev libstdc++-8-dev' } + - { compiler: clang-9, cxxstd: '14,17,2a', os: ubuntu-20.04 } + - { compiler: clang-10, cxxstd: '14,17,20', os: ubuntu-20.04 } + - { compiler: clang-11, cxxstd: '14,17,20', os: ubuntu-20.04 } + - { compiler: clang-12, cxxstd: '14,17,20', os: ubuntu-20.04 } - { name: Linux_clang_6_libcxx, compiler: clang-6.0, cxxstd: '11,14,17', os: ubuntu-18.04, install: 'clang-6.0 libc6-dbg libc++-dev libc++abi-dev libstdc++-8-dev', env: {B2_STDLIB: libc++ } } - - { compiler: clang-5.0, cxxstd: '11,14,17', os: ubuntu-18.04 } - - { compiler: clang-4.0, cxxstd: '11,14', os: ubuntu-18.04 } - - { compiler: clang-3.9, cxxstd: '11,14', os: ubuntu-18.04 } - - { compiler: clang-3.8, cxxstd: '11,14', os: ubuntu-18.04, container: 'ubuntu:16.04' } - - { compiler: clang-3.7, cxxstd: '11', os: ubuntu-18.04, container: 'ubuntu:16.04' } - - { compiler: clang-3.6, cxxstd: '11', os: ubuntu-18.04, container: 'ubuntu:16.04' } - - { compiler: clang-3.5, cxxstd: '11', os: ubuntu-18.04, container: 'ubuntu:16.04' } # OSX - - { compiler: clang, cxxstd: '14,17,2a', os: macOS-10.15, xcode: 12.4 } - - { compiler: clang, cxxstd: '14,17,2a', os: macOS-10.15, xcode: 12.3 } - - { compiler: clang, cxxstd: '14,17,2a', os: macOS-10.15, xcode: 12.2 } - - { compiler: clang, cxxstd: '14,17,2a', os: macOS-10.15, xcode: 12.1.1 } - - { compiler: clang, cxxstd: '14,17,2a', os: macOS-10.15, xcode: 12.0.1 } - - { compiler: clang, cxxstd: '14,17,2a', os: macOS-10.15, xcode: 11.7 } - - { compiler: clang, cxxstd: '14,17,2a', os: macOS-10.15, xcode: 11.6 } - - { compiler: clang, cxxstd: '14,17,2a', os: macOS-10.15, xcode: 11.5 } - - { compiler: clang, cxxstd: '14,17,2a', os: macOS-10.15, xcode: 11.4.1 } - - { compiler: clang, cxxstd: '14,17,2a', os: macOS-10.15, xcode: 11.3.1 } - { compiler: clang, cxxstd: '14,17,2a', os: macOS-10.15, xcode: 11.2.1 } - { compiler: clang, cxxstd: '14,17,2a', os: macOS-10.15, xcode: 11.3 } + - { compiler: clang, cxxstd: '14,17,2a', os: macOS-10.15, xcode: 11.3.1 } + - { compiler: clang, cxxstd: '14,17,2a', os: macOS-10.15, xcode: 11.4.1 } + - { compiler: clang, cxxstd: '14,17,2a', os: macOS-10.15, xcode: 11.5 } + - { compiler: clang, cxxstd: '14,17,2a', os: macOS-10.15, xcode: 11.6 } + - { compiler: clang, cxxstd: '14,17,2a', os: macOS-10.15, xcode: 11.7 } + - { compiler: clang, cxxstd: '14,17,2a', os: macOS-10.15, xcode: 12.0.1 } + - { compiler: clang, cxxstd: '14,17,2a', os: macOS-10.15, xcode: 12.1.1 } + - { compiler: clang, cxxstd: '14,17,2a', os: macOS-10.15, xcode: 12.2 } + - { compiler: clang, cxxstd: '14,17,2a', os: macOS-10.15, xcode: 12.3 } + - { compiler: clang, cxxstd: '14,17,2a', os: macOS-10.15, xcode: 12.4 } stages: - stage: Test @@ -148,34 +148,15 @@ stages: cd $BOOST_ROOT/libs/$SELF ci/azure-pipelines/build.sh - displayName: 'Build' - - job: 'Windows' + - job: Windows timeoutInMinutes: 120 strategy: matrix: - VS_2022: - B2_TOOLSET: msvc-14.3 - B2_CXXSTD: 14,17,20 - B2_ADDRESS_MODEL: 32,64 - VM_IMAGE: 'windows-2022' - VS_2022_strict: - B2_TOOLSET: msvc-14.3 - B2_CXXSTD: 14,17,20 - B2_CXXFLAGS: -permissive- - B2_ADDRESS_MODEL: 32,64 - VM_IMAGE: 'windows-2022' - VS_2019: - B2_TOOLSET: msvc-14.2 - B2_CXXSTD: 14,17,20 - B2_ADDRESS_MODEL: 32,64 - VM_IMAGE: 'windows-2019' - VS_2019_strict: - B2_TOOLSET: msvc-14.2 - B2_CXXSTD: 14,17,20 - B2_CXXFLAGS: -permissive- - B2_ADDRESS_MODEL: 32,64 - VM_IMAGE: 'windows-2019' + VS_2019: { B2_TOOLSET: msvc-14.2, B2_CXXSTD: '14,17,20', B2_ADDRESS_MODEL: '32,64', VM_IMAGE: windows-2019 } + VS_2019_strict: { B2_TOOLSET: msvc-14.2, B2_CXXSTD: '14,17,20', B2_ADDRESS_MODEL: '32,64', VM_IMAGE: windows-2019, B2_CXXFLAGS: -permissive- } + VS_2022: { B2_TOOLSET: msvc-14.3, B2_CXXSTD: '14,17,20', B2_ADDRESS_MODEL: '32,64', VM_IMAGE: windows-2022 } + VS_2022_strict: { B2_TOOLSET: msvc-14.3, B2_CXXSTD: '14,17,20', B2_ADDRESS_MODEL: '32,64', VM_IMAGE: windows-2022, B2_CXXFLAGS: -permissive- } pool: vmImage: $(VM_IMAGE) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bef90b12..110369f6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -55,8 +55,9 @@ jobs: - { compiler: gcc-9, cxxstd: '03,11,14,17,2a', os: ubuntu-18.04 } - { compiler: gcc-10, cxxstd: '03,11,14,17,20', os: ubuntu-20.04 } - { compiler: gcc-11, cxxstd: '03,11,14,17,20', os: ubuntu-20.04 } + - { compiler: gcc-12, cxxstd: '03,11,14,17,20', os: ubuntu-22.04 } - { name: GCC w/ sanitizers, sanitize: yes, - compiler: gcc-11, cxxstd: '03,11,14,17,20', os: ubuntu-20.04 } + compiler: gcc-12, cxxstd: '03,11,14,17,20', os: ubuntu-22.04 } - { name: Collect coverage, coverage: yes, compiler: gcc-8, cxxstd: '03,11', os: ubuntu-20.04, install: 'g++-8-multilib', address-model: '32,64' } @@ -76,12 +77,14 @@ jobs: - { compiler: clang-10, cxxstd: '03,11,14,17,20', os: ubuntu-20.04 } - { compiler: clang-11, cxxstd: '03,11,14,17,20', os: ubuntu-20.04 } - { compiler: clang-12, cxxstd: '03,11,14,17,20', os: ubuntu-20.04 } + - { compiler: clang-13, cxxstd: '03,11,14,17,20', os: ubuntu-22.04 } + - { compiler: clang-14, cxxstd: '03,11,14,17,20', os: ubuntu-22.04 } # libc++ - { compiler: clang-6.0, cxxstd: '03,11,14', os: ubuntu-18.04, stdlib: libc++, install: 'clang-6.0 libc++-dev libc++abi-dev' } - { compiler: clang-12, cxxstd: '03,11,14,17,20', os: ubuntu-20.04, stdlib: libc++, install: 'clang-12 libc++-12-dev libc++abi-12-dev' } - { name: Clang w/ sanitizers, sanitize: yes, - compiler: clang-12, cxxstd: '03,11,14,17,20', os: ubuntu-20.04, stdlib: libc++, install: 'clang-12 libc++-12-dev libc++abi-12-dev' } + compiler: clang-14, cxxstd: '03,11,14,17,20', os: ubuntu-22.04, stdlib: libc++, install: 'clang-14 libc++-14-dev libc++abi-14-dev' } # OSX, clang - { compiler: clang, cxxstd: '03,11,14,17,2a', os: macos-10.15, sanitize: yes } @@ -107,7 +110,7 @@ jobs: apt-get -o Acquire::Retries=$NET_RETRY_COUNT update apt-get -o Acquire::Retries=$NET_RETRY_COUNT install -y g++ python libpython-dev git fi - # multiple job types are not compatible with ccache, they use "ccache: no" in the matrix + # For jobs not compatible with ccache, use "ccache: no" in the matrix if [[ "${{ matrix.ccache }}" == "no" ]]; then echo "B2_USE_CCACHE=0" >> $GITHUB_ENV fi @@ -120,11 +123,14 @@ jobs: fetch-depth: ${{ matrix.coverage && '0' || '1' }} - name: Cache ccache - uses: actions/cache@v2 + uses: actions/cache@v3 if: env.B2_USE_CCACHE with: path: ~/.ccache - key: ${{matrix.os}}-${{matrix.container}}-${{matrix.compiler}} + key: ${{matrix.os}}-${{matrix.container}}-${{matrix.compiler}}-${{github.sha}} + restore-keys: | + ${{matrix.os}}-${{matrix.container}}-${{matrix.compiler}}- + ${{matrix.os}}-${{matrix.container}}-${{matrix.compiler}} - name: Fetch Boost.CI uses: actions/checkout@v3 @@ -275,7 +281,7 @@ jobs: cd "$BOOST_ROOT" mkdir __build_cmake_test__ && cd __build_cmake_test__ cmake -G Ninja -DCMAKE_BUILD_TYPE=Debug -DBOOST_INCLUDE_LIBRARIES=$SELF -DBUILD_SHARED_LIBS=ON -DBUILD_TESTING=ON -DBoost_VERBOSE=ON .. - cmake --build . --target tests --config Debug + cmake --build . --target tests --config Debug -j$B2_JOBS ctest --output-on-failure --build-config Debug CMake: @@ -317,7 +323,7 @@ jobs: cd "$BOOST_ROOT" mkdir __build_cmake_test__ && cd __build_cmake_test__ cmake -G "${{matrix.generator}}" -DCMAKE_BUILD_TYPE=${{matrix.build_type}} -DBOOST_INCLUDE_LIBRARIES=$SELF -DBUILD_SHARED_LIBS=${{matrix.build_shared}} -DBUILD_TESTING=ON -DBoost_VERBOSE=ON .. - cmake --build . --target tests --config ${{matrix.build_type}} + cmake --build . --target tests --config ${{matrix.build_type}} -j$B2_JOBS ctest --output-on-failure --build-config ${{matrix.build_type}} - name: Run CMake subdir tests @@ -327,7 +333,7 @@ jobs: cd "$cmake_test_folder" mkdir __build_cmake_subdir_test__ && cd __build_cmake_subdir_test__ cmake -G "${{matrix.generator}}" -DBOOST_CI_INSTALL_TEST=OFF -DCMAKE_BUILD_TYPE=${{matrix.build_type}} -DBUILD_SHARED_LIBS=${{matrix.build_shared}} .. - cmake --build . --config ${{matrix.build_type}} + cmake --build . --config ${{matrix.build_type}} -j$B2_JOBS ctest --output-on-failure --build-config ${{matrix.build_type}} - name: Install Library @@ -335,7 +341,7 @@ jobs: cd "$BOOST_ROOT" mkdir __build_cmake_install_test__ && cd __build_cmake_install_test__ cmake -G "${{matrix.generator}}" -DCMAKE_BUILD_TYPE=${{matrix.build_type}} -DBOOST_INCLUDE_LIBRARIES=$SELF -DBUILD_SHARED_LIBS=${{matrix.build_shared}} -DCMAKE_INSTALL_PREFIX=~/.local -DBoost_VERBOSE=ON -DBoost_DEBUG=ON .. - cmake --build . --target install --config ${{matrix.build_type}} + cmake --build . --target install --config ${{matrix.build_type}} -j$B2_JOBS - name: Run CMake install tests run: | cmake_test_folder="$BOOST_ROOT/libs/$SELF/test/cmake_test" # New unified folder @@ -343,5 +349,5 @@ jobs: cd "$cmake_test_folder" mkdir __build_cmake_install_test__ && cd __build_cmake_install_test__ cmake -G "${{matrix.generator}}" -DBOOST_CI_INSTALL_TEST=ON -DCMAKE_BUILD_TYPE=${{matrix.build_type}} -DBUILD_SHARED_LIBS=${{matrix.build_shared}} -DCMAKE_PREFIX_PATH=~/.local .. - cmake --build . --config ${{matrix.build_type}} + cmake --build . --config ${{matrix.build_type}} -j$B2_JOBS ctest --output-on-failure --build-config ${{matrix.build_type}} From 4c1bfb3020d3e81750ebca6beb437d2ce7ae4983 Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Mon, 28 Mar 2022 19:15:35 +0200 Subject: [PATCH 039/107] Add test for pbackfail/sungetc/sputbackc --- test/test_filebuf.cpp | 178 +++++++++++++++++++++++++++++++++++------- 1 file changed, 149 insertions(+), 29 deletions(-) diff --git a/test/test_filebuf.cpp b/test/test_filebuf.cpp index f4b9e327..b5fc08aa 100644 --- a/test/test_filebuf.cpp +++ b/test/test_filebuf.cpp @@ -26,6 +26,35 @@ static_assert(std::is_same::value, "!"); static_assert(std::is_same::value, "!"); +const auto eof = nw::filebuf::traits_type::eof(); + +constexpr std::ios_base::openmode make_mode(std::ios_base::openmode flags, bool binary) +{ + return binary ? flags | std::ios_base::binary : flags; +} + +template +bool open_with_buffer(T_FileBuf& filebuf, + const std::string& filepath, + std::ios_base::openmode flags, + char (&buffer)[T_size]) +{ + const bool bufferSet = filebuf.pubsetbuf(buffer, T_size) != nullptr; + return filebuf.open(filepath, flags) && (bufferSet || filebuf.pubsetbuf(buffer, sizeof(buffer))); +} + +// Read the given number of chars from the buffer, checking that there are that many +template +bool skip_chars(T_Buf& buf, size_t num_chars) +{ + for(size_t i = 0; i < num_chars; ++i) + { + if(buf.sbumpc() == eof) + return false; // LCOV_EXCL_LINE + } + return true; +} + void test_open_close(const std::string& filepath) { const std::string filepath2 = filepath + ".2"; @@ -176,13 +205,9 @@ void test_64_bit_seek(const std::string& filepath) void test_read_write_switch(const std::string& filepath, bool binary) { // Switching between read and write requires a seek or (for W->R) a sync - remove_file_at_exit _(filepath); const std::string data = "1234567890"; - auto flags = std::ios_base::in | std::ios_base::out | std::ios_base::trunc; - if(binary) - flags |= std::ios_base::binary; nw::filebuf buf; - TEST(buf.open(filepath, flags)); + TEST(buf.open(filepath, make_mode(std::ios_base::in | std::ios_base::out | std::ios_base::trunc, binary))); TEST_EQ(buf.sputn(data.data(), data.size()), static_cast(data.size())); // W->R via seek buf.pubseekpos(0); @@ -225,9 +250,7 @@ void subtest_sync(const std::string& filepath, bool binary, const std::string& d // Use a small buffer to force filling it up w/o requiring to write lot's of data char buffer[3]; buf.pubsetbuf(buffer, sizeof(buffer)); - auto flags = std::ios_base::out | std::ios_base::trunc; - if(binary) - flags |= std::ios_base::binary; + const auto flags = make_mode(std::ios_base::out | std::ios_base::trunc, binary); // Do a series of single-char and multi-char writes with varying size combinations // Especially test the case of only single-char and only multi-char ops @@ -266,12 +289,9 @@ void subtest_singlechar_positioning(const std::string& filepath, bool binary, co { nw::filebuf buf; // Use a small buffer to force filling it up w/o requiring to write lot's of data - char buffer[3]; - buf.pubsetbuf(buffer, sizeof(buffer)); - auto flags = std::ios_base::in | std::ios_base::out | std::ios_base::trunc; - if(binary) - flags |= std::ios_base::binary; - TEST(buf.open(filepath, flags)); + char buffer[3]{}; + const auto mode = make_mode(std::ios_base::in | std::ios_base::out | std::ios_base::trunc, binary); + TEST(open_with_buffer(buf, filepath, mode, buffer)); // Put each char and record its position std::vector pos(data.size()); @@ -296,12 +316,8 @@ void subtest_singlechar_multichar_reads(const std::string& filepath, bool binary create_file(filepath, data, binary ? data_type::binary : data_type::text); nw::filebuf buf; // Use a small buffer to force filling it up w/o requiring to write lot's of data - char buffer[3]; - buf.pubsetbuf(buffer, sizeof(buffer)); - std::ios_base::openmode flags = std::ios_base::in; - if(binary) - flags |= std::ios_base::binary; - TEST(buf.open(filepath, flags)); + char buffer[3]{}; + TEST(open_with_buffer(buf, filepath, make_mode(std::ios_base::in, binary), buffer)); // Do a series of single-char and multi-char reads with varying size combinations // Especially test the case of only single-char and only multi-char ops @@ -336,9 +352,112 @@ void subtest_singlechar_multichar_reads(const std::string& filepath, bool binary } } +void test_sungetc(const std::string& filepath, bool binary) +{ + const std::string data = "012345\n6"; + create_file(filepath, data, binary ? data_type::binary : data_type::text); + + // Use a small buffer to force filling it up w/o requiring to write lot's of data + char buffer[4]; + nw::filebuf buf; + TEST(open_with_buffer(buf, filepath, make_mode(std::ios_base::in, binary), buffer)); + + // Nothing to unget at beginning of file + TEST_EQ(buf.sungetc(), eof); + + // Able to unget first char and get it again + TEST_EQ(buf.sbumpc(), '0'); + TEST(buf.sungetc() != eof); + TEST_EQ(buf.sbumpc(), '0'); + + // Able to unget and reread after filling up new buffer + TEST(skip_chars(buf, sizeof(buffer) - 1u)); // skip remaining chars + TEST_EQ(buf.sbumpc(), '4'); + TEST(buf.sungetc() != eof); + // Ungetting multiple chars may or may not be possible + if(buf.sungetc() != eof) + TEST_EQ(buf.sbumpc(), '3'); + TEST_EQ(buf.sbumpc(), '4'); + + // \n also works + TEST_EQ(buf.sbumpc(), '5'); + TEST_EQ(buf.sbumpc(), '\n'); + TEST(buf.sungetc() != eof); + TEST_EQ(buf.sbumpc(), '\n'); + TEST_EQ(buf.sbumpc(), '6'); + TEST(buf.sungetc() != eof); + if(buf.sungetc() != eof) + TEST_EQ(buf.sbumpc(), '\n'); + TEST_EQ(buf.sbumpc(), '6'); + + // Go back as far as possible + auto idx = data.size(); + while(buf.sungetc() != eof) + { + TEST(idx > 0u); + --idx; + } + TEST(idx < data.size()); // At least 1 + // Get all put back chars + for(; idx < data.size(); ++idx) + TEST_EQ(buf.sbumpc(), data[idx]); +} + +void test_sputbackc(const std::string& filepath, bool binary) +{ + const std::string data = "012345\n6"; + create_file(filepath, data, binary ? data_type::binary : data_type::text); + + // Use a small buffer to force filling it up w/o requiring to write lot's of data + char buffer[4]; + nw::filebuf buf; + TEST(open_with_buffer(buf, filepath, make_mode(std::ios_base::in, binary), buffer)); + TEST(skip_chars(buf, data.size())); + + // Put back same chars explicitly (as many as possible) + auto idx = data.size(); + while(true) + { + auto res = buf.sputbackc((idx > 0u) ? data[idx - 1] : 'z'); + if(res == eof) + break; + TEST(idx > 0u); + TEST_EQ(res, data[idx - 1]); + --idx; + } + TEST(idx < data.size()); // At least 1 + // Get all put back chars + for(; idx < data.size(); ++idx) + TEST_EQ(buf.sbumpc(), data[idx]); + + // Put back different chars (as many as possible) + const std::string data2 = "789\nab\nc"; + TEST_EQ(data.size(), data2.size()); + idx = data2.size(); + while(true) + { + auto res = buf.sputbackc((idx > 0u) ? data2[idx - 1] : 'z'); + if(res == eof) + break; + TEST(idx > 0u); + TEST_EQ(res, data2[idx - 1]); + --idx; +#if !BOOST_NOWIDE_USE_FILEBUF_REPLACEMENT + break; // Some stdlibs fail on putting back multiple different chars +#endif + } +#if BOOST_NOWIDE_USE_FILEBUF_REPLACEMENT + // At least 1 when using custom filebuf + // But e.g. libc++ doesn't allow putting back a different char + TEST(idx < data2.size()); +#endif + // Get all put back chars + for(; idx < data2.size(); ++idx) + TEST_EQ(buf.sbumpc(), data2[idx]); +} + void test_textmode(const std::string& filepath) { - remove_file_at_exit _(filepath); // Test input, output and getting the file position works for text files with newlines const std::string data = []() { // Some simple test data @@ -360,7 +479,6 @@ void test_textmode(const std::string& filepath) // Useful as the buffer handling is very different void test_binarymode(const std::string& filepath) { - remove_file_at_exit _(filepath); const std::string data = "123" + create_random_data(65, data_type::binary); subtest_singlechar_positioning(filepath, true, data); subtest_singlechar_multichar_reads(filepath, true, data); @@ -373,7 +491,6 @@ void test_swap(const std::string& filepath) remove_file_at_exit _(filepath); remove_file_at_exit _2(filepath2); - const auto eof = nw::filebuf::traits_type::eof(); // Note: Make sure to have en uneven number of swaps so the destructor runs on the others data // Check: FILE*, buffer, buffer_size @@ -505,12 +622,15 @@ void test_main(int, char** argv, char**) test_pubseekpos(exampleFilename); test_pubseekoff(exampleFilename); test_64_bit_seek(exampleFilename); - std::cout << "Testing text mode\n"; - test_read_write_switch(exampleFilename, false); - test_textmode(exampleFilename); - std::cout << "Testing binary mode\n"; - test_read_write_switch(exampleFilename, true); - test_binarymode(exampleFilename); + for(const auto binary : {false, true}) + { + std::cout << "Testing " << (binary ? "binary" : "text") << " mode\n"; + remove_file_at_exit _(exampleFilename); + test_read_write_switch(exampleFilename, binary); + test_sungetc(exampleFilename, binary); + test_sputbackc(exampleFilename, binary); + binary ? test_binarymode(exampleFilename) : test_textmode(exampleFilename); + } // These tests are only useful for the nowide filebuf and are known to fail for // std::filebuf due to bugs in libc++ #if BOOST_NOWIDE_USE_FILEBUF_REPLACEMENT From f2eec7760fac393572c24c3ec7c34318750ae926 Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Thu, 9 Jun 2022 17:27:39 +0200 Subject: [PATCH 040/107] Simplify pbackfail allowing only limited putback There are too many corner cases in putback handling. As use of that is rare anyway do the bare minimum and only allow putback into the current (read) buffer. --- include/boost/nowide/filebuf.hpp | 20 ++++---------- test/test_fstream_special.cpp | 47 +++++++++++++++++++------------- 2 files changed, 33 insertions(+), 34 deletions(-) diff --git a/include/boost/nowide/filebuf.hpp b/include/boost/nowide/filebuf.hpp index 18cd13e0..cc70e025 100644 --- a/include/boost/nowide/filebuf.hpp +++ b/include/boost/nowide/filebuf.hpp @@ -313,25 +313,15 @@ namespace nowide { int pbackfail(int c = EOF) override { - if(!(mode_ & std::ios_base::in)) - return EOF; - if(!stop_writing()) - return EOF; + // For simplicity we only allow putting back into our read buffer + // So putting back more chars than we have read from the buffer will fail if(gptr() > eback()) gbump(-1); - else if(seekoff(-1, std::ios_base::cur) != std::streampos(std::streamoff(-1))) - { - if(underflow() == EOF) - return EOF; - } else + else return EOF; - // Case 1: Caller just wanted space for 1 char - if(c == EOF) - return Traits::not_eof(c); - // Case 2: Caller wants to put back different char - // gptr now points to the (potentially newly read) previous char - if(*gptr() != c) + // Assign the new value if requested + if(c != EOF && *gptr() != Traits::to_char_type(c)) *gptr() = Traits::to_char_type(c); return Traits::not_eof(c); } diff --git a/test/test_fstream_special.cpp b/test/test_fstream_special.cpp index d3a15b5a..870d45e0 100644 --- a/test/test_fstream_special.cpp +++ b/test/test_fstream_special.cpp @@ -29,6 +29,8 @@ void test_with_different_buffer_sizes(const char* filepath) */ for(int i = -1; i < 16; i++) { + remove_file_at_exit _(filepath); + std::cout << "Buffer size = " << i << std::endl; char buf[16]; nw::fstream f; @@ -37,16 +39,12 @@ void test_with_different_buffer_sizes(const char* filepath) f.rdbuf()->pubsetbuf((i == 0) ? nullptr : buf, i); f.open(filepath, std::ios::in | std::ios::out | std::ios::trunc | std::ios::binary); TEST(f); - remove_file_at_exit _(filepath); // Add 'abcdefg' TEST(f.put('a')); TEST(f.put('b')); TEST(f.put('c')); - TEST(f.put('d')); - TEST(f.put('e')); - TEST(f.put('f')); - TEST(f.put('g')); + TEST(f.write("defg", 4)); // Read first char TEST(f.seekg(0)); TEST_EQ(f.get(), 'a'); @@ -86,18 +84,25 @@ void test_with_different_buffer_sizes(const char* filepath) TEST_EQ(f.get(), 'e'); // Putback after flush is implementation defined - // Boost.Nowide: Works -#if BOOST_NOWIDE_USE_FILEBUF_REPLACEMENT TEST(f << std::flush); - TEST(f.putback('e')); - TEST(f.putback('d')); - TEST_EQ(f.get(), 'd'); - TEST_EQ(f.get(), 'e'); + if(f.putback('e')) + { + if(f.putback('d')) + TEST_EQ(f.get(), 'd'); + else + f.clear(); // LCOV_EXCL_LINE + TEST_EQ(f.get(), 'e'); + } else + f.clear(); TEST(f << std::flush); - TEST(f.unget()); - TEST_EQ(f.get(), 'e'); -#endif + if(f.unget()) + TEST_EQ(f.get(), 'e'); + else + f.clear(); + // Put back different char + TEST(f.seekg(-1, std::ios::cur)); + TEST_EQ(f.get(), 'e'); TEST(f.putback('x')); TEST_EQ(f.get(), 'x'); // Rest of sequence @@ -112,11 +117,15 @@ void test_with_different_buffer_sizes(const char* filepath) TEST(f.putback('B')); // Putting back multiple chars is not possible on all implementations after a seek/flush #if BOOST_NOWIDE_USE_FILEBUF_REPLACEMENT - TEST(f.putback('a')); - TEST(!f.putback('x')); // At beginning of file -> No putback possible - // Get characters that were putback to avoid MSVC bug https://github.com/microsoft/STL/issues/342 - f.clear(); - TEST_EQ(f.get(), 'a'); + if(f.putback('a')) + { + // At beginning of file -> No putback possible + TEST(!f.putback('x')); // LCOV_EXCL_LINE + f.clear(); // LCOV_EXCL_LINE + // Get characters that were putback to avoid MSVC bug https://github.com/microsoft/STL/issues/342 + TEST_EQ(f.get(), 'a'); // LCOV_EXCL_LINE + } else + f.clear(); #endif TEST_EQ(f.get(), 'B'); f.close(); From 401940e7c3f1f28c17ccc3153b4b0f1e1098d4ef Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Tue, 22 Mar 2022 14:36:38 +0100 Subject: [PATCH 041/107] Test: filebuf xsgetn/xsputn & write-only/read-only buf --- test/test_filebuf.cpp | 248 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 215 insertions(+), 33 deletions(-) diff --git a/test/test_filebuf.cpp b/test/test_filebuf.cpp index b5fc08aa..8c888fb9 100644 --- a/test/test_filebuf.cpp +++ b/test/test_filebuf.cpp @@ -26,21 +26,38 @@ static_assert(std::is_same::value, "!"); static_assert(std::is_same::value, "!"); -const auto eof = nw::filebuf::traits_type::eof(); +using CharTraits = nw::filebuf::traits_type; +const auto eof = CharTraits::eof(); constexpr std::ios_base::openmode make_mode(std::ios_base::openmode flags, bool binary) { return binary ? flags | std::ios_base::binary : flags; } +template +bool open_with_buffer(T_FileBuf& filebuf, + const std::string& filepath, + std::ios_base::openmode flags, + char* buffer, + size_t size) +{ + const bool bufferSet = filebuf.pubsetbuf(buffer, size) != nullptr; + return filebuf.open(filepath, flags) && (bufferSet || filebuf.pubsetbuf(buffer, size)); +} + template bool open_with_buffer(T_FileBuf& filebuf, const std::string& filepath, std::ios_base::openmode flags, char (&buffer)[T_size]) { - const bool bufferSet = filebuf.pubsetbuf(buffer, T_size) != nullptr; - return filebuf.open(filepath, flags) && (bufferSet || filebuf.pubsetbuf(buffer, sizeof(buffer))); + return open_with_buffer(filebuf, filepath, flags, buffer, T_size); +} + +template +bool open_unbuffered(T_FileBuf& filebuf, const std::string& filepath, std::ios_base::openmode flags) +{ + return open_with_buffer(filebuf, filepath, flags, nullptr, 0); } // Read the given number of chars from the buffer, checking that there are that many @@ -62,22 +79,62 @@ void test_open_close(const std::string& filepath) remove_file_at_exit _(filepath); remove_file_at_exit _2(filepath2); - nw::filebuf buf; - TEST(buf.open(filepath, std::ios_base::out) == &buf); - TEST(buf.is_open()); - - // Opening when already open fails - TEST(buf.open(filepath2, std::ios_base::out) == nullptr); - // Still open - TEST(buf.is_open()); - TEST(buf.close() == &buf); - // Failed opening did not create file - TEST(!file_exists(filepath2)); - - // But it should work now: - TEST(buf.open(filepath2, std::ios_base::out) == &buf); - TEST(buf.close() == &buf); - TEST(file_exists(filepath2)); + { + nw::filebuf buf; + TEST(buf.open(filepath, std::ios_base::out) == &buf); + TEST(buf.is_open()); + + // Opening when already open fails + TEST(buf.open(filepath2, std::ios_base::out) == nullptr); + // Still open + TEST(buf.is_open()); + TEST(buf.close() == &buf); + // Failed opening did not create file + TEST(!file_exists(filepath2)); + + // But it should work now: + TEST(buf.open(filepath2, std::ios_base::out) == &buf); + TEST(buf.close() == &buf); + TEST(file_exists(filepath2)); + } + + const auto file_data = create_random_data(20, data_type::text); + create_file(filepath, file_data); + // Can't write to read-only buf + { + nw::filebuf buf; + TEST(buf.open(filepath, std::ios_base::in)); + TEST_EQ(buf.sputc('a'), eof); + // Even if chars were copied to put area, they cannot be written (in sync) + TEST(buf.sputn("hello", 5) == 0 || buf.pubsync() == -1); + } + TEST_EQ(read_file(filepath), file_data); // File is unchanged + { + nw::filebuf buf; + char buffer[3]; + TEST(open_with_buffer(buf, filepath, std::ios_base::in, buffer)); + // Also doesn't write when using direct I/O due to data>buffersize (at least in Nowide) + TEST(buf.sputn("hello", 5) == 0 || buf.pubsync() == -1); + } + TEST_EQ(read_file(filepath), file_data); // File is unchanged + + // Can't read from write-only buf + { + for(const auto flags : {std::ios_base::out, std::ios_base::app}) + { + create_file(filepath, file_data); + nw::filebuf buf; + TEST(buf.open(filepath, flags)); + TEST_EQ(buf.sgetc(), eof); + TEST_EQ(buf.sbumpc(), eof); + char str[3]; + TEST_EQ(buf.sgetn(str, sizeof(str)), 0); + // Putback is also just for reading + TEST(buf.pubseekoff(0, std::ios_base::end) != std::streampos(-1)); + TEST_EQ(buf.sungetc(), eof); + TEST_EQ(buf.sputbackc('t'), eof); + } + } } void test_pubseekpos(const std::string& filepath) @@ -92,9 +149,8 @@ void test_pubseekpos(const std::string& filepath) using pos_type = nw::filebuf::pos_type; const auto eofPos = pos_type(data.size()); std::uniform_int_distribution distr(0, static_cast(eofPos) - 1); - using traits = nw::filebuf::traits_type; - const auto getData = [&](pos_type pos) { return traits::to_int_type(data[static_cast(pos)]); }; + const auto getData = [&](pos_type pos) { return CharTraits::to_int_type(data[static_cast(pos)]); }; for(int i = 0; i < 100; i++) { @@ -104,9 +160,9 @@ void test_pubseekpos(const std::string& filepath) } // Seek to first and last as corner case tests TEST_EQ(buf.pubseekpos(0), pos_type(0)); - TEST_EQ(buf.sgetc(), traits::to_int_type(data[0])); + TEST_EQ(buf.sgetc(), CharTraits::to_int_type(data[0])); TEST_EQ(buf.pubseekpos(eofPos), eofPos); - TEST_EQ(buf.sgetc(), traits::eof()); + TEST_EQ(buf.sgetc(), eof); } void test_pubseekoff(const std::string& filepath) @@ -122,9 +178,8 @@ void test_pubseekoff(const std::string& filepath) using off_type = nw::filebuf::off_type; const auto eofPos = pos_type(data.size()); std::uniform_int_distribution distr(0, static_cast(eofPos) - 1); - using traits = nw::filebuf::traits_type; - const auto getData = [&](pos_type pos) { return traits::to_int_type(data[static_cast(pos)]); }; + const auto getData = [&](pos_type pos) { return CharTraits::to_int_type(data[static_cast(pos)]); }; // tellg/tellp function as called by basic_[io]fstream const auto tellg = [&]() { return buf.pubseekoff(0, std::ios_base::cur); }; @@ -151,10 +206,10 @@ void test_pubseekoff(const std::string& filepath) // Seek to first and last as corner case tests TEST_EQ(buf.pubseekoff(0, std::ios_base::beg), pos_type(0)); TEST_EQ(tellg(), pos_type(0)); - TEST_EQ(buf.sgetc(), traits::to_int_type(data[0])); + TEST_EQ(buf.sgetc(), CharTraits::to_int_type(data[0])); TEST_EQ(buf.pubseekoff(0, std::ios_base::end), eofPos); TEST_EQ(tellg(), eofPos); - TEST_EQ(buf.sgetc(), traits::eof()); + TEST_EQ(buf.sgetc(), eof); } void test_64_bit_seek(const std::string& filepath) @@ -202,6 +257,134 @@ void test_64_bit_seek(const std::string& filepath) } } +void test_xsgetn(const std::string& filepath, bool binary) +{ + char buffer[200]{}; + const auto dataType = binary ? data_type::binary : data_type::text; + const std::string data = create_random_data(sizeof(buffer) + 50, dataType); + create_file(filepath, data, dataType); + + for(const bool unbuffered : {false, true}) + { + TEST_CONTEXT((unbuffered ? "unbuffered" : "buffered")); + nw::filebuf buf; + if(unbuffered) + TEST(open_unbuffered(buf, filepath, make_mode(std::ios_base::in, binary))); + else + TEST(open_with_buffer(buf, filepath, make_mode(std::ios_base::in, binary), buffer)); + + std::string strBuf(data.size() * 2, '\0'); + // Reading stops at EOF + TEST_EQ(buf.sgetn(&strBuf[0], strBuf.size()), static_cast(data.size())); + strBuf.resize(data.size()); + TEST_EQ(strBuf, data); + TEST(buf.pubseekpos(0) != std::streampos(-1)); + // Read a bit using regular underflow, then via sgetn and again via underflow + TEST_EQ(buf.sbumpc(), CharTraits::to_int_type(data[0])); + TEST_EQ(buf.sbumpc(), CharTraits::to_int_type(data[1])); + strBuf.clear(); + // Go definitely over a buffer boundary + strBuf.resize(sizeof(buffer)); + TEST_EQ(buf.sgetn(&strBuf[0], strBuf.size()), static_cast(strBuf.size())); + TEST_EQ(strBuf, data.substr(2, strBuf.size())); + TEST_EQ(buf.sbumpc(), CharTraits::to_int_type(data[strBuf.size() + 2])); + TEST_EQ(buf.sbumpc(), CharTraits::to_int_type(data[strBuf.size() + 3])); + } + // Corner cases: + // - sgetn with zero or negative count is a no-op + // - sgetn fails on closed filebuf + for(const bool unbuffered : {false, true}) + { + TEST_CONTEXT((unbuffered ? "unbuffered" : "buffered")); + create_file(filepath, "Hello World"); + nw::filebuf buf; + // Set a buffer just to see if it is written to + if(unbuffered) + TEST(open_unbuffered(buf, filepath, make_mode(std::ios_base::in, binary))); + else + TEST(open_with_buffer(buf, filepath, make_mode(std::ios_base::in, binary), buffer)); + + std::string str = create_random_data(data.size(), data_type::binary); + const auto origStr = str; + buffer[0] = origStr[0]; + + TEST_EQ(buf.sgetn(&str[0], 0), 0); +#if defined(__GNUC__) && __GNUC__ >= 7 + // GCC may not detect that the negative value is checked by xsgetn +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wrestrict" +#endif + TEST_EQ(buf.sgetn(&str[0], -1), 0); + TEST_EQ(buf.sgetn(&str[0], -999), 0); +#if defined(__GNUC__) && __GNUC__ >= 12 +#pragma GCC diagnostic pop +#endif + buf.close(); + // No read when closed + TEST_EQ(buf.sgetn(&str[0], 1), 0); + TEST_EQ(str, origStr); + TEST_EQ(buffer[0], origStr[0]); + TEST_EQ(buf.sgetn(&str[0], str.size()), 0); + TEST_EQ(str, origStr); + TEST_EQ(buffer[0], origStr[0]); + } +} + +void test_xsputn(const std::string& filepath, bool binary) +{ + char buffer[200]{}; + const auto dataType = binary ? data_type::binary : data_type::text; + const std::string data = create_random_data(sizeof(buffer) + 50, dataType); + + for(const bool unbuffered : {false, true}) + { + TEST_CONTEXT((unbuffered ? "unbuffered" : "buffered")); + nw::filebuf buf; + const auto flags = make_mode(std::ios_base::out | std::ios_base::trunc, binary); + if(unbuffered) + TEST(open_unbuffered(buf, filepath, flags)); + else + TEST(open_with_buffer(buf, filepath, flags, buffer)); + + TEST_EQ(buf.sputn(data.data(), data.size()), static_cast(data.size())); + buf.close(); + TEST_EQ(read_file(filepath, dataType), data); + + // Write a bit using regular overflow, then via sputn and back using overflow + TEST(buf.open(filepath, flags)); + TEST_EQ(buf.sputc(data[0]), CharTraits::to_int_type(data[0])); + TEST_EQ(buf.sputc(data[1]), CharTraits::to_int_type(data[1])); + // This is more than 1 buffer size + std::streamsize numBytesToWrite = data.size() - 4; + TEST_EQ(buf.sputn(&data[2], numBytesToWrite), numBytesToWrite); + TEST_EQ(buf.sputc(data[data.size() - 2]), CharTraits::to_int_type(data[data.size() - 2])); + TEST_EQ(buf.sputc(data[data.size() - 1]), CharTraits::to_int_type(data[data.size() - 1])); + buf.close(); + TEST_EQ(read_file(filepath, dataType), data); + } + // Corner cases: + // - sputn with zero or negative count is a no-op + // - sputn fails on closed filebuf + for(const bool unbuffered : {false, true}) + { + TEST_CONTEXT((unbuffered ? "unbuffered" : "buffered")); + nw::filebuf buf; + if(unbuffered) + TEST(open_unbuffered(buf, filepath, make_mode(std::ios_base::out | std::ios_base::trunc, binary))); + else + TEST(open_with_buffer(buf, filepath, make_mode(std::ios_base::out | std::ios_base::trunc, binary), buffer)); + + TEST_EQ(buf.sputn(data.data(), 0), 0); + TEST_EQ(buf.sputn(data.data(), -1), 0); + TEST_EQ(buf.sputn(data.data(), -999), 0); + buf.close(); + // No write when closed + TEST_EQ(buf.sputn(data.data(), 1), 0); + TEST_EQ(buf.sputn(data.data(), data.size()), 0); + TEST_EQ(read_file(filepath), ""); + } +} + void test_read_write_switch(const std::string& filepath, bool binary) { // Switching between read and write requires a seek or (for W->R) a sync @@ -267,14 +450,13 @@ void subtest_sync(const std::string& filepath, bool binary, const std::string& d TEST_CONTEXT("sc:" << singleCharOps << " buf:" << bufSize << " i:" << i); for(unsigned j = 0; j < singleCharOps && i < data.size(); ++j, ++i) { - using CharTraits = nw::filebuf::traits_type; TEST_EQ(buf.sputc(data[i]), CharTraits::to_int_type(data[i])); } if(bufSize != 0u) { - const auto remainSize = static_cast(std::min(data.size() - i, bufSize)); - TEST_EQ(buf.sputn(&data[i], remainSize), remainSize); - i += static_cast(remainSize); + const auto remainSize = std::min(data.size() - i, bufSize); + TEST_EQ(buf.sputn(&data[i], remainSize), static_cast(remainSize)); + i += remainSize; } TEST_EQ(buf.pubsync(), 0); TEST_EQ(read_file(filepath, binary ? data_type::binary : data_type::text), data.substr(0, i)); @@ -305,7 +487,6 @@ void subtest_singlechar_positioning(const std::string& filepath, bool binary, co for(unsigned i = 0; i < data.size(); ++i) { TEST_CONTEXT("Position " << i); - using CharTraits = nw::filebuf::traits_type; TEST_EQ(buf.sbumpc(), CharTraits::to_int_type(data[i])); TEST_EQ(buf.pubseekoff(0, std::ios_base::cur), pos[i]); } @@ -336,7 +517,6 @@ void subtest_singlechar_multichar_reads(const std::string& filepath, bool binary TEST_CONTEXT("sc:" << singleCharOps << " buf:" << bufSize << " i:" << i); for(unsigned j = 0; j < singleCharOps && i < data.size(); ++j, ++i) { - using CharTraits = nw::filebuf::traits_type; TEST_EQ(buf.sbumpc(), CharTraits::to_int_type(data[i])); } if(bufSize == 0u) @@ -626,6 +806,8 @@ void test_main(int, char** argv, char**) { std::cout << "Testing " << (binary ? "binary" : "text") << " mode\n"; remove_file_at_exit _(exampleFilename); + test_xsgetn(exampleFilename, binary); + test_xsputn(exampleFilename, binary); test_read_write_switch(exampleFilename, binary); test_sungetc(exampleFilename, binary); test_sputbackc(exampleFilename, binary); From 137686ebbf9af5352421a3c30de4493473795e15 Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Sun, 27 Mar 2022 19:18:53 +0200 Subject: [PATCH 042/107] Move filebuf members around Put private functions together and order member variables by size which may save some memory due to alignment. Also make it more reasonable by putting the FILE* first and the buffer stuff together. --- include/boost/nowide/filebuf.hpp | 88 ++++++++++++++++---------------- 1 file changed, 43 insertions(+), 45 deletions(-) diff --git a/include/boost/nowide/filebuf.hpp b/include/boost/nowide/filebuf.hpp index cc70e025..56adeceb 100644 --- a/include/boost/nowide/filebuf.hpp +++ b/include/boost/nowide/filebuf.hpp @@ -68,8 +68,8 @@ namespace nowide { /// Creates new filebuf /// basic_filebuf() : - buffer_size_(BUFSIZ), buffer_(nullptr), file_(nullptr), owns_buffer_(false), last_char_(), - mode_(std::ios_base::openmode(0)) + file_(nullptr), buffer_(nullptr), buffer_size_(BUFSIZ), owns_buffer_(false), + last_char_(), mode_(std::ios_base::openmode(0)) { setg(nullptr, nullptr, nullptr); setp(nullptr, nullptr); @@ -93,9 +93,9 @@ namespace nowide { { std::basic_streambuf::swap(rhs); using std::swap; - swap(buffer_size_, rhs.buffer_size_); - swap(buffer_, rhs.buffer_); swap(file_, rhs.file_); + swap(buffer_, rhs.buffer_); + swap(buffer_size_, rhs.buffer_size_); swap(owns_buffer_, rhs.owns_buffer_); swap(last_char_[0], rhs.last_char_[0]); swap(mode_, rhs.mode_); @@ -189,23 +189,6 @@ namespace nowide { return file_ != nullptr; } - private: - void make_buffer() - { - if(buffer_) - return; - if(buffer_size_ > 0) - { - buffer_ = new char[buffer_size_]; - owns_buffer_ = true; - } - } - void validate_cvt(const std::locale& loc) - { - if(!std::use_facet>(loc).always_noconv()) - throw std::runtime_error("Converting codecvts are not supported"); - } - protected: std::streambuf* setbuf(char* s, std::streamsize n) override { @@ -224,6 +207,25 @@ namespace nowide { return this; } + int sync() override + { + if(!file_) + return 0; + bool result; + if(pptr()) + { + // Only flush if anything was written, otherwise behavior of fflush is undefined. I.e.: + // - Buffered mode: pptr was set to buffer_ and advanced + // - Unbuffered mode: pptr set to last_char_ + const bool has_prev_write = pptr() != buffer_; + result = overflow() != EOF; + if(has_prev_write && std::fflush(file_) != 0) + result = false; + } else + result = stop_reading(); + return result ? 0 : -1; + } + int overflow(int c = EOF) override { if(!(mode_ & (std::ios_base::out | std::ios_base::app))) @@ -264,30 +266,9 @@ namespace nowide { return Traits::not_eof(c); } - int sync() override - { - if(!file_) - return 0; - bool result; - if(pptr()) - { - // Only flush if anything was written, otherwise behavior of fflush is undefined. I.e.: - // - Buffered mode: pptr was set to buffer_ and advanced - // - Unbuffered mode: pptr set to last_char_ - const bool has_prev_write = pptr() != buffer_; - result = overflow() != EOF; - if(has_prev_write && std::fflush(file_) != 0) - result = false; - } else - result = stop_reading(); - return result ? 0 : -1; - } - int underflow() override { - if(!(mode_ & std::ios_base::in)) - return EOF; - if(!stop_writing()) + if(!(mode_ & std::ios_base::in) || !stop_writing()) return EOF; // In text mode we cannot use a buffer size of more than 1 (i.e. single char only) // This is due to the need to seek back in case of a sync to "put back" unread chars. @@ -362,6 +343,23 @@ namespace nowide { } private: + void make_buffer() + { + if(buffer_) + return; + if(buffer_size_ > 0) + { + buffer_ = new char[buffer_size_]; + owns_buffer_ = true; + } + } + + void validate_cvt(const std::locale& loc) + { + if(!std::use_facet>(loc).always_noconv()) + throw std::runtime_error("Converting codecvts are not supported"); + } + /// Stop reading adjusting the file pointer if necessary /// Postcondition: gptr() == nullptr bool stop_reading() @@ -447,9 +445,9 @@ namespace nowide { return nullptr; } - size_t buffer_size_; - char* buffer_; FILE* file_; + char* buffer_; + size_t buffer_size_; bool owns_buffer_; char last_char_[1]; std::ios::openmode mode_; From a2e6a3653f23d2bc6bec5ab1d38106f9ed464b4e Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Sun, 27 Mar 2022 19:21:27 +0200 Subject: [PATCH 043/107] Improve read performance Implement filebuf::xsgetn to improve read performance for sizes exceeding the current buffer size, especially for text streams. --- include/boost/nowide/filebuf.hpp | 53 ++++++++++++++++++++++++++++---- 1 file changed, 47 insertions(+), 6 deletions(-) diff --git a/include/boost/nowide/filebuf.hpp b/include/boost/nowide/filebuf.hpp index 56adeceb..0df1d2d3 100644 --- a/include/boost/nowide/filebuf.hpp +++ b/include/boost/nowide/filebuf.hpp @@ -68,7 +68,7 @@ namespace nowide { /// Creates new filebuf /// basic_filebuf() : - file_(nullptr), buffer_(nullptr), buffer_size_(BUFSIZ), owns_buffer_(false), + file_(nullptr), buffer_(nullptr), buffer_size_(BUFSIZ), owns_buffer_(false), unbuffered_read_(false), last_char_(), mode_(std::ios_base::openmode(0)) { setg(nullptr, nullptr, nullptr); @@ -97,6 +97,7 @@ namespace nowide { swap(buffer_, rhs.buffer_); swap(buffer_size_, rhs.buffer_size_); swap(owns_buffer_, rhs.owns_buffer_); + swap(unbuffered_read_, rhs.unbuffered_read_); swap(last_char_[0], rhs.last_char_[0]); swap(mode_, rhs.mode_); @@ -157,6 +158,7 @@ namespace nowide { return nullptr; } mode_ = mode; + set_unbuffered_read(); return this; } /// @@ -204,6 +206,7 @@ namespace nowide { } buffer_ = s; buffer_size_ = (n >= 0) ? static_cast(n) : 0; + set_unbuffered_read(); return this; } @@ -270,11 +273,7 @@ namespace nowide { { if(!(mode_ & std::ios_base::in) || !stop_writing()) return EOF; - // In text mode we cannot use a buffer size of more than 1 (i.e. single char only) - // This is due to the need to seek back in case of a sync to "put back" unread chars. - // However determining the number of chars to seek back is impossible in case there are newlines - // as we cannot know if those were converted. - if(buffer_size_ == 0 || !(mode_ & std::ios_base::binary)) + if(unbuffered_read_) { const int c = std::fgetc(file_); if(c == EOF) @@ -292,6 +291,38 @@ namespace nowide { return Traits::to_int_type(*gptr()); } + std::streamsize xsgetn(char* s, std::streamsize n) override + { + // Only optimize when reading more than a buffer worth of data + if(n <= static_cast(unbuffered_read_ ? 1u : buffer_size_)) + return std::basic_streambuf::xsgetn(s, n); + if(!(mode_ & std::ios_base::in) || !stop_writing()) + return 0; + std::streamsize num_copied = 0; + // First empty the remaining get area, if any + const auto num_buffered = egptr() - gptr(); + if(num_buffered != 0) + { + const auto num_read = num_buffered > n ? n : num_buffered; + traits_type::copy(s, gptr(), static_cast(num_read)); + s += num_read; + n -= num_read; + num_copied = num_read; + setg(eback(), gptr() + num_read, egptr()); // i.e. gbump(num_read) + } + // Then read directly from file (loop as number of bytes read may be less than requested) + while(n > 0) + { + const auto num_read = std::fread(s, 1, static_cast(n), file_); + if(num_read == 0) // EOF or error + break; + s += num_read; + n -= num_read; + num_copied += num_read; + } + return num_copied; + } + int pbackfail(int c = EOF) override { // For simplicity we only allow putting back into our read buffer @@ -354,6 +385,15 @@ namespace nowide { } } + void set_unbuffered_read() + { + // In text mode we cannot use buffering as we are required to know the (file) position of each + // char in the get area and to seek back in case of a sync to "put back" unread chars. + // However std::fseek with non-zero offsets is unsupported for text files and the (file) offset + // to seek back is unknown anyway due to newlines which may got converted. + unbuffered_read_ = !(mode_ & std::ios_base::binary) || buffer_size_ == 0u; + } + void validate_cvt(const std::locale& loc) { if(!std::use_facet>(loc).always_noconv()) @@ -449,6 +489,7 @@ namespace nowide { char* buffer_; size_t buffer_size_; bool owns_buffer_; + bool unbuffered_read_; // True to read char by char char last_char_[1]; std::ios::openmode mode_; }; From dd105084bf126c7fc9b3fd5f8b76c46f30253d05 Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Sat, 11 Jun 2022 12:11:16 +0200 Subject: [PATCH 044/107] Improve write performance Implement filebuf::xsputn to improve write performance for sizes exceeding the current buffer size, especially for text streams. --- include/boost/nowide/filebuf.hpp | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/include/boost/nowide/filebuf.hpp b/include/boost/nowide/filebuf.hpp index 0df1d2d3..957f9c75 100644 --- a/include/boost/nowide/filebuf.hpp +++ b/include/boost/nowide/filebuf.hpp @@ -269,6 +269,31 @@ namespace nowide { return Traits::not_eof(c); } + std::streamsize xsputn(const char* s, std::streamsize n) override + { + // Only optimize when writing more than a buffer worth of data + if(n <= static_cast(buffer_size_)) + return std::basic_streambuf::xsputn(s, n); + if(!(mode_ & (std::ios_base::out | std::ios_base::app)) || !stop_reading()) + return 0; + + // First empty the remaining put area, if any + const char* const base = pbase(); + const size_t num_buffered = pptr() - base; + if(num_buffered != 0) + { + const auto num_written = std::fwrite(base, 1, num_buffered, file_); + setp(const_cast(base + num_written), epptr()); // i.e. pbump(num_written) + if(num_written != num_buffered) + return 0; // Error writing buffered chars + } + // Then write directly to file + const auto num_written = std::fwrite(s, 1, static_cast(n), file_); + if(num_written > 0u && base != last_char_) + setp(last_char_, last_char_); // Mark as "written" if not done yet + return num_written; + } + int underflow() override { if(!(mode_ & std::ios_base::in) || !stop_writing()) From f3746eb94ea63d14d26ea2907ec72d21f75b1af4 Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Sun, 12 Jun 2022 19:17:44 +0200 Subject: [PATCH 045/107] Fix the fix for flaky Appveyor CI --- .appveyor.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index 5e82eda2..a14e91d0 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -134,7 +134,7 @@ environment: APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022 CXXSTD: 17 # This test sometimes fails on recent images when using CMake - CXX_FLAGS: -DNOWIDE_DISABLE_CIN_TEST=ON + CMAKE_FLAGS: -DBOOST_NOWIDE_DISABLE_CIN_TEST=ON GENERATOR: Visual Studio 17 2022 configuration: Debug BOOST_ROOT: C:\Libraries\boost_1_77_0 @@ -175,7 +175,7 @@ for: - if exist %INSTALL_DIR%\ (rmdir /S /Q %INSTALL_DIR%) - mkdir __build_cmake_test__ - cd __build_cmake_test__ - - cmake -G "%GENERATOR%" -DCMAKE_CXX_STANDARD=%CXXSTD% %CXX_FLAGS% -DCMAKE_INSTALL_PREFIX=%INSTALL_DIR% .. + - cmake -G "%GENERATOR%" -DCMAKE_CXX_STANDARD=%CXXSTD% %CMAKE_FLAGS% -DCMAKE_INSTALL_PREFIX=%INSTALL_DIR% .. build_script: cmake --build . --config %configuration% --parallel 4 test_script: - ctest --output-on-failure -C %configuration% --parallel 4 @@ -186,7 +186,7 @@ for: # Build consumer example test - cmake --build . --config %configuration% --target install - del /F /S /Q * - - cmake -DBOOST_NOWIDE_INSTALL_TEST=ON -G "%GENERATOR%" -DCMAKE_CXX_STANDARD=%CXXSTD% %CXX_FLAGS% -DCMAKE_PREFIX_PATH=%APPVEYOR_BUILD_FOLDER%\installed ../test/cmake_test + - cmake -DBOOST_NOWIDE_INSTALL_TEST=ON -G "%GENERATOR%" -DCMAKE_CXX_STANDARD=%CXXSTD% %CMAKE_FLAGS% -DCMAKE_PREFIX_PATH=%APPVEYOR_BUILD_FOLDER%\installed ../test/cmake_test - cmake --build . --config %configuration% - ctest --output-on-failure -C %configuration% --parallel 4 From 8cb8207c928e5c47fa35256cc9eaf43c2d3b9534 Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Mon, 13 Jun 2022 16:54:54 +0200 Subject: [PATCH 046/107] Use VS 2019 image for coverity build Coverity requires a newer tool only installed on more recent images. --- .appveyor.yml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index a14e91d0..a2e7f99c 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -141,10 +141,9 @@ environment: # Coverity - COVERITY: true - # Coverity doesn't really support MSVC 2019 yet - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 - GENERATOR: Visual Studio 15 2017 - BOOST_ROOT: C:\Libraries\boost_1_69_0 + APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 + GENERATOR: Visual Studio 16 2019 + BOOST_ROOT: C:\Libraries\boost_1_77_0 COVERITY_SCAN_TOKEN: secure: FzhGUr+AR/VOBGUta7dDLMDruolChnvyMSvsM/zLvPY= COVERITY_SCAN_NOTIFICATION_EMAIL: From 9fa0e728c559e8350bb49e643a75bd3f414d0283 Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Tue, 14 Jun 2022 09:54:44 +0200 Subject: [PATCH 047/107] Coverity: Run cov-configure first to generate MSVC config This seemingly used to be done already but is now explicitely required. --- .appveyor.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.appveyor.yml b/.appveyor.yml index a2e7f99c..79042f00 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -143,6 +143,7 @@ environment: - COVERITY: true APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 GENERATOR: Visual Studio 16 2019 + configuration: Debug BOOST_ROOT: C:\Libraries\boost_1_77_0 COVERITY_SCAN_TOKEN: secure: FzhGUr+AR/VOBGUta7dDLMDruolChnvyMSvsM/zLvPY= @@ -202,6 +203,7 @@ for: - cmake -G "%GENERATOR%" .. - ps: | nuget install -ExcludeVersion PublishCoverity + cov-configure --msvc cov-build.exe --dir cov-int cmake --build . --config $env:configuration If ($LastExitCode -ne 0) { cat cov-int/build-log.txt From 42b41b2ac1ffe75d60ff7b54550d7f0accb53119 Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Tue, 14 Jun 2022 10:43:18 +0200 Subject: [PATCH 048/107] Replace outdated PublishCoverity by manual commands --- .appveyor.yml | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index 79042f00..d26d7897 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -202,22 +202,16 @@ for: - cd build - cmake -G "%GENERATOR%" .. - ps: | - nuget install -ExcludeVersion PublishCoverity cov-configure --msvc - cov-build.exe --dir cov-int cmake --build . --config $env:configuration + cov-build --dir cov-int cmake --build . --config $env:configuration If ($LastExitCode -ne 0) { cat cov-int/build-log.txt $host.SetShouldExit($LastExitCode) } - PublishCoverity\tools\PublishCoverity.exe compress --nologo -i cov-int -o cov-int.zip --overwrite - - # This may fail due to a wrong HTTP 500 code from coverity, hence the stderr redirection via cmd - # to make the build succeed anyway - cmd /c PublishCoverity\tools\PublishCoverity.exe publish --nologo ` - -t "$env:COVERITY_SCAN_TOKEN" ` - -e "$env:COVERITY_SCAN_NOTIFICATION_EMAIL" ` - -r "$env:APPVEYOR_REPO_NAME" ` - -z "cov-int.zip" ` - -d "Appveyor build for $env:APPVEYOR_REPO_BRANCH" ` - --codeVersion "$env:APPVEYOR_REPO_BRANCH" 2`>`&1 - Write-Host "Done" + 7z a -tzip cov-int.zip cov-int + curl.exe --form token="$env:COVERITY_SCAN_TOKEN" ` + --form email="$env:COVERITY_SCAN_NOTIFICATION_EMAIL" ` + --form file=@cov-int.zip ` + --form version="$env:APPVEYOR_REPO_BRANCH" ` + --form description="Appveyor build for $env:APPVEYOR_REPO_BRANCH" ` + https://scan.coverity.com/builds?project=$env:APPVEYOR_REPO_NAME From d9b19166ca7730f381f4524ff4d8272cb6e4d67c Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Tue, 14 Jun 2022 12:14:54 +0200 Subject: [PATCH 049/107] Make Curl only output errors PowerShell thinks any output to stderr is a failure. --- .appveyor.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.appveyor.yml b/.appveyor.yml index d26d7897..f14b4dd9 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -209,9 +209,14 @@ for: $host.SetShouldExit($LastExitCode) } 7z a -tzip cov-int.zip cov-int - curl.exe --form token="$env:COVERITY_SCAN_TOKEN" ` + curl.exe --fail --silent --show-error ` + --form token="$env:COVERITY_SCAN_TOKEN" ` --form email="$env:COVERITY_SCAN_NOTIFICATION_EMAIL" ` --form file=@cov-int.zip ` --form version="$env:APPVEYOR_REPO_BRANCH" ` --form description="Appveyor build for $env:APPVEYOR_REPO_BRANCH" ` https://scan.coverity.com/builds?project=$env:APPVEYOR_REPO_NAME + If ($LastExitCode -ne 0) { + echo "Upload failed" + $host.SetShouldExit($LastExitCode) + } From 9ae1a236199ef5b60f8f6e7fa21c086b989d584c Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Tue, 14 Jun 2022 11:54:04 +0200 Subject: [PATCH 050/107] Coverity: Mark negative counts to xsputn/xsgetn as intended --- include/boost/nowide/filebuf.hpp | 2 ++ test/test_filebuf.cpp | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/include/boost/nowide/filebuf.hpp b/include/boost/nowide/filebuf.hpp index 957f9c75..9d99e4e6 100644 --- a/include/boost/nowide/filebuf.hpp +++ b/include/boost/nowide/filebuf.hpp @@ -277,6 +277,7 @@ namespace nowide { if(!(mode_ & (std::ios_base::out | std::ios_base::app)) || !stop_reading()) return 0; + assert(n >= 0); // First empty the remaining put area, if any const char* const base = pbase(); const size_t num_buffered = pptr() - base; @@ -323,6 +324,7 @@ namespace nowide { return std::basic_streambuf::xsgetn(s, n); if(!(mode_ & std::ios_base::in) || !stop_writing()) return 0; + assert(n >= 0); std::streamsize num_copied = 0; // First empty the remaining get area, if any const auto num_buffered = egptr() - gptr(); diff --git a/test/test_filebuf.cpp b/test/test_filebuf.cpp index 8c888fb9..c89f16b0 100644 --- a/test/test_filebuf.cpp +++ b/test/test_filebuf.cpp @@ -314,7 +314,9 @@ void test_xsgetn(const std::string& filepath, bool binary) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wrestrict" #endif + // coverity[negative_returns] TEST_EQ(buf.sgetn(&str[0], -1), 0); + // coverity[negative_returns] TEST_EQ(buf.sgetn(&str[0], -999), 0); #if defined(__GNUC__) && __GNUC__ >= 12 #pragma GCC diagnostic pop @@ -375,7 +377,9 @@ void test_xsputn(const std::string& filepath, bool binary) TEST(open_with_buffer(buf, filepath, make_mode(std::ios_base::out | std::ios_base::trunc, binary), buffer)); TEST_EQ(buf.sputn(data.data(), 0), 0); + // coverity[negative_returns] TEST_EQ(buf.sputn(data.data(), -1), 0); + // coverity[negative_returns] TEST_EQ(buf.sputn(data.data(), -999), 0); buf.close(); // No write when closed From 668165bad25c2d814db1f00621a7d52ab067ee40 Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Tue, 14 Jun 2022 11:55:07 +0200 Subject: [PATCH 051/107] Catch any exception in benchmark Coverity detected a potential `bad_cast` due to facets in iostreams and `bad_array_new_length` during `vector` construction. Catch those too with the more general `std::exception` although they are very likely false positives / can never occur. --- test/benchmark_fstream.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/benchmark_fstream.cpp b/test/benchmark_fstream.cpp index 5e8d6c2d..e5c8a382 100644 --- a/test/benchmark_fstream.cpp +++ b/test/benchmark_fstream.cpp @@ -279,7 +279,7 @@ int main(int argc, char** argv) try { test_perf(filename.c_str()); - } catch(const std::runtime_error& err) + } catch(const std::exception& err) { std::cerr << "Benchmarking failed: " << err.what() << std::endl; return 1; From 993deff3cae1fcd2a897cd5629ad70ad46d884ff Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Tue, 14 Jun 2022 11:59:24 +0200 Subject: [PATCH 052/107] Coverity: Remove space in supression comments Seemingly the correct syntax is without that space. --- test/test_codecvt.cpp | 2 +- test/test_convert.cpp | 2 +- test/test_env.cpp | 2 +- test/test_filebuf.cpp | 2 +- test/test_fs.cpp | 2 +- test/test_fstream.cpp | 2 +- test/test_fstream_special.cpp | 2 +- test/test_ifstream.cpp | 2 +- test/test_iostream.cpp | 2 +- test/test_ofstream.cpp | 2 +- test/test_stackstring.cpp | 2 +- test/test_stat.cpp | 2 +- test/test_stdio.cpp | 2 +- test/test_system.cpp | 2 +- test/test_traits.cpp | 2 +- 15 files changed, 15 insertions(+), 15 deletions(-) diff --git a/test/test_codecvt.cpp b/test/test_codecvt.cpp index 8f5e8751..0be3f255 100644 --- a/test/test_codecvt.cpp +++ b/test/test_codecvt.cpp @@ -411,7 +411,7 @@ void test_codecvt_subst() run_all(codecvt_to_wide, codecvt_to_narrow); } -// coverity [root_function] +// coverity[root_function] void test_main(int, char**, char**) { test_codecvt_basic(); diff --git a/test/test_convert.cpp b/test/test_convert.cpp index b0fe6c33..84185c5d 100644 --- a/test/test_convert.cpp +++ b/test/test_convert.cpp @@ -127,7 +127,7 @@ std::string narrow_string_view(const std::wstring& s) } #endif -// coverity [root_function] +// coverity[root_function] void test_main(int, char**, char**) { std::string hello = "\xd7\xa9\xd7\x9c\xd7\x95\xd7\x9d"; diff --git a/test/test_env.cpp b/test/test_env.cpp index f3fdb749..38ded69a 100644 --- a/test/test_env.cpp +++ b/test/test_env.cpp @@ -14,7 +14,7 @@ #include #endif -// coverity [root_function] +// coverity[root_function] void test_main(int, char**, char**) { std::string example = "\xd7\xa9-\xd0\xbc-\xce\xbd"; diff --git a/test/test_filebuf.cpp b/test/test_filebuf.cpp index c89f16b0..ba02961f 100644 --- a/test/test_filebuf.cpp +++ b/test/test_filebuf.cpp @@ -798,7 +798,7 @@ void test_swap(const std::string& filepath) } } -// coverity [root_function] +// coverity[root_function] void test_main(int, char** argv, char**) { const std::string exampleFilename = std::string(argv[0]) + "-\xd7\xa9-\xd0\xbc-\xce\xbd.txt"; diff --git a/test/test_fs.cpp b/test/test_fs.cpp index e22038c6..394ac4c6 100644 --- a/test/test_fs.cpp +++ b/test/test_fs.cpp @@ -21,7 +21,7 @@ #endif #include -// coverity [root_function] +// coverity[root_function] void test_main(int, char** argv, char**) { boost::nowide::nowide_filesystem(); diff --git a/test/test_fstream.cpp b/test/test_fstream.cpp index 292c1deb..7119505c 100644 --- a/test/test_fstream.cpp +++ b/test/test_fstream.cpp @@ -533,7 +533,7 @@ void test_flush(const std::string& filepath) TEST(!fo.seekg(0)); // Does not work on closed stream } -// coverity [root_function] +// coverity[root_function] void test_main(int, char** argv, char**) { const std::string exampleFilename = std::string(argv[0]) + "-\xd7\xa9-\xd0\xbc-\xce\xbd.txt"; diff --git a/test/test_fstream_special.cpp b/test/test_fstream_special.cpp index 870d45e0..108cd271 100644 --- a/test/test_fstream_special.cpp +++ b/test/test_fstream_special.cpp @@ -266,7 +266,7 @@ void testPutback(const char* filename) } } -// coverity [root_function] +// coverity[root_function] void test_main(int, char** argv, char**) { const std::string exampleFilename = std::string(argv[0]) + "-\xd7\xa9-\xd0\xbc-\xce\xbd.txt"; diff --git a/test/test_ifstream.cpp b/test/test_ifstream.cpp index 82cf10a0..3151257e 100644 --- a/test/test_ifstream.cpp +++ b/test/test_ifstream.cpp @@ -199,7 +199,7 @@ void test_move_and_swap(const std::string& filename) } } -// coverity [root_function] +// coverity[root_function] void test_main(int, char** argv, char**) { const std::string exampleFilename = std::string(argv[0]) + "-\xd7\xa9-\xd0\xbc-\xce\xbd.txt"; diff --git a/test/test_iostream.cpp b/test/test_iostream.cpp index 5220b92c..3a9613c3 100644 --- a/test/test_iostream.cpp +++ b/test/test_iostream.cpp @@ -526,7 +526,7 @@ void test_console() #endif #endif -// coverity [root_function] +// coverity[root_function] void test_main(int argc, char** argv, char**) { // LCOV_EXCL_START diff --git a/test/test_ofstream.cpp b/test/test_ofstream.cpp index e5c0c826..a39a914f 100644 --- a/test/test_ofstream.cpp +++ b/test/test_ofstream.cpp @@ -202,7 +202,7 @@ void test_reopen(const std::string& filename) TEST_EQ(read_file(filename3, data_type::binary), testData3); } -// coverity [root_function] +// coverity[root_function] void test_main(int, char** argv, char**) { const std::string exampleFilename = std::string(argv[0]) + "-\xd7\xa9-\xd0\xbc-\xce\xbd.txt"; diff --git a/test/test_stackstring.cpp b/test/test_stackstring.cpp index 0685db5e..8452ba4a 100644 --- a/test/test_stackstring.cpp +++ b/test/test_stackstring.cpp @@ -62,7 +62,7 @@ std::string heap_stackstring_to_narrow(const std::wstring& s) return ss.get(); } -// coverity [root_function] +// coverity[root_function] void test_main(int, char**, char**) { std::string hello = "\xd7\xa9\xd7\x9c\xd7\x95\xd7\x9d"; diff --git a/test/test_stat.cpp b/test/test_stat.cpp index 10acde0a..3cedc2cf 100644 --- a/test/test_stat.cpp +++ b/test/test_stat.cpp @@ -13,7 +13,7 @@ #include #endif -// coverity [root_function] +// coverity[root_function] void test_main(int, char** argv, char**) { const std::string prefix = argv[0]; diff --git a/test/test_stdio.cpp b/test/test_stdio.cpp index 1ca8c10c..409d3c40 100644 --- a/test/test_stdio.cpp +++ b/test/test_stdio.cpp @@ -49,7 +49,7 @@ void noop_invalid_param_handler(const wchar_t*, const wchar_t*, const wchar_t*, {} // LCOV_EXCL_LINE #endif -// coverity [root_function] +// coverity[root_function] void test_main(int, char** argv, char**) { const std::string prefix = argv[0]; diff --git a/test/test_system.cpp b/test/test_system.cpp index 70c1dc4f..50e1937b 100644 --- a/test/test_system.cpp +++ b/test/test_system.cpp @@ -141,7 +141,7 @@ void run_parent(const std::string& exe_path) #endif } -// coverity [root_function] +// coverity[root_function] void test_main(int argc, char** argv, char** env) { const int old_argc = argc; diff --git a/test/test_traits.cpp b/test/test_traits.cpp index 09cae0c3..2c69056f 100644 --- a/test/test_traits.cpp +++ b/test/test_traits.cpp @@ -53,7 +53,7 @@ static_assert(get_data_width::value == sizeof(wchar_t), "!"); static_assert(get_data_width::value == sizeof(char16_t), "!"); static_assert(get_data_width::value == sizeof(char32_t), "!"); -// coverity [root_function] +// coverity[root_function] void test_main(int, char**, char**) { #ifdef BOOST_NOWIDE_TEST_STD_STRINGVIEW From 52f14e579f312e43c05836d5293b28566b4a09a2 Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Fri, 24 Jun 2022 12:11:34 +0200 Subject: [PATCH 053/107] Prepare release 11.2.0 --- CMakeLists.txt | 2 +- doc/changelog.dox | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7ff52fe5..7aabda39 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,7 +15,7 @@ cmake_minimum_required(VERSION 3.9) # Version number starts at 10 to avoid conflicts with Boost version -set(_version 11.1.4) +set(_version 11.2.0) if(BOOST_SUPERPROJECT_SOURCE_DIR) set(_version ${BOOST_SUPERPROJECT_VERSION}) endif() diff --git a/doc/changelog.dox b/doc/changelog.dox index 7aabaf51..4e38e6ec 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -10,12 +10,20 @@ \section changelog Changelog +\subsection changelog_11_2_0 Nowide 11.2.0 +- `filebuf`: Major performance improvement for Bulk I/O +- `filebuf`: Fix wrong return value of `sync` when `fflush` failed +- `filebuf`: Fix possible undefined behavior in a corner case when nothing was actually written but buffer is in "write" mode +- `filebuf`: Limit putback of characters (i.e. `pbackfail`) only allowing putback of buffered characters (may be only 1 character) +- Add missing define `NOWIDE_USE_WCHAR_OVERLOADS` (standalone only) + \subsection changelog_11_1_4 Nowide 11.1.4 - Fix possible redefinition of `_LARGEFILE_SOURCE` - Fix missing include when `BOOST_USE_WINDOWS_H` and `WIN32_LEAN_AND_MEAN` are defined. - Fix compile failures on recent MinGW-w64 compilers - Add sanity checking of the buffer size passed to the (possibly) 64 bit `stat` function - Known issues: Read performance for text files is possibly worse than the `std` streams. Binary files and writing is unaffected. +- Fix possible use-after-free when reusing a closed filebuf \subsection changelog_11_1_3 Nowide 11.1.3 (Boost 1.78) From d4961ebd17249e6d676762488c69c1ebfc27e924 Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Sat, 25 Jun 2022 17:09:05 +0200 Subject: [PATCH 054/107] Add filebuf::open overload accpting a path object --- include/boost/nowide/filebuf.hpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/include/boost/nowide/filebuf.hpp b/include/boost/nowide/filebuf.hpp index 9d99e4e6..8a035f04 100644 --- a/include/boost/nowide/filebuf.hpp +++ b/include/boost/nowide/filebuf.hpp @@ -12,6 +12,7 @@ #include #if BOOST_NOWIDE_USE_FILEBUF_REPLACEMENT #include +#include #include #include #include @@ -161,6 +162,11 @@ namespace nowide { set_unbuffered_read(); return this; } + template + detail::enable_if_path_t open(const Path& file_name, std::ios_base::openmode mode) + { + return open(file_name.c_str(), mode); + } /// /// Same as std::filebuf::close() /// From 5aa0b5ba558f81848fe8c8d9d7acf31644099390 Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Sat, 25 Jun 2022 16:53:06 +0200 Subject: [PATCH 055/107] Add tests for const path::value_type* Add some `static_assert`s checking that the filebuf and fstream classes can be used with `const *::filesystem::path::value_type*` Closes #153 --- test/test_traits.cpp | 76 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 74 insertions(+), 2 deletions(-) diff --git a/test/test_traits.cpp b/test/test_traits.cpp index 2c69056f..8ff71de7 100644 --- a/test/test_traits.cpp +++ b/test/test_traits.cpp @@ -8,6 +8,7 @@ #include #include +#include #include "test.hpp" #include #include @@ -28,6 +29,11 @@ #include #define BOOST_NOWIDE_TEST_STD_PATH #endif +#if defined(__cpp_lib_experimental_filesystem) +#define _SILENCE_EXPERIMENTAL_FILESYSTEM_DEPRECATION_WARNING +#include +#define BOOST_NOWIDE_TEST_STD_EXPERIMENTAL_PATH +#endif #ifdef BOOST_NOWIDE_TEST_BFS_PATH #if defined(__GNUC__) && __GNUC__ >= 7 @@ -39,6 +45,17 @@ #include #endif +template +struct has_open : std::false_type +{}; +using boost::nowide::detail::void_t; +template +struct has_open().open(std::declval(), std::ios_base::openmode{}))>> + : std::true_type +{}; + using boost::nowide::detail::is_string_container; static_assert(is_string_container::value, "!"); static_assert(is_string_container::value, "!"); @@ -65,10 +82,65 @@ void test_main(int, char**, char**) #endif #ifdef BOOST_NOWIDE_TEST_STD_PATH std::cout << "Testing std::filesystem::path" << std::endl; - static_assert(boost::nowide::detail::is_path::value, "!"); + using fs_path = std::filesystem::path; + static_assert(boost::nowide::detail::is_path::value, "!"); +#if BOOST_NOWIDE_USE_FILEBUF_REPLACEMENT + static_assert(has_open::value, "!"); +#endif + static_assert(has_open::value, "!"); + static_assert(has_open::value, "!"); + static_assert(has_open::value, "!"); + static_assert(std::is_constructible::value, "!"); + static_assert(std::is_constructible::value, "!"); + static_assert(std::is_constructible::value, "!"); + static_assert(has_open::value, "!"); + static_assert(has_open::value, "!"); + static_assert(has_open::value, "!"); + static_assert(has_open::value, "!"); + static_assert(std::is_constructible::value, "!"); + static_assert(std::is_constructible::value, "!"); + static_assert(std::is_constructible::value, "!"); +#endif +#ifdef BOOST_NOWIDE_TEST_STD_EXPERIMENTAL_PATH + std::cout << "Testing std::experimental::filesystem::path" << std::endl; + using exfs_path = std::experimental::filesystem::path; + static_assert(boost::nowide::detail::is_path::value, "!"); +#if BOOST_NOWIDE_USE_FILEBUF_REPLACEMENT + static_assert(has_open::value, "!"); +#endif + static_assert(has_open::value, "!"); + static_assert(has_open::value, "!"); + static_assert(has_open::value, "!"); + static_assert(std::is_constructible::value, "!"); + static_assert(std::is_constructible::value, "!"); + static_assert(std::is_constructible::value, "!"); + static_assert(has_open::value, "!"); + static_assert(has_open::value, "!"); + static_assert(has_open::value, "!"); + static_assert(has_open::value, "!"); + static_assert(std::is_constructible::value, "!"); + static_assert(std::is_constructible::value, "!"); + static_assert(std::is_constructible::value, "!"); #endif #ifdef BOOST_NOWIDE_TEST_BFS_PATH std::cout << "Testing boost::filesystem::path" << std::endl; - static_assert(boost::nowide::detail::is_path::value, "!"); + using bfs_path = boost::filesystem::path; + static_assert(boost::nowide::detail::is_path::value, "!"); +#if BOOST_NOWIDE_USE_FILEBUF_REPLACEMENT + static_assert(has_open::value, "!"); +#endif + static_assert(has_open::value, "!"); + static_assert(has_open::value, "!"); + static_assert(has_open::value, "!"); + static_assert(std::is_constructible::value, "!"); + static_assert(std::is_constructible::value, "!"); + static_assert(std::is_constructible::value, "!"); + static_assert(has_open::value, "!"); + static_assert(has_open::value, "!"); + static_assert(has_open::value, "!"); + static_assert(has_open::value, "!"); + static_assert(std::is_constructible::value, "!"); + static_assert(std::is_constructible::value, "!"); + static_assert(std::is_constructible::value, "!"); #endif } From dee17516f5bfd0cad64876095e42074f38560c4f Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Sat, 25 Jun 2022 17:20:42 +0200 Subject: [PATCH 056/107] CI: Test standalone release tarball --- .github/workflows/release.yml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index a0b253f0..089a8905 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -43,10 +43,22 @@ jobs: sudo apt-get install doxygen doc/gendoc.sh tar -czf documentation.tar.gz doc index.html + - name: Create standalone version run: | bash tools/create_standalone.sh nowide_standalone_${{steps.get_tag.outputs.tag}} tar -czf nowide_standalone.tar.gz nowide_standalone_${{steps.get_tag.outputs.tag}} + - name: Test standalone release tarball + run: | + tmp_dir=$(mktemp -d -p "$RUNNER_TEMP") + cd "$tmp_dir" + tar -xf "${{github.workspace}}/nowide_standalone.tar.gz" + src_dir="$PWD/nowide_standalone_${{steps.get_tag.outputs.tag}}" + mkdir build && cd build + cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX=${{runner.workspace}}/../install "$src_dir" + cmake --build . --config Debug --target install + ctest --output-on-failure -C Debug --verbose + - name: Create Boost version run: | FOLDER="nowide_${{steps.get_tag.outputs.tag}}" @@ -65,6 +77,7 @@ jobs: cmake -DBoost_DEBUG=ON -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX=${{runner.workspace}}/../install "$src_dir" cmake --build . --config Debug --target install ctest --output-on-failure -C Debug --verbose + - name: Create Release if: github.event_name == 'push' id: create_release From a091a1a9e8a24325dc07d87d0fdf7f640e53bd1b Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Mon, 27 Jun 2022 10:53:15 +0200 Subject: [PATCH 057/107] Update readme Add dependencies and Regression test runner links --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 1be035a7..537be663 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,9 @@ # Boost.Nowide -Branch | Appveyor | Github | codecov.io | Documentation -------------|----------|--------|------------|-------------- -[master](https://github.com/boostorg/nowide/tree/master) | [![Build status](https://ci.appveyor.com/api/projects/status/w5sywrekwd66say4/branch/master?svg=true)](https://ci.appveyor.com/project/Flamefire/nowide-fr98b/branch/master) | ![](https://github.com/boostorg/nowide/workflows/CI%20Tests/badge.svg?branch=master) ![](https://github.com/boostorg/nowide/workflows/POSIX/badge.svg?branch=master) | [![codecov](https://codecov.io/gh/boostorg/nowide/branch/master/graph/badge.svg)](https://codecov.io/gh/boostorg/nowide/branch/master) | [![Documentation](https://img.shields.io/badge/documentation-master-brightgreen.svg)](https://www.boost.org/doc/libs/master/libs/nowide/index.html) -[develop](https://github.com/boostorg/nowide/tree/develop) | [![Build status](https://ci.appveyor.com/api/projects/status/w5sywrekwd66say4/branch/develop?svg=true)](https://ci.appveyor.com/project/Flamefire/nowide-fr98b/branch/develop) | ![](https://github.com/boostorg/nowide/workflows/CI%20Tests/badge.svg?branch=develop) ![](https://github.com/boostorg/nowide/workflows/POSIX/badge.svg?branch=develop) | [![codecov](https://codecov.io/gh/boostorg/nowide/branch/develop/graph/badge.svg)](https://codecov.io/gh/boostorg/nowide/branch/develop) | [![Documentation](https://img.shields.io/badge/documentation-develop-brightgreen.svg)](https://www.boost.org/doc/libs/develop/libs/nowide/index.html) +Branch | Appveyor | Github | codecov.io | Deps | Docs | Tests | +------------|----------|--------|------------| ---- | ---- | ----- | +[master](https://github.com/boostorg/nowide/tree/master) | [![Build status](https://ci.appveyor.com/api/projects/status/w5sywrekwd66say4/branch/master?svg=true)](https://ci.appveyor.com/project/Flamefire/nowide-fr98b/branch/master) | ![](https://github.com/boostorg/nowide/workflows/CI%20Tests/badge.svg?branch=master) ![](https://github.com/boostorg/nowide/workflows/POSIX/badge.svg?branch=master) | [![codecov](https://codecov.io/gh/boostorg/nowide/branch/master/graph/badge.svg)](https://codecov.io/gh/boostorg/nowide/branch/master) | [![Deps](https://img.shields.io/badge/deps-master-brightgreen.svg)](https://pdimov.github.io/boostdep-report/master/nowide.html) | [![Documentation](https://img.shields.io/badge/docs-master-brightgreen.svg)](https://www.boost.org/doc/libs/master/libs/nowide/index.html) | [![Enter the Matrix](https://img.shields.io/badge/matrix-master-brightgreen.svg)](http://www.boost.org/development/tests/master/developer/nowide.html) +[develop](https://github.com/boostorg/nowide/tree/develop) | [![Build status](https://ci.appveyor.com/api/projects/status/w5sywrekwd66say4/branch/develop?svg=true)](https://ci.appveyor.com/project/Flamefire/nowide-fr98b/branch/develop) | ![](https://github.com/boostorg/nowide/workflows/CI%20Tests/badge.svg?branch=develop) ![](https://github.com/boostorg/nowide/workflows/POSIX/badge.svg?branch=develop) | [![codecov](https://codecov.io/gh/boostorg/nowide/branch/develop/graph/badge.svg)](https://codecov.io/gh/boostorg/nowide/branch/develop) | [![Deps](https://img.shields.io/badge/deps-develop-brightgreen.svg)](https://pdimov.github.io/boostdep-report/develop/nowide.html) | [![Documentation](https://img.shields.io/badge/docs-develop-brightgreen.svg)](https://www.boost.org/doc/libs/develop/libs/nowide/index.html) | [![Enter the Matrix](https://img.shields.io/badge/matrix-develop-brightgreen.svg)](http://www.boost.org/development/tests/develop/developer/nowide.html) Quality checks: [![Coverity Scan Build Status](https://scan.coverity.com/projects/20464/badge.svg)](https://scan.coverity.com/projects/boostorg-nowide) From a0327e0b74de19312b878e0e6ff212f24bc94db3 Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Wed, 13 Jul 2022 12:35:54 +0200 Subject: [PATCH 058/107] Update license headers Use the more concise format omitting the reference to the license file and refer to the URL only. --- .appveyor.yml | 5 ++-- .azure-pipelines.yml | 2 +- .github/workflows/ci.yml | 3 ++- .github/workflows/ci_tests.yml | 2 +- .github/workflows/release.yml | 2 +- .github/workflows/update_standalone.yml | 2 +- CMakeLists.txt | 2 +- README.md | 10 ++++---- build/Jamfile.v2 | 7 +++--- config/check_attribute_init_priority.cpp | 7 +++--- config/check_lfs_support.cpp | 7 +++--- config/check_movable_fstreams.cpp | 7 +++--- doc/Jamfile.v2 | 4 ++-- doc/LICENSE_1_0.txt | 23 ------------------- doc/changelog.dox | 8 +++---- doc/gendoc.sh | 10 ++++---- doc/main.dox | 10 ++++---- include/boost/nowide/args.hpp | 9 ++++---- include/boost/nowide/config.hpp | 11 ++++----- include/boost/nowide/convert.hpp | 11 ++++----- include/boost/nowide/cstdio.hpp | 11 ++++----- include/boost/nowide/cstdlib.hpp | 9 ++++---- include/boost/nowide/detail/convert.hpp | 9 ++++---- include/boost/nowide/detail/is_path.hpp | 9 ++++---- .../nowide/detail/is_string_container.hpp | 9 ++++---- include/boost/nowide/detail/utf.hpp | 9 ++++---- include/boost/nowide/filebuf.hpp | 11 ++++----- include/boost/nowide/filesystem.hpp | 9 ++++---- include/boost/nowide/fstream.hpp | 9 ++++---- include/boost/nowide/iostream.hpp | 9 ++++---- include/boost/nowide/replacement.hpp | 9 ++++---- include/boost/nowide/stackstring.hpp | 9 ++++---- include/boost/nowide/stat.hpp | 8 +++---- include/boost/nowide/utf/convert.hpp | 11 ++++----- include/boost/nowide/utf/utf.hpp | 11 ++++----- include/boost/nowide/utf8_codecvt.hpp | 11 ++++----- include/boost/nowide/windows.hpp | 11 ++++----- src/console_buffer.cpp | 9 ++++---- src/console_buffer.hpp | 9 ++++---- src/cstdio.cpp | 10 ++++---- src/cstdlib.cpp | 10 ++++---- src/filebuf.cpp | 8 +++---- src/iostream.cpp | 9 ++++---- src/stat.cpp | 7 +++--- standalone/config.hpp | 11 ++++----- test/CMakeLists.txt | 2 +- test/Jamfile.v2 | 5 +--- test/benchmark_fstream.cpp | 10 ++++---- test/cmake_test/CMakeLists.txt | 3 ++- test/cmake_test/main.cpp | 8 +++---- test/file_test_helpers.cpp | 7 +++--- test/file_test_helpers.hpp | 7 +++--- test/test.hpp | 11 ++++----- test/test_codecvt.cpp | 8 +++---- test/test_convert.cpp | 8 +++---- test/test_env.cpp | 8 +++---- test/test_filebuf.cpp | 9 ++++---- test/test_fs.cpp | 10 ++++---- test/test_fstream.cpp | 9 ++++---- test/test_fstream_special.cpp | 9 ++++---- test/test_ifstream.cpp | 9 ++++---- test/test_iostream.cpp | 9 ++++---- test/test_iostream_passthrough.cmake | 2 +- test/test_ofstream.cpp | 9 ++++---- test/test_sets.hpp | 9 ++++---- test/test_stackstring.cpp | 10 ++++---- test/test_stat.cpp | 7 +++--- test/test_stdio.cpp | 10 ++++---- test/test_system.cpp | 9 ++++---- test/test_traits.cpp | 8 +++---- tools/create_standalone.sh | 2 +- 71 files changed, 242 insertions(+), 335 deletions(-) delete mode 100644 doc/LICENSE_1_0.txt diff --git a/.appveyor.yml b/.appveyor.yml index f14b4dd9..08cf18de 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -1,8 +1,9 @@ # Copyright 2016, 2017 Peter Dimov # Copyright 2017 - 2019 James E. King III # Copyright 2019 - 2022 Alexander Grund +# # Distributed under the Boost Software License, Version 1.0. -# (See accompanying file LICENSE or copy at http://boost.org/LICENSE_1_0.txt) +# https://www.boost.org/LICENSE_1_0.txt version: 1.0.{build}-{branch} @@ -27,7 +28,7 @@ environment: global: B2_CI_VERSION: 1 GIT_FETCH_JOBS: 4 - # see: http://www.boost.org/build/doc/html/bbv2/overview/invocation.html#bbv2.overview.invocation.properties + # see: https://www.boost.org/build/doc/html/bbv2/overview/invocation.html#bbv2.overview.invocation.properties # to use the default for a given environment, comment it out; recommend you build debug and release however: # on Windows it is important to exercise all the possibilities, especially shared vs static, however most # libraries that care about this exercise it in their Jamfiles... diff --git a/.azure-pipelines.yml b/.azure-pipelines.yml index 6796e039..57b9acb7 100644 --- a/.azure-pipelines.yml +++ b/.azure-pipelines.yml @@ -3,7 +3,7 @@ # Copyright 2019 Mateusz Loskot # Copyright 2020-2021 Alexander Grund # Distributed under the Boost Software License, Version 1.0. -# (See accompanying file LICENSE_1_0.txt or copy at http://boost.org/LICENSE_1_0.txt) +# https://www.boost.org/LICENSE_1_0.txt # # Generic Azure Pipelines build script for boostorg repositories diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 110369f6..a78770eb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -4,7 +4,8 @@ # Copyright 2022 James E. King III # # Distributed under the Boost Software License, Version 1.0. -# (See accompanying file LICENSE_1_0.txt or copy at http://boost.org/LICENSE_1_0.txt) +# https://www.boost.org/LICENSE_1_0.txt + --- name: CI diff --git a/.github/workflows/ci_tests.yml b/.github/workflows/ci_tests.yml index d707372a..0d7151fa 100644 --- a/.github/workflows/ci_tests.yml +++ b/.github/workflows/ci_tests.yml @@ -1,6 +1,6 @@ # Copyright 2019 - 2022 Alexander Grund # Distributed under the Boost Software License, Version 1.0. -# (See accompanying file LICENSE or copy at http://boost.org/LICENSE_1_0.txt) +# https://www.boost.org/LICENSE_1_0.txt name: CI Tests diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 089a8905..30523234 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,6 +1,6 @@ # Copyright 2019 - 2020 Alexander Grund # Distributed under the Boost Software License, Version 1.0. -# (See accompanying file LICENSE or copy at http://boost.org/LICENSE_1_0.txt) +# https://www.boost.org/LICENSE_1_0.txt on: push: diff --git a/.github/workflows/update_standalone.yml b/.github/workflows/update_standalone.yml index b74a818d..4adb99b1 100644 --- a/.github/workflows/update_standalone.yml +++ b/.github/workflows/update_standalone.yml @@ -1,6 +1,6 @@ # Copyright 2019 - 2021 Alexander Grund # Distributed under the Boost Software License, Version 1.0. -# (See accompanying file LICENSE or copy at http://boost.org/LICENSE_1_0.txt) +# https://www.boost.org/LICENSE_1_0.txt on: push: diff --git a/CMakeLists.txt b/CMakeLists.txt index 7aabda39..cc97ce8d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ # Copyright 2019 - 2020 Alexander Grund # Distributed under the Boost Software License, Version 1.0. -# (See accompanying file LICENSE or copy at http://boost.org/LICENSE_1_0.txt) +# https://www.boost.org/LICENSE_1_0.txt # Builds the libraries for Boost.Nowide # diff --git a/README.md b/README.md index 537be663..b2f981f3 100644 --- a/README.md +++ b/README.md @@ -2,8 +2,8 @@ Branch | Appveyor | Github | codecov.io | Deps | Docs | Tests | ------------|----------|--------|------------| ---- | ---- | ----- | -[master](https://github.com/boostorg/nowide/tree/master) | [![Build status](https://ci.appveyor.com/api/projects/status/w5sywrekwd66say4/branch/master?svg=true)](https://ci.appveyor.com/project/Flamefire/nowide-fr98b/branch/master) | ![](https://github.com/boostorg/nowide/workflows/CI%20Tests/badge.svg?branch=master) ![](https://github.com/boostorg/nowide/workflows/POSIX/badge.svg?branch=master) | [![codecov](https://codecov.io/gh/boostorg/nowide/branch/master/graph/badge.svg)](https://codecov.io/gh/boostorg/nowide/branch/master) | [![Deps](https://img.shields.io/badge/deps-master-brightgreen.svg)](https://pdimov.github.io/boostdep-report/master/nowide.html) | [![Documentation](https://img.shields.io/badge/docs-master-brightgreen.svg)](https://www.boost.org/doc/libs/master/libs/nowide/index.html) | [![Enter the Matrix](https://img.shields.io/badge/matrix-master-brightgreen.svg)](http://www.boost.org/development/tests/master/developer/nowide.html) -[develop](https://github.com/boostorg/nowide/tree/develop) | [![Build status](https://ci.appveyor.com/api/projects/status/w5sywrekwd66say4/branch/develop?svg=true)](https://ci.appveyor.com/project/Flamefire/nowide-fr98b/branch/develop) | ![](https://github.com/boostorg/nowide/workflows/CI%20Tests/badge.svg?branch=develop) ![](https://github.com/boostorg/nowide/workflows/POSIX/badge.svg?branch=develop) | [![codecov](https://codecov.io/gh/boostorg/nowide/branch/develop/graph/badge.svg)](https://codecov.io/gh/boostorg/nowide/branch/develop) | [![Deps](https://img.shields.io/badge/deps-develop-brightgreen.svg)](https://pdimov.github.io/boostdep-report/develop/nowide.html) | [![Documentation](https://img.shields.io/badge/docs-develop-brightgreen.svg)](https://www.boost.org/doc/libs/develop/libs/nowide/index.html) | [![Enter the Matrix](https://img.shields.io/badge/matrix-develop-brightgreen.svg)](http://www.boost.org/development/tests/develop/developer/nowide.html) +[master](https://github.com/boostorg/nowide/tree/master) | [![Build status](https://ci.appveyor.com/api/projects/status/w5sywrekwd66say4/branch/master?svg=true)](https://ci.appveyor.com/project/Flamefire/nowide-fr98b/branch/master) | ![](https://github.com/boostorg/nowide/workflows/CI%20Tests/badge.svg?branch=master) ![](https://github.com/boostorg/nowide/workflows/POSIX/badge.svg?branch=master) | [![codecov](https://codecov.io/gh/boostorg/nowide/branch/master/graph/badge.svg)](https://codecov.io/gh/boostorg/nowide/branch/master) | [![Deps](https://img.shields.io/badge/deps-master-brightgreen.svg)](https://pdimov.github.io/boostdep-report/master/nowide.html) | [![Documentation](https://img.shields.io/badge/docs-master-brightgreen.svg)](https://www.boost.org/doc/libs/master/libs/nowide/index.html) | [![Enter the Matrix](https://img.shields.io/badge/matrix-master-brightgreen.svg)](https://www.boost.org/development/tests/master/developer/nowide.html) +[develop](https://github.com/boostorg/nowide/tree/develop) | [![Build status](https://ci.appveyor.com/api/projects/status/w5sywrekwd66say4/branch/develop?svg=true)](https://ci.appveyor.com/project/Flamefire/nowide-fr98b/branch/develop) | ![](https://github.com/boostorg/nowide/workflows/CI%20Tests/badge.svg?branch=develop) ![](https://github.com/boostorg/nowide/workflows/POSIX/badge.svg?branch=develop) | [![codecov](https://codecov.io/gh/boostorg/nowide/branch/develop/graph/badge.svg)](https://codecov.io/gh/boostorg/nowide/branch/develop) | [![Deps](https://img.shields.io/badge/deps-develop-brightgreen.svg)](https://pdimov.github.io/boostdep-report/develop/nowide.html) | [![Documentation](https://img.shields.io/badge/docs-develop-brightgreen.svg)](https://www.boost.org/doc/libs/develop/libs/nowide/index.html) | [![Enter the Matrix](https://img.shields.io/badge/matrix-develop-brightgreen.svg)](https://www.boost.org/development/tests/develop/developer/nowide.html) Quality checks: [![Coverity Scan Build Status](https://scan.coverity.com/projects/20464/badge.svg)](https://scan.coverity.com/projects/boostorg-nowide) @@ -15,7 +15,7 @@ The library provides an implementation of standard C and C++ library functions, ### License -Distributed under the [Boost Software License, Version 1.0](http://www.boost.org/LICENSE_1_0.txt). +Distributed under the [Boost Software License, Version 1.0](https://www.boost.org/LICENSE_1_0.txt). ### Properties @@ -104,5 +104,5 @@ Boost.Nowide integrates with Boost.Filesystem: * [Ask questions](http://stackoverflow.com/questions/ask?tags=c%2B%2B,boost,boost-nowide) * [Report bugs](https://github.com/boostorg/nowide/issues): Be sure to mention Boost version, platform and compiler you're using. A small compilable code sample to reproduce the problem is always good as well. -* Submit your patches as pull requests against **develop** branch. Note that by submitting patches you agree to license your modifications under the [Boost Software License, Version 1.0](http://www.boost.org/LICENSE_1_0.txt). -* Discussions about the library are held on the [Boost developers mailing list](http://www.boost.org/community/groups.html#main). Be sure to read the [discussion policy](http://www.boost.org/community/policy.html) before posting and add the `[nowide]` tag at the beginning of the subject line. +* Submit your patches as pull requests against **develop** branch. Note that by submitting patches you agree to license your modifications under the [Boost Software License, Version 1.0](https://www.boost.org/LICENSE_1_0.txt). +* Discussions about the library are held on the [Boost developers mailing list](https://www.boost.org/community/groups.html#main). Be sure to read the [discussion policy](https://www.boost.org/community/policy.html) before posting and add the `[nowide]` tag at the beginning of the subject line. diff --git a/build/Jamfile.v2 b/build/Jamfile.v2 index 3cf8988b..0eab1694 100644 --- a/build/Jamfile.v2 +++ b/build/Jamfile.v2 @@ -1,12 +1,11 @@ -# Boost Nowide Library Build Jamfile - # Copyright (c) 2002, 2006 Beman Dawes # Copyright (c) 2012 Artyom Beilis (Tonkikh) # Copyright (c) 2020-2021 Alexander Grund # # Distributed under the Boost Software License, Version 1.0. -# (See accompanying file LICENSE or www.boost.org/LICENSE_1_0.txt) -# See library home page at http://www.boost.org/libs/nowide +# https://www.boost.org/LICENSE_1_0.txt +# +# See library home page at https://www.boost.org/libs/nowide import ../../config/checks/config : requires ; import configure ; diff --git a/config/check_attribute_init_priority.cpp b/config/check_attribute_init_priority.cpp index 7525fe08..fab03e24 100644 --- a/config/check_attribute_init_priority.cpp +++ b/config/check_attribute_init_priority.cpp @@ -1,8 +1,7 @@ -// Copyright (c) 2021 Alexander Grund -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE or copy at http://www.boost.org/LICENSE.txt) +// Copyright (c) 2021 Alexander Grund // +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt class Foo {}; diff --git a/config/check_lfs_support.cpp b/config/check_lfs_support.cpp index 095c614f..791787f7 100644 --- a/config/check_lfs_support.cpp +++ b/config/check_lfs_support.cpp @@ -1,9 +1,8 @@ // -// Copyright (c) 2020 Alexander Grund -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE or copy at http://www.boost.org/LICENSE.txt) +// Copyright (c) 2020 Alexander Grund // +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt #define _LARGEFILE_SOURCE #ifndef _FILE_OFFSET_BITS diff --git a/config/check_movable_fstreams.cpp b/config/check_movable_fstreams.cpp index 4970d9d7..ed6be385 100644 --- a/config/check_movable_fstreams.cpp +++ b/config/check_movable_fstreams.cpp @@ -1,9 +1,8 @@ // -// Copyright (c) 2020 Alexander Grund -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE or copy at http://www.boost.org/LICENSE.txt) +// Copyright (c) 2020 Alexander Grund // +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt #include #include diff --git a/doc/Jamfile.v2 b/doc/Jamfile.v2 index b6f0ba6b..e03d6af3 100644 --- a/doc/Jamfile.v2 +++ b/doc/Jamfile.v2 @@ -1,7 +1,7 @@ # Copyright (C) 2019-2019 Alexander Grund +# # Distributed under the Boost Software License, Version 1.0 -# (see accompanying file LICENSE or a copy at -# http://www.boost.org/LICENSE_1_0.txt) +# https://www.boost.org/LICENSE_1_0.txt using doxygen ; import doxygen ; diff --git a/doc/LICENSE_1_0.txt b/doc/LICENSE_1_0.txt deleted file mode 100644 index 36b7cd93..00000000 --- a/doc/LICENSE_1_0.txt +++ /dev/null @@ -1,23 +0,0 @@ -Boost Software License - Version 1.0 - August 17th, 2003 - -Permission is hereby granted, free of charge, to any person or organization -obtaining a copy of the software and accompanying documentation covered by -this license (the "Software") to use, reproduce, display, distribute, -execute, and transmit the Software, and to prepare derivative works of the -Software, and to permit third-parties to whom the Software is furnished to -do so, all subject to the following: - -The copyright notices in the Software and this entire statement, including -the above license grant, this restriction and the following disclaimer, -must be included in all copies of the Software, in whole or in part, and -all derivative works of the Software, unless such copies or derivative -works are solely in the form of machine-executable object code generated by -a source language processor. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT -SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE -FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. diff --git a/doc/changelog.dox b/doc/changelog.dox index 4e38e6ec..612daa38 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -1,10 +1,8 @@ // -// Copyright (c) 2019-2021 Alexander Grund -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE or copy at -// http://www.boost.org/LICENSE_1_0.txt) +// Copyright (c) 2019-2021 Alexander Grund // +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt /*! \page changelog_page Changelog diff --git a/doc/gendoc.sh b/doc/gendoc.sh index e57dbc0e..cdf52a0c 100755 --- a/doc/gendoc.sh +++ b/doc/gendoc.sh @@ -1,11 +1,9 @@ #!/bin/bash + +# Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) # -# Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) -# -# Distributed under the Boost Software License, Version 1.0. (See -# accompanying file LICENSE or copy at -# http://www.boost.org/LICENSE_1_0.txt) -# +# Distributed under the Boost Software License, Version 1.0. +# https://www.boost.org/LICENSE_1_0.txt set -euo pipefail diff --git a/doc/main.dox b/doc/main.dox index 0b11cfca..4ebf5c13 100644 --- a/doc/main.dox +++ b/doc/main.dox @@ -1,11 +1,9 @@ // -// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) -// Copyright (c) 2019-2020 Alexander Grund -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE or copy at -// http://www.boost.org/LICENSE_1_0.txt) +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// Copyright (c) 2019-2020 Alexander Grund // +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt /*! diff --git a/include/boost/nowide/args.hpp b/include/boost/nowide/args.hpp index 3c7a47ce..6c382dce 100644 --- a/include/boost/nowide/args.hpp +++ b/include/boost/nowide/args.hpp @@ -1,10 +1,9 @@ // -// Copyright (c) 2012 Artyom Beilis (Tonkikh) -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE or copy at -// http://www.boost.org/LICENSE_1_0.txt) +// Copyright (c) 2012 Artyom Beilis (Tonkikh) // +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + #ifndef BOOST_NOWIDE_ARGS_HPP_INCLUDED #define BOOST_NOWIDE_ARGS_HPP_INCLUDED diff --git a/include/boost/nowide/config.hpp b/include/boost/nowide/config.hpp index f18e69b6..1ba7c5f5 100644 --- a/include/boost/nowide/config.hpp +++ b/include/boost/nowide/config.hpp @@ -1,11 +1,10 @@ // -// Copyright (c) 2012 Artyom Beilis (Tonkikh) -// Copyright (c) 2019 - 2022 Alexander Grund -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE or copy at -// http://www.boost.org/LICENSE_1_0.txt) +// Copyright (c) 2012 Artyom Beilis (Tonkikh) +// Copyright (c) 2019 - 2022 Alexander Grund // +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + #ifndef BOOST_NOWIDE_CONFIG_HPP_INCLUDED #define BOOST_NOWIDE_CONFIG_HPP_INCLUDED diff --git a/include/boost/nowide/convert.hpp b/include/boost/nowide/convert.hpp index 5e913d8a..10bc2f1f 100644 --- a/include/boost/nowide/convert.hpp +++ b/include/boost/nowide/convert.hpp @@ -1,11 +1,10 @@ // -// Copyright (c) 2012 Artyom Beilis (Tonkikh) -// Copyright (c) 2020 Alexander Grund -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE or copy at -// http://www.boost.org/LICENSE_1_0.txt) +// Copyright (c) 2012 Artyom Beilis (Tonkikh) +// Copyright (c) 2020 Alexander Grund // +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + #ifndef BOOST_NOWIDE_CONVERT_HPP_INCLUDED #define BOOST_NOWIDE_CONVERT_HPP_INCLUDED diff --git a/include/boost/nowide/cstdio.hpp b/include/boost/nowide/cstdio.hpp index f3b4b5db..4cdad947 100644 --- a/include/boost/nowide/cstdio.hpp +++ b/include/boost/nowide/cstdio.hpp @@ -1,11 +1,10 @@ // -// Copyright (c) 2012 Artyom Beilis (Tonkikh) -// Copyright (c) 2020 Alexander Grund -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE or copy at -// http://www.boost.org/LICENSE_1_0.txt) +// Copyright (c) 2012 Artyom Beilis (Tonkikh) +// Copyright (c) 2020 Alexander Grund // +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + #ifndef BOOST_NOWIDE_CSTDIO_HPP_INCLUDED #define BOOST_NOWIDE_CSTDIO_HPP_INCLUDED diff --git a/include/boost/nowide/cstdlib.hpp b/include/boost/nowide/cstdlib.hpp index 1f89e729..a48028a1 100644 --- a/include/boost/nowide/cstdlib.hpp +++ b/include/boost/nowide/cstdlib.hpp @@ -1,10 +1,9 @@ // -// Copyright (c) 2012 Artyom Beilis (Tonkikh) -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE or copy at -// http://www.boost.org/LICENSE_1_0.txt) +// Copyright (c) 2012 Artyom Beilis (Tonkikh) // +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + #ifndef BOOST_NOWIDE_CSTDLIB_HPP_INCLUDED #define BOOST_NOWIDE_CSTDLIB_HPP_INCLUDED diff --git a/include/boost/nowide/detail/convert.hpp b/include/boost/nowide/detail/convert.hpp index 5fcf3a1a..39593fa7 100644 --- a/include/boost/nowide/detail/convert.hpp +++ b/include/boost/nowide/detail/convert.hpp @@ -1,10 +1,9 @@ // -// Copyright (c) 2020 Alexander Grund -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE or copy at -// http://www.boost.org/LICENSE_1_0.txt) +// Copyright (c) 2020 Alexander Grund // +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + #ifndef BOOST_NOWIDE_DETAIL_CONVERT_HPP_INCLUDED #define BOOST_NOWIDE_DETAIL_CONVERT_HPP_INCLUDED diff --git a/include/boost/nowide/detail/is_path.hpp b/include/boost/nowide/detail/is_path.hpp index aee11b43..84413c31 100644 --- a/include/boost/nowide/detail/is_path.hpp +++ b/include/boost/nowide/detail/is_path.hpp @@ -1,10 +1,9 @@ // -// Copyright (c) 2020 Alexander Grund -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE or copy at -// http://www.boost.org/LICENSE_1_0.txt) +// Copyright (c) 2020 Alexander Grund // +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + #ifndef BOOST_NOWIDE_DETAIL_IS_PATH_HPP_INCLUDED #define BOOST_NOWIDE_DETAIL_IS_PATH_HPP_INCLUDED diff --git a/include/boost/nowide/detail/is_string_container.hpp b/include/boost/nowide/detail/is_string_container.hpp index 1b54a608..ffaa94b4 100644 --- a/include/boost/nowide/detail/is_string_container.hpp +++ b/include/boost/nowide/detail/is_string_container.hpp @@ -1,10 +1,9 @@ // -// Copyright (c) 2020 Alexander Grund -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE or copy at -// http://www.boost.org/LICENSE_1_0.txt) +// Copyright (c) 2020 Alexander Grund // +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + #ifndef BOOST_NOWIDE_DETAIL_IS_STRING_CONTAINER_HPP_INCLUDED #define BOOST_NOWIDE_DETAIL_IS_STRING_CONTAINER_HPP_INCLUDED diff --git a/include/boost/nowide/detail/utf.hpp b/include/boost/nowide/detail/utf.hpp index 09302817..11b723fa 100644 --- a/include/boost/nowide/detail/utf.hpp +++ b/include/boost/nowide/detail/utf.hpp @@ -1,10 +1,9 @@ // -// Copyright (c) 2020 Alexander Grund -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE or copy at -// http://www.boost.org/LICENSE_1_0.txt) +// Copyright (c) 2020 Alexander Grund // +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + #ifndef BOOST_NOWIDE_DETAIL_UTF_HPP_INCLUDED #define BOOST_NOWIDE_DETAIL_UTF_HPP_INCLUDED diff --git a/include/boost/nowide/filebuf.hpp b/include/boost/nowide/filebuf.hpp index 8a035f04..5e124243 100644 --- a/include/boost/nowide/filebuf.hpp +++ b/include/boost/nowide/filebuf.hpp @@ -1,11 +1,10 @@ // -// Copyright (c) 2012 Artyom Beilis (Tonkikh) -// Copyright (c) 2019-2020 Alexander Grund -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE or copy at -// http://www.boost.org/LICENSE_1_0.txt) +// Copyright (c) 2012 Artyom Beilis (Tonkikh) +// Copyright (c) 2019-2020 Alexander Grund // +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + #ifndef BOOST_NOWIDE_FILEBUF_HPP_INCLUDED #define BOOST_NOWIDE_FILEBUF_HPP_INCLUDED diff --git a/include/boost/nowide/filesystem.hpp b/include/boost/nowide/filesystem.hpp index 1df0c945..4ed205ec 100644 --- a/include/boost/nowide/filesystem.hpp +++ b/include/boost/nowide/filesystem.hpp @@ -1,10 +1,9 @@ // -// Copyright (c) 2012 Artyom Beilis (Tonkikh) -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE or copy at -// http://www.boost.org/LICENSE_1_0.txt) +// Copyright (c) 2012 Artyom Beilis (Tonkikh) // +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + #ifndef BOOST_NOWIDE_INTEGRATION_FILESYSTEM_HPP_INCLUDED #define BOOST_NOWIDE_INTEGRATION_FILESYSTEM_HPP_INCLUDED diff --git a/include/boost/nowide/fstream.hpp b/include/boost/nowide/fstream.hpp index 1829ff42..bcb271b3 100644 --- a/include/boost/nowide/fstream.hpp +++ b/include/boost/nowide/fstream.hpp @@ -1,10 +1,9 @@ // -// Copyright (c) 2012 Artyom Beilis (Tonkikh) -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE or copy at -// http://www.boost.org/LICENSE_1_0.txt) +// Copyright (c) 2012 Artyom Beilis (Tonkikh) // +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + #ifndef BOOST_NOWIDE_FSTREAM_HPP_INCLUDED #define BOOST_NOWIDE_FSTREAM_HPP_INCLUDED diff --git a/include/boost/nowide/iostream.hpp b/include/boost/nowide/iostream.hpp index 3c09203c..54f14001 100644 --- a/include/boost/nowide/iostream.hpp +++ b/include/boost/nowide/iostream.hpp @@ -1,9 +1,8 @@ -// Copyright (c) 2012 Artyom Beilis (Tonkikh) -// Copyright (c) 2020-2021 Alexander Grund +// Copyright (c) 2012 Artyom Beilis (Tonkikh) +// Copyright (c) 2020-2021 Alexander Grund // -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE or copy at -// http://www.boost.org/LICENSE_1_0.txt) +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt #ifndef BOOST_NOWIDE_IOSTREAM_HPP_INCLUDED #define BOOST_NOWIDE_IOSTREAM_HPP_INCLUDED diff --git a/include/boost/nowide/replacement.hpp b/include/boost/nowide/replacement.hpp index 4f116277..e44c26bd 100644 --- a/include/boost/nowide/replacement.hpp +++ b/include/boost/nowide/replacement.hpp @@ -1,10 +1,9 @@ // -// Copyright (c) 2018 Artyom Beilis (Tonkikh) -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE or copy at -// http://www.boost.org/LICENSE_1_0.txt) +// Copyright (c) 2018 Artyom Beilis (Tonkikh) // +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + #ifndef BOOST_NOWIDE_REPLACEMENT_HPP_INCLUDED #define BOOST_NOWIDE_REPLACEMENT_HPP_INCLUDED diff --git a/include/boost/nowide/stackstring.hpp b/include/boost/nowide/stackstring.hpp index 7dd336d0..3261ac57 100644 --- a/include/boost/nowide/stackstring.hpp +++ b/include/boost/nowide/stackstring.hpp @@ -1,10 +1,9 @@ // -// Copyright (c) 2012 Artyom Beilis (Tonkikh) -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE or copy at -// http://www.boost.org/LICENSE_1_0.txt) +// Copyright (c) 2012 Artyom Beilis (Tonkikh) // +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + #ifndef BOOST_NOWIDE_STACKSTRING_HPP_INCLUDED #define BOOST_NOWIDE_STACKSTRING_HPP_INCLUDED diff --git a/include/boost/nowide/stat.hpp b/include/boost/nowide/stat.hpp index 351a731b..2c269e61 100644 --- a/include/boost/nowide/stat.hpp +++ b/include/boost/nowide/stat.hpp @@ -1,9 +1,9 @@ // -// Copyright (c) 2020 Alexander Grund -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt) +// Copyright (c) 2020 Alexander Grund // +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + #ifndef BOOST_NOWIDE_STAT_HPP_INCLUDED #define BOOST_NOWIDE_STAT_HPP_INCLUDED diff --git a/include/boost/nowide/utf/convert.hpp b/include/boost/nowide/utf/convert.hpp index ecd540de..e2746f62 100644 --- a/include/boost/nowide/utf/convert.hpp +++ b/include/boost/nowide/utf/convert.hpp @@ -1,11 +1,10 @@ // -// Copyright (c) 2012 Artyom Beilis (Tonkikh) -// Copyright (c) 2020 Alexander Grund -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE or copy at -// http://www.boost.org/LICENSE_1_0.txt) +// Copyright (c) 2012 Artyom Beilis (Tonkikh) +// Copyright (c) 2020 Alexander Grund // +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + #ifndef BOOST_NOWIDE_UTF_CONVERT_HPP_INCLUDED #define BOOST_NOWIDE_UTF_CONVERT_HPP_INCLUDED diff --git a/include/boost/nowide/utf/utf.hpp b/include/boost/nowide/utf/utf.hpp index acdc57a5..fdb79acf 100644 --- a/include/boost/nowide/utf/utf.hpp +++ b/include/boost/nowide/utf/utf.hpp @@ -1,11 +1,10 @@ // -// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) -// Copyright (c) 2020 Alexander Grund -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE or copy at -// http://www.boost.org/LICENSE_1_0.txt) +// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) +// Copyright (c) 2020 Alexander Grund // +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + #ifndef BOOST_NOWIDE_UTF_HPP_INCLUDED #define BOOST_NOWIDE_UTF_HPP_INCLUDED diff --git a/include/boost/nowide/utf8_codecvt.hpp b/include/boost/nowide/utf8_codecvt.hpp index ebe0bccc..c61c138d 100644 --- a/include/boost/nowide/utf8_codecvt.hpp +++ b/include/boost/nowide/utf8_codecvt.hpp @@ -1,11 +1,10 @@ // -// Copyright (c) 2015 Artyom Beilis (Tonkikh) -// Copyright (c) 2020 Alexander Grund -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE or copy at -// http://www.boost.org/LICENSE_1_0.txt) +// Copyright (c) 2015 Artyom Beilis (Tonkikh) +// Copyright (c) 2020 Alexander Grund // +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + #ifndef BOOST_NOWIDE_UTF8_CODECVT_HPP_INCLUDED #define BOOST_NOWIDE_UTF8_CODECVT_HPP_INCLUDED diff --git a/include/boost/nowide/windows.hpp b/include/boost/nowide/windows.hpp index e7c37f4f..9d32f22f 100644 --- a/include/boost/nowide/windows.hpp +++ b/include/boost/nowide/windows.hpp @@ -1,11 +1,10 @@ // -// Copyright (c) 2012 Artyom Beilis (Tonkikh) -// Copyright (c) 2022 Alexander Grund -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE or copy at -// http://www.boost.org/LICENSE_1_0.txt) +// Copyright (c) 2012 Artyom Beilis (Tonkikh) +// Copyright (c) 2022 Alexander Grund // +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + #ifndef BOOST_NOWIDE_WINDOWS_HPP_INCLUDED #define BOOST_NOWIDE_WINDOWS_HPP_INCLUDED diff --git a/src/console_buffer.cpp b/src/console_buffer.cpp index f92079be..5b6cbe26 100644 --- a/src/console_buffer.cpp +++ b/src/console_buffer.cpp @@ -1,9 +1,8 @@ -// Copyright (c) 2012 Artyom Beilis (Tonkikh) -// Copyright (c) 2020 - 2021 Alexander Grund +// Copyright (c) 2012 Artyom Beilis (Tonkikh) +// Copyright (c) 2020 - 2021 Alexander Grund // -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE or copy at -// http://www.boost.org/LICENSE_1_0.txt) +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt #define BOOST_NOWIDE_SOURCE #include "console_buffer.hpp" diff --git a/src/console_buffer.hpp b/src/console_buffer.hpp index 65d01f2d..0074b384 100644 --- a/src/console_buffer.hpp +++ b/src/console_buffer.hpp @@ -1,9 +1,8 @@ -// Copyright (c) 2012 Artyom Beilis (Tonkikh) -// Copyright (c) 2020 - 2021 Alexander Grund +// Copyright (c) 2012 Artyom Beilis (Tonkikh) +// Copyright (c) 2020 - 2021 Alexander Grund // -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE or copy at -// http://www.boost.org/LICENSE_1_0.txt) +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt #ifndef BOOST_NOWIDE_DETAIL_CONSOLE_BUFFER_HPP_INCLUDED #define BOOST_NOWIDE_DETAIL_CONSOLE_BUFFER_HPP_INCLUDED diff --git a/src/cstdio.cpp b/src/cstdio.cpp index d28ae52c..0aa46ed7 100644 --- a/src/cstdio.cpp +++ b/src/cstdio.cpp @@ -1,11 +1,9 @@ // -// Copyright (c) 2012 Artyom Beilis (Tonkikh) -// Copyright (c) 2020-2022 Alexander Grund -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE or copy at -// http://www.boost.org/LICENSE_1_0.txt) +// Copyright (c) 2012 Artyom Beilis (Tonkikh) +// Copyright (c) 2020-2022 Alexander Grund // +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt #define BOOST_NOWIDE_SOURCE diff --git a/src/cstdlib.cpp b/src/cstdlib.cpp index 5a484374..4234a715 100644 --- a/src/cstdlib.cpp +++ b/src/cstdlib.cpp @@ -1,11 +1,9 @@ // -// Copyright (c) 2012 Artyom Beilis (Tonkikh) -// Copyright (c) 2020-2022 Alexander Grund -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE or copy at -// http://www.boost.org/LICENSE_1_0.txt) +// Copyright (c) 2012 Artyom Beilis (Tonkikh) +// Copyright (c) 2020-2022 Alexander Grund // +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt #define BOOST_NOWIDE_SOURCE diff --git a/src/filebuf.cpp b/src/filebuf.cpp index 50388db1..aea4e784 100644 --- a/src/filebuf.cpp +++ b/src/filebuf.cpp @@ -1,10 +1,8 @@ // -// Copyright (c) 2020 Alexander Grund -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE or copy at -// http://www.boost.org/LICENSE_1_0.txt) +// Copyright (c) 2020 Alexander Grund // +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt #define BOOST_NOWIDE_SOURCE diff --git a/src/iostream.cpp b/src/iostream.cpp index be256c15..26959926 100644 --- a/src/iostream.cpp +++ b/src/iostream.cpp @@ -1,9 +1,8 @@ -// Copyright (c) 2012 Artyom Beilis (Tonkikh) -// Copyright (c) 2020-2021 Alexander Grund +// Copyright (c) 2012 Artyom Beilis (Tonkikh) +// Copyright (c) 2020-2021 Alexander Grund // -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE or copy at -// http://www.boost.org/LICENSE_1_0.txt) +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt #define BOOST_NOWIDE_SOURCE #include diff --git a/src/stat.cpp b/src/stat.cpp index aac6f251..117ede35 100644 --- a/src/stat.cpp +++ b/src/stat.cpp @@ -1,9 +1,8 @@ // -// Copyright (c) 2020-2022 Alexander Grund -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt) +// Copyright (c) 2020-2022 Alexander Grund // +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt #define BOOST_NOWIDE_SOURCE diff --git a/standalone/config.hpp b/standalone/config.hpp index bf3afac3..cbb4cfb2 100644 --- a/standalone/config.hpp +++ b/standalone/config.hpp @@ -1,11 +1,10 @@ // -// Copyright (c) 2012 Artyom Beilis (Tonkikh) -// Copyright (c) 2020 - 2022 Alexander Grund -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE or copy at -// http://www.boost.org/LICENSE_1_0.txt) +// Copyright (c) 2012 Artyom Beilis (Tonkikh) +// Copyright (c) 2020 - 2022 Alexander Grund // +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + // Defines macros which otherwise get defined by including #if(defined(_WIN32) || defined(__WIN32__) || defined(WIN32)) && !defined(__CYGWIN__) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 6f91fc2b..5dab7577 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,6 +1,6 @@ # Copyright 2019 - 2021 Alexander Grund # Distributed under the Boost Software License, Version 1.0. -# (See accompanying file LICENSE or copy at http://boost.org/LICENSE_1_0.txt) +# https://www.boost.org/LICENSE_1_0.txt include(CheckCXXCompilerFlag) check_cxx_compiler_flag(-Wsuggest-override _BOOST_NOWIDE_SUGGEST_OVERRIDE_SUPPORTED) diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 0db56fea..9cdaac86 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -1,12 +1,9 @@ -# Boost Nowide Library test Jamfile - # Copyright (c) 2003, 2006 Beman Dawes # Copyright (c) 2012 Artyom Beilis (Tonkikh) # Copyright (c) 2020-2022 Alexander Grund # # Distributed under the Boost Software License, Version 1.0. -# (See accompanying file LICENSE or www.boost.org/LICENSE_1_0.txt) -# See library home page at http://www.boost.org/libs/nowide +# https://www.boost.org/LICENSE_1_0.txt import testing ; import config : requires ; diff --git a/test/benchmark_fstream.cpp b/test/benchmark_fstream.cpp index e5c8a382..e464d0cf 100644 --- a/test/benchmark_fstream.cpp +++ b/test/benchmark_fstream.cpp @@ -1,11 +1,9 @@ // -// Copyright (c) 2012 Artyom Beilis (Tonkikh) -// Copyright (c) 2019 - 2020 Alexander Grund -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE or copy at -// http://www.boost.org/LICENSE_1_0.txt) +// Copyright (c) 2012 Artyom Beilis (Tonkikh) +// Copyright (c) 2019 - 2020 Alexander Grund // +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt #define BOOST_NOWIDE_TEST_NO_MAIN diff --git a/test/cmake_test/CMakeLists.txt b/test/cmake_test/CMakeLists.txt index 11d5d98c..942a73ff 100644 --- a/test/cmake_test/CMakeLists.txt +++ b/test/cmake_test/CMakeLists.txt @@ -1,6 +1,7 @@ # Copyright 2021 Alexander Grund +# # Distributed under the Boost Software License, Version 1.0. -# See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt +# https://www.boost.org/LICENSE_1_0.txt cmake_minimum_required(VERSION 3.5...3.16) diff --git a/test/cmake_test/main.cpp b/test/cmake_test/main.cpp index 36ccb89e..097bf1a2 100644 --- a/test/cmake_test/main.cpp +++ b/test/cmake_test/main.cpp @@ -1,10 +1,8 @@ // -// Copyright (c) 2019-2021 Alexander Grund -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE or copy at -// http://www.boost.org/LICENSE_1_0.txt) +// Copyright (c) 2019-2021 Alexander Grund // +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt #include #include diff --git a/test/file_test_helpers.cpp b/test/file_test_helpers.cpp index 36de84a3..65e3d7ee 100644 --- a/test/file_test_helpers.cpp +++ b/test/file_test_helpers.cpp @@ -1,8 +1,7 @@ -// Copyright (c) 2019-2021 Alexander Grund +// Copyright (c) 2019-2021 Alexander Grund // -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE or copy at -// http://www.boost.org/LICENSE_1_0.txt) +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt #define BOOST_NOWIDE_TEST_NO_MAIN #include "file_test_helpers.hpp" diff --git a/test/file_test_helpers.hpp b/test/file_test_helpers.hpp index 0902ee09..e2483216 100644 --- a/test/file_test_helpers.hpp +++ b/test/file_test_helpers.hpp @@ -1,8 +1,7 @@ -// Copyright (c) 2019-2021 Alexander Grund +// Copyright (c) 2019-2021 Alexander Grund // -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE or copy at -// http://www.boost.org/LICENSE_1_0.txt) +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt #ifndef BOOST_NOWIDE_FILE_TEST_HELPERS_HPP_INCLUDED #define BOOST_NOWIDE_FILE_TEST_HELPERS_HPP_INCLUDED diff --git a/test/test.hpp b/test/test.hpp index 9bc88524..f5a8ec62 100644 --- a/test/test.hpp +++ b/test/test.hpp @@ -1,11 +1,10 @@ // -// Copyright (c) 2012 Artyom Beilis (Tonkikh) -// Copyright (c) 2019-2020 Alexander Grund -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE or copy at -// http://www.boost.org/LICENSE_1_0.txt) +// Copyright (c) 2012 Artyom Beilis (Tonkikh) +// Copyright (c) 2019-2020 Alexander Grund // +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + #ifndef BOOST_NOWIDE_LIB_TEST_H_INCLUDED #define BOOST_NOWIDE_LIB_TEST_H_INCLUDED diff --git a/test/test_codecvt.cpp b/test/test_codecvt.cpp index 0be3f255..a18ce00f 100644 --- a/test/test_codecvt.cpp +++ b/test/test_codecvt.cpp @@ -1,10 +1,8 @@ // -// Copyright (c) 2015 Artyom Beilis (Tonkikh) -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE or copy at -// http://www.boost.org/LICENSE_1_0.txt) +// Copyright (c) 2015 Artyom Beilis (Tonkikh) // +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt #include diff --git a/test/test_convert.cpp b/test/test_convert.cpp index 84185c5d..8f13e0aa 100644 --- a/test/test_convert.cpp +++ b/test/test_convert.cpp @@ -1,10 +1,8 @@ // -// Copyright (c) 2012 Artyom Beilis (Tonkikh) -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE or copy at -// http://www.boost.org/LICENSE_1_0.txt) +// Copyright (c) 2012 Artyom Beilis (Tonkikh) // +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt #include #include "test.hpp" diff --git a/test/test_env.cpp b/test/test_env.cpp index 38ded69a..0bc782be 100644 --- a/test/test_env.cpp +++ b/test/test_env.cpp @@ -1,10 +1,8 @@ // -// Copyright (c) 2012 Artyom Beilis (Tonkikh) -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE or copy at -// http://www.boost.org/LICENSE_1_0.txt) +// Copyright (c) 2012 Artyom Beilis (Tonkikh) // +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt #include #include "test.hpp" diff --git a/test/test_filebuf.cpp b/test/test_filebuf.cpp index ba02961f..a56c87db 100644 --- a/test/test_filebuf.cpp +++ b/test/test_filebuf.cpp @@ -1,9 +1,8 @@ -// Copyright (c) 2015 Artyom Beilis (Tonkikh) -// Copyright (c) 2019-2021 Alexander Grund +// Copyright (c) 2015 Artyom Beilis (Tonkikh) +// Copyright (c) 2019-2021 Alexander Grund // -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE or copy at -// http://www.boost.org/LICENSE_1_0.txt) +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt #include diff --git a/test/test_fs.cpp b/test/test_fs.cpp index 394ac4c6..28767c4a 100644 --- a/test/test_fs.cpp +++ b/test/test_fs.cpp @@ -1,11 +1,9 @@ // -// Copyright (c) 2015 Artyom Beilis (Tonkikh) -// Copyright (c) 2021 Alexander Grund -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE or copy at -// http://www.boost.org/LICENSE_1_0.txt) +// Copyright (c) 2015 Artyom Beilis (Tonkikh) +// Copyright (c) 2021 Alexander Grund // +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt #if defined(__GNUC__) && __GNUC__ >= 7 #pragma GCC diagnostic ignored "-Wattributes" diff --git a/test/test_fstream.cpp b/test/test_fstream.cpp index 7119505c..0c7257d0 100644 --- a/test/test_fstream.cpp +++ b/test/test_fstream.cpp @@ -1,9 +1,8 @@ -// Copyright (c) 2015 Artyom Beilis (Tonkikh) -// Copyright (c) 2019-2021 Alexander Grund +// Copyright (c) 2015 Artyom Beilis (Tonkikh) +// Copyright (c) 2019-2021 Alexander Grund // -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE or copy at -// http://www.boost.org/LICENSE_1_0.txt) +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt #include diff --git a/test/test_fstream_special.cpp b/test/test_fstream_special.cpp index 108cd271..b2838dd5 100644 --- a/test/test_fstream_special.cpp +++ b/test/test_fstream_special.cpp @@ -1,9 +1,8 @@ -// Copyright (c) 2015 Artyom Beilis (Tonkikh) -// Copyright (c) 2019-2021 Alexander Grund +// Copyright (c) 2015 Artyom Beilis (Tonkikh) +// Copyright (c) 2019-2021 Alexander Grund // -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE or copy at -// http://www.boost.org/LICENSE_1_0.txt) +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt #include diff --git a/test/test_ifstream.cpp b/test/test_ifstream.cpp index 3151257e..5d612c14 100644 --- a/test/test_ifstream.cpp +++ b/test/test_ifstream.cpp @@ -1,9 +1,8 @@ -// Copyright (c) 2015 Artyom Beilis (Tonkikh) -// Copyright (c) 2019-2021 Alexander Grund +// Copyright (c) 2015 Artyom Beilis (Tonkikh) +// Copyright (c) 2019-2021 Alexander Grund // -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE or copy at -// http://www.boost.org/LICENSE_1_0.txt) +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt #include diff --git a/test/test_iostream.cpp b/test/test_iostream.cpp index 3a9613c3..8dfcdf76 100644 --- a/test/test_iostream.cpp +++ b/test/test_iostream.cpp @@ -1,9 +1,8 @@ -// Copyright (c) 2015 Artyom Beilis (Tonkikh) -// Copyright (c) 2020 - 2021 Alexander Grund +// Copyright (c) 2015 Artyom Beilis (Tonkikh) +// Copyright (c) 2020 - 2021 Alexander Grund // -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE or copy at -// http://www.boost.org/LICENSE_1_0.txt) +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt #ifndef _SCL_SECURE_NO_WARNINGS // Call to 'std::copy_n' with parameters that may be unsafe diff --git a/test/test_iostream_passthrough.cmake b/test/test_iostream_passthrough.cmake index 8dfc2ad0..61396bfb 100644 --- a/test/test_iostream_passthrough.cmake +++ b/test/test_iostream_passthrough.cmake @@ -1,6 +1,6 @@ # Copyright 2019 - 2021 Alexander Grund # Distributed under the Boost Software License, Version 1.0. -# (See accompanying file LICENSE or copy at http://boost.org/LICENSE_1_0.txt) +# https://www.boost.org/LICENSE_1_0.txt if(NOT DEFINED TEST_BINARY) if(CMAKE_ARGC GREATER 3) diff --git a/test/test_ofstream.cpp b/test/test_ofstream.cpp index a39a914f..a2110960 100644 --- a/test/test_ofstream.cpp +++ b/test/test_ofstream.cpp @@ -1,9 +1,8 @@ -// Copyright (c) 2015 Artyom Beilis (Tonkikh) -// Copyright (c) 2019-2021 Alexander Grund +// Copyright (c) 2015 Artyom Beilis (Tonkikh) +// Copyright (c) 2019-2021 Alexander Grund // -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE or copy at -// http://www.boost.org/LICENSE_1_0.txt) +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt #include diff --git a/test/test_sets.hpp b/test/test_sets.hpp index d4e0c8a3..bd46ee42 100644 --- a/test/test_sets.hpp +++ b/test/test_sets.hpp @@ -1,10 +1,9 @@ // -// Copyright (c) 2012 Artyom Beilis (Tonkikh) -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE or copy at -// http://www.boost.org/LICENSE_1_0.txt) +// Copyright (c) 2012 Artyom Beilis (Tonkikh) // +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + #ifndef BOOST_NOWIDE_TEST_SETS_HPP_INCLUDED #define BOOST_NOWIDE_TEST_SETS_HPP_INCLUDED diff --git a/test/test_stackstring.cpp b/test/test_stackstring.cpp index 8452ba4a..57b67249 100644 --- a/test/test_stackstring.cpp +++ b/test/test_stackstring.cpp @@ -1,11 +1,9 @@ // -// Copyright (c) 2012 Artyom Beilis (Tonkikh) -// Copyright (c) 2019-2020 Alexander Grund -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE or copy at -// http://www.boost.org/LICENSE_1_0.txt) +// Copyright (c) 2012 Artyom Beilis (Tonkikh) +// Copyright (c) 2019-2020 Alexander Grund // +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt #include #include "test.hpp" diff --git a/test/test_stat.cpp b/test/test_stat.cpp index 3cedc2cf..13c1082a 100644 --- a/test/test_stat.cpp +++ b/test/test_stat.cpp @@ -1,9 +1,8 @@ // -// Copyright (c) 2020 Alexander Grund -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt) +// Copyright (c) 2020 Alexander Grund // +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt #include diff --git a/test/test_stdio.cpp b/test/test_stdio.cpp index 409d3c40..2d40b3c6 100644 --- a/test/test_stdio.cpp +++ b/test/test_stdio.cpp @@ -1,11 +1,9 @@ // -// Copyright (c) 2012 Artyom Beilis (Tonkikh) -// Copyright (c) 2019 Alexander Grund -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE or copy at -// http://www.boost.org/LICENSE_1_0.txt) +// Copyright (c) 2012 Artyom Beilis (Tonkikh) +// Copyright (c) 2019 Alexander Grund // +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt #include diff --git a/test/test_system.cpp b/test/test_system.cpp index 50e1937b..2c0e37e7 100644 --- a/test/test_system.cpp +++ b/test/test_system.cpp @@ -1,10 +1,9 @@ // -// Copyright (c) 2012 Artyom Beilis (Tonkikh) -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE or copy at -// http://www.boost.org/LICENSE_1_0.txt) +// Copyright (c) 2012 Artyom Beilis (Tonkikh) // +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + #ifdef _MSC_VER #define _CRT_SECURE_NO_WARNINGS #endif diff --git a/test/test_traits.cpp b/test/test_traits.cpp index 8ff71de7..18496224 100644 --- a/test/test_traits.cpp +++ b/test/test_traits.cpp @@ -1,10 +1,8 @@ // -// Copyright (c) 2020 Alexander Grund -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE or copy at -// http://www.boost.org/LICENSE_1_0.txt) +// Copyright (c) 2020 Alexander Grund // +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt #include #include diff --git a/tools/create_standalone.sh b/tools/create_standalone.sh index 568df563..09cdd14a 100644 --- a/tools/create_standalone.sh +++ b/tools/create_standalone.sh @@ -2,7 +2,7 @@ # Copyright 2019 - 2020 Alexander Grund # Distributed under the Boost Software License, Version 1.0. -# (See accompanying file LICENSE or copy at http://boost.org/LICENSE_1_0.txt) +# https://www.boost.org/LICENSE_1_0.txt set -euo pipefail From fed43a678bf29e1e1e3a342e724961d198a3ac37 Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Wed, 13 Jul 2022 12:43:22 +0200 Subject: [PATCH 059/107] Remove uneccessary cast in test_swap The cast is actually wrong as the return value of `get` is `int` already. --- test/test_fstream_special.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test/test_fstream_special.cpp b/test/test_fstream_special.cpp index b2838dd5..37a5e9f4 100644 --- a/test/test_fstream_special.cpp +++ b/test/test_fstream_special.cpp @@ -222,6 +222,7 @@ void test_swap(const char* filename, const char* filename2) { const int curChar1 = f1.peek(); const int curChar2 = f2.peek(); + TEST_CONTEXT("ctr " << ctr << ": c1=" << curChar1 << " c2=" << curChar2); // Randomly do a no-op seek of either or both streams to flush internal buffer if(ctr % 10 == 0) TEST(f1.seekg(f1.tellg())); @@ -234,9 +235,9 @@ void test_swap(const char* filename, const char* filename2) TEST(f1.seekg(f1.tellg())); else if(ctr % 15 == 4) TEST(f2.seekg(f2.tellg())); - TEST_EQ(f1.get(), char(curChar2)); + TEST_EQ(f1.get(), curChar2); f1.swap(f2); - TEST_EQ(f1.get(), char(curChar1)); + TEST_EQ(f1.get(), curChar1); ++ctr; } } From 75f7b516167c439f5f9786128a6942b7fc785ef4 Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Tue, 27 Sep 2022 12:29:53 +0200 Subject: [PATCH 060/107] Fix potential macro redefinition in test_traits Check that `_SILENCE_EXPERIMENTAL_FILESYSTEM_DEPRECATION_WARNING` is not defined already before defining it to avoid a warning (e.g. C4005 on MSVC) Fixes #165 --- test/test_traits.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/test_traits.cpp b/test/test_traits.cpp index 18496224..791d266b 100644 --- a/test/test_traits.cpp +++ b/test/test_traits.cpp @@ -28,7 +28,9 @@ #define BOOST_NOWIDE_TEST_STD_PATH #endif #if defined(__cpp_lib_experimental_filesystem) +#ifndef _SILENCE_EXPERIMENTAL_FILESYSTEM_DEPRECATION_WARNING #define _SILENCE_EXPERIMENTAL_FILESYSTEM_DEPRECATION_WARNING +#endif #include #define BOOST_NOWIDE_TEST_STD_EXPERIMENTAL_PATH #endif From a429813dbe210ec636428780d238abb42fafe587 Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Mon, 17 Oct 2022 10:09:55 +0200 Subject: [PATCH 061/107] Use container images of Ubuntu 18.04 The native Ubuntu 18.04 runners are deprecated. --- .github/workflows/ci.yml | 32 ++++++++++++++++++-------------- .github/workflows/ci_tests.yml | 8 ++++---- 2 files changed, 22 insertions(+), 18 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a78770eb..a231c324 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -47,13 +47,13 @@ jobs: - { compiler: gcc-4.4, cxxstd: '98,0x', os: ubuntu-20.04, container: 'ubuntu:16.04' } - { compiler: gcc-4.6, cxxstd: '03,0x', os: ubuntu-20.04, container: 'ubuntu:16.04' } - { compiler: gcc-4.7, cxxstd: '03,11', os: ubuntu-20.04, container: 'ubuntu:16.04' } - - { compiler: gcc-4.8, cxxstd: '03,11', os: ubuntu-18.04 } + - { compiler: gcc-4.8, cxxstd: '03,11', os: ubuntu-22.04, container: 'ubuntu:18.04' } - { compiler: gcc-4.9, cxxstd: '03,11', os: ubuntu-20.04, container: 'ubuntu:16.04' } - - { compiler: gcc-5, cxxstd: '03,11,14,1z', os: ubuntu-18.04 } - - { compiler: gcc-6, cxxstd: '03,11,14,17', os: ubuntu-18.04 } - - { compiler: gcc-7, cxxstd: '03,11,14,17', os: ubuntu-18.04 } - - { compiler: gcc-8, cxxstd: '03,11,14,17,2a', os: ubuntu-18.04 } - - { compiler: gcc-9, cxxstd: '03,11,14,17,2a', os: ubuntu-18.04 } + - { compiler: gcc-5, cxxstd: '03,11,14,1z', os: ubuntu-22.04, container: 'ubuntu:18.04' } + - { compiler: gcc-6, cxxstd: '03,11,14,17', os: ubuntu-22.04, container: 'ubuntu:18.04' } + - { compiler: gcc-7, cxxstd: '03,11,14,17', os: ubuntu-22.04, container: 'ubuntu:18.04' } + - { compiler: gcc-8, cxxstd: '03,11,14,17,2a', os: ubuntu-22.04, container: 'ubuntu:18.04' } + - { compiler: gcc-9, cxxstd: '03,11,14,17,2a', os: ubuntu-22.04, container: 'ubuntu:18.04' } - { compiler: gcc-10, cxxstd: '03,11,14,17,20', os: ubuntu-20.04 } - { compiler: gcc-11, cxxstd: '03,11,14,17,20', os: ubuntu-20.04 } - { compiler: gcc-12, cxxstd: '03,11,14,17,20', os: ubuntu-22.04 } @@ -67,13 +67,13 @@ jobs: - { compiler: clang-3.6, cxxstd: '03,11,14', os: ubuntu-20.04, container: 'ubuntu:16.04' } - { compiler: clang-3.7, cxxstd: '03,11,14', os: ubuntu-20.04, container: 'ubuntu:16.04' } - { compiler: clang-3.8, cxxstd: '03,11,14', os: ubuntu-20.04, container: 'ubuntu:16.04' } - - { compiler: clang-3.9, cxxstd: '03,11,14', os: ubuntu-18.04 } - - { compiler: clang-4.0, cxxstd: '03,11,14', os: ubuntu-18.04 } - - { compiler: clang-5.0, cxxstd: '03,11,14,1z', os: ubuntu-18.04 } - - { compiler: clang-6.0, cxxstd: '03,11,14,17', os: ubuntu-18.04 } - - { compiler: clang-7, cxxstd: '03,11,14,17', os: ubuntu-18.04 } + - { compiler: clang-3.9, cxxstd: '03,11,14', os: ubuntu-22.04, container: 'ubuntu:18.04' } + - { compiler: clang-4.0, cxxstd: '03,11,14', os: ubuntu-22.04, container: 'ubuntu:18.04' } + - { compiler: clang-5.0, cxxstd: '03,11,14,1z', os: ubuntu-22.04, container: 'ubuntu:18.04' } + - { compiler: clang-6.0, cxxstd: '03,11,14,17', os: ubuntu-22.04, container: 'ubuntu:18.04' } + - { compiler: clang-7, cxxstd: '03,11,14,17', os: ubuntu-22.04, container: 'ubuntu:18.04' } # Note: clang-8 does not fully support C++20, so it is not compatible with some libstdc++ versions in this mode - - { compiler: clang-8, cxxstd: '03,11,14,17,2a', os: ubuntu-18.04, install: 'clang-8 g++-7', gcc_toolchain: 7 } + - { compiler: clang-8, cxxstd: '03,11,14,17,2a', os: ubuntu-22.04, container: 'ubuntu:18.04', install: 'clang-8 g++-7', gcc_toolchain: 7 } - { compiler: clang-9, cxxstd: '03,11,14,17,2a', os: ubuntu-20.04 } - { compiler: clang-10, cxxstd: '03,11,14,17,20', os: ubuntu-20.04 } - { compiler: clang-11, cxxstd: '03,11,14,17,20', os: ubuntu-20.04 } @@ -82,7 +82,7 @@ jobs: - { compiler: clang-14, cxxstd: '03,11,14,17,20', os: ubuntu-22.04 } # libc++ - - { compiler: clang-6.0, cxxstd: '03,11,14', os: ubuntu-18.04, stdlib: libc++, install: 'clang-6.0 libc++-dev libc++abi-dev' } + - { compiler: clang-6.0, cxxstd: '03,11,14', os: ubuntu-22.04, container: 'ubuntu:18.04', stdlib: libc++, install: 'clang-6.0 libc++-dev libc++abi-dev' } - { compiler: clang-12, cxxstd: '03,11,14,17,20', os: ubuntu-20.04, stdlib: libc++, install: 'clang-12 libc++-12-dev libc++abi-12-dev' } - { name: Clang w/ sanitizers, sanitize: yes, compiler: clang-14, cxxstd: '03,11,14,17,20', os: ubuntu-22.04, stdlib: libc++, install: 'clang-14 libc++-14-dev libc++abi-14-dev' } @@ -155,7 +155,8 @@ jobs: SOURCES+=(ppa:ubuntu-toolchain-r/test) for key in "${SOURCE_KEYS[@]}"; do for i in {1..$NET_RETRY_COUNT}; do - wget -O - "$key" | sudo apt-key add - && break || sleep 10 + keyfilename=$(basename -s .key $key) + curl -sSL --retry ${NET_RETRY_COUNT:-5} "$key" | sudo gpg --dearmor > /etc/apt/trusted.gpg.d/${keyfilename} && break || sleep 10 done done for source in "${SOURCES[@]}"; do @@ -177,6 +178,9 @@ jobs: run: | GCC_TOOLCHAIN_ROOT="$HOME/gcc-toolchain" echo "GCC_TOOLCHAIN_ROOT=$GCC_TOOLCHAIN_ROOT" >> $GITHUB_ENV + if ! command -v dpkg-architecture; then + apt-get install -y dpkg-dev + fi MULTIARCH_TRIPLET="$(dpkg-architecture -qDEB_HOST_MULTIARCH)" mkdir -p "$GCC_TOOLCHAIN_ROOT" ln -s /usr/include "$GCC_TOOLCHAIN_ROOT/include" diff --git a/.github/workflows/ci_tests.yml b/.github/workflows/ci_tests.yml index 0d7151fa..39e0a4f5 100644 --- a/.github/workflows/ci_tests.yml +++ b/.github/workflows/ci_tests.yml @@ -31,17 +31,17 @@ jobs: shell: bash strategy: matrix: - os: [ubuntu-18.04, windows-2019] + os: [ubuntu-22.04, windows-2019] buildType: [Debug, Release] standalone: [Boost, Standalone] shared_lib: [ON, OFF] generator: ['Visual Studio 16 2019', 'MinGW Makefiles', 'Unix Makefiles'] exclude: - - os: ubuntu-18.04 + - os: ubuntu-22.04 generator: MinGW Makefiles - - os: ubuntu-18.04 + - os: ubuntu-22.04 generator: Visual Studio 16 2019 - - os: ubuntu-18.04 + - os: ubuntu-22.04 buildType: Debug runs-on: ${{matrix.os}} env: From cdcd7043c6ac0b1b67dd91aa50888bd17e3d0159 Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Thu, 20 Oct 2022 10:56:25 +0200 Subject: [PATCH 062/107] Update docs regarding C++11 usage --- README.md | 3 ++- doc/main.dox | 13 +++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index b2f981f3..c8c6731b 100644 --- a/README.md +++ b/README.md @@ -29,9 +29,10 @@ This is different to the version available prior to the inclusion in Boost. ### Requirements (All versions) -* C++11 (or higher) compatible compiler +* **C++11** (or higher) compatible compiler * MSVC 2015 and up work * libstdc++ < 5 is unsupported as it is silently lacking C++11 features + * When building with B2 pass e.g. `cxxstd=11` if your compiler defaults to C++03 ### Requirements (Boost version) diff --git a/doc/main.dox b/doc/main.dox index 4ebf5c13..5f511d31 100644 --- a/doc/main.dox +++ b/doc/main.dox @@ -22,6 +22,7 @@ Table of Contents: - \ref alternative - \ref main_reading - \ref using + - \ref building - \ref using_standard - \ref using_custom - \ref using_integration @@ -154,6 +155,18 @@ Hence under some circumstances (and hopefully always somewhen in the future) thi - Windows console I/O approaches \section using Using The Library +\subsection building Building the library + +Boost.Nowide is usually build as part of Boost via `b2`. +It requires C++11 features and if any are missing the library will **not** be build. + +If that happens unexpectatly watch the configuration check output for anything like `cxx11_constexpr : no`. +This means your compiler doesn't use C++11 (or higher), e.g. because it defaults to C++03. +You can pass `cxxstd=11` to `b2` to build in C++11 mode. + +Experimental support for building with the Boost CMake build system is also available. +For that run e.g. `cmake -DBOOST_INCLUDE_LIBRARIES=nowide `. + \subsection using_standard Standard Features As a developer you are expected to use \c boost::nowide functions instead of the functions available in the From 1e92987a04405fe8f7c97234231af3ba6f6d4b3b Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Thu, 2 Mar 2023 18:23:33 +0100 Subject: [PATCH 063/107] Add `boost::nowide::quoted` to read/write paths from/to streams. --- doc/changelog.dox | 10 ++- doc/main.dox | 24 ++++++ include/boost/nowide/quoted.hpp | 109 +++++++++++++++++++++++++++ include/boost/nowide/utf/convert.hpp | 11 +++ test/test_fs.cpp | 99 +++++++++++++++++++++++- 5 files changed, 249 insertions(+), 4 deletions(-) create mode 100644 include/boost/nowide/quoted.hpp diff --git a/doc/changelog.dox b/doc/changelog.dox index 612daa38..8e7a702e 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -1,5 +1,5 @@ // -// Copyright (c) 2019-2021 Alexander Grund +// Copyright (c) 2019-2023 Alexander Grund // // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt @@ -8,14 +8,18 @@ \section changelog Changelog -\subsection changelog_11_2_0 Nowide 11.2.0 +\subsection changelog_11_2_1 Nowide 11.2.1 (Boost 1.82) +- Add `convert_string` overload accepting a string +- Add `quoted` to output (quoted) paths (std::filesystem or boost::filesystem) + +\subsection changelog_11_2_0 Nowide 11.2.0 (Boost 1.80) - `filebuf`: Major performance improvement for Bulk I/O - `filebuf`: Fix wrong return value of `sync` when `fflush` failed - `filebuf`: Fix possible undefined behavior in a corner case when nothing was actually written but buffer is in "write" mode - `filebuf`: Limit putback of characters (i.e. `pbackfail`) only allowing putback of buffered characters (may be only 1 character) - Add missing define `NOWIDE_USE_WCHAR_OVERLOADS` (standalone only) -\subsection changelog_11_1_4 Nowide 11.1.4 +\subsection changelog_11_1_4 Nowide 11.1.4 (Boost 1.79) - Fix possible redefinition of `_LARGEFILE_SOURCE` - Fix missing include when `BOOST_USE_WINDOWS_H` and `WIN32_LEAN_AND_MEAN` are defined. - Fix compile failures on recent MinGW-w64 compilers diff --git a/doc/main.dox b/doc/main.dox index 5f511d31..aa7be877 100644 --- a/doc/main.dox +++ b/doc/main.dox @@ -303,6 +303,30 @@ However the `u8string()` member function can be used to obtain an UTF-8 encoded And to optain a `path` from an UTF-8 encoded string you may use `std::filesystem::u8path` or since C++20 one of the `path` constructors taking a `char8_t`-type input. +To read/write `std::filesystem::path` instances from/to streams you'd usually use e.g. `os << path`. +However that will effectively be run as `os << std::quoted(path.string())` which means a possible conversion +to a narrow string which may not be UTF-8 encoded. +For that \c quoted can be used: + +\code +#include +#include +#include + +std::string write(const std::filesystem::path& path) +{ + std::ostringstream s; + s << boost::nowide::quoted(path); + return s.str(); +} + +std::experimental::path read(std::istream& is) +{ + std::filesystem::path path; + is >> boost::nowide::quoted(path); + return path; +} +\endcode \section technical Technical Details \subsection technical_imple Windows vs POSIX diff --git a/include/boost/nowide/quoted.hpp b/include/boost/nowide/quoted.hpp new file mode 100644 index 00000000..68edc01d --- /dev/null +++ b/include/boost/nowide/quoted.hpp @@ -0,0 +1,109 @@ +// +// Copyright (c) 2023 Alexander Grund +// +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#ifndef BOOST_NOWIDE_QUOTED_HPP_INCLUDED +#define BOOST_NOWIDE_QUOTED_HPP_INCLUDED + +#include +#include +#include +#include +#include +#include +#include + +#if defined(__cpp_lib_quoted_string_io) && __cpp_lib_quoted_string_io >= 201304 + +namespace boost { +namespace nowide { + /// \cond INTERNAL + namespace detail { + template + struct quoted; + template + using remove_cvref_t = typename std::remove_cv::type>::type; + + } // namespace detail + /// \endcond + + /// \brief Allows insertion and extraction of `filesystem::path` into/from streams. + /// + /// When used in an expression such as `out << quoted(path)`, where `out` is an output stream, + /// has the effect as-if `out << std::quoted(path.native())` was used. + /// + /// When used in an expression like `in >> quoted(path)`, where `in` is an input stream, + /// has the effect as-if `in >> std::quoted(path.native())` was used if that would be valid. + /// To that effect a temporary string is used, which on success is assigned to `path`. + /// + /// Will automatically convert between the streams `char_type` and `path::value_type` if neccessary. + template +#ifdef BOOST_NOWIDE_DOXYGEN + unspecified_type +#else + detail::enable_if_path_t, detail::quoted> +#endif + quoted(Path& path) + { + return {path}; + } + + /// \cond INTERNAL + // Same but for const-refs and r-values + template + detail::enable_if_path_t, detail::quoted> quoted(const Path& path) + { + return {path}; + } + + namespace detail { + template::value>::type> + std::basic_string maybe_convert_string(const std::basic_string& s) + { + return utf::convert_string(s); + } + template + const std::basic_string& maybe_convert_string(const std::basic_string& s) + { + return s; + } + + template + using requires_non_const = + typename std::enable_if::type>::value>::type; + + template + struct quoted + { + Path value; + template + friend std::basic_ostream& operator<<(std::basic_ostream& out, const quoted& path) + { + return out << std::quoted(maybe_convert_string(path.value.native())); + } + + template> + friend std::basic_istream& operator>>(std::basic_istream& in, const quoted& path) + { + std::basic_string value; + using PlainPath = remove_cvref_t; + if(in >> std::quoted(value)) + path.value = PlainPath(maybe_convert_string(value)); + return in; + } + }; + + } // namespace detail + /// \endcond +} // namespace nowide +} // namespace boost + +#elif defined(BOOST_PRAGMA_MESSAGE) +BOOST_PRAGMA_MESSAGE("To use boost::nowide::quoted at least C++14 is required.") +#endif + +#endif diff --git a/include/boost/nowide/utf/convert.hpp b/include/boost/nowide/utf/convert.hpp index e2746f62..2a9cda0f 100644 --- a/include/boost/nowide/utf/convert.hpp +++ b/include/boost/nowide/utf/convert.hpp @@ -90,6 +90,17 @@ namespace nowide { return result; } + /// Convert the UTF sequence in the input string from \a CharIn to \a CharOut + /// and return it as a string + /// + /// Any illegal sequences are replaced with the replacement character, see #BOOST_NOWIDE_REPLACEMENT_CHARACTER + /// \tparam CharOut Output character type + template + std::basic_string convert_string(const std::basic_string& s) + { + return convert_string(s.data(), s.data() + s.size()); + } + } // namespace utf } // namespace nowide } // namespace boost diff --git a/test/test_fs.cpp b/test/test_fs.cpp index 28767c4a..ce4cedbc 100644 --- a/test/test_fs.cpp +++ b/test/test_fs.cpp @@ -13,11 +13,97 @@ #include #include #include +#include +#include #include "test.hpp" +#include +#include +#include #if defined(_MSC_VER) #pragma warning(disable : 4714) // function marked as __forceinline not inlined #endif -#include +#include + +// Exclude apple as support there is target level specific -.- +#if defined(__cpp_lib_filesystem) && !defined(__APPLE__) +#include +#define BOOST_NOWIDE_TEST_STD_PATH +#endif +#if defined(__cpp_lib_experimental_filesystem) +#ifndef _SILENCE_EXPERIMENTAL_FILESYSTEM_DEPRECATION_WARNING +#define _SILENCE_EXPERIMENTAL_FILESYSTEM_DEPRECATION_WARNING +#endif +#include +#define BOOST_NOWIDE_TEST_STD_EXPERIMENTAL_PATH +#endif + +template +struct is_istreamable : std::false_type +{}; +using boost::nowide::detail::void_t; +template +struct is_istreamable() >> std::declval())>> : std::true_type +{}; + +template +std::string maybe_narrow(const std::basic_string& s) +{ + return boost::nowide::narrow(s); +} + +const std::string& maybe_narrow(const std::string& s) +{ + return s; +} + +template +void test_fs_path_io(std::string utf8_name) +{ +#if defined(__cpp_lib_quoted_string_io) && __cpp_lib_quoted_string_io >= 201304 + Path path(boost::nowide::utf::convert_string(utf8_name)); + // Get native and UTF-8/narrow name here as the Path ctor may change the string (e.g. slash substitution) + const auto nativeName = path.native(); + utf8_name = maybe_narrow(nativeName); + // Output + std::ostringstream s, sRef; + sRef << std::quoted(utf8_name); + s << boost::nowide::quoted(path); + TEST_EQ(s.str(), sRef.str()); + // const + const Path constPath(path); + s.str(""); + s << boost::nowide::quoted(constPath); + TEST_EQ(s.str(), sRef.str()); + // Rvalue + s.str(""); + s << boost::nowide::quoted(Path(path)); + TEST_EQ(s.str(), sRef.str()); + + // Input + std::istringstream sIn(sRef.str()); + Path pathOut; + static_assert(is_istreamable::value, "!"); + sIn >> boost::nowide::quoted(pathOut); + TEST_EQ(pathOut.native(), nativeName); + // Can't read into a const path + static_assert(!is_istreamable::value, "!"); + // or an Rvalue + static_assert(!is_istreamable::value, "!"); + + // Wide stream + std::wostringstream ws, wsRef; + wsRef << std::quoted(boost::nowide::widen(utf8_name)); + ws << boost::nowide::quoted(path); + TEST_EQ(ws.str(), wsRef.str()); + std::wistringstream wsIn(wsRef.str()); + pathOut.clear(); + wsIn >> boost::nowide::quoted(pathOut); + TEST_EQ(maybe_narrow(pathOut.native()), utf8_name); +#else + (void)utf8_name; // Suppress unused warning + std::cout << "Skipping tests for boost::nowide::quoted" << std::endl; +#endif +} // coverity[root_function] void test_main(int, char** argv, char**) @@ -63,4 +149,15 @@ void test_main(int, char** argv, char**) TEST(test == "Test"); } boost::filesystem::remove(path); + + std::cout << "Testing boost::filesystem::path" << std::endl; + test_fs_path_io(utf8_name); +#ifdef BOOST_NOWIDE_TEST_STD_EXPERIMENTAL_PATH + std::cout << "Testing std::experimental::filesystem::path" << std::endl; + test_fs_path_io(utf8_name); +#endif +#ifdef BOOST_NOWIDE_TEST_STD_PATH + std::cout << "Testing std::filesystem::path" << std::endl; + test_fs_path_io(utf8_name); +#endif } From cd3b01d6f78afbfe3c68d431b32b82a6b13e0896 Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Sat, 4 Mar 2023 13:47:45 +0100 Subject: [PATCH 064/107] CI: Extend coverage collection to C++14-20 `std::quoted` requires C++14 while std::filesystem::path requires C++17 so to test those with coverage we need to include the newer standards. --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a231c324..4debc399 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -60,7 +60,7 @@ jobs: - { name: GCC w/ sanitizers, sanitize: yes, compiler: gcc-12, cxxstd: '03,11,14,17,20', os: ubuntu-22.04 } - { name: Collect coverage, coverage: yes, - compiler: gcc-8, cxxstd: '03,11', os: ubuntu-20.04, install: 'g++-8-multilib', address-model: '32,64' } + compiler: gcc-8, cxxstd: '03,11,14,17,2a', os: ubuntu-20.04, install: 'g++-8-multilib', address-model: '32,64' } # Linux, clang - { compiler: clang-3.5, cxxstd: '03,11', os: ubuntu-20.04, container: 'ubuntu:16.04' } From 07af3c6144807298f5dbf0fa9f083c2fb337e36e Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Sun, 12 Mar 2023 10:14:30 +0100 Subject: [PATCH 065/107] Increase (internal) version to 11.3.0 --- CMakeLists.txt | 2 +- doc/changelog.dox | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index cc97ce8d..f6b2bae3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,7 +15,7 @@ cmake_minimum_required(VERSION 3.9) # Version number starts at 10 to avoid conflicts with Boost version -set(_version 11.2.0) +set(_version 11.3.0) if(BOOST_SUPERPROJECT_SOURCE_DIR) set(_version ${BOOST_SUPERPROJECT_VERSION}) endif() diff --git a/doc/changelog.dox b/doc/changelog.dox index 8e7a702e..ae2b4674 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -8,7 +8,7 @@ \section changelog Changelog -\subsection changelog_11_2_1 Nowide 11.2.1 (Boost 1.82) +\subsection changelog_11_3_0 Nowide 11.3.0 (Boost 1.82) - Add `convert_string` overload accepting a string - Add `quoted` to output (quoted) paths (std::filesystem or boost::filesystem) From 683d8733cc297e21646903d20c7dd8ffd2ab428a Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Tue, 20 Jun 2023 09:43:17 +0200 Subject: [PATCH 066/107] Add FUNDING.yml --- .github/FUNDING.yml | 1 + 1 file changed, 1 insertion(+) create mode 100644 .github/FUNDING.yml diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 00000000..5933e5ac --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1 @@ +github: Flamefire From 149ee7c84e13d8949f6b8866cd1d33741014c371 Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Wed, 21 Jun 2023 16:58:23 +0200 Subject: [PATCH 067/107] Fix false positive warning in GCC 13 on MinGW --- test/test_codecvt.cpp | 8 ++++++++ test/test_filebuf.cpp | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/test/test_codecvt.cpp b/test/test_codecvt.cpp index a18ce00f..ff5dbdbf 100644 --- a/test/test_codecvt.cpp +++ b/test/test_codecvt.cpp @@ -293,7 +293,15 @@ void test_codecvt_err() TEST_EQ(cvt.in(mb, from, from_end, from_next, to, to_end, to_next), cvt_type::partial); TEST(from_next == from + 1); TEST(to_next == to + 1); + // False positive in GCC 13 in MinGW +#if defined(__GNUC__) && __GNUC__ >= 13 +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wfree-nonheap-object" +#endif TEST(std::wstring(to, to_next) == std::wstring(L"1")); +#if defined(__GNUC__) && __GNUC__ >= 13 +#pragma GCC diagnostic pop +#endif } { char buf[4] = {}; diff --git a/test/test_filebuf.cpp b/test/test_filebuf.cpp index a56c87db..88ff9aa6 100644 --- a/test/test_filebuf.cpp +++ b/test/test_filebuf.cpp @@ -308,7 +308,7 @@ void test_xsgetn(const std::string& filepath, bool binary) buffer[0] = origStr[0]; TEST_EQ(buf.sgetn(&str[0], 0), 0); -#if defined(__GNUC__) && __GNUC__ >= 7 +#if defined(__GNUC__) && __GNUC__ >= 12 // GCC may not detect that the negative value is checked by xsgetn #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wrestrict" From 8bfeeb320de46a33e788313d439ca74b07dfa015 Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Thu, 22 Jun 2023 12:52:26 +0200 Subject: [PATCH 068/107] CI: Fix AzP --- .azure-pipelines.yml | 73 +++++++++++++++++--------------------------- 1 file changed, 28 insertions(+), 45 deletions(-) diff --git a/.azure-pipelines.yml b/.azure-pipelines.yml index 57b9acb7..3d1cc401 100644 --- a/.azure-pipelines.yml +++ b/.azure-pipelines.yml @@ -5,21 +5,6 @@ # Distributed under the Boost Software License, Version 1.0. # https://www.boost.org/LICENSE_1_0.txt -# -# Generic Azure Pipelines build script for boostorg repositories -# See: https://github.com/boostorg/boost-ci/ -# -# Instructions for customizing this script for your library: -# -# 1. Customize the compilers and language levels you want. -# 2. If you have more than include/, src/, test/, example/, examples/, -# benchmark/ or tools/ directories, set the environment variable DEPINST. -# For example if your build uses code in "bench/" and "fog/" directories: -# - DEPINST: --include bench --include fog -# 3. Enable pull request builds in your boostorg/ account. -# -# That's it - the script will do everything else for you. - trigger: branches: include: @@ -44,44 +29,42 @@ parameters: - name: jobs type: object default: - - { compiler: gcc-4.8, cxxstd: '11', os: ubuntu-18.04 } - - { compiler: gcc-4.9, cxxstd: '11', os: ubuntu-18.04, container: 'ubuntu:16.04' } - - { compiler: gcc-5, cxxstd: '11', os: ubuntu-18.04 } - - { compiler: gcc-6, cxxstd: '11,14', os: ubuntu-18.04 } - - { compiler: gcc-7, cxxstd: '11,14,17', os: ubuntu-18.04 } + - { compiler: gcc-4.8, cxxstd: '11', os: ubuntu-20.04, container: 'ubuntu:16.04' } + - { compiler: gcc-4.9, cxxstd: '11', os: ubuntu-20.04, container: 'ubuntu:16.04' } + - { compiler: gcc-5, cxxstd: '11', os: ubuntu-20.04, container: 'ubuntu:18.04' } + - { compiler: gcc-6, cxxstd: '11,14', os: ubuntu-20.04, container: 'ubuntu:18.04' } + - { compiler: gcc-7, cxxstd: '11,14,17', os: ubuntu-20.04 } - { compiler: gcc-8, cxxstd: '14,17,2a', os: ubuntu-20.04 } - { compiler: gcc-9, cxxstd: '14,17,2a', os: ubuntu-20.04 } - { compiler: gcc-10, cxxstd: '14,17,20', os: ubuntu-20.04 } - { compiler: gcc-11, cxxstd: '14,17,20', os: ubuntu-20.04 } - - { compiler: clang-3.5, cxxstd: '11', os: ubuntu-18.04, container: 'ubuntu:16.04' } - - { compiler: clang-3.6, cxxstd: '11', os: ubuntu-18.04, container: 'ubuntu:16.04' } - - { compiler: clang-3.7, cxxstd: '11', os: ubuntu-18.04, container: 'ubuntu:16.04' } - - { compiler: clang-3.8, cxxstd: '11,14', os: ubuntu-18.04, container: 'ubuntu:16.04' } - - { compiler: clang-3.9, cxxstd: '11,14', os: ubuntu-18.04 } - - { compiler: clang-4.0, cxxstd: '11,14', os: ubuntu-18.04 } - - { compiler: clang-5.0, cxxstd: '11,14,17', os: ubuntu-18.04 } - - { compiler: clang-6.0, cxxstd: '11,14,17', os: ubuntu-18.04, install: 'clang-6.0 libc6-dbg libc++-dev libc++abi-dev libstdc++-8-dev' } - - { compiler: clang-7, cxxstd: '14,17', os: ubuntu-18.04, install: 'clang-7 libc6-dbg libc++-dev libstdc++-8-dev' } - - { compiler: clang-8, cxxstd: '14,17', os: ubuntu-18.04, install: 'clang-8 libc6-dbg libc++-dev libstdc++-8-dev' } + - { compiler: clang-3.5, cxxstd: '11', os: ubuntu-20.04, container: 'ubuntu:16.04' } + - { compiler: clang-3.6, cxxstd: '11', os: ubuntu-20.04, container: 'ubuntu:16.04' } + - { compiler: clang-3.7, cxxstd: '11', os: ubuntu-20.04, container: 'ubuntu:16.04' } + - { compiler: clang-3.8, cxxstd: '11,14', os: ubuntu-20.04, container: 'ubuntu:16.04' } + - { compiler: clang-3.9, cxxstd: '11,14', os: ubuntu-20.04, container: 'ubuntu:16.04' } + - { compiler: clang-4.0, cxxstd: '11,14', os: ubuntu-20.04, container: 'ubuntu:16.04' } + - { compiler: clang-5.0, cxxstd: '11,14,17', os: ubuntu-20.04, container: 'ubuntu:16.04' } + - { compiler: clang-6.0, cxxstd: '11,14,17', os: ubuntu-20.04 } + - { compiler: clang-7, cxxstd: '14,17', os: ubuntu-20.04 } + - { compiler: clang-8, cxxstd: '14,17', os: ubuntu-20.04 } - { compiler: clang-9, cxxstd: '14,17,2a', os: ubuntu-20.04 } - { compiler: clang-10, cxxstd: '14,17,20', os: ubuntu-20.04 } - - { compiler: clang-11, cxxstd: '14,17,20', os: ubuntu-20.04 } - - { compiler: clang-12, cxxstd: '14,17,20', os: ubuntu-20.04 } + - { compiler: clang-11, cxxstd: '14,17,20', os: ubuntu-22.04 } + - { compiler: clang-12, cxxstd: '14,17,20', os: ubuntu-22.04 } - { name: Linux_clang_6_libcxx, - compiler: clang-6.0, cxxstd: '11,14,17', os: ubuntu-18.04, install: 'clang-6.0 libc6-dbg libc++-dev libc++abi-dev libstdc++-8-dev', env: {B2_STDLIB: libc++ } } + compiler: clang-6.0, cxxstd: '11,14,17', os: ubuntu-20.04, container: 'ubuntu:18.04', install: 'clang-6.0 libc++-dev libc++abi-dev', env: {B2_STDLIB: libc++ } } # OSX - - { compiler: clang, cxxstd: '14,17,2a', os: macOS-10.15, xcode: 11.2.1 } - - { compiler: clang, cxxstd: '14,17,2a', os: macOS-10.15, xcode: 11.3 } - - { compiler: clang, cxxstd: '14,17,2a', os: macOS-10.15, xcode: 11.3.1 } - - { compiler: clang, cxxstd: '14,17,2a', os: macOS-10.15, xcode: 11.4.1 } - - { compiler: clang, cxxstd: '14,17,2a', os: macOS-10.15, xcode: 11.5 } - - { compiler: clang, cxxstd: '14,17,2a', os: macOS-10.15, xcode: 11.6 } - - { compiler: clang, cxxstd: '14,17,2a', os: macOS-10.15, xcode: 11.7 } - - { compiler: clang, cxxstd: '14,17,2a', os: macOS-10.15, xcode: 12.0.1 } - - { compiler: clang, cxxstd: '14,17,2a', os: macOS-10.15, xcode: 12.1.1 } - - { compiler: clang, cxxstd: '14,17,2a', os: macOS-10.15, xcode: 12.2 } - - { compiler: clang, cxxstd: '14,17,2a', os: macOS-10.15, xcode: 12.3 } - - { compiler: clang, cxxstd: '14,17,2a', os: macOS-10.15, xcode: 12.4 } + - { compiler: clang, cxxstd: '14,17,2a', os: macOS-11, xcode: '11.7' } + - { compiler: clang, cxxstd: '14,17,2a', os: macOS-11, xcode: '12.4' } + - { compiler: clang, cxxstd: '14,17,2a', os: macOS-11, xcode: '12.5.1' } + - { compiler: clang, cxxstd: '14,17,2a', os: macOS-11, xcode: '13.0' } + - { compiler: clang, cxxstd: '14,17,2a', os: macOS-12, xcode: '13.1' } + - { compiler: clang, cxxstd: '14,17,2a', os: macOS-12, xcode: '13.2.1' } + - { compiler: clang, cxxstd: '14,17,2a', os: macOS-12, xcode: '13.3.1' } + - { compiler: clang, cxxstd: '14,17,2a', os: macOS-12, xcode: '13.4' } + - { compiler: clang, cxxstd: '14,17,2a', os: macOS-12, xcode: '13.4.1' } + - { compiler: clang, cxxstd: '14,17,2a', os: macOS-12, xcode: '14.0.1' } stages: - stage: Test From 6ec7524a351839122254230c60fe39e40763d41d Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Thu, 22 Jun 2023 13:02:18 +0200 Subject: [PATCH 069/107] CI: Update GHA container jobs Use Ubuntu 22.04 as the base OS --- .github/workflows/ci.yml | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4debc399..9296b70b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -44,16 +44,16 @@ jobs: matrix: include: # Linux, gcc - - { compiler: gcc-4.4, cxxstd: '98,0x', os: ubuntu-20.04, container: 'ubuntu:16.04' } - - { compiler: gcc-4.6, cxxstd: '03,0x', os: ubuntu-20.04, container: 'ubuntu:16.04' } - - { compiler: gcc-4.7, cxxstd: '03,11', os: ubuntu-20.04, container: 'ubuntu:16.04' } - - { compiler: gcc-4.8, cxxstd: '03,11', os: ubuntu-22.04, container: 'ubuntu:18.04' } - - { compiler: gcc-4.9, cxxstd: '03,11', os: ubuntu-20.04, container: 'ubuntu:16.04' } + - { compiler: gcc-4.4, cxxstd: '98,0x', os: ubuntu-22.04, container: 'ubuntu:16.04' } + - { compiler: gcc-4.6, cxxstd: '03,0x', os: ubuntu-22.04, container: 'ubuntu:16.04' } + - { compiler: gcc-4.7, cxxstd: '03,11', os: ubuntu-22.04, container: 'ubuntu:16.04' } + - { compiler: gcc-4.8, cxxstd: '03,11', os: ubuntu-22.04, container: 'ubuntu:16.04' } + - { compiler: gcc-4.9, cxxstd: '03,11', os: ubuntu-22.04, container: 'ubuntu:16.04' } - { compiler: gcc-5, cxxstd: '03,11,14,1z', os: ubuntu-22.04, container: 'ubuntu:18.04' } - { compiler: gcc-6, cxxstd: '03,11,14,17', os: ubuntu-22.04, container: 'ubuntu:18.04' } - - { compiler: gcc-7, cxxstd: '03,11,14,17', os: ubuntu-22.04, container: 'ubuntu:18.04' } - - { compiler: gcc-8, cxxstd: '03,11,14,17,2a', os: ubuntu-22.04, container: 'ubuntu:18.04' } - - { compiler: gcc-9, cxxstd: '03,11,14,17,2a', os: ubuntu-22.04, container: 'ubuntu:18.04' } + - { compiler: gcc-7, cxxstd: '03,11,14,17', os: ubuntu-20.04 } + - { compiler: gcc-8, cxxstd: '03,11,14,17,2a', os: ubuntu-20.04 } + - { compiler: gcc-9, cxxstd: '03,11,14,17,2a', os: ubuntu-20.04 } - { compiler: gcc-10, cxxstd: '03,11,14,17,20', os: ubuntu-20.04 } - { compiler: gcc-11, cxxstd: '03,11,14,17,20', os: ubuntu-20.04 } - { compiler: gcc-12, cxxstd: '03,11,14,17,20', os: ubuntu-22.04 } @@ -63,10 +63,10 @@ jobs: compiler: gcc-8, cxxstd: '03,11,14,17,2a', os: ubuntu-20.04, install: 'g++-8-multilib', address-model: '32,64' } # Linux, clang - - { compiler: clang-3.5, cxxstd: '03,11', os: ubuntu-20.04, container: 'ubuntu:16.04' } - - { compiler: clang-3.6, cxxstd: '03,11,14', os: ubuntu-20.04, container: 'ubuntu:16.04' } - - { compiler: clang-3.7, cxxstd: '03,11,14', os: ubuntu-20.04, container: 'ubuntu:16.04' } - - { compiler: clang-3.8, cxxstd: '03,11,14', os: ubuntu-20.04, container: 'ubuntu:16.04' } + - { compiler: clang-3.5, cxxstd: '03,11', os: ubuntu-22.04, container: 'ubuntu:16.04' } + - { compiler: clang-3.6, cxxstd: '03,11,14', os: ubuntu-22.04, container: 'ubuntu:16.04' } + - { compiler: clang-3.7, cxxstd: '03,11,14', os: ubuntu-22.04, container: 'ubuntu:16.04' } + - { compiler: clang-3.8, cxxstd: '03,11,14', os: ubuntu-22.04, container: 'ubuntu:16.04' } - { compiler: clang-3.9, cxxstd: '03,11,14', os: ubuntu-22.04, container: 'ubuntu:18.04' } - { compiler: clang-4.0, cxxstd: '03,11,14', os: ubuntu-22.04, container: 'ubuntu:18.04' } - { compiler: clang-5.0, cxxstd: '03,11,14,1z', os: ubuntu-22.04, container: 'ubuntu:18.04' } @@ -88,7 +88,7 @@ jobs: compiler: clang-14, cxxstd: '03,11,14,17,20', os: ubuntu-22.04, stdlib: libc++, install: 'clang-14 libc++-14-dev libc++abi-14-dev' } # OSX, clang - - { compiler: clang, cxxstd: '03,11,14,17,2a', os: macos-10.15, sanitize: yes } + - { compiler: clang, cxxstd: '03,11,14,17,2a', os: macos-11, sanitize: yes } timeout-minutes: 120 runs-on: ${{matrix.os}} From af2b3f5af735858f7219b067a62b3781cc0d97f6 Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Thu, 22 Jun 2023 16:08:32 +0200 Subject: [PATCH 070/107] Fix duplicated PRIVATE in CML --- test/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 5dab7577..56f5fdc3 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -6,7 +6,7 @@ include(CheckCXXCompilerFlag) check_cxx_compiler_flag(-Wsuggest-override _BOOST_NOWIDE_SUGGEST_OVERRIDE_SUPPORTED) add_library(boost_nowide_file_test_helpers STATIC file_test_helpers.cpp) -target_link_libraries(boost_nowide_file_test_helpers PRIVATE PRIVATE Boost::nowide) +target_link_libraries(boost_nowide_file_test_helpers PRIVATE Boost::nowide) target_compile_definitions(boost_nowide_file_test_helpers PRIVATE BOOST_ALL_NO_LIB) if(NOT TARGET tests) From 2c40bddb30ad98274d2440b9b17fff9d44ef5678 Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Wed, 9 Mar 2022 19:22:21 +0100 Subject: [PATCH 071/107] Reduce duplicated requirements from Jamfiles --- build/Jamfile.v2 | 1 - test/Jamfile.v2 | 7 +------ 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/build/Jamfile.v2 b/build/Jamfile.v2 index 0eab1694..fdb27ec2 100644 --- a/build/Jamfile.v2 +++ b/build/Jamfile.v2 @@ -26,7 +26,6 @@ project boost/nowide cxx11_rvalue_references cxx11_static_assert ] - [ check-target-builds ../config//cxx11_moveable_fstreams "std::fstream is moveable and swappable" : : no ] [ check-target-builds ../config//lfs_support "Has Large File Support" : : BOOST_NOWIDE_NO_LFS ] no:BOOST_NOWIDE_NO_LFS [ check-target-builds ../config//attribute_init_priority "Has attribute init_priority" : BOOST_NOWIDE_HAS_INIT_PRIORITY ] : usage-requirements $(requirements) diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 9cdaac86..f632ed58 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -23,17 +23,12 @@ project : requirements . pedantic on - [ requires - cxx11_defaulted_functions - cxx11_noexcept - cxx11_rvalue_references - cxx11_static_assert - ] [ check-target-builds ../config//cxx11_moveable_fstreams "std::fstream is moveable and swappable" : : no ] ; lib shell32 ; lib file_test_helpers : file_test_helpers.cpp : static -/boost/nowide//boost_nowide ; +explicit file_test_helpers ; run test_codecvt.cpp ; run test_convert.cpp ; From f20b831c62a9fe659a0ef9cee2f2bfe3704c4377 Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Wed, 16 Mar 2022 18:16:56 +0100 Subject: [PATCH 072/107] Add some missing C++11 requirements --- build/Jamfile.v2 | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/build/Jamfile.v2 b/build/Jamfile.v2 index fdb27ec2..8ea6ae74 100644 --- a/build/Jamfile.v2 +++ b/build/Jamfile.v2 @@ -21,10 +21,19 @@ project boost/nowide : source-location ../src : requirements $(requirements) [ requires + cxx11_auto_declarations + cxx11_char16_t + cxx11_char32_t + cxx11_constexpr + cxx11_decltype cxx11_defaulted_functions cxx11_noexcept + cxx11_nullptr + cxx11_override cxx11_rvalue_references cxx11_static_assert + cxx11_template_aliases + cxx11_variadic_templates ] [ check-target-builds ../config//lfs_support "Has Large File Support" : : BOOST_NOWIDE_NO_LFS ] no:BOOST_NOWIDE_NO_LFS [ check-target-builds ../config//attribute_init_priority "Has attribute init_priority" : BOOST_NOWIDE_HAS_INIT_PRIORITY ] From 26bc5d540efacdfcfac43b201d677ac5b0416a64 Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Fri, 3 Nov 2023 14:46:45 +0100 Subject: [PATCH 073/107] Avoid warning in test --- test/test_fs.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/test_fs.cpp b/test/test_fs.cpp index ce4cedbc..628d7ca3 100644 --- a/test/test_fs.cpp +++ b/test/test_fs.cpp @@ -13,8 +13,10 @@ #include #include #include -#include #include +#if defined(__cpp_lib_quoted_string_io) && __cpp_lib_quoted_string_io >= 201304 +#include +#endif #include "test.hpp" #include #include From b7a4fa5f566ef0ac5673868de3c7b994be989c53 Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Sat, 4 Nov 2023 10:31:27 +0100 Subject: [PATCH 074/107] Include iomanip before checking feature macros --- test/test_fs.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/test/test_fs.cpp b/test/test_fs.cpp index 628d7ca3..315f20f6 100644 --- a/test/test_fs.cpp +++ b/test/test_fs.cpp @@ -14,11 +14,14 @@ #include #include #include +#include "test.hpp" + +#include // Required for feature macro check below +// Conditional include to avoid warning/message #if defined(__cpp_lib_quoted_string_io) && __cpp_lib_quoted_string_io >= 201304 #include #endif -#include "test.hpp" -#include + #include #include #if defined(_MSC_VER) From 20bde3d48c72de659cdbade45cf5d461e6b02e98 Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Sat, 4 Nov 2023 10:55:23 +0100 Subject: [PATCH 075/107] Fix GHA --- .github/workflows/ci.yml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9296b70b..61f64e2a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -78,8 +78,9 @@ jobs: - { compiler: clang-10, cxxstd: '03,11,14,17,20', os: ubuntu-20.04 } - { compiler: clang-11, cxxstd: '03,11,14,17,20', os: ubuntu-20.04 } - { compiler: clang-12, cxxstd: '03,11,14,17,20', os: ubuntu-20.04 } - - { compiler: clang-13, cxxstd: '03,11,14,17,20', os: ubuntu-22.04 } - - { compiler: clang-14, cxxstd: '03,11,14,17,20', os: ubuntu-22.04 } + - { compiler: clang-13, cxxstd: '03,11,14,17,20', os: ubuntu-22.04, container: 'ubuntu:22.04' } + - { compiler: clang-14, cxxstd: '03,11,14,17,20', os: ubuntu-22.04, container: 'ubuntu:22.04' } + - { compiler: clang-15, cxxstd: '03,11,14,17,20', os: ubuntu-22.04, container: 'ubuntu:22.04' } # libc++ - { compiler: clang-6.0, cxxstd: '03,11,14', os: ubuntu-22.04, container: 'ubuntu:18.04', stdlib: libc++, install: 'clang-6.0 libc++-dev libc++abi-dev' } @@ -104,9 +105,9 @@ jobs: fi if [ -n "${{matrix.container}}" ] && [ -f "/etc/debian_version" ]; then apt-get -o Acquire::Retries=$NET_RETRY_COUNT update - apt-get -o Acquire::Retries=$NET_RETRY_COUNT install -y sudo software-properties-common + apt-get -o Acquire::Retries=$NET_RETRY_COUNT install -y sudo software-properties-common curl # Need (newer) git, and the older Ubuntu container may require requesting the key manually using port 80 - apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys E1DD270288B4E6030699E45FA1715D88E1DF1F24 + curl -sSL --retry ${NET_RETRY_COUNT:-5} 'http://keyserver.ubuntu.com/pks/lookup?op=get&search=0xE1DD270288B4E6030699E45FA1715D88E1DF1F24' | sudo gpg --dearmor > /etc/apt/trusted.gpg.d/git-core_ubuntu_ppa.gpg for i in {1..${NET_RETRY_COUNT:-3}}; do sudo -E add-apt-repository -y ppa:git-core/ppa && break || sleep 10; done apt-get -o Acquire::Retries=$NET_RETRY_COUNT update apt-get -o Acquire::Retries=$NET_RETRY_COUNT install -y g++ python libpython-dev git From fcb82d53e8eef987be74d030c67b97c5973fe78a Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Sat, 4 Nov 2023 11:04:47 +0100 Subject: [PATCH 076/107] GHA: Don't use Ubuntu 22 container yet --- .github/workflows/ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 61f64e2a..0679d9ff 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -78,9 +78,9 @@ jobs: - { compiler: clang-10, cxxstd: '03,11,14,17,20', os: ubuntu-20.04 } - { compiler: clang-11, cxxstd: '03,11,14,17,20', os: ubuntu-20.04 } - { compiler: clang-12, cxxstd: '03,11,14,17,20', os: ubuntu-20.04 } - - { compiler: clang-13, cxxstd: '03,11,14,17,20', os: ubuntu-22.04, container: 'ubuntu:22.04' } - - { compiler: clang-14, cxxstd: '03,11,14,17,20', os: ubuntu-22.04, container: 'ubuntu:22.04' } - - { compiler: clang-15, cxxstd: '03,11,14,17,20', os: ubuntu-22.04, container: 'ubuntu:22.04' } + # Clang isn't compatible with libstdc++-13, so use the slightly older one + - { compiler: clang-13, cxxstd: '03,11,14,17,20', os: ubuntu-22.04, install: 'clang-13 g++-12', gcc_toolchain: 12 } + - { compiler: clang-14, cxxstd: '03,11,14,17,20', os: ubuntu-22.04, install: 'clang-14 g++-12', gcc_toolchain: 12 } # libc++ - { compiler: clang-6.0, cxxstd: '03,11,14', os: ubuntu-22.04, container: 'ubuntu:18.04', stdlib: libc++, install: 'clang-6.0 libc++-dev libc++abi-dev' } From 3d2a2c2d3986eac3b1a7accba8bde68c7275030c Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Sat, 4 Nov 2023 15:50:07 +0100 Subject: [PATCH 077/107] AzP: Fix Clang11+ --- .azure-pipelines.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.azure-pipelines.yml b/.azure-pipelines.yml index 3d1cc401..ed3cb7a4 100644 --- a/.azure-pipelines.yml +++ b/.azure-pipelines.yml @@ -50,8 +50,8 @@ parameters: - { compiler: clang-8, cxxstd: '14,17', os: ubuntu-20.04 } - { compiler: clang-9, cxxstd: '14,17,2a', os: ubuntu-20.04 } - { compiler: clang-10, cxxstd: '14,17,20', os: ubuntu-20.04 } - - { compiler: clang-11, cxxstd: '14,17,20', os: ubuntu-22.04 } - - { compiler: clang-12, cxxstd: '14,17,20', os: ubuntu-22.04 } + - { compiler: clang-11, cxxstd: '14,17,20', os: ubuntu-20.04 } + - { compiler: clang-14, cxxstd: '14,17,20', os: ubuntu-22.04, gcc_toolchain: 12 } - { name: Linux_clang_6_libcxx, compiler: clang-6.0, cxxstd: '11,14,17', os: ubuntu-20.04, container: 'ubuntu:18.04', install: 'clang-6.0 libc++-dev libc++abi-dev', env: {B2_STDLIB: libc++ } } # OSX From 157252a655d3c50b6606bdc5ba454b62d26a810a Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Sat, 4 Nov 2023 15:50:10 +0100 Subject: [PATCH 078/107] Appveyor: Update of preinstalled Boost version used --- .appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.appveyor.yml b/.appveyor.yml index 08cf18de..f7c7d16c 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -138,7 +138,7 @@ environment: CMAKE_FLAGS: -DBOOST_NOWIDE_DISABLE_CIN_TEST=ON GENERATOR: Visual Studio 17 2022 configuration: Debug - BOOST_ROOT: C:\Libraries\boost_1_77_0 + BOOST_ROOT: C:\Libraries\boost_1_83_0 # Coverity - COVERITY: true From 30f94c84f567b93a46e1e3df4e83f440303f871a Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Sat, 4 Nov 2023 16:34:36 +0100 Subject: [PATCH 079/107] AzP: Add missing GCC_TOOLCHAIN code --- .azure-pipelines.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.azure-pipelines.yml b/.azure-pipelines.yml index ed3cb7a4..4ec1992a 100644 --- a/.azure-pipelines.yml +++ b/.azure-pipelines.yml @@ -94,6 +94,8 @@ stages: XCODE_APP: /Applications/Xcode_${{ item.xcode }}.app ${{ if item.install }}: PACKAGES: ${{ item.install }} + ${{ if item.gcc_toolchain }}: + GCC_TOOLCHAIN: ${{ item.gcc_toolchain }} ${{ each var in item.env }}: ${{var.Key}}: ${{var.Value}} steps: From 3c4e04597c21349c5ac7263e4eb9644f54cbfcb4 Mon Sep 17 00:00:00 2001 From: jackarain Date: Mon, 25 Dec 2023 15:08:04 +0800 Subject: [PATCH 080/107] Fix warning '_CRT_SECURE_NO_WARNINGS': macro redefinition --- src/cstdio.cpp | 2 ++ src/cstdlib.cpp | 2 ++ test/test_system.cpp | 2 ++ 3 files changed, 6 insertions(+) diff --git a/src/cstdio.cpp b/src/cstdio.cpp index 0aa46ed7..2ff9574c 100644 --- a/src/cstdio.cpp +++ b/src/cstdio.cpp @@ -8,7 +8,9 @@ #define BOOST_NOWIDE_SOURCE #ifdef _MSC_VER +#ifndef _CRT_SECURE_NO_WARNINGS #define _CRT_SECURE_NO_WARNINGS +#endif #elif defined(__MINGW32__) && defined(__STRICT_ANSI__) // Need the _w* functions which are extensions on MinGW but not on MinGW-w64 #include <_mingw.h> diff --git a/src/cstdlib.cpp b/src/cstdlib.cpp index 4234a715..ab0d4455 100644 --- a/src/cstdlib.cpp +++ b/src/cstdlib.cpp @@ -8,7 +8,9 @@ #define BOOST_NOWIDE_SOURCE #ifdef _MSC_VER +#ifndef _CRT_SECURE_NO_WARNINGS #define _CRT_SECURE_NO_WARNINGS +#endif #elif defined(__MINGW32__) && defined(__STRICT_ANSI__) // Need the _w* functions which are extensions on MinGW but not on MinGW-w64 #include <_mingw.h> diff --git a/test/test_system.cpp b/test/test_system.cpp index 2c0e37e7..76171375 100644 --- a/test/test_system.cpp +++ b/test/test_system.cpp @@ -5,8 +5,10 @@ // https://www.boost.org/LICENSE_1_0.txt #ifdef _MSC_VER +#ifndef _CRT_SECURE_NO_WARNINGS #define _CRT_SECURE_NO_WARNINGS #endif +#endif #include #include From a4311b7ffb645fd86a5c02eea7a1d18c62c25b22 Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Tue, 26 Mar 2024 09:01:35 +0100 Subject: [PATCH 081/107] Appveyor: Drop MinGW32 for MinGW64-32Bit The old MinGW32 doesn't properly support C++11 --- .appveyor.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index f7c7d16c..7da94451 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -99,11 +99,11 @@ environment: B2_CXXSTD: 03,11,14,1z B2_TOOLSET: gcc - - FLAVOR: mingw32 - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 + - FLAVOR: mingw64 (32-bit) + APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 + ADDPATH: C:\mingw-w64\i686-8.1.0-posix-dwarf-rt_v6-rev0\mingw32\bin; B2_ADDRESS_MODEL: 32 - ADDPATH: C:\mingw\bin; - B2_CXXSTD: 03,11,14,1z + B2_CXXSTD: 03,11,14,17,2a B2_TOOLSET: gcc - FLAVOR: mingw64 From 0605516e3bfd11cc0a4d61fb8f4369b696ac0105 Mon Sep 17 00:00:00 2001 From: Dirk Stolle Date: Tue, 30 Apr 2024 23:10:54 +0200 Subject: [PATCH 082/107] Fix a few typos --- doc/main.dox | 8 ++++---- include/boost/nowide/quoted.hpp | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/doc/main.dox b/doc/main.dox index aa7be877..0aeeef0e 100644 --- a/doc/main.dox +++ b/doc/main.dox @@ -138,7 +138,7 @@ Since April 2018 there is a (Beta) function available in Windows 10 to use UTF-8 Both methods do work but have a major drawback: They are not fully reliable for the app developer. The code page via manifest method falls back to a legacy code page when an older Windows version than 1903 is used. -Hence it is only usable if the targetted system is Windows 10 after May 2019. +Hence it is only usable if the targeted system is Windows 10 after May 2019. The second method relies on user interaction prior to starting the program. Obviously this is not reliable when expecting only UTF-8 in the code. @@ -243,7 +243,7 @@ and temporarily replaces the original \c argv (and optionally \c env) with point UTF-8 strings for the lifetime of the instance. - \c boost::nowide::ifstream converts the passed filename (which is now valid UTF-8) to UTF-16 and calls the Windows Wide API to open the file stream which can then be used as usual. -- Similarily \c boost::nowide::cerr and \c boost::nowide::cout use an underlying stream buffer +- Similarly \c boost::nowide::cerr and \c boost::nowide::cout use an underlying stream buffer that converts the UTF-8 string to UTF-16 and use another Wide API function to write it to console. \subsection using_custom Custom API @@ -289,7 +289,7 @@ before including any of the Boost.Nowide headers \subsection using_integration Integration with Boost.Filesystem Boost.Filesystem supports selection of narrow encoding. -Unfortunatelly the default narrow encoding on Windows isn't UTF-8. +Unfortunately the default narrow encoding on Windows isn't UTF-8. But you can enable UTF-8 as default encoding on Boost.Filesystem by calling `boost::nowide::nowide_filesystem()` in the beginning of your program which imbues a locale with a UTF-8 conversion facet to convert between \c char and \c wchar_t. @@ -300,7 +300,7 @@ used as the storage format. For `std::filesystem::path` available since C++17 there is no way to imbue a locale. However the `u8string()` member function can be used to obtain an UTF-8 encoded string from a `path`. -And to optain a `path` from an UTF-8 encoded string you may use `std::filesystem::u8path` +And to obtain a `path` from an UTF-8 encoded string you may use `std::filesystem::u8path` or since C++20 one of the `path` constructors taking a `char8_t`-type input. To read/write `std::filesystem::path` instances from/to streams you'd usually use e.g. `os << path`. diff --git a/include/boost/nowide/quoted.hpp b/include/boost/nowide/quoted.hpp index 68edc01d..d940fde6 100644 --- a/include/boost/nowide/quoted.hpp +++ b/include/boost/nowide/quoted.hpp @@ -38,7 +38,7 @@ namespace nowide { /// has the effect as-if `in >> std::quoted(path.native())` was used if that would be valid. /// To that effect a temporary string is used, which on success is assigned to `path`. /// - /// Will automatically convert between the streams `char_type` and `path::value_type` if neccessary. + /// Will automatically convert between the streams `char_type` and `path::value_type` if necessary. template #ifdef BOOST_NOWIDE_DOXYGEN unspecified_type From 28a2ec27c83c7865230f76d1b765f9629a446d07 Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Thu, 2 May 2024 17:32:48 +0200 Subject: [PATCH 083/107] GHA: Upgrade macos-11 to 12 Homebrew fails to build CCache as the OS seems to be too old --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0679d9ff..cf12f1de 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -89,7 +89,7 @@ jobs: compiler: clang-14, cxxstd: '03,11,14,17,20', os: ubuntu-22.04, stdlib: libc++, install: 'clang-14 libc++-14-dev libc++abi-14-dev' } # OSX, clang - - { compiler: clang, cxxstd: '03,11,14,17,2a', os: macos-11, sanitize: yes } + - { compiler: clang, cxxstd: '11,14,17,20', os: macos-12, sanitize: yes } timeout-minutes: 120 runs-on: ${{matrix.os}} From 5898950dfa018039c54abd3a5e547dbe3ac68524 Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Thu, 2 May 2024 17:36:26 +0200 Subject: [PATCH 084/107] GHA: Improve coverage upload Use the GHA action with a provided token --- .github/workflows/ci.yml | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cf12f1de..68f8bc99 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -223,9 +223,21 @@ jobs: B2_FLAGS: boost.nowide.lfs=no run: ci/build.sh - - name: Upload coverage + - name: Collect coverage if: matrix.coverage run: ci/codecov.sh "upload" + env: + BOOST_CI_CODECOV_IO_UPLOAD: skip + + - name: Upload coverage + if: matrix.coverage + uses: codecov/codecov-action@v4 + with: + disable_search: true + file: coverage.info + name: Github Actions + token: ${{secrets.CODECOV_TOKEN}} + verbose: true - name: Run coverity if: matrix.coverity && github.event_name == 'push' && (github.ref_name == 'develop' || github.ref_name == 'master') From 0571844afdcbd664578fadd9da3607b09787b68f Mon Sep 17 00:00:00 2001 From: Dirk Stolle Date: Tue, 30 Apr 2024 23:17:38 +0200 Subject: [PATCH 085/107] Update GitHub Actions CI The following updates are performed: * update actions/cache to v4 * update actions/checkout to v4 --- .github/workflows/ci.yml | 14 +++++++------- .github/workflows/ci_tests.yml | 14 +++++++------- .github/workflows/release.yml | 2 +- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 68f8bc99..211a1cd7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -119,13 +119,13 @@ jobs: git config --global pack.threads 0 ! command -v cmake &> /dev/null || echo "B2_FLAGS=--nowide-enable-cmake" >> $GITHUB_ENV - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: # For coverage builds fetch the whole history, else only 1 commit using a 'fake ternary' fetch-depth: ${{ matrix.coverage && '0' || '1' }} - name: Cache ccache - uses: actions/cache@v3 + uses: actions/cache@v4 if: env.B2_USE_CCACHE with: path: ~/.ccache @@ -135,7 +135,7 @@ jobs: ${{matrix.os}}-${{matrix.container}}-${{matrix.compiler}} - name: Fetch Boost.CI - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: repository: boostorg/boost-ci ref: master @@ -260,7 +260,7 @@ jobs: runs-on: windows-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Setup MSYS2 environment uses: msys2/setup-msys2@v2 @@ -271,7 +271,7 @@ jobs: pacboy: gcc:p cmake:p ninja:p - name: Fetch Boost.CI - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: repository: boostorg/boost-ci ref: master @@ -320,9 +320,9 @@ jobs: runs-on: ${{matrix.os}} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Fetch Boost.CI - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: repository: boostorg/boost-ci ref: master diff --git a/.github/workflows/ci_tests.yml b/.github/workflows/ci_tests.yml index 39e0a4f5..50c4a39a 100644 --- a/.github/workflows/ci_tests.yml +++ b/.github/workflows/ci_tests.yml @@ -48,10 +48,10 @@ jobs: DEP_DIR: ${{github.workspace}}/dependencies BOOST_VERSION: 1.56.0 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Sanity check version run: grep -E 'set\(_version [0-9]' CMakeLists.txt - - uses: actions/cache@v1 + - uses: actions/cache@v4 id: cache-boost with: path: ${{env.DEP_DIR}} @@ -64,7 +64,7 @@ jobs: if: matrix.standalone == 'Boost' run: echo "BOOST_ROOT=${DEP_DIR//\\/\/}/boost_${BOOST_VERSION//./_}" >> $GITHUB_ENV # Install Boost - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 if: matrix.standalone == 'Boost' && steps.cache-boost.outputs.cache-hit != 'true' with: repository: boostorg/boost @@ -125,7 +125,7 @@ jobs: CreateDocuTest: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v4 - name: Create documentation run: | sudo apt-get install -y doxygen @@ -134,9 +134,9 @@ jobs: CreateBoostDocuTest: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Fetch Boost.CI - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: repository: boostorg/boost-ci ref: master @@ -153,7 +153,7 @@ jobs: CheckFormatting: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: DoozyX/clang-format-lint-action@v0.11 with: exclude: './doc' diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 30523234..1dd3bc94 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -18,7 +18,7 @@ jobs: DEP_DIR: ${{github.workspace}}/dependencies BOOST_VERSION: 1.56.0 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Extract tag name id: get_tag run: | From dd1a4f163079d72be2cb2922d472da0a39ef89c7 Mon Sep 17 00:00:00 2001 From: Dirk Stolle Date: Fri, 3 May 2024 10:44:12 +0200 Subject: [PATCH 086/107] Add workaround for containers that cannot run Node.js 20 --- .github/workflows/ci.yml | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 211a1cd7..13599bc8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -119,14 +119,38 @@ jobs: git config --global pack.threads 0 ! command -v cmake &> /dev/null || echo "B2_FLAGS=--nowide-enable-cmake" >> $GITHUB_ENV + if [[ "${{matrix.container}}" == "ubuntu:16.04" ]] || [[ "${{matrix.container}}" == "ubuntu:18.04" ]]; then + # Ubuntu 16/18 can't run Node 20, so stick to older actions: https://github.com/actions/checkout/issues/1590 + echo "GHA_USE_NODE_20=false" >> $GITHUB_ENV + else + echo "GHA_USE_NODE_20=true" >> $GITHUB_ENV + fi + + - uses: actions/checkout@v3 + if: env.GHA_USE_NODE_20 == 'false' + with: + # For coverage builds fetch the whole history, else only 1 commit using a 'fake ternary' + fetch-depth: ${{ matrix.coverage && '0' || '1' }} + - uses: actions/checkout@v4 + if: env.GHA_USE_NODE_20 == 'true' with: # For coverage builds fetch the whole history, else only 1 commit using a 'fake ternary' fetch-depth: ${{ matrix.coverage && '0' || '1' }} + - name: Cache ccache + uses: actions/cache@v3 + if: env.B2_USE_CCACHE && env.GHA_USE_NODE_20 == 'false' + with: + path: ~/.ccache + key: ${{matrix.os}}-${{matrix.container}}-${{matrix.compiler}}-${{github.sha}} + restore-keys: | + ${{matrix.os}}-${{matrix.container}}-${{matrix.compiler}}- + ${{matrix.os}}-${{matrix.container}}-${{matrix.compiler}} + - name: Cache ccache uses: actions/cache@v4 - if: env.B2_USE_CCACHE + if: env.B2_USE_CCACHE && env.GHA_USE_NODE_20 == 'true' with: path: ~/.ccache key: ${{matrix.os}}-${{matrix.container}}-${{matrix.compiler}}-${{github.sha}} @@ -134,8 +158,17 @@ jobs: ${{matrix.os}}-${{matrix.container}}-${{matrix.compiler}}- ${{matrix.os}}-${{matrix.container}}-${{matrix.compiler}} + - name: Fetch Boost.CI + uses: actions/checkout@v3 + if: env.GHA_USE_NODE_20 == 'false' + with: + repository: boostorg/boost-ci + ref: master + path: boost-ci-cloned + - name: Fetch Boost.CI uses: actions/checkout@v4 + if: env.GHA_USE_NODE_20 == 'true' with: repository: boostorg/boost-ci ref: master From 213c99cd4c4e15cb4328cbba02556f501dee3313 Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Thu, 16 May 2024 19:33:16 +0200 Subject: [PATCH 087/107] CMake: Build tests only on `make test` (#182) Add EXCLUDE_FROM_ALL to test binaries as per the Boost convention --- .appveyor.yml | 4 ++-- .github/workflows/ci_tests.yml | 9 ++++++--- .github/workflows/release.yml | 6 ++++-- test/CMakeLists.txt | 6 +++--- 4 files changed, 15 insertions(+), 10 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index 7da94451..15a93600 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -177,7 +177,7 @@ for: - mkdir __build_cmake_test__ - cd __build_cmake_test__ - cmake -G "%GENERATOR%" -DCMAKE_CXX_STANDARD=%CXXSTD% %CMAKE_FLAGS% -DCMAKE_INSTALL_PREFIX=%INSTALL_DIR% .. - build_script: cmake --build . --config %configuration% --parallel 4 + build_script: cmake --build . --config %configuration% --parallel 4 --target tests test_script: - ctest --output-on-failure -C %configuration% --parallel 4 - ps: | @@ -204,7 +204,7 @@ for: - cmake -G "%GENERATOR%" .. - ps: | cov-configure --msvc - cov-build --dir cov-int cmake --build . --config $env:configuration + cov-build --dir cov-int cmake --build --target tests . --config $env:configuration If ($LastExitCode -ne 0) { cat cov-int/build-log.txt $host.SetShouldExit($LastExitCode) diff --git a/.github/workflows/ci_tests.yml b/.github/workflows/ci_tests.yml index 50c4a39a..dcf90ccf 100644 --- a/.github/workflows/ci_tests.yml +++ b/.github/workflows/ci_tests.yml @@ -1,4 +1,4 @@ -# Copyright 2019 - 2022 Alexander Grund +# Copyright 2019 - 2024 Alexander Grund # Distributed under the Boost Software License, Version 1.0. # https://www.boost.org/LICENSE_1_0.txt @@ -102,8 +102,8 @@ jobs: extraFlags="$extraFlags -DCMAKE_CXX_FLAGS=-Wundef" fi cmake -DCMAKE_BUILD_TYPE=${{matrix.buildType}} -DBUILD_SHARED_LIBS=${{matrix.shared_lib}} -G "${{matrix.generator}}" $extraFlags .. - - name: Build & Install - run: cmake --build build --config ${{matrix.buildType}} --target install + - name: Build + run: cmake --build build --config ${{matrix.buildType}} --target tests # Run test with both bash and powershell and watch for "Using std::cin" on bash but not on powershell - name: Test @@ -114,6 +114,9 @@ jobs: shell: powershell if: runner.os == 'Windows' run: ctest --output-on-failure -C ${{matrix.buildType}} --verbose + + - name: Install + run: cmake --build build --config ${{matrix.buildType}} --target install - name: Test consumption working-directory: build run: | diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 1dd3bc94..c4a9afe4 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -56,8 +56,9 @@ jobs: src_dir="$PWD/nowide_standalone_${{steps.get_tag.outputs.tag}}" mkdir build && cd build cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX=${{runner.workspace}}/../install "$src_dir" - cmake --build . --config Debug --target install + cmake --build . --config Debug --target tests ctest --output-on-failure -C Debug --verbose + cmake --build . --config Debug --target install - name: Create Boost version run: | @@ -75,8 +76,9 @@ jobs: src_dir="$PWD/nowide_${{steps.get_tag.outputs.tag}}" mkdir build && cd build cmake -DBoost_DEBUG=ON -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX=${{runner.workspace}}/../install "$src_dir" - cmake --build . --config Debug --target install + cmake --build . --config Debug --target tests ctest --output-on-failure -C Debug --verbose + cmake --build . --config Debug --target install - name: Create Release if: github.event_name == 'push' diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 56f5fdc3..9565b008 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,11 +1,11 @@ -# Copyright 2019 - 2021 Alexander Grund +# Copyright 2019 - 2024 Alexander Grund # Distributed under the Boost Software License, Version 1.0. # https://www.boost.org/LICENSE_1_0.txt include(CheckCXXCompilerFlag) check_cxx_compiler_flag(-Wsuggest-override _BOOST_NOWIDE_SUGGEST_OVERRIDE_SUPPORTED) -add_library(boost_nowide_file_test_helpers STATIC file_test_helpers.cpp) +add_library(boost_nowide_file_test_helpers STATIC EXCLUDE_FROM_ALL file_test_helpers.cpp) target_link_libraries(boost_nowide_file_test_helpers PRIVATE Boost::nowide) target_compile_definitions(boost_nowide_file_test_helpers PRIVATE BOOST_ALL_NO_LIB) @@ -27,7 +27,7 @@ function(boost_nowide_add_test name) endif() set(name ${PROJECT_NAME}-${name}) - add_executable(${name} ${ARG_SRC}) + add_executable(${name} EXCLUDE_FROM_ALL ${ARG_SRC}) add_dependencies(tests ${name}) target_link_libraries(${name} PRIVATE Boost::nowide ${ARG_LIBRARIES}) boost_add_warnings(${name} pedantic ${Boost_NOWIDE_WERROR}) From 2972d9fbd8b6e7b20d1a9a3213803549f51199f9 Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Fri, 17 May 2024 16:18:45 +0200 Subject: [PATCH 088/107] Appveyor: Fix CMake args in coverity build --- .appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.appveyor.yml b/.appveyor.yml index 15a93600..b14277f3 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -204,7 +204,7 @@ for: - cmake -G "%GENERATOR%" .. - ps: | cov-configure --msvc - cov-build --dir cov-int cmake --build --target tests . --config $env:configuration + cov-build --dir cov-int cmake --build . --target tests --config $env:configuration If ($LastExitCode -ne 0) { cat cov-int/build-log.txt $host.SetShouldExit($LastExitCode) From d4aa719f21149de8960247403435e9b794a01255 Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Sun, 25 Aug 2024 13:39:19 +0200 Subject: [PATCH 089/107] GHA: Workaround node20 GLIBC issues in older Ubuntu containers Avoid errors like > /__e/node20/bin/node: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.28' not found (required by /__e/node20/bin/node) when using Ubuntu 16/18 containers with the @v4 actions See actions/checkout#1590 --- .github/workflows/ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 13599bc8..2c5339c7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -122,6 +122,7 @@ jobs: if [[ "${{matrix.container}}" == "ubuntu:16.04" ]] || [[ "${{matrix.container}}" == "ubuntu:18.04" ]]; then # Ubuntu 16/18 can't run Node 20, so stick to older actions: https://github.com/actions/checkout/issues/1590 echo "GHA_USE_NODE_20=false" >> $GITHUB_ENV + echo "ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION=true" >> $GITHUB_ENV else echo "GHA_USE_NODE_20=true" >> $GITHUB_ENV fi From 43f53ecc30e37aa8df3bdeb68e1d00c7ef2f5d1e Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Sun, 25 Aug 2024 13:41:43 +0200 Subject: [PATCH 090/107] GHA: Use ubuntu-latest for all container jobs --- .github/workflows/ci.yml | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2c5339c7..ed83e29a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -44,13 +44,13 @@ jobs: matrix: include: # Linux, gcc - - { compiler: gcc-4.4, cxxstd: '98,0x', os: ubuntu-22.04, container: 'ubuntu:16.04' } - - { compiler: gcc-4.6, cxxstd: '03,0x', os: ubuntu-22.04, container: 'ubuntu:16.04' } - - { compiler: gcc-4.7, cxxstd: '03,11', os: ubuntu-22.04, container: 'ubuntu:16.04' } - - { compiler: gcc-4.8, cxxstd: '03,11', os: ubuntu-22.04, container: 'ubuntu:16.04' } - - { compiler: gcc-4.9, cxxstd: '03,11', os: ubuntu-22.04, container: 'ubuntu:16.04' } - - { compiler: gcc-5, cxxstd: '03,11,14,1z', os: ubuntu-22.04, container: 'ubuntu:18.04' } - - { compiler: gcc-6, cxxstd: '03,11,14,17', os: ubuntu-22.04, container: 'ubuntu:18.04' } + - { compiler: gcc-4.4, cxxstd: '98,0x', os: ubuntu-latest, container: 'ubuntu:16.04' } + - { compiler: gcc-4.6, cxxstd: '03,0x', os: ubuntu-latest, container: 'ubuntu:16.04' } + - { compiler: gcc-4.7, cxxstd: '03,11', os: ubuntu-latest, container: 'ubuntu:16.04' } + - { compiler: gcc-4.8, cxxstd: '03,11', os: ubuntu-latest, container: 'ubuntu:16.04' } + - { compiler: gcc-4.9, cxxstd: '03,11', os: ubuntu-latest, container: 'ubuntu:16.04' } + - { compiler: gcc-5, cxxstd: '03,11,14,1z', os: ubuntu-latest, container: 'ubuntu:18.04' } + - { compiler: gcc-6, cxxstd: '03,11,14,17', os: ubuntu-latest, container: 'ubuntu:18.04' } - { compiler: gcc-7, cxxstd: '03,11,14,17', os: ubuntu-20.04 } - { compiler: gcc-8, cxxstd: '03,11,14,17,2a', os: ubuntu-20.04 } - { compiler: gcc-9, cxxstd: '03,11,14,17,2a', os: ubuntu-20.04 } @@ -63,17 +63,17 @@ jobs: compiler: gcc-8, cxxstd: '03,11,14,17,2a', os: ubuntu-20.04, install: 'g++-8-multilib', address-model: '32,64' } # Linux, clang - - { compiler: clang-3.5, cxxstd: '03,11', os: ubuntu-22.04, container: 'ubuntu:16.04' } - - { compiler: clang-3.6, cxxstd: '03,11,14', os: ubuntu-22.04, container: 'ubuntu:16.04' } - - { compiler: clang-3.7, cxxstd: '03,11,14', os: ubuntu-22.04, container: 'ubuntu:16.04' } - - { compiler: clang-3.8, cxxstd: '03,11,14', os: ubuntu-22.04, container: 'ubuntu:16.04' } - - { compiler: clang-3.9, cxxstd: '03,11,14', os: ubuntu-22.04, container: 'ubuntu:18.04' } - - { compiler: clang-4.0, cxxstd: '03,11,14', os: ubuntu-22.04, container: 'ubuntu:18.04' } - - { compiler: clang-5.0, cxxstd: '03,11,14,1z', os: ubuntu-22.04, container: 'ubuntu:18.04' } - - { compiler: clang-6.0, cxxstd: '03,11,14,17', os: ubuntu-22.04, container: 'ubuntu:18.04' } - - { compiler: clang-7, cxxstd: '03,11,14,17', os: ubuntu-22.04, container: 'ubuntu:18.04' } + - { compiler: clang-3.5, cxxstd: '03,11', os: ubuntu-latest, container: 'ubuntu:16.04' } + - { compiler: clang-3.6, cxxstd: '03,11,14', os: ubuntu-latest, container: 'ubuntu:16.04' } + - { compiler: clang-3.7, cxxstd: '03,11,14', os: ubuntu-latest, container: 'ubuntu:16.04' } + - { compiler: clang-3.8, cxxstd: '03,11,14', os: ubuntu-latest, container: 'ubuntu:16.04' } + - { compiler: clang-3.9, cxxstd: '03,11,14', os: ubuntu-latest, container: 'ubuntu:18.04' } + - { compiler: clang-4.0, cxxstd: '03,11,14', os: ubuntu-latest, container: 'ubuntu:18.04' } + - { compiler: clang-5.0, cxxstd: '03,11,14,1z', os: ubuntu-latest, container: 'ubuntu:18.04' } + - { compiler: clang-6.0, cxxstd: '03,11,14,17', os: ubuntu-latest, container: 'ubuntu:18.04' } + - { compiler: clang-7, cxxstd: '03,11,14,17', os: ubuntu-latest, container: 'ubuntu:18.04' } # Note: clang-8 does not fully support C++20, so it is not compatible with some libstdc++ versions in this mode - - { compiler: clang-8, cxxstd: '03,11,14,17,2a', os: ubuntu-22.04, container: 'ubuntu:18.04', install: 'clang-8 g++-7', gcc_toolchain: 7 } + - { compiler: clang-8, cxxstd: '03,11,14,17,2a', os: ubuntu-latest, container: 'ubuntu:18.04', install: 'clang-8 g++-7', gcc_toolchain: 7 } - { compiler: clang-9, cxxstd: '03,11,14,17,2a', os: ubuntu-20.04 } - { compiler: clang-10, cxxstd: '03,11,14,17,20', os: ubuntu-20.04 } - { compiler: clang-11, cxxstd: '03,11,14,17,20', os: ubuntu-20.04 } @@ -83,7 +83,7 @@ jobs: - { compiler: clang-14, cxxstd: '03,11,14,17,20', os: ubuntu-22.04, install: 'clang-14 g++-12', gcc_toolchain: 12 } # libc++ - - { compiler: clang-6.0, cxxstd: '03,11,14', os: ubuntu-22.04, container: 'ubuntu:18.04', stdlib: libc++, install: 'clang-6.0 libc++-dev libc++abi-dev' } + - { compiler: clang-6.0, cxxstd: '03,11,14', os: ubuntu-latest, container: 'ubuntu:18.04', stdlib: libc++, install: 'clang-6.0 libc++-dev libc++abi-dev' } - { compiler: clang-12, cxxstd: '03,11,14,17,20', os: ubuntu-20.04, stdlib: libc++, install: 'clang-12 libc++-12-dev libc++abi-12-dev' } - { name: Clang w/ sanitizers, sanitize: yes, compiler: clang-14, cxxstd: '03,11,14,17,20', os: ubuntu-22.04, stdlib: libc++, install: 'clang-14 libc++-14-dev libc++abi-14-dev' } From 2b4691188324b794cee62999c7839395515d12db Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Sun, 25 Aug 2024 18:07:43 +0200 Subject: [PATCH 091/107] Fix appveyor build The VS 2019 image doesn't has Boost 1.77 anymore --- .appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.appveyor.yml b/.appveyor.yml index b14277f3..dbf6ee22 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -145,7 +145,7 @@ environment: APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 GENERATOR: Visual Studio 16 2019 configuration: Debug - BOOST_ROOT: C:\Libraries\boost_1_77_0 + BOOST_ROOT: C:\Libraries\boost_1_85_0 COVERITY_SCAN_TOKEN: secure: FzhGUr+AR/VOBGUta7dDLMDruolChnvyMSvsM/zLvPY= COVERITY_SCAN_NOTIFICATION_EMAIL: From 85a0b04e17ccf96f3dbda42ac4576e601211ec83 Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Sun, 25 Aug 2024 14:02:10 +0200 Subject: [PATCH 092/107] GHA: Remove most C++03 tests --- .github/workflows/ci.yml | 66 ++++++++++++++++++++++++---------------- 1 file changed, 39 insertions(+), 27 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ed83e29a..914499db 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -50,37 +50,41 @@ jobs: - { compiler: gcc-4.8, cxxstd: '03,11', os: ubuntu-latest, container: 'ubuntu:16.04' } - { compiler: gcc-4.9, cxxstd: '03,11', os: ubuntu-latest, container: 'ubuntu:16.04' } - { compiler: gcc-5, cxxstd: '03,11,14,1z', os: ubuntu-latest, container: 'ubuntu:18.04' } - - { compiler: gcc-6, cxxstd: '03,11,14,17', os: ubuntu-latest, container: 'ubuntu:18.04' } - - { compiler: gcc-7, cxxstd: '03,11,14,17', os: ubuntu-20.04 } - - { compiler: gcc-8, cxxstd: '03,11,14,17,2a', os: ubuntu-20.04 } - - { compiler: gcc-9, cxxstd: '03,11,14,17,2a', os: ubuntu-20.04 } - - { compiler: gcc-10, cxxstd: '03,11,14,17,20', os: ubuntu-20.04 } - - { compiler: gcc-11, cxxstd: '03,11,14,17,20', os: ubuntu-20.04 } - - { compiler: gcc-12, cxxstd: '03,11,14,17,20', os: ubuntu-22.04 } + - { compiler: gcc-6, cxxstd: '11,14,17', os: ubuntu-latest, container: 'ubuntu:18.04' } + - { compiler: gcc-7, cxxstd: '11,14,17', os: ubuntu-20.04 } + - { compiler: gcc-8, cxxstd: '11,14,17,2a', os: ubuntu-20.04 } + - { compiler: gcc-9, cxxstd: '11,14,17,2a', os: ubuntu-20.04 } + - { compiler: gcc-10, cxxstd: '11,14,17,20', os: ubuntu-20.04 } + - { compiler: gcc-11, cxxstd: '11,14,17,20', os: ubuntu-20.04 } + - { compiler: gcc-12, cxxstd: '11,14,17,20', os: ubuntu-22.04 } - { name: GCC w/ sanitizers, sanitize: yes, - compiler: gcc-12, cxxstd: '03,11,14,17,20', os: ubuntu-22.04 } + compiler: gcc-12, cxxstd: '11,14,17,20', os: ubuntu-22.04 } - { name: Collect coverage, coverage: yes, - compiler: gcc-8, cxxstd: '03,11,14,17,2a', os: ubuntu-20.04, install: 'g++-8-multilib', address-model: '32,64' } + compiler: gcc-8, cxxstd: '11,14,17,2a', os: ubuntu-20.04, install: 'g++-8-multilib', address-model: '32,64' } # Linux, clang - - { compiler: clang-3.5, cxxstd: '03,11', os: ubuntu-latest, container: 'ubuntu:16.04' } - - { compiler: clang-3.6, cxxstd: '03,11,14', os: ubuntu-latest, container: 'ubuntu:16.04' } - - { compiler: clang-3.7, cxxstd: '03,11,14', os: ubuntu-latest, container: 'ubuntu:16.04' } - - { compiler: clang-3.8, cxxstd: '03,11,14', os: ubuntu-latest, container: 'ubuntu:16.04' } - - { compiler: clang-3.9, cxxstd: '03,11,14', os: ubuntu-latest, container: 'ubuntu:18.04' } - - { compiler: clang-4.0, cxxstd: '03,11,14', os: ubuntu-latest, container: 'ubuntu:18.04' } - - { compiler: clang-5.0, cxxstd: '03,11,14,1z', os: ubuntu-latest, container: 'ubuntu:18.04' } - - { compiler: clang-6.0, cxxstd: '03,11,14,17', os: ubuntu-latest, container: 'ubuntu:18.04' } - - { compiler: clang-7, cxxstd: '03,11,14,17', os: ubuntu-latest, container: 'ubuntu:18.04' } + - { compiler: clang-3.5, cxxstd: '03,11', os: ubuntu-latest, container: 'ubuntu:16.04' } + - { compiler: clang-3.6, cxxstd: '11,14', os: ubuntu-latest, container: 'ubuntu:16.04' } + - { compiler: clang-3.7, cxxstd: '11,14', os: ubuntu-latest, container: 'ubuntu:16.04' } + - { compiler: clang-3.8, cxxstd: '11,14', os: ubuntu-latest, container: 'ubuntu:16.04' } + - { compiler: clang-3.9, cxxstd: '11,14', os: ubuntu-latest, container: 'ubuntu:18.04' } + - { compiler: clang-4.0, cxxstd: '11,14', os: ubuntu-latest, container: 'ubuntu:18.04' } + - { compiler: clang-5.0, cxxstd: '11,14,1z', os: ubuntu-latest, container: 'ubuntu:18.04' } + - { compiler: clang-6.0, cxxstd: '11,14,17', os: ubuntu-latest, container: 'ubuntu:18.04' } + - { compiler: clang-7, cxxstd: '11,14,17', os: ubuntu-latest, container: 'ubuntu:18.04' } # Note: clang-8 does not fully support C++20, so it is not compatible with some libstdc++ versions in this mode - - { compiler: clang-8, cxxstd: '03,11,14,17,2a', os: ubuntu-latest, container: 'ubuntu:18.04', install: 'clang-8 g++-7', gcc_toolchain: 7 } - - { compiler: clang-9, cxxstd: '03,11,14,17,2a', os: ubuntu-20.04 } - - { compiler: clang-10, cxxstd: '03,11,14,17,20', os: ubuntu-20.04 } - - { compiler: clang-11, cxxstd: '03,11,14,17,20', os: ubuntu-20.04 } - - { compiler: clang-12, cxxstd: '03,11,14,17,20', os: ubuntu-20.04 } + - { compiler: clang-8, cxxstd: '11,14,17,2a', os: ubuntu-latest, container: 'ubuntu:18.04', install: 'clang-8 g++-7', gcc_toolchain: 7 } + - { compiler: clang-9, cxxstd: '11,14,17,2a', os: ubuntu-20.04 } + - { compiler: clang-10, cxxstd: '11,14,17,20', os: ubuntu-20.04 } + - { compiler: clang-11, cxxstd: '11,14,17,20', os: ubuntu-20.04 } + - { compiler: clang-12, cxxstd: '11,14,17,20', os: ubuntu-20.04 } # Clang isn't compatible with libstdc++-13, so use the slightly older one - - { compiler: clang-13, cxxstd: '03,11,14,17,20', os: ubuntu-22.04, install: 'clang-13 g++-12', gcc_toolchain: 12 } - - { compiler: clang-14, cxxstd: '03,11,14,17,20', os: ubuntu-22.04, install: 'clang-14 g++-12', gcc_toolchain: 12 } + - { compiler: clang-13, cxxstd: '11,14,17,20', os: ubuntu-22.04, install: 'clang-13 g++-12', gcc_toolchain: 12 } + - { compiler: clang-14, cxxstd: '11,14,17,20', os: ubuntu-22.04, install: 'clang-14 g++-12', gcc_toolchain: 12 } + - { compiler: clang-15, cxxstd: '11,14,17,20', os: ubuntu-22.04, install: 'clang-15 g++-12', gcc_toolchain: 12 } + - { compiler: clang-16, cxxstd: '11,14,17,20,2b', os: ubuntu-latest, container: 'ubuntu:23.04' } + - { compiler: clang-17, cxxstd: '11,14,17,20,2b', os: ubuntu-latest, container: 'ubuntu:23.10' } + - { compiler: clang-18, cxxstd: '11,14,17,20,2b', os: ubuntu-latest, container: 'ubuntu:24.04' } # libc++ - { compiler: clang-6.0, cxxstd: '03,11,14', os: ubuntu-latest, container: 'ubuntu:18.04', stdlib: libc++, install: 'clang-6.0 libc++-dev libc++abi-dev' } @@ -107,10 +111,18 @@ jobs: apt-get -o Acquire::Retries=$NET_RETRY_COUNT update apt-get -o Acquire::Retries=$NET_RETRY_COUNT install -y sudo software-properties-common curl # Need (newer) git, and the older Ubuntu container may require requesting the key manually using port 80 - curl -sSL --retry ${NET_RETRY_COUNT:-5} 'http://keyserver.ubuntu.com/pks/lookup?op=get&search=0xE1DD270288B4E6030699E45FA1715D88E1DF1F24' | sudo gpg --dearmor > /etc/apt/trusted.gpg.d/git-core_ubuntu_ppa.gpg + curl -sSL --retry ${NET_RETRY_COUNT:-5} 'http://keyserver.ubuntu.com/pks/lookup?op=get&search=0xE1DD270288B4E6030699E45FA1715D88E1DF1F24' | sudo gpg --dearmor -o /etc/apt/trusted.gpg.d/git-core_ubuntu_ppa.gpg for i in {1..${NET_RETRY_COUNT:-3}}; do sudo -E add-apt-repository -y ppa:git-core/ppa && break || sleep 10; done apt-get -o Acquire::Retries=$NET_RETRY_COUNT update - apt-get -o Acquire::Retries=$NET_RETRY_COUNT install -y g++ python libpython-dev git + osver=$(lsb_release -sr | cut -f1 -d.) + pkgs="g++ git" + # Ubuntu 22+ has only Python 3 in the repos + if [ -n "$osver" ] && [ "$osver" -ge "22" ]; then + pkgs+=" python-is-python3 libpython3-dev" + else + pkgs+=" python libpython-dev" + fi + apt-get -o Acquire::Retries=$NET_RETRY_COUNT install -y $pkgs fi # For jobs not compatible with ccache, use "ccache: no" in the matrix if [[ "${{ matrix.ccache }}" == "no" ]]; then From 84972e2ebd719ef459d27d55bc4384656e334848 Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Sun, 29 Sep 2024 13:01:48 +0200 Subject: [PATCH 093/107] CI: Fix Clang-Format check --- .github/workflows/ci_tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci_tests.yml b/.github/workflows/ci_tests.yml index dcf90ccf..d2ae15f4 100644 --- a/.github/workflows/ci_tests.yml +++ b/.github/workflows/ci_tests.yml @@ -157,7 +157,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - uses: DoozyX/clang-format-lint-action@v0.11 + - uses: DoozyX/clang-format-lint-action@v0.18 with: exclude: './doc' clangFormatVersion: 10 From bac0f207b6b8d152c36d65d1b16f05ab68a24802 Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Mon, 7 Oct 2024 13:56:59 +0200 Subject: [PATCH 094/107] GHA: Add macos-13 & 14 macos-12 will be dropped by the end of 2024 so test with the newer versions already --- .github/workflows/ci.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 914499db..4173f73d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -94,6 +94,9 @@ jobs: # OSX, clang - { compiler: clang, cxxstd: '11,14,17,20', os: macos-12, sanitize: yes } + - { name: MacOS w/ clang and sanitizers, + compiler: clang, cxxstd: '11,14,17,20,2b', os: macos-13, sanitize: yes } + - { compiler: clang, cxxstd: '11,14,17,20,2b', os: macos-14 } timeout-minutes: 120 runs-on: ${{matrix.os}} From 64ae4e0c28e39562285bbf5014c932060f073244 Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Thu, 17 Oct 2024 19:23:12 +0200 Subject: [PATCH 095/107] Add test for buffering behavior of iostreams Closes #186 --- test/test_iostream.cpp | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/test/test_iostream.cpp b/test/test_iostream.cpp index 8dfcdf76..cffd8ea7 100644 --- a/test/test_iostream.cpp +++ b/test/test_iostream.cpp @@ -35,6 +35,11 @@ const std::string outputString = const bool usesNowideRdBufIn = nw::cin.rdbuf() != std::cin.rdbuf(); const bool usesNowideRdBufOut = nw::cout.rdbuf() != std::cout.rdbuf(); +bool is_buffered(const std::ostream& os) +{ + return (os.flags() & std::ios_base::unitbuf) == 0; +} + #ifndef BOOST_NOWIDE_TEST_INTERACTIVE class mock_output_buffer final : public nw::detail::console_output_buffer_base { @@ -134,12 +139,14 @@ void test_is_valid_UTF8() TEST(!is_valid_UTF8(invalid_utf8_tests[0].utf8)); // Detect invalid } -void test_tie() +void test_tie_and_buffered() { TEST(nw::cin.tie() == &nw::cout); TEST(nw::cerr.tie() == &nw::cout); - TEST((nw::cerr.flags() & std::ios_base::unitbuf) != 0); TEST(nw::clog.tie() == nullptr); + TEST(is_buffered(nw::cout)); + TEST(!is_buffered(nw::cerr)); + TEST(is_buffered(nw::clog)); } void test_putback_and_get() @@ -233,6 +240,17 @@ void test_cerr() TEST_MOCKED(mock_buf.output == nw::widen("aHello World")); } +void test_clog() +{ + if(usesNowideRdBufOut) // Only executed when attached to a real terminal, i.e. not on CI + TEST(nw::clog.rdbuf() != std::clog.rdbuf()); // LCOV_EXCL_STOP + + TEST(nw::clog.rdbuf() != std::cout.rdbuf()); + TEST(nw::clog.rdbuf() != nw::cin.rdbuf()); + TEST(nw::clog.rdbuf() != nw::cout.rdbuf()); + TEST(nw::clog.rdbuf() == nw::cerr.rdbuf()); +} + void test_cerr_single_char() { INSTALL_MOCK_BUF(cerr, mock_output_buffer); @@ -494,7 +512,8 @@ void test_console() std::cout << "Test cout console" << std::endl; { RedirectStdio stdoutHandle(STD_OUTPUT_HANDLE); - decltype(nw::cout) cout(true, nullptr); + using cout_t = decltype(nw::cout); + cout_t cout(cout_t::target_stream::output, true, nullptr); TEST(cout.rdbuf() != std::cout.rdbuf()); const std::string testString = "Hello std out\n\xc3\xa4-\xc3\xb6-\xc3\xbc\n"; @@ -507,7 +526,8 @@ void test_console() { RedirectStdio stderrHandle(STD_ERROR_HANDLE); - decltype(nw::cerr) cerr(false, nullptr); + using cerr_t = decltype(nw::cerr); + cerr_t cerr(cerr_t::target_stream::error, false, nullptr); TEST(cerr.rdbuf() != std::cerr.rdbuf()); const std::string testString = "Hello std err\n\xc3\xa4-\xc3\xb6-\xc3\xbc\n"; @@ -573,12 +593,13 @@ void test_main(int argc, char** argv, char**) test_ctrl_z_is_eof(); // LCOV_EXCL_LINE #else test_is_valid_UTF8(); - test_tie(); + test_tie_and_buffered(); test_putback_and_get(); test_cout(); test_cout_single_char(); test_cerr(); test_cerr_single_char(); + test_clog(); test_cin(); test_cin_getline(); test_ctrl_z_is_eof(); From 00c8a9af2e3fa29e0a9c24f4ab62e74a0968dc30 Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Fri, 18 Oct 2024 10:20:06 +0200 Subject: [PATCH 096/107] Enhance buffering and target stream handling of iostreams buffering may be independent of tied streams, so make it an extra param --- include/boost/nowide/iostream.hpp | 8 ++++++- src/iostream.cpp | 38 ++++++++++++++++++------------- test/test_iostream.cpp | 11 +++++---- 3 files changed, 36 insertions(+), 21 deletions(-) diff --git a/include/boost/nowide/iostream.hpp b/include/boost/nowide/iostream.hpp index 54f14001..ed7cb9e8 100644 --- a/include/boost/nowide/iostream.hpp +++ b/include/boost/nowide/iostream.hpp @@ -40,7 +40,13 @@ namespace nowide { class BOOST_NOWIDE_DECL winconsole_ostream : public std::ostream { public: - winconsole_ostream(bool isBuffered, winconsole_ostream* tieStream); + enum class target_stream + { + output, + error, + log, + }; + winconsole_ostream(target_stream target, bool isBuffered, winconsole_ostream* tieStream); ~winconsole_ostream(); private: diff --git a/src/iostream.cpp b/src/iostream.cpp index 26959926..7171226f 100644 --- a/src/iostream.cpp +++ b/src/iostream.cpp @@ -82,27 +82,32 @@ namespace nowide { } }; - winconsole_ostream::winconsole_ostream(const bool isBuffered, winconsole_ostream* tieStream) : std::ostream(0) + winconsole_ostream::winconsole_ostream(const target_stream target, + const bool isBuffered, + winconsole_ostream* tieStream) : + std::ostream(nullptr) { - HANDLE h; - if(isBuffered) - h = GetStdHandle(STD_OUTPUT_HANDLE); - else - h = GetStdHandle(STD_ERROR_HANDLE); + const HANDLE h = GetStdHandle(target == target_stream::output ? STD_OUTPUT_HANDLE : STD_ERROR_HANDLE); + if(is_atty_handle(h)) { d.reset(new console_output_buffer(h)); - std::ostream::rdbuf(d.get()); + rdbuf(d.get()); } else { - std::ostream::rdbuf(isBuffered ? std::cout.rdbuf() : std::cerr.rdbuf()); - assert(rdbuf()); + switch(target) + { + case target_stream::error: rdbuf(std::cerr.rdbuf()); break; + case target_stream::log: rdbuf(std::clog.rdbuf()); break; + case target_stream::output: rdbuf(std::cout.rdbuf()); break; + } } + assert(rdbuf()); + if(tieStream) - { tie(tieStream); - setf(ios_base::unitbuf); // If tieStream is set, this is cerr -> set unbuffered - } + if(!isBuffered) + setf(ios_base::unitbuf); } winconsole_ostream::~winconsole_ostream() { @@ -134,7 +139,7 @@ namespace nowide { } // namespace detail - // Make sure those are initialized as early as possible +// Make sure those are initialized as early as possible #ifdef BOOST_MSVC #pragma warning(disable : 4073) #pragma init_seg(lib) @@ -144,10 +149,11 @@ namespace nowide { #else #define BOOST_NOWIDE_INIT_PRIORITY #endif - detail::winconsole_ostream cout BOOST_NOWIDE_INIT_PRIORITY(true, nullptr); + using target_stream = detail::winconsole_ostream::target_stream; + detail::winconsole_ostream cout BOOST_NOWIDE_INIT_PRIORITY(target_stream::output, true, nullptr); detail::winconsole_istream cin BOOST_NOWIDE_INIT_PRIORITY(&cout); - detail::winconsole_ostream cerr BOOST_NOWIDE_INIT_PRIORITY(false, &cout); - detail::winconsole_ostream clog BOOST_NOWIDE_INIT_PRIORITY(false, nullptr); + detail::winconsole_ostream cerr BOOST_NOWIDE_INIT_PRIORITY(target_stream::error, false, &cout); + detail::winconsole_ostream clog BOOST_NOWIDE_INIT_PRIORITY(target_stream::log, true, nullptr); } // namespace nowide } // namespace boost diff --git a/test/test_iostream.cpp b/test/test_iostream.cpp index cffd8ea7..59aa1a6e 100644 --- a/test/test_iostream.cpp +++ b/test/test_iostream.cpp @@ -242,13 +242,16 @@ void test_cerr() void test_clog() { - if(usesNowideRdBufOut) // Only executed when attached to a real terminal, i.e. not on CI - TEST(nw::clog.rdbuf() != std::clog.rdbuf()); // LCOV_EXCL_STOP + if(usesNowideRdBufOut) // Only executed when attached to a real terminal, i.e. not on CI + { + TEST(nw::clog.rdbuf() != std::clog.rdbuf()); // LCOV_EXCL_LINE + // for the std:: streams this is not true for all implementations, so only check when using custom buffers + TEST(nw::clog.rdbuf() != nw::cerr.rdbuf()); // LCOV_EXCL_LINE + } - TEST(nw::clog.rdbuf() != std::cout.rdbuf()); TEST(nw::clog.rdbuf() != nw::cin.rdbuf()); TEST(nw::clog.rdbuf() != nw::cout.rdbuf()); - TEST(nw::clog.rdbuf() == nw::cerr.rdbuf()); + TEST(nw::clog.rdbuf() != std::cout.rdbuf()); } void test_cerr_single_char() From 015be201a5d8dad8c1c405f300b8837b883692f5 Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Fri, 18 Oct 2024 09:37:17 +0200 Subject: [PATCH 097/107] Fix test for coverage --- test/test_iostream.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/test_iostream.cpp b/test/test_iostream.cpp index 59aa1a6e..ff7e4c60 100644 --- a/test/test_iostream.cpp +++ b/test/test_iostream.cpp @@ -551,7 +551,6 @@ void test_console() // coverity[root_function] void test_main(int argc, char** argv, char**) { - // LCOV_EXCL_START if(usesNowideRdBufIn) nw::cout << "Using Nowide input buffer\n"; else @@ -560,7 +559,6 @@ void test_main(int argc, char** argv, char**) nw::cout << "Using Nowide output buffer\n"; // LCOV_EXCL_LINE else nw::cout << "NOT using Nowide output buffer\n"; - // LCOV_EXCL_STOP const std::string arg = (argc == 1) ? "" : argv[1]; if(arg == "passthrough") // Read string from cin and write to cout From fd38460b4135b02473fb04dd4f72d667fea8a6cb Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Fri, 22 Nov 2024 13:16:12 +0100 Subject: [PATCH 098/107] Fix documentation of enable_if_path_t --- include/boost/nowide/detail/is_path.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/nowide/detail/is_path.hpp b/include/boost/nowide/detail/is_path.hpp index 84413c31..4419a951 100644 --- a/include/boost/nowide/detail/is_path.hpp +++ b/include/boost/nowide/detail/is_path.hpp @@ -27,7 +27,7 @@ namespace nowide { static constexpr bool value = decltype(test(0))::value; }; - /// SFINAE trait which has a member "type = Result" if the Path is a *\::filesystem::path + /// SFINAE trait/alias which resolves to Result if the Path is a *\::filesystem::path template using enable_if_path_t = typename std::enable_if::value, Result>::type; From ca641dc0caed07140ac06670c41f1d063f603cb1 Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Wed, 27 Nov 2024 19:28:58 +0100 Subject: [PATCH 099/107] GHA: Handle removal of Node 16 Download an unofficial Node 20 build against glibc 2.17 --- .github/workflows/ci.yml | 46 +++++++++------------------------------- 1 file changed, 10 insertions(+), 36 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4173f73d..6e920932 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -100,7 +100,11 @@ jobs: timeout-minutes: 120 runs-on: ${{matrix.os}} - container: ${{matrix.container}} + container: + image: ${{matrix.container}} + volumes: + - /node20217:/node20217:rw,rshared + - ${{ startsWith(matrix.container, 'ubuntu:1') && '/node20217:/__e/node20:ro,rshared' || ' ' }} env: {B2_USE_CCACHE: 1} steps: @@ -132,41 +136,20 @@ jobs: echo "B2_USE_CCACHE=0" >> $GITHUB_ENV fi git config --global pack.threads 0 - ! command -v cmake &> /dev/null || echo "B2_FLAGS=--nowide-enable-cmake" >> $GITHUB_ENV - - if [[ "${{matrix.container}}" == "ubuntu:16.04" ]] || [[ "${{matrix.container}}" == "ubuntu:18.04" ]]; then - # Ubuntu 16/18 can't run Node 20, so stick to older actions: https://github.com/actions/checkout/issues/1590 - echo "GHA_USE_NODE_20=false" >> $GITHUB_ENV - echo "ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION=true" >> $GITHUB_ENV - else - echo "GHA_USE_NODE_20=true" >> $GITHUB_ENV + if [[ "${{matrix.container}}" == "ubuntu:1"* ]]; then + # Node 20 doesn't work with Ubuntu 16/18 glibc: https://github.com/actions/checkout/issues/1590 + curl -sL https://unofficial-builds.nodejs.org/download/release/v20.9.0/node-v20.9.0-linux-x64-glibc-217.tar.xz | tar -xJ --strip-components 1 -C /node20217 fi - - - uses: actions/checkout@v3 - if: env.GHA_USE_NODE_20 == 'false' - with: - # For coverage builds fetch the whole history, else only 1 commit using a 'fake ternary' - fetch-depth: ${{ matrix.coverage && '0' || '1' }} + ! command -v cmake &> /dev/null || echo "B2_FLAGS=--nowide-enable-cmake" >> $GITHUB_ENV - uses: actions/checkout@v4 - if: env.GHA_USE_NODE_20 == 'true' with: # For coverage builds fetch the whole history, else only 1 commit using a 'fake ternary' fetch-depth: ${{ matrix.coverage && '0' || '1' }} - - name: Cache ccache - uses: actions/cache@v3 - if: env.B2_USE_CCACHE && env.GHA_USE_NODE_20 == 'false' - with: - path: ~/.ccache - key: ${{matrix.os}}-${{matrix.container}}-${{matrix.compiler}}-${{github.sha}} - restore-keys: | - ${{matrix.os}}-${{matrix.container}}-${{matrix.compiler}}- - ${{matrix.os}}-${{matrix.container}}-${{matrix.compiler}} - - name: Cache ccache uses: actions/cache@v4 - if: env.B2_USE_CCACHE && env.GHA_USE_NODE_20 == 'true' + if: env.B2_USE_CCACHE with: path: ~/.ccache key: ${{matrix.os}}-${{matrix.container}}-${{matrix.compiler}}-${{github.sha}} @@ -174,17 +157,8 @@ jobs: ${{matrix.os}}-${{matrix.container}}-${{matrix.compiler}}- ${{matrix.os}}-${{matrix.container}}-${{matrix.compiler}} - - name: Fetch Boost.CI - uses: actions/checkout@v3 - if: env.GHA_USE_NODE_20 == 'false' - with: - repository: boostorg/boost-ci - ref: master - path: boost-ci-cloned - - name: Fetch Boost.CI uses: actions/checkout@v4 - if: env.GHA_USE_NODE_20 == 'true' with: repository: boostorg/boost-ci ref: master From dda55a1d8c28eeb4d5dfa384223ff8d686ed62b1 Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Wed, 27 Nov 2024 19:45:57 +0100 Subject: [PATCH 100/107] Don't use Ubuntu 23:x --- .github/workflows/ci.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6e920932..a0365a70 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -82,9 +82,10 @@ jobs: - { compiler: clang-13, cxxstd: '11,14,17,20', os: ubuntu-22.04, install: 'clang-13 g++-12', gcc_toolchain: 12 } - { compiler: clang-14, cxxstd: '11,14,17,20', os: ubuntu-22.04, install: 'clang-14 g++-12', gcc_toolchain: 12 } - { compiler: clang-15, cxxstd: '11,14,17,20', os: ubuntu-22.04, install: 'clang-15 g++-12', gcc_toolchain: 12 } - - { compiler: clang-16, cxxstd: '11,14,17,20,2b', os: ubuntu-latest, container: 'ubuntu:23.04' } - - { compiler: clang-17, cxxstd: '11,14,17,20,2b', os: ubuntu-latest, container: 'ubuntu:23.10' } - - { compiler: clang-18, cxxstd: '11,14,17,20,2b', os: ubuntu-latest, container: 'ubuntu:24.04' } + - { compiler: clang-16, cxxstd: '11,14,17,20,2b', os: ubuntu-24.04 } + # https://github.com/llvm/llvm-project/issues/59827: disabled 2b/23 for clang-17 with libstdc++13 in 24.04 + - { compiler: clang-17, cxxstd: '11,14,17,20', os: ubuntu-24.04 } + - { compiler: clang-18, cxxstd: '11,14,17,20,23,2c', os: ubuntu-24.04 } # libc++ - { compiler: clang-6.0, cxxstd: '03,11,14', os: ubuntu-latest, container: 'ubuntu:18.04', stdlib: libc++, install: 'clang-6.0 libc++-dev libc++abi-dev' } From 51e6d9c6a2c6e8b3bcb6efab1cafc300380fe590 Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Tue, 10 Dec 2024 08:53:48 +0100 Subject: [PATCH 101/107] GHA: Update OS versions, remove containers where possible and add new compilers --- .github/workflows/ci.yml | 37 ++++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a0365a70..4dc80523 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -54,26 +54,29 @@ jobs: - { compiler: gcc-7, cxxstd: '11,14,17', os: ubuntu-20.04 } - { compiler: gcc-8, cxxstd: '11,14,17,2a', os: ubuntu-20.04 } - { compiler: gcc-9, cxxstd: '11,14,17,2a', os: ubuntu-20.04 } - - { compiler: gcc-10, cxxstd: '11,14,17,20', os: ubuntu-20.04 } - - { compiler: gcc-11, cxxstd: '11,14,17,20', os: ubuntu-20.04 } + - { compiler: gcc-10, cxxstd: '11,14,17,20', os: ubuntu-22.04 } + - { compiler: gcc-11, cxxstd: '11,14,17,20', os: ubuntu-22.04 } - { compiler: gcc-12, cxxstd: '11,14,17,20', os: ubuntu-22.04 } + - { compiler: gcc-13, cxxstd: '11,14,17,20,2b', os: ubuntu-24.04 } + - { compiler: gcc-14, cxxstd: '11,14,17,20,2b', os: ubuntu-24.04 } + - { name: GCC w/ sanitizers, sanitize: yes, - compiler: gcc-12, cxxstd: '11,14,17,20', os: ubuntu-22.04 } + compiler: gcc-13, cxxstd: '11,14,17,20', os: ubuntu-24.04 } - { name: Collect coverage, coverage: yes, compiler: gcc-8, cxxstd: '11,14,17,2a', os: ubuntu-20.04, install: 'g++-8-multilib', address-model: '32,64' } # Linux, clang - - { compiler: clang-3.5, cxxstd: '03,11', os: ubuntu-latest, container: 'ubuntu:16.04' } - - { compiler: clang-3.6, cxxstd: '11,14', os: ubuntu-latest, container: 'ubuntu:16.04' } - - { compiler: clang-3.7, cxxstd: '11,14', os: ubuntu-latest, container: 'ubuntu:16.04' } - - { compiler: clang-3.8, cxxstd: '11,14', os: ubuntu-latest, container: 'ubuntu:16.04' } - - { compiler: clang-3.9, cxxstd: '11,14', os: ubuntu-latest, container: 'ubuntu:18.04' } - - { compiler: clang-4.0, cxxstd: '11,14', os: ubuntu-latest, container: 'ubuntu:18.04' } - - { compiler: clang-5.0, cxxstd: '11,14,1z', os: ubuntu-latest, container: 'ubuntu:18.04' } - - { compiler: clang-6.0, cxxstd: '11,14,17', os: ubuntu-latest, container: 'ubuntu:18.04' } - - { compiler: clang-7, cxxstd: '11,14,17', os: ubuntu-latest, container: 'ubuntu:18.04' } + - { compiler: clang-3.5, cxxstd: '11', os: ubuntu-latest, container: 'ubuntu:16.04' } + - { compiler: clang-3.6, cxxstd: '11,14', os: ubuntu-latest, container: 'ubuntu:16.04' } + - { compiler: clang-3.7, cxxstd: '11,14', os: ubuntu-latest, container: 'ubuntu:16.04' } + - { compiler: clang-3.8, cxxstd: '11,14', os: ubuntu-latest, container: 'ubuntu:16.04' } + - { compiler: clang-3.9, cxxstd: '11,14', os: ubuntu-latest, container: 'ubuntu:18.04' } + - { compiler: clang-4.0, cxxstd: '11,14', os: ubuntu-latest, container: 'ubuntu:18.04' } + - { compiler: clang-5.0, cxxstd: '11,14,1z', os: ubuntu-latest, container: 'ubuntu:18.04' } + - { compiler: clang-6.0, cxxstd: '11,14,17', os: ubuntu-20.04 } + - { compiler: clang-7, cxxstd: '11,14,17', os: ubuntu-20.04 } # Note: clang-8 does not fully support C++20, so it is not compatible with some libstdc++ versions in this mode - - { compiler: clang-8, cxxstd: '11,14,17,2a', os: ubuntu-latest, container: 'ubuntu:18.04', install: 'clang-8 g++-7', gcc_toolchain: 7 } + - { compiler: clang-8, cxxstd: '11,14,17,2a', os: ubuntu-20.04 , install: 'clang-8 g++-7', gcc_toolchain: 7 } - { compiler: clang-9, cxxstd: '11,14,17,2a', os: ubuntu-20.04 } - { compiler: clang-10, cxxstd: '11,14,17,20', os: ubuntu-20.04 } - { compiler: clang-11, cxxstd: '11,14,17,20', os: ubuntu-20.04 } @@ -88,16 +91,16 @@ jobs: - { compiler: clang-18, cxxstd: '11,14,17,20,23,2c', os: ubuntu-24.04 } # libc++ - - { compiler: clang-6.0, cxxstd: '03,11,14', os: ubuntu-latest, container: 'ubuntu:18.04', stdlib: libc++, install: 'clang-6.0 libc++-dev libc++abi-dev' } - - { compiler: clang-12, cxxstd: '03,11,14,17,20', os: ubuntu-20.04, stdlib: libc++, install: 'clang-12 libc++-12-dev libc++abi-12-dev' } + - { compiler: clang-6.0, cxxstd: '11,14', os: ubuntu-latest, container: 'ubuntu:18.04', stdlib: libc++, install: 'clang-6.0 libc++-dev libc++abi-dev' } + - { compiler: clang-12, cxxstd: '11,14,17,20', os: ubuntu-20.04, stdlib: libc++, install: 'clang-12 libc++-12-dev libc++abi-12-dev' } - { name: Clang w/ sanitizers, sanitize: yes, - compiler: clang-14, cxxstd: '03,11,14,17,20', os: ubuntu-22.04, stdlib: libc++, install: 'clang-14 libc++-14-dev libc++abi-14-dev' } + compiler: clang-14, cxxstd: '11,14,17,20', os: ubuntu-22.04, stdlib: libc++, install: 'clang-14 libc++-14-dev libc++abi-14-dev' } # OSX, clang - - { compiler: clang, cxxstd: '11,14,17,20', os: macos-12, sanitize: yes } - { name: MacOS w/ clang and sanitizers, compiler: clang, cxxstd: '11,14,17,20,2b', os: macos-13, sanitize: yes } - { compiler: clang, cxxstd: '11,14,17,20,2b', os: macos-14 } + - { compiler: clang, cxxstd: '11,14,17,20,2b', os: macos-15 } timeout-minutes: 120 runs-on: ${{matrix.os}} From 1423d15ba54fa14063fdeab496f0345323920c14 Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Sun, 8 Dec 2024 19:50:51 +0100 Subject: [PATCH 102/107] Use boost.io node --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4dc80523..f8abb1da 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -142,7 +142,7 @@ jobs: git config --global pack.threads 0 if [[ "${{matrix.container}}" == "ubuntu:1"* ]]; then # Node 20 doesn't work with Ubuntu 16/18 glibc: https://github.com/actions/checkout/issues/1590 - curl -sL https://unofficial-builds.nodejs.org/download/release/v20.9.0/node-v20.9.0-linux-x64-glibc-217.tar.xz | tar -xJ --strip-components 1 -C /node20217 + curl -sL https://archives.boost.io/misc/node/node-v20.9.0-linux-x64-glibc-217.tar.xz | tar -xJ --strip-components 1 -C /node20217 fi ! command -v cmake &> /dev/null || echo "B2_FLAGS=--nowide-enable-cmake" >> $GITHUB_ENV From 9646dc324d10d11c5020e120fd732c3fee3e5257 Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Fri, 29 Nov 2024 09:53:38 +0100 Subject: [PATCH 103/107] Make `getenv` thread-safe In order to return a non-owning pointer without memory leaks the function needs to use a static variable. When calling it from multiple threads there is a data race during the assignment (and conversion) to this variable. Fix by making it `thread_local`. Fixes #189 --- include/boost/nowide/cstdlib.hpp | 7 ++++++- src/cstdlib.cpp | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/include/boost/nowide/cstdlib.hpp b/include/boost/nowide/cstdlib.hpp index a48028a1..cfdac7cf 100644 --- a/include/boost/nowide/cstdlib.hpp +++ b/include/boost/nowide/cstdlib.hpp @@ -21,7 +21,12 @@ namespace nowide { /// /// \brief UTF-8 aware getenv. Returns 0 if the variable is not set. /// - /// This function is not thread safe or reenterable as defined by the standard library + /// The string pointed to shall not be modified by the program. + /// This function is thread-safe as long as no other thread modifies the host environment. + /// However subsequent calls to this function might overwrite the string pointed to. + /// + /// Warning: The returned pointer might only be valid for as long as the calling thread is alive. + /// So avoid passing it across thread boundaries. /// BOOST_NOWIDE_DECL char* getenv(const char* key); diff --git a/src/cstdlib.cpp b/src/cstdlib.cpp index ab0d4455..76f0319f 100644 --- a/src/cstdlib.cpp +++ b/src/cstdlib.cpp @@ -52,7 +52,7 @@ namespace boost { namespace nowide { char* getenv(const char* key) { - static stackstring value; + thread_local stackstring value; const wshort_stackstring name(key); From ff34275b81c330a1517c8b85321193712f02f6d1 Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Fri, 29 Nov 2024 10:13:16 +0100 Subject: [PATCH 104/107] Update changelog --- doc/changelog.dox | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/doc/changelog.dox b/doc/changelog.dox index ae2b4674..56cc560e 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -1,5 +1,5 @@ // -// Copyright (c) 2019-2023 Alexander Grund +// Copyright (c) 2019-2024 Alexander Grund // // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt @@ -8,6 +8,10 @@ \section changelog Changelog +\subsection changelog_11_3_1 Nowide 11.3.1 (Boost 1.88) +- Fix redefinition of `_CRT_SECURE_NO_WARNINGS` +- Make `getenv` thread-safe + \subsection changelog_11_3_0 Nowide 11.3.0 (Boost 1.82) - Add `convert_string` overload accepting a string - Add `quoted` to output (quoted) paths (std::filesystem or boost::filesystem) From a2d660f2c1ada415d28bb00b1699dbfa0188b461 Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Wed, 4 Dec 2024 17:11:21 +0100 Subject: [PATCH 105/107] GHA: Fix MinGW test Using `bash` puts `/mingw64/bin` first in the path but the compiler from `/c/mingw64/bin` is used. This leads to errors running the tests: "Exit code 0xc0000139" (DLL issue) which are related to the use of `thread_local`. Using the powershell works in all cases. --- .github/workflows/ci_tests.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci_tests.yml b/.github/workflows/ci_tests.yml index d2ae15f4..b41337a6 100644 --- a/.github/workflows/ci_tests.yml +++ b/.github/workflows/ci_tests.yml @@ -108,7 +108,10 @@ jobs: # Run test with both bash and powershell and watch for "Using std::cin" on bash but not on powershell - name: Test working-directory: build - run: ctest --output-on-failure -C ${{matrix.buildType}} --verbose + run: | + # The bash shell adds an incompatible PATH for MinGW: https://github.com/actions/runner-images/issues/11102 + [[ "${{runner.os}}" != 'Windows' ]] || export PATH="/c/mingw64/bin:$PATH" + ctest --output-on-failure -C ${{matrix.buildType}} --verbose - name: Test on PowerShell working-directory: build shell: powershell From b9ff85d99a4d39ef656a75436cd3c4c635664566 Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Thu, 19 Dec 2024 19:33:59 +0100 Subject: [PATCH 106/107] Workaround crash on exit for MinGW 32bit There is a bug in GCC for 32bit MinGW until version 11. This causes a use-after free for destruction of `thread_local` variables that crash the application when the destructor accesses any member. In the tests it shows up as exit code/status `-1073741819` i.e. `0xC0000005`. Workaround this by not destructing the `stackstring` instance used to hold the value of the last `getenv` result. In the case where any call to `getenv` of a thread yielded a large value heap memory will be allocated and not freed due to this missing destructor call causing a memory leak, possibly for each thread. However values up to some length are stored on stack memory and hence the missing destructor call does not cause a memory leak as the type is essentially trivial in this state. See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83562 Fixed by https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=7fc0f78c3f43af1967cb7b1ee8f4947f3b890aa2 --- src/cstdlib.cpp | 39 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/src/cstdlib.cpp b/src/cstdlib.cpp index 76f0319f..81533cdf 100644 --- a/src/cstdlib.cpp +++ b/src/cstdlib.cpp @@ -48,11 +48,46 @@ namespace nowide { #include #include +namespace { +// thread_local was broken on MinGW for all 32bit compiler releases prior to 11.x, see +// https://sourceforge.net/p/mingw-w64/bugs/527/ +// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83562 +// Using a non-trivial destructor causes program termination on thread exit. +#if defined(__MINGW32__) && !defined(__MINGW64__) && !defined(__clang__) && (__GNUC__ < 11) +class stackstring_for_thread +{ + union + { + boost::nowide::stackstring s_; + }; + +public: + stackstring_for_thread() : s_(){}; + // Empty destructor so the union member (using a non-trivial destructor) does not get destroyed. + // This will leak memory if any is allocated by the stackstring for each terminated thread + // but as most values fit into the stack buffer this is rare and still better than a crash. + ~stackstring_for_thread(){}; + void convert(const wchar_t* begin, const wchar_t* end) + { + s_.convert(begin, end); + } + + char* get() + { + return s_.get(); + } +}; +#else +using stackstring_for_thread = boost::nowide::stackstring; +#endif + +} // namespace + namespace boost { namespace nowide { char* getenv(const char* key) { - thread_local stackstring value; + thread_local stackstring_for_thread value; const wshort_stackstring name(key); @@ -72,7 +107,7 @@ namespace nowide { return 0; ptr = &tmp[0]; } - value.convert(ptr); + value.convert(ptr, ptr + n); return value.get(); } From 39ffd8f840729707447e9679b56d707a3e3b3b6a Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Sat, 28 Dec 2024 10:41:52 +0100 Subject: [PATCH 107/107] GHA: Uprev codecov action to v5 --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f8abb1da..303bcd24 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,6 +1,6 @@ # Copyright 2020-2021 Peter Dimov # Copyright 2021 Andrey Semashev -# Copyright 2021 Alexander Grund +# Copyright 2021-2024 Alexander Grund # Copyright 2022 James E. King III # # Distributed under the Boost Software License, Version 1.0. @@ -258,7 +258,7 @@ jobs: - name: Upload coverage if: matrix.coverage - uses: codecov/codecov-action@v4 + uses: codecov/codecov-action@v5 with: disable_search: true file: coverage.info