Chromium Code Reviews| Index: chrome/install_static/install_util.cc |
| diff --git a/chrome/install_static/install_util.cc b/chrome/install_static/install_util.cc |
| index 2a8f83aed0707aadd9d629a91d4dcc206de98117..57aa7a0b25c2a662d9a78ea40158bc9e02f1ad14 100644 |
| --- a/chrome/install_static/install_util.cc |
| +++ b/chrome/install_static/install_util.cc |
| @@ -7,7 +7,10 @@ |
| #include <windows.h> |
| #include <assert.h> |
| #include <algorithm> |
| +#include <iostream> |
| +#include <iterator> |
| #include <memory> |
| +#include <sstream> |
| #include "base/macros.h" |
| #include "build/build_config.h" |
| @@ -255,41 +258,6 @@ base::string16 GetCurrentProcessExePath() { |
| return exe_path; |
| } |
| -// UTF8 to UTF16 and vice versa conversion helpers. We cannot use the base |
| -// string conversion utilities here as they bring about a dependency on |
| -// user32.dll which is not allowed in this file. |
| - |
| -// Convert a UTF16 string to an UTF8 string. |
| -std::string utf16_to_utf8(const base::string16 &source) { |
| - if (source.empty()) |
| - return std::string(); |
| - int size = ::WideCharToMultiByte(CP_UTF8, 0, &source[0], |
| - static_cast<int>(source.size()), nullptr, 0, nullptr, nullptr); |
| - std::string result(size, '\0'); |
| - if (::WideCharToMultiByte(CP_UTF8, 0, &source[0], |
| - static_cast<int>(source.size()), &result[0], size, nullptr, |
| - nullptr) != size) { |
| - assert(false); |
| - return std::string(); |
| - } |
| - return result; |
| -} |
| - |
| -// Convert a UTF8 string to a UTF16 string. |
| -base::string16 utf8_to_string16(const std::string &source) { |
| - if (source.empty()) |
| - return base::string16(); |
| - int size = ::MultiByteToWideChar(CP_UTF8, 0, &source[0], |
| - static_cast<int>(source.size()), nullptr, 0); |
| - base::string16 result(size, L'\0'); |
| - if (::MultiByteToWideChar(CP_UTF8, 0, &source[0], |
| - static_cast<int>(source.size()), &result[0], size) != size) { |
| - assert(false); |
| - return base::string16(); |
| - } |
| - return result; |
| -} |
| - |
| bool RecursiveDirectoryCreate(const base::string16& full_path) { |
| // If the path exists, we've succeeded if it's a directory, failed otherwise. |
| const wchar_t* full_path_str = full_path.c_str(); |
| @@ -419,6 +387,29 @@ bool MatchPatternImpl(const base::string16& source, |
| return false; |
| } |
| +// Defines the type of whitespace characters typically found in strings. |
| +const char kWhiteSpaces[] = " \t\n\r\f\v"; |
|
grt (UTC plus 2)
2016/05/27 14:13:20
nit: constexpr
ananta
2016/05/27 20:05:25
Done.
|
| + |
| +// Trim whitespaces from left. |
| +void ltrim(std::string* str) { |
| + str->erase(0, str->find_first_not_of(kWhiteSpaces)); |
| +} |
| + |
| +// Trim whitespaces from right |
| +void rtrim(std::string* str) { |
| + str->erase(str->find_last_not_of(kWhiteSpaces) + 1); |
| +} |
| + |
| +// Trim whitespaces from left & right |
| +void trim(std::string* str) { |
|
scottmg
2016/05/27 17:27:22
trim -> Trim
ananta
2016/05/27 20:05:25
Done.
|
| + rtrim(str); |
|
scottmg
2016/05/27 17:27:22
Seems like over-functioning since ltrim() and rtri
ananta
2016/05/27 20:05:25
Done.
|
| + ltrim(str); |
| +} |
| + |
| +bool is_valid_number(const std::string &str) { |
|
scottmg
2016/05/27 17:27:22
IsValidNumber
ananta
2016/05/27 20:05:25
Done.
|
| + return std::all_of(str.begin(), str.end(), ::isdigit); |
|
grt (UTC plus 2)
2016/05/27 14:13:20
as implemented, this will return true if std.empty
ananta
2016/05/27 20:05:25
Done.
|
| +} |
| + |
| } // namespace |
| bool IsSxSChrome(const wchar_t* exe_path) { |
| @@ -576,23 +567,23 @@ bool GetDefaultCrashDumpLocation(base::string16* crash_dir) { |
| std::string GetEnvironmentString(const std::string& variable_name) { |
| DWORD value_length = ::GetEnvironmentVariable( |
| - utf8_to_string16(variable_name).c_str(), NULL, 0); |
| + utf8_to_utf16(variable_name).c_str(), NULL, 0); |
| if (value_length == 0) |
| return std::string(); |
| std::unique_ptr<wchar_t[]> value(new wchar_t[value_length]); |
| - ::GetEnvironmentVariable(utf8_to_string16(variable_name).c_str(), |
| + ::GetEnvironmentVariable(utf8_to_utf16(variable_name).c_str(), |
| value.get(), value_length); |
| return utf16_to_utf8(value.get()); |
| } |
| bool SetEnvironmentString(const std::string& variable_name, |
| const std::string& new_value) { |
| - return !!SetEnvironmentVariable(utf8_to_string16(variable_name).c_str(), |
| - utf8_to_string16(new_value).c_str()); |
| + return !!SetEnvironmentVariable(utf8_to_utf16(variable_name).c_str(), |
| + utf8_to_utf16(new_value).c_str()); |
| } |
| bool HasEnvironmentVariable(const std::string& variable_name) { |
| - return !!::GetEnvironmentVariable(utf8_to_string16(variable_name).c_str(), |
| + return !!::GetEnvironmentVariable(utf8_to_utf16(variable_name).c_str(), |
| NULL, 0); |
| } |
| @@ -743,4 +734,123 @@ bool MatchPattern(const base::string16& source, |
| return MatchPatternImpl(source, pattern, 0, 0); |
| } |
| +std::string utf16_to_utf8(const base::string16 &source) { |
|
grt (UTC plus 2)
2016/05/27 14:13:20
nit: & before space. please use "git cl format" t
ananta
2016/05/27 20:05:25
Yeah. I had done that. It seems every time I copy
|
| + if (source.empty()) |
|
grt (UTC plus 2)
2016/05/27 14:13:20
|| source.size() > std::numeric_limits<int>::max()
ananta
2016/05/27 20:05:25
Done.
|
| + return std::string(); |
| + int size = ::WideCharToMultiByte(CP_UTF8, 0, &source[0], |
| + static_cast<int>(source.size()), nullptr, 0, nullptr, nullptr); |
| + std::string result(size, '\0'); |
| + if (::WideCharToMultiByte(CP_UTF8, 0, &source[0], |
| + static_cast<int>(source.size()), &result[0], size, nullptr, |
| + nullptr) != size) { |
| + assert(false); |
| + return std::string(); |
| + } |
| + return result; |
| +} |
| + |
| +base::string16 utf8_to_utf16(const std::string &source) { |
| + if (source.empty()) |
|
grt (UTC plus 2)
2016/05/27 14:13:20
|| source.size() > std::numeric_limits<int>::max()
ananta
2016/05/27 20:05:25
Done.
|
| + return base::string16(); |
| + int size = ::MultiByteToWideChar(CP_UTF8, 0, &source[0], |
| + static_cast<int>(source.size()), nullptr, 0); |
| + base::string16 result(size, L'\0'); |
| + if (::MultiByteToWideChar(CP_UTF8, 0, &source[0], |
| + static_cast<int>(source.size()), &result[0], size) != size) { |
| + assert(false); |
| + return base::string16(); |
| + } |
| + return result; |
| +} |
| + |
| +std::vector<std::string> TokenizeString(const std::string& str, |
| + const char delimiter, |
|
grt (UTC plus 2)
2016/05/27 14:13:20
no const
ananta
2016/05/27 20:05:25
Done.
|
| + bool trim_spaces) { |
|
scottmg
2016/05/27 17:27:22
I only see trim_spaces=false calls other than in t
ananta
2016/05/27 20:05:25
Prefer to leave it as an argument. Just in case we
|
| + std::vector<std::string> tokens; |
| + std::istringstream buffer(str); |
| + for (std::string token; std::getline(buffer, token, delimiter); ) { |
| + if (trim_spaces) |
| + trim(&token); |
| + tokens.push_back(token); |
| + } |
| + return tokens; |
| +} |
| + |
| +bool CompareVersionStrings(const std::string& version1, |
| + const std::string& version2, |
| + int* result) { |
| + if (version1.empty() || version2.empty()) |
| + return false; |
| + |
| + // Tokenize both version strings with "." as the separator. If either of |
| + // the returned token lists are empty then bail. |
| + std::vector<std::string> version1_components = |
| + install_static::TokenizeString(version1, '.', false); |
|
grt (UTC plus 2)
2016/05/27 14:13:20
omit "install_static::"
ananta
2016/05/27 20:05:25
Done.
|
| + if (version1_components.empty()) |
| + return false; |
| + |
| + std::vector<std::string> version2_components = |
| + install_static::TokenizeString(version2, '.', false); |
| + if (version2_components.empty()) |
| + return false; |
| + |
| + // You may have less tokens in either string. Use the minimum of the number |
| + // of tokens as the initial count. |
| + const size_t count = std::min(version1_components.size(), |
|
scottmg
2016/05/27 17:27:22
nit; weird line break
ananta
2016/05/27 20:05:25
Done.
|
| + version2_components.size()); |
| + for (size_t i = 0; i < count; ++i) { |
| + // If either of the version components don't contain valid numeric digits |
| + // bail. |
| + if (!is_valid_number(version1_components[i]) || |
| + !is_valid_number(version2_components[i])) { |
| + return false; |
| + } |
| + |
| + int version1_component = std::stoi(version1_components[i]); |
|
scottmg
2016/05/27 17:27:22
Ooh, this defaults to base=10, not =0, woohoo!
ananta
2016/05/27 20:05:25
Yeah
|
| + int version2_component = std::stoi(version2_components[i]); |
| + |
| + if (version1_component > version2_component) { |
| + *result = 1; |
| + return true; |
| + } |
| + |
| + if (version1_component < version2_component) { |
| + *result = -1; |
| + return true; |
| + } |
| + } |
| + |
| + // Handle remaining tokens. Here if we have non zero tokens remaining in the |
| + // version 1 list then it means that the version1 string is larger. If the |
| + // version 1 token list has tokens left, then if either of these tokens is |
| + // greater than 0 then it means that the version1 string is smaller than the |
| + // version2 string. |
| + if (version1_components.size() > version2_components.size()) { |
| + for (size_t i = count; i < version1_components.size(); ++i) { |
| + // If the version components don't contain valid numeric digits bail. |
| + if (!is_valid_number(version1_components[i])) |
| + return false; |
| + |
| + if (std::stoi(version1_components[i]) > 0) { |
| + *result = 1; |
| + return true; |
| + } |
| + } |
| + } else if (version1_components.size() < version2_components.size()) { |
| + for (size_t i = count; i < version2_components.size(); ++i) { |
| + // If the version components don't contain valid numeric digits bail. |
| + if (!is_valid_number(version2_components[i])) |
| + return false; |
| + |
| + if (std::stoi(version2_components[i]) > 0) { |
| + *result = -1; |
| + return true; |
| + } |
| + } |
| + } |
| + // Here it means that both versions are equal. |
| + *result = 0; |
| + return true; |
| +} |
| + |
| } // namespace install_static |