PageRenderTime 50ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/bstrwrap.cpp

https://bitbucket.org/aqk/bstring
C++ | 1721 lines | 1420 code | 246 blank | 55 comment | 435 complexity | b1ac1ae24e1ebe25126ff8d142d584e9 MD5 | raw file
Possible License(s): GPL-2.0
  1. /*
  2. * This source file is part of the bstring string library. This code was
  3. * written by Paul Hsieh in 2002-2010, and is covered by either the 3-clause
  4. * BSD open source license or GPL v2.0. Refer to the accompanying documentation
  5. * for details on usage and license.
  6. */
  7. /*
  8. * bstrwrap.c
  9. *
  10. * This file is the C++ wrapper for the bstring functions.
  11. */
  12. #if defined (_MSC_VER)
  13. # define _CRT_SECURE_NO_WARNINGS
  14. #endif
  15. #include <stdio.h>
  16. #include <string.h>
  17. #include <stdlib.h>
  18. #include <stdarg.h>
  19. #include <limits.h>
  20. #include "bstrwrap.h"
  21. #if defined(MEMORY_DEBUG) || defined(BSTRLIB_MEMORY_DEBUG)
  22. #include "memdbg.h"
  23. #endif
  24. #ifndef bstr__alloc
  25. #define bstr__alloc(x) malloc (x)
  26. #endif
  27. #ifndef bstr__free
  28. #define bstr__free(p) free (p)
  29. #endif
  30. #ifndef bstr__realloc
  31. #define bstr__realloc(p,x) realloc ((p), (x))
  32. #endif
  33. #ifndef bstr__memcpy
  34. #define bstr__memcpy(d,s,l) memcpy ((d), (s), (l))
  35. #endif
  36. #ifndef bstr__memmove
  37. #define bstr__memmove(d,s,l) memmove ((d), (s), (l))
  38. #endif
  39. #ifndef bstr__memset
  40. #define bstr__memset(d,c,l) memset ((d), (c), (l))
  41. #endif
  42. #ifndef bstr__memcmp
  43. #define bstr__memcmp(d,c,l) memcmp ((d), (c), (l))
  44. #endif
  45. #ifndef bstr__memchr
  46. #define bstr__memchr(s,c,l) memchr ((s), (c), (l))
  47. #endif
  48. #if defined(BSTRLIB_CAN_USE_IOSTREAM)
  49. #include <iostream>
  50. #endif
  51. namespace Bstrlib {
  52. // Constructors.
  53. CBString::CBString () {
  54. slen = 0;
  55. mlen = 8;
  56. data = (unsigned char *) bstr__alloc (mlen);
  57. if (!data) {
  58. mlen = 0;
  59. bstringThrow ("Failure in default constructor");
  60. } else {
  61. data[0] = '\0';
  62. }
  63. }
  64. CBString::CBString (const void * blk, int len) {
  65. data = NULL;
  66. if (len >= 0) {
  67. mlen = len + 1;
  68. slen = len;
  69. data = (unsigned char *) bstr__alloc (mlen);
  70. }
  71. if (!data) {
  72. mlen = slen = 0;
  73. bstringThrow ("Failure in block constructor");
  74. } else {
  75. if (slen > 0) bstr__memcpy (data, blk, slen);
  76. data[slen] = '\0';
  77. }
  78. }
  79. CBString::CBString (char c, int len) {
  80. data = NULL;
  81. if (len >= 0) {
  82. mlen = len + 1;
  83. slen = len;
  84. data = (unsigned char *) bstr__alloc (mlen);
  85. }
  86. if (!data) {
  87. mlen = slen = 0;
  88. bstringThrow ("Failure in repeat(char) constructor");
  89. } else {
  90. if (slen > 0) bstr__memset (data, c, slen);
  91. data[slen] = '\0';
  92. }
  93. }
  94. CBString::CBString (char c) {
  95. mlen = 2;
  96. slen = 1;
  97. if (NULL == (data = (unsigned char *) bstr__alloc (mlen))) {
  98. mlen = slen = 0;
  99. bstringThrow ("Failure in (char) constructor");
  100. } else {
  101. data[0] = (unsigned char) c;
  102. data[1] = '\0';
  103. }
  104. }
  105. CBString::CBString (unsigned char c) {
  106. mlen = 2;
  107. slen = 1;
  108. if (NULL == (data = (unsigned char *) bstr__alloc (mlen))) {
  109. mlen = slen = 0;
  110. bstringThrow ("Failure in (char) constructor");
  111. } else {
  112. data[0] = c;
  113. data[1] = '\0';
  114. }
  115. }
  116. CBString::CBString (const char *s) {
  117. if (s) {
  118. size_t sslen = strlen (s);
  119. if (sslen >= INT_MAX) bstringThrow ("Failure in (char *) constructor, string too large")
  120. slen = (int) sslen;
  121. mlen = slen + 1;
  122. if (NULL != (data = (unsigned char *) bstr__alloc (mlen))) {
  123. bstr__memcpy (data, s, mlen);
  124. return;
  125. }
  126. }
  127. data = NULL;
  128. bstringThrow ("Failure in (char *) constructor");
  129. }
  130. CBString::CBString (int len, const char *s) {
  131. if (s) {
  132. size_t sslen = strlen (s);
  133. if (sslen >= INT_MAX) bstringThrow ("Failure in (char *) constructor, string too large")
  134. slen = (int) sslen;
  135. mlen = slen + 1;
  136. if (mlen < len) mlen = len;
  137. if (NULL != (data = (unsigned char *) bstr__alloc (mlen))) {
  138. bstr__memcpy (data, s, slen + 1);
  139. return;
  140. }
  141. }
  142. data = NULL;
  143. bstringThrow ("Failure in (int len, char *) constructor");
  144. }
  145. CBString::CBString (const CBString& b) {
  146. slen = b.slen;
  147. mlen = slen + 1;
  148. data = NULL;
  149. if (mlen > 0) data = (unsigned char *) bstr__alloc (mlen);
  150. if (!data) {
  151. bstringThrow ("Failure in (CBString) constructor");
  152. } else {
  153. bstr__memcpy (data, b.data, slen);
  154. data[slen] = '\0';
  155. }
  156. }
  157. CBString::CBString (const tagbstring& x) {
  158. slen = x.slen;
  159. mlen = slen + 1;
  160. data = NULL;
  161. if (slen >= 0 && x.data != NULL) data = (unsigned char *) bstr__alloc (mlen);
  162. if (!data) {
  163. bstringThrow ("Failure in (tagbstring) constructor");
  164. } else {
  165. bstr__memcpy (data, x.data, slen);
  166. data[slen] = '\0';
  167. }
  168. }
  169. // Destructor.
  170. CBString::~CBString () {
  171. if (data != NULL) {
  172. bstr__free (data);
  173. data = NULL;
  174. }
  175. mlen = 0;
  176. slen = -__LINE__;
  177. }
  178. // = operator.
  179. const CBString& CBString::operator = (char c) {
  180. if (mlen <= 0) bstringThrow ("Write protection error");
  181. if (2 >= mlen) alloc (2);
  182. if (!data) {
  183. mlen = slen = 0;
  184. bstringThrow ("Failure in =(char) operator");
  185. } else {
  186. slen = 1;
  187. data[0] = (unsigned char) c;
  188. data[1] = '\0';
  189. }
  190. return *this;
  191. }
  192. const CBString& CBString::operator = (unsigned char c) {
  193. if (mlen <= 0) bstringThrow ("Write protection error");
  194. if (2 >= mlen) alloc (2);
  195. if (!data) {
  196. mlen = slen = 0;
  197. bstringThrow ("Failure in =(char) operator");
  198. } else {
  199. slen = 1;
  200. data[0] = c;
  201. data[1] = '\0';
  202. }
  203. return *this;
  204. }
  205. const CBString& CBString::operator = (const char *s) {
  206. size_t tmpSlen;
  207. if (mlen <= 0) bstringThrow ("Write protection error");
  208. if (NULL == s) s = "";
  209. if ((tmpSlen = strlen (s)) >= (size_t) mlen) {
  210. if (tmpSlen >= INT_MAX-1) bstringThrow ("Failure in =(const char *) operator, string too large");
  211. alloc ((int) tmpSlen);
  212. }
  213. if (data) {
  214. slen = (int) tmpSlen;
  215. bstr__memcpy (data, s, tmpSlen + 1);
  216. } else {
  217. mlen = slen = 0;
  218. bstringThrow ("Failure in =(const char *) operator");
  219. }
  220. return *this;
  221. }
  222. const CBString& CBString::operator = (const CBString& b) {
  223. if (mlen <= 0) bstringThrow ("Write protection error");
  224. if (b.slen >= mlen) alloc (b.slen);
  225. slen = b.slen;
  226. if (!data) {
  227. mlen = slen = 0;
  228. bstringThrow ("Failure in =(CBString) operator");
  229. } else {
  230. bstr__memcpy (data, b.data, slen);
  231. data[slen] = '\0';
  232. }
  233. return *this;
  234. }
  235. const CBString& CBString::operator = (const tagbstring& x) {
  236. if (mlen <= 0) bstringThrow ("Write protection error");
  237. if (x.slen < 0) bstringThrow ("Failure in =(tagbstring) operator, badly formed tagbstring");
  238. if (x.slen >= mlen) alloc (x.slen);
  239. slen = x.slen;
  240. if (!data) {
  241. mlen = slen = 0;
  242. bstringThrow ("Failure in =(tagbstring) operator");
  243. } else {
  244. bstr__memcpy (data, x.data, slen);
  245. data[slen] = '\0';
  246. }
  247. return *this;
  248. }
  249. const CBString& CBString::operator += (const CBString& b) {
  250. if (BSTR_ERR == bconcat (this, (bstring) &b)) {
  251. bstringThrow ("Failure in concatenate");
  252. }
  253. return *this;
  254. }
  255. const CBString& CBString::operator += (const char *s) {
  256. char * d;
  257. int i, l;
  258. if (mlen <= 0) bstringThrow ("Write protection error");
  259. /* Optimistically concatenate directly */
  260. l = mlen - slen;
  261. d = (char *) &data[slen];
  262. for (i=0; i < l; i++) {
  263. if ((*d++ = *s++) == '\0') {
  264. slen += i;
  265. return *this;
  266. }
  267. }
  268. slen += i;
  269. if (BSTR_ERR == bcatcstr (this, s)) {
  270. bstringThrow ("Failure in concatenate");
  271. }
  272. return *this;
  273. }
  274. const CBString& CBString::operator += (char c) {
  275. if (BSTR_ERR == bconchar (this, c)) {
  276. bstringThrow ("Failure in concatenate");
  277. }
  278. return *this;
  279. }
  280. const CBString& CBString::operator += (unsigned char c) {
  281. if (BSTR_ERR == bconchar (this, (char) c)) {
  282. bstringThrow ("Failure in concatenate");
  283. }
  284. return *this;
  285. }
  286. const CBString& CBString::operator += (const tagbstring& x) {
  287. if (mlen <= 0) bstringThrow ("Write protection error");
  288. if (x.slen < 0) bstringThrow ("Failure in +=(tagbstring) operator, badly formed tagbstring");
  289. alloc (x.slen + slen + 1);
  290. if (!data) {
  291. mlen = slen = 0;
  292. bstringThrow ("Failure in +=(tagbstring) operator");
  293. } else {
  294. bstr__memcpy (data + slen, x.data, x.slen);
  295. slen += x.slen;
  296. data[slen] = '\0';
  297. }
  298. return *this;
  299. }
  300. const CBString CBString::operator + (char c) const {
  301. CBString retval (*this);
  302. retval += c;
  303. return retval;
  304. }
  305. const CBString CBString::operator + (unsigned char c) const {
  306. CBString retval (*this);
  307. retval += c;
  308. return retval;
  309. }
  310. const CBString CBString::operator + (const CBString& b) const {
  311. CBString retval (*this);
  312. retval += b;
  313. return retval;
  314. }
  315. const CBString CBString::operator + (const char *s) const {
  316. if (s == NULL) bstringThrow ("Failure in + (char *) operator, NULL");
  317. CBString retval (*this);
  318. retval += s;
  319. return retval;
  320. }
  321. const CBString CBString::operator + (const unsigned char *s) const {
  322. if (s == NULL) bstringThrow ("Failure in + (unsigned char *) operator, NULL");
  323. CBString retval (*this);
  324. retval += (const char *) s;
  325. return retval;
  326. }
  327. const CBString CBString::operator + (const tagbstring& x) const {
  328. if (x.slen < 0) bstringThrow ("Failure in + (tagbstring) operator, badly formed tagbstring");
  329. CBString retval (*this);
  330. retval += x;
  331. return retval;
  332. }
  333. bool CBString::operator == (const CBString& b) const {
  334. int retval;
  335. if (BSTR_ERR == (retval = biseq ((bstring)this, (bstring)&b))) {
  336. bstringThrow ("Failure in compare (==)");
  337. }
  338. return retval > 0;
  339. }
  340. bool CBString::operator == (const char * s) const {
  341. int retval;
  342. if (NULL == s) {
  343. bstringThrow ("Failure in compare (== NULL)");
  344. }
  345. if (BSTR_ERR == (retval = biseqcstr ((bstring) this, s))) {
  346. bstringThrow ("Failure in compare (==)");
  347. }
  348. return retval > 0;
  349. }
  350. bool CBString::operator == (const unsigned char * s) const {
  351. int retval;
  352. if (NULL == s) {
  353. bstringThrow ("Failure in compare (== NULL)");
  354. }
  355. if (BSTR_ERR == (retval = biseqcstr ((bstring) this, (const char *) s))) {
  356. bstringThrow ("Failure in compare (==)");
  357. }
  358. return retval > 0;
  359. }
  360. bool CBString::operator != (const CBString& b) const {
  361. return ! ((*this) == b);
  362. }
  363. bool CBString::operator != (const char * s) const {
  364. return ! ((*this) == s);
  365. }
  366. bool CBString::operator != (const unsigned char * s) const {
  367. return ! ((*this) == s);
  368. }
  369. bool CBString::operator < (const CBString& b) const {
  370. int retval;
  371. if (SHRT_MIN == (retval = bstrcmp ((bstring) this, (bstring)&b))) {
  372. bstringThrow ("Failure in compare (<)");
  373. }
  374. return retval < 0;
  375. }
  376. bool CBString::operator < (const char * s) const {
  377. if (s == NULL) {
  378. bstringThrow ("Failure in compare (<)");
  379. }
  380. return strcmp ((const char *)this->data, s) < 0;
  381. }
  382. bool CBString::operator < (const unsigned char * s) const {
  383. if (s == NULL) {
  384. bstringThrow ("Failure in compare (<)");
  385. }
  386. return strcmp ((const char *)this->data, (const char *)s) < 0;
  387. }
  388. bool CBString::operator <= (const CBString& b) const {
  389. int retval;
  390. if (SHRT_MIN == (retval = bstrcmp ((bstring) this, (bstring)&b))) {
  391. bstringThrow ("Failure in compare (<=)");
  392. }
  393. return retval <= 0;
  394. }
  395. bool CBString::operator <= (const char * s) const {
  396. if (s == NULL) {
  397. bstringThrow ("Failure in compare (<=)");
  398. }
  399. return strcmp ((const char *)this->data, s) <= 0;
  400. }
  401. bool CBString::operator <= (const unsigned char * s) const {
  402. if (s == NULL) {
  403. bstringThrow ("Failure in compare (<=)");
  404. }
  405. return strcmp ((const char *)this->data, (const char *)s) <= 0;
  406. }
  407. bool CBString::operator > (const CBString& b) const {
  408. return ! ((*this) <= b);
  409. }
  410. bool CBString::operator > (const char * s) const {
  411. return ! ((*this) <= s);
  412. }
  413. bool CBString::operator > (const unsigned char * s) const {
  414. return ! ((*this) <= s);
  415. }
  416. bool CBString::operator >= (const CBString& b) const {
  417. return ! ((*this) < b);
  418. }
  419. bool CBString::operator >= (const char * s) const {
  420. return ! ((*this) < s);
  421. }
  422. bool CBString::operator >= (const unsigned char * s) const {
  423. return ! ((*this) < s);
  424. }
  425. CBString::operator double () const {
  426. double d = 0;
  427. if (1 != sscanf ((const char *)this->data, "%lf", &d)) {
  428. bstringThrow ("Unable to convert to a double");
  429. }
  430. return d;
  431. }
  432. CBString::operator float () const {
  433. float d = 0;
  434. if (1 != sscanf ((const char *)this->data, "%f", &d)) {
  435. bstringThrow ("Unable to convert to a float");
  436. }
  437. return d;
  438. }
  439. CBString::operator int () const {
  440. int d = 0;
  441. if (1 != sscanf ((const char *)this->data, "%d", &d)) {
  442. bstringThrow ("Unable to convert to an int");
  443. }
  444. return d;
  445. }
  446. CBString::operator unsigned int () const {
  447. unsigned int d = 0;
  448. if (1 != sscanf ((const char *)this->data, "%u", &d)) {
  449. bstringThrow ("Unable to convert to an unsigned int");
  450. }
  451. return d;
  452. }
  453. #ifdef __TURBOC__
  454. # ifndef BSTRLIB_NOVSNP
  455. # define BSTRLIB_NOVSNP
  456. # endif
  457. #endif
  458. /* Give WATCOM C/C++, MSVC some latitude for their non-support of vsnprintf */
  459. #if defined(__WATCOMC__) || defined(_MSC_VER)
  460. #define exvsnprintf(r,b,n,f,a) {r = _vsnprintf (b,n,f,a);}
  461. #else
  462. #ifdef BSTRLIB_NOVSNP
  463. /* This is just a hack. If you are using a system without a vsnprintf, it is
  464. not recommended that bformat be used at all. */
  465. #define exvsnprintf(r,b,n,f,a) {vsprintf (b,f,a); r = -1;}
  466. #define START_VSNBUFF (256)
  467. #else
  468. #if defined (__GNUC__) && !defined (__PPC__)
  469. /* Something is making gcc complain about this prototype not being here, so
  470. I've just gone ahead and put it in. */
  471. extern "C" {
  472. extern int vsnprintf (char *buf, size_t count, const char *format, va_list arg);
  473. }
  474. #endif
  475. #define exvsnprintf(r,b,n,f,a) {r = vsnprintf (b,n,f,a);}
  476. #endif
  477. #endif
  478. #ifndef START_VSNBUFF
  479. #define START_VSNBUFF (16)
  480. #endif
  481. /*
  482. * Yeah I'd like to just call a vformat function or something, but because of
  483. * the ANSI specified brokeness of the va_* macros, it is actually not
  484. * possible to do this correctly.
  485. */
  486. void CBString::format (const char * fmt, ...) {
  487. bstring b;
  488. va_list arglist;
  489. int r, n;
  490. if (mlen <= 0) bstringThrow ("Write protection error");
  491. if (fmt == NULL) {
  492. *this = "<NULL>";
  493. bstringThrow ("CBString::format (NULL, ...) is erroneous.");
  494. } else {
  495. if ((b = bfromcstr ("")) == NULL) {
  496. #ifdef BSTRLIB_THROWS_EXCEPTIONS
  497. bstringThrow ("CBString::format out of memory.");
  498. #else
  499. *this = "<NULL>";
  500. #endif
  501. } else {
  502. if ((n = (int) (2 * (strlen) (fmt))) < START_VSNBUFF) n = START_VSNBUFF;
  503. for (;;) {
  504. if (BSTR_OK != balloc (b, n + 2)) {
  505. #ifdef BSTRLIB_THROWS_EXCEPTIONS
  506. bstringThrow ("CBString::format out of memory.");
  507. #else
  508. b = bformat ("<NULL>");
  509. break;
  510. #endif
  511. }
  512. va_start (arglist, fmt);
  513. exvsnprintf (r, (char *) b->data, n + 1, fmt, arglist);
  514. va_end (arglist);
  515. b->data[n] = '\0';
  516. b->slen = (int) (strlen) ((char *) b->data);
  517. if (b->slen < n) break;
  518. if (r > n) n = r; else n += n;
  519. }
  520. *this = *b;
  521. bdestroy (b);
  522. }
  523. }
  524. }
  525. void CBString::formata (const char * fmt, ...) {
  526. bstring b;
  527. va_list arglist;
  528. int r, n;
  529. if (mlen <= 0) bstringThrow ("Write protection error");
  530. if (fmt == NULL) {
  531. *this += "<NULL>";
  532. bstringThrow ("CBString::formata (NULL, ...) is erroneous.");
  533. } else {
  534. if ((b = bfromcstr ("")) == NULL) {
  535. #ifdef BSTRLIB_THROWS_EXCEPTIONS
  536. bstringThrow ("CBString::format out of memory.");
  537. #else
  538. *this += "<NULL>";
  539. #endif
  540. } else {
  541. if ((n = (int) (2 * (strlen) (fmt))) < START_VSNBUFF) n = START_VSNBUFF;
  542. for (;;) {
  543. if (BSTR_OK != balloc (b, n + 2)) {
  544. #ifdef BSTRLIB_THROWS_EXCEPTIONS
  545. bstringThrow ("CBString::format out of memory.");
  546. #else
  547. b = bformat ("<NULL>");
  548. break;
  549. #endif
  550. }
  551. va_start (arglist, fmt);
  552. exvsnprintf (r, (char *) b->data, n + 1, fmt, arglist);
  553. va_end (arglist);
  554. b->data[n] = '\0';
  555. b->slen = (int) (strlen) ((char *) b->data);
  556. if (b->slen < n) break;
  557. if (r > n) n = r; else n += n;
  558. }
  559. *this += *b;
  560. bdestroy (b);
  561. }
  562. }
  563. }
  564. int CBString::caselessEqual (const CBString& b) const {
  565. int ret;
  566. if (BSTR_ERR == (ret = biseqcaseless ((bstring) this, (bstring) &b))) {
  567. bstringThrow ("CBString::caselessEqual Unable to compare");
  568. }
  569. return ret;
  570. }
  571. int CBString::caselessCmp (const CBString& b) const {
  572. int ret;
  573. if (SHRT_MIN == (ret = bstricmp ((bstring) this, (bstring) &b))) {
  574. bstringThrow ("CBString::caselessCmp Unable to compare");
  575. }
  576. return ret;
  577. }
  578. int CBString::find (const CBString& b, int pos) const {
  579. return binstr ((bstring) this, pos, (bstring) &b);
  580. }
  581. /*
  582. int CBString::find (const char * b, int pos) const;
  583. Uses and unrolling and sliding paired indexes character matching. Since
  584. the unrolling is the primary real world impact the true purpose of this
  585. algorithm choice is maximize the effectiveness of the unrolling. The
  586. idea is to scan until at least one match of the current indexed character
  587. from each string, and then shift indexes of both down by and repeat until
  588. the last character form b matches. When the last character from b
  589. matches if the were no mismatches in previous strlen(b) characters then
  590. we know we have a full match, otherwise shift both indexes back strlen(b)
  591. characters and continue.
  592. In general, if there is any character in b that is not at all in this
  593. CBString, then this algorithm is O(slen). The algorithm does not easily
  594. degenerate into O(slen * strlen(b)) performance except in very uncommon
  595. situations. Thus from a real world perspective, the overhead of
  596. precomputing suffix shifts in the Boyer-Moore algorithm is avoided, while
  597. delivering an unrolled matching inner loop most of the time.
  598. */
  599. int CBString::find (const char * b, int pos) const {
  600. int ii, j;
  601. unsigned char c0;
  602. register int i, l;
  603. register unsigned char cx;
  604. register unsigned char * pdata;
  605. if (NULL == b) {
  606. #ifdef BSTRLIB_THROWS_EXCEPTIONS
  607. bstringThrow ("CBString::find NULL.");
  608. #else
  609. return BSTR_ERR;
  610. #endif
  611. }
  612. if ((unsigned int) pos > (unsigned int) slen) return BSTR_ERR;
  613. if ('\0' == b[0]) return pos;
  614. if (pos == slen) return BSTR_ERR;
  615. if ('\0' == b[1]) return find (b[0], pos);
  616. cx = c0 = (unsigned char) b[0];
  617. l = slen - 1;
  618. pdata = data;
  619. for (ii = -1, i = pos, j = 0; i < l;) {
  620. /* Unrolled current character test */
  621. if (cx != pdata[i]) {
  622. if (cx != pdata[1+i]) {
  623. i += 2;
  624. continue;
  625. }
  626. i++;
  627. }
  628. /* Take note if this is the start of a potential match */
  629. if (0 == j) ii = i;
  630. /* Shift the test character down by one */
  631. j++;
  632. i++;
  633. /* If this isn't past the last character continue */
  634. if ('\0' != (cx = b[j])) continue;
  635. N0:;
  636. /* If no characters mismatched, then we matched */
  637. if (i == ii+j) return ii;
  638. /* Shift back to the beginning */
  639. i -= j;
  640. j = 0;
  641. cx = c0;
  642. }
  643. /* Deal with last case if unrolling caused a misalignment */
  644. if (i == l && cx == pdata[i] && '\0' == b[j+1]) goto N0;
  645. return BSTR_ERR;
  646. }
  647. int CBString::caselessfind (const CBString& b, int pos) const {
  648. return binstrcaseless ((bstring) this, pos, (bstring) &b);
  649. }
  650. int CBString::caselessfind (const char * b, int pos) const {
  651. struct tagbstring t;
  652. if (NULL == b) {
  653. #ifdef BSTRLIB_THROWS_EXCEPTIONS
  654. bstringThrow ("CBString::caselessfind NULL.");
  655. #else
  656. return BSTR_ERR;
  657. #endif
  658. }
  659. if ((unsigned int) pos > (unsigned int) slen) return BSTR_ERR;
  660. if ('\0' == b[0]) return pos;
  661. if (pos == slen) return BSTR_ERR;
  662. btfromcstr (t, b);
  663. return binstrcaseless ((bstring) this, pos, (bstring) &t);
  664. }
  665. int CBString::find (char c, int pos) const {
  666. if (pos < 0) return BSTR_ERR;
  667. for (;pos < slen; pos++) {
  668. if (data[pos] == (unsigned char) c) return pos;
  669. }
  670. return BSTR_ERR;
  671. }
  672. int CBString::reversefind (const CBString& b, int pos) const {
  673. return binstrr ((bstring) this, pos, (bstring) &b);
  674. }
  675. int CBString::reversefind (const char * b, int pos) const {
  676. struct tagbstring t;
  677. if (NULL == b) {
  678. #ifdef BSTRLIB_THROWS_EXCEPTIONS
  679. bstringThrow ("CBString::reversefind NULL.");
  680. #else
  681. return BSTR_ERR;
  682. #endif
  683. }
  684. cstr2tbstr (t, b);
  685. return binstrr ((bstring) this, pos, &t);
  686. }
  687. int CBString::caselessreversefind (const CBString& b, int pos) const {
  688. return binstrrcaseless ((bstring) this, pos, (bstring) &b);
  689. }
  690. int CBString::caselessreversefind (const char * b, int pos) const {
  691. struct tagbstring t;
  692. if (NULL == b) {
  693. #ifdef BSTRLIB_THROWS_EXCEPTIONS
  694. bstringThrow ("CBString::caselessreversefind NULL.");
  695. #else
  696. return BSTR_ERR;
  697. #endif
  698. }
  699. if ((unsigned int) pos > (unsigned int) slen) return BSTR_ERR;
  700. if ('\0' == b[0]) return pos;
  701. if (pos == slen) return BSTR_ERR;
  702. btfromcstr (t, b);
  703. return binstrrcaseless ((bstring) this, pos, (bstring) &t);
  704. }
  705. int CBString::reversefind (char c, int pos) const {
  706. if (pos > slen) return BSTR_ERR;
  707. if (pos == slen) pos--;
  708. for (;pos >= 0; pos--) {
  709. if (data[pos] == (unsigned char) c) return pos;
  710. }
  711. return BSTR_ERR;
  712. }
  713. int CBString::findchr (const CBString& b, int pos) const {
  714. return binchr ((bstring) this, pos, (bstring) &b);
  715. }
  716. int CBString::findchr (const char * s, int pos) const {
  717. struct tagbstring t;
  718. if (NULL == s) {
  719. #ifdef BSTRLIB_THROWS_EXCEPTIONS
  720. bstringThrow ("CBString::findchr NULL.");
  721. #else
  722. return BSTR_ERR;
  723. #endif
  724. }
  725. cstr2tbstr (t, s);
  726. return binchr ((bstring) this, pos, (bstring) &t);
  727. }
  728. int CBString::nfindchr (const CBString& b, int pos) const {
  729. return bninchr ((bstring) this, pos, (bstring) &b);
  730. }
  731. int CBString::nfindchr (const char * s, int pos) const {
  732. struct tagbstring t;
  733. if (NULL == s) {
  734. #ifdef BSTRLIB_THROWS_EXCEPTIONS
  735. bstringThrow ("CBString::nfindchr NULL.");
  736. #else
  737. return BSTR_ERR;
  738. #endif
  739. }
  740. cstr2tbstr (t, s);
  741. return bninchr ((bstring) this, pos, &t);
  742. }
  743. int CBString::reversefindchr (const CBString& b, int pos) const {
  744. return binchrr ((bstring) this, pos, (bstring) &b);
  745. }
  746. int CBString::reversefindchr (const char * s, int pos) const {
  747. struct tagbstring t;
  748. if (NULL == s) {
  749. #ifdef BSTRLIB_THROWS_EXCEPTIONS
  750. bstringThrow ("CBString::reversefindchr NULL.");
  751. #else
  752. return BSTR_ERR;
  753. #endif
  754. }
  755. cstr2tbstr (t, s);
  756. return binchrr ((bstring) this, pos, &t);
  757. }
  758. int CBString::nreversefindchr (const CBString& b, int pos) const {
  759. return bninchrr ((bstring) this, pos, (bstring) &b);
  760. }
  761. int CBString::nreversefindchr (const char * s, int pos) const {
  762. struct tagbstring t;
  763. if (NULL == s) {
  764. #ifdef BSTRLIB_THROWS_EXCEPTIONS
  765. bstringThrow ("CBString::nreversefindchr NULL.");
  766. #else
  767. return BSTR_ERR;
  768. #endif
  769. }
  770. cstr2tbstr (t, s);
  771. return bninchrr ((bstring) this, pos, &t);
  772. }
  773. const CBString CBString::midstr (int left, int len) const {
  774. struct tagbstring t;
  775. if (left < 0) {
  776. len += left;
  777. left = 0;
  778. }
  779. if (len > slen - left) len = slen - left;
  780. if (len <= 0) return CBString ("");
  781. blk2tbstr (t, data + left, len);
  782. return CBString (t);
  783. }
  784. void CBString::alloc (int len) {
  785. if (BSTR_ERR == balloc ((bstring)this, len)) {
  786. bstringThrow ("Failure in alloc");
  787. }
  788. }
  789. void CBString::fill (int len, unsigned char cfill) {
  790. slen = 0;
  791. if (BSTR_ERR == bsetstr (this, len, NULL, cfill)) {
  792. bstringThrow ("Failure in fill");
  793. }
  794. }
  795. void CBString::setsubstr (int pos, const CBString& b, unsigned char cfill) {
  796. if (BSTR_ERR == bsetstr (this, pos, (bstring) &b, cfill)) {
  797. bstringThrow ("Failure in setsubstr");
  798. }
  799. }
  800. void CBString::setsubstr (int pos, const char * s, unsigned char cfill) {
  801. struct tagbstring t;
  802. if (NULL == s) {
  803. #ifdef BSTRLIB_THROWS_EXCEPTIONS
  804. bstringThrow ("setsubstr NULL.");
  805. #else
  806. return;
  807. #endif
  808. }
  809. cstr2tbstr (t, s);
  810. if (BSTR_ERR == bsetstr (this, pos, &t, cfill)) {
  811. bstringThrow ("Failure in setsubstr");
  812. }
  813. }
  814. void CBString::insert (int pos, const CBString& b, unsigned char cfill) {
  815. if (BSTR_ERR == binsert (this, pos, (bstring) &b, cfill)) {
  816. bstringThrow ("Failure in insert");
  817. }
  818. }
  819. void CBString::insert (int pos, const char * s, unsigned char cfill) {
  820. struct tagbstring t;
  821. if (NULL == s) {
  822. #ifdef BSTRLIB_THROWS_EXCEPTIONS
  823. bstringThrow ("insert NULL.");
  824. #else
  825. return;
  826. #endif
  827. }
  828. cstr2tbstr (t, s);
  829. if (BSTR_ERR == binsert (this, pos, &t, cfill)) {
  830. bstringThrow ("Failure in insert");
  831. }
  832. }
  833. void CBString::insertchrs (int pos, int len, unsigned char cfill) {
  834. if (BSTR_ERR == binsertch (this, pos, len, cfill)) {
  835. bstringThrow ("Failure in insertchrs");
  836. }
  837. }
  838. void CBString::replace (int pos, int len, const CBString& b, unsigned char cfill) {
  839. if (BSTR_ERR == breplace (this, pos, len, (bstring) &b, cfill)) {
  840. bstringThrow ("Failure in replace");
  841. }
  842. }
  843. void CBString::replace (int pos, int len, const char * s, unsigned char cfill) {
  844. struct tagbstring t;
  845. size_t q;
  846. if (mlen <= 0) bstringThrow ("Write protection error");
  847. if (NULL == s || (pos|len) < 0) {
  848. bstringThrow ("Failure in replace");
  849. } else {
  850. if (pos + len >= slen) {
  851. cstr2tbstr (t, s);
  852. if (BSTR_ERR == bsetstr (this, pos, &t, cfill)) {
  853. bstringThrow ("Failure in replace");
  854. } else if (pos + t.slen < slen) {
  855. slen = pos + t.slen;
  856. data[slen] = '\0';
  857. }
  858. } else {
  859. /* Aliasing case */
  860. if ((unsigned int) (data - (unsigned char *) s) < (unsigned int) slen) {
  861. replace (pos, len, CBString(s), cfill);
  862. return;
  863. }
  864. if ((q = strlen (s)) > (size_t) len || len < 0) {
  865. if (slen + q - len >= INT_MAX) bstringThrow ("Failure in replace, result too long.");
  866. alloc ((int) (slen + q - len));
  867. if (NULL == data) return;
  868. }
  869. if ((int) q != len) bstr__memmove (data + pos + q, data + pos + len, slen - (pos + len));
  870. bstr__memcpy (data + pos, s, q);
  871. slen += ((int) q) - len;
  872. data[slen] = '\0';
  873. }
  874. }
  875. }
  876. void CBString::findreplace (const CBString& sfind, const CBString& repl, int pos) {
  877. if (BSTR_ERR == bfindreplace (this, (bstring) &sfind, (bstring) &repl, pos)) {
  878. bstringThrow ("Failure in findreplace");
  879. }
  880. }
  881. void CBString::findreplace (const CBString& sfind, const char * repl, int pos) {
  882. struct tagbstring t;
  883. if (NULL == repl) {
  884. #ifdef BSTRLIB_THROWS_EXCEPTIONS
  885. bstringThrow ("findreplace NULL.");
  886. #else
  887. return;
  888. #endif
  889. }
  890. cstr2tbstr (t, repl);
  891. if (BSTR_ERR == bfindreplace (this, (bstring) &sfind, (bstring) &t, pos)) {
  892. bstringThrow ("Failure in findreplace");
  893. }
  894. }
  895. void CBString::findreplace (const char * sfind, const CBString& repl, int pos) {
  896. struct tagbstring t;
  897. if (NULL == sfind) {
  898. #ifdef BSTRLIB_THROWS_EXCEPTIONS
  899. bstringThrow ("findreplace NULL.");
  900. #else
  901. return;
  902. #endif
  903. }
  904. cstr2tbstr (t, sfind);
  905. if (BSTR_ERR == bfindreplace (this, (bstring) &t, (bstring) &repl, pos)) {
  906. bstringThrow ("Failure in findreplace");
  907. }
  908. }
  909. void CBString::findreplace (const char * sfind, const char * repl, int pos) {
  910. struct tagbstring t, u;
  911. if (NULL == repl || NULL == sfind) {
  912. #ifdef BSTRLIB_THROWS_EXCEPTIONS
  913. bstringThrow ("findreplace NULL.");
  914. #else
  915. return;
  916. #endif
  917. }
  918. cstr2tbstr (t, sfind);
  919. cstr2tbstr (u, repl);
  920. if (BSTR_ERR == bfindreplace (this, (bstring) &t, (bstring) &u, pos)) {
  921. bstringThrow ("Failure in findreplace");
  922. }
  923. }
  924. void CBString::findreplacecaseless (const CBString& sfind, const CBString& repl, int pos) {
  925. if (BSTR_ERR == bfindreplacecaseless (this, (bstring) &sfind, (bstring) &repl, pos)) {
  926. bstringThrow ("Failure in findreplacecaseless");
  927. }
  928. }
  929. void CBString::findreplacecaseless (const CBString& sfind, const char * repl, int pos) {
  930. struct tagbstring t;
  931. if (NULL == repl) {
  932. #ifdef BSTRLIB_THROWS_EXCEPTIONS
  933. bstringThrow ("findreplacecaseless NULL.");
  934. #else
  935. return;
  936. #endif
  937. }
  938. cstr2tbstr (t, repl);
  939. if (BSTR_ERR == bfindreplacecaseless (this, (bstring) &sfind, (bstring) &t, pos)) {
  940. bstringThrow ("Failure in findreplacecaseless");
  941. }
  942. }
  943. void CBString::findreplacecaseless (const char * sfind, const CBString& repl, int pos) {
  944. struct tagbstring t;
  945. if (NULL == sfind) {
  946. #ifdef BSTRLIB_THROWS_EXCEPTIONS
  947. bstringThrow ("findreplacecaseless NULL.");
  948. #else
  949. return;
  950. #endif
  951. }
  952. cstr2tbstr (t, sfind);
  953. if (BSTR_ERR == bfindreplacecaseless (this, (bstring) &t, (bstring) &repl, pos)) {
  954. bstringThrow ("Failure in findreplacecaseless");
  955. }
  956. }
  957. void CBString::findreplacecaseless (const char * sfind, const char * repl, int pos) {
  958. struct tagbstring t, u;
  959. if (NULL == repl || NULL == sfind) {
  960. #ifdef BSTRLIB_THROWS_EXCEPTIONS
  961. bstringThrow ("findreplacecaseless NULL.");
  962. #else
  963. return;
  964. #endif
  965. }
  966. cstr2tbstr (t, sfind);
  967. cstr2tbstr (u, repl);
  968. if (BSTR_ERR == bfindreplacecaseless (this, (bstring) &t, (bstring) &u, pos)) {
  969. bstringThrow ("Failure in findreplacecaseless");
  970. }
  971. }
  972. void CBString::remove (int pos, int len) {
  973. if (BSTR_ERR == bdelete (this, pos, len)) {
  974. bstringThrow ("Failure in remove");
  975. }
  976. }
  977. void CBString::trunc (int len) {
  978. if (len < 0) {
  979. bstringThrow ("Failure in trunc");
  980. }
  981. if (len < slen) {
  982. slen = len;
  983. data[len] = '\0';
  984. }
  985. }
  986. void CBString::ltrim (const CBString& b) {
  987. int l = nfindchr (b, 0);
  988. if (l == BSTR_ERR) l = slen;
  989. remove (0, l);
  990. }
  991. void CBString::rtrim (const CBString& b) {
  992. int l = nreversefindchr (b, slen - 1);
  993. #if BSTR_ERR != -1
  994. if (l == BSTR_ERR) l = -1;
  995. #endif
  996. slen = l + 1;
  997. if (mlen > slen) data[slen] = '\0';
  998. }
  999. void CBString::toupper () {
  1000. if (BSTR_ERR == btoupper ((bstring) this)) {
  1001. bstringThrow ("Failure in toupper");
  1002. }
  1003. }
  1004. void CBString::tolower () {
  1005. if (BSTR_ERR == btolower ((bstring) this)) {
  1006. bstringThrow ("Failure in tolower");
  1007. }
  1008. }
  1009. void CBString::repeat (int count) {
  1010. count *= slen;
  1011. if (count == 0) {
  1012. trunc (0);
  1013. return;
  1014. }
  1015. if (count < 0 || BSTR_ERR == bpattern (this, count)) {
  1016. bstringThrow ("Failure in repeat");
  1017. }
  1018. }
  1019. int CBString::gets (bNgetc getcPtr, void * parm, char terminator) {
  1020. if (mlen <= 0) bstringThrow ("Write protection error");
  1021. bstring b = bgets (getcPtr, parm, terminator);
  1022. if (b == NULL) {
  1023. slen = 0;
  1024. return -1;
  1025. }
  1026. *this = *b;
  1027. bdestroy (b);
  1028. return 0;
  1029. }
  1030. int CBString::read (bNread readPtr, void * parm) {
  1031. if (mlen <= 0) bstringThrow ("Write protection error");
  1032. bstring b = bread (readPtr, parm);
  1033. if (b == NULL) {
  1034. slen = 0;
  1035. return -1;
  1036. }
  1037. *this = *b;
  1038. bdestroy (b);
  1039. return 0;
  1040. }
  1041. const CBString operator + (const char *a, const CBString& b) {
  1042. return CBString(a) + b;
  1043. }
  1044. const CBString operator + (const unsigned char *a, const CBString& b) {
  1045. return CBString((const char *)a) + b;
  1046. }
  1047. const CBString operator + (char c, const CBString& b) {
  1048. return CBString(c) + b;
  1049. }
  1050. const CBString operator + (unsigned char c, const CBString& b) {
  1051. return CBString(c) + b;
  1052. }
  1053. const CBString operator + (const tagbstring& x, const CBString& b) {
  1054. return CBString(x) + b;
  1055. }
  1056. void CBString::writeprotect () {
  1057. if (mlen >= 0) mlen = -1;
  1058. }
  1059. void CBString::writeallow () {
  1060. if (mlen == -1) mlen = slen + (slen == 0);
  1061. else if (mlen < 0) {
  1062. bstringThrow ("Cannot unprotect a constant");
  1063. }
  1064. }
  1065. #if defined(BSTRLIB_CAN_USE_STL)
  1066. // Constructors.
  1067. CBString::CBString (const CBStringList& l) {
  1068. int c;
  1069. size_t i;
  1070. for (c=1, i=0; i < l.size(); i++) {
  1071. c += l.at(i).slen;
  1072. }
  1073. mlen = c;
  1074. slen = 0;
  1075. data = (unsigned char *) bstr__alloc (c);
  1076. if (!data) {
  1077. mlen = slen = 0;
  1078. bstringThrow ("Failure in (CBStringList) constructor");
  1079. } else {
  1080. for (i=0; i < l.size(); i++) {
  1081. *this += l.at(i);
  1082. }
  1083. }
  1084. }
  1085. CBString::CBString (const struct CBStringList& l, const CBString& sep) {
  1086. int c, sl = sep.length ();
  1087. size_t i;
  1088. for (c=1, i=0; i < l.size(); i++) {
  1089. c += l.at(i).slen + sl;
  1090. }
  1091. mlen = c;
  1092. slen = 0;
  1093. data = (unsigned char *) bstr__alloc (mlen);
  1094. if (!data) {
  1095. mlen = slen = 0;
  1096. bstringThrow ("Failure in (CBStringList) constructor");
  1097. } else {
  1098. for (i=0; i < l.size(); i++) {
  1099. if (i > 0) *this += sep;
  1100. *this += l.at(i);
  1101. }
  1102. }
  1103. }
  1104. CBString::CBString (const struct CBStringList& l, char sep) {
  1105. int c;
  1106. size_t i;
  1107. for (c=1, i=0; i < l.size(); i++) {
  1108. c += l.at(i).slen + 1;
  1109. }
  1110. mlen = c;
  1111. slen = 0;
  1112. data = (unsigned char *) bstr__alloc (mlen);
  1113. if (!data) {
  1114. mlen = slen = 0;
  1115. bstringThrow ("Failure in (CBStringList) constructor");
  1116. } else {
  1117. for (i=0; i < l.size(); i++) {
  1118. if (i > 0) *this += sep;
  1119. *this += l.at(i);
  1120. }
  1121. }
  1122. }
  1123. CBString::CBString (const struct CBStringList& l, unsigned char sep) {
  1124. int c;
  1125. size_t i;
  1126. for (c=1, i=0; i < l.size(); i++) {
  1127. c += l.at(i).slen + 1;
  1128. }
  1129. mlen = c;
  1130. slen = 0;
  1131. data = (unsigned char *) bstr__alloc (mlen);
  1132. if (!data) {
  1133. mlen = slen = 0;
  1134. bstringThrow ("Failure in (CBStringList) constructor");
  1135. } else {
  1136. for (i=0; i < l.size(); i++) {
  1137. if (i > 0) *this += sep;
  1138. *this += l.at(i);
  1139. }
  1140. }
  1141. }
  1142. void CBString::join (const struct CBStringList& l) {
  1143. int c;
  1144. size_t i;
  1145. if (mlen <= 0) {
  1146. bstringThrow ("Write protection error");
  1147. }
  1148. for (c=1, i=0; i < l.size(); i++) {
  1149. c += l.at(i).slen;
  1150. if (c < 0) bstringThrow ("Failure in (CBStringList) constructor, too long");
  1151. }
  1152. alloc (c);
  1153. slen = 0;
  1154. if (!data) {
  1155. mlen = slen = 0;
  1156. bstringThrow ("Failure in (CBStringList) constructor");
  1157. } else {
  1158. for (i=0; i < l.size(); i++) {
  1159. *this += l.at(i);
  1160. }
  1161. }
  1162. }
  1163. void CBString::join (const struct CBStringList& l, const CBString& sep) {
  1164. int c, sl = sep.length();
  1165. size_t i;
  1166. if (mlen <= 0) {
  1167. bstringThrow ("Write protection error");
  1168. }
  1169. for (c=1, i=0; i < l.size(); i++) {
  1170. c += l.at(i).slen + sl;
  1171. if (c < sl) bstringThrow ("Failure in (CBStringList) constructor, too long");
  1172. }
  1173. alloc (c);
  1174. slen = 0;
  1175. if (!data) {
  1176. mlen = slen = 0;
  1177. bstringThrow ("Failure in (CBStringList) constructor");
  1178. } else {
  1179. for (i=0; i < l.size(); i++) {
  1180. if (i > 0) *this += sep;
  1181. *this += l.at(i);
  1182. }
  1183. }
  1184. }
  1185. void CBString::join (const struct CBStringList& l, char sep) {
  1186. int c;
  1187. size_t i;
  1188. if (mlen <= 0) {
  1189. bstringThrow ("Write protection error");
  1190. }
  1191. for (c=1, i=0; i < l.size(); i++) {
  1192. c += l.at(i).slen + 1;
  1193. if (c <= 0) bstringThrow ("Failure in (CBStringList) constructor, too long");
  1194. }
  1195. alloc (c);
  1196. slen = 0;
  1197. if (!data) {
  1198. mlen = slen = 0;
  1199. bstringThrow ("Failure in (CBStringList) constructor");
  1200. } else {
  1201. for (i=0; i < l.size(); i++) {
  1202. if (i > 0) *this += sep;
  1203. *this += l.at(i);
  1204. }
  1205. }
  1206. }
  1207. void CBString::join (const struct CBStringList& l, unsigned char sep) {
  1208. int c;
  1209. size_t i;
  1210. if (mlen <= 0) {
  1211. bstringThrow ("Write protection error");
  1212. }
  1213. for (c=1, i=0; i < l.size(); i++) {
  1214. c += l.at(i).slen + 1;
  1215. if (c <= 0) bstringThrow ("Failure in (CBStringList) constructor, too long");
  1216. }
  1217. alloc (c);
  1218. slen = 0;
  1219. if (!data) {
  1220. mlen = slen = 0;
  1221. bstringThrow ("Failure in (CBStringList) constructor");
  1222. } else {
  1223. for (i=0; i < l.size(); i++) {
  1224. if (i > 0) *this += sep;
  1225. *this += l.at(i);
  1226. }
  1227. }
  1228. }
  1229. // Split functions.
  1230. void CBStringList::split (const CBString& b, unsigned char splitChar) {
  1231. int p, i;
  1232. p = 0;
  1233. do {
  1234. for (i = p; i < b.length (); i++) {
  1235. if (b.character (i) == splitChar) break;
  1236. }
  1237. if (i >= p) this->push_back (CBString (&(b.data[p]), i - p));
  1238. p = i + 1;
  1239. } while (p <= b.length ());
  1240. }
  1241. void CBStringList::split (const CBString& b, const CBString& s) {
  1242. struct { unsigned long content[(1 << CHAR_BIT) / 32]; } chrs;
  1243. unsigned char c;
  1244. int p, i;
  1245. if (s.length() == 0) bstringThrow ("Null splitstring failure");
  1246. if (s.length() == 1) {
  1247. this->split (b, s.character (0));
  1248. } else {
  1249. for (i=0; i < ((1 << CHAR_BIT) / 32); i++) chrs.content[i] = 0x0;
  1250. for (i=0; i < s.length(); i++) {
  1251. c = s.character (i);
  1252. chrs.content[c >> 5] |= ((long)1) << (c & 31);
  1253. }
  1254. p = 0;
  1255. do {
  1256. for (i = p; i < b.length (); i++) {
  1257. c = b.character (i);
  1258. if (chrs.content[c >> 5] & ((long)1) << (c & 31)) break;
  1259. }
  1260. if (i >= p) this->push_back (CBString (&(b.data[p]), i - p));
  1261. p = i + 1;
  1262. } while (p <= b.length ());
  1263. }
  1264. }
  1265. void CBStringList::splitstr (const CBString& b, const CBString& s) {
  1266. int p, i;
  1267. if (s.length() == 1) {
  1268. this->split (b, s.character (0));
  1269. } else if (s.length() == 0) {
  1270. for (i=0; i < b.length (); i++) {
  1271. this->push_back (CBString (b.data[i]));
  1272. }
  1273. } else {
  1274. for (p=0; (i = b.find (s, p)) >= 0; p = i + s.length ()) {
  1275. this->push_back (b.midstr (p, i - p));
  1276. }
  1277. if (p <= b.length ()) {
  1278. this->push_back (b.midstr (p, b.length () - p));
  1279. }
  1280. }
  1281. }
  1282. static int streamSplitCb (void * parm, int ofs, const_bstring entry) {
  1283. CBStringList * r = (CBStringList *) parm;
  1284. ofs = ofs;
  1285. r->push_back (CBString (*entry));
  1286. return 0;
  1287. }
  1288. void CBStringList::split (const CBStream& b, const CBString& s) {
  1289. if (0 > bssplitscb (b.m_s, (bstring) &s, streamSplitCb,
  1290. (void *) this)) {
  1291. bstringThrow ("Split bstream failure");
  1292. }
  1293. }
  1294. void CBStringList::split (const CBStream& b, unsigned char splitChar) {
  1295. CBString sc (splitChar);
  1296. if (0 > bssplitscb (b.m_s, (bstring) &sc,
  1297. streamSplitCb, (void *) this)) {
  1298. bstringThrow ("Split bstream failure");
  1299. }
  1300. }
  1301. void CBStringList::splitstr (const CBStream& b, const CBString& s) {
  1302. if (0 > bssplitstrcb (b.m_s, (bstring) &s, streamSplitCb,
  1303. (void *) this)) {
  1304. bstringThrow ("Split bstream failure");
  1305. }
  1306. }
  1307. #endif
  1308. #if defined(BSTRLIB_CAN_USE_IOSTREAM)
  1309. std::ostream& operator << (std::ostream& sout, CBString b) {
  1310. return sout.write ((const char *)b, b.length());
  1311. }
  1312. #include <ctype.h>
  1313. static int istreamGets (void * parm) {
  1314. char c = '\n';
  1315. ((std::istream *)parm)->get(c);
  1316. if (isspace (c)) c = '\n';
  1317. return c;
  1318. }
  1319. std::istream& operator >> (std::istream& sin, CBString& b) {
  1320. do {
  1321. b.gets ((bNgetc) istreamGets, &sin, '\n');
  1322. if (b.slen > 0 && b.data[b.slen-1] == '\n') b.slen--;
  1323. } while (b.slen == 0 && !sin.eof ());
  1324. return sin;
  1325. }
  1326. struct sgetc {
  1327. std::istream * sin;
  1328. char terminator;
  1329. };
  1330. static int istreamGetc (void * parm) {
  1331. char c = ((struct sgetc *)parm)->terminator;
  1332. ((struct sgetc *)parm)->sin->get(c);
  1333. return c;
  1334. }
  1335. std::istream& getline (std::istream& sin, CBString& b, char terminator) {
  1336. struct sgetc parm;
  1337. parm.sin = &sin;
  1338. parm.terminator = terminator;
  1339. b.gets ((bNgetc) istreamGetc, &parm, terminator);
  1340. if (b.slen > 0 && b.data[b.slen-1] == terminator) b.slen--;
  1341. return sin;
  1342. }
  1343. #endif
  1344. CBStream::CBStream (bNread readPtr, void * parm) {
  1345. m_s = bsopen (readPtr, parm);
  1346. }
  1347. CBStream::~CBStream () {
  1348. bsclose (m_s);
  1349. }
  1350. int CBStream::buffLengthSet (int sz) {
  1351. if (sz <= 0) {
  1352. bstringThrow ("buffLengthSet parameter failure");
  1353. }
  1354. return bsbufflength (m_s, sz);
  1355. }
  1356. int CBStream::buffLengthGet () {
  1357. return bsbufflength (m_s, 0);
  1358. }
  1359. CBString CBStream::readLine (char terminator) {
  1360. CBString ret("");
  1361. if (0 > bsreadln ((bstring) &ret, m_s, terminator) && eof () < 0) {
  1362. bstringThrow ("Failed readLine");
  1363. }
  1364. return ret;
  1365. }
  1366. CBString CBStream::readLine (const CBString& terminator) {
  1367. CBString ret("");
  1368. if (0 > bsreadlns ((bstring) &ret, m_s, (bstring) &terminator) && eof () < 0) {
  1369. bstringThrow ("Failed readLine");
  1370. }
  1371. return ret;
  1372. }
  1373. void CBStream::readLine (CBString& s, char terminator) {
  1374. if (0 > bsreadln ((bstring) &s, m_s, terminator) && eof () < 0) {
  1375. bstringThrow ("Failed readLine");
  1376. }
  1377. }
  1378. void CBStream::readLine (CBString& s, const CBString& terminator) {
  1379. if (0 > bsreadlns ((bstring) &s, m_s, (bstring) &terminator) && eof () < 0) {
  1380. bstringThrow ("Failed readLine");
  1381. }
  1382. }
  1383. void CBStream::readLineAppend (CBString& s, char terminator) {
  1384. if (0 > bsreadlna ((bstring) &s, m_s, terminator) && eof () < 0) {
  1385. bstringThrow ("Failed readLineAppend");
  1386. }
  1387. }
  1388. void CBStream::readLineAppend (CBString& s, const CBString& terminator) {
  1389. if (0 > bsreadlnsa ((bstring) &s, m_s, (bstring) &terminator) && eof () < 0) {
  1390. bstringThrow ("Failed readLineAppend");
  1391. }
  1392. }
  1393. #define BS_BUFF_SZ (1024)
  1394. CBString CBStream::read () {
  1395. CBString ret("");
  1396. while (!bseof (m_s)) {
  1397. if (0 > bsreada ((bstring) &ret, m_s, BS_BUFF_SZ) && eof () < 0) {
  1398. bstringThrow ("Failed read");
  1399. }
  1400. }
  1401. return ret;
  1402. }
  1403. CBString& CBStream::operator >> (CBString& s) {
  1404. while (!bseof (m_s)) {
  1405. if (0 > bsreada ((bstring) &s, m_s, BS_BUFF_SZ) && eof () < 0) {
  1406. bstringThrow ("Failed read");
  1407. }
  1408. }
  1409. return s;
  1410. }
  1411. CBString CBStream::read (int n) {
  1412. CBString ret("");
  1413. if (0 > bsread ((bstring) &ret, m_s, n) && eof () < 0) {
  1414. bstringThrow ("Failed read");
  1415. }
  1416. return ret;
  1417. }
  1418. void CBStream::read (CBString& s) {
  1419. s.slen = 0;
  1420. while (!bseof (m_s)) {
  1421. if (0 > bsreada ((bstring) &s, m_s, BS_BUFF_SZ)) {
  1422. bstringThrow ("Failed read");
  1423. }
  1424. }
  1425. }
  1426. void CBStream::read (CBString& s, int n) {
  1427. if (0 > bsread ((bstring) &s, m_s, n)) {
  1428. bstringThrow ("Failed read");
  1429. }
  1430. }
  1431. void CBStream::readAppend (CBString& s) {
  1432. while (!bseof (m_s)) {
  1433. if (0 > bsreada ((bstring) &s, m_s, BS_BUFF_SZ)) {
  1434. bstringThrow ("Failed readAppend");
  1435. }
  1436. }
  1437. }
  1438. void CBStream::readAppend (CBString& s, int n) {
  1439. if (0 > bsreada ((bstring) &s, m_s, n)) {
  1440. bstringThrow ("Failed readAppend");
  1441. }
  1442. }
  1443. void CBStream::unread (const CBString& s) {
  1444. if (0 > bsunread (m_s, (bstring) &s)) {
  1445. bstringThrow ("Failed unread");
  1446. }
  1447. }
  1448. CBString CBStream::peek () const {
  1449. CBString ret ("");
  1450. if (0 > bspeek ((bstring) &ret, m_s)) {
  1451. bstringThrow ("Failed peek");
  1452. }
  1453. return ret;
  1454. }
  1455. void CBStream::peek (CBString& s) const {
  1456. s.slen = 0;
  1457. if (0 > bspeek ((bstring) &s, m_s)) {
  1458. bstringThrow ("Failed peek");
  1459. }
  1460. }
  1461. void CBStream::peekAppend (CBString& s) const {
  1462. if (0 > bspeek ((bstring) &s, m_s)) {
  1463. bstringThrow ("Failed peekAppend");
  1464. }
  1465. }
  1466. int CBStream::eof () const {
  1467. int ret = bseof (m_s);
  1468. if (0 > ret) {
  1469. bstringThrow ("Failed eof");
  1470. }
  1471. return ret;
  1472. }
  1473. } // namespace Bstrlib