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

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file llstring.cpp
  3.  * @brief String utility functions and the 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. #include "linden_common.h"
  33. #include "llstring.h"
  34. #include "llerror.h"
  35. #if LL_WINDOWS
  36. #define WIN32_LEAN_AND_MEAN
  37. #include <winsock2.h>
  38. #include <windows.h>
  39. #include <winnls.h> // for WideCharToMultiByte
  40. #endif
  41. LLFastTimer::DeclareTimer FT_STRING_FORMAT("String Format");
  42. std::string ll_safe_string(const char* in)
  43. {
  44. if(in) return std::string(in);
  45. return std::string();
  46. }
  47. std::string ll_safe_string(const char* in, S32 maxlen)
  48. {
  49. if(in) return std::string(in, maxlen);
  50. return std::string();
  51. }
  52. U8 hex_as_nybble(char hex)
  53. {
  54. if((hex >= '0') && (hex <= '9'))
  55. {
  56. return (U8)(hex - '0');
  57. }
  58. else if((hex >= 'a') && (hex <='f'))
  59. {
  60. return (U8)(10 + hex - 'a');
  61. }
  62. else if((hex >= 'A') && (hex <='F'))
  63. {
  64. return (U8)(10 + hex - 'A');
  65. }
  66. return 0; // uh - oh, not hex any more...
  67. }
  68. bool iswindividual(llwchar elem)
  69. {   
  70. U32 cur_char = (U32)elem;
  71. bool result = false;
  72. if (0x2E80<= cur_char && cur_char <= 0x9FFF)
  73. {
  74. result = true;
  75. }
  76. else if (0xAC00<= cur_char && cur_char <= 0xD7A0 )
  77. {
  78. result = true;
  79. }
  80. else if (0xF900<= cur_char && cur_char <= 0xFA60 )
  81. {
  82. result = true;
  83. }
  84. return result;
  85. }
  86. bool _read_file_into_string(std::string& str, const std::string& filename)
  87. {
  88. llifstream ifs(filename, llifstream::binary);
  89. if (!ifs.is_open())
  90. {
  91. llinfos << "Unable to open file " << filename << llendl;
  92. return false;
  93. }
  94. std::ostringstream oss;
  95. oss << ifs.rdbuf();
  96. str = oss.str();
  97. ifs.close();
  98. return true;
  99. }
  100. // See http://www.unicode.org/Public/BETA/CVTUTF-1-2/ConvertUTF.c
  101. // for the Unicode implementation - this doesn't match because it was written before finding
  102. // it.
  103. std::ostream& operator<<(std::ostream &s, const LLWString &wstr)
  104. {
  105. std::string utf8_str = wstring_to_utf8str(wstr);
  106. s << utf8_str;
  107. return s;
  108. }
  109. std::string rawstr_to_utf8(const std::string& raw)
  110. {
  111. LLWString wstr(utf8str_to_wstring(raw));
  112. return wstring_to_utf8str(wstr);
  113. }
  114. S32 wchar_to_utf8chars(llwchar in_char, char* outchars)
  115. {
  116. U32 cur_char = (U32)in_char;
  117. char* base = outchars;
  118. if (cur_char < 0x80)
  119. {
  120. *outchars++ = (U8)cur_char;
  121. }
  122. else if (cur_char < 0x800)
  123. {
  124. *outchars++ = 0xC0 | (cur_char >> 6);
  125. *outchars++ = 0x80 | (cur_char & 0x3F);
  126. }
  127. else if (cur_char < 0x10000)
  128. {
  129. *outchars++ = 0xE0 | (cur_char >> 12);
  130. *outchars++ = 0x80 | ((cur_char >> 6) & 0x3F);
  131. *outchars++ = 0x80 | (cur_char & 0x3F);
  132. }
  133. else if (cur_char < 0x200000)
  134. {
  135. *outchars++ = 0xF0 | (cur_char >> 18);
  136. *outchars++ = 0x80 | ((cur_char >> 12) & 0x3F);
  137. *outchars++ = 0x80 | ((cur_char >> 6) & 0x3F);
  138. *outchars++ = 0x80 | (cur_char & 0x3F);
  139. }
  140. else if (cur_char < 0x4000000)
  141. {
  142. *outchars++ = 0xF8 | (cur_char >> 24);
  143. *outchars++ = 0x80 | ((cur_char >> 18) & 0x3F);
  144. *outchars++ = 0x80 | ((cur_char >> 12) & 0x3F);
  145. *outchars++ = 0x80 | ((cur_char >> 6) & 0x3F);
  146. *outchars++ = 0x80 | (cur_char & 0x3F);
  147. }
  148. else if (cur_char < 0x80000000)
  149. {
  150. *outchars++ = 0xFC | (cur_char >> 30);
  151. *outchars++ = 0x80 | ((cur_char >> 24) & 0x3F);
  152. *outchars++ = 0x80 | ((cur_char >> 18) & 0x3F);
  153. *outchars++ = 0x80 | ((cur_char >> 12) & 0x3F);
  154. *outchars++ = 0x80 | ((cur_char >> 6) & 0x3F);
  155. *outchars++ = 0x80 | (cur_char & 0x3F);
  156. }
  157. else
  158. {
  159. llwarns << "Invalid Unicode character " << cur_char << "!" << llendl;
  160. *outchars++ = LL_UNKNOWN_CHAR;
  161. }
  162. return outchars - base;
  163. }
  164. S32 utf16chars_to_wchar(const U16* inchars, llwchar* outchar)
  165. {
  166. const U16* base = inchars;
  167. U16 cur_char = *inchars++;
  168. llwchar char32 = cur_char;
  169. if ((cur_char >= 0xD800) && (cur_char <= 0xDFFF))
  170. {
  171. // Surrogates
  172. char32 = ((llwchar)(cur_char - 0xD800)) << 10;
  173. cur_char = *inchars++;
  174. char32 += (llwchar)(cur_char - 0xDC00) + 0x0010000UL;
  175. }
  176. else
  177. {
  178. char32 = (llwchar)cur_char;
  179. }
  180. *outchar = char32;
  181. return inchars - base;
  182. }
  183. llutf16string wstring_to_utf16str(const LLWString &utf32str, S32 len)
  184. {
  185. llutf16string out;
  186. S32 i = 0;
  187. while (i < len)
  188. {
  189. U32 cur_char = utf32str[i];
  190. if (cur_char > 0xFFFF)
  191. {
  192. out += (0xD7C0 + (cur_char >> 10));
  193. out += (0xDC00 | (cur_char & 0x3FF));
  194. }
  195. else
  196. {
  197. out += cur_char;
  198. }
  199. i++;
  200. }
  201. return out;
  202. }
  203. llutf16string wstring_to_utf16str(const LLWString &utf32str)
  204. {
  205. const S32 len = (S32)utf32str.length();
  206. return wstring_to_utf16str(utf32str, len);
  207. }
  208. llutf16string utf8str_to_utf16str ( const std::string& utf8str )
  209. {
  210. LLWString wstr = utf8str_to_wstring ( utf8str );
  211. return wstring_to_utf16str ( wstr );
  212. }
  213. LLWString utf16str_to_wstring(const llutf16string &utf16str, S32 len)
  214. {
  215. LLWString wout;
  216. if((len <= 0) || utf16str.empty()) return wout;
  217. S32 i = 0;
  218. // craziness to make gcc happy (llutf16string.c_str() is tweaked on linux):
  219. const U16* chars16 = &(*(utf16str.begin()));
  220. while (i < len)
  221. {
  222. llwchar cur_char;
  223. i += utf16chars_to_wchar(chars16+i, &cur_char);
  224. wout += cur_char;
  225. }
  226. return wout;
  227. }
  228. LLWString utf16str_to_wstring(const llutf16string &utf16str)
  229. {
  230. const S32 len = (S32)utf16str.length();
  231. return utf16str_to_wstring(utf16str, len);
  232. }
  233. // Length in llwchar (UTF-32) of the first len units (16 bits) of the given UTF-16 string.
  234. S32 utf16str_wstring_length(const llutf16string &utf16str, const S32 utf16_len)
  235. {
  236. S32 surrogate_pairs = 0;
  237. // ... craziness to make gcc happy (llutf16string.c_str() is tweaked on linux):
  238. const U16 *const utf16_chars = &(*(utf16str.begin()));
  239. S32 i = 0;
  240. while (i < utf16_len)
  241. {
  242. const U16 c = utf16_chars[i++];
  243. if (c >= 0xD800 && c <= 0xDBFF) // See http://en.wikipedia.org/wiki/UTF-16
  244. {   // Have first byte of a surrogate pair
  245. if (i >= utf16_len)
  246. {
  247. break;
  248. }
  249. const U16 d = utf16_chars[i];
  250. if (d >= 0xDC00 && d <= 0xDFFF)
  251. {   // Have valid second byte of a surrogate pair
  252. surrogate_pairs++;
  253. i++;
  254. }
  255. }
  256. }
  257. return utf16_len - surrogate_pairs;
  258. }
  259. // Length in utf16string (UTF-16) of wlen wchars beginning at woffset.
  260. S32 wstring_utf16_length(const LLWString &wstr, const S32 woffset, const S32 wlen)
  261. {
  262. const S32 end = llmin((S32)wstr.length(), woffset + wlen);
  263. if (end < woffset)
  264. {
  265. return 0;
  266. }
  267. else
  268. {
  269. S32 length = end - woffset;
  270. for (S32 i = woffset; i < end; i++)
  271. {
  272. if (wstr[i] >= 0x10000)
  273. {
  274. length++;
  275. }
  276. }
  277. return length;
  278. }
  279. }
  280. // Given a wstring and an offset in it, returns the length as wstring (i.e.,
  281. // number of llwchars) of the longest substring that starts at the offset
  282. // and whose equivalent utf-16 string does not exceeds the given utf16_length.
  283. S32 wstring_wstring_length_from_utf16_length(const LLWString & wstr, const S32 woffset, const S32 utf16_length, BOOL *unaligned)
  284. {
  285. const S32 end = wstr.length();
  286. BOOL u = FALSE;
  287. S32 n = woffset + utf16_length;
  288. S32 i = woffset;
  289. while (i < end)
  290. {
  291. if (wstr[i] >= 0x10000)
  292. {
  293. --n;
  294. }
  295. if (i >= n)
  296. {
  297. u = (i > n);
  298. break;
  299. }
  300. i++;
  301. }
  302. if (unaligned)
  303. {
  304. *unaligned = u;
  305. }
  306. return i - woffset;
  307. }
  308. S32 wchar_utf8_length(const llwchar wc)
  309. {
  310. if (wc < 0x80)
  311. {
  312. // This case will also catch negative values which are
  313. // technically invalid.
  314. return 1;
  315. }
  316. else if (wc < 0x800)
  317. {
  318. return 2;
  319. }
  320. else if (wc < 0x10000)
  321. {
  322. return 3;
  323. }
  324. else if (wc < 0x200000)
  325. {
  326. return 4;
  327. }
  328. else if (wc < 0x4000000)
  329. {
  330. return 5;
  331. }
  332. else
  333. {
  334. return 6;
  335. }
  336. }
  337. S32 wstring_utf8_length(const LLWString& wstr)
  338. {
  339. S32 len = 0;
  340. for (S32 i = 0; i < (S32)wstr.length(); i++)
  341. {
  342. len += wchar_utf8_length(wstr[i]);
  343. }
  344. return len;
  345. }
  346. LLWString utf8str_to_wstring(const std::string& utf8str, S32 len)
  347. {
  348. LLWString wout;
  349. S32 i = 0;
  350. while (i < len)
  351. {
  352. llwchar unichar;
  353. U8 cur_char = utf8str[i];
  354. if (cur_char < 0x80)
  355. {
  356. // Ascii character, just add it
  357. unichar = cur_char;
  358. }
  359. else
  360. {
  361. S32 cont_bytes = 0;
  362. if ((cur_char >> 5) == 0x6) // Two byte UTF8 -> 1 UTF32
  363. {
  364. unichar = (0x1F&cur_char);
  365. cont_bytes = 1;
  366. }
  367. else if ((cur_char >> 4) == 0xe) // Three byte UTF8 -> 1 UTF32
  368. {
  369. unichar = (0x0F&cur_char);
  370. cont_bytes = 2;
  371. }
  372. else if ((cur_char >> 3) == 0x1e) // Four byte UTF8 -> 1 UTF32
  373. {
  374. unichar = (0x07&cur_char);
  375. cont_bytes = 3;
  376. }
  377. else if ((cur_char >> 2) == 0x3e) // Five byte UTF8 -> 1 UTF32
  378. {
  379. unichar = (0x03&cur_char);
  380. cont_bytes = 4;
  381. }
  382. else if ((cur_char >> 1) == 0x7e) // Six byte UTF8 -> 1 UTF32
  383. {
  384. unichar = (0x01&cur_char);
  385. cont_bytes = 5;
  386. }
  387. else
  388. {
  389. wout += LL_UNKNOWN_CHAR;
  390. ++i;
  391. continue;
  392. }
  393. // Check that this character doesn't go past the end of the string
  394. S32 end = (len < (i + cont_bytes)) ? len : (i + cont_bytes);
  395. do
  396. {
  397. ++i;
  398. cur_char = utf8str[i];
  399. if ( (cur_char >> 6) == 0x2 )
  400. {
  401. unichar <<= 6;
  402. unichar += (0x3F&cur_char);
  403. }
  404. else
  405. {
  406. // Malformed sequence - roll back to look at this as a new char
  407. unichar = LL_UNKNOWN_CHAR;
  408. --i;
  409. break;
  410. }
  411. } while(i < end);
  412. // Handle overlong characters and NULL characters
  413. if ( ((cont_bytes == 1) && (unichar < 0x80))
  414. || ((cont_bytes == 2) && (unichar < 0x800))
  415. || ((cont_bytes == 3) && (unichar < 0x10000))
  416. || ((cont_bytes == 4) && (unichar < 0x200000))
  417. || ((cont_bytes == 5) && (unichar < 0x4000000)) )
  418. {
  419. unichar = LL_UNKNOWN_CHAR;
  420. }
  421. }
  422. wout += unichar;
  423. ++i;
  424. }
  425. return wout;
  426. }
  427. LLWString utf8str_to_wstring(const std::string& utf8str)
  428. {
  429. const S32 len = (S32)utf8str.length();
  430. return utf8str_to_wstring(utf8str, len);
  431. }
  432. std::string wstring_to_utf8str(const LLWString& utf32str, S32 len)
  433. {
  434. std::string out;
  435. S32 i = 0;
  436. while (i < len)
  437. {
  438. char tchars[8]; /* Flawfinder: ignore */
  439. S32 n = wchar_to_utf8chars(utf32str[i], tchars);
  440. tchars[n] = 0;
  441. out += tchars;
  442. i++;
  443. }
  444. return out;
  445. }
  446. std::string wstring_to_utf8str(const LLWString& utf32str)
  447. {
  448. const S32 len = (S32)utf32str.length();
  449. return wstring_to_utf8str(utf32str, len);
  450. }
  451. std::string utf16str_to_utf8str(const llutf16string& utf16str)
  452. {
  453. return wstring_to_utf8str(utf16str_to_wstring(utf16str));
  454. }
  455. std::string utf16str_to_utf8str(const llutf16string& utf16str, S32 len)
  456. {
  457. return wstring_to_utf8str(utf16str_to_wstring(utf16str, len), len);
  458. }
  459. std::string utf8str_trim(const std::string& utf8str)
  460. {
  461. LLWString wstr = utf8str_to_wstring(utf8str);
  462. LLWStringUtil::trim(wstr);
  463. return wstring_to_utf8str(wstr);
  464. }
  465. std::string utf8str_tolower(const std::string& utf8str)
  466. {
  467. LLWString out_str = utf8str_to_wstring(utf8str);
  468. LLWStringUtil::toLower(out_str);
  469. return wstring_to_utf8str(out_str);
  470. }
  471. S32 utf8str_compare_insensitive(const std::string& lhs, const std::string& rhs)
  472. {
  473. LLWString wlhs = utf8str_to_wstring(lhs);
  474. LLWString wrhs = utf8str_to_wstring(rhs);
  475. return LLWStringUtil::compareInsensitive(wlhs, wrhs);
  476. }
  477. std::string utf8str_truncate(const std::string& utf8str, const S32 max_len)
  478. {
  479. if (0 == max_len)
  480. {
  481. return std::string();
  482. }
  483. if ((S32)utf8str.length() <= max_len)
  484. {
  485. return utf8str;
  486. }
  487. else
  488. {
  489. S32 cur_char = max_len;
  490. // If we're ASCII, we don't need to do anything
  491. if ((U8)utf8str[cur_char] > 0x7f)
  492. {
  493. // If first two bits are (10), it's the tail end of a multibyte char.  We need to shift back
  494. // to the first character
  495. while (0x80 == (0xc0 & utf8str[cur_char]))
  496. {
  497. cur_char--;
  498. // Keep moving forward until we hit the first char;
  499. if (cur_char == 0)
  500. {
  501. // Make sure we don't trash memory if we've got a bogus string.
  502. break;
  503. }
  504. }
  505. }
  506. // The byte index we're on is one we want to get rid of, so we only want to copy up to (cur_char-1) chars
  507. return utf8str.substr(0, cur_char);
  508. }
  509. }
  510. std::string utf8str_substChar(
  511. const std::string& utf8str,
  512. const llwchar target_char,
  513. const llwchar replace_char)
  514. {
  515. LLWString wstr = utf8str_to_wstring(utf8str);
  516. LLWStringUtil::replaceChar(wstr, target_char, replace_char);
  517. //wstr = wstring_substChar(wstr, target_char, replace_char);
  518. return wstring_to_utf8str(wstr);
  519. }
  520. std::string utf8str_makeASCII(const std::string& utf8str)
  521. {
  522. LLWString wstr = utf8str_to_wstring(utf8str);
  523. LLWStringUtil::_makeASCII(wstr);
  524. return wstring_to_utf8str(wstr);
  525. }
  526. std::string mbcsstring_makeASCII(const std::string& wstr)
  527. {
  528. // Replace non-ASCII chars with replace_char
  529. std::string out_str = wstr;
  530. for (S32 i = 0; i < (S32)out_str.length(); i++)
  531. {
  532. if ((U8)out_str[i] > 0x7f)
  533. {
  534. out_str[i] = LL_UNKNOWN_CHAR;
  535. }
  536. }
  537. return out_str;
  538. }
  539. std::string utf8str_removeCRLF(const std::string& utf8str)
  540. {
  541. if (0 == utf8str.length())
  542. {
  543. return std::string();
  544. }
  545. const char CR = 13;
  546. std::string out;
  547. out.reserve(utf8str.length());
  548. const S32 len = (S32)utf8str.length();
  549. for( S32 i = 0; i < len; i++ )
  550. {
  551. if( utf8str[i] != CR )
  552. {
  553. out.push_back(utf8str[i]);
  554. }
  555. }
  556. return out;
  557. }
  558. #if LL_WINDOWS
  559. // documentation moved to header. Phoenix 2007-11-27
  560. namespace snprintf_hack
  561. {
  562. int snprintf(char *str, size_t size, const char *format, ...)
  563. {
  564. va_list args;
  565. va_start(args, format);
  566. int num_written = _vsnprintf(str, size, format, args); /* Flawfinder: ignore */
  567. va_end(args);
  568. str[size-1] = ''; // always null terminate
  569. return num_written;
  570. }
  571. }
  572. std::string ll_convert_wide_to_string(const wchar_t* in)
  573. {
  574. std::string out;
  575. if(in)
  576. {
  577. int len_in = wcslen(in);
  578. int len_out = WideCharToMultiByte(
  579. CP_ACP,
  580. 0,
  581. in,
  582. len_in,
  583. NULL,
  584. 0,
  585. 0,
  586. 0);
  587. // We will need two more bytes for the double NULL ending
  588. // created in WideCharToMultiByte().
  589. char* pout = new char [len_out + 2];
  590. memset(pout, 0, len_out + 2);
  591. if(pout)
  592. {
  593. WideCharToMultiByte(
  594. CP_ACP,
  595. 0,
  596. in,
  597. len_in,
  598. pout,
  599. len_out,
  600. 0,
  601. 0);
  602. out.assign(pout);
  603. delete[] pout;
  604. }
  605. }
  606. return out;
  607. }
  608. #endif // LL_WINDOWS
  609. long LLStringOps::sPacificTimeOffset = 0;
  610. long LLStringOps::sLocalTimeOffset = 0;
  611. bool LLStringOps::sPacificDaylightTime = 0;
  612. std::map<std::string, std::string> LLStringOps::datetimeToCodes;
  613. S32 LLStringOps::collate(const llwchar* a, const llwchar* b)
  614. #if LL_WINDOWS
  615. // in Windows, wide string functions operator on 16-bit strings, 
  616. // not the proper 32 bit wide string
  617. return strcmp(wstring_to_utf8str(LLWString(a)).c_str(), wstring_to_utf8str(LLWString(b)).c_str());
  618. #else
  619. return wcscoll(a, b);
  620. #endif
  621. }
  622. void LLStringOps::setupDatetimeInfo (bool daylight)
  623. {
  624. time_t nowT, localT, gmtT;
  625. struct tm * tmpT;
  626. nowT = time (NULL);
  627. tmpT = localtime (&nowT);
  628. localT = mktime (tmpT);
  629. tmpT = gmtime (&nowT);
  630. gmtT = mktime (tmpT);
  631. sLocalTimeOffset = (long) (gmtT - localT);
  632. sPacificDaylightTime = daylight;
  633. sPacificTimeOffset = (sPacificDaylightTime? 7 : 8 ) * 60 * 60;
  634. datetimeToCodes["wkday"] = "%a"; // Thu
  635. datetimeToCodes["weekday"] = "%A"; // Thursday
  636. datetimeToCodes["year4"] = "%Y"; // 2009
  637. datetimeToCodes["year"] = "%Y"; // 2009
  638. datetimeToCodes["year2"] = "%y"; // 09
  639. datetimeToCodes["mth"] = "%b"; // Aug
  640. datetimeToCodes["month"] = "%B"; // August
  641. datetimeToCodes["mthnum"] = "%m"; // 08
  642. datetimeToCodes["day"] = "%d"; // 31
  643. datetimeToCodes["hour24"] = "%H"; // 14
  644. datetimeToCodes["hour"] = "%H"; // 14
  645. datetimeToCodes["hour12"] = "%I"; // 02
  646. datetimeToCodes["min"] = "%M"; // 59
  647. datetimeToCodes["ampm"] = "%p"; // AM
  648. datetimeToCodes["second"] = "%S"; // 59
  649. datetimeToCodes["timezone"] = "%Z"; // PST
  650. }
  651. std::string LLStringOps::getDatetimeCode (std::string key)
  652. {
  653. std::map<std::string, std::string>::iterator iter;
  654. iter = datetimeToCodes.find (key);
  655. if (iter != datetimeToCodes.end())
  656. {
  657. return iter->second;
  658. }
  659. else
  660. {
  661. return std::string("");
  662. }
  663. }
  664. namespace LLStringFn
  665. {
  666. // NOTE - this restricts output to ascii
  667. void replace_nonprintable_in_ascii(std::basic_string<char>& string, char replacement)
  668. {
  669. const char MIN = 0x20;
  670. std::basic_string<char>::size_type len = string.size();
  671. for(std::basic_string<char>::size_type ii = 0; ii < len; ++ii)
  672. {
  673. if(string[ii] < MIN)
  674. {
  675. string[ii] = replacement;
  676. }
  677. }
  678. }
  679. // NOTE - this restricts output to ascii
  680. void replace_nonprintable_and_pipe_in_ascii(std::basic_string<char>& str,
  681.    char replacement)
  682. {
  683. const char MIN  = 0x20;
  684. const char PIPE = 0x7c;
  685. std::basic_string<char>::size_type len = str.size();
  686. for(std::basic_string<char>::size_type ii = 0; ii < len; ++ii)
  687. {
  688. if( (str[ii] < MIN) || (str[ii] == PIPE) )
  689. {
  690. str[ii] = replacement;
  691. }
  692. }
  693. }
  694. // https://wiki.lindenlab.com/wiki/Unicode_Guidelines has details on
  695. // allowable code points for XML. Specifically, they are:
  696. // 0x09, 0x0a, 0x0d, and 0x20 on up.  JC
  697. std::string strip_invalid_xml(const std::string& instr)
  698. {
  699. std::string output;
  700. output.reserve( instr.size() );
  701. std::string::const_iterator it = instr.begin();
  702. while (it != instr.end())
  703. {
  704. // Must compare as unsigned for >=
  705. // Test most likely match first
  706. const unsigned char c = (unsigned char)*it;
  707. if (   c >= (unsigned char)0x20   // SPACE
  708. || c == (unsigned char)0x09   // TAB
  709. || c == (unsigned char)0x0a   // LINE_FEED
  710. || c == (unsigned char)0x0d ) // CARRIAGE_RETURN
  711. {
  712. output.push_back(c);
  713. }
  714. ++it;
  715. }
  716. return output;
  717. }
  718. /**
  719.  * @brief Replace all control characters (c < 0x20) with replacement in
  720.  * string.
  721.  */
  722. void replace_ascii_controlchars(std::basic_string<char>& string, char replacement)
  723. {
  724. const unsigned char MIN = 0x20;
  725. std::basic_string<char>::size_type len = string.size();
  726. for(std::basic_string<char>::size_type ii = 0; ii < len; ++ii)
  727. {
  728. const unsigned char c = (unsigned char) string[ii];
  729. if(c < MIN)
  730. {
  731. string[ii] = replacement;
  732. }
  733. }
  734. }
  735. }
  736. ////////////////////////////////////////////////////////////
  737. //static
  738. template<> 
  739. void LLStringUtil::getTokens(const std::string& instr, std::vector<std::string >& tokens, const std::string& delims)
  740. {
  741. std::string currToken;
  742. std::string::size_type begIdx, endIdx;
  743. begIdx = instr.find_first_not_of (delims);
  744. while (begIdx != std::string::npos)
  745. {
  746. endIdx = instr.find_first_of (delims, begIdx);
  747. if (endIdx == std::string::npos)
  748. {
  749. endIdx = instr.length();
  750. }
  751. currToken = instr.substr(begIdx, endIdx - begIdx);
  752. LLStringUtil::trim (currToken);
  753. tokens.push_back(currToken);
  754. begIdx = instr.find_first_not_of (delims, endIdx);
  755. }
  756. }
  757. template<> 
  758. LLStringUtil::size_type LLStringUtil::getSubstitution(const std::string& instr, size_type& start, std::vector<std::string>& tokens)
  759. {
  760. const std::string delims (",");
  761. // Find the first ]
  762. size_type pos2 = instr.find(']', start);
  763. if (pos2 == std::string::npos)
  764. return std::string::npos;
  765. // Find the last [ before ]
  766. size_type pos1 = instr.find_last_of('[', pos2-1);
  767. if (pos1 == std::string::npos || pos1 < start)
  768. return std::string::npos;
  769. getTokens(std::string(instr,pos1+1,pos2-pos1-1), tokens, delims);
  770. start = pos2+1;
  771. return pos1;
  772. }
  773. // static
  774. template<> 
  775. bool LLStringUtil::simpleReplacement(std::string &replacement, std::string token, const format_map_t& substitutions)
  776. {
  777. // see if we have a replacement for the bracketed string (without the brackets)
  778. // test first using has() because if we just look up with operator[] we get back an
  779. // empty string even if the value is missing. We want to distinguish between 
  780. // missing replacements and deliberately empty replacement strings.
  781. format_map_t::const_iterator iter = substitutions.find(token);
  782. if (iter != substitutions.end())
  783. {
  784. replacement = iter->second;
  785. return true;
  786. }
  787. // if not, see if there's one WITH brackets
  788. iter = substitutions.find(std::string("[" + token + "]"));
  789. if (iter != substitutions.end())
  790. {
  791. replacement = iter->second;
  792. return true;
  793. }
  794. return false;
  795. }
  796. // static
  797. template<> 
  798. bool LLStringUtil::simpleReplacement(std::string &replacement, std::string token, const LLSD& substitutions)
  799. {
  800. // see if we have a replacement for the bracketed string (without the brackets)
  801. // test first using has() because if we just look up with operator[] we get back an
  802. // empty string even if the value is missing. We want to distinguish between 
  803. // missing replacements and deliberately empty replacement strings.
  804. if (substitutions.has(token))
  805. {
  806. replacement = substitutions[token].asString();
  807. return true;
  808. }
  809. // if not, see if there's one WITH brackets
  810. else if (substitutions.has(std::string("[" + token + "]")))
  811. {
  812. replacement = substitutions[std::string("[" + token + "]")].asString();
  813. return true;
  814. }
  815. return false;
  816. }
  817. // static
  818. template<> 
  819. void LLStringUtil::formatNumber(std::string& numStr, std::string decimals)
  820. {
  821. std::stringstream strStream;
  822. S32 intDecimals = 0;
  823. convertToS32 (decimals, intDecimals);
  824. if (!sLocale.empty())
  825. {
  826. strStream.imbue (std::locale(sLocale.c_str()));
  827. }
  828. if (!intDecimals)
  829. {
  830. S32 intStr;
  831. if (convertToS32(numStr, intStr))
  832. {
  833. strStream << intStr;
  834. numStr = strStream.str();
  835. }
  836. }
  837. else
  838. {
  839. F32 floatStr;
  840. if (convertToF32(numStr, floatStr))
  841. {
  842. strStream << std::fixed << std::showpoint << std::setprecision(intDecimals) << floatStr;
  843. numStr = strStream.str();
  844. }
  845. }
  846. }
  847. // static
  848. template<> 
  849. bool LLStringUtil::formatDatetime(std::string& replacement, std::string token,
  850.   std::string param, S32 secFromEpoch)
  851. {
  852. if (param == "local")   // local
  853. {
  854. secFromEpoch -= LLStringOps::getLocalTimeOffset();
  855. }
  856. else if (param != "utc") // slt
  857. {
  858. secFromEpoch -= LLStringOps::getPacificTimeOffset();
  859. }
  860. // if never fell into those two ifs above, param must be utc
  861. if (secFromEpoch < 0) secFromEpoch = 0;
  862. LLDate datetime((F64)secFromEpoch);
  863. std::string code = LLStringOps::getDatetimeCode (token);
  864. // special case to handle timezone
  865. if (code == "%Z") {
  866. if (param == "utc")
  867. {
  868. replacement = "GMT";
  869. }
  870. else if (param == "local")
  871. {
  872. replacement = ""; // user knows their own timezone
  873. }
  874. else
  875. {
  876. // "slt" = Second Life Time, which is deprecated.
  877. // If not utc or user local time, fallback to Pacific time
  878. replacement = LLStringOps::getPacificDaylightTime() ? "PDT" : "PST";
  879. }
  880. return true;
  881. }
  882. replacement = datetime.toHTTPDateString(code);
  883. // *HACK: delete leading zero from hour string in case 'hour12' (code = %I) time format
  884. // to show time without leading zero, e.g. 08:16 -> 8:16 (EXT-2738).
  885. // We could have used '%l' format instead, but it's not supported by Windows.
  886. if(code == "%I" && token == "hour12" && replacement.at(0) == '0')
  887. {
  888. replacement = replacement.at(1);
  889. }
  890. return !code.empty();
  891. }
  892. // LLStringUtil::format recogizes the following patterns.
  893. // All substitutions *must* be encased in []'s in the input string.
  894. // The []'s are optional in the substitution map.
  895. // [FOO_123]
  896. // [FOO,number,precision]
  897. // [FOO,datetime,format]
  898. // static
  899. template<> 
  900. S32 LLStringUtil::format(std::string& s, const format_map_t& substitutions)
  901. {
  902. LLFastTimer ft(FT_STRING_FORMAT);
  903. S32 res = 0;
  904. std::string output;
  905. std::vector<std::string> tokens;
  906. std::string::size_type start = 0;
  907. std::string::size_type prev_start = 0;
  908. std::string::size_type key_start = 0;
  909. while ((key_start = getSubstitution(s, start, tokens)) != std::string::npos)
  910. {
  911. output += std::string(s, prev_start, key_start-prev_start);
  912. prev_start = start;
  913. bool found_replacement = false;
  914. std::string replacement;
  915. if (tokens.size() == 0)
  916. {
  917. found_replacement = false;
  918. }
  919. else if (tokens.size() == 1)
  920. {
  921. found_replacement = simpleReplacement (replacement, tokens[0], substitutions);
  922. }
  923. else if (tokens[1] == "number")
  924. {
  925. std::string param = "0";
  926. if (tokens.size() > 2) param = tokens[2];
  927. found_replacement = simpleReplacement (replacement, tokens[0], substitutions);
  928. if (found_replacement) formatNumber (replacement, param);
  929. }
  930. else if (tokens[1] == "datetime")
  931. {
  932. std::string param;
  933. if (tokens.size() > 2) param = tokens[2];
  934. format_map_t::const_iterator iter = substitutions.find("datetime");
  935. if (iter != substitutions.end())
  936. {
  937. S32 secFromEpoch = 0;
  938. BOOL r = LLStringUtil::convertToS32(iter->second, secFromEpoch);
  939. if (r)
  940. {
  941. found_replacement = formatDatetime(replacement, tokens[0], param, secFromEpoch);
  942. }
  943. }
  944. }
  945. if (found_replacement)
  946. {
  947. output += replacement;
  948. res++;
  949. }
  950. else
  951. {
  952. // we had no replacement, use the string as is
  953. // e.g. "hello [MISSING_REPLACEMENT]" or "-=[Stylized Name]=-"
  954. output += std::string(s, key_start, start-key_start);
  955. }
  956. tokens.clear();
  957. }
  958. // send the remainder of the string (with no further matches for bracketed names)
  959. output += std::string(s, start);
  960. s = output;
  961. return res;
  962. }
  963. //static
  964. template<> 
  965. S32 LLStringUtil::format(std::string& s, const LLSD& substitutions)
  966. {
  967. LLFastTimer ft(FT_STRING_FORMAT);
  968. S32 res = 0;
  969. if (!substitutions.isMap()) 
  970. {
  971. return res;
  972. }
  973. std::string output;
  974. std::vector<std::string> tokens;
  975. std::string::size_type start = 0;
  976. std::string::size_type prev_start = 0;
  977. std::string::size_type key_start = 0;
  978. while ((key_start = getSubstitution(s, start, tokens)) != std::string::npos)
  979. {
  980. output += std::string(s, prev_start, key_start-prev_start);
  981. prev_start = start;
  982. bool found_replacement = false;
  983. std::string replacement;
  984. if (tokens.size() == 0)
  985. {
  986. found_replacement = false;
  987. }
  988. else if (tokens.size() == 1)
  989. {
  990. found_replacement = simpleReplacement (replacement, tokens[0], substitutions);
  991. }
  992. else if (tokens[1] == "number")
  993. {
  994. std::string param = "0";
  995. if (tokens.size() > 2) param = tokens[2];
  996. found_replacement = simpleReplacement (replacement, tokens[0], substitutions);
  997. if (found_replacement) formatNumber (replacement, param);
  998. }
  999. else if (tokens[1] == "datetime")
  1000. {
  1001. std::string param;
  1002. if (tokens.size() > 2) param = tokens[2];
  1003. S32 secFromEpoch = (S32) substitutions["datetime"].asInteger();
  1004. found_replacement = formatDatetime (replacement, tokens[0], param, secFromEpoch);
  1005. }
  1006. if (found_replacement)
  1007. {
  1008. output += replacement;
  1009. res++;
  1010. }
  1011. else
  1012. {
  1013. // we had no replacement, use the string as is
  1014. // e.g. "hello [MISSING_REPLACEMENT]" or "-=[Stylized Name]=-"
  1015. output += std::string(s, key_start, start-key_start);
  1016. }
  1017. tokens.clear();
  1018. }
  1019. // send the remainder of the string (with no further matches for bracketed names)
  1020. output += std::string(s, start);
  1021. s = output;
  1022. return res;
  1023. }
  1024. ////////////////////////////////////////////////////////////
  1025. // Testing
  1026. #ifdef _DEBUG
  1027. template<class T> 
  1028. void LLStringUtilBase<T>::testHarness()
  1029. {
  1030. std::string s1;
  1031. llassert( s1.c_str() == NULL );
  1032. llassert( s1.size() == 0 );
  1033. llassert( s1.empty() );
  1034. std::string s2( "hello");
  1035. llassert( !strcmp( s2.c_str(), "hello" ) );
  1036. llassert( s2.size() == 5 ); 
  1037. llassert( !s2.empty() );
  1038. std::string s3( s2 );
  1039. llassert( "hello" == s2 );
  1040. llassert( s2 == "hello" );
  1041. llassert( s2 > "gello" );
  1042. llassert( "gello" < s2 );
  1043. llassert( "gello" != s2 );
  1044. llassert( s2 != "gello" );
  1045. std::string s4 = s2;
  1046. llassert( !s4.empty() );
  1047. s4.empty();
  1048. llassert( s4.empty() );
  1049. std::string s5("");
  1050. llassert( s5.empty() );
  1051. llassert( isValidIndex(s5, 0) );
  1052. llassert( !isValidIndex(s5, 1) );
  1053. s3 = s2;
  1054. s4 = "hello again";
  1055. s4 += "!";
  1056. s4 += s4;
  1057. llassert( s4 == "hello again!hello again!" );
  1058. std::string s6 = s2 + " " + s2;
  1059. std::string s7 = s6;
  1060. llassert( s6 == s7 );
  1061. llassert( !( s6 != s7) );
  1062. llassert( !(s6 < s7) );
  1063. llassert( !(s6 > s7) );
  1064. llassert( !(s6 == "hi"));
  1065. llassert( s6 == "hello hello");
  1066. llassert( s6 < "hi");
  1067. llassert( s6[1] == 'e' );
  1068. s6[1] = 'f';
  1069. llassert( s6[1] == 'f' );
  1070. s2.erase( 4, 1 );
  1071. llassert( s2 == "hell");
  1072. s2.insert( 0, 'y' );
  1073. llassert( s2 == "yhell");
  1074. s2.erase( 1, 3 );
  1075. llassert( s2 == "yl");
  1076. s2.insert( 1, "awn, don't yel");
  1077. llassert( s2 == "yawn, don't yell");
  1078. std::string s8 = s2.substr( 6, 5 );
  1079. llassert( s8 == "don't"  );
  1080. std::string s9 = "   tntest  ttn  ";
  1081. trim(s9);
  1082. llassert( s9 == "test"  );
  1083. s8 = "abc123&*(ABC";
  1084. s9 = s8;
  1085. toUpper(s9);
  1086. llassert( s9 == "ABC123&*(ABC"  );
  1087. s9 = s8;
  1088. toLower(s9);
  1089. llassert( s9 == "abc123&*(abc"  );
  1090. std::string s10( 10, 'x' );
  1091. llassert( s10 == "xxxxxxxxxx" );
  1092. std::string s11( "monkey in the middle", 7, 2 );
  1093. llassert( s11 == "in" );
  1094. std::string s12;  //empty
  1095. s12 += "foo";
  1096. llassert( s12 == "foo" );
  1097. std::string s13;  //empty
  1098. s13 += 'f';
  1099. llassert( s13 == "f" );
  1100. }
  1101. #endif  // _DEBUG