UString.cpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335
  1. /*
  2. ** Command & Conquer Generals(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /******************************************************************************
  19. *
  20. * FILE
  21. * $Archive: $
  22. *
  23. * DESCRIPTION
  24. * String management class (Unicode)
  25. *
  26. * PROGRAMMER
  27. * Denzil E. Long, Jr.
  28. * $Author: $
  29. *
  30. * VERSION INFO
  31. * $Modtime: $
  32. * $Revision: $
  33. *
  34. ******************************************************************************/
  35. #include "VisualC.h"
  36. #include "UString.h"
  37. #include "StringConvert.h"
  38. #include <string.h>
  39. #include <stdlib.h>
  40. #include <assert.h>
  41. // Convert character to lowercase
  42. template<typename T> T CharToLower(const T ch)
  43. {
  44. if ((ch >= (T)'A') && (ch <= (T)'Z'))
  45. {
  46. return (ch + 32);
  47. }
  48. return ch;
  49. }
  50. // Convert character to uppercase
  51. template<typename T> T CharToUpper(const T ch)
  52. {
  53. if ((ch >= (T)'a') && (ch <= (T)'z'))
  54. {
  55. return (ch - 32);
  56. }
  57. return ch;
  58. }
  59. // Check if character is one of the specified characters
  60. template<typename T>bool IsCharacter(WChar ch, const T* oneOf)
  61. {
  62. assert(oneOf != NULL);
  63. int length = 0;
  64. while (oneOf[length] != 0)
  65. {
  66. length++;
  67. }
  68. for (int index = 0; index < length; index++)
  69. {
  70. if (ch == (WChar)oneOf[index])
  71. {
  72. return true;
  73. }
  74. }
  75. return false;
  76. }
  77. // Strip all left side characters that are trim chars
  78. template<typename T> bool StripLeft(WChar* string, const T* trimChars)
  79. {
  80. // Strip leading trim characters from the string.
  81. WChar* start = string;
  82. while ((*start != 0) && IsCharacter<T>(*start, trimChars))
  83. {
  84. start++;
  85. }
  86. if (start != string)
  87. {
  88. wcscpy(string, start);
  89. }
  90. return true;
  91. }
  92. // Strip all right side characters that are trim chars
  93. template<typename T> bool StripRight(WChar* string, const T* trimChars)
  94. {
  95. int length = wcslen(string) - 1;
  96. int index = length;
  97. while (index >= 0)
  98. {
  99. if (!IsCharacter<T>(string[index], trimChars))
  100. {
  101. break;
  102. }
  103. string[index] = 0;
  104. index--;
  105. }
  106. return (index != length);
  107. }
  108. /******************************************************************************
  109. *
  110. * NAME
  111. * UString::UString - Default constructor
  112. *
  113. * DESCRIPTION
  114. * Create a new empty UString.
  115. *
  116. * INPUTS
  117. * NONE
  118. *
  119. * RESULT
  120. * NONE
  121. *
  122. ******************************************************************************/
  123. UString::UString()
  124. : mData(NULL),
  125. mCapacity(0)
  126. {
  127. }
  128. /******************************************************************************
  129. *
  130. * NAME
  131. * UString::UString - Capacity contructor
  132. *
  133. * DESCRIPTION
  134. * Create a new empty UString with the specified capacity.
  135. *
  136. * INPUTS
  137. * Capacity - Number of characters to allocated to string.
  138. *
  139. * RESULT
  140. * NONE
  141. *
  142. ******************************************************************************/
  143. UString::UString(UInt capacity)
  144. : mData(NULL),
  145. mCapacity(0)
  146. {
  147. AllocString(capacity);
  148. }
  149. /******************************************************************************
  150. *
  151. * NAME
  152. * UString::UString - ANSI string literal constructor
  153. *
  154. * DESCRIPTION
  155. * Create a new UString from an ANSI string literal
  156. *
  157. * INPUTS
  158. * String - Pointer to a NULL terminated ANSI string
  159. *
  160. * RESULT
  161. * NONE
  162. *
  163. ******************************************************************************/
  164. UString::UString(const Char* s)
  165. : mData(NULL),
  166. mCapacity(0)
  167. {
  168. Copy(s);
  169. }
  170. /******************************************************************************
  171. *
  172. * NAME
  173. * UString::UString - UNICODE string literal constructor
  174. *
  175. * DESCRIPTION
  176. * Create a new UString from a UNICODE string literal
  177. *
  178. * INPUTS
  179. * String - Pointer to a NULL terminated UNICODE string
  180. *
  181. * RESULT
  182. * NONE
  183. *
  184. ******************************************************************************/
  185. UString::UString(const WChar* ws)
  186. : mData(NULL),
  187. mCapacity(0)
  188. {
  189. Copy(ws);
  190. }
  191. /******************************************************************************
  192. *
  193. * NAME
  194. * UString::UString - Copy constructor
  195. *
  196. * DESCRIPTION
  197. * Create a new UString from another UString
  198. *
  199. * INPUTS
  200. * String - Reference to UString to copy
  201. *
  202. * RESULT
  203. * NONE
  204. *
  205. ******************************************************************************/
  206. UString::UString(const UString& s)
  207. : mData(NULL),
  208. mCapacity(0)
  209. {
  210. Copy(s);
  211. }
  212. /******************************************************************************
  213. *
  214. * NAME
  215. * UString::~UString - Destructor
  216. *
  217. * DESCRIPTION
  218. * Destroy the object
  219. *
  220. * INPUTS
  221. * NONE
  222. *
  223. * RESULT
  224. * NONE
  225. *
  226. ******************************************************************************/
  227. UString::~UString()
  228. {
  229. if (mData != NULL)
  230. {
  231. delete mData;
  232. }
  233. }
  234. /******************************************************************************
  235. *
  236. * NAME
  237. * UString::Length
  238. *
  239. * DESCRIPTION
  240. * Retrieve the length of the string in characters.
  241. *
  242. * INPUTS
  243. * NONE
  244. *
  245. * RESULT
  246. * Length - Length of string
  247. *
  248. ******************************************************************************/
  249. UInt UString::Length(void) const
  250. {
  251. if (mData == NULL)
  252. {
  253. return 0;
  254. }
  255. return wcslen(mData);
  256. }
  257. /******************************************************************************
  258. *
  259. * NAME
  260. * UString::Copy - ANSI string literal
  261. *
  262. * DESCRIPTION
  263. * Copy ANSI string literal.
  264. *
  265. * INPUTS
  266. * String - Pointer to ANSI string literal
  267. *
  268. * RESULT
  269. * NONE
  270. *
  271. ******************************************************************************/
  272. void UString::Copy(const Char* s)
  273. {
  274. assert(s != NULL);
  275. UInt length = strlen(s);
  276. if (length == 0)
  277. {
  278. return;
  279. }
  280. if (Capacity() < length)
  281. {
  282. AllocString(length);
  283. }
  284. // Copy and convert ansi string to unicode
  285. assert(Capacity() >= length);
  286. WChar* wsPtr = mData;
  287. const Char* sPtr = s;
  288. while (length-- > 0)
  289. {
  290. *wsPtr++ = (WChar)*sPtr++;
  291. }
  292. *wsPtr = 0;
  293. }
  294. /******************************************************************************
  295. *
  296. * NAME
  297. * UString::Copy - Unicode string literal
  298. *
  299. * DESCRIPTION
  300. * Copy a Unicode string literal
  301. *
  302. * INPUTS
  303. * String - Pointer to UNICODE string literal
  304. *
  305. * RESULT
  306. * NONE
  307. *
  308. ******************************************************************************/
  309. void UString::Copy(const WChar* ws)
  310. {
  311. assert(ws != NULL);
  312. UInt length = wcslen(ws);
  313. if (length == 0)
  314. {
  315. return;
  316. }
  317. if (Capacity() < length)
  318. {
  319. AllocString(length);
  320. }
  321. assert(Capacity() >= length);
  322. wcscpy(mData, ws);
  323. }
  324. /******************************************************************************
  325. *
  326. * NAME
  327. * UString::Copy
  328. *
  329. * DESCRIPTION
  330. * Copy string
  331. *
  332. * INPUTS
  333. * String - Reference to UString
  334. *
  335. * RESULT
  336. * NONE
  337. *
  338. ******************************************************************************/
  339. void UString::Copy(const UString& s)
  340. {
  341. Copy(s.Get());
  342. }
  343. /******************************************************************************
  344. *
  345. * NAME
  346. * UString::Concat - ANSI string literal
  347. *
  348. * DESCRIPTION
  349. * Concatenate an ANSI string literal to this string
  350. *
  351. * INPUTS
  352. * String - Pointer to ANSI string literal
  353. *
  354. * RESULT
  355. * NONE
  356. *
  357. ******************************************************************************/
  358. void UString::Concat(const Char* s)
  359. {
  360. // Parameter check
  361. assert(s != NULL);
  362. UInt length = Length();
  363. UInt additional = strlen(s);
  364. UInt totalLength = (length + additional);
  365. // Resize the string if the combined size is to small
  366. if (Capacity() < totalLength)
  367. {
  368. Resize(totalLength);
  369. }
  370. // Concatenate and convert ansi string to unicode
  371. WChar* wsPtr = &mData[length];
  372. const Char* sPtr = s;
  373. while (additional-- > 0)
  374. {
  375. *wsPtr++ = (WChar)*sPtr++;
  376. }
  377. *wsPtr = 0;
  378. }
  379. /******************************************************************************
  380. *
  381. * NAME
  382. * UString::Concat - Unicode string literal
  383. *
  384. * DESCRIPTION
  385. * Concatenate a Unicode string literal to this string
  386. *
  387. * INPUTS
  388. * String - Pointer to UNICODE string literal
  389. *
  390. * RESULT
  391. * NONE
  392. *
  393. ******************************************************************************/
  394. void UString::Concat(const WChar* ws)
  395. {
  396. assert(ws != NULL);
  397. UInt length = (Length() + wcslen(ws));
  398. if (Capacity() < length)
  399. {
  400. Resize(length);
  401. }
  402. wcscat(mData, ws);
  403. }
  404. /******************************************************************************
  405. *
  406. * NAME
  407. * UString::Concat
  408. *
  409. * DESCRIPTION
  410. * Concatenate string
  411. *
  412. * INPUTS
  413. * String - Reference to UString
  414. *
  415. * RESULT
  416. * NONE
  417. *
  418. ******************************************************************************/
  419. void UString::Concat(const UString& s)
  420. {
  421. Concat(s.Get());
  422. }
  423. /******************************************************************************
  424. *
  425. * NAME
  426. * UString::Compare - ANSI string literal
  427. *
  428. * DESCRIPTION
  429. * Compare strings, returning a value representing their relationship.
  430. *
  431. * INPUTS
  432. * String - String to compare against
  433. *
  434. * RESULT
  435. * Relationship - < 0 String less than this.
  436. * = 0 Strings identical
  437. * > 0 String greater than this.
  438. *
  439. ******************************************************************************/
  440. Int UString::Compare(const Char* s) const
  441. {
  442. // If comparing string is NULL and this string is NULL then strings are equal,
  443. // otherwise comparing string is less than this string.
  444. if (s == NULL)
  445. {
  446. if (Get() == NULL)
  447. {
  448. return 0;
  449. }
  450. return -1;
  451. }
  452. // If this string is NULL then comparing string is greater
  453. if (Get() == NULL)
  454. {
  455. return 1;
  456. }
  457. // Compare each character
  458. const WChar* ws = Get();
  459. Int index = 0;
  460. for (;;)
  461. {
  462. // Difference between characters
  463. Int diff = ((WChar)s[index] - ws[index]);
  464. // If the difference is not zero then the characters differ
  465. if (diff != 0)
  466. {
  467. return diff;
  468. }
  469. // If the end of either string has been reached then terminate loop
  470. if ((ws[index] == L'\0') || (s[index] == '\0'))
  471. {
  472. break;
  473. }
  474. // Advance to next character
  475. index++;
  476. }
  477. return 0;
  478. }
  479. /******************************************************************************
  480. *
  481. * NAME
  482. * UString::Compare - Unicode string literal
  483. *
  484. * DESCRIPTION
  485. * Compare strings, returning a value representing their relationship.
  486. *
  487. * INPUTS
  488. * String - String to compare against
  489. *
  490. * RESULT
  491. * Relationship - < 0 String less than this.
  492. * = 0 Strings identical
  493. * > 0 String greater than this.
  494. *
  495. ******************************************************************************/
  496. Int UString::Compare(const WChar* ws) const
  497. {
  498. return wcscmp(ws, Get());
  499. }
  500. /******************************************************************************
  501. *
  502. * NAME
  503. * UString::Compare
  504. *
  505. * DESCRIPTION
  506. * Compare strings, returning a value representing their relationship.
  507. *
  508. * INPUTS
  509. * String - String to compare against
  510. *
  511. * RESULT
  512. * Relationship - < 0 String less than this.
  513. * = 0 Strings identical
  514. * > 0 String greater than this.
  515. *
  516. ******************************************************************************/
  517. Int UString::Compare(const UString& s) const
  518. {
  519. return Compare(s.Get());
  520. }
  521. /******************************************************************************
  522. *
  523. * NAME
  524. * UString::CompareNoCase - ANSI string literal
  525. *
  526. * DESCRIPTION
  527. * Compare strings (case insensitive), returning a value representing their
  528. * relationship.
  529. *
  530. * INPUTS
  531. * String - String to compare against
  532. *
  533. * RESULT
  534. * Relationship - < 0 String less than this.
  535. * = 0 Strings identical
  536. * > 0 String greater than this.
  537. *
  538. ******************************************************************************/
  539. Int UString::CompareNoCase(const Char* s) const
  540. {
  541. // If comparing string is NULL and this string is NULL then strings are
  542. // equal, otherwise comparing string is less than this string.
  543. if (s == NULL)
  544. {
  545. if (Get() == NULL)
  546. {
  547. return 0;
  548. }
  549. return -1;
  550. }
  551. // If this string is NULL then comparing string is greater.
  552. if (Get() == NULL)
  553. {
  554. return 1;
  555. }
  556. // Compare each character
  557. const WChar* ws = Get();
  558. Int index = 0;
  559. for (;;)
  560. {
  561. // Convert to lowercase for compare
  562. WChar sc = (WChar)CharToLower<Char>(s[index]);
  563. WChar wc = CharToLower<WChar>(ws[index]);
  564. // Difference between characters.
  565. Int diff = (sc - wc);
  566. // If the difference is not zero then the characters differ.
  567. if (diff != 0)
  568. {
  569. return diff;
  570. }
  571. // If the end of either string has been reached then terminate loop.
  572. if ((ws[index] == L'\0') || (s[index] == '\0'))
  573. {
  574. break;
  575. }
  576. // Advance to next character
  577. index++;
  578. }
  579. return 0;
  580. }
  581. /******************************************************************************
  582. *
  583. * NAME
  584. * UString::CompareNoCase - Unicode string literal
  585. *
  586. * DESCRIPTION
  587. * Compare strings (case insensitive), returning a value representing their
  588. * relationship.
  589. *
  590. * INPUTS
  591. * String - String to compare against
  592. *
  593. * RESULT
  594. * Relationship - < 0 String less than this.
  595. * = 0 Strings identical
  596. * > 0 String greater than this.
  597. *
  598. ******************************************************************************/
  599. Int UString::CompareNoCase(const WChar* ws) const
  600. {
  601. return wcsicmp(ws, Get());
  602. }
  603. /******************************************************************************
  604. *
  605. * NAME
  606. * UString::CompareNoCase
  607. *
  608. * DESCRIPTION
  609. * Compare strings (case insensitive), returning a value representing their
  610. * relationship.
  611. *
  612. * INPUTS
  613. * String - String to compare against
  614. *
  615. * RESULT
  616. * Relationship - < 0 String less than this.
  617. * = 0 Strings identical
  618. * > 0 String greater than this.
  619. *
  620. ******************************************************************************/
  621. Int UString::CompareNoCase(const UString& s) const
  622. {
  623. return CompareNoCase(s.Get());
  624. }
  625. /******************************************************************************
  626. *
  627. * NAME
  628. * UString::Find - ANSI character
  629. *
  630. * DESCRIPTION
  631. * Find the first occurance of character
  632. *
  633. * INPUTS
  634. * Char - ANSI character to search for
  635. *
  636. * RESULT
  637. * Position - Position of character (-1 if not found)
  638. *
  639. ******************************************************************************/
  640. Int UString::Find(Char c) const
  641. {
  642. return Find((WChar)c);
  643. }
  644. /******************************************************************************
  645. *
  646. * NAME
  647. * UString::Find - Unicode character
  648. *
  649. * DESCRIPTION
  650. * Find the first occurance of character
  651. *
  652. * INPUTS
  653. * Char - Unicode character to search for.
  654. *
  655. * RESULT
  656. * Position - Position of character (-1 if not found)
  657. *
  658. ******************************************************************************/
  659. Int UString::Find(WChar c) const
  660. {
  661. WChar* ptr = wcschr(Get(), c);
  662. // Not found?
  663. if (ptr == NULL)
  664. {
  665. return -1;
  666. }
  667. return ((ptr - mData) / sizeof(WChar));
  668. }
  669. /******************************************************************************
  670. *
  671. * NAME
  672. * UString::FindLast - ANSI character
  673. *
  674. * DESCRIPTION
  675. * Find the last occurance of a character
  676. *
  677. * INPUTS
  678. * Char - ANSI character
  679. *
  680. * RESULT
  681. * Position - Position of character (-1 if not found)
  682. *
  683. ******************************************************************************/
  684. Int UString::FindLast(Char c) const
  685. {
  686. return FindLast((WChar)c);
  687. }
  688. /******************************************************************************
  689. *
  690. * NAME
  691. * UString::FindLast - Unicode character
  692. *
  693. * DESCRIPTION
  694. * Find the last occurance of a character
  695. *
  696. * INPUTS
  697. * Char - Unicode character
  698. *
  699. * RESULT
  700. * Position - Position of character (-1 if not found)
  701. *
  702. ******************************************************************************/
  703. Int UString::FindLast(WChar c) const
  704. {
  705. assert(mData != NULL);
  706. WChar* ptr = wcsrchr(mData, (WChar)c);
  707. // Not found?
  708. if (ptr == NULL)
  709. {
  710. return -1;
  711. }
  712. return ((ptr - mData) / sizeof(WChar));
  713. }
  714. /******************************************************************************
  715. *
  716. * NAME
  717. * UString::SubString - ANSI string literal
  718. *
  719. * DESCRIPTION
  720. * Find a substring
  721. *
  722. * INPUTS
  723. * SubString - Substring to search for.
  724. *
  725. * RESULT
  726. *
  727. *
  728. ******************************************************************************/
  729. UString UString::SubString(const Char* s)
  730. {
  731. assert(false);
  732. assert(s != NULL);
  733. return UString("");
  734. }
  735. UString UString::SubString(const WChar* ws)
  736. {
  737. assert(false);
  738. assert(ws != NULL);
  739. return UString("");
  740. }
  741. UString UString::SubString(const UString& s)
  742. {
  743. assert(false);
  744. return SubString(s.mData);
  745. }
  746. /******************************************************************************
  747. *
  748. * NAME
  749. * UString::Left
  750. *
  751. * DESCRIPTION
  752. * Extract left part of the string.
  753. *
  754. * INPUTS
  755. * Count - Number of characters to extract
  756. *
  757. * RESULT
  758. * Left - Extracted left part of the string
  759. *
  760. ******************************************************************************/
  761. UString UString::Left(UInt count)
  762. {
  763. assert(false);
  764. // If the count is zero then return an empty string.
  765. if ((Length() == 0) || (count == 0))
  766. {
  767. return UString("");
  768. }
  769. return UString("");
  770. }
  771. /******************************************************************************
  772. *
  773. * NAME
  774. * UString::Middle
  775. *
  776. * DESCRIPTION
  777. * Extract middle part of the string.
  778. *
  779. * INPUTS
  780. * First - Position of first character
  781. * Count - Number of characters to extract
  782. *
  783. * RESULT
  784. * Middle - Extracted middle part of the string
  785. *
  786. ******************************************************************************/
  787. UString UString::Middle(UInt first, UInt count)
  788. {
  789. assert(false);
  790. // If the first character position is greater than the length of the string
  791. // or the count is zero then return an empty string.
  792. if ((Length() < first) || (count == 0))
  793. {
  794. return UString("");
  795. }
  796. return UString("");
  797. }
  798. /******************************************************************************
  799. *
  800. * NAME
  801. * UString::Right
  802. *
  803. * DESCRIPTION
  804. * Extract right part of the string.
  805. *
  806. * INPUTS
  807. * Count - Number of characters to extract
  808. *
  809. * RESULT
  810. * Right - Extracted right part of the string
  811. *
  812. ******************************************************************************/
  813. UString UString::Right(UInt count)
  814. {
  815. UInt length = Length();
  816. // If the count is zero then return an empty string.
  817. if ((length == 0) || (count == 0))
  818. {
  819. return UString("");
  820. }
  821. const WChar* ptr = Get();
  822. UInt pos = (length - count);
  823. return UString(ptr[pos]);
  824. }
  825. /******************************************************************************
  826. *
  827. * NAME
  828. * UString::ToUpper
  829. *
  830. * DESCRIPTION
  831. * Convert string to uppercase
  832. *
  833. * INPUTS
  834. * NONE
  835. *
  836. * RESULT
  837. * NONE
  838. *
  839. ******************************************************************************/
  840. void UString::ToUpper(void)
  841. {
  842. if (mData != NULL)
  843. {
  844. wcsupr(mData);
  845. }
  846. }
  847. /******************************************************************************
  848. *
  849. * NAME
  850. * UString::ToLower
  851. *
  852. * DESCRIPTION
  853. * Convert string to lowercase
  854. *
  855. * INPUTS
  856. * NONE
  857. *
  858. * RESULT
  859. * NONE
  860. *
  861. ******************************************************************************/
  862. void UString::ToLower(void)
  863. {
  864. if (mData != NULL)
  865. {
  866. wcslwr(mData);
  867. }
  868. }
  869. /******************************************************************************
  870. *
  871. * NAME
  872. * UString::Reverse
  873. *
  874. * DESCRIPTION
  875. * Reverse characters of string
  876. *
  877. * INPUTS
  878. * NONE
  879. *
  880. * RESULT
  881. * NONE
  882. *
  883. ******************************************************************************/
  884. void UString::Reverse(void)
  885. {
  886. if (mData != NULL)
  887. {
  888. wcsrev(mData);
  889. }
  890. }
  891. /******************************************************************************
  892. *
  893. * NAME
  894. * UString::Trim
  895. *
  896. * DESCRIPTION
  897. * Remove leading and trailing characters from string.
  898. *
  899. * INPUTS
  900. * TrimChars - Characters to trim
  901. *
  902. * RESULT
  903. * Removed - True if any characters removed
  904. *
  905. ******************************************************************************/
  906. bool UString::Trim(const Char* trimChars)
  907. {
  908. bool leftRemoved = TrimLeft(trimChars);
  909. bool rightRemoved = TrimRight(trimChars);
  910. return (leftRemoved || rightRemoved);
  911. }
  912. bool UString::Trim(const WChar* trimChars)
  913. {
  914. bool leftRemoved = TrimLeft(trimChars);
  915. bool rightRemoved = TrimRight(trimChars);
  916. return (leftRemoved || rightRemoved);
  917. }
  918. bool UString::Trim(const UString& trimChars)
  919. {
  920. bool leftRemoved = TrimLeft(trimChars);
  921. bool rightRemoved = TrimRight(trimChars);
  922. return (leftRemoved || rightRemoved);
  923. }
  924. /******************************************************************************
  925. *
  926. * NAME
  927. * UString::TrimLeft
  928. *
  929. * DESCRIPTION
  930. * Remove characters from left side of string
  931. *
  932. * INPUTS
  933. * TrimChars - Characters to trim
  934. *
  935. * RESULT
  936. * Removed - True if any characters removed
  937. *
  938. ******************************************************************************/
  939. bool UString::TrimLeft(const Char* trimChars)
  940. {
  941. if ((trimChars == NULL) || (strlen(trimChars) == 0))
  942. {
  943. return false;
  944. }
  945. return StripLeft<Char>(mData, trimChars);
  946. }
  947. bool UString::TrimLeft(const WChar* trimChars)
  948. {
  949. if ((trimChars == NULL) || (wcslen(trimChars) == 0))
  950. {
  951. return false;
  952. }
  953. return StripLeft<WChar>(mData, trimChars);
  954. }
  955. bool UString::TrimLeft(const UString& trimChars)
  956. {
  957. return TrimLeft(trimChars.Get());
  958. }
  959. /******************************************************************************
  960. *
  961. * NAME
  962. * UString::TrimRight
  963. *
  964. * DESCRIPTION
  965. * Remove characters from right side of string
  966. *
  967. * INPUTS
  968. * TrimChars - Characters to trim
  969. *
  970. * RESULT
  971. * Removed - True if any characters removed
  972. *
  973. ******************************************************************************/
  974. bool UString::TrimRight(const Char* trimChars)
  975. {
  976. if ((trimChars == NULL) || (strlen(trimChars) == 0))
  977. {
  978. return false;
  979. }
  980. return StripRight<Char>(mData, trimChars);
  981. }
  982. bool UString::TrimRight(const WChar* trimChars)
  983. {
  984. if ((trimChars == NULL) || (wcslen(trimChars) == 0))
  985. {
  986. return false;
  987. }
  988. return StripRight<WChar>(mData, trimChars);
  989. }
  990. bool UString::TrimRight(const UString& trimChars)
  991. {
  992. return TrimRight(trimChars.mData);
  993. }
  994. /******************************************************************************
  995. *
  996. * NAME
  997. * UString::ConvertToANSI
  998. *
  999. * DESCRIPTION
  1000. * Convert the string to ANSI string
  1001. *
  1002. * INPUTS
  1003. * Buffer - Buffer to convert into
  1004. * Length - Maximum length of buffer
  1005. *
  1006. * RESULT
  1007. * NONE
  1008. *
  1009. ******************************************************************************/
  1010. void UString::ConvertToANSI(Char* buffer, UInt bufferLength) const
  1011. {
  1012. UStringToANSI(*this, buffer, bufferLength);
  1013. }
  1014. /******************************************************************************
  1015. *
  1016. * NAME
  1017. * UString::Size
  1018. *
  1019. * DESCRIPTION
  1020. * Retrieve the size of the string in bytes
  1021. *
  1022. * INPUTS
  1023. * NONE
  1024. *
  1025. * RESULT
  1026. * Size - Size of string in bytes
  1027. *
  1028. ******************************************************************************/
  1029. UInt UString::Size(void) const
  1030. {
  1031. if (mData == NULL)
  1032. {
  1033. return 0;
  1034. }
  1035. return ((Length() + 1) * sizeof(WChar));
  1036. }
  1037. /******************************************************************************
  1038. *
  1039. * NAME
  1040. * UString::Capacity
  1041. *
  1042. * DESCRIPTION
  1043. * Retrieve the capacity (maximum number of characters) of the string.
  1044. *
  1045. * INPUTS
  1046. * NONE
  1047. *
  1048. * RESULT
  1049. * Capacity - Maximum number of characters that string can hold.
  1050. *
  1051. ******************************************************************************/
  1052. UInt UString::Capacity(void) const
  1053. {
  1054. return mCapacity;
  1055. }
  1056. /******************************************************************************
  1057. *
  1058. * NAME
  1059. * UString::Resize
  1060. *
  1061. * DESCRIPTION
  1062. * Resize the string capacity.
  1063. *
  1064. * INPUTS
  1065. * NewSize - Size to resize string to.
  1066. *
  1067. * RESULT
  1068. * Success - True if successful; otherwise false
  1069. *
  1070. ******************************************************************************/
  1071. bool UString::Resize(UInt size)
  1072. {
  1073. // Allocate new storage
  1074. assert(size > 0);
  1075. WChar* data = new WChar[size + 1];
  1076. assert(data != NULL);
  1077. if (data == NULL)
  1078. {
  1079. return false;
  1080. }
  1081. // Copy existing string into new storage buffer
  1082. if (mData != NULL)
  1083. {
  1084. UInt minSize = __min(Capacity(), size);
  1085. wcsncpy(data, mData, minSize);
  1086. data[minSize] = 0;
  1087. delete mData;
  1088. }
  1089. // Set new storage
  1090. mData = data;
  1091. mCapacity = size;
  1092. return true;
  1093. }
  1094. /******************************************************************************
  1095. *
  1096. * NAME
  1097. * UString::AllocString
  1098. *
  1099. * DESCRIPTION
  1100. * Allocate string storage
  1101. *
  1102. * INPUTS
  1103. * Size - Number of characters
  1104. *
  1105. * RESULT
  1106. * Success - True if allocate successful; otherwise false
  1107. *
  1108. ******************************************************************************/
  1109. bool UString::AllocString(UInt size)
  1110. {
  1111. WChar* data = new WChar[size + 1];
  1112. assert(data != NULL);
  1113. if (data == NULL)
  1114. {
  1115. return false;
  1116. }
  1117. data[0] = 0;
  1118. if (mData != NULL)
  1119. {
  1120. delete mData;
  1121. }
  1122. mData = data;
  1123. mCapacity = size;
  1124. return true;
  1125. }