Skip to content

Commit 551a5f9

Browse files
authored
Merge pull request #1725 from evoskuil/master
Fix handling of std::filesystem::path re:utf8-everywhere (win32).
2 parents bb91915 + 439df58 commit 551a5f9

15 files changed

Lines changed: 225 additions & 78 deletions

File tree

Makefile.am

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -388,6 +388,7 @@ test_libbitcoin_system_test_SOURCES = \
388388
test/unicode/utf8_everywhere/environment.cpp \
389389
test/unicode/utf8_everywhere/ifstream.cpp \
390390
test/unicode/utf8_everywhere/ofstream.cpp \
391+
test/unicode/utf8_everywhere/paths.cpp \
391392
test/unicode/utf8_everywhere/unicode_istream.cpp \
392393
test/unicode/utf8_everywhere/unicode_ostream.cpp \
393394
test/utreexo/utreexo.cpp \

builds/cmake/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -867,6 +867,7 @@ if (with-tests)
867867
"../../test/unicode/utf8_everywhere/environment.cpp"
868868
"../../test/unicode/utf8_everywhere/ifstream.cpp"
869869
"../../test/unicode/utf8_everywhere/ofstream.cpp"
870+
"../../test/unicode/utf8_everywhere/paths.cpp"
870871
"../../test/unicode/utf8_everywhere/unicode_istream.cpp"
871872
"../../test/unicode/utf8_everywhere/unicode_ostream.cpp"
872873
"../../test/utreexo/utreexo.cpp"

builds/msvc/vs2022/libbitcoin-system-test/libbitcoin-system-test.vcxproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,7 @@
317317
<ClCompile Include="..\..\..\..\test\unicode\utf8_everywhere\environment.cpp" />
318318
<ClCompile Include="..\..\..\..\test\unicode\utf8_everywhere\ifstream.cpp" />
319319
<ClCompile Include="..\..\..\..\test\unicode\utf8_everywhere\ofstream.cpp" />
320+
<ClCompile Include="..\..\..\..\test\unicode\utf8_everywhere\paths.cpp" />
320321
<ClCompile Include="..\..\..\..\test\unicode\utf8_everywhere\unicode_istream.cpp" />
321322
<ClCompile Include="..\..\..\..\test\unicode\utf8_everywhere\unicode_ostream.cpp" />
322323
<ClCompile Include="..\..\..\..\test\utreexo\utreexo.cpp" />

builds/msvc/vs2022/libbitcoin-system-test/libbitcoin-system-test.vcxproj.filters

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -615,6 +615,9 @@
615615
<ClCompile Include="..\..\..\..\test\unicode\utf8_everywhere\ofstream.cpp">
616616
<Filter>src\unicode\utf8_everywhere</Filter>
617617
</ClCompile>
618+
<ClCompile Include="..\..\..\..\test\unicode\utf8_everywhere\paths.cpp">
619+
<Filter>src\unicode\utf8_everywhere</Filter>
620+
</ClCompile>
618621
<ClCompile Include="..\..\..\..\test\unicode\utf8_everywhere\unicode_istream.cpp">
619622
<Filter>src\unicode\utf8_everywhere</Filter>
620623
</ClCompile>

include/bitcoin/system/config/parser.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ class BC_API parser
3939
const std::string& message) NOEXCEPT;
4040
static bool get_option(variables_map& variables,
4141
const std::string& name) NOEXCEPT;
42+
43+
/// Path is read as u8string (c++20) and held internally as wide on win32.
4244
static std::filesystem::path get_config_option(variables_map& variables,
4345
const std::string& name) NOEXCEPT;
4446

