00001
00032 #ifndef LL_LLSTRING_H
00033 #define LL_LLSTRING_H
00034
00035 #if LL_LINUX || LL_SOLARIS
00036 #include <wctype.h>
00037 #include <wchar.h>
00038 #endif
00039
00040 const char LL_UNKNOWN_CHAR = '?';
00041
00042 class LLVector3;
00043 class LLVector3d;
00044 class LLQuaternion;
00045 class LLUUID;
00046 class LLColor4;
00047 class LLColor4U;
00048
00049 #if (LL_DARWIN || LL_SOLARIS || (LL_LINUX && __GNUC__ > 2))
00050
00051 namespace std
00052 {
00053 template<>
00054 struct char_traits<U16>
00055 {
00056 typedef U16 char_type;
00057 typedef int int_type;
00058 typedef streampos pos_type;
00059 typedef streamoff off_type;
00060 typedef mbstate_t state_type;
00061
00062 static void
00063 assign(char_type& __c1, const char_type& __c2)
00064 { __c1 = __c2; }
00065
00066 static bool
00067 eq(const char_type& __c1, const char_type& __c2)
00068 { return __c1 == __c2; }
00069
00070 static bool
00071 lt(const char_type& __c1, const char_type& __c2)
00072 { return __c1 < __c2; }
00073
00074 static int
00075 compare(const char_type* __s1, const char_type* __s2, size_t __n)
00076 { return memcmp(__s1, __s2, __n * sizeof(char_type)); }
00077
00078 static size_t
00079 length(const char_type* __s)
00080 {
00081 const char_type *cur_char = __s;
00082 while (*cur_char != 0)
00083 {
00084 ++cur_char;
00085 }
00086 return cur_char - __s;
00087 }
00088
00089 static const char_type*
00090 find(const char_type* __s, size_t __n, const char_type& __a)
00091 { return static_cast<const char_type*>(memchr(__s, __a, __n * sizeof(char_type))); }
00092
00093 static char_type*
00094 move(char_type* __s1, const char_type* __s2, size_t __n)
00095 { return static_cast<char_type*>(memmove(__s1, __s2, __n * sizeof(char_type))); }
00096
00097 static char_type*
00098 copy(char_type* __s1, const char_type* __s2, size_t __n)
00099 { return static_cast<char_type*>(memcpy(__s1, __s2, __n * sizeof(char_type))); }
00100
00101 static char_type*
00102 assign(char_type* __s, size_t __n, char_type __a)
00103 {
00104
00105
00106
00107
00108
00109
00110 size_t __i;
00111 for(__i = 0; __i < __n; __i++)
00112 {
00113 __s[__i] = __a;
00114 }
00115 return __s;
00116 }
00117
00118 static char_type
00119 to_char_type(const int_type& __c)
00120 { return static_cast<char_type>(__c); }
00121
00122 static int_type
00123 to_int_type(const char_type& __c)
00124 { return static_cast<int_type>(__c); }
00125
00126 static bool
00127 eq_int_type(const int_type& __c1, const int_type& __c2)
00128 { return __c1 == __c2; }
00129
00130 static int_type
00131 eof() { return static_cast<int_type>(EOF); }
00132
00133 static int_type
00134 not_eof(const int_type& __c)
00135 { return (__c == eof()) ? 0 : __c; }
00136 };
00137 };
00138 #endif
00139
00140 class LLStringOps
00141 {
00142 public:
00143 static char toUpper(char elem) { return toupper(elem); }
00144 static llwchar toUpper(llwchar elem) { return towupper(elem); }
00145
00146 static char toLower(char elem) { return tolower(elem); }
00147 static llwchar toLower(llwchar elem) { return towlower(elem); }
00148
00149 static BOOL isSpace(char elem) { return isspace(elem) != 0; }
00150 static BOOL isSpace(llwchar elem) { return iswspace(elem) != 0; }
00151
00152 static BOOL isUpper(char elem) { return isupper(elem) != 0; }
00153 static BOOL isUpper(llwchar elem) { return iswupper(elem) != 0; }
00154
00155 static BOOL isLower(char elem) { return islower(elem) != 0; }
00156 static BOOL isLower(llwchar elem) { return iswlower(elem) != 0; }
00157
00158 static S32 collate(const char* a, const char* b) { return strcoll(a, b); }
00159 static S32 collate(const llwchar* a, const llwchar* b);
00160
00161 static BOOL isDigit(char a) { return isdigit(a) != 0; }
00162 static BOOL isDigit(llwchar a) { return iswdigit(a) != 0; }
00163 };
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177 template <class T>
00178 class LLStringBase : public std::basic_string<T>
00179 {
00180 public:
00181 typedef typename std::basic_string<T>::size_type size_type;
00182
00183
00184
00185
00186
00187
00188
00189 LLStringBase() : std::basic_string<T>() {}
00190 LLStringBase(const LLStringBase& s): std::basic_string<T>(s) {}
00191 LLStringBase(const std::basic_string<T>& s) : std::basic_string<T>(s) {}
00192 LLStringBase(const std::basic_string<T>& s, size_type pos, size_type n = std::basic_string<T>::npos)
00193 : std::basic_string<T>(s, pos, n) {}
00194 LLStringBase(size_type count, const T& c) : std::basic_string<T>() { assign(count, c);}
00195
00196 LLStringBase(const T* s);
00197 LLStringBase(const T* s, size_type n);
00198 LLStringBase(const T* s, size_type pos, size_type n );
00199
00200 #if LL_LINUX || LL_SOLARIS
00201 void clear() { assign(null); }
00202
00203 LLStringBase<T>& assign(const T* s);
00204 LLStringBase<T>& assign(const T* s, size_type n);
00205 LLStringBase<T>& assign(const LLStringBase& s);
00206 LLStringBase<T>& assign(size_type n, const T& c);
00207 LLStringBase<T>& assign(const T* a, const T* b);
00208 LLStringBase<T>& assign(typename LLStringBase<T>::iterator &it1, typename LLStringBase<T>::iterator &it2);
00209 LLStringBase<T>& assign(typename LLStringBase<T>::const_iterator &it1, typename LLStringBase<T>::const_iterator &it2);
00210
00211
00212 #if ((__GNUC__ <= 2) && (!defined _STLPORT_VERSION))
00213 const T* c_str () const
00214 {
00215 if (length () == 0)
00216 {
00217 static const T zero = 0;
00218 return &zero;
00219 }
00220
00221
00222 { string_char_traits<T>::assign(const_cast<T*>(data())[length()], string_char_traits<T>::eos()); }
00223
00224 return data ();
00225 }
00226 #endif
00227 #endif
00228
00229 bool operator==(const T* _Right) const { return _Right ? (std::basic_string<T>::compare(_Right) == 0) : this->empty(); }
00230
00231 public:
00233
00234
00235 static LLStringBase null;
00236
00237 typedef std::map<std::string, std::string> format_map_t;
00238 static S32 format(std::basic_string<T>& s, const format_map_t& fmt_map);
00239
00240 static BOOL isValidIndex(const std::basic_string<T>& string, size_type i)
00241 {
00242 return !string.empty() && (0 <= i) && (i <= string.size());
00243 }
00244
00245 static void trimHead(std::basic_string<T>& string);
00246 static void trimTail(std::basic_string<T>& string);
00247 static void trim(std::basic_string<T>& string) { trimHead(string); trimTail(string); }
00248 static void truncate(std::basic_string<T>& string, size_type count);
00249
00250 static void toUpper(std::basic_string<T>& string);
00251 static void toLower(std::basic_string<T>& string);
00252
00253
00254 static BOOL isHead( const std::basic_string<T>& string, const T* s );
00255
00256 static void addCRLF(std::basic_string<T>& string);
00257 static void removeCRLF(std::basic_string<T>& string);
00258
00259 static void replaceTabsWithSpaces( std::basic_string<T>& string, size_type spaces_per_tab );
00260 static void replaceNonstandardASCII( std::basic_string<T>& string, T replacement );
00261 static void replaceChar( std::basic_string<T>& string, T target, T replacement );
00262
00263 static BOOL containsNonprintable(const std::basic_string<T>& string);
00264 static void stripNonprintable(std::basic_string<T>& string);
00265
00273 static void _makeASCII(std::basic_string<T>& string);
00274
00275
00276 static BOOL convertToBOOL(const std::basic_string<T>& string, BOOL& value);
00277 static BOOL convertToU8(const std::basic_string<T>& string, U8& value);
00278 static BOOL convertToS8(const std::basic_string<T>& string, S8& value);
00279 static BOOL convertToS16(const std::basic_string<T>& string, S16& value);
00280 static BOOL convertToU16(const std::basic_string<T>& string, U16& value);
00281 static BOOL convertToU32(const std::basic_string<T>& string, U32& value);
00282 static BOOL convertToS32(const std::basic_string<T>& string, S32& value);
00283 static BOOL convertToF32(const std::basic_string<T>& string, F32& value);
00284 static BOOL convertToF64(const std::basic_string<T>& string, F64& value);
00285
00287
00288
00289
00290
00291 static S32 compareStrings(const T* lhs, const T* rhs);
00292
00293
00294
00295
00296 static S32 compareInsensitive(const T* lhs, const T* rhs);
00297
00298
00299
00300 static S32 compareDict(const std::basic_string<T>& a, const std::basic_string<T>& b);
00301
00302
00303
00304 static S32 compareDictInsensitive(const std::basic_string<T>& a, const std::basic_string<T>& b);
00305
00306
00307 static BOOL precedesDict( const std::basic_string<T>& a, const std::basic_string<T>& b );
00308
00309
00310
00311
00312 static void copy(T* dst, const T* src, size_type dst_size);
00313
00314
00315 static void copyInto(std::basic_string<T>& dst, const std::basic_string<T>& src, size_type offset);
00316
00317 #ifdef _DEBUG
00318 static void testHarness();
00319 #endif
00320
00321 };
00322
00323 template<class T> LLStringBase<T> LLStringBase<T>::null;
00324
00325 typedef LLStringBase<char> LLString;
00326 typedef LLStringBase<llwchar> LLWString;
00327
00328
00329
00330
00331 class LLStringExplicit : public LLString
00332 {
00333 public:
00334 explicit LLStringExplicit(const char* s) : LLString(s) {}
00335 LLStringExplicit(const LLString& s) : LLString(s) {}
00336 LLStringExplicit(const std::string& s) : LLString(s) {}
00337 LLStringExplicit(const std::string& s, size_type pos, size_type n = std::string::npos) : LLString(s, pos, n) {}
00338 };
00339
00340 struct LLDictionaryLess
00341 {
00342 public:
00343 bool operator()(const std::string& a, const std::string& b)
00344 {
00345 return (LLString::precedesDict(a, b) ? true : false);
00346 }
00347 };
00348
00349
00362 inline std::string chop_tail_copy(
00363 const std::string& in,
00364 std::string::size_type count)
00365 {
00366 return std::string(in, 0, in.length() - count);
00367 }
00368
00373 std::string ll_safe_string(const char* in);
00374
00379 U8 hex_as_nybble(char hex);
00380
00390 bool _read_file_into_string(std::string& str, const char* filename);
00391
00396
00397
00398
00399 std::string rawstr_to_utf8(const std::string& raw);
00400
00401
00402
00403
00404 typedef std::basic_string<U16> llutf16string;
00405
00406 LLWString utf16str_to_wstring(const llutf16string &utf16str, S32 len);
00407 LLWString utf16str_to_wstring(const llutf16string &utf16str);
00408
00409 llutf16string wstring_to_utf16str(const LLWString &utf32str, S32 len);
00410 llutf16string wstring_to_utf16str(const LLWString &utf32str);
00411
00412 llutf16string utf8str_to_utf16str ( const LLString& utf8str, S32 len);
00413 llutf16string utf8str_to_utf16str ( const LLString& utf8str );
00414
00415 LLWString utf8str_to_wstring(const std::string &utf8str, S32 len);
00416 LLWString utf8str_to_wstring(const std::string &utf8str);
00417
00418 inline LLWString utf8string_to_wstring(const std::string& utf8_string) { return utf8str_to_wstring(utf8_string); }
00419
00420
00421 S32 utf16chars_to_utf8chars(const U16* inchars, char* outchars, S32* nchars8 = 0);
00422 S32 utf16chars_to_wchar(const U16* inchars, llwchar* outchar);
00423 S32 wchar_to_utf8chars(llwchar inchar, char* outchars);
00424
00425
00426 std::string wstring_to_utf8str(const LLWString &utf32str, S32 len);
00427 std::string wstring_to_utf8str(const LLWString &utf32str);
00428
00429 std::string utf16str_to_utf8str(const llutf16string &utf16str, S32 len);
00430 std::string utf16str_to_utf8str(const llutf16string &utf16str);
00431
00432
00433 S32 wstring_utf8_length(const LLWString& wstr);
00434
00435
00436 S32 wchar_utf8_length(const llwchar wc);
00437
00438 std::string utf8str_tolower(const std::string& utf8str);
00439
00440
00441 S32 utf16str_wstring_length(const llutf16string &utf16str, S32 len);
00442
00443
00444 S32 wstring_utf16_length(const LLWString & wstr, S32 woffset, S32 wlen);
00445
00446
00447 S32 wstring_wstring_length_from_utf16_length(const LLWString & wstr, S32 woffset, S32 utf16_length, BOOL *unaligned = NULL);
00448
00459 std::string utf8str_truncate(const std::string& utf8str, const S32 max_len);
00460
00461 std::string utf8str_trim(const std::string& utf8str);
00462
00463 S32 utf8str_compare_insensitive(
00464 const std::string& lhs,
00465 const std::string& rhs);
00466
00474 std::string utf8str_substChar(
00475 const std::string& utf8str,
00476 const llwchar target_char,
00477 const llwchar replace_char);
00478
00479 std::string utf8str_makeASCII(const std::string& utf8str);
00480
00481
00482 std::string mbcsstring_makeASCII(const std::string& str);
00483
00484 std::string utf8str_removeCRLF(const std::string& utf8str);
00485
00486
00487 template <class T>
00488 std::ostream& operator<<(std::ostream &s, const LLStringBase<T> &str)
00489 {
00490 s << ((std::basic_string<T>)str);
00491 return s;
00492 }
00493
00494 std::ostream& operator<<(std::ostream &s, const LLWString &wstr);
00495
00496 #if LL_WINDOWS
00497
00498
00500
00518 int safe_snprintf(char* str, size_t size, const char* format, ...);
00519
00525 std::string ll_convert_wide_to_string(const wchar_t* in);
00526
00528 #endif // LL_WINDOWS
00529
00537 namespace LLStringFn
00538 {
00547 void replace_nonprintable(
00548 std::basic_string<char>& string,
00549 char replacement);
00550
00559 void replace_nonprintable(
00560 std::basic_string<llwchar>& string,
00561 llwchar replacement);
00562
00571 void replace_nonprintable_and_pipe(std::basic_string<char>& str,
00572 char replacement);
00573
00582 void replace_nonprintable_and_pipe(std::basic_string<llwchar>& str,
00583 llwchar replacement);
00584 }
00585
00587
00588
00589 template<class T>
00590 S32 LLStringBase<T>::format(std::basic_string<T>& s, const format_map_t& fmt_map)
00591 {
00592 typedef typename std::basic_string<T>::size_type string_size_type_t;
00593 S32 res = 0;
00594 for (format_map_t::const_iterator iter = fmt_map.begin(); iter != fmt_map.end(); ++iter)
00595 {
00596 U32 fmtlen = iter->first.size();
00597 string_size_type_t n = 0;
00598 while (1)
00599 {
00600 n = s.find(iter->first, n);
00601 if (n == std::basic_string<T>::npos)
00602 {
00603 break;
00604 }
00605 s.erase(n, fmtlen);
00606 s.insert(n, iter->second);
00607 n += fmtlen;
00608 ++res;
00609 }
00610 }
00611 return res;
00612 }
00613
00614
00615 template<class T>
00616 S32 LLStringBase<T>::compareStrings(const T* lhs, const T* rhs)
00617 {
00618 S32 result;
00619 if( lhs == rhs )
00620 {
00621 result = 0;
00622 }
00623 else
00624 if ( !lhs || !lhs[0] )
00625 {
00626 result = ((!rhs || !rhs[0]) ? 0 : 1);
00627 }
00628 else
00629 if ( !rhs || !rhs[0])
00630 {
00631 result = -1;
00632 }
00633 else
00634 {
00635 result = LLStringOps::collate(lhs, rhs);
00636 }
00637 return result;
00638 }
00639
00640
00641 template<class T>
00642 S32 LLStringBase<T>::compareInsensitive(const T* lhs, const T* rhs )
00643 {
00644 S32 result;
00645 if( lhs == rhs )
00646 {
00647 result = 0;
00648 }
00649 else
00650 if ( !lhs || !lhs[0] )
00651 {
00652 result = ((!rhs || !rhs[0]) ? 0 : 1);
00653 }
00654 else
00655 if ( !rhs || !rhs[0] )
00656 {
00657 result = -1;
00658 }
00659 else
00660 {
00661 LLStringBase<T> lhs_string(lhs);
00662 LLStringBase<T> rhs_string(rhs);
00663 LLStringBase<T>::toUpper(lhs_string);
00664 LLStringBase<T>::toUpper(rhs_string);
00665 result = LLStringOps::collate(lhs_string.c_str(), rhs_string.c_str());
00666 }
00667 return result;
00668 }
00669
00670
00671
00672
00673
00674
00675 template<class T>
00676 S32 LLStringBase<T>::compareDict(const std::basic_string<T>& astr, const std::basic_string<T>& bstr)
00677 {
00678 const T* a = astr.c_str();
00679 const T* b = bstr.c_str();
00680 T ca, cb;
00681 S32 ai, bi, cnt = 0;
00682 S32 bias = 0;
00683
00684 ca = *(a++);
00685 cb = *(b++);
00686 while( ca && cb ){
00687 if( bias==0 ){
00688 if( LLStringOps::isUpper(ca) ){ ca = LLStringOps::toLower(ca); bias--; }
00689 if( LLStringOps::isUpper(cb) ){ cb = LLStringOps::toLower(cb); bias++; }
00690 }else{
00691 if( LLStringOps::isUpper(ca) ){ ca = LLStringOps::toLower(ca); }
00692 if( LLStringOps::isUpper(cb) ){ cb = LLStringOps::toLower(cb); }
00693 }
00694 if( LLStringOps::isDigit(ca) ){
00695 if( cnt-->0 ){
00696 if( cb!=ca ) break;
00697 }else{
00698 if( !LLStringOps::isDigit(cb) ) break;
00699 for(ai=0; LLStringOps::isDigit(a[ai]); ai++);
00700 for(bi=0; LLStringOps::isDigit(b[bi]); bi++);
00701 if( ai<bi ){ ca=0; break; }
00702 if( bi<ai ){ cb=0; break; }
00703 if( ca!=cb ) break;
00704 cnt = ai;
00705 }
00706 }else if( ca!=cb ){ break;
00707 }
00708 ca = *(a++);
00709 cb = *(b++);
00710 }
00711 if( ca==cb ) ca += bias;
00712 return ca-cb;
00713 }
00714
00715 template<class T>
00716 S32 LLStringBase<T>::compareDictInsensitive(const std::basic_string<T>& astr, const std::basic_string<T>& bstr)
00717 {
00718 const T* a = astr.c_str();
00719 const T* b = bstr.c_str();
00720 T ca, cb;
00721 S32 ai, bi, cnt = 0;
00722
00723 ca = *(a++);
00724 cb = *(b++);
00725 while( ca && cb ){
00726 if( LLStringOps::isUpper(ca) ){ ca = LLStringOps::toLower(ca); }
00727 if( LLStringOps::isUpper(cb) ){ cb = LLStringOps::toLower(cb); }
00728 if( LLStringOps::isDigit(ca) ){
00729 if( cnt-->0 ){
00730 if( cb!=ca ) break;
00731 }else{
00732 if( !LLStringOps::isDigit(cb) ) break;
00733 for(ai=0; LLStringOps::isDigit(a[ai]); ai++);
00734 for(bi=0; LLStringOps::isDigit(b[bi]); bi++);
00735 if( ai<bi ){ ca=0; break; }
00736 if( bi<ai ){ cb=0; break; }
00737 if( ca!=cb ) break;
00738 cnt = ai;
00739 }
00740 }else if( ca!=cb ){ break;
00741 }
00742 ca = *(a++);
00743 cb = *(b++);
00744 }
00745 return ca-cb;
00746 }
00747
00748
00749
00750 template<class T>
00751 BOOL LLStringBase<T>::precedesDict( const std::basic_string<T>& a, const std::basic_string<T>& b )
00752 {
00753 if( a.size() && b.size() )
00754 {
00755 return (LLStringBase<T>::compareDict(a.c_str(), b.c_str()) < 0);
00756 }
00757 else
00758 {
00759 return (!b.empty());
00760 }
00761 }
00762
00763
00764 template<class T>
00765 LLStringBase<T>::LLStringBase(const T* s ) : std::basic_string<T>()
00766 {
00767 if (s) assign(s);
00768 }
00769
00770 template<class T>
00771 LLStringBase<T>::LLStringBase(const T* s, size_type n ) : std::basic_string<T>()
00772 {
00773 if (s) assign(s, n);
00774 }
00775
00776
00777 template<class T>
00778 LLStringBase<T>::LLStringBase(const T* s, size_type pos, size_type n ) : std::basic_string<T>()
00779 {
00780 if( s )
00781 {
00782 assign(s + pos, n);
00783 }
00784 else
00785 {
00786 assign(LLStringBase<T>::null);
00787 }
00788 }
00789
00790 #if LL_LINUX || LL_SOLARIS
00791 template<class T>
00792 LLStringBase<T>& LLStringBase<T>::assign(const T* s)
00793 {
00794 if (s)
00795 {
00796 std::basic_string<T>::assign(s);
00797 }
00798 else
00799 {
00800 assign(LLStringBase<T>::null);
00801 }
00802 return *this;
00803 }
00804
00805 template<class T>
00806 LLStringBase<T>& LLStringBase<T>::assign(const T* s, size_type n)
00807 {
00808 if (s)
00809 {
00810 std::basic_string<T>::assign(s, n);
00811 }
00812 else
00813 {
00814 assign(LLStringBase<T>::null);
00815 }
00816 return *this;
00817 }
00818
00819 template<class T>
00820 LLStringBase<T>& LLStringBase<T>::assign(const LLStringBase<T>& s)
00821 {
00822 std::basic_string<T>::assign(s);
00823 return *this;
00824 }
00825
00826 template<class T>
00827 LLStringBase<T>& LLStringBase<T>::assign(size_type n, const T& c)
00828 {
00829 std::basic_string<T>::assign(n, c);
00830 return *this;
00831 }
00832
00833 template<class T>
00834 LLStringBase<T>& LLStringBase<T>::assign(const T* a, const T* b)
00835 {
00836 if (a > b)
00837 assign(LLStringBase<T>::null);
00838 else
00839 assign(a, (size_type) (b-a));
00840 return *this;
00841 }
00842
00843 template<class T>
00844 LLStringBase<T>& LLStringBase<T>::assign(typename LLStringBase<T>::iterator &it1, typename LLStringBase<T>::iterator &it2)
00845 {
00846 assign(LLStringBase<T>::null);
00847 while(it1 != it2)
00848 *this += *it1++;
00849 return *this;
00850 }
00851
00852 template<class T>
00853 LLStringBase<T>& LLStringBase<T>::assign(typename LLStringBase<T>::const_iterator &it1, typename LLStringBase<T>::const_iterator &it2)
00854 {
00855 assign(LLStringBase<T>::null);
00856 while(it1 != it2)
00857 *this += *it1++;
00858 return *this;
00859 }
00860 #endif
00861
00862
00863 template<class T>
00864 void LLStringBase<T>::toUpper(std::basic_string<T>& string)
00865 {
00866 if( !string.empty() )
00867 {
00868 std::transform(
00869 string.begin(),
00870 string.end(),
00871 string.begin(),
00872 (T(*)(T)) &LLStringOps::toUpper);
00873 }
00874 }
00875
00876
00877 template<class T>
00878 void LLStringBase<T>::toLower(std::basic_string<T>& string)
00879 {
00880 if( !string.empty() )
00881 {
00882 std::transform(
00883 string.begin(),
00884 string.end(),
00885 string.begin(),
00886 (T(*)(T)) &LLStringOps::toLower);
00887 }
00888 }
00889
00890
00891 template<class T>
00892 void LLStringBase<T>::trimHead(std::basic_string<T>& string)
00893 {
00894 if( !string.empty() )
00895 {
00896 size_type i = 0;
00897 while( i < string.length() && LLStringOps::isSpace( string[i] ) )
00898 {
00899 i++;
00900 }
00901 string.erase(0, i);
00902 }
00903 }
00904
00905
00906 template<class T>
00907 void LLStringBase<T>::trimTail(std::basic_string<T>& string)
00908 {
00909 if( string.size() )
00910 {
00911 size_type len = string.length();
00912 size_type i = len;
00913 while( i > 0 && LLStringOps::isSpace( string[i-1] ) )
00914 {
00915 i--;
00916 }
00917
00918 string.erase( i, len - i );
00919 }
00920 }
00921
00922
00923
00924
00925 template<class T>
00926 void LLStringBase<T>::addCRLF(std::basic_string<T>& string)
00927 {
00928 const T LF = 10;
00929 const T CR = 13;
00930
00931
00932 size_type count = 0;
00933 size_type len = string.size();
00934 size_type i;
00935 for( i = 0; i < len; i++ )
00936 {
00937 if( string[i] == LF )
00938 {
00939 count++;
00940 }
00941 }
00942
00943
00944 if( count )
00945 {
00946 size_type size = len + count;
00947 T *t = new T[size];
00948 size_type j = 0;
00949 for( i = 0; i < len; ++i )
00950 {
00951 if( string[i] == LF )
00952 {
00953 t[j] = CR;
00954 ++j;
00955 }
00956 t[j] = string[i];
00957 ++j;
00958 }
00959
00960 string.assign(t, size);
00961 }
00962 }
00963
00964
00965
00966 template<class T>
00967 void LLStringBase<T>::removeCRLF(std::basic_string<T>& string)
00968 {
00969 const T CR = 13;
00970
00971 size_type cr_count = 0;
00972 size_type len = string.size();
00973 size_type i;
00974 for( i = 0; i < len - cr_count; i++ )
00975 {
00976 if( string[i+cr_count] == CR )
00977 {
00978 cr_count++;
00979 }
00980
00981 string[i] = string[i+cr_count];
00982 }
00983 string.erase(i, cr_count);
00984 }
00985
00986
00987 template<class T>
00988 void LLStringBase<T>::replaceChar( std::basic_string<T>& string, T target, T replacement )
00989 {
00990 size_type found_pos = 0;
00991 for (found_pos = string.find(target, found_pos);
00992 found_pos != std::basic_string<T>::npos;
00993 found_pos = string.find(target, found_pos))
00994 {
00995 string[found_pos] = replacement;
00996 }
00997 }
00998
00999
01000 template<class T>
01001 void LLStringBase<T>::replaceNonstandardASCII( std::basic_string<T>& string, T replacement )
01002 {
01003 const char LF = 10;
01004 const S8 MIN = 32;
01005
01006
01007 size_type len = string.size();
01008 for( size_type i = 0; i < len; i++ )
01009 {
01010
01011
01012 if( ( S8(string[i]) < MIN ) && (string[i] != LF) )
01013 {
01014 string[i] = replacement;
01015 }
01016 }
01017 }
01018
01019
01020 template<class T>
01021 void LLStringBase<T>::replaceTabsWithSpaces( std::basic_string<T>& str, size_type spaces_per_tab )
01022 {
01023 const T TAB = '\t';
01024 const T SPACE = ' ';
01025
01026 LLStringBase<T> out_str;
01027
01028 for (size_type i = 0; i < str.length(); i++)
01029 {
01030 if (str[i] == TAB)
01031 {
01032 for (size_type j = 0; j < spaces_per_tab; j++)
01033 out_str += SPACE;
01034 }
01035 else
01036 {
01037 out_str += str[i];
01038 }
01039 }
01040 str = out_str;
01041 }
01042
01043
01044 template<class T>
01045 BOOL LLStringBase<T>::containsNonprintable(const std::basic_string<T>& string)
01046 {
01047 const char MIN = 32;
01048 BOOL rv = FALSE;
01049 for (size_type i = 0; i < string.size(); i++)
01050 {
01051 if(string[i] < MIN)
01052 {
01053 rv = TRUE;
01054 break;
01055 }
01056 }
01057 return rv;
01058 }
01059
01060
01061 template<class T>
01062 void LLStringBase<T>::stripNonprintable(std::basic_string<T>& string)
01063 {
01064 const char MIN = 32;
01065 size_type j = 0;
01066 if (string.empty())
01067 {
01068 return;
01069 }
01070 char* c_string = new char[string.size() + 1];
01071 if(c_string == NULL)
01072 {
01073 return;
01074 }
01075 strcpy(c_string, string.c_str());
01076 char* write_head = &c_string[0];
01077 for (size_type i = 0; i < string.size(); i++)
01078 {
01079 char* read_head = &string[i];
01080 write_head = &c_string[j];
01081 if(!(*read_head < MIN))
01082 {
01083 *write_head = *read_head;
01084 ++j;
01085 }
01086 }
01087 c_string[j]= '\0';
01088 string = c_string;
01089 delete []c_string;
01090 }
01091
01092 template<class T>
01093 void LLStringBase<T>::_makeASCII(std::basic_string<T>& string)
01094 {
01095
01096 for (size_type i = 0; i < string.length(); i++)
01097 {
01098 if (string[i] > 0x7f)
01099 {
01100 string[i] = LL_UNKNOWN_CHAR;
01101 }
01102 }
01103 }
01104
01105
01106 template<class T>
01107 void LLStringBase<T>::copy( T* dst, const T* src, size_type dst_size )
01108 {
01109 if( dst_size > 0 )
01110 {
01111 size_type min_len = 0;
01112 if( src )
01113 {
01114 min_len = llmin( dst_size - 1, strlen( src ) );
01115 memcpy(dst, src, min_len * sizeof(T));
01116 }
01117 dst[min_len] = '\0';
01118 }
01119 }
01120
01121
01122 template<class T>
01123 void LLStringBase<T>::copyInto(std::basic_string<T>& dst, const std::basic_string<T>& src, size_type offset)
01124 {
01125 if ( offset == dst.length() )
01126 {
01127
01128
01129 dst += src;
01130 }
01131 else
01132 {
01133 std::basic_string<T> tail = dst.substr(offset);
01134
01135 dst = dst.substr(0, offset);
01136 dst += src;
01137 dst += tail;
01138 };
01139 }
01140
01141
01142
01143 template<class T>
01144 BOOL LLStringBase<T>::isHead( const std::basic_string<T>& string, const T* s )
01145 {
01146 if( string.empty() )
01147 {
01148
01149 return FALSE;
01150 }
01151 else
01152 {
01153 return (strncmp( s, string.c_str(), string.size() ) == 0);
01154 }
01155 }
01156
01157 template<class T>
01158 BOOL LLStringBase<T>::convertToBOOL(const std::basic_string<T>& string, BOOL& value)
01159 {
01160 if( string.empty() )
01161 {
01162 return FALSE;
01163 }
01164
01165 LLStringBase<T> temp( string );
01166 trim(temp);
01167 if(
01168 (temp == "1") ||
01169 (temp == "T") ||
01170 (temp == "t") ||
01171 (temp == "TRUE") ||
01172 (temp == "true") ||
01173 (temp == "True") )
01174 {
01175 value = TRUE;
01176 return TRUE;
01177 }
01178 else
01179 if(
01180 (temp == "0") ||
01181 (temp == "F") ||
01182 (temp == "f") ||
01183 (temp == "FALSE") ||
01184 (temp == "false") ||
01185 (temp == "False") )
01186 {
01187 value = FALSE;
01188 return TRUE;
01189 }
01190
01191 return FALSE;
01192 }
01193
01194 template<class T>
01195 BOOL LLStringBase<T>::convertToU8(const std::basic_string<T>& string, U8& value)
01196 {
01197 S32 value32 = 0;
01198 BOOL success = convertToS32(string, value32);
01199 if( success && (U8_MIN <= value32) && (value32 <= U8_MAX) )
01200 {
01201 value = (U8) value32;
01202 return TRUE;
01203 }
01204 return FALSE;
01205 }
01206
01207 template<class T>
01208 BOOL LLStringBase<T>::convertToS8(const std::basic_string<T>& string, S8& value)
01209 {
01210 S32 value32 = 0;
01211 BOOL success = convertToS32(string, value32);
01212 if( success && (S8_MIN <= value32) && (value32 <= S8_MAX) )
01213 {
01214 value = (S8) value32;
01215 return TRUE;
01216 }
01217 return FALSE;
01218 }
01219
01220 template<class T>
01221 BOOL LLStringBase<T>::convertToS16(const std::basic_string<T>& string, S16& value)
01222 {
01223 S32 value32 = 0;
01224 BOOL success = convertToS32(string, value32);
01225 if( success && (S16_MIN <= value32) && (value32 <= S16_MAX) )
01226 {
01227 value = (S16) value32;
01228 return TRUE;
01229 }
01230 return FALSE;
01231 }
01232
01233 template<class T>
01234 BOOL LLStringBase<T>::convertToU16(const std::basic_string<T>& string, U16& value)
01235 {
01236 S32 value32 = 0;
01237 BOOL success = convertToS32(string, value32);
01238 if( success && (U16_MIN <= value32) && (value32 <= U16_MAX) )
01239 {
01240 value = (U16) value32;
01241 return TRUE;
01242 }
01243 return FALSE;
01244 }
01245
01246 template<class T>
01247 BOOL LLStringBase<T>::convertToU32(const std::basic_string<T>& string, U32& value)
01248 {
01249 if( string.empty() )
01250 {
01251 return FALSE;
01252 }
01253
01254 LLStringBase<T> temp( string );
01255 trim(temp);
01256 U32 v;
01257 std::basic_istringstream<T> i_stream((std::basic_string<T>)temp);
01258 if(i_stream >> v)
01259 {
01260
01261
01262
01263
01264
01265
01266
01267 value = v;
01268 return TRUE;
01269 }
01270 return FALSE;
01271 }
01272
01273 template<class T>
01274 BOOL LLStringBase<T>::convertToS32(const std::basic_string<T>& string, S32& value)
01275 {
01276 if( string.empty() )
01277 {
01278 return FALSE;
01279 }
01280
01281 LLStringBase<T> temp( string );
01282 trim(temp);
01283 S32 v;
01284 std::basic_istringstream<T> i_stream((std::basic_string<T>)temp);
01285 if(i_stream >> v)
01286 {
01287
01288
01289
01290
01291
01292
01293
01294 value = v;
01295 return TRUE;
01296 }
01297 return FALSE;
01298 }
01299
01300 template<class T>
01301 BOOL LLStringBase<T>::convertToF32(const std::basic_string<T>& string, F32& value)
01302 {
01303 F64 value64 = 0.0;
01304 BOOL success = convertToF64(string, value64);
01305 if( success && (-F32_MAX <= value64) && (value64 <= F32_MAX) )
01306 {
01307 value = (F32) value64;
01308 return TRUE;
01309 }
01310 return FALSE;
01311 }
01312
01313 template<class T>
01314 BOOL LLStringBase<T>::convertToF64(const std::basic_string<T>& string, F64& value)
01315 {
01316 if( string.empty() )
01317 {
01318 return FALSE;
01319 }
01320
01321 LLStringBase<T> temp( string );
01322 trim(temp);
01323 F64 v;
01324 std::basic_istringstream<T> i_stream((std::basic_string<T>)temp);
01325 if(i_stream >> v)
01326 {
01327
01328
01329
01330
01331
01332
01333
01334 value = v;
01335 return TRUE;
01336 }
01337 return FALSE;
01338 }
01339
01340 template<class T>
01341 void LLStringBase<T>::truncate(std::basic_string<T>& string, size_type count)
01342 {
01343 size_type cur_size = string.size();
01344 string.resize(count < cur_size ? count : cur_size);
01345 }
01346
01347 #endif // LL_STRING_H