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         // Case *in*sensitive comparison with good handling of numbers.  Does not use current locale.
00303         // a.k.a. strdictcmp()
00304         static S32              compareDictInsensitive(const std::basic_string<T>& a, const std::basic_string<T>& b);
00305 
00306         // Puts compareDict() in a form appropriate for LL container classes to use for sorting.
00307         static BOOL             precedesDict( const std::basic_string<T>& a, const std::basic_string<T>& b );
00308 
00309         // A replacement for strncpy.
00310         // If the dst buffer is dst_size bytes long or more, ensures that dst is null terminated and holds
00311         // up to dst_size-1 characters of src.
00312         static void             copy(T* dst, const T* src, size_type dst_size);
00313         
00314         // Copies src into dst at a given offset.  
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 //@ Use this where we want to disallow input in the form of "foo"
00329 //  This is used to catch places where english text is embedded in the code
00330 //  instead of in a translatable XUI file.
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 // Make the incoming string a utf8 string. Replaces any unknown glyph
00397 // with the UNKOWN_CHARACTER. Once any unknown glph is found, the rest
00398 // of the data may not be recovered.
00399 std::string rawstr_to_utf8(const std::string& raw);
00400 
00401 //
00402 // We should never use UTF16 except when communicating with Win32!
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 // Same function, better name. JC
00418 inline LLWString utf8string_to_wstring(const std::string& utf8_string) { return utf8str_to_wstring(utf8_string); }
00419 
00420 // Special hack for llfilepicker.cpp:
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 // Length of this UTF32 string in bytes when transformed to UTF8
00433 S32 wstring_utf8_length(const LLWString& wstr); 
00434 
00435 // Length in bytes of this wide char in a UTF8 string
00436 S32 wchar_utf8_length(const llwchar wc); 
00437 
00438 std::string utf8str_tolower(const std::string& utf8str);
00439 
00440 // Length in llwchar (UTF-32) of the first len units (16 bits) of the given UTF-16 string.
00441 S32 utf16str_wstring_length(const llutf16string &utf16str, S32 len);
00442 
00443 // Length in utf16string (UTF-16) of wlen wchars beginning at woffset.
00444 S32 wstring_utf16_length(const LLWString & wstr, S32 woffset, S32 wlen);
00445 
00446 // Length in wstring (i.e., llwchar count) of a part of a wstring specified by utf16 length (i.e., utf16 units.)
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 // Hack - used for evil notecards.
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 /* @name Windows string helpers
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 // static
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 // static
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 // static
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 // Case sensitive comparison with good handling of numbers.  Does not use current locale.
00672 // a.k.a. strdictcmp()
00673 
00674 //static 
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 // Puts compareDict() in a form appropriate for LL container classes to use for sorting.
00749 // static 
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 // Constructors
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 // Init from a substring
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 //static
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 //static
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 //static
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 //static
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 // Replace line feeds with carriage return-line feed pairs.
00924 //static
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         // Count the number of line feeds
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         // Insert a carriage return before each line feed
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 // Remove all carriage returns
00965 //static
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 //static
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 //static
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 //      const S8 MAX = 127;
01006 
01007         size_type len = string.size();
01008         for( size_type i = 0; i < len; i++ )
01009         {
01010                 // No need to test MAX < mText[i] because we treat mText[i] as a signed char,
01011                 // which has a max value of 127.
01012                 if( ( S8(string[i]) < MIN ) && (string[i] != LF) )
01013                 {
01014                         string[i] = replacement;
01015                 }
01016         }
01017 }
01018 
01019 //static
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         // Replace tabs with spaces
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 //static
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 //static
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());       /*Flawfinder: ignore*/
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         // Replace non-ASCII chars with LL_UNKNOWN_CHAR
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 // static
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 ) );  /* Flawfinder: ignore */
01115                         memcpy(dst, src, min_len * sizeof(T));          /* Flawfinder: ignore */
01116                 }
01117                 dst[min_len] = '\0';
01118         }
01119 }
01120 
01121 // static
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                 // special case - append to end of string and avoid expensive
01128                 // (when strings are large) string manipulations
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 // True if this is the head of s.
01142 //static
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                 // Early exit
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                 //TODO: figure out overflow reporting here
01261                 //if( ULONG_MAX == v )
01262                 //{
01263                 //      // Underflow or overflow
01264                 //      return FALSE;
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                 //TODO: figure out overflow and underflow reporting here
01288                 //if((LONG_MAX == v) || (LONG_MIN == v))
01289                 //{
01290                 //      // Underflow or overflow
01291                 //      return FALSE;
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                 //TODO: figure out overflow and underflow reporting here
01328                 //if( ((-HUGE_VAL == v) || (HUGE_VAL == v))) )
01329                 //{
01330                 //      // Underflow or overflow
01331                 //      return FALSE;
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

Generated on Fri May 16 08:32:09 2008 for SecondLife by  doxygen 1.5.5