diff options
author | Nat Goodspeed <nat@lindenlab.com> | 2018-12-14 12:01:51 -0500 |
---|---|---|
committer | Nat Goodspeed <nat@lindenlab.com> | 2018-12-14 12:01:51 -0500 |
commit | 132e708fec50fd756b822925313456c70a4ff27f (patch) | |
tree | bc5ac17d8e0cfe8e5c550615789da8a4eabab541 | |
parent | 9ffcafb64b4483c315d00e88ffc1438bce1f7915 (diff) |
SL-10153: Fix previous commit for non-Windows systems.
Move Windows-flavored llstring_getoptenv() to Windows-specific section of
llstring.cpp.
boost::optional type must be stated explicitly to initialize with a value.
On platforms where llwchar is the same as wchar_t, LLWString is the same as
std::wstring, so ll_convert specializations for std::wstring would duplicate
those for LLWString. Defend against that.
The compilers we use don't like 'return condition? { expr } : {}', in which we
hope to construct and return an instance of the declared return type without
having to restate the type. It works to use an explicit 'if' statement.
-rw-r--r-- | indra/llcommon/llstring.cpp | 70 | ||||
-rw-r--r-- | indra/llcommon/llstring.h | 30 |
2 files changed, 57 insertions, 43 deletions
diff --git a/indra/llcommon/llstring.cpp b/indra/llcommon/llstring.cpp index f931103ba6..0174c411b4 100644 --- a/indra/llcommon/llstring.cpp +++ b/indra/llcommon/llstring.cpp @@ -53,40 +53,6 @@ std::string ll_safe_string(const char* in, S32 maxlen) return std::string(); } -boost::optional<std::wstring> llstring_getoptenv(const std::string& key) -{ - auto wkey = ll_convert_string_to_wide(key); - // Take a wild guess as to how big the buffer should be. - std::vector<wchar_t> buffer(1024); - auto n = GetEnvironmentVariableW(wkey.c_str(), &buffer[0], buffer.size()); - // If our initial guess was too short, n will indicate the size (in - // wchar_t's) that buffer should have been, including the terminating nul. - if (n > (buffer.size() - 1)) - { - // make it big enough - buffer.resize(n); - // and try again - n = GetEnvironmentVariableW(wkey.c_str(), &buffer[0], buffer.size()); - } - // did that (ultimately) succeed? - if (n) - { - // great, return populated boost::optional - return { &buffer[0] }; - } - - // not successful - auto last_error = GetLastError(); - // Don't bother warning for NOT_FOUND; that's an expected case - if (last_error != ERROR_ENVVAR_NOT_FOUND) - { - LL_WARNS() << "GetEnvironmentVariableW('" << key << "') failed: " - << windows_message<std::string>(last_error) << LL_ENDL; - } - // return empty boost::optional - return {}; -} - bool is_char_hex(char hex) { if((hex >= '0') && (hex <= '9')) @@ -854,6 +820,40 @@ std::wstring windows_message<std::wstring>(DWORD error) return out.str(); } +boost::optional<std::wstring> llstring_getoptenv(const std::string& key) +{ + auto wkey = ll_convert_string_to_wide(key); + // Take a wild guess as to how big the buffer should be. + std::vector<wchar_t> buffer(1024); + auto n = GetEnvironmentVariableW(wkey.c_str(), &buffer[0], buffer.size()); + // If our initial guess was too short, n will indicate the size (in + // wchar_t's) that buffer should have been, including the terminating nul. + if (n > (buffer.size() - 1)) + { + // make it big enough + buffer.resize(n); + // and try again + n = GetEnvironmentVariableW(wkey.c_str(), &buffer[0], buffer.size()); + } + // did that (ultimately) succeed? + if (n) + { + // great, return populated boost::optional + return boost::optional<std::wstring>(&buffer[0]); + } + + // not successful + auto last_error = GetLastError(); + // Don't bother warning for NOT_FOUND; that's an expected case + if (last_error != ERROR_ENVVAR_NOT_FOUND) + { + LL_WARNS() << "GetEnvironmentVariableW('" << key << "') failed: " + << windows_message<std::string>(last_error) << LL_ENDL; + } + // return empty boost::optional + return {}; +} + #else // ! LL_WINDOWS boost::optional<std::string> llstring_getoptenv(const std::string& key) @@ -862,7 +862,7 @@ boost::optional<std::string> llstring_getoptenv(const std::string& key) if (found) { // return populated boost::optional - return { found }; + return boost::optional<std::string>(found); } else { diff --git a/indra/llcommon/llstring.h b/indra/llcommon/llstring.h index 2dccc7cbdf..87cb35c59c 100644 --- a/indra/llcommon/llstring.h +++ b/indra/llcommon/llstring.h @@ -583,19 +583,24 @@ typedef std::basic_string<U16> llutf16string; // comparable preferred alias involving std::wstring. (In this scenario, if // you pass llutf16string, it will engage the std::wstring specialization.) #define ll_convert_u16_alias(TO, FROM, EXPR) // nothing -#else +#else // defined(LL_WCHAR_T_NATIVE) // wchar_t is a distinct native type, so llutf16string is also a distinct // type, and there IS a point to converting separately to/from llutf16string. // (But why? Windows APIs are still defined in terms of wchar_t, and // in this scenario llutf16string won't work for them!) #define ll_convert_u16_alias(TO, FROM, EXPR) ll_convert_alias(TO, FROM, EXPR) -// converting between std::wstring and llutf16string involves copying chars -// enclose the brace-initialization expression in parens to protect the comma -// from macro-argument parsing -ll_convert_alias(llutf16string, std::wstring, ({ in.begin(), in.end() })); -ll_convert_alias(std::wstring, llutf16string, ({ in.begin(), in.end() })); -#endif +#if LL_WINDOWS +// LL_WCHAR_T_NATIVE is defined on non-Windows systems because, in fact, +// wchar_t is native. Everywhere but Windows, we use it for llwchar (see +// stdtypes.h). That makes LLWString identical to std::wstring, so these +// aliases for std::wstring would collide with those for LLWString. Only +// define on Windows, where converting between std::wstring and llutf16string +// means copying chars. +ll_convert_alias(llutf16string, std::wstring, llutf16string(in.begin(), in.end())); +ll_convert_alias(std::wstring, llutf16string, std::wstring(in.begin(), in.end())); +#endif // LL_WINDOWS +#endif // defined(LL_WCHAR_T_NATIVE) LL_COMMON_API LLWString utf16str_to_wstring(const llutf16string &utf16str, S32 len); LL_COMMON_API LLWString utf16str_to_wstring(const llutf16string &utf16str); @@ -1751,7 +1756,16 @@ template<class T> auto LLStringUtilBase<T>::getoptenv(const std::string& key) -> boost::optional<string_type> { auto found{llstring_getoptenv(key)}; - return found? { ll_convert<string_type>(*found) } : {}; + if (found) + { + // return populated boost::optional + return { ll_convert<string_type>(*found) }; + } + else + { + // empty boost::optional + return {}; + } } // static |