Skip to content
Snippets Groups Projects
Commit 6a4897db authored by Steven Bennetts's avatar Steven Bennetts
Browse files

Significant optimization to LLUIString.

parent 6b31bc72
No related branches found
No related tags found
No related merge requests found
...@@ -232,9 +232,10 @@ class LLStringUtilBase ...@@ -232,9 +232,10 @@ class LLStringUtilBase
typedef std::map<LLFormatMapString, LLFormatMapString> format_map_t; typedef std::map<LLFormatMapString, LLFormatMapString> format_map_t;
static void getTokens (std::basic_string<T> input, std::vector<std::basic_string<T> >& tokens); static void getTokens (std::basic_string<T> input, std::vector<std::basic_string<T> >& tokens);
static void formatNumber(std::basic_string<T>& numStr, std::basic_string<T> decimals); static void formatNumber(std::basic_string<T>& numStr, std::basic_string<T> decimals);
static bool formatDatetime(std::basic_string<T>& replacement, std::basic_string<T> token, std::basic_string<T> param, const LLSD& substitutions); static bool formatDatetime(std::basic_string<T>& replacement, std::basic_string<T> token, std::basic_string<T> param, S32 secFromEpoch);
static S32 format(std::basic_string<T>& s, const format_map_t& substitutions);
static S32 format(std::basic_string<T>& s, const LLSD& substitutions); static S32 format(std::basic_string<T>& s, const LLSD& substitutions);
static S32 format(std::basic_string<T>& s, const format_map_t& fmt_map); static bool simpleReplacement(std::basic_string<T>& replacement, std::basic_string<T> token, const format_map_t& substitutions);
static bool simpleReplacement(std::basic_string<T>& replacement, std::basic_string<T> token, const LLSD& substitutions); static bool simpleReplacement(std::basic_string<T>& replacement, std::basic_string<T> token, const LLSD& substitutions);
static void setLocale (std::string inLocale) {sLocale = inLocale;}; static void setLocale (std::string inLocale) {sLocale = inLocale;};
static std::string getLocale (void) {return sLocale;}; static std::string getLocale (void) {return sLocale;};
...@@ -618,18 +619,76 @@ void LLStringUtilBase<T>::getTokens (std::basic_string<T> input, std::vector<std ...@@ -618,18 +619,76 @@ void LLStringUtilBase<T>::getTokens (std::basic_string<T> input, std::vector<std
// static // static
template<class T> template<class T>
S32 LLStringUtilBase<T>::format(std::basic_string<T>& s, const format_map_t& fmt_map) S32 LLStringUtilBase<T>::format(std::basic_string<T>& s, const format_map_t& substitutions)
{ {
LLSD llsdMap; S32 res = 0;
std::basic_ostringstream<T> output;
// match strings like [NAME,number,3]
const boost::regex key("\\[((\\s)*([0-9_A-Za-z]+)((\\s)*,(\\s)*[0-9_A-Za-z\\s]*){0,2}(\\s)*)]");
for (format_map_t::const_iterator iter = fmt_map.begin();
iter != fmt_map.end(); typename std::basic_string<T>::const_iterator start = s.begin();
++iter) typename std::basic_string<T>::const_iterator end = s.end();
boost::smatch match;
while (boost::regex_search(start, end, match, key, boost::match_default))
{ {
llsdMap[iter->first] = iter->second; bool found_replacement = false;
} std::vector<std::basic_string<T> > tokens;
std::basic_string<T> replacement;
getTokens (std::basic_string<T>(match[1].first, match[1].second), tokens);
if (tokens.size() == 1)
{
found_replacement = simpleReplacement (replacement, tokens[0], substitutions);
}
else if (tokens[1] == "number")
{
std::basic_string<T> param = "0";
if (tokens.size() > 2) param = tokens[2];
found_replacement = simpleReplacement (replacement, tokens[0], substitutions);
if (found_replacement) formatNumber (replacement, param);
}
else if (tokens[1] == "datetime")
{
std::basic_string<T> param;
if (tokens.size() > 2) param = tokens[2];
format_map_t::const_iterator iter = substitutions.find("datetime");
if (iter != substitutions.end())
{
S32 secFromEpoch = 0;
BOOL r = LLStringUtil::convertToS32(iter->second, secFromEpoch);
if (r)
{
found_replacement = formatDatetime(replacement, tokens[0], param, secFromEpoch);
}
}
}
return format (s, llsdMap); if (found_replacement)
{
output << std::basic_string<T>(start, match[0].first) << replacement;
res++;
}
else
{
// we had no replacement, so leave the string we searched for so that it gets noticed by QA
// "hello [NAME_NOT_FOUND]" is output
output << std::basic_string<T>(start, match[0].second);
}
// update search position
start = match[0].second;
}
// send the remainder of the string (with no further matches for bracketed names)
output << std::basic_string<T>(start, end);
s = output.str();
return res;
} }
//static //static
...@@ -704,7 +763,32 @@ S32 LLStringUtilBase<T>::format(std::basic_string<T>& s, const LLSD& substitutio ...@@ -704,7 +763,32 @@ S32 LLStringUtilBase<T>::format(std::basic_string<T>& s, const LLSD& substitutio
// static // static
template<class T> template<class T>
bool LLStringUtilBase<T>::simpleReplacement(std::basic_string<T> &replacement, std::basic_string<T> token, const LLSD &substitutions) bool LLStringUtilBase<T>::simpleReplacement(std::basic_string<T> &replacement, std::basic_string<T> token, const format_map_t& substitutions)
{
// see if we have a replacement for the bracketed string (without the brackets)
// test first using has() because if we just look up with operator[] we get back an
// empty string even if the value is missing. We want to distinguish between
// missing replacements and deliberately empty replacement strings.
format_map_t::const_iterator iter = substitutions.find(token);
if (iter != substitutions.end())
{
replacement = iter->second;
return true;
}
// if not, see if there's one WITH brackets
iter = substitutions.find(std::basic_string<T>("[" + token + "]"));
if (iter != substitutions.end())
{
replacement = iter->second;
return true;
}
return false;
}
// static
template<class T>
bool LLStringUtilBase<T>::simpleReplacement(std::basic_string<T> &replacement, std::basic_string<T> token, const LLSD& substitutions)
{ {
// see if we have a replacement for the bracketed string (without the brackets) // see if we have a replacement for the bracketed string (without the brackets)
// test first using has() because if we just look up with operator[] we get back an // test first using has() because if we just look up with operator[] we get back an
...@@ -764,10 +848,8 @@ void LLStringUtilBase<T>::formatNumber(std::basic_string<T>& numStr, std::basic_ ...@@ -764,10 +848,8 @@ void LLStringUtilBase<T>::formatNumber(std::basic_string<T>& numStr, std::basic_
// static // static
template<class T> template<class T>
bool LLStringUtilBase<T>::formatDatetime(std::basic_string<T>& replacement, std::basic_string<T> token, bool LLStringUtilBase<T>::formatDatetime(std::basic_string<T>& replacement, std::basic_string<T> token,
std::basic_string<T> param, const LLSD& substitutions) std::basic_string<T> param, S32 secFromEpoch)
{ {
S32 secFromEpoch = (long) substitutions["datetime"].asInteger();
if (param == "local") // local if (param == "local") // local
{ {
secFromEpoch -= LLStringOps::getLocalTimeOffset(); secFromEpoch -= LLStringOps::getLocalTimeOffset();
......
...@@ -37,6 +37,8 @@ ...@@ -37,6 +37,8 @@
const LLStringUtil::format_map_t LLUIString::sNullArgs; const LLStringUtil::format_map_t LLUIString::sNullArgs;
LLFastTimer::DeclareTimer FTM_UI_STRING("UI String");
LLUIString::LLUIString(const std::string& instring, const LLStringUtil::format_map_t& args) LLUIString::LLUIString(const std::string& instring, const LLStringUtil::format_map_t& args)
: mOrig(instring), : mOrig(instring),
...@@ -59,6 +61,8 @@ void LLUIString::setArgList(const LLStringUtil::format_map_t& args) ...@@ -59,6 +61,8 @@ void LLUIString::setArgList(const LLStringUtil::format_map_t& args)
void LLUIString::setArgs(const LLSD& sd) void LLUIString::setArgs(const LLSD& sd)
{ {
LLFastTimer timer(FTM_UI_STRING);
if (!sd.isMap()) return; if (!sd.isMap()) return;
for(LLSD::map_const_iterator sd_it = sd.beginMap(); for(LLSD::map_const_iterator sd_it = sd.beginMap();
sd_it != sd.endMap(); sd_it != sd.endMap();
...@@ -112,6 +116,8 @@ void LLUIString::clear() ...@@ -112,6 +116,8 @@ void LLUIString::clear()
void LLUIString::format() void LLUIString::format()
{ {
LLFastTimer timer(FTM_UI_STRING);
// optimize for empty strings (don't attempt string replacement) // optimize for empty strings (don't attempt string replacement)
if (mOrig.empty()) if (mOrig.empty())
{ {
......
...@@ -104,15 +104,15 @@ ...@@ -104,15 +104,15 @@
top_delta="0" top_delta="0"
value="Second Life:" value="Second Life:"
width="140" /> width="140" />
<text <text_editor
follows="left|top|right" follows="left|top|right"
height="90" height="90"
layout="topleft" layout="topleft"
name="sl_description_edit" name="sl_description_edit"
width="130" width="180"
word_wrap="true"> word_wrap="true">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean viverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet ipsum. adipiscing elit. Aenean viverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet ipsum. adipiscing elit. Aenean viverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet ipsum. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean viverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet ipsum. adipiscing elit. Aenean viverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet ipsum. adipiscing elit. Aenean viverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet ipsum.
</text> </text_editor>
</panel> </panel>
<panel <panel
follows="left|top" follows="left|top"
...@@ -142,15 +142,15 @@ ...@@ -142,15 +142,15 @@
top_delta="0" top_delta="0"
value="Real World:" value="Real World:"
width="140" /> width="140" />
<text <text_editor
follows="left|top|right" follows="left|top|right"
height="90" height="90"
layout="topleft" layout="topleft"
name="fl_description_edit" name="fl_description_edit"
width="130" width="180"
word_wrap="true"> word_wrap="true">
Lorem ipsum dolor sit amet, consectetur adlkjpiscing elit moose moose. Aenean viverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet. adipiscing elit. Aenean rigviverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet sorbet ipsum. adipiscing elit. Aenean viverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet ipsum. Lorem ipsum dolor sit amet, consectetur adlkjpiscing elit moose moose. Aenean viverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet. adipiscing elit. Aenean rigviverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet sorbet ipsum. adipiscing elit. Aenean viverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet ipsum.
</text> </text_editor>
</panel> </panel>
<link <link
follows="left|top|right" follows="left|top|right"
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment