llstring.h
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:36k
源码类别:

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file llstring.h
  3.  * @brief String utility functions and std::string class.
  4.  *
  5.  * $LicenseInfo:firstyear=2001&license=viewergpl$
  6.  * 
  7.  * Copyright (c) 2001-2010, Linden Research, Inc.
  8.  * 
  9.  * Second Life Viewer Source Code
  10.  * The source code in this file ("Source Code") is provided by Linden Lab
  11.  * to you under the terms of the GNU General Public License, version 2.0
  12.  * ("GPL"), unless you have obtained a separate licensing agreement
  13.  * ("Other License"), formally executed by you and Linden Lab.  Terms of
  14.  * the GPL can be found in doc/GPL-license.txt in this distribution, or
  15.  * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  16.  * 
  17.  * There are special exceptions to the terms and conditions of the GPL as
  18.  * it is applied to this Source Code. View the full text of the exception
  19.  * in the file doc/FLOSS-exception.txt in this software distribution, or
  20.  * online at
  21.  * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  22.  * 
  23.  * By copying, modifying or distributing this software, you acknowledge
  24.  * that you have read and understood your obligations described above,
  25.  * and agree to abide by those obligations.
  26.  * 
  27.  * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  28.  * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  29.  * COMPLETENESS OR PERFORMANCE.
  30.  * $/LicenseInfo$
  31.  */
  32. #ifndef LL_LLSTRING_H
  33. #define LL_LLSTRING_H
  34. #include <string>
  35. #include <cstdio>
  36. #include <locale>
  37. #include <iomanip>
  38. #include "llsd.h"
  39. #include "llfasttimer.h"
  40. #if LL_LINUX || LL_SOLARIS
  41. #include <wctype.h>
  42. #include <wchar.h>
  43. #endif
  44. #include <string.h>
  45. #if LL_SOLARIS
  46. // stricmp and strnicmp do not exist on Solaris:
  47. #define stricmp strcasecmp
  48. #define strnicmp strncasecmp
  49. #endif
  50. const char LL_UNKNOWN_CHAR = '?';
  51. #if LL_DARWIN || LL_LINUX || LL_SOLARIS
  52. // Template specialization of char_traits for U16s. Only necessary on Mac and Linux (exists on Windows already)
  53. #include <cstring>
  54. namespace std
  55. {
  56. template<>
  57. struct char_traits<U16>
  58. {
  59. typedef U16  char_type;
  60. typedef int      int_type;
  61. typedef streampos  pos_type;
  62. typedef streamoff  off_type;
  63. typedef mbstate_t  state_type;
  64. static void 
  65. assign(char_type& __c1, const char_type& __c2)
  66. { __c1 = __c2; }
  67. static bool 
  68. eq(const char_type& __c1, const char_type& __c2)
  69. { return __c1 == __c2; }
  70. static bool 
  71. lt(const char_type& __c1, const char_type& __c2)
  72. { return __c1 < __c2; }
  73. static int 
  74. compare(const char_type* __s1, const char_type* __s2, size_t __n)
  75. { return memcmp(__s1, __s2, __n * sizeof(char_type)); }
  76. static size_t
  77. length(const char_type* __s)
  78. {
  79. const char_type *cur_char = __s;
  80. while (*cur_char != 0)
  81. {
  82. ++cur_char;
  83. }
  84. return cur_char - __s;
  85. }
  86. static const char_type* 
  87. find(const char_type* __s, size_t __n, const char_type& __a)
  88. { return static_cast<const char_type*>(memchr(__s, __a, __n * sizeof(char_type))); }
  89. static char_type* 
  90. move(char_type* __s1, const char_type* __s2, size_t __n)
  91. { return static_cast<char_type*>(memmove(__s1, __s2, __n * sizeof(char_type))); }
  92. static char_type* 
  93. copy(char_type* __s1, const char_type* __s2, size_t __n)
  94. {  return static_cast<char_type*>(memcpy(__s1, __s2, __n * sizeof(char_type))); } /* Flawfinder: ignore */
  95. static char_type* 
  96. assign(char_type* __s, size_t __n, char_type __a)
  97. // This isn't right.
  98. //return static_cast<char_type*>(memset(__s, __a, __n * sizeof(char_type))); 
  99. // I don't think there's a standard 'memset' for 16-bit values.
  100. // Do this the old-fashioned way.
  101. size_t __i;
  102. for(__i = 0; __i < __n; __i++)
  103. {
  104. __s[__i] = __a;
  105. }
  106. return __s; 
  107. }
  108. static char_type 
  109. to_char_type(const int_type& __c)
  110. { return static_cast<char_type>(__c); }
  111. static int_type 
  112. to_int_type(const char_type& __c)
  113. { return static_cast<int_type>(__c); }
  114. static bool 
  115. eq_int_type(const int_type& __c1, const int_type& __c2)
  116. { return __c1 == __c2; }
  117. static int_type 
  118. eof() { return static_cast<int_type>(EOF); }
  119. static int_type 
  120. not_eof(const int_type& __c)
  121.       { return (__c == eof()) ? 0 : __c; }
  122.   };
  123. };
  124. #endif
  125. class LL_COMMON_API LLStringOps
  126. {
  127. private:
  128. static long sPacificTimeOffset;
  129. static long sLocalTimeOffset;
  130. static bool sPacificDaylightTime;
  131. static std::map<std::string, std::string> datetimeToCodes;
  132. public:
  133. static char toUpper(char elem) { return toupper((unsigned char)elem); }
  134. static llwchar toUpper(llwchar elem) { return towupper(elem); }
  135. static char toLower(char elem) { return tolower((unsigned char)elem); }
  136. static llwchar toLower(llwchar elem) { return towlower(elem); }
  137. static bool isSpace(char elem) { return isspace((unsigned char)elem) != 0; }
  138. static bool isSpace(llwchar elem) { return iswspace(elem) != 0; }
  139. static bool isUpper(char elem) { return isupper((unsigned char)elem) != 0; }
  140. static bool isUpper(llwchar elem) { return iswupper(elem) != 0; }
  141. static bool isLower(char elem) { return islower((unsigned char)elem) != 0; }
  142. static bool isLower(llwchar elem) { return iswlower(elem) != 0; }
  143. static bool isDigit(char a) { return isdigit((unsigned char)a) != 0; }
  144. static bool isDigit(llwchar a) { return iswdigit(a) != 0; }
  145. static bool isPunct(char a) { return ispunct((unsigned char)a) != 0; }
  146. static bool isPunct(llwchar a) { return iswpunct(a) != 0; }
  147. static bool isAlnum(char a) { return isalnum((unsigned char)a) != 0; }
  148. static bool isAlnum(llwchar a) { return iswalnum(a) != 0; }
  149. static S32 collate(const char* a, const char* b) { return strcoll(a, b); }
  150. static S32 collate(const llwchar* a, const llwchar* b);
  151. static void setupDatetimeInfo(bool pacific_daylight_time);
  152. static long getPacificTimeOffset(void) { return sPacificTimeOffset;}
  153. static long getLocalTimeOffset(void) { return sLocalTimeOffset;}
  154. // Is the Pacific time zone (aka server time zone)
  155. // currently in daylight savings time?
  156. static bool getPacificDaylightTime(void) { return sPacificDaylightTime;}
  157. static std::string getDatetimeCode (std::string key);
  158. };
  159. /**
  160.  * @brief Return a string constructed from in without crashing if the
  161.  * pointer is NULL.
  162.  */
  163. LL_COMMON_API std::string ll_safe_string(const char* in);
  164. LL_COMMON_API std::string ll_safe_string(const char* in, S32 maxlen);
  165. // Allowing assignments from non-strings into format_map_t is apparently
  166. // *really* error-prone, so subclass std::string with just basic c'tors.
  167. class LLFormatMapString
  168. {
  169. public:
  170. LLFormatMapString() {};
  171. LLFormatMapString(const char* s) : mString(ll_safe_string(s)) {};
  172. LLFormatMapString(const std::string& s) : mString(s) {};
  173. operator std::string() const { return mString; }
  174. bool operator<(const LLFormatMapString& rhs) const { return mString < rhs.mString; }
  175. std::size_t length() const { return mString.length(); }
  176. private:
  177. std::string mString;
  178. };
  179. template <class T>
  180. class LLStringUtilBase
  181. {
  182. private:
  183. static std::string sLocale;
  184. public:
  185. typedef typename std::basic_string<T>::size_type size_type;
  186. public:
  187. /////////////////////////////////////////////////////////////////////////////////////////
  188. // Static Utility functions that operate on std::strings
  189. static std::basic_string<T> null;
  190. typedef std::map<LLFormatMapString, LLFormatMapString> format_map_t;
  191. LL_COMMON_API static void getTokens(const std::basic_string<T>& instr, std::vector<std::basic_string<T> >& tokens, const std::basic_string<T>& delims);
  192. LL_COMMON_API static void formatNumber(std::basic_string<T>& numStr, std::basic_string<T> decimals);
  193. LL_COMMON_API static bool formatDatetime(std::basic_string<T>& replacement, std::basic_string<T> token, std::basic_string<T> param, S32 secFromEpoch);
  194. LL_COMMON_API static S32 format(std::basic_string<T>& s, const format_map_t& substitutions);
  195. LL_COMMON_API static S32 format(std::basic_string<T>& s, const LLSD& substitutions);
  196. LL_COMMON_API static bool simpleReplacement(std::basic_string<T>& replacement, std::basic_string<T> token, const format_map_t& substitutions);
  197. LL_COMMON_API static bool simpleReplacement(std::basic_string<T>& replacement, std::basic_string<T> token, const LLSD& substitutions);
  198. static void setLocale (std::string inLocale) {sLocale = inLocale;};
  199. static std::string getLocale (void) {return sLocale;};
  200. static bool isValidIndex(const std::basic_string<T>& string, size_type i)
  201. {
  202. return !string.empty() && (0 <= i) && (i <= string.size());
  203. }
  204. static void trimHead(std::basic_string<T>& string);
  205. static void trimTail(std::basic_string<T>& string);
  206. static void trim(std::basic_string<T>& string) { trimHead(string); trimTail(string); }
  207. static void truncate(std::basic_string<T>& string, size_type count);
  208. static void toUpper(std::basic_string<T>& string);
  209. static void toLower(std::basic_string<T>& string);
  210. // True if this is the head of s.
  211. static BOOL isHead( const std::basic_string<T>& string, const T* s ); 
  212. /**
  213.  * @brief Returns true if string starts with substr
  214.  *
  215.  * If etither string or substr are empty, this method returns false.
  216.  */
  217. static bool startsWith(
  218. const std::basic_string<T>& string,
  219. const std::basic_string<T>& substr);
  220. /**
  221.  * @brief Returns true if string ends in substr
  222.  *
  223.  * If etither string or substr are empty, this method returns false.
  224.  */
  225. static bool endsWith(
  226. const std::basic_string<T>& string,
  227. const std::basic_string<T>& substr);
  228. static void addCRLF(std::basic_string<T>& string);
  229. static void removeCRLF(std::basic_string<T>& string);
  230. static void replaceTabsWithSpaces( std::basic_string<T>& string, size_type spaces_per_tab );
  231. static void replaceNonstandardASCII( std::basic_string<T>& string, T replacement );
  232. static void replaceChar( std::basic_string<T>& string, T target, T replacement );
  233. static void replaceString( std::basic_string<T>& string, std::basic_string<T> target, std::basic_string<T> replacement );
  234. static BOOL containsNonprintable(const std::basic_string<T>& string);
  235. static void stripNonprintable(std::basic_string<T>& string);
  236. /**
  237.  * @brief Unsafe way to make ascii characters. You should probably
  238.  * only call this when interacting with the host operating system.
  239.  * The 1 byte std::string does not work correctly.
  240.  * The 2 and 4 byte std::string probably work, so LLWStringUtil::_makeASCII
  241.  * should work.
  242.  */
  243. static void _makeASCII(std::basic_string<T>& string);
  244. // Conversion to other data types
  245. static BOOL convertToBOOL(const std::basic_string<T>& string, BOOL& value);
  246. static BOOL convertToU8(const std::basic_string<T>& string, U8& value);
  247. static BOOL convertToS8(const std::basic_string<T>& string, S8& value);
  248. static BOOL convertToS16(const std::basic_string<T>& string, S16& value);
  249. static BOOL convertToU16(const std::basic_string<T>& string, U16& value);
  250. static BOOL convertToU32(const std::basic_string<T>& string, U32& value);
  251. static BOOL convertToS32(const std::basic_string<T>& string, S32& value);
  252. static BOOL convertToF32(const std::basic_string<T>& string, F32& value);
  253. static BOOL convertToF64(const std::basic_string<T>& string, F64& value);
  254. /////////////////////////////////////////////////////////////////////////////////////////
  255. // Utility functions for working with char*'s and strings
  256. // Like strcmp but also handles empty strings. Uses
  257. // current locale.
  258. static S32 compareStrings(const T* lhs, const T* rhs);
  259. static S32 compareStrings(const std::basic_string<T>& lhs, const std::basic_string<T>& rhs);
  260. // case insensitive version of above. Uses current locale on
  261. // Win32, and falls back to a non-locale aware comparison on
  262. // Linux.
  263. static S32 compareInsensitive(const T* lhs, const T* rhs);
  264. static S32 compareInsensitive(const std::basic_string<T>& lhs, const std::basic_string<T>& rhs);
  265. // Case sensitive comparison with good handling of numbers.  Does not use current locale.
  266. // a.k.a. strdictcmp()
  267. static S32 compareDict(const std::basic_string<T>& a, const std::basic_string<T>& b);
  268. // Case *in*sensitive comparison with good handling of numbers.  Does not use current locale.
  269. // a.k.a. strdictcmp()
  270. static S32 compareDictInsensitive(const std::basic_string<T>& a, const std::basic_string<T>& b);
  271. // Puts compareDict() in a form appropriate for LL container classes to use for sorting.
  272. static BOOL precedesDict( const std::basic_string<T>& a, const std::basic_string<T>& b );
  273. // A replacement for strncpy.
  274. // If the dst buffer is dst_size bytes long or more, ensures that dst is null terminated and holds
  275. // up to dst_size-1 characters of src.
  276. static void copy(T* dst, const T* src, size_type dst_size);
  277. // Copies src into dst at a given offset.  
  278. static void copyInto(std::basic_string<T>& dst, const std::basic_string<T>& src, size_type offset);
  279. static bool isPartOfWord(T c) { return (c == (T)'_') || LLStringOps::isAlnum(c); }
  280. #ifdef _DEBUG
  281. LL_COMMON_API static void testHarness();
  282. #endif
  283. private:
  284. LL_COMMON_API static size_type getSubstitution(const std::basic_string<T>& instr, size_type& start, std::vector<std::basic_string<T> >& tokens);
  285. };
  286. template<class T> std::basic_string<T> LLStringUtilBase<T>::null;
  287. template<class T> std::string LLStringUtilBase<T>::sLocale;
  288. typedef LLStringUtilBase<char> LLStringUtil;
  289. typedef LLStringUtilBase<llwchar> LLWStringUtil;
  290. typedef std::basic_string<llwchar> LLWString;
  291. //@ Use this where we want to disallow input in the form of "foo"
  292. //  This is used to catch places where english text is embedded in the code
  293. //  instead of in a translatable XUI file.
  294. class LLStringExplicit : public std::string
  295. {
  296. public:
  297. explicit LLStringExplicit(const char* s) : std::string(s) {}
  298. LLStringExplicit(const std::string& s) : std::string(s) {}
  299. LLStringExplicit(const std::string& s, size_type pos, size_type n = std::string::npos) : std::string(s, pos, n) {}
  300. };
  301. struct LLDictionaryLess
  302. {
  303. public:
  304. bool operator()(const std::string& a, const std::string& b)
  305. {
  306. return (LLStringUtil::precedesDict(a, b) ? true : false);
  307. }
  308. };
  309. /**
  310.  * Simple support functions
  311.  */
  312. /**
  313.  * @brief chop off the trailing characters in a string.
  314.  *
  315.  * This function works on bytes rather than glyphs, so this will
  316.  * incorrectly truncate non-single byte strings.
  317.  * Use utf8str_truncate() for utf8 strings
  318.  * @return a copy of in string minus the trailing count bytes.
  319.  */
  320. inline std::string chop_tail_copy(
  321. const std::string& in,
  322. std::string::size_type count)
  323. {
  324. return std::string(in, 0, in.length() - count);
  325. }
  326. /**
  327.  * @brief This translates a nybble stored as a hex value from 0-f back
  328.  * to a nybble in the low order bits of the return byte.
  329.  */
  330. LL_COMMON_API U8 hex_as_nybble(char hex);
  331. /**
  332.  * @brief read the contents of a file into a string.
  333.  *
  334.  * Since this function has no concept of character encoding, most
  335.  * anything you do with this method ill-advised. Please avoid.
  336.  * @param str [out] The string which will have.
  337.  * @param filename The full name of the file to read.
  338.  * @return Returns true on success. If false, str is unmodified.
  339.  */
  340. LL_COMMON_API bool _read_file_into_string(std::string& str, const std::string& filename);
  341. LL_COMMON_API bool iswindividual(llwchar elem);
  342. /**
  343.  * Unicode support
  344.  */
  345. // Make the incoming string a utf8 string. Replaces any unknown glyph
  346. // with the UNKOWN_CHARACTER. Once any unknown glph is found, the rest
  347. // of the data may not be recovered.
  348. LL_COMMON_API std::string rawstr_to_utf8(const std::string& raw);
  349. //
  350. // We should never use UTF16 except when communicating with Win32!
  351. //
  352. typedef std::basic_string<U16> llutf16string;
  353. LL_COMMON_API LLWString utf16str_to_wstring(const llutf16string &utf16str, S32 len);
  354. LL_COMMON_API LLWString utf16str_to_wstring(const llutf16string &utf16str);
  355. LL_COMMON_API llutf16string wstring_to_utf16str(const LLWString &utf32str, S32 len);
  356. LL_COMMON_API llutf16string wstring_to_utf16str(const LLWString &utf32str);
  357. LL_COMMON_API llutf16string utf8str_to_utf16str ( const std::string& utf8str, S32 len);
  358. LL_COMMON_API llutf16string utf8str_to_utf16str ( const std::string& utf8str );
  359. LL_COMMON_API LLWString utf8str_to_wstring(const std::string &utf8str, S32 len);
  360. LL_COMMON_API LLWString utf8str_to_wstring(const std::string &utf8str);
  361. // Same function, better name. JC
  362. inline LLWString utf8string_to_wstring(const std::string& utf8_string) { return utf8str_to_wstring(utf8_string); }
  363. //
  364. LL_COMMON_API S32 wchar_to_utf8chars(llwchar inchar, char* outchars);
  365. LL_COMMON_API std::string wstring_to_utf8str(const LLWString &utf32str, S32 len);
  366. LL_COMMON_API std::string wstring_to_utf8str(const LLWString &utf32str);
  367. LL_COMMON_API std::string utf16str_to_utf8str(const llutf16string &utf16str, S32 len);
  368. LL_COMMON_API std::string utf16str_to_utf8str(const llutf16string &utf16str);
  369. // Length of this UTF32 string in bytes when transformed to UTF8
  370. LL_COMMON_API S32 wstring_utf8_length(const LLWString& wstr); 
  371. // Length in bytes of this wide char in a UTF8 string
  372. LL_COMMON_API S32 wchar_utf8_length(const llwchar wc); 
  373. LL_COMMON_API std::string utf8str_tolower(const std::string& utf8str);
  374. // Length in llwchar (UTF-32) of the first len units (16 bits) of the given UTF-16 string.
  375. LL_COMMON_API S32 utf16str_wstring_length(const llutf16string &utf16str, S32 len);
  376. // Length in utf16string (UTF-16) of wlen wchars beginning at woffset.
  377. LL_COMMON_API S32 wstring_utf16_length(const LLWString & wstr, S32 woffset, S32 wlen);
  378. // Length in wstring (i.e., llwchar count) of a part of a wstring specified by utf16 length (i.e., utf16 units.)
  379. LL_COMMON_API S32 wstring_wstring_length_from_utf16_length(const LLWString & wstr, S32 woffset, S32 utf16_length, BOOL *unaligned = NULL);
  380. /**
  381.  * @brief Properly truncate a utf8 string to a maximum byte count.
  382.  * 
  383.  * The returned string may be less than max_len if the truncation
  384.  * happens in the middle of a glyph. If max_len is longer than the
  385.  * string passed in, the return value == utf8str.
  386.  * @param utf8str A valid utf8 string to truncate.
  387.  * @param max_len The maximum number of bytes in the return value.
  388.  * @return Returns a valid utf8 string with byte count <= max_len.
  389.  */
  390. LL_COMMON_API std::string utf8str_truncate(const std::string& utf8str, const S32 max_len);
  391. LL_COMMON_API std::string utf8str_trim(const std::string& utf8str);
  392. LL_COMMON_API S32 utf8str_compare_insensitive(
  393. const std::string& lhs,
  394. const std::string& rhs);
  395. /**
  396.  * @brief Replace all occurences of target_char with replace_char
  397.  *
  398.  * @param utf8str A utf8 string to process.
  399.  * @param target_char The wchar to be replaced
  400.  * @param replace_char The wchar which is written on replace
  401.  */
  402. LL_COMMON_API std::string utf8str_substChar(
  403. const std::string& utf8str,
  404. const llwchar target_char,
  405. const llwchar replace_char);
  406. LL_COMMON_API std::string utf8str_makeASCII(const std::string& utf8str);
  407. // Hack - used for evil notecards.
  408. LL_COMMON_API std::string mbcsstring_makeASCII(const std::string& str); 
  409. LL_COMMON_API std::string utf8str_removeCRLF(const std::string& utf8str);
  410. #if LL_WINDOWS
  411. /* @name Windows string helpers
  412.  */
  413. //@{
  414. /**
  415.  * @brief Implementation the expected snprintf interface.
  416.  *
  417.  * If the size of the passed in buffer is not large enough to hold the string,
  418.  * two bad things happen:
  419.  * 1. resulting formatted string is NOT null terminated
  420.  * 2. Depending on the platform, the return value could be a) the required
  421.  *    size of the buffer to copy the entire formatted string or b) -1.
  422.  *    On Windows with VS.Net 2003, it returns -1 e.g. 
  423.  *
  424.  * safe_snprintf always adds a NULL terminator so that the caller does not
  425.  * need to check for return value or need to add the NULL terminator.
  426.  * It does not, however change the return value - to let the caller know
  427.  * that the passed in buffer size was not large enough to hold the
  428.  * formatted string.
  429.  *
  430.  */
  431. // Deal with the differeneces on Windows
  432. namespace snprintf_hack
  433. {
  434. LL_COMMON_API int snprintf(char *str, size_t size, const char *format, ...);
  435. }
  436. using snprintf_hack::snprintf;
  437. /**
  438.  * @brief Convert a wide string to std::string
  439.  *
  440.  * This replaces the unsafe W2A macro from ATL.
  441.  */
  442. LL_COMMON_API std::string ll_convert_wide_to_string(const wchar_t* in);
  443. //@}
  444. #endif // LL_WINDOWS
  445. /**
  446.  * Many of the 'strip' and 'replace' methods of LLStringUtilBase need
  447.  * specialization to work with the signed char type.
  448.  * Sadly, it is not possible (AFAIK) to specialize a single method of
  449.  * a template class.
  450.  * That stuff should go here.
  451.  */
  452. namespace LLStringFn
  453. {
  454. /**
  455.  * @brief Replace all non-printable characters with replacement in
  456.  * string.
  457.  * NOTE - this will zap non-ascii
  458.  *
  459.  * @param [in,out] string the to modify. out value is the string
  460.  * with zero non-printable characters.
  461.  * @param The replacement character. use LL_UNKNOWN_CHAR if unsure.
  462.  */
  463. LL_COMMON_API void replace_nonprintable_in_ascii(
  464. std::basic_string<char>& string,
  465. char replacement);
  466. /**
  467.  * @brief Replace all non-printable characters and pipe characters
  468.  * with replacement in a string.
  469.  * NOTE - this will zap non-ascii
  470.  *
  471.  * @param [in,out] the string to modify. out value is the string
  472.  * with zero non-printable characters and zero pipe characters.
  473.  * @param The replacement character. use LL_UNKNOWN_CHAR if unsure.
  474.  */
  475. LL_COMMON_API void replace_nonprintable_and_pipe_in_ascii(std::basic_string<char>& str,
  476.    char replacement);
  477. /**
  478.  * @brief Remove all characters that are not allowed in XML 1.0.
  479.  * Returns a copy of the string with those characters removed.
  480.  * Works with US ASCII and UTF-8 encoded strings.  JC
  481.  */
  482. LL_COMMON_API std::string strip_invalid_xml(const std::string& input);
  483. /**
  484.  * @brief Replace all control characters (0 <= c < 0x20) with replacement in
  485.  * string.   This is safe for utf-8
  486.  *
  487.  * @param [in,out] string the to modify. out value is the string
  488.  * with zero non-printable characters.
  489.  * @param The replacement character. use LL_UNKNOWN_CHAR if unsure.
  490.  */
  491. LL_COMMON_API void replace_ascii_controlchars(
  492. std::basic_string<char>& string,
  493. char replacement);
  494. }
  495. ////////////////////////////////////////////////////////////
  496. // NOTE: LLStringUtil::format, getTokens, and support functions moved to llstring.cpp.
  497. // There is no LLWStringUtil::format implementation currently.
  498. // Calling thse for anything other than LLStringUtil will produce link errors.
  499. ////////////////////////////////////////////////////////////
  500. // static
  501. template<class T> 
  502. S32 LLStringUtilBase<T>::compareStrings(const T* lhs, const T* rhs)
  503. {
  504. S32 result;
  505. if( lhs == rhs )
  506. {
  507. result = 0;
  508. }
  509. else
  510. if ( !lhs || !lhs[0] )
  511. {
  512. result = ((!rhs || !rhs[0]) ? 0 : 1);
  513. }
  514. else
  515. if ( !rhs || !rhs[0])
  516. {
  517. result = -1;
  518. }
  519. else
  520. {
  521. result = LLStringOps::collate(lhs, rhs);
  522. }
  523. return result;
  524. }
  525. //static 
  526. template<class T> 
  527. S32 LLStringUtilBase<T>::compareStrings(const std::basic_string<T>& lhs, const std::basic_string<T>& rhs)
  528. {
  529. return LLStringOps::collate(lhs.c_str(), rhs.c_str());
  530. }
  531. // static
  532. template<class T> 
  533. S32 LLStringUtilBase<T>::compareInsensitive(const T* lhs, const T* rhs )
  534. {
  535. S32 result;
  536. if( lhs == rhs )
  537. {
  538. result = 0;
  539. }
  540. else
  541. if ( !lhs || !lhs[0] )
  542. {
  543. result = ((!rhs || !rhs[0]) ? 0 : 1);
  544. }
  545. else
  546. if ( !rhs || !rhs[0] )
  547. {
  548. result = -1;
  549. }
  550. else
  551. {
  552. std::basic_string<T> lhs_string(lhs);
  553. std::basic_string<T> rhs_string(rhs);
  554. LLStringUtilBase<T>::toUpper(lhs_string);
  555. LLStringUtilBase<T>::toUpper(rhs_string);
  556. result = LLStringOps::collate(lhs_string.c_str(), rhs_string.c_str());
  557. }
  558. return result;
  559. }
  560. //static 
  561. template<class T> 
  562. S32 LLStringUtilBase<T>::compareInsensitive(const std::basic_string<T>& lhs, const std::basic_string<T>& rhs)
  563. {
  564. std::basic_string<T> lhs_string(lhs);
  565. std::basic_string<T> rhs_string(rhs);
  566. LLStringUtilBase<T>::toUpper(lhs_string);
  567. LLStringUtilBase<T>::toUpper(rhs_string);
  568. return LLStringOps::collate(lhs_string.c_str(), rhs_string.c_str());
  569. }
  570. // Case sensitive comparison with good handling of numbers.  Does not use current locale.
  571. // a.k.a. strdictcmp()
  572. //static 
  573. template<class T>
  574. S32 LLStringUtilBase<T>::compareDict(const std::basic_string<T>& astr, const std::basic_string<T>& bstr)
  575. {
  576. const T* a = astr.c_str();
  577. const T* b = bstr.c_str();
  578. T ca, cb;
  579. S32 ai, bi, cnt = 0;
  580. S32 bias = 0;
  581. ca = *(a++);
  582. cb = *(b++);
  583. while( ca && cb ){
  584. if( bias==0 ){
  585. if( LLStringOps::isUpper(ca) ){ ca = LLStringOps::toLower(ca); bias--; }
  586. if( LLStringOps::isUpper(cb) ){ cb = LLStringOps::toLower(cb); bias++; }
  587. }else{
  588. if( LLStringOps::isUpper(ca) ){ ca = LLStringOps::toLower(ca); }
  589. if( LLStringOps::isUpper(cb) ){ cb = LLStringOps::toLower(cb); }
  590. }
  591. if( LLStringOps::isDigit(ca) ){
  592. if( cnt-->0 ){
  593. if( cb!=ca ) break;
  594. }else{
  595. if( !LLStringOps::isDigit(cb) ) break;
  596. for(ai=0; LLStringOps::isDigit(a[ai]); ai++);
  597. for(bi=0; LLStringOps::isDigit(b[bi]); bi++);
  598. if( ai<bi ){ ca=0; break; }
  599. if( bi<ai ){ cb=0; break; }
  600. if( ca!=cb ) break;
  601. cnt = ai;
  602. }
  603. }else if( ca!=cb ){   break;
  604. }
  605. ca = *(a++);
  606. cb = *(b++);
  607. }
  608. if( ca==cb ) ca += bias;
  609. return ca-cb;
  610. }
  611. // static
  612. template<class T>
  613. S32 LLStringUtilBase<T>::compareDictInsensitive(const std::basic_string<T>& astr, const std::basic_string<T>& bstr)
  614. {
  615. const T* a = astr.c_str();
  616. const T* b = bstr.c_str();
  617. T ca, cb;
  618. S32 ai, bi, cnt = 0;
  619. ca = *(a++);
  620. cb = *(b++);
  621. while( ca && cb ){
  622. if( LLStringOps::isUpper(ca) ){ ca = LLStringOps::toLower(ca); }
  623. if( LLStringOps::isUpper(cb) ){ cb = LLStringOps::toLower(cb); }
  624. if( LLStringOps::isDigit(ca) ){
  625. if( cnt-->0 ){
  626. if( cb!=ca ) break;
  627. }else{
  628. if( !LLStringOps::isDigit(cb) ) break;
  629. for(ai=0; LLStringOps::isDigit(a[ai]); ai++);
  630. for(bi=0; LLStringOps::isDigit(b[bi]); bi++);
  631. if( ai<bi ){ ca=0; break; }
  632. if( bi<ai ){ cb=0; break; }
  633. if( ca!=cb ) break;
  634. cnt = ai;
  635. }
  636. }else if( ca!=cb ){   break;
  637. }
  638. ca = *(a++);
  639. cb = *(b++);
  640. }
  641. return ca-cb;
  642. }
  643. // Puts compareDict() in a form appropriate for LL container classes to use for sorting.
  644. // static 
  645. template<class T> 
  646. BOOL LLStringUtilBase<T>::precedesDict( const std::basic_string<T>& a, const std::basic_string<T>& b )
  647. {
  648. if( a.size() && b.size() )
  649. {
  650. return (LLStringUtilBase<T>::compareDict(a.c_str(), b.c_str()) < 0);
  651. }
  652. else
  653. {
  654. return (!b.empty());
  655. }
  656. }
  657. //static
  658. template<class T> 
  659. void LLStringUtilBase<T>::toUpper(std::basic_string<T>& string)
  660. if( !string.empty() )
  661. std::transform(
  662. string.begin(),
  663. string.end(),
  664. string.begin(),
  665. (T(*)(T)) &LLStringOps::toUpper);
  666. }
  667. }
  668. //static
  669. template<class T> 
  670. void LLStringUtilBase<T>::toLower(std::basic_string<T>& string)
  671. if( !string.empty() )
  672. std::transform(
  673. string.begin(),
  674. string.end(),
  675. string.begin(),
  676. (T(*)(T)) &LLStringOps::toLower);
  677. }
  678. }
  679. //static
  680. template<class T> 
  681. void LLStringUtilBase<T>::trimHead(std::basic_string<T>& string)
  682. {
  683. if( !string.empty() )
  684. {
  685. size_type i = 0;
  686. while( i < string.length() && LLStringOps::isSpace( string[i] ) )
  687. {
  688. i++;
  689. }
  690. string.erase(0, i);
  691. }
  692. }
  693. //static
  694. template<class T> 
  695. void LLStringUtilBase<T>::trimTail(std::basic_string<T>& string)
  696. {
  697. if( string.size() )
  698. {
  699. size_type len = string.length();
  700. size_type i = len;
  701. while( i > 0 && LLStringOps::isSpace( string[i-1] ) )
  702. {
  703. i--;
  704. }
  705. string.erase( i, len - i );
  706. }
  707. }
  708. // Replace line feeds with carriage return-line feed pairs.
  709. //static
  710. template<class T>
  711. void LLStringUtilBase<T>::addCRLF(std::basic_string<T>& string)
  712. {
  713. const T LF = 10;
  714. const T CR = 13;
  715. // Count the number of line feeds
  716. size_type count = 0;
  717. size_type len = string.size();
  718. size_type i;
  719. for( i = 0; i < len; i++ )
  720. {
  721. if( string[i] == LF )
  722. {
  723. count++;
  724. }
  725. }
  726. // Insert a carriage return before each line feed
  727. if( count )
  728. {
  729. size_type size = len + count;
  730. T *t = new T[size];
  731. size_type j = 0;
  732. for( i = 0; i < len; ++i )
  733. {
  734. if( string[i] == LF )
  735. {
  736. t[j] = CR;
  737. ++j;
  738. }
  739. t[j] = string[i];
  740. ++j;
  741. }
  742. string.assign(t, size);
  743. delete[] t;
  744. }
  745. }
  746. // Remove all carriage returns
  747. //static
  748. template<class T> 
  749. void LLStringUtilBase<T>::removeCRLF(std::basic_string<T>& string)
  750. {
  751. const T CR = 13;
  752. size_type cr_count = 0;
  753. size_type len = string.size();
  754. size_type i;
  755. for( i = 0; i < len - cr_count; i++ )
  756. {
  757. if( string[i+cr_count] == CR )
  758. {
  759. cr_count++;
  760. }
  761. string[i] = string[i+cr_count];
  762. }
  763. string.erase(i, cr_count);
  764. }
  765. //static
  766. template<class T> 
  767. void LLStringUtilBase<T>::replaceChar( std::basic_string<T>& string, T target, T replacement )
  768. {
  769. size_type found_pos = 0;
  770. while( (found_pos = string.find(target, found_pos)) != std::basic_string<T>::npos ) 
  771. {
  772. string[found_pos] = replacement;
  773. found_pos++; // avoid infinite defeat if target == replacement
  774. }
  775. }
  776. //static
  777. template<class T> 
  778. void LLStringUtilBase<T>::replaceString( std::basic_string<T>& string, std::basic_string<T> target, std::basic_string<T> replacement )
  779. {
  780. size_type found_pos = 0;
  781. while( (found_pos = string.find(target, found_pos)) != std::basic_string<T>::npos )
  782. {
  783. string.replace( found_pos, target.length(), replacement );
  784. found_pos += replacement.length(); // avoid infinite defeat if replacement contains target
  785. }
  786. }
  787. //static
  788. template<class T> 
  789. void LLStringUtilBase<T>::replaceNonstandardASCII( std::basic_string<T>& string, T replacement )
  790. {
  791. const char LF = 10;
  792. const S8 MIN = 32;
  793. // const S8 MAX = 127;
  794. size_type len = string.size();
  795. for( size_type i = 0; i < len; i++ )
  796. {
  797. // No need to test MAX < mText[i] because we treat mText[i] as a signed char,
  798. // which has a max value of 127.
  799. if( ( S8(string[i]) < MIN ) && (string[i] != LF) )
  800. {
  801. string[i] = replacement;
  802. }
  803. }
  804. }
  805. //static
  806. template<class T> 
  807. void LLStringUtilBase<T>::replaceTabsWithSpaces( std::basic_string<T>& str, size_type spaces_per_tab )
  808. {
  809. const T TAB = 't';
  810. const T SPACE = ' ';
  811. std::basic_string<T> out_str;
  812. // Replace tabs with spaces
  813. for (size_type i = 0; i < str.length(); i++)
  814. {
  815. if (str[i] == TAB)
  816. {
  817. for (size_type j = 0; j < spaces_per_tab; j++)
  818. out_str += SPACE;
  819. }
  820. else
  821. {
  822. out_str += str[i];
  823. }
  824. }
  825. str = out_str;
  826. }
  827. //static
  828. template<class T> 
  829. BOOL LLStringUtilBase<T>::containsNonprintable(const std::basic_string<T>& string)
  830. {
  831. const char MIN = 32;
  832. BOOL rv = FALSE;
  833. for (size_type i = 0; i < string.size(); i++)
  834. {
  835. if(string[i] < MIN)
  836. {
  837. rv = TRUE;
  838. break;
  839. }
  840. }
  841. return rv;
  842. }
  843. //static
  844. template<class T> 
  845. void LLStringUtilBase<T>::stripNonprintable(std::basic_string<T>& string)
  846. {
  847. const char MIN = 32;
  848. size_type j = 0;
  849. if (string.empty())
  850. {
  851. return;
  852. }
  853. size_t src_size = string.size();
  854. char* c_string = new char[src_size + 1];
  855. if(c_string == NULL)
  856. {
  857. return;
  858. }
  859. copy(c_string, string.c_str(), src_size+1);
  860. char* write_head = &c_string[0];
  861. for (size_type i = 0; i < src_size; i++)
  862. {
  863. char* read_head = &string[i];
  864. write_head = &c_string[j];
  865. if(!(*read_head < MIN))
  866. {
  867. *write_head = *read_head;
  868. ++j;
  869. }
  870. }
  871. c_string[j]= '';
  872. string = c_string;
  873. delete []c_string;
  874. }
  875. template<class T> 
  876. void LLStringUtilBase<T>::_makeASCII(std::basic_string<T>& string)
  877. {
  878. // Replace non-ASCII chars with LL_UNKNOWN_CHAR
  879. for (size_type i = 0; i < string.length(); i++)
  880. {
  881. if (string[i] > 0x7f)
  882. {
  883. string[i] = LL_UNKNOWN_CHAR;
  884. }
  885. }
  886. }
  887. // static
  888. template<class T> 
  889. void LLStringUtilBase<T>::copy( T* dst, const T* src, size_type dst_size )
  890. {
  891. if( dst_size > 0 )
  892. {
  893. size_type min_len = 0;
  894. if( src )
  895. {
  896. min_len = llmin( dst_size - 1, strlen( src ) );  /* Flawfinder: ignore */
  897. memcpy(dst, src, min_len * sizeof(T)); /* Flawfinder: ignore */
  898. }
  899. dst[min_len] = '';
  900. }
  901. }
  902. // static
  903. template<class T> 
  904. void LLStringUtilBase<T>::copyInto(std::basic_string<T>& dst, const std::basic_string<T>& src, size_type offset)
  905. {
  906. if ( offset == dst.length() )
  907. {
  908. // special case - append to end of string and avoid expensive
  909. // (when strings are large) string manipulations
  910. dst += src;
  911. }
  912. else
  913. {
  914. std::basic_string<T> tail = dst.substr(offset);
  915. dst = dst.substr(0, offset);
  916. dst += src;
  917. dst += tail;
  918. };
  919. }
  920. // True if this is the head of s.
  921. //static
  922. template<class T> 
  923. BOOL LLStringUtilBase<T>::isHead( const std::basic_string<T>& string, const T* s ) 
  924. if( string.empty() )
  925. {
  926. // Early exit
  927. return FALSE;
  928. }
  929. else
  930. {
  931. return (strncmp( s, string.c_str(), string.size() ) == 0);
  932. }
  933. }
  934. // static
  935. template<class T> 
  936. bool LLStringUtilBase<T>::startsWith(
  937. const std::basic_string<T>& string,
  938. const std::basic_string<T>& substr)
  939. {
  940. if(string.empty() || (substr.empty())) return false;
  941. if(0 == string.find(substr)) return true;
  942. return false;
  943. }
  944. // static
  945. template<class T> 
  946. bool LLStringUtilBase<T>::endsWith(
  947. const std::basic_string<T>& string,
  948. const std::basic_string<T>& substr)
  949. {
  950. if(string.empty() || (substr.empty())) return false;
  951. std::string::size_type idx = string.rfind(substr);
  952. if(std::string::npos == idx) return false;
  953. return (idx == (string.size() - substr.size()));
  954. }
  955. template<class T> 
  956. BOOL LLStringUtilBase<T>::convertToBOOL(const std::basic_string<T>& string, BOOL& value)
  957. {
  958. if( string.empty() )
  959. {
  960. return FALSE;
  961. }
  962. std::basic_string<T> temp( string );
  963. trim(temp);
  964. if( 
  965. (temp == "1") || 
  966. (temp == "T") || 
  967. (temp == "t") || 
  968. (temp == "TRUE") || 
  969. (temp == "true") || 
  970. (temp == "True") )
  971. {
  972. value = TRUE;
  973. return TRUE;
  974. }
  975. else
  976. if( 
  977. (temp == "0") || 
  978. (temp == "F") || 
  979. (temp == "f") || 
  980. (temp == "FALSE") || 
  981. (temp == "false") || 
  982. (temp == "False") )
  983. {
  984. value = FALSE;
  985. return TRUE;
  986. }
  987. return FALSE;
  988. }
  989. template<class T> 
  990. BOOL LLStringUtilBase<T>::convertToU8(const std::basic_string<T>& string, U8& value) 
  991. {
  992. S32 value32 = 0;
  993. BOOL success = convertToS32(string, value32);
  994. if( success && (U8_MIN <= value32) && (value32 <= U8_MAX) )
  995. {
  996. value = (U8) value32;
  997. return TRUE;
  998. }
  999. return FALSE;
  1000. }
  1001. template<class T> 
  1002. BOOL LLStringUtilBase<T>::convertToS8(const std::basic_string<T>& string, S8& value) 
  1003. {
  1004. S32 value32 = 0;
  1005. BOOL success = convertToS32(string, value32);
  1006. if( success && (S8_MIN <= value32) && (value32 <= S8_MAX) )
  1007. {
  1008. value = (S8) value32;
  1009. return TRUE;
  1010. }
  1011. return FALSE;
  1012. }
  1013. template<class T> 
  1014. BOOL LLStringUtilBase<T>::convertToS16(const std::basic_string<T>& string, S16& value) 
  1015. {
  1016. S32 value32 = 0;
  1017. BOOL success = convertToS32(string, value32);
  1018. if( success && (S16_MIN <= value32) && (value32 <= S16_MAX) )
  1019. {
  1020. value = (S16) value32;
  1021. return TRUE;
  1022. }
  1023. return FALSE;
  1024. }
  1025. template<class T> 
  1026. BOOL LLStringUtilBase<T>::convertToU16(const std::basic_string<T>& string, U16& value) 
  1027. {
  1028. S32 value32 = 0;
  1029. BOOL success = convertToS32(string, value32);
  1030. if( success && (U16_MIN <= value32) && (value32 <= U16_MAX) )
  1031. {
  1032. value = (U16) value32;
  1033. return TRUE;
  1034. }
  1035. return FALSE;
  1036. }
  1037. template<class T> 
  1038. BOOL LLStringUtilBase<T>::convertToU32(const std::basic_string<T>& string, U32& value) 
  1039. {
  1040. if( string.empty() )
  1041. {
  1042. return FALSE;
  1043. }
  1044. std::basic_string<T> temp( string );
  1045. trim(temp);
  1046. U32 v;
  1047. std::basic_istringstream<T> i_stream((std::basic_string<T>)temp);
  1048. if(i_stream >> v)
  1049. {
  1050. value = v;
  1051. return TRUE;
  1052. }
  1053. return FALSE;
  1054. }
  1055. template<class T> 
  1056. BOOL LLStringUtilBase<T>::convertToS32(const std::basic_string<T>& string, S32& value) 
  1057. {
  1058. if( string.empty() )
  1059. {
  1060. return FALSE;
  1061. }
  1062. std::basic_string<T> temp( string );
  1063. trim(temp);
  1064. S32 v;
  1065. std::basic_istringstream<T> i_stream((std::basic_string<T>)temp);
  1066. if(i_stream >> v)
  1067. {
  1068. //TODO: figure out overflow and underflow reporting here
  1069. //if((LONG_MAX == v) || (LONG_MIN == v))
  1070. //{
  1071. // // Underflow or overflow
  1072. // return FALSE;
  1073. //}
  1074. value = v;
  1075. return TRUE;
  1076. }
  1077. return FALSE;
  1078. }
  1079. template<class T> 
  1080. BOOL LLStringUtilBase<T>::convertToF32(const std::basic_string<T>& string, F32& value) 
  1081. {
  1082. F64 value64 = 0.0;
  1083. BOOL success = convertToF64(string, value64);
  1084. if( success && (-F32_MAX <= value64) && (value64 <= F32_MAX) )
  1085. {
  1086. value = (F32) value64;
  1087. return TRUE;
  1088. }
  1089. return FALSE;
  1090. }
  1091. template<class T> 
  1092. BOOL LLStringUtilBase<T>::convertToF64(const std::basic_string<T>& string, F64& value)
  1093. {
  1094. if( string.empty() )
  1095. {
  1096. return FALSE;
  1097. }
  1098. std::basic_string<T> temp( string );
  1099. trim(temp);
  1100. F64 v;
  1101. std::basic_istringstream<T> i_stream((std::basic_string<T>)temp);
  1102. if(i_stream >> v)
  1103. {
  1104. //TODO: figure out overflow and underflow reporting here
  1105. //if( ((-HUGE_VAL == v) || (HUGE_VAL == v))) )
  1106. //{
  1107. // // Underflow or overflow
  1108. // return FALSE;
  1109. //}
  1110. value = v;
  1111. return TRUE;
  1112. }
  1113. return FALSE;
  1114. }
  1115. template<class T> 
  1116. void LLStringUtilBase<T>::truncate(std::basic_string<T>& string, size_type count)
  1117. {
  1118. size_type cur_size = string.size();
  1119. string.resize(count < cur_size ? count : cur_size);
  1120. }
  1121. #endif  // LL_STRING_H