From f0d1afc2266e13b4f36f750ba5e721e427caf7b8 Mon Sep 17 00:00:00 2001 From: Kitty Barnett Date: Fri, 20 Jan 2012 18:07:35 +0100 Subject: STORM-276 Added spellcheck functionality to the LLLineEditor control --- indra/llcommon/llstring.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'indra/llcommon/llstring.h') diff --git a/indra/llcommon/llstring.h b/indra/llcommon/llstring.h index 7e41e787b5..3a27badb5a 100644 --- a/indra/llcommon/llstring.h +++ b/indra/llcommon/llstring.h @@ -182,6 +182,9 @@ public: static bool isPunct(char a) { return ispunct((unsigned char)a) != 0; } static bool isPunct(llwchar a) { return iswpunct(a) != 0; } + static bool isAlpha(char a) { return isalpha((unsigned char)a) != 0; } + static bool isAlpha(llwchar a) { return iswalpha(a) != 0; } + static bool isAlnum(char a) { return isalnum((unsigned char)a) != 0; } static bool isAlnum(llwchar a) { return iswalnum(a) != 0; } -- cgit v1.2.3 From 507e136f9a25179992b2093e10ade1093cc71698 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Mon, 23 Jan 2012 16:24:33 -0500 Subject: Per Richard: close unusable Job Object; move quote() to LLStringUtil. If LLProcess can't set the right flag on a Windows Job Object, the object isn't useful to us, so we might as well discard it. quote() is sufficiently general that it belongs in LLStringUtil instead of buried as a static helper function in llprocess.cpp. --- indra/llcommon/llstring.h | 223 ++++++++++++++++++++++++++-------------------- 1 file changed, 128 insertions(+), 95 deletions(-) (limited to 'indra/llcommon/llstring.h') diff --git a/indra/llcommon/llstring.h b/indra/llcommon/llstring.h index 7e41e787b5..d3f1d01aa2 100644 --- a/indra/llcommon/llstring.h +++ b/indra/llcommon/llstring.h @@ -237,40 +237,41 @@ private: static std::string sLocale; public: - typedef typename std::basic_string::size_type size_type; + typedef std::basic_string string_type; + typedef typename string_type::size_type size_type; public: ///////////////////////////////////////////////////////////////////////////////////////// // Static Utility functions that operate on std::strings - static const std::basic_string null; + static const string_type null; typedef std::map format_map_t; - LL_COMMON_API static void getTokens(const std::basic_string& instr, std::vector >& tokens, const std::basic_string& delims); - LL_COMMON_API static void formatNumber(std::basic_string& numStr, std::basic_string decimals); - LL_COMMON_API static bool formatDatetime(std::basic_string& replacement, std::basic_string token, std::basic_string param, S32 secFromEpoch); - LL_COMMON_API static S32 format(std::basic_string& s, const format_map_t& substitutions); - LL_COMMON_API static S32 format(std::basic_string& s, const LLSD& substitutions); - LL_COMMON_API static bool simpleReplacement(std::basic_string& replacement, std::basic_string token, const format_map_t& substitutions); - LL_COMMON_API static bool simpleReplacement(std::basic_string& replacement, std::basic_string token, const LLSD& substitutions); + LL_COMMON_API static void getTokens(const string_type& instr, std::vector& tokens, const string_type& delims); + LL_COMMON_API static void formatNumber(string_type& numStr, string_type decimals); + LL_COMMON_API static bool formatDatetime(string_type& replacement, string_type token, string_type param, S32 secFromEpoch); + LL_COMMON_API static S32 format(string_type& s, const format_map_t& substitutions); + LL_COMMON_API static S32 format(string_type& s, const LLSD& substitutions); + LL_COMMON_API static bool simpleReplacement(string_type& replacement, string_type token, const format_map_t& substitutions); + LL_COMMON_API static bool simpleReplacement(string_type& replacement, string_type token, const LLSD& substitutions); LL_COMMON_API static void setLocale (std::string inLocale); LL_COMMON_API static std::string getLocale (void); - static bool isValidIndex(const std::basic_string& string, size_type i) + static bool isValidIndex(const string_type& string, size_type i) { return !string.empty() && (0 <= i) && (i <= string.size()); } - static void trimHead(std::basic_string& string); - static void trimTail(std::basic_string& string); - static void trim(std::basic_string& string) { trimHead(string); trimTail(string); } - static void truncate(std::basic_string& string, size_type count); + static void trimHead(string_type& string); + static void trimTail(string_type& string); + static void trim(string_type& string) { trimHead(string); trimTail(string); } + static void truncate(string_type& string, size_type count); - static void toUpper(std::basic_string& string); - static void toLower(std::basic_string& string); + static void toUpper(string_type& string); + static void toLower(string_type& string); // True if this is the head of s. - static BOOL isHead( const std::basic_string& string, const T* s ); + static BOOL isHead( const string_type& string, const T* s ); /** * @brief Returns true if string starts with substr @@ -278,8 +279,8 @@ public: * If etither string or substr are empty, this method returns false. */ static bool startsWith( - const std::basic_string& string, - const std::basic_string& substr); + const string_type& string, + const string_type& substr); /** * @brief Returns true if string ends in substr @@ -287,19 +288,26 @@ public: * If etither string or substr are empty, this method returns false. */ static bool endsWith( - const std::basic_string& string, - const std::basic_string& substr); + const string_type& string, + const string_type& substr); - static void addCRLF(std::basic_string& string); - static void removeCRLF(std::basic_string& string); + static void addCRLF(string_type& string); + static void removeCRLF(string_type& string); - static void replaceTabsWithSpaces( std::basic_string& string, size_type spaces_per_tab ); - static void replaceNonstandardASCII( std::basic_string& string, T replacement ); - static void replaceChar( std::basic_string& string, T target, T replacement ); - static void replaceString( std::basic_string& string, std::basic_string target, std::basic_string replacement ); + static void replaceTabsWithSpaces( string_type& string, size_type spaces_per_tab ); + static void replaceNonstandardASCII( string_type& string, T replacement ); + static void replaceChar( string_type& string, T target, T replacement ); + static void replaceString( string_type& string, string_type target, string_type replacement ); - static BOOL containsNonprintable(const std::basic_string& string); - static void stripNonprintable(std::basic_string& string); + static BOOL containsNonprintable(const string_type& string); + static void stripNonprintable(string_type& string); + + /** + * Double-quote an argument string, unless it's already double-quoted. If we + * quote it, escape any embedded double-quote with the escape string (default + * backslash). + */ + string_type quote(const string_type& str, const string_type& escape="\\"); /** * @brief Unsafe way to make ascii characters. You should probably @@ -308,18 +316,18 @@ public: * The 2 and 4 byte std::string probably work, so LLWStringUtil::_makeASCII * should work. */ - static void _makeASCII(std::basic_string& string); + static void _makeASCII(string_type& string); // Conversion to other data types - static BOOL convertToBOOL(const std::basic_string& string, BOOL& value); - static BOOL convertToU8(const std::basic_string& string, U8& value); - static BOOL convertToS8(const std::basic_string& string, S8& value); - static BOOL convertToS16(const std::basic_string& string, S16& value); - static BOOL convertToU16(const std::basic_string& string, U16& value); - static BOOL convertToU32(const std::basic_string& string, U32& value); - static BOOL convertToS32(const std::basic_string& string, S32& value); - static BOOL convertToF32(const std::basic_string& string, F32& value); - static BOOL convertToF64(const std::basic_string& string, F64& value); + static BOOL convertToBOOL(const string_type& string, BOOL& value); + static BOOL convertToU8(const string_type& string, U8& value); + static BOOL convertToS8(const string_type& string, S8& value); + static BOOL convertToS16(const string_type& string, S16& value); + static BOOL convertToU16(const string_type& string, U16& value); + static BOOL convertToU32(const string_type& string, U32& value); + static BOOL convertToS32(const string_type& string, S32& value); + static BOOL convertToF32(const string_type& string, F32& value); + static BOOL convertToF64(const string_type& string, F64& value); ///////////////////////////////////////////////////////////////////////////////////////// // Utility functions for working with char*'s and strings @@ -327,24 +335,24 @@ public: // Like strcmp but also handles empty strings. Uses // current locale. static S32 compareStrings(const T* lhs, const T* rhs); - static S32 compareStrings(const std::basic_string& lhs, const std::basic_string& rhs); + static S32 compareStrings(const string_type& lhs, const string_type& rhs); // case insensitive version of above. Uses current locale on // Win32, and falls back to a non-locale aware comparison on // Linux. static S32 compareInsensitive(const T* lhs, const T* rhs); - static S32 compareInsensitive(const std::basic_string& lhs, const std::basic_string& rhs); + static S32 compareInsensitive(const string_type& lhs, const string_type& rhs); // Case sensitive comparison with good handling of numbers. Does not use current locale. // a.k.a. strdictcmp() - static S32 compareDict(const std::basic_string& a, const std::basic_string& b); + static S32 compareDict(const string_type& a, const string_type& b); // Case *in*sensitive comparison with good handling of numbers. Does not use current locale. // a.k.a. strdictcmp() - static S32 compareDictInsensitive(const std::basic_string& a, const std::basic_string& b); + static S32 compareDictInsensitive(const string_type& a, const string_type& b); // Puts compareDict() in a form appropriate for LL container classes to use for sorting. - static BOOL precedesDict( const std::basic_string& a, const std::basic_string& b ); + static BOOL precedesDict( const string_type& a, const string_type& b ); // A replacement for strncpy. // If the dst buffer is dst_size bytes long or more, ensures that dst is null terminated and holds @@ -352,7 +360,7 @@ public: static void copy(T* dst, const T* src, size_type dst_size); // Copies src into dst at a given offset. - static void copyInto(std::basic_string& dst, const std::basic_string& src, size_type offset); + static void copyInto(string_type& dst, const string_type& src, size_type offset); static bool isPartOfWord(T c) { return (c == (T)'_') || LLStringOps::isAlnum(c); } @@ -362,7 +370,7 @@ public: #endif private: - LL_COMMON_API static size_type getSubstitution(const std::basic_string& instr, size_type& start, std::vector >& tokens); + LL_COMMON_API static size_type getSubstitution(const string_type& instr, size_type& start, std::vector& tokens); }; template const std::basic_string LLStringUtilBase::null; @@ -669,7 +677,7 @@ S32 LLStringUtilBase::compareStrings(const T* lhs, const T* rhs) //static template -S32 LLStringUtilBase::compareStrings(const std::basic_string& lhs, const std::basic_string& rhs) +S32 LLStringUtilBase::compareStrings(const string_type& lhs, const string_type& rhs) { return LLStringOps::collate(lhs.c_str(), rhs.c_str()); } @@ -695,8 +703,8 @@ S32 LLStringUtilBase::compareInsensitive(const T* lhs, const T* rhs ) } else { - std::basic_string lhs_string(lhs); - std::basic_string rhs_string(rhs); + string_type lhs_string(lhs); + string_type rhs_string(rhs); LLStringUtilBase::toUpper(lhs_string); LLStringUtilBase::toUpper(rhs_string); result = LLStringOps::collate(lhs_string.c_str(), rhs_string.c_str()); @@ -706,10 +714,10 @@ S32 LLStringUtilBase::compareInsensitive(const T* lhs, const T* rhs ) //static template -S32 LLStringUtilBase::compareInsensitive(const std::basic_string& lhs, const std::basic_string& rhs) +S32 LLStringUtilBase::compareInsensitive(const string_type& lhs, const string_type& rhs) { - std::basic_string lhs_string(lhs); - std::basic_string rhs_string(rhs); + string_type lhs_string(lhs); + string_type rhs_string(rhs); LLStringUtilBase::toUpper(lhs_string); LLStringUtilBase::toUpper(rhs_string); return LLStringOps::collate(lhs_string.c_str(), rhs_string.c_str()); @@ -720,7 +728,7 @@ S32 LLStringUtilBase::compareInsensitive(const std::basic_string& lhs, con //static template -S32 LLStringUtilBase::compareDict(const std::basic_string& astr, const std::basic_string& bstr) +S32 LLStringUtilBase::compareDict(const string_type& astr, const string_type& bstr) { const T* a = astr.c_str(); const T* b = bstr.c_str(); @@ -761,7 +769,7 @@ S32 LLStringUtilBase::compareDict(const std::basic_string& astr, const std // static template -S32 LLStringUtilBase::compareDictInsensitive(const std::basic_string& astr, const std::basic_string& bstr) +S32 LLStringUtilBase::compareDictInsensitive(const string_type& astr, const string_type& bstr) { const T* a = astr.c_str(); const T* b = bstr.c_str(); @@ -796,7 +804,7 @@ S32 LLStringUtilBase::compareDictInsensitive(const std::basic_string& astr // Puts compareDict() in a form appropriate for LL container classes to use for sorting. // static template -BOOL LLStringUtilBase::precedesDict( const std::basic_string& a, const std::basic_string& b ) +BOOL LLStringUtilBase::precedesDict( const string_type& a, const string_type& b ) { if( a.size() && b.size() ) { @@ -810,7 +818,7 @@ BOOL LLStringUtilBase::precedesDict( const std::basic_string& a, const std //static template -void LLStringUtilBase::toUpper(std::basic_string& string) +void LLStringUtilBase::toUpper(string_type& string) { if( !string.empty() ) { @@ -824,7 +832,7 @@ void LLStringUtilBase::toUpper(std::basic_string& string) //static template -void LLStringUtilBase::toLower(std::basic_string& string) +void LLStringUtilBase::toLower(string_type& string) { if( !string.empty() ) { @@ -838,7 +846,7 @@ void LLStringUtilBase::toLower(std::basic_string& string) //static template -void LLStringUtilBase::trimHead(std::basic_string& string) +void LLStringUtilBase::trimHead(string_type& string) { if( !string.empty() ) { @@ -853,7 +861,7 @@ void LLStringUtilBase::trimHead(std::basic_string& string) //static template -void LLStringUtilBase::trimTail(std::basic_string& string) +void LLStringUtilBase::trimTail(string_type& string) { if( string.size() ) { @@ -872,7 +880,7 @@ void LLStringUtilBase::trimTail(std::basic_string& string) // Replace line feeds with carriage return-line feed pairs. //static template -void LLStringUtilBase::addCRLF(std::basic_string& string) +void LLStringUtilBase::addCRLF(string_type& string) { const T LF = 10; const T CR = 13; @@ -914,7 +922,7 @@ void LLStringUtilBase::addCRLF(std::basic_string& string) // Remove all carriage returns //static template -void LLStringUtilBase::removeCRLF(std::basic_string& string) +void LLStringUtilBase::removeCRLF(string_type& string) { const T CR = 13; @@ -935,10 +943,10 @@ void LLStringUtilBase::removeCRLF(std::basic_string& string) //static template -void LLStringUtilBase::replaceChar( std::basic_string& string, T target, T replacement ) +void LLStringUtilBase::replaceChar( string_type& string, T target, T replacement ) { size_type found_pos = 0; - while( (found_pos = string.find(target, found_pos)) != std::basic_string::npos ) + while( (found_pos = string.find(target, found_pos)) != string_type::npos ) { string[found_pos] = replacement; found_pos++; // avoid infinite defeat if target == replacement @@ -947,10 +955,10 @@ void LLStringUtilBase::replaceChar( std::basic_string& string, T target, T //static template -void LLStringUtilBase::replaceString( std::basic_string& string, std::basic_string target, std::basic_string replacement ) +void LLStringUtilBase::replaceString( string_type& string, string_type target, string_type replacement ) { size_type found_pos = 0; - while( (found_pos = string.find(target, found_pos)) != std::basic_string::npos ) + while( (found_pos = string.find(target, found_pos)) != string_type::npos ) { string.replace( found_pos, target.length(), replacement ); found_pos += replacement.length(); // avoid infinite defeat if replacement contains target @@ -959,7 +967,7 @@ void LLStringUtilBase::replaceString( std::basic_string& string, std::basi //static template -void LLStringUtilBase::replaceNonstandardASCII( std::basic_string& string, T replacement ) +void LLStringUtilBase::replaceNonstandardASCII( string_type& string, T replacement ) { const char LF = 10; const S8 MIN = 32; @@ -979,12 +987,12 @@ void LLStringUtilBase::replaceNonstandardASCII( std::basic_string& string, //static template -void LLStringUtilBase::replaceTabsWithSpaces( std::basic_string& str, size_type spaces_per_tab ) +void LLStringUtilBase::replaceTabsWithSpaces( string_type& str, size_type spaces_per_tab ) { const T TAB = '\t'; const T SPACE = ' '; - std::basic_string out_str; + string_type out_str; // Replace tabs with spaces for (size_type i = 0; i < str.length(); i++) { @@ -1003,7 +1011,7 @@ void LLStringUtilBase::replaceTabsWithSpaces( std::basic_string& str, size //static template -BOOL LLStringUtilBase::containsNonprintable(const std::basic_string& string) +BOOL LLStringUtilBase::containsNonprintable(const string_type& string) { const char MIN = 32; BOOL rv = FALSE; @@ -1020,7 +1028,7 @@ BOOL LLStringUtilBase::containsNonprintable(const std::basic_string& strin //static template -void LLStringUtilBase::stripNonprintable(std::basic_string& string) +void LLStringUtilBase::stripNonprintable(string_type& string) { const char MIN = 32; size_type j = 0; @@ -1051,8 +1059,33 @@ void LLStringUtilBase::stripNonprintable(std::basic_string& string) delete []c_string; } +template +std::basic_string LLStringUtilBase::quote(const string_type& str, const string_type& escape) +{ + size_type len(str.length()); + // If the string is already quoted, assume user knows what s/he's doing. + if (len >= 2 && str[0] == '"' && str[len-1] == '"') + { + return str; + } + + // Not already quoted: do it. + string_type result; + result.push_back('"'); + for (typename string_type::const_iterator ci(str.begin()), cend(str.end()); ci != cend; ++ci) + { + if (*ci == '"') + { + result.append(escape); + } + result.push_back(*ci); + } + result.push_back('"'); + return result; +} + template -void LLStringUtilBase::_makeASCII(std::basic_string& string) +void LLStringUtilBase::_makeASCII(string_type& string) { // Replace non-ASCII chars with LL_UNKNOWN_CHAR for (size_type i = 0; i < string.length(); i++) @@ -1082,7 +1115,7 @@ void LLStringUtilBase::copy( T* dst, const T* src, size_type dst_size ) // static template -void LLStringUtilBase::copyInto(std::basic_string& dst, const std::basic_string& src, size_type offset) +void LLStringUtilBase::copyInto(string_type& dst, const string_type& src, size_type offset) { if ( offset == dst.length() ) { @@ -1092,7 +1125,7 @@ void LLStringUtilBase::copyInto(std::basic_string& dst, const std::basic_s } else { - std::basic_string tail = dst.substr(offset); + string_type tail = dst.substr(offset); dst = dst.substr(0, offset); dst += src; @@ -1103,7 +1136,7 @@ void LLStringUtilBase::copyInto(std::basic_string& dst, const std::basic_s // True if this is the head of s. //static template -BOOL LLStringUtilBase::isHead( const std::basic_string& string, const T* s ) +BOOL LLStringUtilBase::isHead( const string_type& string, const T* s ) { if( string.empty() ) { @@ -1119,8 +1152,8 @@ BOOL LLStringUtilBase::isHead( const std::basic_string& string, const T* s // static template bool LLStringUtilBase::startsWith( - const std::basic_string& string, - const std::basic_string& substr) + const string_type& string, + const string_type& substr) { if(string.empty() || (substr.empty())) return false; if(0 == string.find(substr)) return true; @@ -1130,8 +1163,8 @@ bool LLStringUtilBase::startsWith( // static template bool LLStringUtilBase::endsWith( - const std::basic_string& string, - const std::basic_string& substr) + const string_type& string, + const string_type& substr) { if(string.empty() || (substr.empty())) return false; std::string::size_type idx = string.rfind(substr); @@ -1141,14 +1174,14 @@ bool LLStringUtilBase::endsWith( template -BOOL LLStringUtilBase::convertToBOOL(const std::basic_string& string, BOOL& value) +BOOL LLStringUtilBase::convertToBOOL(const string_type& string, BOOL& value) { if( string.empty() ) { return FALSE; } - std::basic_string temp( string ); + string_type temp( string ); trim(temp); if( (temp == "1") || @@ -1178,7 +1211,7 @@ BOOL LLStringUtilBase::convertToBOOL(const std::basic_string& string, BOOL } template -BOOL LLStringUtilBase::convertToU8(const std::basic_string& string, U8& value) +BOOL LLStringUtilBase::convertToU8(const string_type& string, U8& value) { S32 value32 = 0; BOOL success = convertToS32(string, value32); @@ -1191,7 +1224,7 @@ BOOL LLStringUtilBase::convertToU8(const std::basic_string& string, U8& va } template -BOOL LLStringUtilBase::convertToS8(const std::basic_string& string, S8& value) +BOOL LLStringUtilBase::convertToS8(const string_type& string, S8& value) { S32 value32 = 0; BOOL success = convertToS32(string, value32); @@ -1204,7 +1237,7 @@ BOOL LLStringUtilBase::convertToS8(const std::basic_string& string, S8& va } template -BOOL LLStringUtilBase::convertToS16(const std::basic_string& string, S16& value) +BOOL LLStringUtilBase::convertToS16(const string_type& string, S16& value) { S32 value32 = 0; BOOL success = convertToS32(string, value32); @@ -1217,7 +1250,7 @@ BOOL LLStringUtilBase::convertToS16(const std::basic_string& string, S16& } template -BOOL LLStringUtilBase::convertToU16(const std::basic_string& string, U16& value) +BOOL LLStringUtilBase::convertToU16(const string_type& string, U16& value) { S32 value32 = 0; BOOL success = convertToS32(string, value32); @@ -1230,17 +1263,17 @@ BOOL LLStringUtilBase::convertToU16(const std::basic_string& string, U16& } template -BOOL LLStringUtilBase::convertToU32(const std::basic_string& string, U32& value) +BOOL LLStringUtilBase::convertToU32(const string_type& string, U32& value) { if( string.empty() ) { return FALSE; } - std::basic_string temp( string ); + string_type temp( string ); trim(temp); U32 v; - std::basic_istringstream i_stream((std::basic_string)temp); + std::basic_istringstream i_stream((string_type)temp); if(i_stream >> v) { value = v; @@ -1250,17 +1283,17 @@ BOOL LLStringUtilBase::convertToU32(const std::basic_string& string, U32& } template -BOOL LLStringUtilBase::convertToS32(const std::basic_string& string, S32& value) +BOOL LLStringUtilBase::convertToS32(const string_type& string, S32& value) { if( string.empty() ) { return FALSE; } - std::basic_string temp( string ); + string_type temp( string ); trim(temp); S32 v; - std::basic_istringstream i_stream((std::basic_string)temp); + std::basic_istringstream i_stream((string_type)temp); if(i_stream >> v) { //TODO: figure out overflow and underflow reporting here @@ -1277,7 +1310,7 @@ BOOL LLStringUtilBase::convertToS32(const std::basic_string& string, S32& } template -BOOL LLStringUtilBase::convertToF32(const std::basic_string& string, F32& value) +BOOL LLStringUtilBase::convertToF32(const string_type& string, F32& value) { F64 value64 = 0.0; BOOL success = convertToF64(string, value64); @@ -1290,17 +1323,17 @@ BOOL LLStringUtilBase::convertToF32(const std::basic_string& string, F32& } template -BOOL LLStringUtilBase::convertToF64(const std::basic_string& string, F64& value) +BOOL LLStringUtilBase::convertToF64(const string_type& string, F64& value) { if( string.empty() ) { return FALSE; } - std::basic_string temp( string ); + string_type temp( string ); trim(temp); F64 v; - std::basic_istringstream i_stream((std::basic_string)temp); + std::basic_istringstream i_stream((string_type)temp); if(i_stream >> v) { //TODO: figure out overflow and underflow reporting here @@ -1317,7 +1350,7 @@ BOOL LLStringUtilBase::convertToF64(const std::basic_string& string, F64& } template -void LLStringUtilBase::truncate(std::basic_string& string, size_type count) +void LLStringUtilBase::truncate(string_type& string, size_type count) { size_type cur_size = string.size(); string.resize(count < cur_size ? count : cur_size); -- cgit v1.2.3 From da5d243c8f76f43a6bb4000402fade76eee0be33 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Mon, 23 Jan 2012 17:29:42 -0500 Subject: LLStringUtil methods are conventionally static. --- indra/llcommon/llstring.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/llcommon/llstring.h') diff --git a/indra/llcommon/llstring.h b/indra/llcommon/llstring.h index d3f1d01aa2..4c3936f9ab 100644 --- a/indra/llcommon/llstring.h +++ b/indra/llcommon/llstring.h @@ -307,7 +307,7 @@ public: * quote it, escape any embedded double-quote with the escape string (default * backslash). */ - string_type quote(const string_type& str, const string_type& escape="\\"); + static string_type quote(const string_type& str, const string_type& escape="\\"); /** * @brief Unsafe way to make ascii characters. You should probably -- cgit v1.2.3 From 27df0a84564d3a886661aae0faae74c2157cd31b Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Fri, 27 Jan 2012 23:46:00 -0500 Subject: On Windows, only quote LLProcess arguments if they seem to need it. On Posix platforms, the OS argument mechanism makes quoting/reparsing unnecessary anyway, so this only affects Windows. Add optional 'triggers' parameter to LLStringUtils::quote() (default: space and double-quote). Only if the passed string contains a character in 'triggers' will it be double-quoted. This is observed to fix a Windows-specific problem in which plugin child process would fail to start because it wasn't expecting a quoted number. Use LLStringUtils::quote() more consistently in LLProcess implementation for logging. --- indra/llcommon/llstring.h | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) (limited to 'indra/llcommon/llstring.h') diff --git a/indra/llcommon/llstring.h b/indra/llcommon/llstring.h index 4c3936f9ab..7b24b5e279 100644 --- a/indra/llcommon/llstring.h +++ b/indra/llcommon/llstring.h @@ -303,11 +303,17 @@ public: static void stripNonprintable(string_type& string); /** - * Double-quote an argument string, unless it's already double-quoted. If we - * quote it, escape any embedded double-quote with the escape string (default + * Double-quote an argument string if needed, unless it's already + * double-quoted. Decide whether it's needed based on the presence of any + * character in @a triggers (default space or double-quote). If we quote + * it, escape any embedded double-quote with the @a escape string (default * backslash). + * + * Passing triggers="" means always quote, unless it's already double-quoted. */ - static string_type quote(const string_type& str, const string_type& escape="\\"); + static string_type quote(const string_type& str, + const string_type& triggers=" \"", + const string_type& escape="\\"); /** * @brief Unsafe way to make ascii characters. You should probably @@ -1060,7 +1066,9 @@ void LLStringUtilBase::stripNonprintable(string_type& string) } template -std::basic_string LLStringUtilBase::quote(const string_type& str, const string_type& escape) +std::basic_string LLStringUtilBase::quote(const string_type& str, + const string_type& triggers, + const string_type& escape) { size_type len(str.length()); // If the string is already quoted, assume user knows what s/he's doing. @@ -1069,7 +1077,15 @@ std::basic_string LLStringUtilBase::quote(const string_type& str, const st return str; } - // Not already quoted: do it. + // Not already quoted: do we need to? triggers.empty() is a special case + // meaning "always quote." + if ((! triggers.empty()) && str.find_first_of(triggers) == string_type::npos) + { + // no trigger characters, don't bother quoting + return str; + } + + // For whatever reason, we must quote this string. string_type result; result.push_back('"'); for (typename string_type::const_iterator ci(str.begin()), cend(str.end()); ci != cend; ++ci) -- cgit v1.2.3 From 025329b6a2ecb8ddee3022d6a73344f862f0d326 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Fri, 24 Feb 2012 15:06:44 -0500 Subject: Add LLStringUtil::getTokens() overload handling quoted substrings. We didn't have any tokenizer suitable for scanning something like a bash command line. We do have a couple hacks, e.g. LLExternalEditor::tokenize() and LLCommandLineParser::parseCommandLineString(). Both try to work around boost::tokenizer limitations; but existing boost::tokenizer support just doesn't address this case. Neither of the above is available as a general scanner anyway, and parseCommandLineString() fails outright when passed "". New getTokens() also distinguishes between "drop delimiters" (e.g. space, return, newline) to be discarded from the token stream, versus "keep delimiters" (e.g. "+-*/") to be returned as tokens in their own right. There's an overload that honors escapes and a more efficient one that doesn't; each has a convenience overload that returns the scanned string vector rather than requiring a separate declaration. Tweak and comment older getTokens() implementation. Add unit tests for both old and new getTokens() implementations. Break out StringVec and std::ostream << StringVec from indra/llcommon/tests/listener.h to StringVec.h: that's coming in handy for a number of different TUT test sources. --- indra/llcommon/llstring.h | 355 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 353 insertions(+), 2 deletions(-) (limited to 'indra/llcommon/llstring.h') diff --git a/indra/llcommon/llstring.h b/indra/llcommon/llstring.h index 7b24b5e279..e4ae54cec5 100644 --- a/indra/llcommon/llstring.h +++ b/indra/llcommon/llstring.h @@ -40,6 +40,7 @@ #endif #include +#include #if LL_SOLARIS // stricmp and strnicmp do not exist on Solaris: @@ -247,7 +248,38 @@ public: static const string_type null; typedef std::map format_map_t; - LL_COMMON_API static void getTokens(const string_type& instr, std::vector& tokens, const string_type& delims); + /// considers any sequence of delims as a single field separator + LL_COMMON_API static void getTokens(const string_type& instr, + std::vector& tokens, + const string_type& delims); + /// like simple scan overload, but returns scanned vector + LL_COMMON_API static std::vector getTokens(const string_type& instr, + const string_type& delims); + /// add support for keep_delims and quotes (either could be empty string) + LL_COMMON_API static void getTokens(const string_type& instr, + std::vector& tokens, + const string_type& drop_delims, + const string_type& keep_delims, + const string_type& quotes=string_type()); + /// like keep_delims-and-quotes overload, but returns scanned vector + LL_COMMON_API static std::vector getTokens(const string_type& instr, + const string_type& drop_delims, + const string_type& keep_delims, + const string_type& quotes=string_type()); + /// add support for escapes (could be empty string) + LL_COMMON_API static void getTokens(const string_type& instr, + std::vector& tokens, + const string_type& drop_delims, + const string_type& keep_delims, + const string_type& quotes, + const string_type& escapes); + /// like escapes overload, but returns scanned vector + LL_COMMON_API static std::vector getTokens(const string_type& instr, + const string_type& drop_delims, + const string_type& keep_delims, + const string_type& quotes, + const string_type& escapes); + LL_COMMON_API static void formatNumber(string_type& numStr, string_type decimals); LL_COMMON_API static bool formatDatetime(string_type& replacement, string_type token, string_type param, S32 secFromEpoch); LL_COMMON_API static S32 format(string_type& s, const format_map_t& substitutions); @@ -262,6 +294,11 @@ public: return !string.empty() && (0 <= i) && (i <= string.size()); } + static bool contains(const string_type& string, T c, size_type i=0) + { + return string.find(c, i) != string_type::npos; + } + static void trimHead(string_type& string); static void trimTail(string_type& string); static void trim(string_type& string) { trimHead(string); trimTail(string); } @@ -650,10 +687,324 @@ namespace LLStringFn //////////////////////////////////////////////////////////// // NOTE: LLStringUtil::format, getTokens, and support functions moved to llstring.cpp. // There is no LLWStringUtil::format implementation currently. -// Calling thse for anything other than LLStringUtil will produce link errors. +// Calling these for anything other than LLStringUtil will produce link errors. //////////////////////////////////////////////////////////// +// static +template +std::vector::string_type> +LLStringUtilBase::getTokens(const string_type& instr, const string_type& delims) +{ + std::vector tokens; + getTokens(instr, tokens, delims); + return tokens; +} + +// static +template +std::vector::string_type> +LLStringUtilBase::getTokens(const string_type& instr, + const string_type& drop_delims, + const string_type& keep_delims, + const string_type& quotes) +{ + std::vector tokens; + getTokens(instr, tokens, drop_delims, keep_delims, quotes); + return tokens; +} + +// static +template +std::vector::string_type> +LLStringUtilBase::getTokens(const string_type& instr, + const string_type& drop_delims, + const string_type& keep_delims, + const string_type& quotes, + const string_type& escapes) +{ + std::vector tokens; + getTokens(instr, tokens, drop_delims, keep_delims, quotes, escapes); + return tokens; +} + +namespace LLStringUtilBaseImpl +{ + +/** + * Input string scanner helper for getTokens(), or really any other + * character-parsing routine that may have to deal with escape characters. + * This implementation defines the concept (also an interface, should you + * choose to implement the concept by subclassing) and provides trivial + * implementations for a string @em without escape processing. + */ +template +struct InString +{ + typedef std::basic_string string_type; + typedef typename string_type::const_iterator const_iterator; + + InString(const_iterator b, const_iterator e): + iter(b), + end(e) + {} + + bool done() const { return iter == end; } + /// Is the current character (*iter) escaped? This implementation can + /// answer trivially because it doesn't support escapes. + virtual bool escaped() const { return false; } + /// Obtain the current character and advance @c iter. + virtual T next() { return *iter++; } + /// Does the current character match specified character? + virtual bool is(T ch) const { return (! done()) && *iter == ch; } + /// Is the current character any one of the specified characters? + virtual bool oneof(const string_type& delims) const + { + return (! done()) && LLStringUtilBase::contains(delims, *iter); + } + + /** + * Scan forward from @from until either @a delim or end. This is primarily + * useful for processing quoted substrings. + * + * If we do see @a delim, append everything from @from until (excluding) + * @a delim to @a into, advance @c iter to skip @a delim, and return @c + * true. + * + * If we do not see @a delim, do not alter @a into or @c iter and return + * @c false. Do not pass GO, do not collect $200. + * + * @note The @c false case described above implements normal getTokens() + * treatment of an unmatched open quote: treat the quote character as if + * escaped, that is, simply collect it as part of the current token. Other + * plausible behaviors directly affect the way getTokens() deals with an + * unmatched quote: e.g. throwing an exception to treat it as an error, or + * assuming a close quote beyond end of string (in which case return @c + * true). + */ + virtual bool collect_until(string_type& into, const_iterator from, T delim) + { + const_iterator found = std::find(from, end, delim); + // If we didn't find delim, change nothing, just tell caller. + if (found == end) + return false; + // Found delim! Append everything between from and found. + into.append(from, found); + // advance past delim in input + iter = found + 1; + return true; + } + + const_iterator iter, end; +}; + +/// InString subclass that handles escape characters +template +class InEscString: public InString +{ +public: + typedef InString super; + typedef typename super::string_type string_type; + typedef typename super::const_iterator const_iterator; + using super::done; + using super::iter; + using super::end; + + InEscString(const_iterator b, const_iterator e, const string_type& escapes_): + super(b, e), + escapes(escapes_) + { + // Even though we've already initialized 'iter' via our base-class + // constructor, set it again to check for initial escape char. + setiter(b); + } + + /// This implementation uses the answer cached by setiter(). + virtual bool escaped() const { return isesc; } + virtual T next() + { + // If we're looking at the escape character of an escape sequence, + // skip that character. This is the one time we can modify 'iter' + // without using setiter: for this one case we DO NOT CARE if the + // escaped character is itself an escape. + if (isesc) + ++iter; + // If we were looking at an escape character, this is the escaped + // character; otherwise it's just the next character. + T result(*iter); + // Advance iter, checking for escape sequence. + setiter(iter + 1); + return result; + } + + virtual bool is(T ch) const + { + // Like base-class is(), except that an escaped character matches + // nothing. + return (! done()) && (! isesc) && *iter == ch; + } + + virtual bool oneof(const string_type& delims) const + { + // Like base-class oneof(), except that an escaped character matches + // nothing. + return (! done()) && (! isesc) && LLStringUtilBase::contains(delims, *iter); + } + + virtual bool collect_until(string_type& into, const_iterator from, T delim) + { + // Deal with escapes in the characters we collect; that is, an escaped + // character must become just that character without the preceding + // escape. Collect characters in a separate string rather than + // directly appending to 'into' in case we do not find delim, in which + // case we're supposed to leave 'into' unmodified. + string_type collected; + // For scanning purposes, we're going to work directly with 'iter'. + // Save its current value in case we fail to see delim. + const_iterator save_iter(iter); + // Okay, set 'iter', checking for escape. + setiter(from); + while (! done()) + { + // If we see an unescaped delim, stop and report success. + if ((! isesc) && *iter == delim) + { + // Append collected chars to 'into'. + into.append(collected); + // Don't forget to advance 'iter' past delim. + setiter(iter + 1); + return true; + } + // We're not at end, and either we're not looking at delim or it's + // escaped. Collect this character and keep going. + collected.push_back(next()); + } + // Here we hit 'end' without ever seeing delim. Restore iter and tell + // caller. + setiter(save_iter); + return false; + } + +private: + void setiter(const_iterator i) + { + iter = i; + + // Every time we change 'iter', set 'isesc' to be able to repetitively + // answer escaped() without having to rescan 'escapes'. isesc caches + // contains(escapes, *iter). + + // We're looking at an escaped char if we're not already at end (that + // is, *iter is even meaningful); if *iter is in fact one of the + // specified escape characters; and if there's one more character + // following it. That is, if an escape character is the very last + // character of the input string, it loses its special meaning. + isesc = (! done()) && + LLStringUtilBase::contains(escapes, *iter) && + (iter+1) != end; + } + + const string_type escapes; + bool isesc; +}; + +/// getTokens() implementation based on InString concept +template +void getTokens(INSTRING& instr, std::vector& tokens, + const string_type& drop_delims, const string_type& keep_delims, + const string_type& quotes) +{ + // There are times when we want to match either drop_delims or + // keep_delims. Concatenate them up front to speed things up. + string_type all_delims(drop_delims + keep_delims); + // no tokens yet + tokens.clear(); + + // try for another token + while (! instr.done()) + { + // scan past any drop_delims + while (instr.oneof(drop_delims)) + { + // skip this drop_delim + instr.next(); + // but if that was the end of the string, done + if (instr.done()) + return; + } + // found the start of another token: make a slot for it + tokens.push_back(string_type()); + if (instr.oneof(keep_delims)) + { + // *iter is a keep_delim, a token of exactly 1 character. Append + // that character to the new token and proceed. + tokens.back().push_back(instr.next()); + continue; + } + // Here we have a non-delimiter token, which might consist of a mix of + // quoted and unquoted parts. Use bash rules for quoting: you can + // embed a quoted substring in the midst of an unquoted token (e.g. + // ~/"sub dir"/myfile.txt); you can ram two quoted substrings together + // to make a single token (e.g. 'He said, "'"Don't."'"'). We diverge + // from bash in that bash considers an unmatched quote an error. Our + // param signature doesn't allow for errors, so just pretend it's not + // a quote and embed it. + // At this level, keep scanning until we hit the next delimiter of + // either type (drop_delims or keep_delims). + while (! instr.oneof(all_delims)) + { + // If we're looking at an open quote, search forward for + // a close quote, collecting characters along the way. + if (instr.oneof(quotes) && + instr.collect_until(tokens.back(), instr.iter+1, *instr.iter)) + { + // collect_until is cleverly designed to do exactly what we + // need here. No further action needed if it returns true. + } + else + { + // Either *iter isn't a quote, or there's no matching close + // quote: in other words, just an ordinary char. Append it to + // current token. + tokens.back().push_back(instr.next()); + } + // having scanned that segment of this token, if we've reached the + // end of the string, we're done + if (instr.done()) + return; + } + } +} + +} // namespace LLStringUtilBaseImpl + +// static +template +void LLStringUtilBase::getTokens(const string_type& string, std::vector& tokens, + const string_type& drop_delims, const string_type& keep_delims, + const string_type& quotes) +{ + // Because this overload doesn't support escapes, use simple InString to + // manage input range. + LLStringUtilBaseImpl::InString instring(string.begin(), string.end()); + LLStringUtilBaseImpl::getTokens(instring, tokens, drop_delims, keep_delims, quotes); +} + +// static +template +void LLStringUtilBase::getTokens(const string_type& string, std::vector& tokens, + const string_type& drop_delims, const string_type& keep_delims, + const string_type& quotes, const string_type& escapes) +{ + // This overload must deal with escapes. Delegate that to InEscString + // (unless there ARE no escapes). + boost::scoped_ptr< LLStringUtilBaseImpl::InString > instrp; + if (escapes.empty()) + instrp.reset(new LLStringUtilBaseImpl::InString(string.begin(), string.end())); + else + instrp.reset(new LLStringUtilBaseImpl::InEscString(string.begin(), string.end(), escapes)); + LLStringUtilBaseImpl::getTokens(*instrp, tokens, drop_delims, keep_delims, quotes); +} // static template -- cgit v1.2.3 From 4edf93d6d991af3f1aa0aba764388ad52ab1464b Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Fri, 24 Feb 2012 16:50:47 -0500 Subject: "Then there's Windows..." Fix llstring.h to build there too. --- indra/llcommon/llstring.h | 45 +++++++++++++++++++++++---------------------- 1 file changed, 23 insertions(+), 22 deletions(-) (limited to 'indra/llcommon/llstring.h') diff --git a/indra/llcommon/llstring.h b/indra/llcommon/llstring.h index e4ae54cec5..5085d32f7f 100644 --- a/indra/llcommon/llstring.h +++ b/indra/llcommon/llstring.h @@ -253,32 +253,32 @@ public: std::vector& tokens, const string_type& delims); /// like simple scan overload, but returns scanned vector - LL_COMMON_API static std::vector getTokens(const string_type& instr, - const string_type& delims); + static std::vector getTokens(const string_type& instr, + const string_type& delims); /// add support for keep_delims and quotes (either could be empty string) - LL_COMMON_API static void getTokens(const string_type& instr, - std::vector& tokens, - const string_type& drop_delims, - const string_type& keep_delims, - const string_type& quotes=string_type()); + static void getTokens(const string_type& instr, + std::vector& tokens, + const string_type& drop_delims, + const string_type& keep_delims, + const string_type& quotes=string_type()); /// like keep_delims-and-quotes overload, but returns scanned vector - LL_COMMON_API static std::vector getTokens(const string_type& instr, - const string_type& drop_delims, - const string_type& keep_delims, - const string_type& quotes=string_type()); + static std::vector getTokens(const string_type& instr, + const string_type& drop_delims, + const string_type& keep_delims, + const string_type& quotes=string_type()); /// add support for escapes (could be empty string) - LL_COMMON_API static void getTokens(const string_type& instr, - std::vector& tokens, - const string_type& drop_delims, - const string_type& keep_delims, - const string_type& quotes, - const string_type& escapes); + static void getTokens(const string_type& instr, + std::vector& tokens, + const string_type& drop_delims, + const string_type& keep_delims, + const string_type& quotes, + const string_type& escapes); /// like escapes overload, but returns scanned vector - LL_COMMON_API static std::vector getTokens(const string_type& instr, - const string_type& drop_delims, - const string_type& keep_delims, - const string_type& quotes, - const string_type& escapes); + static std::vector getTokens(const string_type& instr, + const string_type& drop_delims, + const string_type& keep_delims, + const string_type& quotes, + const string_type& escapes); LL_COMMON_API static void formatNumber(string_type& numStr, string_type decimals); LL_COMMON_API static bool formatDatetime(string_type& replacement, string_type token, string_type param, S32 secFromEpoch); @@ -748,6 +748,7 @@ struct InString iter(b), end(e) {} + virtual ~InString() {} bool done() const { return iter == end; } /// Is the current character (*iter) escaped? This implementation can -- cgit v1.2.3 From 8815cfa5c916ac454cfa5b6f22f9ce312b00a846 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Fri, 23 Mar 2012 15:53:44 -0400 Subject: Rename In[Esc]String helper-class data members, per code review. --- indra/llcommon/llstring.h | 92 +++++++++++++++++++++++------------------------ 1 file changed, 46 insertions(+), 46 deletions(-) (limited to 'indra/llcommon/llstring.h') diff --git a/indra/llcommon/llstring.h b/indra/llcommon/llstring.h index 5085d32f7f..09733e8e2a 100644 --- a/indra/llcommon/llstring.h +++ b/indra/llcommon/llstring.h @@ -745,23 +745,23 @@ struct InString typedef typename string_type::const_iterator const_iterator; InString(const_iterator b, const_iterator e): - iter(b), - end(e) + mIter(b), + mEnd(e) {} virtual ~InString() {} - bool done() const { return iter == end; } - /// Is the current character (*iter) escaped? This implementation can + bool done() const { return mIter == mEnd; } + /// Is the current character (*mIter) escaped? This implementation can /// answer trivially because it doesn't support escapes. virtual bool escaped() const { return false; } - /// Obtain the current character and advance @c iter. - virtual T next() { return *iter++; } + /// Obtain the current character and advance @c mIter. + virtual T next() { return *mIter++; } /// Does the current character match specified character? - virtual bool is(T ch) const { return (! done()) && *iter == ch; } + virtual bool is(T ch) const { return (! done()) && *mIter == ch; } /// Is the current character any one of the specified characters? virtual bool oneof(const string_type& delims) const { - return (! done()) && LLStringUtilBase::contains(delims, *iter); + return (! done()) && LLStringUtilBase::contains(delims, *mIter); } /** @@ -769,10 +769,10 @@ struct InString * useful for processing quoted substrings. * * If we do see @a delim, append everything from @from until (excluding) - * @a delim to @a into, advance @c iter to skip @a delim, and return @c + * @a delim to @a into, advance @c mIter to skip @a delim, and return @c * true. * - * If we do not see @a delim, do not alter @a into or @c iter and return + * If we do not see @a delim, do not alter @a into or @c mIter and return * @c false. Do not pass GO, do not collect $200. * * @note The @c false case described above implements normal getTokens() @@ -785,18 +785,18 @@ struct InString */ virtual bool collect_until(string_type& into, const_iterator from, T delim) { - const_iterator found = std::find(from, end, delim); + const_iterator found = std::find(from, mEnd, delim); // If we didn't find delim, change nothing, just tell caller. - if (found == end) + if (found == mEnd) return false; // Found delim! Append everything between from and found. into.append(from, found); // advance past delim in input - iter = found + 1; + mIter = found + 1; return true; } - const_iterator iter, end; + const_iterator mIter, mEnd; }; /// InString subclass that handles escape characters @@ -808,33 +808,33 @@ public: typedef typename super::string_type string_type; typedef typename super::const_iterator const_iterator; using super::done; - using super::iter; - using super::end; + using super::mIter; + using super::mEnd; - InEscString(const_iterator b, const_iterator e, const string_type& escapes_): + InEscString(const_iterator b, const_iterator e, const string_type& escapes): super(b, e), - escapes(escapes_) + mEscapes(escapes) { - // Even though we've already initialized 'iter' via our base-class + // Even though we've already initialized 'mIter' via our base-class // constructor, set it again to check for initial escape char. setiter(b); } /// This implementation uses the answer cached by setiter(). - virtual bool escaped() const { return isesc; } + virtual bool escaped() const { return mIsEsc; } virtual T next() { // If we're looking at the escape character of an escape sequence, - // skip that character. This is the one time we can modify 'iter' + // skip that character. This is the one time we can modify 'mIter' // without using setiter: for this one case we DO NOT CARE if the // escaped character is itself an escape. - if (isesc) - ++iter; + if (mIsEsc) + ++mIter; // If we were looking at an escape character, this is the escaped // character; otherwise it's just the next character. - T result(*iter); - // Advance iter, checking for escape sequence. - setiter(iter + 1); + T result(*mIter); + // Advance mIter, checking for escape sequence. + setiter(mIter + 1); return result; } @@ -842,14 +842,14 @@ public: { // Like base-class is(), except that an escaped character matches // nothing. - return (! done()) && (! isesc) && *iter == ch; + return (! done()) && (! mIsEsc) && *mIter == ch; } virtual bool oneof(const string_type& delims) const { // Like base-class oneof(), except that an escaped character matches // nothing. - return (! done()) && (! isesc) && LLStringUtilBase::contains(delims, *iter); + return (! done()) && (! mIsEsc) && LLStringUtilBase::contains(delims, *mIter); } virtual bool collect_until(string_type& into, const_iterator from, T delim) @@ -860,27 +860,27 @@ public: // directly appending to 'into' in case we do not find delim, in which // case we're supposed to leave 'into' unmodified. string_type collected; - // For scanning purposes, we're going to work directly with 'iter'. + // For scanning purposes, we're going to work directly with 'mIter'. // Save its current value in case we fail to see delim. - const_iterator save_iter(iter); - // Okay, set 'iter', checking for escape. + const_iterator save_iter(mIter); + // Okay, set 'mIter', checking for escape. setiter(from); while (! done()) { // If we see an unescaped delim, stop and report success. - if ((! isesc) && *iter == delim) + if ((! mIsEsc) && *mIter == delim) { // Append collected chars to 'into'. into.append(collected); - // Don't forget to advance 'iter' past delim. - setiter(iter + 1); + // Don't forget to advance 'mIter' past delim. + setiter(mIter + 1); return true; } // We're not at end, and either we're not looking at delim or it's // escaped. Collect this character and keep going. collected.push_back(next()); } - // Here we hit 'end' without ever seeing delim. Restore iter and tell + // Here we hit 'mEnd' without ever seeing delim. Restore mIter and tell // caller. setiter(save_iter); return false; @@ -889,24 +889,24 @@ public: private: void setiter(const_iterator i) { - iter = i; + mIter = i; - // Every time we change 'iter', set 'isesc' to be able to repetitively - // answer escaped() without having to rescan 'escapes'. isesc caches - // contains(escapes, *iter). + // Every time we change 'mIter', set 'mIsEsc' to be able to repetitively + // answer escaped() without having to rescan 'mEscapes'. mIsEsc caches + // contains(mEscapes, *mIter). // We're looking at an escaped char if we're not already at end (that - // is, *iter is even meaningful); if *iter is in fact one of the + // is, *mIter is even meaningful); if *mIter is in fact one of the // specified escape characters; and if there's one more character // following it. That is, if an escape character is the very last // character of the input string, it loses its special meaning. - isesc = (! done()) && - LLStringUtilBase::contains(escapes, *iter) && - (iter+1) != end; + mIsEsc = (! done()) && + LLStringUtilBase::contains(mEscapes, *mIter) && + (mIter+1) != mEnd; } - const string_type escapes; - bool isesc; + const string_type mEscapes; + bool mIsEsc; }; /// getTokens() implementation based on InString concept @@ -957,7 +957,7 @@ void getTokens(INSTRING& instr, std::vector& tokens, // If we're looking at an open quote, search forward for // a close quote, collecting characters along the way. if (instr.oneof(quotes) && - instr.collect_until(tokens.back(), instr.iter+1, *instr.iter)) + instr.collect_until(tokens.back(), instr.mIter+1, *instr.mIter)) { // collect_until is cleverly designed to do exactly what we // need here. No further action needed if it returns true. -- cgit v1.2.3 From bf6182daa8b4d7cea79310547f71d7a3155e17b0 Mon Sep 17 00:00:00 2001 From: Graham Madarasz Date: Fri, 29 Mar 2013 07:50:08 -0700 Subject: Update Mac and Windows breakpad builds to latest --- indra/llcommon/llstring.h | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 indra/llcommon/llstring.h (limited to 'indra/llcommon/llstring.h') diff --git a/indra/llcommon/llstring.h b/indra/llcommon/llstring.h old mode 100644 new mode 100755 -- cgit v1.2.3 From 892f3cdd2c4d1b6aa9ec86547022d9f8194d6b80 Mon Sep 17 00:00:00 2001 From: Gilbert Gonzales Date: Wed, 22 May 2013 06:26:54 -0400 Subject: CHUI-967: fix display of % escapes in chat --- indra/llcommon/llstring.h | 1 + 1 file changed, 1 insertion(+) (limited to 'indra/llcommon/llstring.h') diff --git a/indra/llcommon/llstring.h b/indra/llcommon/llstring.h index 119efc7957..f9702868c8 100755 --- a/indra/llcommon/llstring.h +++ b/indra/llcommon/llstring.h @@ -470,6 +470,7 @@ inline std::string chop_tail_copy( * @brief This translates a nybble stored as a hex value from 0-f back * to a nybble in the low order bits of the return byte. */ +LL_COMMON_API bool is_char_hex(char hex); LL_COMMON_API U8 hex_as_nybble(char hex); /** -- cgit v1.2.3