PageRenderTime 55ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 0ms

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

https://github.com/dtmetz/xbmc-fork
C++ | 910 lines | 585 code | 101 blank | 224 comment | 188 complexity | 7819d4b87bce1d2cb60204a590b633eb MD5 | raw file
Possible License(s): LGPL-2.1, AGPL-1.0, GPL-2.0
  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(long 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 = 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(unsigned long value)
  69. {
  70. char str[32];
  71. char* c = &str[31];
  72. *c = '\0';
  73. // process the digits
  74. do {
  75. int digit = 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::SubString
  340. +---------------------------------------------------------------------*/
  341. NPT_String
  342. NPT_String::SubString(NPT_Ordinal first, NPT_Size length) const
  343. {
  344. return NPT_String(*this, first, length);
  345. }
  346. /*----------------------------------------------------------------------
  347. | NPT_StringStartsWith
  348. |
  349. | returns:
  350. | 1 if str starts with sub,
  351. | 0 if str is large enough but does not start with sub
  352. | -1 if str is too short to start with sub
  353. +---------------------------------------------------------------------*/
  354. static inline int
  355. NPT_StringStartsWith(const char* str, const char* sub, bool ignore_case)
  356. {
  357. if (ignore_case) {
  358. while (NPT_Uppercase(*str) == NPT_Uppercase(*sub)) {
  359. if (*str++ == '\0') {
  360. return 1;
  361. }
  362. sub++;
  363. }
  364. } else {
  365. while (*str == *sub) {
  366. if (*str++ == '\0') {
  367. return 1;
  368. }
  369. sub++;
  370. }
  371. }
  372. return (*sub == '\0') ? 1 : (*str == '\0' ? -1 : 0);
  373. }
  374. /*----------------------------------------------------------------------
  375. | NPT_String::StartsWith
  376. +---------------------------------------------------------------------*/
  377. bool
  378. NPT_String::StartsWith(const char *s, bool ignore_case) const
  379. {
  380. if (s == NULL) return false;
  381. return NPT_StringStartsWith(GetChars(), s, ignore_case) == 1;
  382. }
  383. /*----------------------------------------------------------------------
  384. | NPT_String::EndsWith
  385. +---------------------------------------------------------------------*/
  386. bool
  387. NPT_String::EndsWith(const char *s, bool ignore_case) const
  388. {
  389. if (s == NULL) return false;
  390. NPT_Size str_length = NPT_StringLength(s);
  391. if (str_length > GetLength()) return false;
  392. return NPT_StringStartsWith(GetChars()+GetLength()-str_length, s, ignore_case) == 1;
  393. }
  394. /*----------------------------------------------------------------------
  395. | NPT_String::Find
  396. +---------------------------------------------------------------------*/
  397. int
  398. NPT_String::Find(const char* str, NPT_Ordinal start, bool ignore_case) const
  399. {
  400. // check args
  401. if (str == NULL || start >= GetLength()) return -1;
  402. // skip to start position
  403. const char* src = m_Chars + start;
  404. // look for a substring
  405. while (*src) {
  406. int cmp = NPT_StringStartsWith(src, str, ignore_case);
  407. switch (cmp) {
  408. case -1:
  409. // ref is too short, abort
  410. return -1;
  411. case 1:
  412. // match
  413. return (int)(src-m_Chars);
  414. }
  415. src++;
  416. }
  417. return -1;
  418. }
  419. /*----------------------------------------------------------------------
  420. | NPT_String::Find
  421. +---------------------------------------------------------------------*/
  422. int
  423. NPT_String::Find(char c, NPT_Ordinal start, bool ignore_case) const
  424. {
  425. // check args
  426. if (start >= GetLength()) return -1;
  427. // skip to start position
  428. const char* src = m_Chars + start;
  429. // look for the character
  430. if (ignore_case) {
  431. while (*src) {
  432. if (NPT_Uppercase(*src) == NPT_Uppercase(c)) {
  433. return (int)(src-m_Chars);
  434. }
  435. src++;
  436. }
  437. } else {
  438. while (*src) {
  439. if (*src == c) return (int)(src-m_Chars);
  440. src++;
  441. }
  442. }
  443. return -1;
  444. }
  445. /*----------------------------------------------------------------------
  446. | NPT_String::ReverseFind
  447. +---------------------------------------------------------------------*/
  448. int
  449. NPT_String::ReverseFind(const char* str, NPT_Ordinal start, bool ignore_case) const
  450. {
  451. // check args
  452. if (str == NULL || *str == '\0') return -1;
  453. // look for a substring
  454. NPT_Size my_length = GetLength();
  455. NPT_Size str_length = NPT_StringLength(str);
  456. int i=my_length-start-str_length;
  457. const char* src = GetChars();
  458. if (i<0) return -1;
  459. for (;i>=0; i--) {
  460. int cmp = NPT_StringStartsWith(src+i, str, ignore_case);
  461. if (cmp == 1) {
  462. // match
  463. return i;
  464. }
  465. }
  466. return -1;
  467. }
  468. /*----------------------------------------------------------------------
  469. | NPT_String::ReverseFind
  470. +---------------------------------------------------------------------*/
  471. int
  472. NPT_String::ReverseFind(char c, NPT_Ordinal start, bool ignore_case) const
  473. {
  474. // check args
  475. NPT_Size length = GetLength();
  476. int i = length-start-1;
  477. if (i < 0) return -1;
  478. // look for the character
  479. const char* src = GetChars();
  480. if (ignore_case) {
  481. for (;i>=0;i--) {
  482. if (NPT_Uppercase(src[i]) == NPT_Uppercase(c)) {
  483. return i;
  484. }
  485. }
  486. } else {
  487. for (;i>=0;i--) {
  488. if (src[i] == c) return i;
  489. }
  490. }
  491. return -1;
  492. }
  493. /*----------------------------------------------------------------------
  494. | NPT_String::MakeLowercase
  495. +---------------------------------------------------------------------*/
  496. void
  497. NPT_String::MakeLowercase()
  498. {
  499. // the source is the current buffer
  500. const char* src = GetChars();
  501. // convert all the characters of the existing buffer
  502. char* dst = const_cast<char*>(src);
  503. while (*dst != '\0') {
  504. *dst = NPT_Lowercase(*dst);
  505. dst++;
  506. }
  507. }
  508. /*----------------------------------------------------------------------
  509. | NPT_String::MakeUppercase
  510. +---------------------------------------------------------------------*/
  511. void
  512. NPT_String::MakeUppercase()
  513. {
  514. // the source is the current buffer
  515. const char* src = GetChars();
  516. // convert all the characters of the existing buffer
  517. char* dst = const_cast<char*>(src);
  518. while (*dst != '\0') {
  519. *dst = NPT_Uppercase(*dst);
  520. dst++;
  521. }
  522. }
  523. /*----------------------------------------------------------------------
  524. | NPT_String::ToLowercase
  525. +---------------------------------------------------------------------*/
  526. NPT_String
  527. NPT_String::ToLowercase() const
  528. {
  529. NPT_String result(*this);
  530. result.MakeLowercase();
  531. return result;
  532. }
  533. /*----------------------------------------------------------------------
  534. | NPT_String::ToUppercase
  535. +---------------------------------------------------------------------*/
  536. NPT_String
  537. NPT_String::ToUppercase() const
  538. {
  539. NPT_String result(*this);
  540. result.MakeUppercase();
  541. return result;
  542. }
  543. /*----------------------------------------------------------------------
  544. | NPT_String::Replace
  545. +---------------------------------------------------------------------*/
  546. void
  547. NPT_String::Replace(char a, char b)
  548. {
  549. // check args
  550. if (m_Chars == NULL || a == '\0' || b == '\0') return;
  551. // we are going to modify the characters
  552. char* src = m_Chars;
  553. // process the buffer in place
  554. while (*src) {
  555. if (*src == a) *src = b;
  556. src++;
  557. }
  558. }
  559. /*----------------------------------------------------------------------
  560. | NPT_String::Insert
  561. +---------------------------------------------------------------------*/
  562. void
  563. NPT_String::Insert(const char* str, NPT_Ordinal where)
  564. {
  565. // check args
  566. if (str == NULL || where > GetLength()) return;
  567. // measure the string to insert
  568. NPT_Size str_length = StringLength(str);
  569. if (str_length == 0) return;
  570. // compute the size of the new string
  571. NPT_Size old_length = GetLength();
  572. NPT_Size new_length = str_length + GetLength();
  573. // prepare to write the new string
  574. char* src = m_Chars;
  575. char* nst = Buffer::Create(new_length, new_length);
  576. char* dst = nst;
  577. // copy the beginning of the old string
  578. if (where > 0) {
  579. CopyBuffer(dst, src, where);
  580. src += where;
  581. dst += where;
  582. }
  583. // copy the inserted string
  584. CopyString(dst, str);
  585. dst += str_length;
  586. // copy the end of the old string
  587. if (old_length > where) {
  588. CopyString(dst, src);
  589. }
  590. // use the new string
  591. if (m_Chars) delete GetBuffer();
  592. m_Chars = nst;
  593. }
  594. /*----------------------------------------------------------------------
  595. | NPT_String::Erase
  596. +---------------------------------------------------------------------*/
  597. void
  598. NPT_String::Erase(NPT_Ordinal start, NPT_Cardinal count /* = 1 */)
  599. {
  600. // check bounds
  601. NPT_Size length = GetLength();
  602. if (start+count > length) {
  603. if (start >= length) return;
  604. count = length-start;
  605. }
  606. if (count == 0) return;
  607. CopyString(m_Chars+start, m_Chars+start+count);
  608. GetBuffer()->SetLength(length-count);
  609. }
  610. /*----------------------------------------------------------------------
  611. | NPT_String::ToInteger
  612. +---------------------------------------------------------------------*/
  613. NPT_Result
  614. NPT_String::ToInteger(unsigned long& value, bool relaxed) const
  615. {
  616. long tmp;
  617. NPT_Result res = ToInteger(tmp, relaxed);
  618. if (NPT_FAILED(res)) {
  619. return res;
  620. }
  621. if (tmp < 0) {
  622. return NPT_ERROR_INVALID_PARAMETERS;
  623. }
  624. value = (unsigned long)tmp;
  625. return NPT_SUCCESS;
  626. }
  627. /*----------------------------------------------------------------------
  628. | NPT_String::ToInteger
  629. +---------------------------------------------------------------------*/
  630. NPT_Result
  631. NPT_String::ToInteger(long& value, bool relaxed) const
  632. {
  633. return NPT_ParseInteger(GetChars(), value, relaxed);
  634. }
  635. /*----------------------------------------------------------------------
  636. | NPT_String::ToFloat
  637. +---------------------------------------------------------------------*/
  638. NPT_Result
  639. NPT_String::ToFloat(float& value, bool relaxed) const
  640. {
  641. return NPT_ParseFloat(GetChars(), value, relaxed);
  642. }
  643. /*----------------------------------------------------------------------
  644. | NPT_String::TrimLeft
  645. +---------------------------------------------------------------------*/
  646. void
  647. NPT_String::TrimLeft()
  648. {
  649. TrimLeft(NPT_STRINGS_WHITESPACE_CHARS);
  650. }
  651. /*----------------------------------------------------------------------
  652. | NPT_String::TrimLeft
  653. +---------------------------------------------------------------------*/
  654. void
  655. NPT_String::TrimLeft(char c)
  656. {
  657. char s[2] = {c, 0};
  658. TrimLeft((const char*)s);
  659. }
  660. /*----------------------------------------------------------------------
  661. | NPT_String::TrimLeft
  662. +---------------------------------------------------------------------*/
  663. void
  664. NPT_String::TrimLeft(const char* chars)
  665. {
  666. if (m_Chars == NULL) return;
  667. const char* s = m_Chars;
  668. while (char c = *s) {
  669. const char* x = chars;
  670. while (*x) {
  671. if (*x == c) break;
  672. x++;
  673. }
  674. if (*x == 0) break; // not found
  675. s++;
  676. }
  677. if (s == m_Chars) {
  678. // nothing was trimmed
  679. return;
  680. }
  681. // shift chars to the left
  682. char* d = m_Chars;
  683. GetBuffer()->SetLength(GetLength()-(s-d));
  684. while ((*d++ = *s++)) {};
  685. }
  686. /*----------------------------------------------------------------------
  687. | NPT_String::TrimRight
  688. +---------------------------------------------------------------------*/
  689. void
  690. NPT_String::TrimRight()
  691. {
  692. TrimRight(NPT_STRINGS_WHITESPACE_CHARS);
  693. }
  694. /*----------------------------------------------------------------------
  695. | NPT_String::TrimRight
  696. +---------------------------------------------------------------------*/
  697. void
  698. NPT_String::TrimRight(char c)
  699. {
  700. char s[2] = {c, 0};
  701. TrimRight((const char*)s);
  702. }
  703. /*----------------------------------------------------------------------
  704. | NPT_String::TrimRight
  705. +---------------------------------------------------------------------*/
  706. void
  707. NPT_String::TrimRight(const char* chars)
  708. {
  709. if (m_Chars == NULL || m_Chars[0] == '\0') return;
  710. char* tail = m_Chars+GetLength()-1;
  711. char* s = tail;
  712. while (s != m_Chars-1) {
  713. const char* x = chars;
  714. while (*x) {
  715. if (*x == *s) {
  716. *s = '\0';
  717. break;
  718. }
  719. x++;
  720. }
  721. if (*x == 0) break; // not found
  722. s--;
  723. }
  724. if (s == tail) {
  725. // nothing was trimmed
  726. return;
  727. }
  728. GetBuffer()->SetLength(1+(int)(s-m_Chars));
  729. }
  730. /*----------------------------------------------------------------------
  731. | NPT_String::Trim
  732. +---------------------------------------------------------------------*/
  733. void
  734. NPT_String::Trim()
  735. {
  736. TrimLeft();
  737. TrimRight();
  738. }
  739. /*----------------------------------------------------------------------
  740. | NPT_String::Trim
  741. +---------------------------------------------------------------------*/
  742. void
  743. NPT_String::Trim(char c)
  744. {
  745. char s[2] = {c, 0};
  746. TrimLeft((const char*)s);
  747. TrimRight((const char*)s);
  748. }
  749. /*----------------------------------------------------------------------
  750. | NPT_String::Trim
  751. +---------------------------------------------------------------------*/
  752. void
  753. NPT_String::Trim(const char* chars)
  754. {
  755. TrimLeft(chars);
  756. TrimRight(chars);
  757. }
  758. /*----------------------------------------------------------------------
  759. | NPT_String::operator+(const NPT_String&, const char*)
  760. +---------------------------------------------------------------------*/
  761. NPT_String
  762. operator+(const NPT_String& s1, const char* s2)
  763. {
  764. // shortcut
  765. if (s2 == NULL) return NPT_String(s1);
  766. // measure strings
  767. NPT_Size s1_length = s1.GetLength();
  768. NPT_Size s2_length = NPT_String::StringLength(s2);
  769. // allocate space for the new string
  770. NPT_String result;
  771. char* start = result.PrepareToWrite(s1_length+s2_length);
  772. // concatenate the two strings into the result
  773. NPT_String::CopyBuffer(start, s1, s1_length);
  774. NPT_String::CopyString(start+s1_length, s2);
  775. return result;
  776. }
  777. /*----------------------------------------------------------------------
  778. | NPT_String::operator+(const NPT_String& , const char*)
  779. +---------------------------------------------------------------------*/
  780. NPT_String
  781. operator+(const char* s1, const NPT_String& s2)
  782. {
  783. // shortcut
  784. if (s1 == NULL) return NPT_String(s2);
  785. // measure strings
  786. NPT_Size s1_length = NPT_String::StringLength(s1);
  787. NPT_Size s2_length = s2.GetLength();
  788. // allocate space for the new string
  789. NPT_String result;
  790. char* start = result.PrepareToWrite(s1_length+s2_length);
  791. // concatenate the two strings into the result
  792. NPT_String::CopyBuffer(start, s1, s1_length);
  793. NPT_String::CopyString(start+s1_length, s2.GetChars());
  794. return result;
  795. }
  796. /*----------------------------------------------------------------------
  797. | NPT_String::operator+(const NPT_String& , char)
  798. +---------------------------------------------------------------------*/
  799. NPT_String
  800. operator+(const NPT_String& s1, char c)
  801. {
  802. // allocate space for the new string
  803. NPT_String result;
  804. result.Reserve(s1.GetLength()+1);
  805. // append
  806. result = s1;
  807. result += c;
  808. return result;
  809. }