llstring.h

Go to the documentation of this file.
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 // Template specialization of char_traits for U16s. Only necessary on Mac for now (exists on Windows, unused/broken on Linux/gcc2.95)
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))); }       /* Flawfinder: ignore */
00100         
00101         static char_type* 
00102                 assign(char_type* __s, size_t __n, char_type __a)
00103         { 
00104                 // This isn't right.
00105                 //return static_cast<char_type*>(memset(__s, __a, __n * sizeof(char_type))); 
00106                 
00107                 // I don't think there's a standard 'memset' for 16-bit values.
00108                 // Do this the old-fashioned way.
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 //RN: I used a templated base class instead of a pure interface class to minimize code duplication
00166 // but it might be worthwhile to just go with two implementations (LLString and LLWString) of
00167 // an interface class, unless we can think of a good reason to have a std::basic_string polymorphic base
00168 
00169 //****************************************************************
00170 // NOTA BENE: do *NOT* dynamically allocate memory inside of LLStringBase as the {*()^#%*)#%W^*)#%*)STL implentation
00171 // of basic_string doesn't provide a virtual destructor.  If we need to allocate resources specific to LLString
00172 // then we should either customize std::basic_string to linden::basic_string or change LLString to be a wrapper
00173 // that contains an instance of std::basic_string.  Similarly, overriding methods defined in std::basic_string will *not*
00174 // be called in a polymorphic manner (passing an instance of basic_string to a particular function)
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         // naming convention follows those set for LLUUID
00184 //      static LLStringBase null; // deprecated for std::string compliance
00185 //      static LLStringBase zero_length; // deprecated for std::string compliance
00186         
00187         
00188         // standard constructors
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         // custom constructors
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     // workaround for bug in gcc2 STL headers.
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         //terminate ();
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         // Static Utility functions that operate on std::strings
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         // True if this is the head of s.
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         // Conversion to other data types
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         // Utility functions for working with char*'s and strings
00288 
00289         // Like strcmp but also handles empty strings. Uses
00290         // current locale.
00291         static S32              compareStrings(const T* lhs, const T* rhs);
00292         
00293         // case insensitive version of above. Uses current locale on
00294         // Win32, and falls back to a non-locale aware comparison on
00295         // Linux.
00296         static S32              compareInsensitive(const T* lhs, const T* rhs);
00297 
00298         // Case sensitive comparison with good handling of numbers.  Does not use current locale.
00299         // a.k.a. strdictcmp()
00300         static S32              compareDict(const std::basic_string<T>& a, const std::basic_string<T>& b);
00301 
00302         // Puts compareDict() in a form appropriate for LL container classes to use for sorting.
00303         static BOOL             precedesDict( const std::basic_string<T>& a, const std::basic_string<T>& b );
00304 
00305         // A replacement for strncpy.
00306         // If the dst buffer is dst_size bytes long or more, ensures that dst is null terminated and holds
00307         // up to dst_size-1 characters of src.
00308         static void             copy(T* dst, const T* src, size_type dst_size);
00309         
00310         // Copies src into dst at a given offset.  
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 //@ Use this where we want to disallow input in the form of "foo"
00325 //  This is used to catch places where english text is embedded in the code
00326 //  instead of in a translatable XUI file.
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 // Make the incoming string a utf8 string. Replaces any unknown glyph
00393 // with the UNKOWN_CHARACTER. Once any unknown glph is found, the rest
00394 // of the data may not be recovered.
00395 std::string rawstr_to_utf8(const std::string& raw);
00396 
00397 //
00398 // We should never use UTF16 except when communicating with Win32!
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 // Same function, better name. JC
00414 inline LLWString utf8string_to_wstring(const std::string& utf8_string) { return utf8str_to_wstring(utf8_string); }
00415 
00416 // Special hack for llfilepicker.cpp:
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 // Length of this UTF32 string in bytes when transformed to UTF8
00429 S32 wstring_utf8_length(const LLWString& wstr); 
00430 
00431 // Length in bytes of this wide char in a UTF8 string
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 // Hack - used for evil notecards.
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 // static
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 // static
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 // static
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 // Case sensitive comparison with good handling of numbers.  Does not use current locale.
00629 // a.k.a. strdictcmp()
00630 
00631 //static 
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 // Puts compareDict() in a form appropriate for LL container classes to use for sorting.
00673 // static 
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 // Constructors
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 // Init from a substring
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 //static
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 //static
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 //static
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 //static
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 // Replace line feeds with carriage return-line feed pairs.
00848 //static
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         // Count the number of line feeds
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         // Insert a carriage return before each line feed
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 // Remove all carriage returns
00889 //static
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 //static
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 //static
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 //      const S8 MAX = 127;
00930 
00931         size_type len = string.size();
00932         for( size_type i = 0; i < len; i++ )
00933         {
00934                 // No need to test MAX < mText[i] because we treat mText[i] as a signed char,
00935                 // which has a max value of 127.
00936                 if( ( S8(string[i]) < MIN ) && (string[i] != LF) )
00937                 {
00938                         string[i] = replacement;
00939                 }
00940         }
00941 }
00942 
00943 //static
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         // Replace tabs with spaces
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 //static
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 //static
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());       /*Flawfinder: ignore*/
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         // Replace non-ASCII chars with LL_UNKNOWN_CHAR
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 // static
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 ) );  /* Flawfinder: ignore */
01039                         memcpy(dst, src, min_len * sizeof(T));          /* Flawfinder: ignore */
01040                 }
01041                 dst[min_len] = '\0';
01042         }
01043 }
01044 
01045 // static
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                 // special case - append to end of string and avoid expensive
01052                 // (when strings are large) string manipulations
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 // True if this is the head of s.
01066 //static
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                 // Early exit
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                 //TODO: figure out overflow reporting here
01185                 //if( ULONG_MAX == v )
01186                 //{
01187                 //      // Underflow or overflow
01188                 //      return FALSE;
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                 //TODO: figure out overflow and underflow reporting here
01212                 //if((LONG_MAX == v) || (LONG_MIN == v))
01213                 //{
01214                 //      // Underflow or overflow
01215                 //      return FALSE;
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                 //TODO: figure out overflow and underflow reporting here
01252                 //if( ((-HUGE_VAL == v) || (HUGE_VAL == v))) )
01253                 //{
01254                 //      // Underflow or overflow
01255                 //      return FALSE;
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

Generated on Thu Jul 1 06:09:14 2010 for Second Life Viewer by  doxygen 1.4.7