|
|
1.1 ! root 1: #include "String.h" ! 2: ! 3: #define FALSE 0 ! 4: #define TRUE (!FALSE) ! 5: ! 6: extern "C" { ! 7: extern char *memcpy(char *to, const char *from, int); ! 8: } ! 9: ! 10: inline char* // thanx to Jerry Schwarz ! 11: my_mcpy(char *to, const char *from, int n) ! 12: { ! 13: if (n==1) { ! 14: *to = *from; ! 15: return to; ! 16: } else return memcpy(to, from, n); ! 17: } ! 18: ! 19: inline char* ! 20: my_Mcpy(char *to, const char *from, int n) ! 21: { ! 22: if (n==1) { ! 23: *to = *from; ! 24: return to; ! 25: } else return Memcpy(to, from, n); ! 26: } ! 27: ! 28: int fieldSize = 32768; /* size of field to allocate */ ! 29: ! 30: Rep::Rep(const char *s, unsigned slen) ! 31: { ! 32: switch (slen) { ! 33: case 0: ! 34: this = nullRep; ! 35: break; ! 36: case 1: ! 37: this = &oneChar[*s]; ! 38: break; ! 39: default: ! 40: this = new Rep(slen); ! 41: my_mcpy(start, s, slen); ! 42: break; ! 43: } ! 44: } ! 45: ! 46: Rep::Rep(const Rep &rr) ! 47: { ! 48: switch (rr.len) { ! 49: case 0: ! 50: this = nullRep; ! 51: break; ! 52: case 1: ! 53: this = &oneChar[*rr.start]; ! 54: break; ! 55: default: ! 56: this = new Rep(rr.len); ! 57: my_mcpy(start, rr.start, len); ! 58: break; ! 59: } ! 60: } ! 61: ! 62: Rep::Rep(unsigned slen) ! 63: { ! 64: Charfield *oldCurr = currfield; ! 65: Rep *temp; ! 66: if (slen <= 1) abort(); // internal String error ! 67: while (!(temp = currfield->newRep(slen))) ! 68: if (currfield->compactify(slen) && ! 69: (currfield=currfield->next) == oldCurr) { ! 70: oldCurr = oldCurr->next; ! 71: currfield->next = new Charfield(slen); ! 72: (currfield=currfield->next)->next = oldCurr; ! 73: } ! 74: this = temp; ! 75: this->refCount = 1; ! 76: } ! 77: ! 78: Rep::~Rep() ! 79: { ! 80: if (!is_constant()) { ! 81: Charfield *field = myField(); ! 82: if (field) { ! 83: field->usedSpace -= len; ! 84: field->putMt((MtRep *)this); ! 85: } ! 86: } ! 87: this = 0; ! 88: } ! 89: ! 90: Charfield* ! 91: Rep::myField() _const ! 92: { ! 93: Charfield *rslt = currfield; ! 94: do { ! 95: if (rslt->field <= (char*)this && rslt->end > (char*)this) ! 96: return rslt; ! 97: } while ((rslt=rslt->next) != currfield); ! 98: return 0; ! 99: } ! 100: ! 101: int ! 102: Charfield::compactify(unsigned need) ! 103: { ! 104: char *bigBuf; ! 105: register charSpace = (char*)lastRep - field; ! 106: if (4*usedSpace > 3*charSpace || charSpace - usedSpace - sizeof(Rep) < need) ! 107: return TRUE; ! 108: bigBuf = new char[usedSpace]; ! 109: char *ptr = bigBuf; ! 110: Rep *aRep = (Rep *)end; ! 111: while ( --aRep >= lastRep ) { ! 112: if( !aRep->isMt() ) { ! 113: my_mcpy(ptr, aRep->start, aRep->len); /* copy out */ ! 114: aRep->start = field + (ptr - bigBuf); ! 115: aRep->mutable(); ! 116: ptr += aRep->len; ! 117: } ! 118: } ! 119: my_mcpy(field, bigBuf, usedSpace); /* copy in */ ! 120: firstFree = field + usedSpace; ! 121: delete bigBuf; ! 122: return FALSE; ! 123: } ! 124: ! 125: Charfield::Charfield() ! 126: { ! 127: end = (firstFree = field = new char[fieldSize]) + fieldSize; ! 128: usedSpace = 0; ! 129: lastRep = (Rep *)end; ! 130: emptyHead = 0; ! 131: } ! 132: ! 133: Charfield::Charfield(unsigned sz) ! 134: { ! 135: if (sz > fieldSize/2) ! 136: sz = ( sz + fieldSize/2 + 3 ) & ~3; ! 137: else ! 138: sz = fieldSize; ! 139: end = (firstFree = field = new char[sz]) + sz; ! 140: usedSpace = 0; ! 141: lastRep = (Rep *)end; ! 142: emptyHead = 0; ! 143: } ! 144: ! 145: Rep* ! 146: Charfield::newRep(unsigned ln) ! 147: { ! 148: Rep *rslt; ! 149: /* first get an empty Rep and free space in the field */ ! 150: if (rslt = getMt()) { ! 151: if ((char *)lastRep - firstFree >= ln) { ! 152: rslt->start = firstFree; ! 153: rslt->flags = 0; // not_constant and mutable ! 154: rslt->len = ln; ! 155: firstFree += ln; ! 156: usedSpace += ln; ! 157: return rslt; ! 158: } else ! 159: putMt((MtRep *)rslt); ! 160: } ! 161: /* give up */ ! 162: return 0; ! 163: } ! 164: ! 165: Rep* ! 166: Charfield::getMt() ! 167: { ! 168: if (emptyHead) { ! 169: if (emptyHead->dummy != empty_dummy) // for debugging ! 170: abort(); // double destruction! ! 171: Rep *rslt = (Rep *) emptyHead; ! 172: emptyHead = emptyHead->next; ! 173: rslt->refCount = 1; ! 174: rslt->flags = 0; ! 175: return rslt; ! 176: } ! 177: if ((char *)lastRep - firstFree >= sizeof(Rep) ) { ! 178: lastRep -= 1; ! 179: lastRep->refCount = 1; ! 180: lastRep->flags = 0; ! 181: return lastRep; ! 182: } ! 183: return 0; ! 184: } ! 185: ! 186: void ! 187: Charfield::putMt(MtRep *x) ! 188: { ! 189: if (emptyHead && emptyHead->dummy != empty_dummy || ! 190: x->dummy == empty_dummy) // for debugging ! 191: abort(); // double destruction! ! 192: x->next = emptyHead; ! 193: x->dummy = empty_dummy; /* mark this as empty */ ! 194: emptyHead = x; ! 195: } ! 196: ! 197: int ! 198: Rep::hashval() const /* for use in hash tables, etc. */ ! 199: { ! 200: register int rslt = 0; ! 201: register char *p = start; ! 202: register char *q = start + len; ! 203: while ( p < q ) { ! 204: rslt += rslt + *p++; ! 205: if ( rslt < 0 ) ! 206: rslt = -rslt; ! 207: } ! 208: return rslt; ! 209: } ! 210: ! 211: Rep* ! 212: Rep::newSub(int offset, int length) ! 213: { ! 214: Charfield *myF; ! 215: Rep *rslt; ! 216: if (!(myF = myField()) || !(rslt = myF->getMt())) ! 217: return NULL; ! 218: rslt->start = start + offset; ! 219: rslt->immutable(); ! 220: rslt->len = length; ! 221: immutable(); ! 222: myF->usedSpace += length; /* this space is now shared */ ! 223: return rslt; ! 224: } ! 225: ! 226: /* try for a new Rep which will be this plus something */ ! 227: Rep* ! 228: Rep::canCat(int plus) ! 229: { ! 230: Charfield *myF = myField(); ! 231: if (myF == 0 || start+len != myF->firstFree) ! 232: return 0; /* no way if not at top */ ! 233: Rep *rslt = myF->getMt(); ! 234: if (rslt) ! 235: if ((myF->firstFree += plus) < (char *)myF->lastRep) { ! 236: rslt->start = start; ! 237: rslt->immutable(); ! 238: rslt->len = len + plus; ! 239: immutable(); ! 240: myF->usedSpace += len + plus; ! 241: } else { ! 242: myF->firstFree -= plus; /* good try, but ... */ ! 243: myF->putMt((MtRep*)rslt); ! 244: rslt = 0; ! 245: } ! 246: return rslt; ! 247: } ! 248: ! 249: bit ! 250: Rep::extend(register int plus) // TRUE if the Rep can be extended (or shrunk) ! 251: { ! 252: register Charfield *myF = myField(); ! 253: if (!myF) return FALSE; ! 254: if (plus <= 0) { // if shrink (could try to adjust firstFree) ! 255: myF->usedSpace += plus; ! 256: len += plus; ! 257: return TRUE; ! 258: } ! 259: if (start + len == myF->firstFree) ! 260: if ((myF->firstFree += plus) < (char *)myF->lastRep) { ! 261: myF->usedSpace += plus; ! 262: len += plus; ! 263: return TRUE; ! 264: } else ! 265: myF->firstFree -= plus; // good try, but ... ! 266: return FALSE; ! 267: } ! 268: ! 269: int ! 270: Rep::compare (register const char *q) _const /* like strcmp(3C) */ ! 271: { ! 272: /* do this in assembler some day */ ! 273: register char *p = start; ! 274: register int i = len+1; ! 275: register char c; ! 276: ! 277: while (--i && (c = *q++) &&*p++ == c) ! 278: ; ! 279: return i ? (c ? (*--p > *--q)*2-1 : 1) : *q ? -1 : 0; ! 280: } ! 281: ! 282: int ! 283: Rep::match(const Rep& r) _const // return first differing position ! 284: { ! 285: /* do this in assembler some day */ ! 286: register char *p = start; ! 287: register char *q = r.start; ! 288: register int i = min(len, r.len)+1; ! 289: ! 290: while (--i && *p++ == *q++) ! 291: ; ! 292: return i ? p - start -1 : p - start; ! 293: } ! 294: ! 295: int ! 296: Rep::match(register const char *q) _const // return first differing position ! 297: { ! 298: /* do this in assembler some day */ ! 299: register char *p = start; ! 300: register int i = len+1; ! 301: register char c; ! 302: ! 303: while (--i && (c = *q++) &&*p++ == c) ! 304: ; ! 305: return i ? (c ? p - start - 1 : p - start) : len; ! 306: } ! 307: ! 308: int ! 309: Rep::strchr(char c) _const /* position of first occurrence of char */ ! 310: { ! 311: /* do this in assembler some day */ ! 312: register char *p = start-1, *q = start + len; ! 313: while ( ++p < q ) ! 314: if ( *p == c ) ! 315: return p - start; ! 316: return -1; ! 317: } ! 318: ! 319: int ! 320: Rep::strrchr(char c) _const /* ... last ... (-1 if char not there) */ ! 321: { ! 322: /* do this in assembler some day */ ! 323: register char *p = start + len, *q = start; ! 324: while ( --p >= q ) ! 325: if ( *p == c ) ! 326: return p - start; ! 327: return -1; ! 328: } ! 329: ! 330: int ! 331: Rep::strpbrk(const Rep &rr) _const ! 332: { ! 333: /* do this in assembler some day */ ! 334: char tab[256]; ! 335: register char *p, *q; ! 336: for ( p = tab, q=&tab[256]; p<q;) ! 337: *p++ = 0; ! 338: for ( p = rr.start, q=rr.start+rr.len; p<q; ) ! 339: tab[(unsigned char)*p++] = 1; ! 340: for ( p = start-1, q=start+len; ++p < q; ) ! 341: if ( tab[(unsigned char)*p] ) ! 342: return p - start; ! 343: return -1; ! 344: } ! 345: ! 346: int ! 347: Rep::strspn(const Rep &rr) _const ! 348: { ! 349: /* do this in assembler some day */ ! 350: char tab[256]; ! 351: register char *p, *q; ! 352: for ( p = tab, q=&tab[256]; p<q;) ! 353: *p++ = 0; ! 354: for ( p = rr.start, q=rr.start+rr.len; p<q; ) ! 355: tab[(unsigned char)*p++] = 1; ! 356: for ( p = start-1, q=start+len; ++p < q; ) ! 357: if ( !tab[(unsigned char)*p] ) ! 358: break; ! 359: return p - start; ! 360: } ! 361: ! 362: int ! 363: Rep::strcspn(const Rep &rr) _const ! 364: { ! 365: /* do this in assembler some day */ ! 366: char tab[256]; ! 367: register char *p, *q; ! 368: for ( p = tab, q=&tab[256]; p<q;) ! 369: *p++ = 0; ! 370: for ( p = rr.start, q=rr.start+rr.len; p<q; ) ! 371: tab[(unsigned char)*p++] = 1; ! 372: for ( p = start-1, q=start+len; ++p < q; ) ! 373: if ( tab[(unsigned char)*p] ) ! 374: break; ! 375: return p - start; ! 376: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.