Str.c++
上传用户:weiyuanprp
上传日期:2020-05-20
资源大小:1169k
文件大小:19k
源码类别:

传真(Fax)编程

开发平台:

C/C++

  1. /* $Id: Str.c++,v 1.6 2009/10/07 15:36:26 faxguy Exp $ */
  2. /*
  3.  * Copyright (c) 1990-1996 Sam Leffler
  4.  * Copyright (c) 1991-1996 Silicon Graphics, Inc.
  5.  * HylaFAX is a trademark of Silicon Graphics
  6.  *
  7.  * Permission to use, copy, modify, distribute, and sell this software and 
  8.  * its documentation for any purpose is hereby granted without fee, provided
  9.  * that (i) the above copyright notices and this permission notice appear in
  10.  * all copies of the software and related documentation, and (ii) the names of
  11.  * Sam Leffler and Silicon Graphics may not be used in any advertising or
  12.  * publicity relating to the software without the specific, prior written
  13.  * permission of Sam Leffler and Silicon Graphics.
  14.  * 
  15.  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
  16.  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
  17.  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
  18.  * 
  19.  * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
  20.  * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
  21.  * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  22.  * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
  23.  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
  24.  * OF THIS SOFTWARE.
  25.  */
  26. #include "Str.h"
  27. #include <stdlib.h>
  28. #include <ctype.h>
  29. #include <stdarg.h>
  30. #include <errno.h>
  31. #define DEFAULT_FORMAT_BUFFER 4096
  32. char fxStr::emptyString = '';
  33. fxStr fxStr::null = "";
  34. fxStr::fxStr(u_int l)
  35. {
  36.     isutf8 = false;
  37.     slength = l+1;
  38.     if (l>0) {
  39. data = (char*) malloc(slength);
  40. memset(data,0,slength);
  41.     } else
  42. data = &emptyString;
  43. }
  44. fxStr::fxStr(const char *s)
  45. {
  46.     isutf8 = false;
  47.     u_int l = strlen(s)+1;
  48.     if (l>1) {
  49. data = (char*) malloc(l);
  50. memcpy(data,s,l);
  51.     } else {
  52. data = &emptyString;
  53.     }
  54.     slength = l;
  55. }
  56. fxStr::fxStr(const char *s, u_int len)
  57. {
  58.     isutf8 = false;
  59.     if (len>0) {
  60. data = (char*) malloc(len+1);
  61. memcpy(data,s,len);
  62. data[len] = 0;
  63.     } else
  64. data = &emptyString;
  65.     slength = len+1;
  66. }
  67. fxStr::fxStr(const fxStr& s)
  68. {
  69.     isutf8 = s.isutf8;
  70.     slength = s.slength;
  71.     if (slength > 1) {
  72. data = (char*) malloc(slength);
  73. memcpy(data,s.data,slength);
  74.     } else {
  75. data = &emptyString;
  76.     }
  77. }
  78. fxStr::fxStr(const fxTempStr& t)
  79. {
  80.     isutf8 = t.isutf8;
  81.     slength = t.slength;
  82.     if (t.slength>1) {
  83. data = (char*) malloc(slength);
  84. memcpy(data,t.data,slength);
  85.     } else {
  86. data = &emptyString;
  87.     }
  88. }
  89. fxStr::fxStr(int a, const char * format)
  90. {
  91.     fxStr s = fxStr::format((format) ? format : "%d", a);
  92.     slength = s.slength;
  93.     isutf8 = s.isutf8;
  94.     if (slength > 1) {
  95.         data = (char*) malloc(slength);
  96.         memcpy(data, s.data, slength);
  97.     } else {
  98.         data = &emptyString;
  99.     }
  100. }
  101. fxStr::fxStr(long a, const char * format)
  102. {
  103.     fxStr s = fxStr::format((format) ? format : "%ld", a);
  104.     slength = s.slength;
  105.     isutf8 = s.isutf8;
  106.     if (slength > 1) {
  107.         data = (char*) malloc(slength);
  108.         memcpy(data, s.data, slength);
  109.     } else {
  110.         data = &emptyString;
  111.     }
  112. }
  113. fxStr::fxStr(float a, const char * format)
  114. {
  115.     fxStr s = fxStr::format((format) ? format : "%g", a);
  116.     slength = s.slength;
  117.     isutf8 = s.isutf8;
  118.     if (slength > 1) {
  119.         data = (char*) malloc(slength);
  120.         memcpy(data, s.data, slength);
  121.     } else {
  122.         data = &emptyString;
  123.     }
  124. }
  125. fxStr::fxStr(double a, const char * format)
  126. {
  127.     fxStr s = fxStr::format((format) ? format : "%lg", a);
  128.     slength = s.slength;
  129.     isutf8 = s.isutf8;
  130.     if (slength > 1) {
  131.         data = (char*) malloc(slength);
  132.         memcpy(data, s.data, slength);
  133.     } else {
  134.         data = &emptyString;
  135.     }
  136. }
  137. fxStr::~fxStr()
  138. {
  139.     assert(data);
  140.     if (data != &emptyString) free(data);
  141. }
  142. fxStr
  143. fxStr::format(const char* fmt ...)
  144. {
  145.     int size = DEFAULT_FORMAT_BUFFER;
  146.     fxStr s;
  147.     va_list ap;
  148.     va_start(ap, fmt);
  149.     s.data = (char*)malloc(size);
  150.     int len = vsnprintf(s.data, size, fmt, ap);
  151.     va_end(ap);
  152.     while (len < 0 || len >= size) {
  153. if (len < 0 && errno != 0)
  154.     return s;
  155. if (len >= size) {
  156.             size = len + 1;
  157.         } else {
  158.             size *= 2;
  159.         }
  160.         s.data = (char*)realloc(s.data, size);
  161.         va_start(ap, fmt);
  162.         len = vsnprintf(s.data, size, fmt, ap);
  163.         va_end(ap);
  164.     }
  165.     if (size > len + 1) {
  166.         s.data = (char*) realloc(s.data, len + 1);
  167.     }
  168.     s.slength = len + 1;
  169.     return s; //XXX this is return by value which is inefficient
  170. }
  171. fxStr
  172. fxStr::vformat(const char* fmt, va_list ap)
  173. {
  174.     int size = DEFAULT_FORMAT_BUFFER;
  175.     fxStr s;
  176.     char* tmp = NULL;
  177.     int len = 0;
  178.     do
  179.     {
  180. if (len)
  181.     size *= 2;
  182. tmp = (char*)realloc(tmp, size);
  183. va_list ac;
  184. va_copy(ac, ap);
  185. len = vsnprintf(tmp, size, fmt, ac);
  186. va_end(ac);
  187. fxAssert(len >= 0, "Str::vformat() error in vsnprintf");
  188.     } while (len > size);
  189.     if (size > len + 1) {
  190.         tmp = (char*) realloc(tmp, len + 1);
  191.     }
  192.     s.data = tmp;
  193.     s.slength = len + 1;
  194.     return s; //XXX this is return by value which is inefficient
  195. }
  196. fxStr fxStr::extract(u_int start, u_int chars) const
  197. {
  198.     fxAssert(start+chars<slength, "Str::extract: Invalid range");
  199.     return fxStr(data+start,chars);
  200. }
  201. fxStr fxStr::head(u_int chars) const
  202. {
  203.     fxAssert(chars<slength, "Str::head: Invalid size");
  204.     return fxStr(data,chars);
  205. }
  206. fxStr fxStr::tail(u_int chars) const
  207. {
  208.     fxAssert(chars<slength, "Str::tail: Invalid size");
  209.     return fxStr(data+slength-chars-1,chars);
  210. }
  211. void fxStr::lowercase(u_int posn, u_int chars)
  212. {
  213.     if (!chars) chars = slength-1-posn;
  214.     fxAssert(posn+chars<slength, "Str::lowercase: Invalid range");
  215.     while (chars--) {
  216. #if defined(hpux) || defined(__hpux) || defined(__hpux__)
  217. /*
  218.  * HPUX (10.x at least) is seriously busted.  According
  219.  * to the manual page, when compiling in ANSI C mode tolower
  220.  * is defined as a macro that expands to a function that
  221.  * is undefined.  It is necessary to #undef tolower before
  222.  * using it! (sigh)
  223.  */
  224. #ifdef tolower
  225. #undef tolower
  226. #endif
  227. data[posn] = tolower(data[posn]);
  228. #elif defined(_tolower)
  229. char c = data[posn];
  230. if (isupper(c))
  231.     data[posn] = _tolower(c);
  232. #else
  233. data[posn] = tolower(data[posn]);
  234. #endif
  235. posn++;
  236.     }
  237. }
  238. void fxStr::raisecase(u_int posn, u_int chars)
  239. {
  240.     if (!chars) chars = slength-1-posn;
  241.     fxAssert(posn+chars<slength, "Str::raisecase: Invalid range");
  242.     while (chars--) {
  243. #ifdef hpux // HPUX bogosity; see above
  244. #ifdef toupper
  245. #undef toupper
  246. #endif
  247. data[posn] = toupper(data[posn]);
  248. #elif defined(_toupper)
  249. char c = data[posn];
  250. if (islower(c))
  251.     data[posn] = _toupper(c);
  252. #else
  253. data[posn] = toupper(data[posn]);
  254. #endif
  255. posn++;
  256.     }
  257. }
  258. /*
  259.  * Although T.32 6.1.1 and T.31 6.1 may lead a DCE to not
  260.  * distinguish between lower case and upper case, many DCEs
  261.  * actually support lower case characters in quoted strings.
  262.  * Thus, we don't rasecase quoted strings.
  263.  */
  264. void fxStr::raiseatcmd(u_int posn, u_int chars)
  265. {
  266.     if (!chars) chars = slength-1-posn;
  267.     fxAssert(posn+chars<slength, "Str::raiseatcmd: Invalid range");
  268.     bool quoted = false;
  269.     while (chars--) {
  270. #ifdef hpux // HPUX bogosity; see above
  271. #ifdef toupper
  272. #undef toupper
  273. #endif
  274. if (!quoted)
  275.     data[posn] = toupper(data[posn]);
  276. #elif defined(_toupper)
  277. char c = data[posn];
  278. if (islower(c) && !quoted)
  279.     data[posn] = _toupper(c);
  280. #else
  281. if (!quoted)
  282.     data[posn] = toupper(data[posn]);
  283. #endif
  284. if (data[posn] == '"')
  285.     quoted = !quoted;
  286. posn++;
  287.     }
  288. }
  289. fxStr fxStr::copy() const
  290. {
  291.     return fxStr(data,slength-1);
  292. }
  293. void fxStr::remove(u_int start, u_int chars)
  294. {
  295.     fxAssert(start+chars<slength,"Str::remove: Invalid range");
  296.     long move = slength-start-chars; // we always move at least 1
  297.     assert(move > 0);
  298.     if (slength - chars <= 1) {
  299. resizeInternal(0);
  300. slength = 1;
  301.     } else {
  302. memmove(data+start, data+start+chars, (u_int)move);
  303. slength -= chars;
  304.     }
  305. }
  306. fxStr fxStr::cut(u_int start, u_int chars)
  307. {
  308.     fxAssert(start+chars<slength,"Str::cut: Invalid range");
  309.     fxStr a(data+start, chars);
  310.     remove(start, chars);
  311.     return a;
  312. }
  313. void fxStr::insert(const char * v, u_int posn, u_int len)
  314. {
  315.     if (!len) len = strlen(v);
  316.     if (!len) return;
  317.     fxAssert(posn<slength, "Str::insert: Invalid index");
  318.     u_int move = slength - posn;
  319.     u_int nl = slength + len;
  320.     resizeInternal(nl);
  321.     /*
  322.      * When move is one we are always moving ; but beware
  323.      * that the previous string might have been null before
  324.      * the call to resizeInternal; so set the byte explicitly.
  325.      */
  326.     if (move == 1)
  327. data[posn+len] = '';
  328.     else
  329. memmove(data+posn+len, data+posn, move);
  330.     memcpy(data+posn, v, len);
  331.     slength = nl;
  332. }
  333. void fxStr::insert(char a, u_int posn)
  334. {
  335.     u_int nl = slength + 1;
  336.     resizeInternal(nl);
  337.     long move = (long)slength - (long)posn;
  338.     fxAssert(move>0, "Str::insert(char): Invalid index");
  339.     /*
  340.      * When move is one we are always moving ; but beware
  341.      * that the previous string might have been null before
  342.      * the call to resizeInternal; so set the byte explicitly.
  343.      */
  344.     if (move == 1)
  345. data[posn+1] = '';
  346.     else
  347. memmove(data+posn+1, data+posn, (size_t) move); // move string tail
  348.     data[posn] = a;
  349.     slength = nl;
  350. }
  351. void fxStr::resizeInternal(u_int chars)
  352. {
  353.     if (slength > 1) {
  354.         if (chars > 0) {
  355.             if (chars >= slength) {
  356.                 data = (char*) realloc(data,chars+1);
  357.             }
  358.         } else {
  359.             assert(data != &emptyString);
  360.             free(data);
  361.             data = &emptyString;
  362.         }
  363.     } else {
  364.         assert(data == &emptyString);
  365.         if (chars) {
  366.             data = (char*) malloc(chars+1);
  367.         }
  368.     }
  369. }
  370. void fxStr::resize(u_int chars, bool)
  371. {
  372.     resizeInternal(chars);
  373.     if (chars != 0) {
  374. if (slength == 1) // NB: special case for emptyString
  375.     memset(data, 0, chars+1);
  376. else {
  377.     if (chars >= slength) // zero expanded data segment
  378. memset(data+slength, 0, chars+1-slength);
  379.     else // null terminate shortened string
  380. data[chars] = 0;
  381. }
  382.     } else
  383. ; // now points to emptyString
  384.     slength = chars+1;
  385. }
  386. void fxStr::setMaxLength(u_int len)
  387. {
  388.     if (slength>1) resizeInternal(fxmax(len,slength-1));
  389. }
  390. void fxStr::operator=(const fxTempStr& s)
  391. {
  392.     resizeInternal(s.slength-1);
  393.     memcpy(data,s.data,s.slength);
  394.     slength = s.slength;
  395.     isutf8 = s.isutf8;
  396. }
  397. void fxStr::operator=(const fxStr& s)
  398. {
  399.     if (data == s.data && slength == s.slength)
  400. return;
  401.     resizeInternal(s.slength-1);
  402.     memcpy(data,s.data,s.slength);
  403.     slength = s.slength;
  404.     isutf8 = s.isutf8;
  405. }
  406. void fxStr::operator=(const char *s)
  407. {
  408.     u_int nl = strlen(s) + 1;
  409.     resizeInternal(nl-1);
  410.     slength = nl;
  411.     memcpy(data,s,slength);
  412. }
  413. void fxStr::append(const char * s, u_int l)
  414. {
  415.     if (!l) l = strlen(s);
  416.     if (!l) return;
  417.     u_int nl = slength + l;
  418.     resizeInternal(nl-1);
  419.     memcpy(data+slength-1, s, l);
  420.     slength = nl;
  421.     data[slength-1] = 0;
  422. }
  423. void fxStr::append(char a)
  424. {
  425.     resizeInternal(slength);
  426.     slength++;
  427.     data[slength-2] = a;
  428.     data[slength-1] = 0;
  429. }
  430. bool operator==(const fxStr& a,const fxStr& b)
  431. {
  432.     return (a.slength == b.slength) && (memcmp(a.data,b.data,a.slength) == 0) && (a.isutf8 == b.isutf8);
  433. }
  434. bool operator==(const fxStr& a,const char* b)
  435. {
  436.     return (a.slength == strlen(b)+1) && (memcmp(a.data,b,a.slength) == 0);
  437. }
  438. bool operator==(const char* b, const fxStr& a)
  439. {
  440.     return (a.slength == strlen(b)+1) && (memcmp(a.data,b,a.slength) == 0);
  441. bool operator!=(const fxStr& a,const fxStr& b)
  442. {
  443.     return (a.slength != b.slength) || (memcmp(a.data,b.data,a.slength) != 0) || (a.isutf8 != b.isutf8);
  444. }
  445. bool operator!=(const fxStr& a,const char* b)
  446. {
  447.     return (a.slength != strlen(b)+1) || (memcmp(a.data,b,a.slength) != 0);
  448. }
  449. bool operator!=(const char* b, const fxStr& a)
  450. {
  451.     return (a.slength != strlen(b)+1) || (memcmp(a.data,b,a.slength) != 0);
  452. bool operator>=(const fxStr& a,const fxStr& b)
  453. {
  454.     return strcmp(a,b) >= 0;
  455. }
  456. bool operator>=(const fxStr& a,const char* b)
  457. {
  458.     return strcmp(a,b) >= 0;
  459. }
  460. bool operator>=(const char* a, const fxStr& b)
  461. {
  462.     return strcmp(a,b) >= 0;
  463. bool operator>(const fxStr& a,const fxStr& b)
  464. {
  465.     return strcmp(a,b) > 0;
  466. }
  467. bool operator>(const fxStr& a,const char* b)
  468. {
  469.     return strcmp(a,b) > 0;
  470. }
  471. bool operator>(const char* a, const fxStr& b)
  472. {
  473.     return strcmp(a,b) > 0;
  474. bool operator<=(const fxStr& a,const fxStr& b)
  475. {
  476.     return strcmp(a,b) <= 0;
  477. }
  478. bool operator<=(const fxStr& a,const char* b)
  479. {
  480.     return strcmp(a,b) <= 0;
  481. }
  482. bool operator<=(const char* a, const fxStr& b)
  483. {
  484.     return strcmp(a,b) <= 0;
  485. bool operator<(const fxStr& a,const fxStr& b)
  486. {
  487.     return strcmp(a,b) < 0;
  488. }
  489. bool operator<(const fxStr& a,const char* b)
  490. {
  491.     return strcmp(a,b) < 0;
  492. }
  493. bool operator<(const char* a, const fxStr& b)
  494. {
  495.     return strcmp(a,b) < 0;
  496. int compare(const fxStr&a, const fxStr&b)
  497. {
  498.     return strcmp(a,b);
  499. }
  500. int compare(const fxStr&a, const char*b)
  501. {
  502.     return strcmp(a,b);
  503. }
  504. int compare(const char *a, const char *b)
  505. {
  506.     return strcmp(a,b);
  507. }
  508. static int quickFind(char a, const char * buf, u_int buflen)
  509. {
  510.     while (buflen--)
  511. if (*buf++ == a) return 1;
  512.     return 0;
  513. }
  514. u_int fxStr::next(u_int posn, char a) const
  515. {
  516.     fxAssert(posn<slength, "Str::next: invalid index");
  517.     char * buf = data+posn;
  518.     u_int counter = slength-1-posn;
  519.     while (counter--) {
  520. if (*buf == a) {
  521.     if (!isutf8) return (buf-data);
  522.     /*
  523.      * buf is signed, thus buf < 0 means that it has the 
  524.      * high bit set and is therefore part of a multi-byte 
  525.      * character.  Ignore those bytes.
  526.      */
  527.     if (*buf > 0) return (buf-data);
  528. }
  529. buf++;
  530.     }
  531.     return slength-1;
  532. }
  533. u_int fxStr::next(u_int posn, const char * c, u_int clen) const
  534. {
  535.     fxAssert(posn<slength, "Str::next: invalid index");
  536.     char * buf = data + posn;
  537.     u_int counter = slength-1-posn;
  538.     if (!clen) clen = strlen(c);
  539.     while (counter--) {
  540. if (quickFind(*buf,c,clen)) return (buf-data);
  541. buf++;
  542.     }
  543.     return slength-1;
  544. }
  545. u_int fxStr::nextR(u_int posn, char a) const
  546. {
  547.     fxAssert(posn<slength, "Str::nextR: invalid index");
  548.     char * buf = data + posn - 1;
  549.     u_int counter = posn;
  550.     while (counter--) {
  551. if (*buf == a) return (buf-data+1);
  552. buf--;
  553.     }
  554.     return 0;
  555. }
  556. u_int fxStr::nextR(u_int posn, const char * c, u_int clen) const
  557. {
  558.     fxAssert(posn<slength, "Str::nextR: invalid index");
  559.     char * buf = data + posn - 1;
  560.     u_int counter = posn;
  561.     if (!clen) clen = strlen(c);
  562.     while (counter--) {
  563. if (quickFind(*buf,c,clen)) return (buf-data+1);
  564. buf--;
  565.     }
  566.     return 0;
  567. }
  568. u_int fxStr::find(u_int posn, const char * c, u_int clen) const
  569. {
  570.     fxAssert(posn<slength, "Str::find: invalid index");
  571.     char * buf = data + posn;
  572.     u_int counter = slength-1-posn;
  573.     if (!clen) clen = strlen(c);
  574.     while (counter--) {
  575. if (quickFind(*buf,c,clen) && strncmp(buf,c,clen) == 0)
  576.     return (buf-data);
  577. buf++;
  578.     }
  579.     return slength-1;
  580. }
  581. u_int fxStr::findR(u_int posn, const char * c, u_int clen) const
  582. {
  583.     fxAssert(posn<slength, "Str::findR: invalid index");
  584.     char * buf = data + posn - 1;
  585.     u_int counter = posn;
  586.     if (!clen) clen = strlen(c);
  587.     while (counter--) {
  588. if (quickFind(*buf,c,clen) && strncmp(buf,c,clen) == 0)
  589.     return (buf-data+1);
  590. buf--;
  591.     }
  592.     return 0;
  593. }
  594. u_int fxStr::skip(u_int posn, char a) const
  595. {
  596.     fxAssert(posn<slength, "Str::skip: invalid index");
  597.     char * buf = data+posn;
  598.     u_int counter = slength-1-posn;
  599.     while (counter--) {
  600. if (*buf != a) return (buf-data);
  601. buf++;
  602.     }
  603.     return slength-1;
  604. }
  605. u_int fxStr::skip(u_int posn, const char * c, u_int clen) const
  606. {
  607.     fxAssert(posn<slength, "Str::skip: invalid index");
  608.     char * buf = data + posn;
  609.     u_int counter = slength-1-posn;
  610.     if (!clen) clen = strlen(c);
  611.     while (counter--) {
  612. if (!quickFind(*buf,c,clen)) return (buf-data);
  613. buf++;
  614.     }
  615.     return slength-1;
  616. }
  617. u_int fxStr::skipR(u_int posn, char a) const
  618. {
  619.     fxAssert(posn<slength, "Str::skipR: invalid index");
  620.     char * buf = data + posn - 1;
  621.     u_int counter = posn;
  622.     while (counter--) {
  623. if (*buf != a) return (buf-data+1);
  624. buf--;
  625.     }
  626.     return 0;
  627. }
  628. u_int fxStr::skipR(u_int posn, const char * c, u_int clen) const
  629. {
  630.     fxAssert(posn<slength, "Str::skipR: invalid index");
  631.     char * buf = data + posn - 1;
  632.     u_int counter = posn;
  633.     if (!clen) clen = strlen(c);
  634.     while (counter--) {
  635. if (!quickFind(*buf,c,clen)) return (buf-data+1);
  636. buf--;
  637.     }
  638.     return 0;
  639. }
  640. fxStr fxStr::token(u_int & posn, const char * delim, u_int dlen) const
  641. {
  642.     fxAssert(posn<slength, "Str::token: invalid index");
  643.     if (!dlen) dlen = strlen(delim);
  644.     u_int end = next(posn, delim, dlen);
  645.     u_int old = posn;
  646.     posn = skip(end, delim, dlen);
  647.     return extract(old,end-old);
  648. }
  649. fxStr fxStr::token(u_int & posn, char a) const
  650. {
  651.     fxAssert(posn<slength, "Str::token: invalid index");
  652.     u_int end = next(posn, a);
  653.     u_int old = posn;
  654.     posn = skip(end, a);
  655.     return extract(old,end-old);
  656. }
  657. fxStr fxStr::tokenR(u_int & posn, const char * delim, u_int dlen) const
  658. {
  659.     fxAssert(posn<slength, "Str::tokenR: invalid index");
  660.     if (!dlen) dlen = strlen(delim);
  661.     u_int begin = nextR(posn, delim, dlen);
  662.     u_int old = posn;
  663.     posn = skipR(begin, delim, dlen);
  664.     return extract(begin, old-begin);
  665. }
  666. fxStr fxStr::tokenR(u_int & posn, char a) const
  667. {
  668.     fxAssert(posn<slength, "Str::tokenR: invalid index");
  669.     u_int begin = nextR(posn, a);
  670.     u_int old = posn;
  671.     posn = skipR(begin, a);
  672.     return extract(begin,old-begin);
  673. }
  674. u_long fxStr::hash() const
  675. {
  676.     char * elementc = data;
  677.     u_int slen = slength - 1;
  678.     u_long k = 0;
  679.     if (slen < 2*sizeof(k)) {
  680. if (slen <= sizeof(k)) {
  681.     memcpy((char *)&k + (sizeof(k) - slen), elementc, slen);
  682.     k<<=3;
  683. } else {
  684.     memcpy((char *)&k + (sizeof(k)*2 - slen), elementc, slen-sizeof(k));
  685.     k<<=3;
  686.     k ^= *(u_long *)elementc;
  687. }
  688.     } else {
  689. k = *(u_long *)(elementc + sizeof(k));
  690. k<<=3;
  691. k ^= *(u_long *)elementc;
  692.     }
  693.     return k;
  694. }
  695. //--- concatenation support ----------------------------------
  696. fxTempStr::fxTempStr(const char *d1, u_int l1, const char *d2, u_int l2)
  697. {
  698.     slength = l1 + l2 + 1;
  699.     if (slength <= sizeof(indata)) {
  700. data = &indata[0];
  701.     } else {
  702. data = (char*) malloc(slength);
  703.     }
  704.     memcpy(data,d1,l1);
  705.     memcpy(data+l1,d2,l2);
  706.     data[l1+l2] = 0;
  707. }
  708. fxTempStr::fxTempStr(fxTempStr const &other)
  709. {
  710.     slength = other.slength;
  711.     if (slength <= sizeof (indata)) {
  712. data = &indata[0];
  713.     } else {
  714. data = (char*) malloc(slength);
  715.     }
  716.     memcpy(data, other.data, slength);
  717.     data[slength] = 0;
  718. }
  719. fxTempStr::~fxTempStr()
  720. {
  721.     if (data != indata) free(data);
  722. }
  723. fxTempStr& operator|(const fxTempStr& ts, const fxStr &b)
  724. {
  725.     return ((fxTempStr &)ts).concat(b.data, b.slength-1);
  726. }
  727. fxTempStr& operator|(const fxTempStr& ts, const char *b)
  728. {
  729.     return ((fxTempStr &)ts).concat(b, strlen(b));
  730. }
  731. fxTempStr& fxTempStr::concat(const char* b, u_int bl)
  732. {
  733.     if (slength <= sizeof(indata)) {
  734. // Current temporary is in the internal buffer.  See if the
  735. // concatenation will fit too.
  736. if (slength + bl > sizeof(indata)) {
  737.     // Have to malloc.
  738.     data = (char*) malloc(slength + bl);
  739.     memcpy(data, indata, slength - 1);
  740. }
  741.     } else {
  742. // Temporary is already too large.
  743. data = (char*) realloc(data, slength + bl);
  744.     }
  745.     // concatenate data
  746.     memcpy(data+slength-1, b, bl);
  747.     slength += bl;
  748.     data[slength-1] = 0;
  749.     return *this;
  750. }
  751. fxTempStr operator|(const fxStr &a, const fxStr &b)
  752. {
  753.     return fxTempStr(a.data, a.slength-1, b.data, b.slength-1);
  754. }
  755. fxTempStr operator|(const fxStr &a, const char *b)
  756. {
  757.     return fxTempStr(a.data, a.slength-1, b, strlen(b));
  758. }
  759. fxTempStr operator|(const char *a, const fxStr &b)
  760. {
  761.     return fxTempStr(a, strlen(a), b.data, b.slength-1);
  762. }