include/bitcoin/system/data/string.hpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@ BC_API std::string join(const string_list& tokens,
4141

4242
/// Split text into tokens by the specified delimiter(s).
4343
/// Compression removes all but a last empty token (after trimming).
44-
/// Compression removes all but a last empty token (after trimming).
4544
BC_API string_list split(const std::string& text, bool compress=true) NOEXCEPT;
4645
BC_API string_list split(const std::string& text,
4746
const std::string& delimiter, bool trim=true, bool compress=true) NOEXCEPT;

include/bitcoin/system/unicode/utf8_everywhere/paths.hpp

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -25,29 +25,25 @@
2525
namespace libbitcoin {
2626
namespace system {
2727

28+
/// std::filesystem::path maintains path internally as unicode, constructing
29+
/// from the current ANSI code page on Win32. This must be avoided when using
30+
/// utf8-everywhere. These utilities simplify proper contruction and extraction.
31+
BC_API std::string cast_to_string(const std::u8string& value) NOEXCEPT;
32+
BC_API std::u8string cast_to_u8string(const std::string& value) NOEXCEPT;
33+
BC_API std::string from_path(const std::filesystem::path& value) NOEXCEPT;
34+
BC_API std::filesystem::path to_path(const std::string& value) NOEXCEPT;
35+
2836
/// Get the default configuration file path with subdirectory.
2937
BC_API std::filesystem::path default_config_path(
3038
const std::filesystem::path& subdirectory) NOEXCEPT;
3139

32-
/// These allow std::*fstream(to_extended_path(std::filesystem::path)),
33-
/// due to a vc++ fstream extension that accepts std::wstring path.
34-
35-
#ifdef HAVE_MSC
36-
37-
/// Convert to std::wstring path, extended for win32.
40+
/// Extend the path and return it as another.
41+
/// std::filesystem::path does not extend long paths, so we provide this.
3842
/// Not thread safe. If another thread calls SetCurrentDirectory during this
3943
/// call, the result may be corrupted as static storage is used for directory.
40-
BC_API std::wstring to_extended_path(
41-
const std::filesystem::path& path) NOEXCEPT;
42-
43-
#else
44-
45-
/// Return std::string path, for consistency with std::wstring version.
46-
BC_API std::string to_extended_path(
44+
BC_API std::filesystem::path extended_path(
4745
const std::filesystem::path& path) NOEXCEPT;
4846

49-
#endif
50-
5147
} // namespace system
5248
} // namespace libbitcoin
5349

src/config/parser.cpp

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@
2121
#include <filesystem>
2222
#include <sstream>
2323
#include <bitcoin/system/data/data.hpp>
24-
#include <bitcoin/system/unicode/utf8_everywhere/ifstream.hpp>
24+
#include <bitcoin/system/unicode/unicode.hpp>
25+
#include <bitcoin/system/unicode/utf8_everywhere/utf8_everywhere.hpp>
2526

2627
namespace libbitcoin {
2728
namespace system {
@@ -51,7 +52,8 @@ std::filesystem::path parser::get_config_option(variables_map& variables,
5152
if (config.empty())
5253
return {};
5354

54-
return config.as<std::filesystem::path>();
55+
// Capture as utf8 so std::filesystem::path does assume ansi code page.
56+
return { config.as<std::u8string>() };
5557
}
5658

5759
bool parser::get_option(variables_map& variables,
@@ -88,27 +90,26 @@ void parser::load_environment_variables(variables_map& variables,
8890
bool parser::load_configuration_variables(variables_map& variables,
8991
const std::string& option_name) THROWS
9092
{
91-
const auto config_settings = load_settings();
92-
const auto config_path = get_config_option(variables, option_name);
93+
const auto settings = load_settings();
94+
const auto path = get_config_option(variables, option_name);
95+
const auto extended = extended_path(path);
9396

9497
// If the existence test errors out we pretend there's no file :/.
95-
std::error_code code;
96-
if (!config_path.empty() && exists(config_path, code))
98+
std::error_code code{};
99+
if (!path.empty() && std::filesystem::exists(extended, code))
97100
{
98-
const auto& path = config_path.string();
99-
ifstream file(path);
100-
101+
ifstream file{ path };
101102
if (!file.good())
102-
throw ifstream_exception(path.c_str());
103+
throw ifstream_exception{ from_path(extended).c_str() };
103104

104-
const auto config = parse_config_file(file, config_settings);
105+
const auto config = parse_config_file(file, settings);
105106
store(config, variables);
106107
return true;
107108
}
108109

109110
// Loading from an empty stream causes the defaults to populate.
110-
std::istringstream stream;
111-
const auto config = parse_config_file(stream, config_settings);
111+
std::istringstream stream{};
112+
const auto config = parse_config_file(stream, settings);
112113
store(config, variables);
113114
return false;
114115
}

src/unicode/utf8_everywhere/ifstream.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,9 @@
2525
namespace libbitcoin {
2626
namespace system {
2727

28-
// VC++ EXTENSION: "construct with wide-named file".
2928
ifstream::ifstream(const std::filesystem::path& path,
3029
std::ifstream::openmode mode) THROWS
31-
: std::ifstream(to_extended_path(path), mode)
30+
: std::ifstream(extended_path(path), mode)
3231
{
3332
// This opens the stream, and creates file system file if out/app mode.
3433
}

src/unicode/utf8_everywhere/ofstream.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,10 @@
2424

2525
namespace libbitcoin {
2626
namespace system {
27-
28-
// VC++ EXTENSION: "construct with wide-named file".
27+
2928
ofstream::ofstream(const std::filesystem::path& path,
3029
std::ofstream::openmode mode) THROWS
31-
: std::ofstream(to_extended_path(path), mode)
30+
: std::ofstream(extended_path(path), mode)
3231
{
3332
// This opens the stream, and creates file system file if out/app mode.
3433
}

0 commit comments

Comments
 (0)