PageRenderTime 58ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/Sources/bstring/bstrwrap.cpp

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