Skip to content

Commit 105ac5c

Browse files
committed
Merge branch 'develop'
2 parents 72429c3 + 64f1eee commit 105ac5c

15 files changed

+257
-132
lines changed

.appveyor.yml

+3-3
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ environment:
145145
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
146146
GENERATOR: Visual Studio 16 2019
147147
configuration: Debug
148-
BOOST_ROOT: C:\Libraries\boost_1_77_0
148+
BOOST_ROOT: C:\Libraries\boost_1_85_0
149149
COVERITY_SCAN_TOKEN:
150150
secure: FzhGUr+AR/VOBGUta7dDLMDruolChnvyMSvsM/zLvPY=
151151
COVERITY_SCAN_NOTIFICATION_EMAIL:
@@ -177,7 +177,7 @@ for:
177177
- mkdir __build_cmake_test__
178178
- cd __build_cmake_test__
179179
- cmake -G "%GENERATOR%" -DCMAKE_CXX_STANDARD=%CXXSTD% %CMAKE_FLAGS% -DCMAKE_INSTALL_PREFIX=%INSTALL_DIR% ..
180-
build_script: cmake --build . --config %configuration% --parallel 4
180+
build_script: cmake --build . --config %configuration% --parallel 4 --target tests
181181
test_script:
182182
- ctest --output-on-failure -C %configuration% --parallel 4
183183
- ps: |
@@ -204,7 +204,7 @@ for:
204204
- cmake -G "%GENERATOR%" ..
205205
- ps: |
206206
cov-configure --msvc
207-
cov-build --dir cov-int cmake --build . --config $env:configuration
207+
cov-build --dir cov-int cmake --build . --target tests --config $env:configuration
208208
If ($LastExitCode -ne 0) {
209209
cat cov-int/build-log.txt
210210
$host.SetShouldExit($LastExitCode)

.github/workflows/ci.yml

+114-75
Large diffs are not rendered by default.

.github/workflows/ci_tests.yml

+18-12
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright 2019 - 2022 Alexander Grund
1+
# Copyright 2019 - 2024 Alexander Grund
22
# Distributed under the Boost Software License, Version 1.0.
33
# https://www.boost.org/LICENSE_1_0.txt
44

@@ -48,10 +48,10 @@ jobs:
4848
DEP_DIR: ${{github.workspace}}/dependencies
4949
BOOST_VERSION: 1.56.0
5050
steps:
51-
- uses: actions/checkout@v3
51+
- uses: actions/checkout@v4
5252
- name: Sanity check version
5353
run: grep -E 'set\(_version [0-9]' CMakeLists.txt
54-
- uses: actions/cache@v1
54+
- uses: actions/cache@v4
5555
id: cache-boost
5656
with:
5757
path: ${{env.DEP_DIR}}
@@ -64,7 +64,7 @@ jobs:
6464
if: matrix.standalone == 'Boost'
6565
run: echo "BOOST_ROOT=${DEP_DIR//\\/\/}/boost_${BOOST_VERSION//./_}" >> $GITHUB_ENV
6666
# Install Boost
67-
- uses: actions/checkout@v3
67+
- uses: actions/checkout@v4
6868
if: matrix.standalone == 'Boost' && steps.cache-boost.outputs.cache-hit != 'true'
6969
with:
7070
repository: boostorg/boost
@@ -102,18 +102,24 @@ jobs:
102102
extraFlags="$extraFlags -DCMAKE_CXX_FLAGS=-Wundef"
103103
fi
104104
cmake -DCMAKE_BUILD_TYPE=${{matrix.buildType}} -DBUILD_SHARED_LIBS=${{matrix.shared_lib}} -G "${{matrix.generator}}" $extraFlags ..
105-
- name: Build & Install
106-
run: cmake --build build --config ${{matrix.buildType}} --target install
105+
- name: Build
106+
run: cmake --build build --config ${{matrix.buildType}} --target tests
107107

108108
# Run test with both bash and powershell and watch for "Using std::cin" on bash but not on powershell
109109
- name: Test
110110
working-directory: build
111-
run: ctest --output-on-failure -C ${{matrix.buildType}} --verbose
111+
run: |
112+
# The bash shell adds an incompatible PATH for MinGW: https://github.com/actions/runner-images/issues/11102
113+
[[ "${{runner.os}}" != 'Windows' ]] || export PATH="/c/mingw64/bin:$PATH"
114+
ctest --output-on-failure -C ${{matrix.buildType}} --verbose
112115
- name: Test on PowerShell
113116
working-directory: build
114117
shell: powershell
115118
if: runner.os == 'Windows'
116119
run: ctest --output-on-failure -C ${{matrix.buildType}} --verbose
120+
121+
- name: Install
122+
run: cmake --build build --config ${{matrix.buildType}} --target install
117123
- name: Test consumption
118124
working-directory: build
119125
run: |
@@ -125,7 +131,7 @@ jobs:
125131
CreateDocuTest:
126132
runs-on: ubuntu-latest
127133
steps:
128-
- uses: actions/checkout@v1
134+
- uses: actions/checkout@v4
129135
- name: Create documentation
130136
run: |
131137
sudo apt-get install -y doxygen
@@ -134,9 +140,9 @@ jobs:
134140
CreateBoostDocuTest:
135141
runs-on: ubuntu-latest
136142
steps:
137-
- uses: actions/checkout@v3
143+
- uses: actions/checkout@v4
138144
- name: Fetch Boost.CI
139-
uses: actions/checkout@v3
145+
uses: actions/checkout@v4
140146
with:
141147
repository: boostorg/boost-ci
142148
ref: master
@@ -153,8 +159,8 @@ jobs:
153159
CheckFormatting:
154160
runs-on: ubuntu-latest
155161
steps:
156-
- uses: actions/checkout@v3
157-
- uses: DoozyX/clang-format-lint-action@v0.11
162+
- uses: actions/checkout@v4
163+
- uses: DoozyX/clang-format-lint-action@v0.18
158164
with:
159165
exclude: './doc'
160166
clangFormatVersion: 10

.github/workflows/release.yml

+5-3
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ jobs:
1818
DEP_DIR: ${{github.workspace}}/dependencies
1919
BOOST_VERSION: 1.56.0
2020
steps:
21-
- uses: actions/checkout@v3
21+
- uses: actions/checkout@v4
2222
- name: Extract tag name
2323
id: get_tag
2424
run: |
@@ -56,8 +56,9 @@ jobs:
5656
src_dir="$PWD/nowide_standalone_${{steps.get_tag.outputs.tag}}"
5757
mkdir build && cd build
5858
cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX=${{runner.workspace}}/../install "$src_dir"
59-
cmake --build . --config Debug --target install
59+
cmake --build . --config Debug --target tests
6060
ctest --output-on-failure -C Debug --verbose
61+
cmake --build . --config Debug --target install
6162
6263
- name: Create Boost version
6364
run: |
@@ -75,8 +76,9 @@ jobs:
7576
src_dir="$PWD/nowide_${{steps.get_tag.outputs.tag}}"
7677
mkdir build && cd build
7778
cmake -DBoost_DEBUG=ON -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX=${{runner.workspace}}/../install "$src_dir"
78-
cmake --build . --config Debug --target install
79+
cmake --build . --config Debug --target tests
7980
ctest --output-on-failure -C Debug --verbose
81+
cmake --build . --config Debug --target install
8082
8183
- name: Create Release
8284
if: github.event_name == 'push'

README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22

33
Branch | Appveyor | Github | codecov.io | Deps | Docs | Tests |
44
------------|----------|--------|------------| ---- | ---- | ----- |
5-
[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)
6-
[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)
5+
[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) | [![Build status](https://github.com/boostorg/nowide/actions/workflows/ci.yml/badge.svg?branch=master)](https://github.com/boostorg/nowide/actions/workflows/ci.yml) | [![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) | [![Tests](https://img.shields.io/badge/tests-master-brightgreen.svg)](https://www.boost.org/development/tests/master/developer/nowide.html)
6+
[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) | [![Build status](https://github.com/boostorg/nowide/actions/workflows/ci.yml/badge.svg?branch=develop)](https://github.com/boostorg/nowide/actions/workflows/ci.yml) | [![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) | [![Tests](https://img.shields.io/badge/tests-develop-brightgreen.svg)](https://www.boost.org/development/tests/develop/developer/nowide.html)
77

88
Quality checks:
99
[![Coverity Scan Build Status](https://scan.coverity.com/projects/20464/badge.svg)](https://scan.coverity.com/projects/boostorg-nowide)

doc/changelog.dox

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
//
2-
// Copyright (c) 2019-2023 Alexander Grund
2+
// Copyright (c) 2019-2024 Alexander Grund
33
//
44
// Distributed under the Boost Software License, Version 1.0.
55
// https://www.boost.org/LICENSE_1_0.txt
@@ -8,6 +8,10 @@
88

99
\section changelog Changelog
1010

11+
\subsection changelog_11_3_1 Nowide 11.3.1 (Boost 1.88)
12+
- Fix redefinition of `_CRT_SECURE_NO_WARNINGS`
13+
- Make `getenv` thread-safe
14+
1115
\subsection changelog_11_3_0 Nowide 11.3.0 (Boost 1.82)
1216
- Add `convert_string` overload accepting a string
1317
- Add `quoted` to output (quoted) paths (std::filesystem or boost::filesystem)

doc/main.dox

+4-4
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ Since April 2018 there is a (Beta) function available in Windows 10 to use UTF-8
138138

139139
Both methods do work but have a major drawback: They are not fully reliable for the app developer.
140140
The code page via manifest method falls back to a legacy code page when an older Windows version than 1903 is used.
141-
Hence it is only usable if the targetted system is Windows 10 after May 2019.
141+
Hence it is only usable if the targeted system is Windows 10 after May 2019.
142142
The second method relies on user interaction prior to starting the program.
143143
Obviously this is not reliable when expecting only UTF-8 in the code.
144144

@@ -243,7 +243,7 @@ and temporarily replaces the original \c argv (and optionally \c env) with point
243243
UTF-8 strings for the lifetime of the instance.
244244
- \c boost::nowide::ifstream converts the passed filename (which is now valid UTF-8) to UTF-16
245245
and calls the Windows Wide API to open the file stream which can then be used as usual.
246-
- Similarily \c boost::nowide::cerr and \c boost::nowide::cout use an underlying stream buffer
246+
- Similarly \c boost::nowide::cerr and \c boost::nowide::cout use an underlying stream buffer
247247
that converts the UTF-8 string to UTF-16 and use another Wide API function to write it to console.
248248

249249
\subsection using_custom Custom API
@@ -289,7 +289,7 @@ before including any of the Boost.Nowide headers
289289
\subsection using_integration Integration with Boost.Filesystem
290290

291291
Boost.Filesystem supports selection of narrow encoding.
292-
Unfortunatelly the default narrow encoding on Windows isn't UTF-8.
292+
Unfortunately the default narrow encoding on Windows isn't UTF-8.
293293
But you can enable UTF-8 as default encoding on Boost.Filesystem by calling
294294
`boost::nowide::nowide_filesystem()` in the beginning of your program which
295295
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.
300300

301301
For `std::filesystem::path` available since C++17 there is no way to imbue a locale.
302302
However the `u8string()` member function can be used to obtain an UTF-8 encoded string from a `path`.
303-
And to optain a `path` from an UTF-8 encoded string you may use `std::filesystem::u8path`
303+
And to obtain a `path` from an UTF-8 encoded string you may use `std::filesystem::u8path`
304304
or since C++20 one of the `path` constructors taking a `char8_t`-type input.
305305

306306
To read/write `std::filesystem::path` instances from/to streams you'd usually use e.g. `os << path`.

include/boost/nowide/cstdlib.hpp

+6-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,12 @@ namespace nowide {
2121
///
2222
/// \brief UTF-8 aware getenv. Returns 0 if the variable is not set.
2323
///
24-
/// This function is not thread safe or reenterable as defined by the standard library
24+
/// The string pointed to shall not be modified by the program.
25+
/// This function is thread-safe as long as no other thread modifies the host environment.
26+
/// However subsequent calls to this function might overwrite the string pointed to.
27+
///
28+
/// Warning: The returned pointer might only be valid for as long as the calling thread is alive.
29+
/// So avoid passing it across thread boundaries.
2530
///
2631
BOOST_NOWIDE_DECL char* getenv(const char* key);
2732

include/boost/nowide/detail/is_path.hpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ namespace nowide {
2727

2828
static constexpr bool value = decltype(test<T>(0))::value;
2929
};
30-
/// SFINAE trait which has a member "type = Result" if the Path is a *\::filesystem::path
30+
/// SFINAE trait/alias which resolves to Result if the Path is a *\::filesystem::path
3131
template<typename Path, typename Result>
3232
using enable_if_path_t = typename std::enable_if<is_path<Path>::value, Result>::type;
3333

include/boost/nowide/iostream.hpp

+7-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,13 @@ namespace nowide {
4040
class BOOST_NOWIDE_DECL winconsole_ostream : public std::ostream
4141
{
4242
public:
43-
winconsole_ostream(bool isBuffered, winconsole_ostream* tieStream);
43+
enum class target_stream
44+
{
45+
output,
46+
error,
47+
log,
48+
};
49+
winconsole_ostream(target_stream target, bool isBuffered, winconsole_ostream* tieStream);
4450
~winconsole_ostream();
4551

4652
private:

include/boost/nowide/quoted.hpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ namespace nowide {
3838
/// has the effect as-if `in >> std::quoted(path.native())` was used if that would be valid.
3939
/// To that effect a temporary string is used, which on success is assigned to `path`.
4040
///
41-
/// Will automatically convert between the streams `char_type` and `path::value_type` if neccessary.
41+
/// Will automatically convert between the streams `char_type` and `path::value_type` if necessary.
4242
template<class Path>
4343
#ifdef BOOST_NOWIDE_DOXYGEN
4444
unspecified_type

src/cstdlib.cpp

+37-2
Original file line numberDiff line numberDiff line change
@@ -48,11 +48,46 @@ namespace nowide {
4848
#include <vector>
4949
#include <windows.h>
5050

51+
namespace {
52+
// thread_local was broken on MinGW for all 32bit compiler releases prior to 11.x, see
53+
// https://sourceforge.net/p/mingw-w64/bugs/527/
54+
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83562
55+
// Using a non-trivial destructor causes program termination on thread exit.
56+
#if defined(__MINGW32__) && !defined(__MINGW64__) && !defined(__clang__) && (__GNUC__ < 11)
57+
class stackstring_for_thread
58+
{
59+
union
60+
{
61+
boost::nowide::stackstring s_;
62+
};
63+
64+
public:
65+
stackstring_for_thread() : s_(){};
66+
// Empty destructor so the union member (using a non-trivial destructor) does not get destroyed.
67+
// This will leak memory if any is allocated by the stackstring for each terminated thread
68+
// but as most values fit into the stack buffer this is rare and still better than a crash.
69+
~stackstring_for_thread(){};
70+
void convert(const wchar_t* begin, const wchar_t* end)
71+
{
72+
s_.convert(begin, end);
73+
}
74+
75+
char* get()
76+
{
77+
return s_.get();
78+
}
79+
};
80+
#else
81+
using stackstring_for_thread = boost::nowide::stackstring;
82+
#endif
83+
84+
} // namespace
85+
5186
namespace boost {
5287
namespace nowide {
5388
char* getenv(const char* key)
5489
{
55-
static stackstring value;
90+
thread_local stackstring_for_thread value;
5691

5792
const wshort_stackstring name(key);
5893

@@ -72,7 +107,7 @@ namespace nowide {
72107
return 0;
73108
ptr = &tmp[0];
74109
}
75-
value.convert(ptr);
110+
value.convert(ptr, ptr + n);
76111
return value.get();
77112
}
78113

src/iostream.cpp

+22-16
Original file line numberDiff line numberDiff line change
@@ -82,27 +82,32 @@ namespace nowide {
8282
}
8383
};
8484

85-
winconsole_ostream::winconsole_ostream(const bool isBuffered, winconsole_ostream* tieStream) : std::ostream(0)
85+
winconsole_ostream::winconsole_ostream(const target_stream target,
86+
const bool isBuffered,
87+
winconsole_ostream* tieStream) :
88+
std::ostream(nullptr)
8689
{
87-
HANDLE h;
88-
if(isBuffered)
89-
h = GetStdHandle(STD_OUTPUT_HANDLE);
90-
else
91-
h = GetStdHandle(STD_ERROR_HANDLE);
90+
const HANDLE h = GetStdHandle(target == target_stream::output ? STD_OUTPUT_HANDLE : STD_ERROR_HANDLE);
91+
9292
if(is_atty_handle(h))
9393
{
9494
d.reset(new console_output_buffer(h));
95-
std::ostream::rdbuf(d.get());
95+
rdbuf(d.get());
9696
} else
9797
{
98-
std::ostream::rdbuf(isBuffered ? std::cout.rdbuf() : std::cerr.rdbuf());
99-
assert(rdbuf());
98+
switch(target)
99+
{
100+
case target_stream::error: rdbuf(std::cerr.rdbuf()); break;
101+
case target_stream::log: rdbuf(std::clog.rdbuf()); break;
102+
case target_stream::output: rdbuf(std::cout.rdbuf()); break;
103+
}
100104
}
105+
assert(rdbuf());
106+
101107
if(tieStream)
102-
{
103108
tie(tieStream);
104-
setf(ios_base::unitbuf); // If tieStream is set, this is cerr -> set unbuffered
105-
}
109+
if(!isBuffered)
110+
setf(ios_base::unitbuf);
106111
}
107112
winconsole_ostream::~winconsole_ostream()
108113
{
@@ -134,7 +139,7 @@ namespace nowide {
134139

135140
} // namespace detail
136141

137-
// Make sure those are initialized as early as possible
142+
// Make sure those are initialized as early as possible
138143
#ifdef BOOST_MSVC
139144
#pragma warning(disable : 4073)
140145
#pragma init_seg(lib)
@@ -144,10 +149,11 @@ namespace nowide {
144149
#else
145150
#define BOOST_NOWIDE_INIT_PRIORITY
146151
#endif
147-
detail::winconsole_ostream cout BOOST_NOWIDE_INIT_PRIORITY(true, nullptr);
152+
using target_stream = detail::winconsole_ostream::target_stream;
153+
detail::winconsole_ostream cout BOOST_NOWIDE_INIT_PRIORITY(target_stream::output, true, nullptr);
148154
detail::winconsole_istream cin BOOST_NOWIDE_INIT_PRIORITY(&cout);
149-
detail::winconsole_ostream cerr BOOST_NOWIDE_INIT_PRIORITY(false, &cout);
150-
detail::winconsole_ostream clog BOOST_NOWIDE_INIT_PRIORITY(false, nullptr);
155+
detail::winconsole_ostream cerr BOOST_NOWIDE_INIT_PRIORITY(target_stream::error, false, &cout);
156+
detail::winconsole_ostream clog BOOST_NOWIDE_INIT_PRIORITY(target_stream::log, true, nullptr);
151157
} // namespace nowide
152158
} // namespace boost
153159

0 commit comments

Comments
 (0)