diff options
author | Yun Peng <pcloudy@google.com> | 2018-06-20 07:56:11 -0700 |
---|---|---|
committer | Copybara-Service <copybara-piper@google.com> | 2018-06-20 07:57:33 -0700 |
commit | 4e578e6f7205a352630720ed482967b6edb4afca (patch) | |
tree | 72183211005d58534693656832922c63a5f55f15 /src/main | |
parent | 3e1e177502133f906d1614e32f2c4af02167e990 (diff) |
Make blaze_util::AsAbsoluteWindowsPath support wstring as input
Now we have:
bool AsAbsoluteWindowsPath(const std::wstring& path, std::wstring* result, std::string* error);
This change helps making the C++ native launcher work with UTF-16.
See https://github.com/bazelbuild/bazel/issues/4473
Closes #5406.
Change-Id: I7eaf55f9fe5a4d41e3dd09edc2a21e9b3cc9277c
PiperOrigin-RevId: 201352866
Diffstat (limited to 'src/main')
-rw-r--r-- | src/main/cpp/util/BUILD | 5 | ||||
-rw-r--r-- | src/main/cpp/util/logging.cc | 7 | ||||
-rw-r--r-- | src/main/cpp/util/logging.h | 1 | ||||
-rw-r--r-- | src/main/cpp/util/path_platform.h | 40 | ||||
-rw-r--r-- | src/main/cpp/util/path_windows.cc | 51 |
5 files changed, 81 insertions, 23 deletions
diff --git a/src/main/cpp/util/BUILD b/src/main/cpp/util/BUILD index 6f53b4d590..eed2a60a12 100644 --- a/src/main/cpp/util/BUILD +++ b/src/main/cpp/util/BUILD @@ -107,7 +107,10 @@ cc_library( srcs = ["logging.cc"], hdrs = ["logging.h"], visibility = ["//visibility:public"], - deps = [":blaze_exit_code"], + deps = [ + ":blaze_exit_code", + ":strings", + ], ) cc_library( diff --git a/src/main/cpp/util/logging.cc b/src/main/cpp/util/logging.cc index 40a54aed17..c2e7565bd8 100644 --- a/src/main/cpp/util/logging.cc +++ b/src/main/cpp/util/logging.cc @@ -21,6 +21,7 @@ #include <memory> #include "src/main/cpp/util/exit_code.h" +#include "src/main/cpp/util/strings.h" namespace blaze_util { @@ -68,6 +69,12 @@ DECLARE_STREAM_OPERATOR(float) DECLARE_STREAM_OPERATOR(double) DECLARE_STREAM_OPERATOR(long double) DECLARE_STREAM_OPERATOR(void*) + +LogMessage& LogMessage::operator<<(const std::wstring& wstr) { + message_ << WstringToString(wstr); + return *this; +} + #undef DECLARE_STREAM_OPERATOR void LogMessage::Finish() { diff --git a/src/main/cpp/util/logging.h b/src/main/cpp/util/logging.h index b2cd459d06..7346c18176 100644 --- a/src/main/cpp/util/logging.h +++ b/src/main/cpp/util/logging.h @@ -53,6 +53,7 @@ class LogMessage { int exit_code); LogMessage& operator<<(const std::string& value); + LogMessage& operator<<(const std::wstring& wstr); LogMessage& operator<<(const char* value); LogMessage& operator<<(char value); LogMessage& operator<<(bool value); diff --git a/src/main/cpp/util/path_platform.h b/src/main/cpp/util/path_platform.h index 3c4671f004..e2efe097fe 100644 --- a/src/main/cpp/util/path_platform.h +++ b/src/main/cpp/util/path_platform.h @@ -77,9 +77,6 @@ std::pair<std::wstring, std::wstring> SplitPathW(const std::wstring &path); bool IsRootDirectoryW(const std::wstring &path); -bool AsWindowsPath(const std::string &path, std::string *result, - std::string *error); - // Returns a normalized form of the input `path`. // // `path` must be a relative or absolute Windows path, it may use "/" instead of @@ -95,7 +92,14 @@ bool AsWindowsPath(const std::string &path, std::string *result, // "foo". // // Visible for testing, would be static otherwise. -std::string NormalizeWindowsPath(std::string path); +template <typename char_type> +std::basic_string<char_type> NormalizeWindowsPath( + std::basic_string<char_type> path); + +template <typename char_type> +std::basic_string<char_type> NormalizeWindowsPath(const char_type *path) { + return NormalizeWindowsPath(std::basic_string<char_type>(path)); +} // Converts a UTF8-encoded `path` to a normalized, widechar Windows path. // @@ -116,8 +120,32 @@ std::string NormalizeWindowsPath(std::string path); bool AsWindowsPath(const std::string &path, std::wstring *result, std::string *error); -bool AsAbsoluteWindowsPath(const std::string &path, std::wstring *wpath, - std::string *error); +template <typename char_type> +bool AsWindowsPath(const std::basic_string<char_type> &path, + std::basic_string<char_type> *result, std::string *error); + +template <typename char_type> +bool AsWindowsPath(const char_type *path, std::basic_string<char_type> *result, + std::string *error) { + return AsWindowsPath(std::basic_string<char_type>(path), result, error); +} + +template <typename char_type> +bool AsAbsoluteWindowsPath(const std::basic_string<char_type> &path, + std::wstring *result, std::string *error); + +template <typename char_type> +bool AsAbsoluteWindowsPath(const char_type *path, std::wstring *result, + std::string *error) { + return AsAbsoluteWindowsPath(std::basic_string<char_type>(path), result, + error); +} + +// Explicit instantiate AsAbsoluteWindowsPath for char and wchar_t. +template bool AsAbsoluteWindowsPath<char>(const char *, std::wstring *, + std::string *); +template bool AsAbsoluteWindowsPath<wchar_t>(const wchar_t *, std::wstring *, + std::string *); // Same as `AsWindowsPath`, but returns a lowercase 8dot3 style shortened path. // Result will never have a UNC prefix, nor a trailing "/" or "\". diff --git a/src/main/cpp/util/path_windows.cc b/src/main/cpp/util/path_windows.cc index 15dd0ddce6..d115b6e6d9 100644 --- a/src/main/cpp/util/path_windows.cc +++ b/src/main/cpp/util/path_windows.cc @@ -215,14 +215,19 @@ std::pair<std::wstring, std::wstring> SplitPathW(const std::wstring& path) { return SplitPathImpl(path); } -bool AsWindowsPath(const std::string& path, std::string* result, - std::string* error) { +void assignNUL(std::string* s) { s->assign("NUL"); } + +void assignNUL(std::wstring* s) { s->assign(L"NUL"); } + +template <typename char_type> +bool AsWindowsPath(const std::basic_string<char_type>& path, + std::basic_string<char_type>* result, std::string* error) { if (path.empty()) { result->clear(); return true; } if (IsDevNull(path.c_str())) { - result->assign("NUL"); + assignNUL(result); return true; } if (HasUncPrefix(path.c_str())) { @@ -247,7 +252,7 @@ bool AsWindowsPath(const std::string& path, std::string* result, return false; } - std::string mutable_path = path; + std::basic_string<char_type> mutable_path = path; if (path[0] == '/') { if (error) { *error = "Unix-style paths are unsupported"; @@ -257,9 +262,10 @@ bool AsWindowsPath(const std::string& path, std::string* result, if (path[0] == '\\') { // This is an absolute Windows path on the current drive, e.g. "\foo\bar". - mutable_path = std::string(1, GetCurrentDrive()) + ":" + path; + std::basic_string<char_type> drive(1, GetCurrentDrive()); + drive.push_back(':'); + mutable_path = drive + path; } // otherwise this is a relative path, or absolute Windows path. - result->assign(NormalizeWindowsPath(mutable_path)); return true; } @@ -275,8 +281,9 @@ bool AsWindowsPath(const std::string& path, std::wstring* result, return true; } -bool AsAbsoluteWindowsPath(const std::string& path, std::wstring* result, - std::string* error) { +template <typename char_type> +bool AsAbsoluteWindowsPath(const std::basic_string<char_type>& path, + std::wstring* result, std::string* error) { if (path.empty()) { result->clear(); return true; @@ -373,6 +380,14 @@ bool IsDevNull(const char* path) { (path[2] == 'L' || path[2] == 'l') && path[3] == 0)); } +bool IsDevNull(const wchar_t* path) { + return path != NULL && *path != 0 && + (wcsncmp(L"/dev/null\0", path, 10) == 0 || + ((path[0] == L'N' || path[0] == L'n') && + (path[1] == L'U' || path[1] == L'u') && + (path[2] == L'L' || path[2] == L'l') && path[3] == 0)); +} + bool IsRootDirectory(const std::string& path) { return IsRootOrAbsolute(path, true); } @@ -392,9 +407,11 @@ static char GetCurrentDrive() { return 'a' + wdrive - offset; } -std::string NormalizeWindowsPath(std::string path) { +template <typename char_type> +std::basic_string<char_type> NormalizeWindowsPath( + std::basic_string<char_type> path) { if (path.empty()) { - return ""; + return std::basic_string<char_type>(); } if (path[0] == '/') { // This is an absolute MSYS path, error out. @@ -405,10 +422,10 @@ std::string NormalizeWindowsPath(std::string path) { path = path.substr(4); } - static const std::string dot("."); - static const std::string dotdot(".."); + static const std::basic_string<char_type> dot(1, '.'); + static const std::basic_string<char_type> dotdot(2, '.'); - std::vector<std::string> segments; + std::vector<std::basic_string<char_type>> segments; int segment_start = -1; // Find the path segments in `path` (separated by "/"). for (int i = 0;; ++i) { @@ -421,7 +438,8 @@ std::string NormalizeWindowsPath(std::string path) { } else if (segment_start >= 0 && i > segment_start) { // The current character is "/" or "\0", so this ends a segment. // Add that to `segments` if there's anything to add; handle "." and "..". - std::string segment(path, segment_start, i - segment_start); + std::basic_string<char_type> segment(path, segment_start, + i - segment_start); segment_start = -1; if (segment == dotdot) { if (!segments.empty() && @@ -441,12 +459,13 @@ std::string NormalizeWindowsPath(std::string path) { // form of it, e.g. "c:\.."). if (segments.size() == 1 && segments[0].size() == 2 && HasDriveSpecifierPrefix(segments[0].c_str())) { - return segments[0] + '\\'; + segments[0].push_back('\\'); + return segments[0]; } // Join all segments. bool first = true; - std::ostringstream result; + std::basic_ostringstream<char_type> result; for (const auto& s : segments) { if (!first) { result << '\\'; |