summaryrefslogtreecommitdiff
path: root/indra/llcommon/llstring.h
diff options
context:
space:
mode:
authorSteven Bennetts <steve@lindenlab.com>2008-08-12 17:29:50 +0000
committerSteven Bennetts <steve@lindenlab.com>2008-08-12 17:29:50 +0000
commit80be4c1d2d73982ea2df6dd7ef3fc3465416c882 (patch)
tree9c5958572368be494b6302db8b03967a2c67b7ad /indra/llcommon/llstring.h
parenta09f7d41efdb945755efaeb07f7418c1f6e2a78b (diff)
QAR-767 Combined maint-render-7 and maint-viewer-9 merge
merge release@93398 viewer-merge-1@94007 -> release dataserver-is-deprecated
Diffstat (limited to 'indra/llcommon/llstring.h')
-rw-r--r--indra/llcommon/llstring.h64
1 files changed, 52 insertions, 12 deletions
diff --git a/indra/llcommon/llstring.h b/indra/llcommon/llstring.h
index 50681b7967..475531a2ad 100644
--- a/indra/llcommon/llstring.h
+++ b/indra/llcommon/llstring.h
@@ -155,6 +155,16 @@ public:
static BOOL isDigit(llwchar a) { return iswdigit(a) != 0; }
};
+// Allowing assignments from non-strings into format_map_t is apparently
+// *really* error-prone, so subclass std::string with just basic c'tors.
+class FormatMapString : public std::string
+{
+public:
+ FormatMapString() : std::string() {};
+ FormatMapString(const char* s) : std::string(s) {};
+ FormatMapString(const std::string& s) : std::string(s) {};
+};
+
template <class T>
class LLStringUtilBase
{
@@ -167,7 +177,7 @@ public:
static std::basic_string<T> null;
- typedef std::map<std::basic_string<T>, std::basic_string<T> > format_map_t;
+ typedef std::map<FormatMapString, FormatMapString> format_map_t;
static S32 format(std::basic_string<T>& s, const format_map_t& fmt_map);
static BOOL isValidIndex(const std::basic_string<T>& string, size_type i)
@@ -516,27 +526,57 @@ namespace LLStringFn
////////////////////////////////////////////////////////////
+// LLStringBase::format()
+//
+// This function takes a string 's' and a map 'fmt_map' of strings-to-strings.
+// All occurances of strings in 's' from the left-hand side of 'fmt_map' are
+// then replaced with the corresponding right-hand side of 'fmt_map', non-
+// recursively. The function returns the number of substitutions made.
+
// static
template<class T>
S32 LLStringUtilBase<T>::format(std::basic_string<T>& s, const format_map_t& fmt_map)
{
typedef typename std::basic_string<T>::size_type string_size_type_t;
- typedef typename format_map_t::const_iterator format_map_const_iterator_t;
+ string_size_type_t scanstart = 0;
S32 res = 0;
- for (format_map_const_iterator_t iter = fmt_map.begin(); iter != fmt_map.end(); ++iter)
+
+ // Look for the first match of any keyword, replace that keyword,
+ // repeat from the end of the replacement string. This avoids
+ // accidentally performing substitution on a substituted string.
+ while (1)
{
- U32 fmtlen = iter->first.size();
- string_size_type_t n = 0;
- while (1)
+ string_size_type_t first_match_pos = scanstart;
+ string_size_type_t first_match_str_length = 0;
+ std::basic_string<T> first_match_str_replacement;
+
+ for (format_map_t::const_iterator iter = fmt_map.begin();
+ iter != fmt_map.end();
+ ++iter)
{
- n = s.find(iter->first, n);
- if (n == std::basic_string<T>::npos)
+ string_size_type_t n = s.find(iter->first, scanstart);
+ if (n != std::basic_string<T>::npos &&
+ (n < first_match_pos ||
+ 0 == first_match_str_length))
{
- break;
+ first_match_pos = n;
+ first_match_str_length = iter->first.length();
+ first_match_str_replacement = iter->second;
}
- s.erase(n, fmtlen);
- s.insert(n, iter->second);
- n += fmtlen;
+ }
+
+ if (0 == first_match_str_length)
+ {
+ // no more keys found to substitute from this point
+ // in the string forward.
+ break;
+ }
+ else
+ {
+ s.erase(first_match_pos, first_match_str_length);
+ s.insert(first_match_pos, first_match_str_replacement);
+ scanstart = first_match_pos +
+ first_match_str_replacement.length();
++res;
}
}