summaryrefslogtreecommitdiff
path: root/indra/llcommon
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llcommon')
-rwxr-xr-xindra/llcommon/hexdump.h4
-rw-r--r--indra/llcommon/llinstancetracker.h1
-rw-r--r--indra/llcommon/llleaplistener.cpp2
-rw-r--r--indra/llcommon/llleaplistener.h2
-rw-r--r--indra/llcommon/llstring.cpp131
-rw-r--r--indra/llcommon/llstring.h6
-rw-r--r--indra/llcommon/lua_function.cpp12
-rw-r--r--indra/llcommon/lua_function.h13
-rw-r--r--indra/llcommon/tests/llrand_test.cpp2
9 files changed, 106 insertions, 67 deletions
diff --git a/indra/llcommon/hexdump.h b/indra/llcommon/hexdump.h
index ab5ba2b16d..4b734426a3 100755
--- a/indra/llcommon/hexdump.h
+++ b/indra/llcommon/hexdump.h
@@ -25,7 +25,7 @@ namespace LL
class hexdump
{
public:
- hexdump(const std::string_view& data):
+ hexdump(std::string_view data):
hexdump(data.data(), data.length())
{}
@@ -66,7 +66,7 @@ private:
class hexmix
{
public:
- hexmix(const std::string_view& data):
+ hexmix(std::string_view data):
mData(data)
{}
diff --git a/indra/llcommon/llinstancetracker.h b/indra/llcommon/llinstancetracker.h
index 03418e9bad..b5c681e60a 100644
--- a/indra/llcommon/llinstancetracker.h
+++ b/indra/llcommon/llinstancetracker.h
@@ -41,6 +41,7 @@
#include <boost/iterator/indirect_iterator.hpp>
#include <boost/iterator/filter_iterator.hpp>
+#include "llprofiler.h"
#include "lockstatic.h"
#include "stringize.h"
diff --git a/indra/llcommon/llleaplistener.cpp b/indra/llcommon/llleaplistener.cpp
index b81ee66ba9..9742c9e9de 100644
--- a/indra/llcommon/llleaplistener.cpp
+++ b/indra/llcommon/llleaplistener.cpp
@@ -54,7 +54,7 @@
return features;
}
-LLLeapListener::LLLeapListener(const std::string_view& caller, const Callback& callback):
+LLLeapListener::LLLeapListener(std::string_view caller, const Callback& callback):
// Each LEAP plugin has an instance of this listener. Make the command
// pump name difficult for other such plugins to guess.
LLEventAPI(LLUUID::generateNewID().asString(),
diff --git a/indra/llcommon/llleaplistener.h b/indra/llcommon/llleaplistener.h
index d36d2ff8db..d38a6f4ace 100644
--- a/indra/llcommon/llleaplistener.h
+++ b/indra/llcommon/llleaplistener.h
@@ -28,7 +28,7 @@ public:
* event is received.
*/
using Callback = std::function<bool(const std::string& pump, const LLSD& data)>;
- LLLeapListener(const std::string_view& caller, const Callback& callback);
+ LLLeapListener(std::string_view caller, const Callback& callback);
~LLLeapListener();
LLEventPump& getReplyPump() { return mReplyPump; }
diff --git a/indra/llcommon/llstring.cpp b/indra/llcommon/llstring.cpp
index 505789f9ea..005864a843 100644
--- a/indra/llcommon/llstring.cpp
+++ b/indra/llcommon/llstring.cpp
@@ -31,6 +31,7 @@
#include "llfasttimer.h"
#include "llsd.h"
#include <vector>
+#include <sstream>
#if LL_WINDOWS
#include "llwin32headerslean.h"
@@ -141,10 +142,10 @@ std::string rawstr_to_utf8(const std::string& raw)
return wstring_to_utf8str(wstr);
}
-std::ptrdiff_t wchar_to_utf8chars(llwchar in_char, char* outchars)
+std::string wchar_to_utf8chars(llwchar in_char)
{
- U32 cur_char = (U32)in_char;
- char* base = outchars;
+ U32 cur_char(in_char);
+ char buff[8], *outchars = buff;
if (cur_char < 0x80)
{
*outchars++ = (U8)cur_char;
@@ -189,7 +190,7 @@ std::ptrdiff_t wchar_to_utf8chars(llwchar in_char, char* outchars)
LL_WARNS() << "Invalid Unicode character " << cur_char << "!" << LL_ENDL;
*outchars++ = LL_UNKNOWN_CHAR;
}
- return outchars - base;
+ return { buff, std::string::size_type(outchars - buff) };
}
auto utf16chars_to_wchar(const U16* inchars, llwchar* outchar)
@@ -214,7 +215,8 @@ auto utf16chars_to_wchar(const U16* inchars, llwchar* outchar)
llutf16string wstring_to_utf16str(const llwchar* utf32str, size_t len)
{
- llutf16string out;
+ // ostringstream for llutf16string
+ std::basic_ostringstream<U16> out;
S32 i = 0;
while (i < len)
@@ -222,16 +224,16 @@ llutf16string wstring_to_utf16str(const llwchar* utf32str, size_t len)
U32 cur_char = utf32str[i];
if (cur_char > 0xFFFF)
{
- out += (0xD7C0 + (cur_char >> 10));
- out += (0xDC00 | (cur_char & 0x3FF));
+ out.put(U16(0xD7C0 + (cur_char >> 10)));
+ out.put(U16(0xDC00 | (cur_char & 0x3FF)));
}
else
{
- out += cur_char;
+ out.put(U16(cur_char));
}
i++;
}
- return out;
+ return out.str();
}
llutf16string utf8str_to_utf16str( const char* utf8str, size_t len )
@@ -242,8 +244,16 @@ llutf16string utf8str_to_utf16str( const char* utf8str, size_t len )
LLWString utf16str_to_wstring(const U16* utf16str, size_t len)
{
- LLWString wout;
- if (len == 0) return wout;
+ if (len == 0) return {};
+
+ // MS doesn't support std::basic_ostringstream<llwchar>; have to work
+ // around it.
+ std::vector<llwchar> wout;
+ // We want to minimize allocations. We don't know how many llwchars we'll
+ // generate from this utf16str, but we do know the length should be at
+ // most len. So if we reserve 'len' llwchars, we shouldn't need to expand
+ // wout incrementally.
+ wout.reserve(len);
S32 i = 0;
const U16* chars16 = utf16str;
@@ -251,9 +261,9 @@ LLWString utf16str_to_wstring(const U16* utf16str, size_t len)
{
llwchar cur_char;
i += (S32)utf16chars_to_wchar(chars16+i, &cur_char);
- wout += cur_char;
+ wout.push_back(cur_char);
}
- return wout;
+ return { wout.begin(), wout.end() };
}
// Length in llwchar (UTF-32) of the first len units (16 bits) of the given UTF-16 string.
@@ -367,13 +377,12 @@ std::string wchar_utf8_preview(const llwchar wc)
std::ostringstream oss;
oss << std::hex << std::uppercase << (U32)wc;
- U8 out_bytes[8];
- U32 size = (U32)wchar_to_utf8chars(wc, (char*)out_bytes);
+ auto out_bytes = wchar_to_utf8chars(wc);
- if (size > 1)
+ if (out_bytes.length() > 1)
{
oss << " [";
- for (U32 i = 0; i < size; ++i)
+ for (U32 i = 0; i < out_bytes.length(); ++i)
{
if (i)
{
@@ -399,7 +408,14 @@ S32 wstring_utf8_length(const LLWString& wstr)
LLWString utf8str_to_wstring(const char* utf8str, size_t len)
{
- LLWString wout;
+ // MS doesn't support std::basic_ostringstream<llwchar>; have to work
+ // around it.
+ std::vector<llwchar> wout;
+ // We want to minimize allocations. We don't know how many llwchars we'll
+ // generate from this utf8str, but we do know the length should be at most
+ // len. So if we reserve 'len' llwchars, we shouldn't need to expand wout
+ // incrementally.
+ wout.reserve(len);
S32 i = 0;
while (i < len)
@@ -442,7 +458,7 @@ LLWString utf8str_to_wstring(const char* utf8str, size_t len)
}
else
{
- wout += LL_UNKNOWN_CHAR;
+ wout.push_back(LL_UNKNOWN_CHAR);
++i;
continue;
}
@@ -479,26 +495,21 @@ LLWString utf8str_to_wstring(const char* utf8str, size_t len)
}
}
- wout += unichar;
+ wout.push_back(unichar);
++i;
}
- return wout;
+ return { wout.begin(), wout.end() };
}
std::string wstring_to_utf8str(const llwchar* utf32str, size_t len)
{
- std::string out;
+ std::ostringstream out;
- S32 i = 0;
- while (i < len)
+ for (size_t i = 0; i < len; ++i)
{
- char tchars[8]; /* Flawfinder: ignore */
- auto n = wchar_to_utf8chars(utf32str[i], tchars);
- tchars[n] = 0;
- out += tchars;
- i++;
+ out << wchar_to_utf8chars(utf32str[i]);
}
- return out;
+ return out.str();
}
std::string utf16str_to_utf8str(const U16* utf16str, size_t len)
@@ -686,7 +697,21 @@ llwchar utf8str_to_wchar(const std::string& utf8str, size_t offset, size_t lengt
std::string utf8str_showBytesUTF8(const std::string& utf8str)
{
- std::string result;
+ std::ostringstream result;
+ char lastchar = '\0';
+ auto append = [&result, &lastchar](char c)
+ {
+ lastchar = c;
+ result << c;
+ };
+ auto appends = [&result, &lastchar](const std::string& s)
+ {
+ if (! s.empty())
+ {
+ lastchar = s.back();
+ result << s;
+ }
+ };
bool in_sequence = false;
size_t sequence_size = 0;
@@ -695,9 +720,9 @@ std::string utf8str_showBytesUTF8(const std::string& utf8str)
auto open_sequence = [&]()
{
- if (!result.empty() && result.back() != '\n')
- result += '\n'; // Use LF as a separator before new UTF-8 sequence
- result += '[';
+ if (lastchar != '\0' && lastchar != '\n')
+ append('\n'); // Use LF as a separator before new UTF-8 sequence
+ append('[');
in_sequence = true;
};
@@ -706,9 +731,9 @@ std::string utf8str_showBytesUTF8(const std::string& utf8str)
llwchar unicode = utf8str_to_wchar(utf8str, byte_index - sequence_size, sequence_size);
if (unicode != LL_UNKNOWN_CHAR)
{
- result += llformat("+%04X", unicode);
+ appends(llformat("+%04X", unicode));
}
- result += ']';
+ append(']');
in_sequence = false;
sequence_size = 0;
};
@@ -729,9 +754,9 @@ std::string utf8str_showBytesUTF8(const std::string& utf8str)
}
else // Continue the same UTF-8 sequence
{
- result += '.';
+ append('.');
}
- result += llformat("%02X", byte); // The byte is represented in hexadecimal form
+ appends(llformat("%02X", byte)); // The byte is represented in hexadecimal form
++sequence_size;
}
else // ASCII symbol is represented as a character
@@ -741,10 +766,10 @@ std::string utf8str_showBytesUTF8(const std::string& utf8str)
close_sequence();
if (byte != '\n')
{
- result += '\n'; // Use LF as a separator between UTF-8 and ASCII
+ append('\n'); // Use LF as a separator between UTF-8 and ASCII
}
}
- result += byte;
+ append(byte);
}
++byte_index;
}
@@ -754,7 +779,7 @@ std::string utf8str_showBytesUTF8(const std::string& utf8str)
close_sequence();
}
- return result;
+ return result.str();
}
// Search for any emoji symbol, return true if found
@@ -1587,7 +1612,7 @@ S32 LLStringUtil::format(std::string& s, const format_map_t& substitutions)
LL_PROFILE_ZONE_SCOPED_CATEGORY_STRING;
S32 res = 0;
- std::string output;
+ std::ostringstream output;
std::vector<std::string> tokens;
std::string::size_type start = 0;
@@ -1595,7 +1620,7 @@ S32 LLStringUtil::format(std::string& s, const format_map_t& substitutions)
std::string::size_type key_start = 0;
while ((key_start = getSubstitution(s, start, tokens)) != std::string::npos)
{
- output += std::string(s, prev_start, key_start-prev_start);
+ output << std::string(s, prev_start, key_start-prev_start);
prev_start = start;
bool found_replacement = false;
@@ -1636,20 +1661,20 @@ S32 LLStringUtil::format(std::string& s, const format_map_t& substitutions)
if (found_replacement)
{
- output += replacement;
+ output << replacement;
res++;
}
else
{
// we had no replacement, use the string as is
// e.g. "hello [MISSING_REPLACEMENT]" or "-=[Stylized Name]=-"
- output += std::string(s, key_start, start-key_start);
+ output << std::string(s, key_start, start-key_start);
}
tokens.clear();
}
// send the remainder of the string (with no further matches for bracketed names)
- output += std::string(s, start);
- s = output;
+ output << std::string(s, start);
+ s = output.str();
return res;
}
@@ -1665,7 +1690,7 @@ S32 LLStringUtil::format(std::string& s, const LLSD& substitutions)
return res;
}
- std::string output;
+ std::ostringstream output;
std::vector<std::string> tokens;
std::string::size_type start = 0;
@@ -1673,7 +1698,7 @@ S32 LLStringUtil::format(std::string& s, const LLSD& substitutions)
std::string::size_type key_start = 0;
while ((key_start = getSubstitution(s, start, tokens)) != std::string::npos)
{
- output += std::string(s, prev_start, key_start-prev_start);
+ output << std::string(s, prev_start, key_start-prev_start);
prev_start = start;
bool found_replacement = false;
@@ -1706,20 +1731,20 @@ S32 LLStringUtil::format(std::string& s, const LLSD& substitutions)
if (found_replacement)
{
- output += replacement;
+ output << replacement;
res++;
}
else
{
// we had no replacement, use the string as is
// e.g. "hello [MISSING_REPLACEMENT]" or "-=[Stylized Name]=-"
- output += std::string(s, key_start, start-key_start);
+ output << std::string(s, key_start, start-key_start);
}
tokens.clear();
}
// send the remainder of the string (with no further matches for bracketed names)
- output += std::string(s, start);
- s = output;
+ output << std::string(s, start);
+ s = output.str();
return res;
}
diff --git a/indra/llcommon/llstring.h b/indra/llcommon/llstring.h
index e4be1efaed..b552aede82 100644
--- a/indra/llcommon/llstring.h
+++ b/indra/llcommon/llstring.h
@@ -707,7 +707,11 @@ ll_convert_forms(ll_convert_alias, LLWString, std::string, utf8str_to_
// Same function, better name. JC
inline LLWString utf8string_to_wstring(const std::string& utf8_string) { return utf8str_to_wstring(utf8_string); }
-LL_COMMON_API std::ptrdiff_t wchar_to_utf8chars(llwchar inchar, char* outchars);
+// return a UTF-8 string representation of a single llwchar, which we
+// occasionally require:
+// cheaper than ll_convert_to<std::string>(LLWString(1, inchar))
+LL_COMMON_API std::string wchar_to_utf8chars(llwchar inchar);
+ll_convert_alias(std::string, llwchar, wchar_to_utf8chars(in));
ll_convert_forms(ll_convert_alias, std::string, LLWString, wstring_to_utf8str);
ll_convert_forms(ll_convert_u16_alias, std::string, llutf16string, utf16str_to_utf8str);
diff --git a/indra/llcommon/lua_function.cpp b/indra/llcommon/lua_function.cpp
index eefb1e62cf..2557fd0cc9 100644
--- a/indra/llcommon/lua_function.cpp
+++ b/indra/llcommon/lua_function.cpp
@@ -709,6 +709,11 @@ int lua_metaipair(lua_State* L)
LuaState::~LuaState()
{
+ // If we're unwinding the stack due to an exception, don't bother trying
+ // to call any callbacks -- either Lua or C++.
+ if (std::uncaught_exceptions() != 0)
+ return;
+
/*---------------------------- feature flag ----------------------------*/
if (mFeature)
/*---------------------------- feature flag ----------------------------*/
@@ -990,7 +995,8 @@ lua_function(atexit, "atexit(function): "
*****************************************************************************/
LuaPopper::~LuaPopper()
{
- if (mCount)
+ // If we're unwinding the C++ stack due to an exception, don't pop!
+ if (std::uncaught_exceptions() == 0 && mCount)
{
lua_pop(mState, mCount);
}
@@ -999,8 +1005,8 @@ LuaPopper::~LuaPopper()
/*****************************************************************************
* LuaFunction class
*****************************************************************************/
-LuaFunction::LuaFunction(const std::string_view& name, lua_CFunction function,
- const std::string_view& helptext)
+LuaFunction::LuaFunction(std::string_view name, lua_CFunction function,
+ std::string_view helptext)
{
const auto& [registry, lookup] = getState();
registry.emplace(name, Registry::mapped_type{ function, helptext });
diff --git a/indra/llcommon/lua_function.h b/indra/llcommon/lua_function.h
index 967d8eaba1..10c201c234 100644
--- a/indra/llcommon/lua_function.h
+++ b/indra/llcommon/lua_function.h
@@ -172,7 +172,10 @@ public:
LuaRemover& operator=(const LuaRemover&) = delete;
~LuaRemover()
{
- lua_remove(mState, mIndex);
+ // If we're unwinding the C++ stack due to an exception, don't mess
+ // with the Lua stack!
+ if (std::uncaught_exceptions() == 0)
+ lua_remove(mState, mIndex);
}
private:
@@ -351,7 +354,7 @@ auto lua_setfieldv(lua_State* L, int index, const char* k, const T& value)
// return to C++, from table at index, the value of field k (without metamethods)
template <typename T>
-auto lua_rawgetfield(lua_State* L, int index, const std::string_view& k)
+auto lua_rawgetfield(lua_State* L, int index, std::string_view k)
{
index = lua_absindex(L, index);
lua_checkdelta(L);
@@ -364,7 +367,7 @@ auto lua_rawgetfield(lua_State* L, int index, const std::string_view& k)
// set in table at index, as field k, the specified C++ value (without metamethods)
template <typename T>
-void lua_rawsetfield(lua_State* L, int index, const std::string_view& k, const T& value)
+void lua_rawsetfield(lua_State* L, int index, std::string_view k, const T& value)
{
index = lua_absindex(L, index);
lua_checkdelta(L);
@@ -389,8 +392,8 @@ void lua_rawsetfield(lua_State* L, int index, const std::string_view& k, const T
class LuaFunction
{
public:
- LuaFunction(const std::string_view& name, lua_CFunction function,
- const std::string_view& helptext);
+ LuaFunction(std::string_view name, lua_CFunction function,
+ std::string_view helptext);
static void init(lua_State* L);
diff --git a/indra/llcommon/tests/llrand_test.cpp b/indra/llcommon/tests/llrand_test.cpp
index a0dd4ef576..85dd53ce96 100644
--- a/indra/llcommon/tests/llrand_test.cpp
+++ b/indra/llcommon/tests/llrand_test.cpp
@@ -38,7 +38,7 @@
// testing extent < 0, negate the return value and the extent before passing
// into ensure_in_range().
template <typename NUMBER>
-void ensure_in_range(const std::string_view& name,
+void ensure_in_range(std::string_view name,
NUMBER value, NUMBER low, NUMBER high)
{
auto failmsg{ stringize(name, " >= ", low, " (", value, ')') };