PageRenderTime 56ms CodeModel.GetById 6ms RepoModel.GetById 0ms app.codeStats 0ms

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

https://github.com/riviera/plex
C++ | 1056 lines | 658 code | 123 blank | 275 comment | 209 complexity | 6e0e731ba44f931c0f91d3a0f69cef85 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, GPL-3.0, Unlicense, AGPL-1.0
  1. /*****************************************************************
  2. |
  3. | Neptune - String Objects
  4. |
  5. | Copyright (c) 2002-2008, Axiomatic Systems, LLC.
  6. | All rights reserved.
  7. |
  8. | Redistribution and use in source and binary forms, with or without
  9. | modification, are permitted provided that the following conditions are met:
  10. | * Redistributions of source code must retain the above copyright
  11. | notice, this list of conditions and the following disclaimer.
  12. | * Redistributions in binary form must reproduce the above copyright
  13. | notice, this list of conditions and the following disclaimer in the
  14. | documentation and/or other materials provided with the distribution.
  15. | * Neither the name of Axiomatic Systems nor the
  16. | names of its contributors may be used to endorse or promote products
  17. | derived from this software without specific prior written permission.
  18. |
  19. | THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
  20. | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  21. | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  22. | DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
  23. | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  24. | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  25. | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  26. | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  27. | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  28. | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  29. |
  30. ****************************************************************/
  31. /*----------------------------------------------------------------------
  32. | includes
  33. +---------------------------------------------------------------------*/
  34. #include "NptConfig.h"
  35. #include "NptTypes.h"
  36. #include "NptConstants.h"
  37. #include "NptStrings.h"
  38. #include "NptResults.h"
  39. #include "NptUtils.h"
  40. #include "NptDebug.h"
  41. /*----------------------------------------------------------------------
  42. | constants
  43. +---------------------------------------------------------------------*/
  44. #define NPT_STRINGS_WHITESPACE_CHARS "\r\n\t "
  45. const unsigned int NPT_STRING_FORMAT_BUFFER_DEFAULT_SIZE = 256;
  46. const unsigned int NPT_STRING_FORMAT_BUFFER_MAX_SIZE = 0x80000; // 512k
  47. /*----------------------------------------------------------------------
  48. | helpers
  49. +---------------------------------------------------------------------*/
  50. inline char NPT_Uppercase(char x) {
  51. return (x >= 'a' && x <= 'z') ? x&0xdf : x;
  52. }
  53. inline char NPT_Lowercase(char x) {
  54. return (x >= 'A' && x <= 'Z') ? x^32 : x;
  55. }
  56. /*----------------------------------------------------------------------
  57. | NPT_String::EmptyString
  58. +---------------------------------------------------------------------*/
  59. char NPT_String::EmptyString = '\0';
  60. /*----------------------------------------------------------------------
  61. | NPT_String::FromInteger
  62. +---------------------------------------------------------------------*/
  63. NPT_String
  64. NPT_String::FromInteger(NPT_Int64 value)
  65. {
  66. char str[32];
  67. char* c = &str[31];
  68. *c-- = '\0';
  69. // handle the sign
  70. bool negative = false;
  71. if (value < 0) {
  72. negative = true;
  73. value = -value;
  74. }
  75. // process the digits
  76. do {
  77. int digit = (int)(value%10);
  78. *c-- = '0'+digit;
  79. value /= 10;
  80. } while(value);
  81. if (negative) {
  82. *c = '-';
  83. } else {
  84. ++c;
  85. }
  86. return NPT_String(c);
  87. }
  88. /*----------------------------------------------------------------------
  89. | NPT_String::FromIntegerU
  90. +---------------------------------------------------------------------*/
  91. NPT_String
  92. NPT_String::FromIntegerU(NPT_UInt64 value)
  93. {
  94. char str[32];
  95. char* c = &str[31];
  96. *c = '\0';
  97. // process the digits
  98. do {
  99. int digit = (int)(value%10);
  100. *--c = '0'+digit;
  101. value /= 10;
  102. } while(value);
  103. return NPT_String(c);
  104. }
  105. /*----------------------------------------------------------------------
  106. | NPT_String::Format
  107. +---------------------------------------------------------------------*/
  108. NPT_String
  109. NPT_String::Format(const char* format, ...)
  110. {
  111. NPT_String result;
  112. NPT_Size buffer_size = NPT_STRING_FORMAT_BUFFER_DEFAULT_SIZE; // default value
  113. va_list args;
  114. va_start(args, format);
  115. for(;;) {
  116. /* try to format (it might not fit) */
  117. result.Reserve(buffer_size);
  118. char* buffer = result.UseChars();
  119. int f_result = NPT_FormatStringVN(buffer, buffer_size, format, args);
  120. if (f_result >= (int)(buffer_size)) f_result = -1;
  121. if (f_result >= 0) {
  122. result.SetLength(f_result);
  123. break;
  124. }
  125. /* the buffer was too small, try something bigger */
  126. /* (we don't trust the return value of NPT_FormatStringVN */
  127. /* for the actual size needed) */
  128. buffer_size *= 2;
  129. if (buffer_size > NPT_STRING_FORMAT_BUFFER_MAX_SIZE) break;
  130. }
  131. va_end(args);
  132. return result;
  133. }
  134. /*----------------------------------------------------------------------
  135. | NPT_String::NPT_String
  136. +---------------------------------------------------------------------*/
  137. NPT_String::NPT_String(const char* str)
  138. {
  139. if (str == NULL) {
  140. m_Chars = NULL;
  141. } else {
  142. m_Chars = Buffer::Create(str);
  143. }
  144. }
  145. /*----------------------------------------------------------------------
  146. | NPT_String::NPT_String
  147. +---------------------------------------------------------------------*/
  148. NPT_String::NPT_String(const char* str, NPT_Size length)
  149. {
  150. if (str == NULL || length == 0) {
  151. m_Chars = NULL;
  152. } else {
  153. m_Chars = Buffer::Create(str, length);
  154. }
  155. }
  156. /*----------------------------------------------------------------------
  157. | NPT_String::NPT_String
  158. +---------------------------------------------------------------------*/
  159. NPT_String::NPT_String(const NPT_String& str)
  160. {
  161. if (str.GetLength() == 0) {
  162. m_Chars = NULL;
  163. } else {
  164. m_Chars = Buffer::Create(str.GetChars(), str.GetLength());
  165. }
  166. }
  167. /*----------------------------------------------------------------------
  168. | NPT_String::NPT_String
  169. +---------------------------------------------------------------------*/
  170. NPT_String::NPT_String(const char* str,
  171. NPT_Ordinal first,
  172. NPT_Size length)
  173. {
  174. // shortcut
  175. if (str != NULL && length != 0) {
  176. // truncate length
  177. NPT_Size str_length = StringLength(str);
  178. if (first < str_length) {
  179. if (first+length > str_length) {
  180. length = str_length-first;
  181. }
  182. if (length != 0) {
  183. m_Chars = Buffer::Create(str+first, length);
  184. return;
  185. }
  186. }
  187. }
  188. m_Chars = NULL;
  189. }
  190. /*----------------------------------------------------------------------
  191. | NPT_String::NPT_String
  192. +---------------------------------------------------------------------*/
  193. NPT_String::NPT_String(char c, NPT_Cardinal repeat)
  194. {
  195. if (repeat != 0) {
  196. m_Chars = Buffer::Create(c, repeat);
  197. } else {
  198. m_Chars = NULL;
  199. }
  200. }
  201. /*----------------------------------------------------------------------
  202. | NPT_String::SetLength
  203. +---------------------------------------------------------------------*/
  204. NPT_Result
  205. NPT_String::SetLength(NPT_Size length, bool pad)
  206. {
  207. // special case for 0
  208. if (length == 0) {
  209. Reset();
  210. return NPT_SUCCESS;
  211. }
  212. // reserve the space
  213. Reserve(length);
  214. // pad with spaces if necessary
  215. char* chars = UseChars();
  216. if (pad) {
  217. unsigned int current_length = GetLength();
  218. if (length > current_length) {
  219. unsigned int pad_length = length-current_length;
  220. NPT_SetMemory(chars+current_length, ' ', pad_length);
  221. }
  222. }
  223. // update the length and terminate the buffer
  224. GetBuffer()->SetLength(length);
  225. chars[length] = '\0';
  226. return NPT_SUCCESS;
  227. }
  228. /*----------------------------------------------------------------------
  229. | NPT_String::PrepareToWrite
  230. +---------------------------------------------------------------------*/
  231. inline char*
  232. NPT_String::PrepareToWrite(NPT_Size length)
  233. {
  234. NPT_ASSERT(length != 0);
  235. if (m_Chars == NULL || GetBuffer()->GetAllocated() < length) {
  236. // the buffer is too small, we need to allocate a new one.
  237. NPT_Size needed = length;
  238. if (m_Chars != NULL) {
  239. NPT_Size grow = GetBuffer()->GetAllocated()*2;
  240. if (grow > length) needed = grow;
  241. delete GetBuffer();
  242. }
  243. m_Chars = Buffer::Create(needed);
  244. }
  245. GetBuffer()->SetLength(length);
  246. return m_Chars;
  247. }
  248. /*----------------------------------------------------------------------
  249. | NPT_String::Reserve
  250. +---------------------------------------------------------------------*/
  251. void
  252. NPT_String::Reserve(NPT_Size allocate)
  253. {
  254. if (m_Chars == NULL || GetBuffer()->GetAllocated() < allocate) {
  255. // the buffer is too small, we need to allocate a new one.
  256. NPT_Size needed = allocate;
  257. if (m_Chars != NULL) {
  258. NPT_Size grow = GetBuffer()->GetAllocated()*2;
  259. if (grow > allocate) needed = grow;
  260. }
  261. NPT_Size length = GetLength();
  262. char* copy = Buffer::Create(needed, length);
  263. if (m_Chars != NULL) {
  264. CopyString(copy, m_Chars);
  265. delete GetBuffer();
  266. } else {
  267. copy[0] = '\0';
  268. }
  269. m_Chars = copy;
  270. }
  271. }
  272. /*----------------------------------------------------------------------
  273. | NPT_String::Assign
  274. +---------------------------------------------------------------------*/
  275. void
  276. NPT_String::Assign(const char* str, NPT_Size length)
  277. {
  278. if (str == NULL || length == 0) {
  279. Reset();
  280. } else {
  281. PrepareToWrite(length);
  282. CopyBuffer(m_Chars, str, length);
  283. m_Chars[length] = '\0';
  284. }
  285. }
  286. /*----------------------------------------------------------------------
  287. | NPT_String::operator=
  288. +---------------------------------------------------------------------*/
  289. NPT_String&
  290. NPT_String::operator=(const char* str)
  291. {
  292. if (str == NULL) {
  293. Reset();
  294. } else {
  295. NPT_Size length = StringLength(str);
  296. if (length == 0) {
  297. Reset();
  298. } else {
  299. CopyString(PrepareToWrite(length), str);
  300. }
  301. }
  302. return *this;
  303. }
  304. /*----------------------------------------------------------------------
  305. | NPT_String::operator=
  306. +---------------------------------------------------------------------*/
  307. NPT_String&
  308. NPT_String::operator=(const NPT_String& str)
  309. {
  310. // do nothing if we're assigning to ourselves
  311. if (this != &str) {
  312. Assign(str.GetChars(), str.GetLength());
  313. }
  314. return *this;
  315. }
  316. /*----------------------------------------------------------------------
  317. | NPT_String::Append
  318. +---------------------------------------------------------------------*/
  319. void
  320. NPT_String::Append(const char* str, NPT_Size length)
  321. {
  322. // shortcut
  323. if (str == NULL || length == 0) return;
  324. // compute the new length
  325. NPT_Size old_length = GetLength();
  326. NPT_Size new_length = old_length + length;
  327. // allocate enough space
  328. Reserve(new_length);
  329. // append the new string at the end of the current one
  330. CopyBuffer(m_Chars+old_length, str, length);
  331. m_Chars[new_length] = '\0';
  332. // update the length
  333. GetBuffer()->SetLength(new_length);
  334. }
  335. /*----------------------------------------------------------------------
  336. | NPT_String::Compare
  337. +---------------------------------------------------------------------*/
  338. int
  339. NPT_String::Compare(const char *s, bool ignore_case) const
  340. {
  341. return NPT_String::Compare(GetChars(), s, ignore_case);
  342. }
  343. /*----------------------------------------------------------------------
  344. | NPT_String::Compare
  345. +---------------------------------------------------------------------*/
  346. int
  347. NPT_String::Compare(const char *s1, const char *s2, bool ignore_case)
  348. {
  349. const char *r1 = s1;
  350. const char *r2 = s2;
  351. if (ignore_case) {
  352. while (NPT_Uppercase(*r1) == NPT_Uppercase(*r2)) {
  353. if (*r1++ == '\0') {
  354. return 0;
  355. }
  356. r2++;
  357. }
  358. return NPT_Uppercase(*r1) - NPT_Uppercase(*r2);
  359. } else {
  360. while (*r1 == *r2) {
  361. if (*r1++ == '\0') {
  362. return 0;
  363. }
  364. r2++;
  365. }
  366. return (*r1 - *r2);
  367. }
  368. }
  369. /*----------------------------------------------------------------------
  370. | NPT_String::CompareN
  371. +---------------------------------------------------------------------*/
  372. int
  373. NPT_String::CompareN(const char *s, NPT_Size count, bool ignore_case) const
  374. {
  375. return NPT_String::CompareN(GetChars(), s, count, ignore_case);
  376. }
  377. /*----------------------------------------------------------------------
  378. | NPT_String::CompareN
  379. +---------------------------------------------------------------------*/
  380. int
  381. NPT_String::CompareN(const char* s1, const char *s2, NPT_Size count, bool ignore_case)
  382. {
  383. const char* me = s1;
  384. if (ignore_case) {
  385. for (unsigned int i=0; i<count; i++) {
  386. if (NPT_Uppercase(me[i]) != NPT_Uppercase(s2[i])) {
  387. return NPT_Uppercase(me[i]) - NPT_Uppercase(s2[i]);
  388. }
  389. }
  390. return 0;
  391. } else {
  392. for (unsigned int i=0; i<count; i++) {
  393. if (me[i] != s2[i]) {
  394. return (me[i] - s2[i]);
  395. }
  396. }
  397. return 0;
  398. }
  399. }
  400. /*----------------------------------------------------------------------
  401. | NPT_String::Split
  402. +---------------------------------------------------------------------*/
  403. NPT_List<NPT_String>
  404. NPT_String::Split(const char* separator) const
  405. {
  406. NPT_List<NPT_String> result;
  407. NPT_Size separator_length = NPT_StringLength(separator);
  408. // sepcial case for empty separators
  409. if (separator_length == 0) {
  410. result.Add(*this);
  411. return result;
  412. }
  413. int current = 0;
  414. int next;
  415. do {
  416. next = Find(separator, current);
  417. unsigned int end = (next>=0?next:GetLength());
  418. result.Add(SubString(current, end-current));
  419. current = next+separator_length;
  420. } while (next >= 0);
  421. return result;
  422. }
  423. /*----------------------------------------------------------------------
  424. | NPT_String::SubString
  425. +---------------------------------------------------------------------*/
  426. NPT_String
  427. NPT_String::SubString(NPT_Ordinal first, NPT_Size length) const
  428. {
  429. if (first >= GetLength()) {
  430. first = GetLength();
  431. length = 0;
  432. } else if (first+length >= GetLength()) {
  433. length = GetLength()-first;
  434. }
  435. return NPT_String(GetChars()+first, length);
  436. }
  437. /*----------------------------------------------------------------------
  438. | NPT_StringStartsWith
  439. |
  440. | returns:
  441. | 1 if str starts with sub,
  442. | 0 if str is large enough but does not start with sub
  443. | -1 if str is too short to start with sub
  444. +---------------------------------------------------------------------*/
  445. static inline int
  446. NPT_StringStartsWith(const char* str, const char* sub, bool ignore_case)
  447. {
  448. if (ignore_case) {
  449. while (NPT_Uppercase(*str) == NPT_Uppercase(*sub)) {
  450. if (*str++ == '\0') {
  451. return 1;
  452. }
  453. sub++;
  454. }
  455. } else {
  456. while (*str == *sub) {
  457. if (*str++ == '\0') {
  458. return 1;
  459. }
  460. sub++;
  461. }
  462. }
  463. return (*sub == '\0') ? 1 : (*str == '\0' ? -1 : 0);
  464. }
  465. /*----------------------------------------------------------------------
  466. | NPT_String::StartsWith
  467. +---------------------------------------------------------------------*/
  468. bool
  469. NPT_String::StartsWith(const char *s, bool ignore_case) const
  470. {
  471. if (s == NULL) return false;
  472. return NPT_StringStartsWith(GetChars(), s, ignore_case) == 1;
  473. }
  474. /*----------------------------------------------------------------------
  475. | NPT_String::EndsWith
  476. +---------------------------------------------------------------------*/
  477. bool
  478. NPT_String::EndsWith(const char *s, bool ignore_case) const
  479. {
  480. if (s == NULL) return false;
  481. NPT_Size str_length = NPT_StringLength(s);
  482. if (str_length > GetLength()) return false;
  483. return NPT_StringStartsWith(GetChars()+GetLength()-str_length, s, ignore_case) == 1;
  484. }
  485. /*----------------------------------------------------------------------
  486. | NPT_String::Find
  487. +---------------------------------------------------------------------*/
  488. int
  489. NPT_String::Find(const char* str, NPT_Ordinal start, bool ignore_case) const
  490. {
  491. // check args
  492. if (str == NULL || start >= GetLength()) return -1;
  493. // skip to start position
  494. const char* src = m_Chars + start;
  495. // look for a substring
  496. while (*src) {
  497. int cmp = NPT_StringStartsWith(src, str, ignore_case);
  498. switch (cmp) {
  499. case -1:
  500. // ref is too short, abort
  501. return -1;
  502. case 1:
  503. // match
  504. return (int)(src-m_Chars);
  505. }
  506. src++;
  507. }
  508. return -1;
  509. }
  510. /*----------------------------------------------------------------------
  511. | NPT_String::Find
  512. +---------------------------------------------------------------------*/
  513. int
  514. NPT_String::Find(char c, NPT_Ordinal start, bool ignore_case) const
  515. {
  516. // check args
  517. if (start >= GetLength()) return -1;
  518. // skip to start position
  519. const char* src = m_Chars + start;
  520. // look for the character
  521. if (ignore_case) {
  522. while (*src) {
  523. if (NPT_Uppercase(*src) == NPT_Uppercase(c)) {
  524. return (int)(src-m_Chars);
  525. }
  526. src++;
  527. }
  528. } else {
  529. while (*src) {
  530. if (*src == c) return (int)(src-m_Chars);
  531. src++;
  532. }
  533. }
  534. return -1;
  535. }
  536. /*----------------------------------------------------------------------
  537. | NPT_String::ReverseFind
  538. +---------------------------------------------------------------------*/
  539. int
  540. NPT_String::ReverseFind(const char* str, NPT_Ordinal start, bool ignore_case) const
  541. {
  542. // check args
  543. if (str == NULL || *str == '\0') return -1;
  544. // look for a substring
  545. NPT_Size my_length = GetLength();
  546. NPT_Size str_length = NPT_StringLength(str);
  547. int i=my_length-start-str_length;
  548. const char* src = GetChars();
  549. if (i<0) return -1;
  550. for (;i>=0; i--) {
  551. int cmp = NPT_StringStartsWith(src+i, str, ignore_case);
  552. if (cmp == 1) {
  553. // match
  554. return i;
  555. }
  556. }
  557. return -1;
  558. }
  559. /*----------------------------------------------------------------------
  560. | NPT_String::ReverseFind
  561. +---------------------------------------------------------------------*/
  562. int
  563. NPT_String::ReverseFind(char c, NPT_Ordinal start, bool ignore_case) const
  564. {
  565. // check args
  566. NPT_Size length = GetLength();
  567. int i = length-start-1;
  568. if (i < 0) return -1;
  569. // look for the character
  570. const char* src = GetChars();
  571. if (ignore_case) {
  572. for (;i>=0;i--) {
  573. if (NPT_Uppercase(src[i]) == NPT_Uppercase(c)) {
  574. return i;
  575. }
  576. }
  577. } else {
  578. for (;i>=0;i--) {
  579. if (src[i] == c) return i;
  580. }
  581. }
  582. return -1;
  583. }
  584. /*----------------------------------------------------------------------
  585. | NPT_String::MakeLowercase
  586. +---------------------------------------------------------------------*/
  587. void
  588. NPT_String::MakeLowercase()
  589. {
  590. // the source is the current buffer
  591. const char* src = GetChars();
  592. // convert all the characters of the existing buffer
  593. char* dst = const_cast<char*>(src);
  594. while (*dst != '\0') {
  595. *dst = NPT_Lowercase(*dst);
  596. dst++;
  597. }
  598. }
  599. /*----------------------------------------------------------------------
  600. | NPT_String::MakeUppercase
  601. +---------------------------------------------------------------------*/
  602. void
  603. NPT_String::MakeUppercase()
  604. {
  605. // the source is the current buffer
  606. const char* src = GetChars();
  607. // convert all the characters of the existing buffer
  608. char* dst = const_cast<char*>(src);
  609. while (*dst != '\0') {
  610. *dst = NPT_Uppercase(*dst);
  611. dst++;
  612. }
  613. }
  614. /*----------------------------------------------------------------------
  615. | NPT_String::ToLowercase
  616. +---------------------------------------------------------------------*/
  617. NPT_String
  618. NPT_String::ToLowercase() const
  619. {
  620. NPT_String result(*this);
  621. result.MakeLowercase();
  622. return result;
  623. }
  624. /*----------------------------------------------------------------------
  625. | NPT_String::ToUppercase
  626. +---------------------------------------------------------------------*/
  627. NPT_String
  628. NPT_String::ToUppercase() const
  629. {
  630. NPT_String result(*this);
  631. result.MakeUppercase();
  632. return result;
  633. }
  634. /*----------------------------------------------------------------------
  635. | NPT_String::Replace
  636. +---------------------------------------------------------------------*/
  637. void
  638. NPT_String::Replace(char a, char b)
  639. {
  640. // check args
  641. if (m_Chars == NULL || a == '\0' || b == '\0') return;
  642. // we are going to modify the characters
  643. char* src = m_Chars;
  644. // process the buffer in place
  645. while (*src) {
  646. if (*src == a) *src = b;
  647. src++;
  648. }
  649. }
  650. /*----------------------------------------------------------------------
  651. | NPT_String::Replace
  652. +---------------------------------------------------------------------*/
  653. void
  654. NPT_String::Replace(char a, const char* str)
  655. {
  656. // check args
  657. if (m_Chars == NULL || a == '\0' || str == NULL || str[0] == '\0') return;
  658. // optimization
  659. if (NPT_StringLength(str) == 1) return Replace(a, str[0]);
  660. // we are going to create a new string
  661. NPT_String dst;
  662. char* src = m_Chars;
  663. // reserve at least as much as input
  664. dst.Reserve(GetLength());
  665. // process the buffer
  666. while (*src) {
  667. if (*src == a) {
  668. dst += str;
  669. } else {
  670. dst += *src;
  671. }
  672. src++;
  673. }
  674. Assign(dst.GetChars(), dst.GetLength());
  675. }
  676. /*----------------------------------------------------------------------
  677. | NPT_String::Insert
  678. +---------------------------------------------------------------------*/
  679. void
  680. NPT_String::Insert(const char* str, NPT_Ordinal where)
  681. {
  682. // check args
  683. if (str == NULL || where > GetLength()) return;
  684. // measure the string to insert
  685. NPT_Size str_length = StringLength(str);
  686. if (str_length == 0) return;
  687. // compute the size of the new string
  688. NPT_Size old_length = GetLength();
  689. NPT_Size new_length = str_length + GetLength();
  690. // prepare to write the new string
  691. char* src = m_Chars;
  692. char* nst = Buffer::Create(new_length, new_length);
  693. char* dst = nst;
  694. // copy the beginning of the old string
  695. if (where > 0) {
  696. CopyBuffer(dst, src, where);
  697. src += where;
  698. dst += where;
  699. }
  700. // copy the inserted string
  701. CopyString(dst, str);
  702. dst += str_length;
  703. // copy the end of the old string
  704. if (old_length > where) {
  705. CopyString(dst, src);
  706. }
  707. // use the new string
  708. if (m_Chars) delete GetBuffer();
  709. m_Chars = nst;
  710. }
  711. /*----------------------------------------------------------------------
  712. | NPT_String::Erase
  713. +---------------------------------------------------------------------*/
  714. void
  715. NPT_String::Erase(NPT_Ordinal start, NPT_Cardinal count /* = 1 */)
  716. {
  717. // check bounds
  718. NPT_Size length = GetLength();
  719. if (start+count > length) {
  720. if (start >= length) return;
  721. count = length-start;
  722. }
  723. if (count == 0) return;
  724. CopyString(m_Chars+start, m_Chars+start+count);
  725. GetBuffer()->SetLength(length-count);
  726. }
  727. /*----------------------------------------------------------------------
  728. | NPT_String::ToInteger
  729. +---------------------------------------------------------------------*/
  730. NPT_Result
  731. NPT_String::ToInteger(NPT_Int32& value, bool relaxed) const
  732. {
  733. return NPT_ParseInteger32(GetChars(), value, relaxed);
  734. }
  735. /*----------------------------------------------------------------------
  736. | NPT_String::ToInteger
  737. +---------------------------------------------------------------------*/
  738. NPT_Result
  739. NPT_String::ToInteger(NPT_UInt32& value, bool relaxed) const
  740. {
  741. return NPT_ParseInteger32U(GetChars(), value, relaxed);
  742. }
  743. /*----------------------------------------------------------------------
  744. | NPT_String::ToInteger
  745. +---------------------------------------------------------------------*/
  746. NPT_Result
  747. NPT_String::ToInteger(NPT_Int64& value, bool relaxed) const
  748. {
  749. return NPT_ParseInteger64(GetChars(), value, relaxed);
  750. }
  751. /*----------------------------------------------------------------------
  752. | NPT_String::ToInteger
  753. +---------------------------------------------------------------------*/
  754. NPT_Result
  755. NPT_String::ToInteger(NPT_UInt64& value, bool relaxed) const
  756. {
  757. return NPT_ParseInteger64U(GetChars(), value, relaxed);
  758. }
  759. /*----------------------------------------------------------------------
  760. | NPT_String::ToFloat
  761. +---------------------------------------------------------------------*/
  762. NPT_Result
  763. NPT_String::ToFloat(float& value, bool relaxed) const
  764. {
  765. return NPT_ParseFloat(GetChars(), value, relaxed);
  766. }
  767. /*----------------------------------------------------------------------
  768. | NPT_String::TrimLeft
  769. +---------------------------------------------------------------------*/
  770. void
  771. NPT_String::TrimLeft()
  772. {
  773. TrimLeft(NPT_STRINGS_WHITESPACE_CHARS);
  774. }
  775. /*----------------------------------------------------------------------
  776. | NPT_String::TrimLeft
  777. +---------------------------------------------------------------------*/
  778. void
  779. NPT_String::TrimLeft(char c)
  780. {
  781. char s[2] = {c, 0};
  782. TrimLeft((const char*)s);
  783. }
  784. /*----------------------------------------------------------------------
  785. | NPT_String::TrimLeft
  786. +---------------------------------------------------------------------*/
  787. void
  788. NPT_String::TrimLeft(const char* chars)
  789. {
  790. if (m_Chars == NULL) return;
  791. const char* s = m_Chars;
  792. while (char c = *s) {
  793. const char* x = chars;
  794. while (*x) {
  795. if (*x == c) break;
  796. x++;
  797. }
  798. if (*x == 0) break; // not found
  799. s++;
  800. }
  801. if (s == m_Chars) {
  802. // nothing was trimmed
  803. return;
  804. }
  805. // shift chars to the left
  806. char* d = m_Chars;
  807. GetBuffer()->SetLength(GetLength()-(s-d));
  808. while ((*d++ = *s++)) {};
  809. }
  810. /*----------------------------------------------------------------------
  811. | NPT_String::TrimRight
  812. +---------------------------------------------------------------------*/
  813. void
  814. NPT_String::TrimRight()
  815. {
  816. TrimRight(NPT_STRINGS_WHITESPACE_CHARS);
  817. }
  818. /*----------------------------------------------------------------------
  819. | NPT_String::TrimRight
  820. +---------------------------------------------------------------------*/
  821. void
  822. NPT_String::TrimRight(char c)
  823. {
  824. char s[2] = {c, 0};
  825. TrimRight((const char*)s);
  826. }
  827. /*----------------------------------------------------------------------
  828. | NPT_String::TrimRight
  829. +---------------------------------------------------------------------*/
  830. void
  831. NPT_String::TrimRight(const char* chars)
  832. {
  833. if (m_Chars == NULL || m_Chars[0] == '\0') return;
  834. char* tail = m_Chars+GetLength()-1;
  835. char* s = tail;
  836. while (s != m_Chars-1) {
  837. const char* x = chars;
  838. while (*x) {
  839. if (*x == *s) {
  840. *s = '\0';
  841. break;
  842. }
  843. x++;
  844. }
  845. if (*x == 0) break; // not found
  846. s--;
  847. }
  848. if (s == tail) {
  849. // nothing was trimmed
  850. return;
  851. }
  852. GetBuffer()->SetLength(1+(int)(s-m_Chars));
  853. }
  854. /*----------------------------------------------------------------------
  855. | NPT_String::Trim
  856. +---------------------------------------------------------------------*/
  857. void
  858. NPT_String::Trim()
  859. {
  860. TrimLeft();
  861. TrimRight();
  862. }
  863. /*----------------------------------------------------------------------
  864. | NPT_String::Trim
  865. +---------------------------------------------------------------------*/
  866. void
  867. NPT_String::Trim(char c)
  868. {
  869. char s[2] = {c, 0};
  870. TrimLeft((const char*)s);
  871. TrimRight((const char*)s);
  872. }
  873. /*----------------------------------------------------------------------
  874. | NPT_String::Trim
  875. +---------------------------------------------------------------------*/
  876. void
  877. NPT_String::Trim(const char* chars)
  878. {
  879. TrimLeft(chars);
  880. TrimRight(chars);
  881. }
  882. /*----------------------------------------------------------------------
  883. | NPT_String::operator+(const NPT_String&, const char*)
  884. +---------------------------------------------------------------------*/
  885. NPT_String
  886. operator+(const NPT_String& s1, const char* s2)
  887. {
  888. // shortcut
  889. if (s2 == NULL) return NPT_String(s1);
  890. // measure strings
  891. NPT_Size s1_length = s1.GetLength();
  892. NPT_Size s2_length = NPT_String::StringLength(s2);
  893. // allocate space for the new string
  894. NPT_String result;
  895. char* start = result.PrepareToWrite(s1_length+s2_length);
  896. // concatenate the two strings into the result
  897. NPT_String::CopyBuffer(start, s1, s1_length);
  898. NPT_String::CopyString(start+s1_length, s2);
  899. return result;
  900. }
  901. /*----------------------------------------------------------------------
  902. | NPT_String::operator+(const NPT_String& , const char*)
  903. +---------------------------------------------------------------------*/
  904. NPT_String
  905. operator+(const char* s1, const NPT_String& s2)
  906. {
  907. // shortcut
  908. if (s1 == NULL) return NPT_String(s2);
  909. // measure strings
  910. NPT_Size s1_length = NPT_String::StringLength(s1);
  911. NPT_Size s2_length = s2.GetLength();
  912. // allocate space for the new string
  913. NPT_String result;
  914. char* start = result.PrepareToWrite(s1_length+s2_length);
  915. // concatenate the two strings into the result
  916. NPT_String::CopyBuffer(start, s1, s1_length);
  917. NPT_String::CopyString(start+s1_length, s2.GetChars());
  918. return result;
  919. }
  920. /*----------------------------------------------------------------------
  921. | NPT_String::operator+(const NPT_String& , char)
  922. +---------------------------------------------------------------------*/
  923. NPT_String
  924. operator+(const NPT_String& s1, char c)
  925. {
  926. // allocate space for the new string
  927. NPT_String result;
  928. result.Reserve(s1.GetLength()+1);
  929. // append
  930. result = s1;
  931. result += c;
  932. return result;
  933. }