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 static BOOL precedesDict( const std::basic_string<T>& a, const std::basic_string<T>& b );
00304
00305
00306
00307
00308 static void copy(T* dst, const T* src, size_type dst_size);
00309
00310
00311 static void copyInto(std::basic_string<T>& dst, const std::basic_string<T>& src, size_type offset);
00312
00313 #ifdef _DEBUG
00314 static void testHarness();
00315 #endif
00316
00317 };
00318
00319 template<class T> LLStringBase<T> LLStringBase<T>::null;
00320
00321 typedef LLStringBase<char> LLString;
00322 typedef LLStringBase<llwchar> LLWString;
00323
00324
00325
00326
00327 class LLStringExplicit : public LLString
00328 {
00329 public:
00330 explicit LLStringExplicit(const char* s) : LLString(s) {}
00331 LLStringExplicit(const LLString& s) : LLString(s) {}
00332 LLStringExplicit(const std::string& s) : LLString(s) {}
00333 LLStringExplicit(const std::string& s, size_type pos, size_type n = std::string::npos) : LLString(s, pos, n) {}
00334 };
00335
00336 struct LLDictionaryLess
00337 {
00338 public:
00339 bool operator()(const std::string& a, const std::string& b)
00340 {
00341 return (LLString::precedesDict(a, b) ? true : false);
00342 }
00343 };
00344
00345
00358 inline std::string chop_tail_copy(
00359 const std::string& in,
00360 std::string::size_type count)
00361 {
00362 return std::string(in, 0, in.length() - count);
00363 }
00364
00369 std::string ll_safe_string(const char* in);
00370
00375 U8 hex_as_nybble(char hex);
00376
00386 bool _read_file_into_string(std::string& str, const char* filename);
00387
00392
00393
00394
00395 std::string rawstr_to_utf8(const std::string& raw);
00396
00397
00398
00399
00400 typedef std::basic_string<U16> llutf16string;
00401
00402 LLWString utf16str_to_wstring(const llutf16string &utf16str, S32 len);
00403 LLWString utf16str_to_wstring(const llutf16string &utf16str);
00404
00405 llutf16string wstring_to_utf16str(const LLWString &utf32str, S32 len);
00406 llutf16string wstring_to_utf16str(const LLWString &utf32str);
00407
00408 llutf16string utf8str_to_utf16str ( const LLString& utf8str, S32 len);
00409 llutf16string utf8str_to_utf16str ( const LLString& utf8str );
00410
00411 LLWString utf8str_to_wstring(const std::string &utf8str, S32 len);
00412 LLWString utf8str_to_wstring(const std::string &utf8str);
00413
00414 inline LLWString utf8string_to_wstring(const std::string& utf8_string) { return utf8str_to_wstring(utf8_string); }
00415
00416
00417 S32 utf16chars_to_utf8chars(const U16* inchars, char* outchars, S32* nchars8 = 0);
00418 S32 utf16chars_to_wchar(const U16* inchars, llwchar* outchar);
00419 S32 wchar_to_utf8chars(llwchar inchar, char* outchars);
00420
00421
00422 std::string wstring_to_utf8str(const LLWString &utf32str, S32 len);
00423 std::string wstring_to_utf8str(const LLWString &utf32str);
00424
00425 std::string utf16str_to_utf8str(const llutf16string &utf16str, S32 len);
00426 std::string utf16str_to_utf8str(const llutf16string &utf16str);
00427
00428
00429 S32 wstring_utf8_length(const LLWString& wstr);
00430
00431
00432 S32 wchar_utf8_length(const llwchar wc);
00433
00434 std::string utf8str_tolower(const std::string& utf8str);
00435
00446 std::string utf8str_truncate(const std::string& utf8str, const S32 max_len);
00447
00448 std::string utf8str_trim(const std::string& utf8str);
00449
00450 S32 utf8str_compare_insensitive(
00451 const std::string& lhs,
00452 const std::string& rhs);
00453
00461 std::string utf8str_substChar(
00462 const std::string& utf8str,
00463 const llwchar target_char,
00464 const llwchar replace_char);
00465
00466 std::string utf8str_makeASCII(const std::string& utf8str);
00467
00468
00469 std::string mbcsstring_makeASCII(const std::string& str);
00470
00471 std::string utf8str_removeCRLF(const std::string& utf8str);
00472
00473
00474 template <class T>
00475 std::ostream& operator<<(std::ostream &s, const LLStringBase<T> &str)
00476 {
00477 s << ((std::basic_string<T>)str);
00478 return s;
00479 }
00480
00481 std::ostream& operator<<(std::ostream &s, const LLWString &wstr);
00482
00483 #if LL_WINDOWS
00484 int safe_snprintf(char *str, size_t size, const char *format, ...);
00485 #endif // LL_WINDOWS
00486
00494 namespace LLStringFn
00495 {
00504 void replace_nonprintable(
00505 std::basic_string<char>& string,
00506 char replacement);
00507
00516 void replace_nonprintable(
00517 std::basic_string<llwchar>& string,
00518 llwchar replacement);
00519
00528 void replace_nonprintable_and_pipe(std::basic_string<char>& str,
00529 char replacement);
00530
00539 void replace_nonprintable_and_pipe(std::basic_string<llwchar>& str,
00540 llwchar replacement);
00541 }
00542
00544
00545
00546 template<class T>
00547 S32 LLStringBase<T>::format(std::basic_string<T>& s, const format_map_t& fmt_map)
00548 {
00549 typedef typename std::basic_string<T>::size_type string_size_type_t;
00550 S32 res = 0;
00551 for (format_map_t::const_iterator iter = fmt_map.begin(); iter != fmt_map.end(); ++iter)
00552 {
00553 U32 fmtlen = iter->first.size();
00554 string_size_type_t n = 0;
00555 while (1)
00556 {
00557 n = s.find(iter->first, n);
00558 if (n == std::basic_string<T>::npos)
00559 {
00560 break;
00561 }
00562 s.erase(n, fmtlen);
00563 s.insert(n, iter->second);
00564 n += fmtlen;
00565 ++res;
00566 }
00567 }
00568 return res;
00569 }
00570
00571
00572 template<class T>
00573 S32 LLStringBase<T>::compareStrings(const T* lhs, const T* rhs)
00574 {
00575 S32 result;
00576 if( lhs == rhs )
00577 {
00578 result = 0;
00579 }
00580 else
00581 if ( !lhs || !lhs[0] )
00582 {
00583 result = ((!rhs || !rhs[0]) ? 0 : 1);
00584 }
00585 else
00586 if ( !rhs || !rhs[0])
00587 {
00588 result = -1;
00589 }
00590 else
00591 {
00592 result = LLStringOps::collate(lhs, rhs);
00593 }
00594 return result;
00595 }
00596
00597
00598 template<class T>
00599 S32 LLStringBase<T>::compareInsensitive(const T* lhs, const T* rhs )
00600 {
00601 S32 result;
00602 if( lhs == rhs )
00603 {
00604 result = 0;
00605 }
00606 else
00607 if ( !lhs || !lhs[0] )
00608 {
00609 result = ((!rhs || !rhs[0]) ? 0 : 1);
00610 }
00611 else
00612 if ( !rhs || !rhs[0] )
00613 {
00614 result = -1;
00615 }
00616 else
00617 {
00618 LLStringBase<T> lhs_string(lhs);
00619 LLStringBase<T> rhs_string(rhs);
00620 LLStringBase<T>::toUpper(lhs_string);
00621 LLStringBase<T>::toUpper(rhs_string);
00622 result = LLStringOps::collate(lhs_string.c_str(), rhs_string.c_str());
00623 }
00624 return result;
00625 }
00626
00627
00628
00629
00630
00631
00632 template<class T>
00633 S32 LLStringBase<T>::compareDict(const std::basic_string<T>& astr, const std::basic_string<T>& bstr)
00634 {
00635 const T* a = astr.c_str();
00636 const T* b = bstr.c_str();
00637 T ca, cb;
00638 S32 ai, bi, cnt = 0;
00639 S32 bias = 0;
00640
00641 ca = *(a++);
00642 cb = *(b++);
00643 while( ca && cb ){
00644 if( bias==0 ){
00645 if( LLStringOps::isUpper(ca) ){ ca = LLStringOps::toLower(ca); bias--; }
00646 if( LLStringOps::isUpper(cb) ){ cb = LLStringOps::toLower(cb); bias++; }
00647 }else{
00648 if( LLStringOps::isUpper(ca) ){ ca = LLStringOps::toLower(ca); }
00649 if( LLStringOps::isUpper(cb) ){ cb = LLStringOps::toLower(cb); }
00650 }
00651 if( LLStringOps::isDigit(ca) ){
00652 if( cnt-->0 ){
00653 if( cb!=ca ) break;
00654 }else{
00655 if( !LLStringOps::isDigit(cb) ) break;
00656 for(ai=0; LLStringOps::isDigit(a[ai]); ai++);
00657 for(bi=0; LLStringOps::isDigit(b[bi]); bi++);
00658 if( ai<bi ){ ca=0; break; }
00659 if( bi<ai ){ cb=0; break; }
00660 if( ca!=cb ) break;
00661 cnt = ai;
00662 }
00663 }else if( ca!=cb ){ break;
00664 }
00665 ca = *(a++);
00666 cb = *(b++);
00667 }
00668 if( ca==cb ) ca += bias;
00669 return ca-cb;
00670 }
00671
00672
00673
00674 template<class T>
00675 BOOL LLStringBase<T>::precedesDict( const std::basic_string<T>& a, const std::basic_string<T>& b )
00676 {
00677 if( a.size() && b.size() )
00678 {
00679 return (LLStringBase<T>::compareDict(a.c_str(), b.c_str()) < 0);
00680 }
00681 else
00682 {
00683 return (!b.empty());
00684 }
00685 }
00686
00687
00688 template<class T>
00689 LLStringBase<T>::LLStringBase(const T* s ) : std::basic_string<T>()
00690 {
00691 if (s) assign(s);
00692 }
00693
00694 template<class T>
00695 LLStringBase<T>::LLStringBase(const T* s, size_type n ) : std::basic_string<T>()
00696 {
00697 if (s) assign(s, n);
00698 }
00699
00700
00701 template<class T>
00702 LLStringBase<T>::LLStringBase(const T* s, size_type pos, size_type n ) : std::basic_string<T>()
00703 {
00704 if( s )
00705 {
00706 assign(s + pos, n);
00707 }
00708 else
00709 {
00710 assign(LLStringBase<T>::null);
00711 }
00712 }
00713
00714 #if LL_LINUX || LL_SOLARIS
00715 template<class T>
00716 LLStringBase<T>& LLStringBase<T>::assign(const T* s)
00717 {
00718 if (s)
00719 {
00720 std::basic_string<T>::assign(s);
00721 }
00722 else
00723 {
00724 assign(LLStringBase<T>::null);
00725 }
00726 return *this;
00727 }
00728
00729 template<class T>
00730 LLStringBase<T>& LLStringBase<T>::assign(const T* s, size_type n)
00731 {
00732 if (s)
00733 {
00734 std::basic_string<T>::assign(s, n);
00735 }
00736 else
00737 {
00738 assign(LLStringBase<T>::null);
00739 }
00740 return *this;
00741 }
00742
00743 template<class T>
00744 LLStringBase<T>& LLStringBase<T>::assign(const LLStringBase<T>& s)
00745 {
00746 std::basic_string<T>::assign(s);
00747 return *this;
00748 }
00749
00750 template<class T>
00751 LLStringBase<T>& LLStringBase<T>::assign(size_type n, const T& c)
00752 {
00753 std::basic_string<T>::assign(n, c);
00754 return *this;
00755 }
00756
00757 template<class T>
00758 LLStringBase<T>& LLStringBase<T>::assign(const T* a, const T* b)
00759 {
00760 if (a > b)
00761 assign(LLStringBase<T>::null);
00762 else
00763 assign(a, (size_type) (b-a));
00764 return *this;
00765 }
00766
00767 template<class T>
00768 LLStringBase<T>& LLStringBase<T>::assign(typename LLStringBase<T>::iterator &it1, typename LLStringBase<T>::iterator &it2)
00769 {
00770 assign(LLStringBase<T>::null);
00771 while(it1 != it2)
00772 *this += *it1++;
00773 return *this;
00774 }
00775
00776 template<class T>
00777 LLStringBase<T>& LLStringBase<T>::assign(typename LLStringBase<T>::const_iterator &it1, typename LLStringBase<T>::const_iterator &it2)
00778 {
00779 assign(LLStringBase<T>::null);
00780 while(it1 != it2)
00781 *this += *it1++;
00782 return *this;
00783 }
00784 #endif
00785
00786
00787 template<class T>
00788 void LLStringBase<T>::toUpper(std::basic_string<T>& string)
00789 {
00790 if( !string.empty() )
00791 {
00792 std::transform(
00793 string.begin(),
00794 string.end(),
00795 string.begin(),
00796 (T(*)(T)) &LLStringOps::toUpper);
00797 }
00798 }
00799
00800
00801 template<class T>
00802 void LLStringBase<T>::toLower(std::basic_string<T>& string)
00803 {
00804 if( !string.empty() )
00805 {
00806 std::transform(
00807 string.begin(),
00808 string.end(),
00809 string.begin(),
00810 (T(*)(T)) &LLStringOps::toLower);
00811 }
00812 }
00813
00814
00815 template<class T>
00816 void LLStringBase<T>::trimHead(std::basic_string<T>& string)
00817 {
00818 if( !string.empty() )
00819 {
00820 size_type i = 0;
00821 while( i < string.length() && LLStringOps::isSpace( string[i] ) )
00822 {
00823 i++;
00824 }
00825 string.erase(0, i);
00826 }
00827 }
00828
00829
00830 template<class T>
00831 void LLStringBase<T>::trimTail(std::basic_string<T>& string)
00832 {
00833 if( string.size() )
00834 {
00835 size_type len = string.length();
00836 size_type i = len;
00837 while( i > 0 && LLStringOps::isSpace( string[i-1] ) )
00838 {
00839 i--;
00840 }
00841
00842 string.erase( i, len - i );
00843 }
00844 }
00845
00846
00847
00848
00849 template<class T>
00850 void LLStringBase<T>::addCRLF(std::basic_string<T>& string)
00851 {
00852 const T LF = 10;
00853 const T CR = 13;
00854
00855
00856 size_type count = 0;
00857 size_type len = string.size();
00858 size_type i;
00859 for( i = 0; i < len; i++ )
00860 {
00861 if( string[i] == LF )
00862 {
00863 count++;
00864 }
00865 }
00866
00867
00868 if( count )
00869 {
00870 size_type size = len + count;
00871 T *t = new T[size];
00872 size_type j = 0;
00873 for( i = 0; i < len; ++i )
00874 {
00875 if( string[i] == LF )
00876 {
00877 t[j] = CR;
00878 ++j;
00879 }
00880 t[j] = string[i];
00881 ++j;
00882 }
00883
00884 string.assign(t, size);
00885 }
00886 }
00887
00888
00889
00890 template<class T>
00891 void LLStringBase<T>::removeCRLF(std::basic_string<T>& string)
00892 {
00893 const T CR = 13;
00894
00895 size_type cr_count = 0;
00896 size_type len = string.size();
00897 size_type i;
00898 for( i = 0; i < len - cr_count; i++ )
00899 {
00900 if( string[i+cr_count] == CR )
00901 {
00902 cr_count++;
00903 }
00904
00905 string[i] = string[i+cr_count];
00906 }
00907 string.erase(i, cr_count);
00908 }
00909
00910
00911 template<class T>
00912 void LLStringBase<T>::replaceChar( std::basic_string<T>& string, T target, T replacement )
00913 {
00914 size_type found_pos = 0;
00915 for (found_pos = string.find(target, found_pos);
00916 found_pos != std::basic_string<T>::npos;
00917 found_pos = string.find(target, found_pos))
00918 {
00919 string[found_pos] = replacement;
00920 }
00921 }
00922
00923
00924 template<class T>
00925 void LLStringBase<T>::replaceNonstandardASCII( std::basic_string<T>& string, T replacement )
00926 {
00927 const char LF = 10;
00928 const S8 MIN = 32;
00929
00930
00931 size_type len = string.size();
00932 for( size_type i = 0; i < len; i++ )
00933 {
00934
00935
00936 if( ( S8(string[i]) < MIN ) && (string[i] != LF) )
00937 {
00938 string[i] = replacement;
00939 }
00940 }
00941 }
00942
00943
00944 template<class T>
00945 void LLStringBase<T>::replaceTabsWithSpaces( std::basic_string<T>& str, size_type spaces_per_tab )
00946 {
00947 const T TAB = '\t';
00948 const T SPACE = ' ';
00949
00950 LLStringBase<T> out_str;
00951
00952 for (size_type i = 0; i < str.length(); i++)
00953 {
00954 if (str[i] == TAB)
00955 {
00956 for (size_type j = 0; j < spaces_per_tab; j++)
00957 out_str += SPACE;
00958 }
00959 else
00960 {
00961 out_str += str[i];
00962 }
00963 }
00964 str = out_str;
00965 }
00966
00967
00968 template<class T>
00969 BOOL LLStringBase<T>::containsNonprintable(const std::basic_string<T>& string)
00970 {
00971 const char MIN = 32;
00972 BOOL rv = FALSE;
00973 for (size_type i = 0; i < string.size(); i++)
00974 {
00975 if(string[i] < MIN)
00976 {
00977 rv = TRUE;
00978 break;
00979 }
00980 }
00981 return rv;
00982 }
00983
00984
00985 template<class T>
00986 void LLStringBase<T>::stripNonprintable(std::basic_string<T>& string)
00987 {
00988 const char MIN = 32;
00989 size_type j = 0;
00990 if (string.empty())
00991 {
00992 return;
00993 }
00994 char* c_string = new char[string.size() + 1];
00995 if(c_string == NULL)
00996 {
00997 return;
00998 }
00999 strcpy(c_string, string.c_str());
01000 char* write_head = &c_string[0];
01001 for (size_type i = 0; i < string.size(); i++)
01002 {
01003 char* read_head = &string[i];
01004 write_head = &c_string[j];
01005 if(!(*read_head < MIN))
01006 {
01007 *write_head = *read_head;
01008 ++j;
01009 }
01010 }
01011 c_string[j]= '\0';
01012 string = c_string;
01013 delete []c_string;
01014 }
01015
01016 template<class T>
01017 void LLStringBase<T>::_makeASCII(std::basic_string<T>& string)
01018 {
01019
01020 for (size_type i = 0; i < string.length(); i++)
01021 {
01022 if (string[i] > 0x7f)
01023 {
01024 string[i] = LL_UNKNOWN_CHAR;
01025 }
01026 }
01027 }
01028
01029
01030 template<class T>
01031 void LLStringBase<T>::copy( T* dst, const T* src, size_type dst_size )
01032 {
01033 if( dst_size > 0 )
01034 {
01035 size_type min_len = 0;
01036 if( src )
01037 {
01038 min_len = llmin( dst_size - 1, strlen( src ) );
01039 memcpy(dst, src, min_len * sizeof(T));
01040 }
01041 dst[min_len] = '\0';
01042 }
01043 }
01044
01045
01046 template<class T>
01047 void LLStringBase<T>::copyInto(std::basic_string<T>& dst, const std::basic_string<T>& src, size_type offset)
01048 {
01049 if ( offset == dst.length() )
01050 {
01051
01052
01053 dst += src;
01054 }
01055 else
01056 {
01057 std::basic_string<T> tail = dst.substr(offset);
01058
01059 dst = dst.substr(0, offset);
01060 dst += src;
01061 dst += tail;
01062 };
01063 }
01064
01065
01066
01067 template<class T>
01068 BOOL LLStringBase<T>::isHead( const std::basic_string<T>& string, const T* s )
01069 {
01070 if( string.empty() )
01071 {
01072
01073 return FALSE;
01074 }
01075 else
01076 {
01077 return (strncmp( s, string.c_str(), string.size() ) == 0);
01078 }
01079 }
01080
01081 template<class T>
01082 BOOL LLStringBase<T>::convertToBOOL(const std::basic_string<T>& string, BOOL& value)
01083 {
01084 if( string.empty() )
01085 {
01086 return FALSE;
01087 }
01088
01089 LLStringBase<T> temp( string );
01090 trim(temp);
01091 if(
01092 (temp == "1") ||
01093 (temp == "T") ||
01094 (temp == "t") ||
01095 (temp == "TRUE") ||
01096 (temp == "true") ||
01097 (temp == "True") )
01098 {
01099 value = TRUE;
01100 return TRUE;
01101 }
01102 else
01103 if(
01104 (temp == "0") ||
01105 (temp == "F") ||
01106 (temp == "f") ||
01107 (temp == "FALSE") ||
01108 (temp == "false") ||
01109 (temp == "False") )
01110 {
01111 value = FALSE;
01112 return TRUE;
01113 }
01114
01115 return FALSE;
01116 }
01117
01118 template<class T>
01119 BOOL LLStringBase<T>::convertToU8(const std::basic_string<T>& string, U8& value)
01120 {
01121 S32 value32 = 0;
01122 BOOL success = convertToS32(string, value32);
01123 if( success && (U8_MIN <= value32) && (value32 <= U8_MAX) )
01124 {
01125 value = (U8) value32;
01126 return TRUE;
01127 }
01128 return FALSE;
01129 }
01130
01131 template<class T>
01132 BOOL LLStringBase<T>::convertToS8(const std::basic_string<T>& string, S8& value)
01133 {
01134 S32 value32 = 0;
01135 BOOL success = convertToS32(string, value32);
01136 if( success && (S8_MIN <= value32) && (value32 <= S8_MAX) )
01137 {
01138 value = (S8) value32;
01139 return TRUE;
01140 }
01141 return FALSE;
01142 }
01143
01144 template<class T>
01145 BOOL LLStringBase<T>::convertToS16(const std::basic_string<T>& string, S16& value)
01146 {
01147 S32 value32 = 0;
01148 BOOL success = convertToS32(string, value32);
01149 if( success && (S16_MIN <= value32) && (value32 <= S16_MAX) )
01150 {
01151 value = (S16) value32;
01152 return TRUE;
01153 }
01154 return FALSE;
01155 }
01156
01157 template<class T>
01158 BOOL LLStringBase<T>::convertToU16(const std::basic_string<T>& string, U16& value)
01159 {
01160 S32 value32 = 0;
01161 BOOL success = convertToS32(string, value32);
01162 if( success && (U16_MIN <= value32) && (value32 <= U16_MAX) )
01163 {
01164 value = (U16) value32;
01165 return TRUE;
01166 }
01167 return FALSE;
01168 }
01169
01170 template<class T>
01171 BOOL LLStringBase<T>::convertToU32(const std::basic_string<T>& string, U32& value)
01172 {
01173 if( string.empty() )
01174 {
01175 return FALSE;
01176 }
01177
01178 LLStringBase<T> temp( string );
01179 trim(temp);
01180 U32 v;
01181 std::basic_istringstream<T> i_stream((std::basic_string<T>)temp);
01182 if(i_stream >> v)
01183 {
01184
01185
01186
01187
01188
01189
01190
01191 value = v;
01192 return TRUE;
01193 }
01194 return FALSE;
01195 }
01196
01197 template<class T>
01198 BOOL LLStringBase<T>::convertToS32(const std::basic_string<T>& string, S32& value)
01199 {
01200 if( string.empty() )
01201 {
01202 return FALSE;
01203 }
01204
01205 LLStringBase<T> temp( string );
01206 trim(temp);
01207 S32 v;
01208 std::basic_istringstream<T> i_stream((std::basic_string<T>)temp);
01209 if(i_stream >> v)
01210 {
01211
01212
01213
01214
01215
01216
01217
01218 value = v;
01219 return TRUE;
01220 }
01221 return FALSE;
01222 }
01223
01224 template<class T>
01225 BOOL LLStringBase<T>::convertToF32(const std::basic_string<T>& string, F32& value)
01226 {
01227 F64 value64 = 0.0;
01228 BOOL success = convertToF64(string, value64);
01229 if( success && (-F32_MAX <= value64) && (value64 <= F32_MAX) )
01230 {
01231 value = (F32) value64;
01232 return TRUE;
01233 }
01234 return FALSE;
01235 }
01236
01237 template<class T>
01238 BOOL LLStringBase<T>::convertToF64(const std::basic_string<T>& string, F64& value)
01239 {
01240 if( string.empty() )
01241 {
01242 return FALSE;
01243 }
01244
01245 LLStringBase<T> temp( string );
01246 trim(temp);
01247 F64 v;
01248 std::basic_istringstream<T> i_stream((std::basic_string<T>)temp);
01249 if(i_stream >> v)
01250 {
01251
01252
01253
01254
01255
01256
01257
01258 value = v;
01259 return TRUE;
01260 }
01261 return FALSE;
01262 }
01263
01264 template<class T>
01265 void LLStringBase<T>::truncate(std::basic_string<T>& string, size_type count)
01266 {
01267 size_type cur_size = string.size();
01268 string.resize(count < cur_size ? count : cur_size);
01269 }
01270
01271 #endif // LL_STRING_H