str.cpp 39 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2012 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #include <stdarg.h>
  23. #include <stdio.h>
  24. #include "platform/platform.h"
  25. // Sigh... guess what compiler needs this...
  26. namespace DictHash { U32 hash( String::StringData* ); }
  27. namespace KeyCmp
  28. {
  29. template< typename Key > bool equals( const Key&, const Key& );
  30. template<> bool equals<>( String::StringData* const&, String::StringData* const& );
  31. }
  32. #include "core/util/str.h"
  33. #include "core/util/tDictionary.h"
  34. #include "core/strings/stringFunctions.h"
  35. #include "core/strings/unicode.h"
  36. #include "core/util/hashFunction.h"
  37. #include "core/util/autoPtr.h"
  38. #include "core/util/tVector.h"
  39. #include "core/dataChunker.h"
  40. #include "console/console.h"
  41. #include "math/mMathFn.h"
  42. #include "platform/platform.h"
  43. #include "platform/profiler.h"
  44. #include "platform/platformIntrinsics.h"
  45. #include "platform/threads/mutex.h"
  46. #ifndef TORQUE_DISABLE_MEMORY_MANAGER
  47. # undef new
  48. #else
  49. # define _new new
  50. #endif
  51. const String::SizeType String::NPos = U32(~0);
  52. const String String::EmptyString;
  53. /// A delete policy for the AutoPtr class
  54. struct DeleteString
  55. {
  56. template<class T>
  57. static void destroy(T *ptr) { dFree(ptr); }
  58. };
  59. //-----------------------------------------------------------------------------
  60. /// Search for a character.
  61. /// Search for the position of the needle in the haystack.
  62. /// Default mode is StrCase | StrLeft, mode also accepts StrNoCase and StrRight.
  63. /// If pos is non-zero, then in mode StrLeft the search starts at (hay + pos) and
  64. /// in mode StrRight the search starts at (hay + pos - 1)
  65. /// @return Returns a pointer to the location of the character in the haystack or 0
  66. static const char* StrFind(const char* hay, char needle, S32 pos, U32 mode)
  67. {
  68. if (mode & String::Right)
  69. {
  70. // Go to the end first, then search backwards
  71. const char *he = hay;
  72. if (pos)
  73. {
  74. he += pos - 1;
  75. }
  76. else
  77. {
  78. while (*he)
  79. he++;
  80. }
  81. if (mode & String::NoCase)
  82. {
  83. needle = dTolower(needle);
  84. for (; he >= hay; he--)
  85. {
  86. if (dTolower(*he) == needle)
  87. return he;
  88. }
  89. }
  90. else
  91. {
  92. for (; he >= hay; he--)
  93. {
  94. if (*he == needle)
  95. return he;
  96. }
  97. }
  98. return 0;
  99. }
  100. else
  101. {
  102. if (mode & String::NoCase)
  103. {
  104. needle = dTolower(needle);
  105. for (hay += pos; *hay && dTolower(*hay) != needle;)
  106. hay++;
  107. }
  108. else
  109. {
  110. for (hay += pos; *hay && *hay != needle;)
  111. hay++;
  112. }
  113. return *hay ? hay : 0;
  114. }
  115. }
  116. /// Search for a StringData.
  117. /// Search for the position of the needle in the haystack.
  118. /// Default mode is StrCase | StrLeft, mode also accepts StrNoCase and StrRight.
  119. /// If pos is non-zero, then in mode StrLeft the search starts at (hay + pos) and
  120. /// in mode StrRight the search starts at (hay + pos - 1)
  121. /// @return Returns a pointer to the StringData in the haystack or 0
  122. static const char* StrFind(const char* hay, const char* needle, S32 pos, U32 mode)
  123. {
  124. if (mode & String::Right)
  125. {
  126. const char *he = hay;
  127. if (pos)
  128. {
  129. he += pos - 1;
  130. }
  131. else
  132. {
  133. while (*he)
  134. he++;
  135. }
  136. if (mode & String::NoCase)
  137. {
  138. AutoPtr<char,DeleteString> ln(dStrlwr(dStrdup(needle)));
  139. for (; he >= hay; he--)
  140. {
  141. if (dTolower(*he) == *ln)
  142. {
  143. U32 i = 0;
  144. while (ln[i] && ln[i] == dTolower(he[i]))
  145. i++;
  146. if (!ln[i])
  147. return he;
  148. if (!hay[i])
  149. return 0;
  150. }
  151. }
  152. }
  153. else
  154. {
  155. for (; he >= hay; he--)
  156. {
  157. if (*he == *needle)
  158. {
  159. U32 i = 0;
  160. while (needle[i] && needle[i] == he[i])
  161. i++;
  162. if (!needle[i])
  163. return he;
  164. if (!hay[i])
  165. return 0;
  166. }
  167. }
  168. }
  169. return 0;
  170. }
  171. else
  172. {
  173. if (mode & String::NoCase)
  174. {
  175. AutoPtr<char,DeleteString> ln(dStrlwr(dStrdup(needle)));
  176. for (hay += pos; *hay; hay++)
  177. {
  178. if (dTolower(*hay) == *ln)
  179. {
  180. U32 i = 0;
  181. while (ln[i] && ln[i] == dTolower(hay[i]))
  182. i++;
  183. if (!ln[i])
  184. return hay;
  185. if (!hay[i])
  186. return 0;
  187. }
  188. }
  189. }
  190. else
  191. {
  192. for (hay += pos; *hay; hay++)
  193. {
  194. if (*hay == *needle)
  195. {
  196. U32 i = 0;
  197. while (needle[i] && needle[i] == hay[i])
  198. i++;
  199. if (!needle[i])
  200. return hay;
  201. if (!hay[i])
  202. return 0;
  203. }
  204. }
  205. }
  206. }
  207. return 0;
  208. }
  209. //-----------------------------------------------------------------------------
  210. /// Struct with String::StringData's field so we can initialize
  211. /// this without a constructor.
  212. struct StringDataImpl
  213. {
  214. #ifdef TORQUE_DEBUG
  215. StringChar* mString; ///< so we can inspect data in a debugger
  216. #endif
  217. U32 mRefCount; ///< String reference count; string is not refcounted if this is U32_MAX (necessary for thread-safety of interned strings and the empty string).
  218. U32 mLength; ///< String length in bytes excluding null.
  219. mutable U32 mNumChars; ///< Character count; varies from byte count for strings with multi-bytes characters.
  220. mutable U32 mHashCase; ///< case-sensitive hash
  221. mutable U32 mHashNoCase; ///< case-insensitive hash
  222. mutable UTF16* mUTF16;
  223. bool mIsInterned; ///< If true, this string is interned in the string table.
  224. StringChar mData[1]; ///< Start of string data
  225. };
  226. ///
  227. class String::StringData : protected StringDataImpl
  228. {
  229. public:
  230. ///
  231. StringData( const StringChar* data, bool interned = false )
  232. {
  233. mRefCount = 1;
  234. mNumChars = U32_MAX;
  235. mHashCase = U32_MAX;
  236. mHashNoCase = U32_MAX;
  237. mUTF16 = NULL;
  238. mIsInterned = interned;
  239. // mLength is initialized by operator new()
  240. if( data )
  241. {
  242. dMemcpy( mData, data, sizeof( StringChar ) * mLength );
  243. mData[ mLength ] = '\0';
  244. }
  245. #ifdef TORQUE_DEBUG
  246. mString = &mData[0];
  247. #endif
  248. if( mIsInterned )
  249. mRefCount = U32_MAX;
  250. }
  251. ~StringData()
  252. {
  253. if( mUTF16 )
  254. delete [] mUTF16;
  255. }
  256. void* operator new(size_t size, U32 len);
  257. void* operator new( size_t size, U32 len, DataChunker& chunker );
  258. void operator delete(void *);
  259. bool isShared() const
  260. {
  261. return ( mRefCount > 1 );
  262. }
  263. void addRef()
  264. {
  265. if( mRefCount != U32_MAX )
  266. mRefCount ++;
  267. }
  268. void release()
  269. {
  270. if( mRefCount != U32_MAX )
  271. {
  272. -- mRefCount;
  273. if( !mRefCount )
  274. delete this;
  275. }
  276. }
  277. U32 getLength() const
  278. {
  279. return mLength;
  280. }
  281. U32 getDataSize() const
  282. {
  283. return ( mLength + 1 );
  284. }
  285. U32 getDataSizeUTF16() const
  286. {
  287. return ( mLength * sizeof( UTF16 ) );
  288. }
  289. UTF8 operator []( U32 index ) const
  290. {
  291. AssertFatal( index < mLength, "String::StringData::operator []() - index out of range" );
  292. return mData[ index ];
  293. }
  294. UTF8* utf8()
  295. {
  296. return mData;
  297. }
  298. const UTF8* utf8() const
  299. {
  300. return mData;
  301. }
  302. UTF16* utf16() const
  303. {
  304. if( !mUTF16 )
  305. {
  306. // Do this atomically to protect interned strings.
  307. UTF16* utf16 = convertUTF8toUTF16( mData );
  308. if( !dCompareAndSwap( mUTF16,( UTF16* ) NULL, utf16 ) )
  309. delete [] utf16;
  310. }
  311. return mUTF16;
  312. }
  313. U32 getHashCase() const
  314. {
  315. return mHashCase;
  316. }
  317. U32 getOrCreateHashCase() const
  318. {
  319. if( mHashCase == U32_MAX )
  320. {
  321. PROFILE_SCOPE(StringData_getOrCreateHashCase);
  322. mHashCase = Torque::hash((const U8 *)(mData), mLength, 0);
  323. }
  324. return mHashCase;
  325. }
  326. U32 getHashNoCase() const
  327. {
  328. return mHashNoCase;
  329. }
  330. U32 getOrCreateHashNoCase() const
  331. {
  332. if( mHashNoCase == U32_MAX)
  333. {
  334. PROFILE_SCOPE(StringData_getOrCreateHashNoCase);
  335. UTF8 *lower = new UTF8[ mLength + 1 ];
  336. dStrncpy( lower, utf8(), mLength );
  337. lower[ mLength ] = 0;
  338. dStrlwr( lower );
  339. mHashNoCase = Torque::hash( (const U8*)lower, mLength, 0 );
  340. delete [] lower;
  341. }
  342. return mHashNoCase;
  343. }
  344. U32 getNumChars() const
  345. {
  346. if( mNumChars == U32_MAX )
  347. mNumChars = dStrlen( utf16() );
  348. return mNumChars;
  349. }
  350. bool isInterned() const
  351. {
  352. return mIsInterned;
  353. }
  354. static StringData* Empty()
  355. {
  356. static UTF16 emptyUTF16[ 1 ] = { 0 };
  357. static StringDataImpl empty =
  358. {
  359. #ifdef TORQUE_DEBUG
  360. "", // mString
  361. #endif
  362. U32_MAX, // mRefCount
  363. 0, // mLength
  364. 0, // mNumChars
  365. 0, // mHashCase
  366. 0, // mHashNoCase
  367. emptyUTF16, // mUTF16
  368. true, // mIsInterned
  369. { 0 } // mData
  370. };
  371. return ( StringData* ) &empty;
  372. }
  373. };
  374. //-----------------------------------------------------------------------------
  375. namespace DictHash
  376. {
  377. inline U32 hash( String::StringData* data )
  378. {
  379. return data->getOrCreateHashCase();
  380. }
  381. }
  382. namespace KeyCmp
  383. {
  384. template<>
  385. inline bool equals<>( String::StringData* const& d1, String::StringData* const& d2 )
  386. {
  387. return ( dStrcmp( d1->utf8(), d2->utf8() ) == 0 );
  388. }
  389. }
  390. /// Type for the intern string table. We don't want String instances directly
  391. /// on the table so that destructors don't run when the table is destroyed. This
  392. /// is because we really shouldn't depend on dtor ordering within this file and thus
  393. /// we can't tell whether the intern string memory is freed before or after the
  394. /// table is destroyed.
  395. struct StringInternTable : public HashTable< String::StringData*, String::StringData* >
  396. {
  397. Mutex mMutex;
  398. DataChunker mChunker;
  399. };
  400. static StringInternTable* sInternTable;
  401. struct KillInternTable
  402. {
  403. ~KillInternTable()
  404. {
  405. if( sInternTable )
  406. delete sInternTable;
  407. }
  408. };
  409. static KillInternTable sKillInternTable;
  410. //-----------------------------------------------------------------------------
  411. #ifdef TORQUE_DEBUG
  412. /// Tracks the number of bytes allocated for strings.
  413. /// @bug This currently does not include UTF16 allocations.
  414. static U32 sgStringMemBytes;
  415. /// Tracks the number of Strings which are currently instantiated.
  416. static U32 sgStringInstances;
  417. ConsoleFunction( dumpStringMemStats, void, 1, 1, "()"
  418. "@brief Dumps information about String memory usage\n\n"
  419. "@ingroup Debugging\n"
  420. "@ingroup Strings\n")
  421. {
  422. Con::printf( "String Data: %i instances, %i bytes", sgStringInstances, sgStringMemBytes );
  423. }
  424. #endif
  425. //-----------------------------------------------------------------------------
  426. void* String::StringData::operator new( size_t size, U32 len )
  427. {
  428. AssertFatal( len != 0, "String::StringData::operator new() - string must not be empty" );
  429. StringData *str = reinterpret_cast<StringData*>( dMalloc( size + len * sizeof(StringChar) ) );
  430. str->mLength = len;
  431. #ifdef TORQUE_DEBUG
  432. dFetchAndAdd( sgStringMemBytes, size + len * sizeof(StringChar) );
  433. dFetchAndAdd( sgStringInstances, 1 );
  434. #endif
  435. return str;
  436. }
  437. void String::StringData::operator delete(void *ptr)
  438. {
  439. StringData* sub = static_cast<StringData *>(ptr);
  440. AssertFatal( sub->mRefCount == 0, "StringData::delete() - invalid refcount" );
  441. #ifdef TORQUE_DEBUG
  442. dFetchAndAdd( sgStringMemBytes, U32( -( S32( sizeof( StringData ) + sub->mLength * sizeof(StringChar) ) ) ) );
  443. dFetchAndAdd( sgStringInstances, U32( -1 ) );
  444. #endif
  445. dFree( ptr );
  446. }
  447. void* String::StringData::operator new( size_t size, U32 len, DataChunker& chunker )
  448. {
  449. AssertFatal( len != 0, "String::StringData::operator new() - string must not be empty" );
  450. StringData *str = reinterpret_cast<StringData*>( chunker.alloc( size + len * sizeof(StringChar) ) );
  451. str->mLength = len;
  452. #ifdef TORQUE_DEBUG
  453. dFetchAndAdd( sgStringMemBytes, size + len * sizeof(StringChar) );
  454. dFetchAndAdd( sgStringInstances, 1 );
  455. #endif
  456. return str;
  457. }
  458. //-----------------------------------------------------------------------------
  459. String::String()
  460. {
  461. PROFILE_SCOPE(String_default_constructor);
  462. _string = StringData::Empty();
  463. }
  464. String::String(const String &str)
  465. {
  466. PROFILE_SCOPE(String_String_constructor);
  467. _string = str._string;
  468. _string->addRef();
  469. }
  470. String::String(const StringChar *str)
  471. {
  472. PROFILE_SCOPE(String_char_constructor);
  473. if( str && *str )
  474. {
  475. U32 len = dStrlen(str);
  476. _string = new ( len ) StringData( str );
  477. }
  478. else
  479. _string = StringData::Empty();
  480. }
  481. String::String(const StringChar *str, SizeType len)
  482. {
  483. PROFILE_SCOPE(String_char_len_constructor);
  484. if (str && *str && len!=0)
  485. {
  486. AssertFatal(len<=dStrlen(str), "String::String: string too short");
  487. _string = new ( len ) StringData( str );
  488. }
  489. else
  490. _string = StringData::Empty();
  491. }
  492. String::String(const UTF16 *str)
  493. {
  494. PROFILE_SCOPE(String_UTF16_constructor);
  495. if( str && str[ 0 ] )
  496. {
  497. UTF8* utf8 = convertUTF16toUTF8( str );
  498. U32 len = dStrlen( utf8 );
  499. _string = new ( len ) StringData( utf8 );
  500. delete [] utf8;
  501. }
  502. else
  503. _string = StringData::Empty();
  504. }
  505. String::~String()
  506. {
  507. _string->release();
  508. }
  509. //-----------------------------------------------------------------------------
  510. String String::intern() const
  511. {
  512. if( isInterned() )
  513. return *this;
  514. // Create the intern table, if we haven't already.
  515. if( !sInternTable )
  516. sInternTable = new StringInternTable;
  517. // Lock the string table.
  518. MutexHandle mutex;
  519. mutex.lock( &sInternTable->mMutex );
  520. // Lookup.
  521. StringInternTable::Iterator iter = sInternTable->find( _string );
  522. if( iter != sInternTable->end() )
  523. return ( *iter ).value;
  524. // Create new.
  525. StringData* data = new ( length(), sInternTable->mChunker ) StringData( c_str(), true );
  526. iter = sInternTable->insertUnique( data, data );
  527. return ( *iter ).value;
  528. }
  529. //-----------------------------------------------------------------------------
  530. const StringChar* String::c_str() const
  531. {
  532. return _string->utf8();
  533. }
  534. const UTF16 *String::utf16() const
  535. {
  536. return _string->utf16();
  537. }
  538. String::SizeType String::length() const
  539. {
  540. return _string->getLength();
  541. }
  542. String::SizeType String::size() const
  543. {
  544. return _string->getDataSize();
  545. }
  546. String::SizeType String::numChars() const
  547. {
  548. return _string->getNumChars();
  549. }
  550. bool String::isEmpty() const
  551. {
  552. return ( _string == StringData::Empty() );
  553. }
  554. bool String::isShared() const
  555. {
  556. return _string->isShared();
  557. }
  558. bool String::isSame( const String& str ) const
  559. {
  560. return ( _string == str._string );
  561. }
  562. bool String::isInterned() const
  563. {
  564. return ( _string->isInterned() );
  565. }
  566. U32 String::getHashCaseSensitive() const
  567. {
  568. return _string->getOrCreateHashCase();
  569. }
  570. U32 String::getHashCaseInsensitive() const
  571. {
  572. return _string->getOrCreateHashNoCase();
  573. }
  574. //-----------------------------------------------------------------------------
  575. String::SizeType String::find(const String &str, SizeType pos, U32 mode) const
  576. {
  577. return find(str._string->utf8(), pos, mode);
  578. }
  579. String& String::insert(SizeType pos, const String &str)
  580. {
  581. return insert(pos, str._string->utf8());
  582. }
  583. String& String::replace(SizeType pos, SizeType len, const String &str)
  584. {
  585. return replace(pos, len, str._string->utf8());
  586. }
  587. //-----------------------------------------------------------------------------
  588. String& String::operator=(StringChar c)
  589. {
  590. _string->release();
  591. _string = new ( 2 ) StringData( 0 );
  592. _string->utf8()[ 0 ] = c;
  593. _string->utf8()[ 1 ] = '\0';
  594. return *this;
  595. }
  596. String& String::operator+=(StringChar c)
  597. {
  598. // Append the given string into a new string
  599. U32 len = _string->getLength();
  600. StringData* sub = new ( len + 1 ) StringData( NULL );
  601. copy( sub->utf8(), _string->utf8(), len );
  602. sub->utf8()[len] = c;
  603. sub->utf8()[len+1] = 0;
  604. _string->release();
  605. _string = sub;
  606. return *this;
  607. }
  608. //-----------------------------------------------------------------------------
  609. String& String::operator=(const StringChar *str)
  610. {
  611. // Protect against self assignment which is not only a
  612. // waste of time, but can also lead to the string being
  613. // freed before it can be reassigned.
  614. if ( _string->utf8() == str )
  615. return *this;
  616. _string->release();
  617. if (str && *str)
  618. {
  619. U32 len = dStrlen(str);
  620. _string = new ( len ) StringData( str );
  621. }
  622. else
  623. _string = StringData::Empty();
  624. return *this;
  625. }
  626. String& String::operator=(const String &src)
  627. {
  628. // Inc src first to avoid assignment to self problems.
  629. src._string->addRef();
  630. _string->release();
  631. _string = src._string;
  632. return *this;
  633. }
  634. String& String::operator+=(const StringChar *src)
  635. {
  636. if( src == NULL && !*src )
  637. return *this;
  638. // Append the given string into a new string
  639. U32 lena = _string->getLength();
  640. U32 lenb = dStrlen(src);
  641. U32 newlen = lena + lenb;
  642. StringData* sub;
  643. if( !newlen )
  644. sub = StringData::Empty();
  645. else
  646. {
  647. sub = new ( newlen ) StringData( NULL );
  648. copy(sub->utf8(),_string->utf8(),lena);
  649. copy(sub->utf8() + lena,src,lenb + 1);
  650. }
  651. _string->release();
  652. _string = sub;
  653. return *this;
  654. }
  655. String& String::operator+=(const String &src)
  656. {
  657. if( src.isEmpty() )
  658. return *this;
  659. // Append the given string into a new string
  660. U32 lena = _string->getLength();
  661. U32 lenb = src._string->getLength();
  662. U32 newlen = lena + lenb;
  663. StringData* sub;
  664. if( !newlen )
  665. sub = StringData::Empty();
  666. else
  667. {
  668. sub = new ( newlen ) StringData( NULL );
  669. copy(sub->utf8(),_string->utf8(),lena);
  670. copy(sub->utf8() + lena,src._string->utf8(),lenb + 1);
  671. }
  672. _string->release();
  673. _string = sub;
  674. return *this;
  675. }
  676. //-----------------------------------------------------------------------------
  677. String operator+(const String &a, const String &b)
  678. {
  679. PROFILE_SCOPE( String_String_plus_String );
  680. if( a.isEmpty() )
  681. return b;
  682. else if( b.isEmpty() )
  683. return a;
  684. U32 lena = a.length();
  685. U32 lenb = b.length();
  686. String::StringData *sub = new ( lena + lenb ) String::StringData( NULL );
  687. String::copy(sub->utf8(),a._string->utf8(),lena);
  688. String::copy(sub->utf8() + lena,b._string->utf8(),lenb + 1);
  689. return String(sub);
  690. }
  691. String operator+(const String &a, StringChar c)
  692. {
  693. //PROFILE_SCOPE( String_String_plus_Char );
  694. U32 lena = a.length();
  695. String::StringData *sub = new ( lena + 1 ) String::StringData( NULL );
  696. String::copy(sub->utf8(),a._string->utf8(),lena);
  697. sub->utf8()[lena] = c;
  698. sub->utf8()[lena+1] = 0;
  699. return String(sub);
  700. }
  701. String operator+(StringChar c, const String &a)
  702. {
  703. //PROFILE_SCOPE( String_Char_plus_String );
  704. U32 lena = a.length();
  705. String::StringData *sub = new ( lena + 1 ) String::StringData( NULL );
  706. String::copy(sub->utf8() + 1,a._string->utf8(),lena + 1);
  707. sub->utf8()[0] = c;
  708. return String(sub);
  709. }
  710. String operator+(const String &a, const StringChar *b)
  711. {
  712. //PROFILE_SCOPE( String_String_plus_CString );
  713. AssertFatal(b,"String:: Invalid null ptr argument");
  714. if( a.isEmpty() )
  715. return String( b );
  716. U32 lena = a.length();
  717. U32 lenb = dStrlen(b);
  718. if( !lenb )
  719. return a;
  720. String::StringData *sub = new ( lena + lenb ) String::StringData( NULL );
  721. String::copy(sub->utf8(),a._string->utf8(),lena);
  722. String::copy(sub->utf8() + lena,b,lenb + 1);
  723. return String(sub);
  724. }
  725. String operator+(const StringChar *a, const String &b)
  726. {
  727. //PROFILE_SCOPE( String_CString_plus_String );
  728. AssertFatal(a,"String:: Invalid null ptr argument");
  729. if( b.isEmpty() )
  730. return String( a );
  731. U32 lena = dStrlen(a);
  732. if( !lena )
  733. return b;
  734. U32 lenb = b.length();
  735. String::StringData* sub = new ( lena + lenb ) String::StringData( NULL );
  736. String::copy(sub->utf8(),a,lena);
  737. String::copy(sub->utf8() + lena,b._string->utf8(),lenb + 1);
  738. return String(sub);
  739. }
  740. bool String::operator==(const String &str) const
  741. {
  742. //PROFILE_SCOPE( String_op_equal );
  743. if( str._string == _string )
  744. return true;
  745. else if( str._string->isInterned() && _string->isInterned() )
  746. return false;
  747. else if( str.length() != length() )
  748. return false;
  749. else if( str._string->getHashCase() != U32_MAX
  750. && _string->getHashCase() != U32_MAX
  751. && str._string->getHashCase() != _string->getHashCase() )
  752. return false;
  753. else
  754. return ( dMemcmp( str._string->utf8(), _string->utf8(), _string->getLength() ) == 0 );
  755. }
  756. bool String::operator==( StringChar c ) const
  757. {
  758. if( !_string || _string->getLength() != 1 )
  759. return false;
  760. else
  761. return ( _string->utf8()[ 0 ] == c );
  762. }
  763. bool String::operator<(const String &str) const
  764. {
  765. return ( dStrnatcmp( _string->utf8(), str._string->utf8() ) < 0 );
  766. }
  767. bool String::operator>(const String &str) const
  768. {
  769. return ( dStrnatcmp( _string->utf8(), str._string->utf8() ) > 0 );
  770. }
  771. bool String::operator<=(const String &str) const
  772. {
  773. return ( dStrnatcmp( _string->utf8(), str._string->utf8() ) <= 0 );
  774. }
  775. bool String::operator>=(const String &str) const
  776. {
  777. return ( dStrnatcmp( _string->utf8(), str._string->utf8() ) >= 0 );
  778. }
  779. //-----------------------------------------------------------------------------
  780. // Base functions for string comparison
  781. S32 String::compare(const StringChar *str, SizeType len, U32 mode) const
  782. {
  783. PROFILE_SCOPE( String_compare );
  784. AssertFatal(str,"String:: Invalid null ptr argument");
  785. const StringChar *p1 = _string->utf8();
  786. const StringChar *p2 = str;
  787. if (p1 == p2)
  788. return 0;
  789. if( mode & String::Right )
  790. {
  791. U32 n = len;
  792. if( n > length() )
  793. n = length();
  794. p1 += length() - n;
  795. p2 += dStrlen( str ) - n;
  796. }
  797. if (mode & String::NoCase)
  798. {
  799. if (len)
  800. {
  801. for (;--len; p1++,p2++)
  802. {
  803. if (dTolower(*p1) != dTolower(*p2) || !*p1)
  804. break;
  805. }
  806. }
  807. else
  808. {
  809. while (dTolower(*p1) == dTolower(*p2) && *p1)
  810. {
  811. p1++;
  812. p2++;
  813. }
  814. }
  815. return dTolower(*p1) - dTolower(*p2);
  816. }
  817. if (len)
  818. return dMemcmp(p1,p2,len);
  819. while (*p1 == *p2 && *p1)
  820. {
  821. p1++;
  822. p2++;
  823. }
  824. return *p1 - *p2;
  825. }
  826. S32 String::compare(const String &str, SizeType len, U32 mode) const
  827. {
  828. if ( str._string == _string )
  829. return 0;
  830. return compare( str.c_str(), len, mode );
  831. }
  832. bool String::equal(const String &str, U32 mode) const
  833. {
  834. if( !mode )
  835. return ( *this == str );
  836. else
  837. {
  838. if( _string == str._string )
  839. return true;
  840. else if( _string->isInterned() && str._string->isInterned() )
  841. return false;
  842. else if( length() != str.length() )
  843. return false;
  844. else if( _string->getHashNoCase() != U32_MAX
  845. && str._string->getHashNoCase() != U32_MAX
  846. && _string->getHashNoCase() != str._string->getHashNoCase() )
  847. return false;
  848. else
  849. return ( compare( str.c_str(), length(), mode ) == 0 );
  850. }
  851. }
  852. //-----------------------------------------------------------------------------
  853. String::SizeType String::find(StringChar c, SizeType pos, U32 mode) const
  854. {
  855. const StringChar* ptr = StrFind(_string->utf8(),c,pos,mode);
  856. return ptr? SizeType(ptr - _string->utf8()): NPos;
  857. }
  858. String::SizeType String::find(const StringChar *str, SizeType pos, U32 mode) const
  859. {
  860. AssertFatal(str,"String:: Invalid null ptr argument");
  861. const StringChar* ptr = StrFind(_string->utf8(),str,pos,mode);
  862. return ptr? SizeType(ptr - _string->utf8()): NPos;
  863. }
  864. //-----------------------------------------------------------------------------
  865. String& String::insert(SizeType pos, const StringChar *str)
  866. {
  867. AssertFatal(str,"String:: Invalid null ptr argument");
  868. return insert(pos,str,dStrlen(str));
  869. }
  870. ///@todo review for error checking
  871. String& String::insert(SizeType pos, const StringChar *str, SizeType len)
  872. {
  873. if( !len )
  874. return *this;
  875. AssertFatal( str, "String:: Invalid null ptr argument" );
  876. SizeType lena = length();
  877. AssertFatal((pos <= lena),"Calling String::insert with position greater than length");
  878. U32 newlen = lena + len;
  879. StringData *sub;
  880. if( !newlen )
  881. sub = StringData::Empty();
  882. else
  883. {
  884. sub = new ( newlen ) StringData( NULL );
  885. String::copy(sub->utf8(),_string->utf8(),pos);
  886. String::copy(sub->utf8() + pos,str,len);
  887. String::copy(sub->utf8() + pos + len,_string->utf8() + pos,lena - pos + 1);
  888. }
  889. _string->release();
  890. _string = sub;
  891. return *this;
  892. }
  893. String& String::erase(SizeType pos, SizeType len)
  894. {
  895. AssertFatal( len != 0, "String::erase() - Calling String::erase with 0 length" );
  896. AssertFatal( ( pos + len ) <= length(), "String::erase() - Invalid string region" );
  897. if( !len )
  898. return *this;
  899. SizeType slen = length();
  900. U32 newlen = slen - len;
  901. StringData *sub;
  902. if( !newlen )
  903. sub = StringData::Empty();
  904. else
  905. {
  906. sub = new ( newlen ) StringData( NULL );
  907. if (pos > 0)
  908. String::copy(sub->utf8(),_string->utf8(),pos);
  909. String::copy(sub->utf8() + pos, _string->utf8() + pos + len, slen - (pos + len) + 1);
  910. }
  911. _string->release();
  912. _string = sub;
  913. return *this;
  914. }
  915. ///@todo review for error checking
  916. String& String::replace(SizeType pos, SizeType len, const StringChar *str)
  917. {
  918. AssertFatal( str, "String::replace() - Invalid null ptr argument" );
  919. AssertFatal( len != 0, "String::replace() - Zero length" );
  920. AssertFatal( ( pos + len ) <= length(), "String::replace() - Invalid string region" );
  921. SizeType slen = length();
  922. SizeType rlen = dStrlen(str);
  923. U32 newlen = slen - len + rlen;
  924. StringData *sub;
  925. if( !newlen )
  926. sub = StringData::Empty();
  927. else
  928. {
  929. sub = new ( newlen ) StringData( NULL );
  930. String::copy(sub->utf8(),_string->utf8(), pos);
  931. String::copy(sub->utf8() + pos,str,rlen);
  932. String::copy(sub->utf8() + pos + rlen,_string->utf8() + pos + len,slen - pos - len + 1);
  933. }
  934. _string->release();
  935. _string = sub;
  936. return *this;
  937. }
  938. String& String::replace( StringChar c1, StringChar c2 )
  939. {
  940. if( isEmpty() )
  941. return *this;
  942. // Create the new string lazily so that we don't needlessly
  943. // dup strings when there is nothing to replace.
  944. StringData* sub = NULL;
  945. bool foundReplacement = false;
  946. StringChar* c = _string->utf8();
  947. while( *c )
  948. {
  949. if( *c == c1 )
  950. {
  951. if( !foundReplacement )
  952. {
  953. sub = new ( length() ) StringData( _string->utf8() );
  954. c = &sub->utf8()[ c - _string->utf8() ];
  955. foundReplacement = true;
  956. }
  957. *c = c2;
  958. }
  959. c++;
  960. }
  961. if( foundReplacement )
  962. {
  963. _string->release();
  964. _string = sub;
  965. }
  966. return *this;
  967. }
  968. String &String::replace(const String &s1, const String &s2)
  969. {
  970. // Find number of occurrences of s1 and
  971. // Calculate length of the new string...
  972. const U32 &s1len = s1.length();
  973. const U32 &s2len = s2.length();
  974. U32 pos = 0;
  975. Vector<U32> indices;
  976. StringChar *walk = _string->utf8();
  977. while ( walk )
  978. {
  979. // Casting away the const... was there a better way?
  980. walk = (StringChar*)StrFind( _string->utf8(), s1.c_str(), pos, Case|Left );
  981. if ( walk )
  982. {
  983. pos = SizeType(walk - _string->utf8());
  984. indices.push_back( pos );
  985. pos += s1len;
  986. }
  987. }
  988. // Early-out, no StringDatas found.
  989. if ( indices.size() == 0 )
  990. return *this;
  991. U32 newSize = size() - ( indices.size() * s1len ) + ( indices.size() * s2len );
  992. StringData *sub;
  993. if( newSize == 1 )
  994. sub = StringData::Empty();
  995. else
  996. {
  997. sub = new (newSize - 1 ) StringData( NULL );
  998. // Now assemble the new string from the pieces of the old...
  999. // Index into the old string
  1000. pos = 0;
  1001. // Index into the new string
  1002. U32 newPos = 0;
  1003. // Used to store a character count to be memcpy'd
  1004. U32 copyCharCount = 0;
  1005. for ( U32 i = 0; i < indices.size(); i++ )
  1006. {
  1007. const U32 &index = indices[i];
  1008. // Number of chars (if any) before the next indexed StringData
  1009. copyCharCount = index - pos;
  1010. // Copy chars before the StringData if we have any.
  1011. if ( copyCharCount > 0 )
  1012. {
  1013. dMemcpy( sub->utf8() + newPos, _string->utf8() + pos, copyCharCount * sizeof(StringChar) );
  1014. newPos += copyCharCount;
  1015. }
  1016. // Copy over the replacement string.
  1017. if ( s2len > 0 )
  1018. dMemcpy( sub->utf8() + newPos, s2._string->utf8(), s2len * sizeof(StringChar) );
  1019. newPos += s2len;
  1020. pos = index + s1len;
  1021. }
  1022. // There could be characters left in the original string after the last
  1023. // StringData occurrence, which we need to copy now - outside the loop.
  1024. copyCharCount = length() - indices.last() - s1len;
  1025. if ( copyCharCount != 0 )
  1026. dMemcpy( sub->utf8() + newPos, _string->utf8() + pos, copyCharCount * sizeof(StringChar) );
  1027. // Null terminate it!
  1028. sub->utf8()[newSize-1] = 0;
  1029. }
  1030. _string->release();
  1031. _string = sub;
  1032. return *this;
  1033. }
  1034. //-----------------------------------------------------------------------------
  1035. String String::substr(SizeType pos, SizeType len) const
  1036. {
  1037. //PROFILE_SCOPE( String_substr );
  1038. AssertFatal( pos <= length(), "String::substr - Invalid position!" );
  1039. if ( len == -1 )
  1040. len = length() - pos;
  1041. AssertFatal( len + pos <= length(), "String::substr - Invalid length!" );
  1042. StringData* sub;
  1043. if( !len )
  1044. sub = StringData::Empty();
  1045. else
  1046. sub = new ( len ) StringData( _string->utf8() + pos );
  1047. return sub;
  1048. }
  1049. //-----------------------------------------------------------------------------
  1050. String String::trim() const
  1051. {
  1052. if( isEmpty() )
  1053. return *this;
  1054. const StringChar* start = _string->utf8();
  1055. while( *start && dIsspace( *start ) )
  1056. start ++;
  1057. const StringChar* end = _string->utf8() + length() - 1;
  1058. while( end > start && dIsspace( *end ) )
  1059. end --;
  1060. end ++;
  1061. const U32 len = end - start;
  1062. if( len == length() )
  1063. return *this;
  1064. StringData* sub;
  1065. if( !len )
  1066. sub = StringData::Empty();
  1067. else
  1068. sub = new ( len ) StringData( start );
  1069. return sub;
  1070. }
  1071. //-----------------------------------------------------------------------------
  1072. String String::expandEscapes() const
  1073. {
  1074. char* tmp = ( char* ) dMalloc( length() * 2 + 1 ); // worst-case situation.
  1075. expandEscape( tmp, c_str() );
  1076. String str( tmp );
  1077. dFree( tmp );
  1078. return str;
  1079. }
  1080. //-----------------------------------------------------------------------------
  1081. String String::collapseEscapes() const
  1082. {
  1083. char* tmp = dStrdup( c_str() );
  1084. collapseEscape( tmp );
  1085. String str( tmp );
  1086. dFree( tmp );
  1087. return str;
  1088. }
  1089. //-----------------------------------------------------------------------------
  1090. void String::split( const char* delimiter, Vector< String >& outElements ) const
  1091. {
  1092. const char* ptr = _string->utf8();
  1093. const char* start = ptr;
  1094. while( *ptr )
  1095. {
  1096. // Search for start of delimiter.
  1097. if( *ptr != delimiter[ 0 ] )
  1098. ptr ++;
  1099. else
  1100. {
  1101. // Skip delimiter.
  1102. const char* end = ptr;
  1103. const char* del = delimiter;
  1104. while( *del && *del == *ptr )
  1105. {
  1106. ptr ++;
  1107. del ++;
  1108. }
  1109. // If we didn't match all of delimiter,
  1110. // continue with search.
  1111. if( *del != '\0' )
  1112. continue;
  1113. // Extract component.
  1114. outElements.push_back( String( start, end - start ) );
  1115. start = ptr;
  1116. }
  1117. }
  1118. // Add rest of string if there is any.
  1119. if( start != ptr )
  1120. outElements.push_back( start );
  1121. }
  1122. //-----------------------------------------------------------------------------
  1123. bool String::startsWith( const char* text ) const
  1124. {
  1125. return dStrStartsWith( _string->utf8(), text );
  1126. }
  1127. //-----------------------------------------------------------------------------
  1128. bool String::endsWith( const char* text ) const
  1129. {
  1130. return dStrEndsWith( _string->utf8(), text );
  1131. }
  1132. //-----------------------------------------------------------------------------
  1133. void String::copy(StringChar* dst, const StringChar *src, U32 len)
  1134. {
  1135. dMemcpy(dst, src, len * sizeof(StringChar));
  1136. }
  1137. //-----------------------------------------------------------------------------
  1138. #if defined(TORQUE_OS_WIN) || defined(TORQUE_OS_XBOX) || defined(TORQUE_OS_XENON)
  1139. // This standard function is not defined when compiling with VC7...
  1140. #define vsnprintf _vsnprintf
  1141. #endif
  1142. String::StrFormat::~StrFormat()
  1143. {
  1144. if( _dynamicBuffer )
  1145. dFree( _dynamicBuffer );
  1146. }
  1147. S32 String::StrFormat::format( const char *format, void *args )
  1148. {
  1149. _len=0;
  1150. return formatAppend(format,args);
  1151. }
  1152. S32 String::StrFormat::formatAppend( const char *format, void *args )
  1153. {
  1154. // Format into the fixed buffer first.
  1155. S32 startLen = _len;
  1156. if (_dynamicBuffer == NULL)
  1157. {
  1158. _len += vsnprintf(_fixedBuffer + _len, sizeof(_fixedBuffer) - _len, format, *(va_list*)args);
  1159. if (_len >= 0 && _len < sizeof(_fixedBuffer))
  1160. return _len;
  1161. // Start off the dynamic buffer at twice fixed buffer size
  1162. _len = startLen;
  1163. _dynamicSize = sizeof(_fixedBuffer) * 2;
  1164. _dynamicBuffer = (char*)dMalloc(_dynamicSize);
  1165. dMemcpy(_dynamicBuffer, _fixedBuffer, _len + 1);
  1166. }
  1167. // Format into the dynamic buffer, if the buffer is not large enough, then
  1168. // keep doubling it's size until it is. The buffer is not reallocated
  1169. // using reallocate() to avoid unnecessary buffer copying.
  1170. _len += vsnprintf(_dynamicBuffer + _len, _dynamicSize - _len, format, *(va_list*)args);
  1171. while (_len < 0 || _len >= _dynamicSize)
  1172. {
  1173. _len = startLen;
  1174. _dynamicBuffer = (char*)dRealloc(_dynamicBuffer, _dynamicSize *= 2);
  1175. _len += vsnprintf(_dynamicBuffer + _len, _dynamicSize - _len, format, *(va_list*)args);
  1176. }
  1177. return _len;
  1178. }
  1179. S32 String::StrFormat::append(const char * str, S32 len)
  1180. {
  1181. if (_dynamicBuffer == NULL)
  1182. {
  1183. if (_len+len >= 0 && _len+len < sizeof(_fixedBuffer))
  1184. {
  1185. dMemcpy(_fixedBuffer + _len, str, len);
  1186. _len += len;
  1187. _fixedBuffer[_len] = '\0';
  1188. return _len;
  1189. }
  1190. _dynamicSize = sizeof(_fixedBuffer) * 2;
  1191. _dynamicBuffer = (char*)dMalloc(_dynamicSize);
  1192. dMemcpy(_dynamicBuffer, _fixedBuffer, _len + 1);
  1193. }
  1194. S32 newSize = _dynamicSize;
  1195. while (newSize < _len+len)
  1196. newSize *= 2;
  1197. if (newSize != _dynamicSize)
  1198. _dynamicBuffer = (char*) dRealloc(_dynamicBuffer, newSize);
  1199. _dynamicSize = newSize;
  1200. dMemcpy(_dynamicBuffer + _len, str, len);
  1201. _len += len;
  1202. _dynamicBuffer[_len] = '\0';
  1203. return _len;
  1204. }
  1205. S32 String::StrFormat::append(const char * str)
  1206. {
  1207. return append(str, dStrlen(str));
  1208. }
  1209. char* String::StrFormat::copy( char *buffer ) const
  1210. {
  1211. dMemcpy(buffer, _dynamicBuffer? _dynamicBuffer: _fixedBuffer, _len+1);
  1212. return buffer;
  1213. }
  1214. //-----------------------------------------------------------------------------
  1215. String String::ToString( bool value )
  1216. {
  1217. static String sTrue = "true";
  1218. static String sFalse = "false";
  1219. if( value )
  1220. return sTrue;
  1221. return sFalse;
  1222. }
  1223. String String::ToString(const char *str, ...)
  1224. {
  1225. AssertFatal(str,"String:: Invalid null ptr argument");
  1226. // Use the format object
  1227. va_list args;
  1228. va_start(args, str);
  1229. String ret = VToString(str, args);
  1230. va_end(args);
  1231. return ret;
  1232. }
  1233. String String::VToString(const char* str, void* args)
  1234. {
  1235. StrFormat format(str,&args);
  1236. // Copy it into a string
  1237. U32 len = format.length();
  1238. StringData* sub;
  1239. if( !len )
  1240. sub = StringData::Empty();
  1241. else
  1242. {
  1243. sub = new ( len ) StringData( NULL );
  1244. format.copy( sub->utf8() );
  1245. sub->utf8()[ len ] = 0;
  1246. }
  1247. return sub;
  1248. }
  1249. String String::SpanToString(const char *start, const char *end)
  1250. {
  1251. if ( end == start )
  1252. return String();
  1253. AssertFatal( end > start, "Invalid arguments to String::SpanToString - end is before start" );
  1254. U32 len = U32(end - start);
  1255. StringData* sub = new ( len ) StringData( start );
  1256. return sub;
  1257. }
  1258. String String::ToLower(const String &string)
  1259. {
  1260. if ( string.isEmpty() )
  1261. return String();
  1262. StringData* sub = new ( string.length() ) StringData( string );
  1263. dStrlwr( sub->utf8() );
  1264. return sub;
  1265. }
  1266. String String::ToUpper(const String &string)
  1267. {
  1268. if ( string.isEmpty() )
  1269. return String();
  1270. StringData* sub = new ( string.length() ) StringData( string );
  1271. dStrupr( sub->utf8() );
  1272. return sub;
  1273. }
  1274. String String::GetTrailingNumber(const char* str, S32& number)
  1275. {
  1276. // Check for trivial strings
  1277. if (!str || !str[0])
  1278. return String::EmptyString;
  1279. // Find the number at the end of the string
  1280. String base(str);
  1281. const char* p = base.c_str() + base.length() - 1;
  1282. // Ignore trailing whitespace
  1283. while ((p != base.c_str()) && dIsspace(*p))
  1284. p--;
  1285. // Need at least one digit!
  1286. if (!isdigit(*p))
  1287. return base;
  1288. // Back up to the first non-digit character
  1289. while ((p != base.c_str()) && isdigit(*p))
  1290. p--;
  1291. // Convert number => allow negative numbers, treat '_' as '-' for Maya
  1292. if ((*p == '-') || (*p == '_'))
  1293. number = -dAtoi(p + 1);
  1294. else
  1295. number = ((p == base.c_str()) ? dAtoi(p) : dAtoi(++p));
  1296. // Remove space between the name and the number
  1297. while ((p > base.c_str()) && dIsspace(*(p-1)))
  1298. p--;
  1299. return base.substr(0, p - base.c_str());
  1300. }