From 132e708fec50fd756b822925313456c70a4ff27f Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Fri, 14 Dec 2018 12:01:51 -0500
Subject: [PATCH] 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.
---
 indra/llcommon/llstring.cpp | 70 ++++++++++++++++++-------------------
 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 f931103ba69..0174c411b4b 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 2dccc7cbdf5..87cb35c59c3 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
-- 
GitLab