PageRenderTime 68ms CodeModel.GetById 27ms RepoModel.GetById 1ms app.codeStats 0ms

/xbmc/lib/libUPnP/Platinum/ThirdParty/Neptune/Source/Core/NptStrings.cpp

https://github.com/pundy/plex
C++ | 942 lines | 606 code | 105 blank | 231 comment | 192 complexity | bf560f22a33b339edb25395901e3eb8c MD5 | raw file
Possible License(s): AGPL-1.0, GPL-2.0, LGPL-2.1, GPL-3.0, Unlicense
  1. /*****************************************************************
  2. |
  3. | Neptune - String Objects
  4. |
  5. | (c) 2001-2006 Gilles Boccon-Gibod
  6. | Author: Gilles Boccon-Gibod (bok@bok.net)
  7. |
  8. ****************************************************************/
  9. /*----------------------------------------------------------------------
  10. | includes
  11. +---------------------------------------------------------------------*/
  12. #include "NptConfig.h"
  13. #include "NptTypes.h"
  14. #include "NptConstants.h"
  15. #include "NptStrings.h"
  16. #include "NptResults.h"
  17. #include "NptUtils.h"
  18. #include "NptDebug.h"
  19. /*----------------------------------------------------------------------
  20. | constants
  21. +---------------------------------------------------------------------*/
  22. #define NPT_STRINGS_WHITESPACE_CHARS "\r\n\t "
  23. /*----------------------------------------------------------------------
  24. | helpers
  25. +---------------------------------------------------------------------*/
  26. inline char NPT_Uppercase(char x) {
  27. return (x >= 'a' && x <= 'z') ? x&0xdf : x;
  28. }
  29. inline char NPT_Lowercase(char x) {
  30. return (x >= 'A' && x <= 'Z') ? x^32 : x;
  31. }
  32. /*----------------------------------------------------------------------
  33. | NPT_String::EmptyString
  34. +---------------------------------------------------------------------*/
  35. char NPT_String::EmptyString = '\0';
  36. /*----------------------------------------------------------------------
  37. | NPT_String::FromInteger
  38. +---------------------------------------------------------------------*/
  39. NPT_String
  40. NPT_String::FromInteger(NPT_Int64 value)
  41. {
  42. char str[32];
  43. char* c = &str[31];
  44. *c-- = '\0';
  45. // handle the sign
  46. bool negative = false;
  47. if (value < 0) {
  48. negative = true;
  49. value = -value;
  50. }
  51. // process the digits
  52. do {
  53. int digit = (int)(value%10);
  54. *c-- = '0'+digit;
  55. value /= 10;
  56. } while(value);
  57. if (negative) {
  58. *c = '-';
  59. } else {
  60. ++c;
  61. }
  62. return NPT_String(c);
  63. }
  64. /*----------------------------------------------------------------------
  65. | NPT_String::FromIntegerU
  66. +---------------------------------------------------------------------*/
  67. NPT_String
  68. NPT_String::FromIntegerU(NPT_UInt64 value)
  69. {
  70. char str[32];
  71. char* c = &str[31];
  72. *c = '\0';
  73. // process the digits
  74. do {
  75. int digit = (int)(value%10);
  76. *--c = '0'+digit;
  77. value /= 10;
  78. } while(value);
  79. return NPT_String(c);
  80. }
  81. /*----------------------------------------------------------------------
  82. | NPT_String::NPT_String
  83. +---------------------------------------------------------------------*/
  84. NPT_String::NPT_String(const char* str)
  85. {
  86. if (str == NULL) {
  87. m_Chars = NULL;
  88. } else {
  89. m_Chars = Buffer::Create(str);
  90. }
  91. }
  92. /*----------------------------------------------------------------------
  93. | NPT_String::NPT_String
  94. +---------------------------------------------------------------------*/
  95. NPT_String::NPT_String(const char* str, NPT_Size length)
  96. {
  97. if (str == NULL || length == 0) {
  98. m_Chars = NULL;
  99. } else {
  100. m_Chars = Buffer::Create(str, length);
  101. }
  102. }
  103. /*----------------------------------------------------------------------
  104. | NPT_String::NPT_String
  105. +---------------------------------------------------------------------*/
  106. NPT_String::NPT_String(const NPT_String& str)
  107. {
  108. if (str.GetLength() == 0) {
  109. m_Chars = NULL;
  110. } else {
  111. m_Chars = Buffer::Create(str.GetChars(), str.GetLength());
  112. }
  113. }
  114. /*----------------------------------------------------------------------
  115. | NPT_String::NPT_String
  116. +---------------------------------------------------------------------*/
  117. NPT_String::NPT_String(const char* str,
  118. NPT_Ordinal first,
  119. NPT_Size length)
  120. {
  121. // shortcut
  122. if (str != NULL && length != 0) {
  123. // truncate length
  124. NPT_Size str_length = StringLength(str);
  125. if (first < str_length) {
  126. if (first+length > str_length) {
  127. length = str_length-first;
  128. }
  129. if (length != 0) {
  130. m_Chars = Buffer::Create(str+first, length);
  131. return;
  132. }
  133. }
  134. }
  135. m_Chars = NULL;
  136. }
  137. /*----------------------------------------------------------------------
  138. | NPT_String::NPT_String
  139. +---------------------------------------------------------------------*/
  140. NPT_String::NPT_String(char c, NPT_Cardinal repeat)
  141. {
  142. if (repeat != 0) {
  143. m_Chars = Buffer::Create(c, repeat);
  144. } else {
  145. m_Chars = NULL;
  146. }
  147. }
  148. /*----------------------------------------------------------------------
  149. | NPT_String::SetLength
  150. +---------------------------------------------------------------------*/
  151. NPT_Result
  152. NPT_String::SetLength(NPT_Size length)
  153. {
  154. if (m_Chars == NULL) {
  155. return (length == 0 ? NPT_SUCCESS : NPT_ERROR_INVALID_PARAMETERS);
  156. }
  157. if (length <= GetBuffer()->GetAllocated()) {
  158. char* chars = UseChars();
  159. GetBuffer()->SetLength(length);
  160. chars[length] = '\0';
  161. return NPT_SUCCESS;
  162. } else {
  163. return NPT_ERROR_INVALID_PARAMETERS;
  164. }
  165. }
  166. /*----------------------------------------------------------------------
  167. | NPT_String::PrepareToWrite
  168. +---------------------------------------------------------------------*/
  169. inline char*
  170. NPT_String::PrepareToWrite(NPT_Size length)
  171. {
  172. NPT_ASSERT(length != 0);
  173. if (m_Chars == NULL || GetBuffer()->GetAllocated() < length) {
  174. // the buffer is too small, we need to allocate a new one.
  175. NPT_Size needed = length;
  176. if (m_Chars != NULL) {
  177. NPT_Size grow = GetBuffer()->GetAllocated()*2;
  178. if (grow > length) needed = grow;
  179. delete GetBuffer();
  180. }
  181. m_Chars = Buffer::Create(needed);
  182. }
  183. GetBuffer()->SetLength(length);
  184. return m_Chars;
  185. }
  186. /*----------------------------------------------------------------------
  187. | NPT_String::Reserve
  188. +---------------------------------------------------------------------*/
  189. void
  190. NPT_String::Reserve(NPT_Size allocate)
  191. {
  192. if (m_Chars == NULL || GetBuffer()->GetAllocated() < allocate) {
  193. // the buffer is too small, we need to allocate a new one.
  194. NPT_Size needed = allocate;
  195. if (m_Chars != NULL) {
  196. NPT_Size grow = GetBuffer()->GetAllocated()*2;
  197. if (grow > allocate) needed = grow;
  198. }
  199. NPT_Size length = GetLength();
  200. char* copy = Buffer::Create(needed, length);
  201. if (m_Chars != NULL) {
  202. CopyString(copy, m_Chars);
  203. delete GetBuffer();
  204. } else {
  205. copy[0] = '\0';
  206. }
  207. m_Chars = copy;
  208. }
  209. }
  210. /*----------------------------------------------------------------------
  211. | NPT_String::Assign
  212. +---------------------------------------------------------------------*/
  213. void
  214. NPT_String::Assign(const char* str, NPT_Size length)
  215. {
  216. if (str == NULL || length == 0) {
  217. Reset();
  218. } else {
  219. PrepareToWrite(length);
  220. CopyBuffer(m_Chars, str, length);
  221. m_Chars[length] = '\0';
  222. }
  223. }
  224. /*----------------------------------------------------------------------
  225. | NPT_String::operator=
  226. +---------------------------------------------------------------------*/
  227. NPT_String&
  228. NPT_String::operator=(const char* str)
  229. {
  230. if (str == NULL) {
  231. Reset();
  232. } else {
  233. NPT_Size length = StringLength(str);
  234. if (length == 0) {
  235. Reset();
  236. } else {
  237. CopyString(PrepareToWrite(length), str);
  238. }
  239. }
  240. return *this;
  241. }
  242. /*----------------------------------------------------------------------
  243. | NPT_String::operator=
  244. +---------------------------------------------------------------------*/
  245. NPT_String&
  246. NPT_String::operator=(const NPT_String& str)
  247. {
  248. // do nothing if we're assigning to ourselves
  249. if (this != &str) {
  250. Assign(str.GetChars(), str.GetLength());
  251. }
  252. return *this;
  253. }
  254. /*----------------------------------------------------------------------
  255. | NPT_String::Append
  256. +---------------------------------------------------------------------*/
  257. void
  258. NPT_String::Append(const char* str, NPT_Size length)
  259. {
  260. // shortcut
  261. if (str == NULL || length == 0) return;
  262. // compute the new length
  263. NPT_Size old_length = GetLength();
  264. NPT_Size new_length = old_length + length;
  265. // allocate enough space
  266. Reserve(new_length);
  267. // append the new string at the end of the current one
  268. CopyBuffer(m_Chars+old_length, str, length);
  269. m_Chars[new_length] = '\0';
  270. // update the length
  271. GetBuffer()->SetLength(new_length);
  272. }
  273. /*----------------------------------------------------------------------
  274. | NPT_String::Compare
  275. +---------------------------------------------------------------------*/
  276. int
  277. NPT_String::Compare(const char *s, bool ignore_case) const
  278. {
  279. return NPT_String::Compare(GetChars(), s, ignore_case);
  280. }
  281. /*----------------------------------------------------------------------
  282. | NPT_String::Compare
  283. +---------------------------------------------------------------------*/
  284. int
  285. NPT_String::Compare(const char *s1, const char *s2, bool ignore_case)
  286. {
  287. const char *r1 = s1;
  288. const char *r2 = s2;
  289. if (ignore_case) {
  290. while (NPT_Uppercase(*r1) == NPT_Uppercase(*r2)) {
  291. if (*r1++ == '\0') {
  292. return 0;
  293. }
  294. r2++;
  295. }
  296. return NPT_Uppercase(*r1) - NPT_Uppercase(*r2);
  297. } else {
  298. while (*r1 == *r2) {
  299. if (*r1++ == '\0') {
  300. return 0;
  301. }
  302. r2++;
  303. }
  304. return (*r1 - *r2);
  305. }
  306. }
  307. /*----------------------------------------------------------------------
  308. | NPT_String::CompareN
  309. +---------------------------------------------------------------------*/
  310. int
  311. NPT_String::CompareN(const char *s, NPT_Size count, bool ignore_case) const
  312. {
  313. return NPT_String::CompareN(GetChars(), s, count, ignore_case);
  314. }
  315. /*----------------------------------------------------------------------
  316. | NPT_String::CompareN
  317. +---------------------------------------------------------------------*/
  318. int
  319. NPT_String::CompareN(const char* s1, const char *s2, NPT_Size count, bool ignore_case)
  320. {
  321. const char* me = s1;
  322. if (ignore_case) {
  323. for (unsigned int i=0; i<count; i++) {
  324. if (NPT_Uppercase(me[i]) != NPT_Uppercase(s2[i])) {
  325. return NPT_Uppercase(me[i]) - NPT_Uppercase(s2[i]);
  326. }
  327. }
  328. return 0;
  329. } else {
  330. for (unsigned int i=0; i<count; i++) {
  331. if (me[i] != s2[i]) {
  332. return (me[i] - s2[i]);
  333. }
  334. }
  335. return 0;
  336. }
  337. }
  338. /*----------------------------------------------------------------------
  339. | NPT_String::Split
  340. +---------------------------------------------------------------------*/
  341. NPT_List<NPT_String>
  342. NPT_String::Split(const char* separator) const
  343. {
  344. NPT_List<NPT_String> result;
  345. NPT_Size separator_length = NPT_StringLength(separator);
  346. // sepcial case for empty separators
  347. if (separator_length == 0) {
  348. result.Add(*this);
  349. return result;
  350. }
  351. int current = 0;
  352. int next;
  353. do {
  354. next = Find(separator, current);
  355. unsigned int end = (next>=0?next:GetLength());
  356. result.Add(SubString(current, end-current));
  357. current = next+separator_length;
  358. } while (next >= 0);
  359. return result;
  360. }
  361. /*----------------------------------------------------------------------
  362. | NPT_String::SubString
  363. +---------------------------------------------------------------------*/
  364. NPT_String
  365. NPT_String::SubString(NPT_Ordinal first, NPT_Size length) const
  366. {
  367. if (first >= GetLength()) {
  368. first = GetLength();
  369. length = 0;
  370. } else if (first+length >= GetLength()) {
  371. length = GetLength()-first;
  372. }
  373. return NPT_String(GetChars()+first, length);
  374. }
  375. /*----------------------------------------------------------------------
  376. | NPT_StringStartsWith
  377. |
  378. | returns:
  379. | 1 if str starts with sub,
  380. | 0 if str is large enough but does not start with sub
  381. | -1 if str is too short to start with sub
  382. +---------------------------------------------------------------------*/
  383. static inline int
  384. NPT_StringStartsWith(const char* str, const char* sub, bool ignore_case)
  385. {
  386. if (ignore_case) {
  387. while (NPT_Uppercase(*str) == NPT_Uppercase(*sub)) {
  388. if (*str++ == '\0') {
  389. return 1;
  390. }
  391. sub++;
  392. }
  393. } else {
  394. while (*str == *sub) {
  395. if (*str++ == '\0') {
  396. return 1;
  397. }
  398. sub++;
  399. }
  400. }
  401. return (*sub == '\0') ? 1 : (*str == '\0' ? -1 : 0);
  402. }
  403. /*----------------------------------------------------------------------
  404. | NPT_String::StartsWith
  405. +---------------------------------------------------------------------*/
  406. bool
  407. NPT_String::StartsWith(const char *s, bool ignore_case) const
  408. {
  409. if (s == NULL) return false;
  410. return NPT_StringStartsWith(GetChars(), s, ignore_case) == 1;
  411. }
  412. /*----------------------------------------------------------------------
  413. | NPT_String::EndsWith
  414. +---------------------------------------------------------------------*/
  415. bool
  416. NPT_String::EndsWith(const char *s, bool ignore_case) const
  417. {
  418. if (s == NULL) return false;
  419. NPT_Size str_length = NPT_StringLength(s);
  420. if (str_length > GetLength()) return false;
  421. return NPT_StringStartsWith(GetChars()+GetLength()-str_length, s, ignore_case) == 1;
  422. }
  423. /*----------------------------------------------------------------------
  424. | NPT_String::Find
  425. +---------------------------------------------------------------------*/
  426. int
  427. NPT_String::Find(const char* str, NPT_Ordinal start, bool ignore_case) const
  428. {
  429. // check args
  430. if (str == NULL || start >= GetLength()) return -1;
  431. // skip to start position
  432. const char* src = m_Chars + start;
  433. // look for a substring
  434. while (*src) {
  435. int cmp = NPT_StringStartsWith(src, str, ignore_case);
  436. switch (cmp) {
  437. case -1:
  438. // ref is too short, abort
  439. return -1;
  440. case 1:
  441. // match
  442. return (int)(src-m_Chars);
  443. }
  444. src++;
  445. }
  446. return -1;
  447. }
  448. /*----------------------------------------------------------------------
  449. | NPT_String::Find
  450. +---------------------------------------------------------------------*/
  451. int
  452. NPT_String::Find(char c, NPT_Ordinal start, bool ignore_case) const
  453. {
  454. // check args
  455. if (start >= GetLength()) return -1;
  456. // skip to start position
  457. const char* src = m_Chars + start;
  458. // look for the character
  459. if (ignore_case) {
  460. while (*src) {
  461. if (NPT_Uppercase(*src) == NPT_Uppercase(c)) {
  462. return (int)(src-m_Chars);
  463. }
  464. src++;
  465. }
  466. } else {
  467. while (*src) {
  468. if (*src == c) return (int)(src-m_Chars);
  469. src++;
  470. }
  471. }
  472. return -1;
  473. }
  474. /*----------------------------------------------------------------------
  475. | NPT_String::ReverseFind
  476. +---------------------------------------------------------------------*/
  477. int
  478. NPT_String::ReverseFind(const char* str, NPT_Ordinal start, bool ignore_case) const
  479. {
  480. // check args
  481. if (str == NULL || *str == '\0') return -1;
  482. // look for a substring
  483. NPT_Size my_length = GetLength();
  484. NPT_Size str_length = NPT_StringLength(str);
  485. int i=my_length-start-str_length;
  486. const char* src = GetChars();
  487. if (i<0) return -1;
  488. for (;i>=0; i--) {
  489. int cmp = NPT_StringStartsWith(src+i, str, ignore_case);
  490. if (cmp == 1) {
  491. // match
  492. return i;
  493. }
  494. }
  495. return -1;
  496. }
  497. /*----------------------------------------------------------------------
  498. | NPT_String::ReverseFind
  499. +---------------------------------------------------------------------*/
  500. int
  501. NPT_String::ReverseFind(char c, NPT_Ordinal start, bool ignore_case) const
  502. {
  503. // check args
  504. NPT_Size length = GetLength();
  505. int i = length-start-1;
  506. if (i < 0) return -1;
  507. // look for the character
  508. const char* src = GetChars();
  509. if (ignore_case) {
  510. for (;i>=0;i--) {
  511. if (NPT_Uppercase(src[i]) == NPT_Uppercase(c)) {
  512. return i;
  513. }
  514. }
  515. } else {
  516. for (;i>=0;i--) {
  517. if (src[i] == c) return i;
  518. }
  519. }
  520. return -1;
  521. }
  522. /*----------------------------------------------------------------------
  523. | NPT_String::MakeLowercase
  524. +---------------------------------------------------------------------*/
  525. void
  526. NPT_String::MakeLowercase()
  527. {
  528. // the source is the current buffer
  529. const char* src = GetChars();
  530. // convert all the characters of the existing buffer
  531. char* dst = const_cast<char*>(src);
  532. while (*dst != '\0') {
  533. *dst = NPT_Lowercase(*dst);
  534. dst++;
  535. }
  536. }
  537. /*----------------------------------------------------------------------
  538. | NPT_String::MakeUppercase
  539. +---------------------------------------------------------------------*/
  540. void
  541. NPT_String::MakeUppercase()
  542. {
  543. // the source is the current buffer
  544. const char* src = GetChars();
  545. // convert all the characters of the existing buffer
  546. char* dst = const_cast<char*>(src);
  547. while (*dst != '\0') {
  548. *dst = NPT_Uppercase(*dst);
  549. dst++;
  550. }
  551. }
  552. /*----------------------------------------------------------------------
  553. | NPT_String::ToLowercase
  554. +---------------------------------------------------------------------*/
  555. NPT_String
  556. NPT_String::ToLowercase() const
  557. {
  558. NPT_String result(*this);
  559. result.MakeLowercase();
  560. return result;
  561. }
  562. /*----------------------------------------------------------------------
  563. | NPT_String::ToUppercase
  564. +---------------------------------------------------------------------*/
  565. NPT_String
  566. NPT_String::ToUppercase() const
  567. {
  568. NPT_String result(*this);
  569. result.MakeUppercase();
  570. return result;
  571. }
  572. /*----------------------------------------------------------------------
  573. | NPT_String::Replace
  574. +---------------------------------------------------------------------*/
  575. void
  576. NPT_String::Replace(char a, char b)
  577. {
  578. // check args
  579. if (m_Chars == NULL || a == '\0' || b == '\0') return;
  580. // we are going to modify the characters
  581. char* src = m_Chars;
  582. // process the buffer in place
  583. while (*src) {
  584. if (*src == a) *src = b;
  585. src++;
  586. }
  587. }
  588. /*----------------------------------------------------------------------
  589. | NPT_String::Insert
  590. +---------------------------------------------------------------------*/
  591. void
  592. NPT_String::Insert(const char* str, NPT_Ordinal where)
  593. {
  594. // check args
  595. if (str == NULL || where > GetLength()) return;
  596. // measure the string to insert
  597. NPT_Size str_length = StringLength(str);
  598. if (str_length == 0) return;
  599. // compute the size of the new string
  600. NPT_Size old_length = GetLength();
  601. NPT_Size new_length = str_length + GetLength();
  602. // prepare to write the new string
  603. char* src = m_Chars;
  604. char* nst = Buffer::Create(new_length, new_length);
  605. char* dst = nst;
  606. // copy the beginning of the old string
  607. if (where > 0) {
  608. CopyBuffer(dst, src, where);
  609. src += where;
  610. dst += where;
  611. }
  612. // copy the inserted string
  613. CopyString(dst, str);
  614. dst += str_length;
  615. // copy the end of the old string
  616. if (old_length > where) {
  617. CopyString(dst, src);
  618. }
  619. // use the new string
  620. if (m_Chars) delete GetBuffer();
  621. m_Chars = nst;
  622. }
  623. /*----------------------------------------------------------------------
  624. | NPT_String::Erase
  625. +---------------------------------------------------------------------*/
  626. void
  627. NPT_String::Erase(NPT_Ordinal start, NPT_Cardinal count /* = 1 */)
  628. {
  629. // check bounds
  630. NPT_Size length = GetLength();
  631. if (start+count > length) {
  632. if (start >= length) return;
  633. count = length-start;
  634. }
  635. if (count == 0) return;
  636. CopyString(m_Chars+start, m_Chars+start+count);
  637. GetBuffer()->SetLength(length-count);
  638. }
  639. /*----------------------------------------------------------------------
  640. | NPT_String::ToInteger
  641. +---------------------------------------------------------------------*/
  642. NPT_Result
  643. NPT_String::ToInteger(unsigned long& value, bool relaxed) const
  644. {
  645. return NPT_ParseUInteger(GetChars(), value, relaxed);
  646. }
  647. /*----------------------------------------------------------------------
  648. | NPT_String::ToInteger
  649. +---------------------------------------------------------------------*/
  650. NPT_Result
  651. NPT_String::ToInteger(long& value, bool relaxed) const
  652. {
  653. return NPT_ParseInteger(GetChars(), value, relaxed);
  654. }
  655. /*----------------------------------------------------------------------
  656. | NPT_String::ToInteger
  657. +---------------------------------------------------------------------*/
  658. NPT_Result
  659. NPT_String::ToInteger(NPT_UInt64& value, bool relaxed) const
  660. {
  661. return NPT_ParseUInteger64(GetChars(), value, relaxed);
  662. }
  663. /*----------------------------------------------------------------------
  664. | NPT_String::ToFloat
  665. +---------------------------------------------------------------------*/
  666. NPT_Result
  667. NPT_String::ToFloat(float& value, bool relaxed) const
  668. {
  669. return NPT_ParseFloat(GetChars(), value, relaxed);
  670. }
  671. /*----------------------------------------------------------------------
  672. | NPT_String::TrimLeft
  673. +---------------------------------------------------------------------*/
  674. void
  675. NPT_String::TrimLeft()
  676. {
  677. TrimLeft(NPT_STRINGS_WHITESPACE_CHARS);
  678. }
  679. /*----------------------------------------------------------------------
  680. | NPT_String::TrimLeft
  681. +---------------------------------------------------------------------*/
  682. void
  683. NPT_String::TrimLeft(char c)
  684. {
  685. char s[2] = {c, 0};
  686. TrimLeft((const char*)s);
  687. }
  688. /*----------------------------------------------------------------------
  689. | NPT_String::TrimLeft
  690. +---------------------------------------------------------------------*/
  691. void
  692. NPT_String::TrimLeft(const char* chars)
  693. {
  694. if (m_Chars == NULL) return;
  695. const char* s = m_Chars;
  696. while (char c = *s) {
  697. const char* x = chars;
  698. while (*x) {
  699. if (*x == c) break;
  700. x++;
  701. }
  702. if (*x == 0) break; // not found
  703. s++;
  704. }
  705. if (s == m_Chars) {
  706. // nothing was trimmed
  707. return;
  708. }
  709. // shift chars to the left
  710. char* d = m_Chars;
  711. GetBuffer()->SetLength(GetLength()-(s-d));
  712. while ((*d++ = *s++)) {};
  713. }
  714. /*----------------------------------------------------------------------
  715. | NPT_String::TrimRight
  716. +---------------------------------------------------------------------*/
  717. void
  718. NPT_String::TrimRight()
  719. {
  720. TrimRight(NPT_STRINGS_WHITESPACE_CHARS);
  721. }
  722. /*----------------------------------------------------------------------
  723. | NPT_String::TrimRight
  724. +---------------------------------------------------------------------*/
  725. void
  726. NPT_String::TrimRight(char c)
  727. {
  728. char s[2] = {c, 0};
  729. TrimRight((const char*)s);
  730. }
  731. /*----------------------------------------------------------------------
  732. | NPT_String::TrimRight
  733. +---------------------------------------------------------------------*/
  734. void
  735. NPT_String::TrimRight(const char* chars)
  736. {
  737. if (m_Chars == NULL || m_Chars[0] == '\0') return;
  738. char* tail = m_Chars+GetLength()-1;
  739. char* s = tail;
  740. while (s != m_Chars-1) {
  741. const char* x = chars;
  742. while (*x) {
  743. if (*x == *s) {
  744. *s = '\0';
  745. break;
  746. }
  747. x++;
  748. }
  749. if (*x == 0) break; // not found
  750. s--;
  751. }
  752. if (s == tail) {
  753. // nothing was trimmed
  754. return;
  755. }
  756. GetBuffer()->SetLength(1+(int)(s-m_Chars));
  757. }
  758. /*----------------------------------------------------------------------
  759. | NPT_String::Trim
  760. +---------------------------------------------------------------------*/
  761. void
  762. NPT_String::Trim()
  763. {
  764. TrimLeft();
  765. TrimRight();
  766. }
  767. /*----------------------------------------------------------------------
  768. | NPT_String::Trim
  769. +---------------------------------------------------------------------*/
  770. void
  771. NPT_String::Trim(char c)
  772. {
  773. char s[2] = {c, 0};
  774. TrimLeft((const char*)s);
  775. TrimRight((const char*)s);
  776. }
  777. /*----------------------------------------------------------------------
  778. | NPT_String::Trim
  779. +---------------------------------------------------------------------*/
  780. void
  781. NPT_String::Trim(const char* chars)
  782. {
  783. TrimLeft(chars);
  784. TrimRight(chars);
  785. }
  786. /*----------------------------------------------------------------------
  787. | NPT_String::operator+(const NPT_String&, const char*)
  788. +---------------------------------------------------------------------*/
  789. NPT_String
  790. operator+(const NPT_String& s1, const char* s2)
  791. {
  792. // shortcut
  793. if (s2 == NULL) return NPT_String(s1);
  794. // measure strings
  795. NPT_Size s1_length = s1.GetLength();
  796. NPT_Size s2_length = NPT_String::StringLength(s2);
  797. // allocate space for the new string
  798. NPT_String result;
  799. char* start = result.PrepareToWrite(s1_length+s2_length);
  800. // concatenate the two strings into the result
  801. NPT_String::CopyBuffer(start, s1, s1_length);
  802. NPT_String::CopyString(start+s1_length, s2);
  803. return result;
  804. }
  805. /*----------------------------------------------------------------------
  806. | NPT_String::operator+(const NPT_String& , const char*)
  807. +---------------------------------------------------------------------*/
  808. NPT_String
  809. operator+(const char* s1, const NPT_String& s2)
  810. {
  811. // shortcut
  812. if (s1 == NULL) return NPT_String(s2);
  813. // measure strings
  814. NPT_Size s1_length = NPT_String::StringLength(s1);
  815. NPT_Size s2_length = s2.GetLength();
  816. // allocate space for the new string
  817. NPT_String result;
  818. char* start = result.PrepareToWrite(s1_length+s2_length);
  819. // concatenate the two strings into the result
  820. NPT_String::CopyBuffer(start, s1, s1_length);
  821. NPT_String::CopyString(start+s1_length, s2.GetChars());
  822. return result;
  823. }
  824. /*----------------------------------------------------------------------
  825. | NPT_String::operator+(const NPT_String& , char)
  826. +---------------------------------------------------------------------*/
  827. NPT_String
  828. operator+(const NPT_String& s1, char c)
  829. {
  830. // allocate space for the new string
  831. NPT_String result;
  832. result.Reserve(s1.GetLength()+1);
  833. // append
  834. result = s1;
  835. result += c;
  836. return result;
  837. }