|
|
1.1 ! root 1: #include "String.h" ! 2: #include <ctype.h> ! 3: ! 4: extern "C" { ! 5: extern char *memcpy(char *to, const char *from, int); ! 6: } ! 7: ! 8: inline char* // thanx to Jerry Schwarz ! 9: my_mcpy(char *to, const char *from, int n) ! 10: { ! 11: if (n==1) { ! 12: *to = *from; ! 13: return to; ! 14: } else return memcpy(to, from, n); ! 15: } ! 16: ! 17: inline char* ! 18: my_Mcpy(char *to, const char *from, int n) ! 19: { ! 20: if (n==1) { ! 21: *to = *from; ! 22: return to; ! 23: } else return Memcpy(to, from, n); ! 24: } ! 25: ! 26: String ! 27: String::operator+ (const String& oo) _const /* catenate */ ! 28: { ! 29: register Rep *sd = d; ! 30: register Rep *sood = oo.d; ! 31: register sdlen = sd->len; ! 32: register soodlen = sood->len; ! 33: if (sdlen + soodlen > MAXSTRINGLENGTH) ! 34: error( 1, "String.operator+: overflow" ); ! 35: if (sdlen == 0) return oo; ! 36: else if (soodlen == 0) return *this; ! 37: // try to make this a SubString of the result ! 38: Rep *temp; ! 39: if ((temp = sd->canCat(soodlen)) == NULL) { ! 40: temp = new Rep(sdlen + soodlen); ! 41: my_mcpy(temp->start, sd->start, sdlen); ! 42: } ! 43: my_mcpy(temp->start+sdlen, sood->start, soodlen); ! 44: return String(*temp); ! 45: } ! 46: ! 47: String ! 48: String::operator+ (const char *p) _const /* catenate */ ! 49: { ! 50: register Rep *sd = d; ! 51: register sdlen = sd->len; ! 52: register len = strlen(p); ! 53: if (sdlen + len > MAXSTRINGLENGTH) ! 54: error(1, "String::operator+: overflow"); ! 55: if (sdlen == 0) return String(p); ! 56: else if (len == 0) return *this; ! 57: // try to make this a SubString of the result ! 58: Rep *temp; ! 59: if ((temp = sd->canCat(len)) == NULL) { ! 60: temp = new Rep(sdlen + len); ! 61: my_mcpy(temp->start, sd->start, sdlen); ! 62: } ! 63: my_mcpy(temp->start+sdlen, p, len); ! 64: return String(*temp); ! 65: } ! 66: ! 67: String ! 68: String::operator+ (const char c) const /* catenate */ ! 69: { ! 70: register Rep *sd = d; ! 71: register sdlen = sd->len; ! 72: if (sdlen > MAXSTRINGLENGTH - 1) ! 73: error( 1, "String.operator+: overflow" ); ! 74: if (sdlen == 0) return String(c); ! 75: // try to make this a SubString of the result ! 76: Rep *temp; ! 77: if ((temp = sd->canCat(1)) == NULL) { ! 78: temp = new Rep(sdlen + 1); ! 79: my_mcpy(temp->start, sd->start, sdlen); ! 80: } ! 81: temp->start[sdlen] = c; ! 82: return String(*temp); ! 83: } ! 84: ! 85: String ! 86: operator+ (const char *p, const String& s) /* catenate */ ! 87: { ! 88: register Rep *ssd = s.d; ! 89: register ssdlen = ssd->len; ! 90: register len = strlen(p); ! 91: if (ssdlen + len > MAXSTRINGLENGTH) ! 92: s.error( 1, "operator+(char*,String): overflow" ); ! 93: if (ssdlen == 0) return String(p); ! 94: else if (len == 0) return s; ! 95: Rep *temp = new Rep(ssdlen + len); ! 96: my_mcpy(temp->start, p, len); ! 97: my_mcpy(temp->start+len, ssd->start, ssdlen); ! 98: return String(*temp); ! 99: } ! 100: ! 101: String ! 102: operator+ (const char c, const String& s) /* catenate */ ! 103: { ! 104: register Rep *ssd = s.d; ! 105: register ssdlen = ssd->len; ! 106: if (ssdlen > MAXSTRINGLENGTH - 1) ! 107: s.error( 1, "operator+(char,String): overflow" ); ! 108: if (ssdlen == 0) return String(c); ! 109: Rep *temp = new Rep(ssdlen + 1); ! 110: my_mcpy(temp->start+1, ssd->start, ssdlen); ! 111: temp->start[0] = c; ! 112: return String(*temp); ! 113: } ! 114: ! 115: Subchar& ! 116: String::operator[](const unsigned i) /* character selection */ ! 117: { ! 118: if ( i >= length()) ! 119: error(1, "String.operator[]: out of bounds"); ! 120: return *new Subchar(*this,i); ! 121: } ! 122: ! 123: SubString& ! 124: String::operator()(const unsigned offset, const unsigned len) /* SubString */ ! 125: { ! 126: if ( offset > length() ) ! 127: error(1, "String.operator(): offset out of bounds"); ! 128: if ( len > MAXSUBSTRINGLENGTH || offset + len > d->len) ! 129: error(1, "String.operator(): length out of bounds"); ! 130: return *new SubString(*this, offset, len); ! 131: } ! 132: ! 133: Subchar::Subchar(const Subchar&) ! 134: { ! 135: error(1, "Subchar.Subchar(Subchar&): shouldn't call this" ); ! 136: } ! 137: ! 138: SubString::SubString(const SubString&) ! 139: { ! 140: error(1, "SubString.SubString(SubString&): shouldn't call this" ); ! 141: } ! 142: ! 143: String& ! 144: String::operator=(const String& oo) ! 145: { ! 146: register Rep *sd = d; ! 147: register Rep *sood = oo.d; ! 148: if ( sd != sood ) { ! 149: sd->refDecr(); ! 150: sd = d = sood; ! 151: sd->refIncr(); ! 152: } ! 153: return *this; ! 154: } ! 155: ! 156: String& ! 157: String::operator=(const char *s) ! 158: { ! 159: register Rep *sd = d; ! 160: sd->refDecr(); ! 161: d = new Rep(s); ! 162: return *this; ! 163: } ! 164: ! 165: String& ! 166: String::operator= (const char c) ! 167: { ! 168: register Rep *sd = d; ! 169: sd->refDecr(); ! 170: d = &oneChar[c]; ! 171: return *this; ! 172: } ! 173: ! 174: char ! 175: Subchar::operator=(const char cc) ! 176: { ! 177: register Rep *sd = ss->d; ! 178: if (sd->len == 1) { /* one character String */ ! 179: sd = &oneChar[cc]; ! 180: } else if (sd->refCount == 1 && !sd->is_constant()) { ! 181: /* modify in place */ ! 182: sd->start[oo] = cc; ! 183: } else { ! 184: Rep *rr = new Rep(*sd); ! 185: /* copy middle */ ! 186: rr->start[oo] = cc; ! 187: sd->refDecr(); ! 188: ss->d = rr; ! 189: } ! 190: /* delete this; it's used up */ ! 191: return cc; ! 192: } ! 193: ! 194: void ! 195: SubString::operator=(const String& oss) ! 196: { ! 197: register Rep *sd = ss->d; ! 198: register Rep *osd = oss.d; ! 199: int itsOldLength = ss->length(); ! 200: int newLength = itsOldLength + oss.length() - ll; ! 201: if (newLength == 0) { ! 202: sd->refDecr(); ! 203: sd = ss->d = nullRep; ! 204: } else if (newLength == 1) { ! 205: Rep *rr; ! 206: if (oss.length() == 1) ! 207: rr = osd; ! 208: else if (oo == 1) /* the head of this */ ! 209: rr = &oneChar[*sd->start]; ! 210: else /* the last character */ ! 211: rr = &oneChar[*(sd->start+ss->length()-1)]; ! 212: sd->refDecr(); ! 213: ss->d = rr; ! 214: } else if (sd->refCount == 1 && !sd->is_constant() && ! 215: (sd->extend(oss.length() - ll))) { ! 216: /* modify in place */ ! 217: if (ll != oss.length()) ! 218: /* copy tail */ ! 219: my_Mcpy(sd->start + oo + oss.length(), ! 220: sd->start + oo + ll, ! 221: itsOldLength - (oo + ll)); ! 222: /* copy middle */ ! 223: my_mcpy(sd->start+oo, osd->start, oss.length()); ! 224: } else { ! 225: Rep *rr = new Rep(newLength); ! 226: /* copy head */ ! 227: my_mcpy(rr->start, sd->start, oo); ! 228: /* copy middle */ ! 229: my_mcpy(rr->start+oo, osd->start, oss.length()); ! 230: /* copy tail */ ! 231: my_mcpy(rr->start + oo + oss.length(), ! 232: sd->start + oo + ll, ! 233: ss->length() - (oo + ll)); ! 234: sd->refDecr(); ! 235: ss->d = rr; ! 236: } ! 237: /* delete this; it's used up */ ! 238: } ! 239: ! 240: bit ! 241: String::getX(char& c) /* or lop */ ! 242: { ! 243: register Rep *sd = d; ! 244: if ( length() < 1 ) ! 245: return FALSE; ! 246: c = *sd->start; ! 247: if ( length() == 1 ) ! 248: d = nullRep; ! 249: else if ( length() == 2 ) { ! 250: d = &oneChar[(unsigned char)sd->start[1]]; ! 251: sd->refDecr(); ! 252: } else { ! 253: Charfield *myF = sd->myField(); ! 254: if (sd->refCount == 1 && !sd->is_constant()) { ! 255: sd->start++; ! 256: sd->len--; ! 257: myF->usedSpace -= 1; ! 258: } else { ! 259: Rep *rr = myF->getMt(); ! 260: if (rr) { ! 261: sd->immutable(); ! 262: rr->immutable(); ! 263: rr->start = sd->start + 1; ! 264: myF->usedSpace += (rr->len = sd->len - 1); ! 265: } else ! 266: rr = new Rep (sd->start+1, sd->len - 1); ! 267: sd->refDecr(); ! 268: d = rr; ! 269: } ! 270: } ! 271: return TRUE; ! 272: } ! 273: ! 274: bit ! 275: String::firstX(char &c) _const // don't change the String ! 276: { ! 277: return length() ? (c = *d->start, TRUE) : FALSE; ! 278: } ! 279: ! 280: bit ! 281: String::lastX(char &c) _const // don't change the String ! 282: { ! 283: return length() ? (c = d->start[length()-1], TRUE) : FALSE; ! 284: } ! 285: ! 286: bit ! 287: String::unputX(char& c) /* remove from back */ ! 288: { ! 289: register Rep *sd = d; ! 290: if (length() < 1) ! 291: return FALSE; ! 292: c = sd->start[length()-1]; ! 293: if (length() == 1) ! 294: d = nullRep; ! 295: else if (length() == 2) { ! 296: d = &oneChar[(unsigned char)*sd->start]; ! 297: sd->refDecr(); ! 298: } else { ! 299: Charfield *myF = sd->myField(); ! 300: if (!myF) abort(); // internal string error ! 301: if (sd->refCount == 1 && !sd->is_constant()) { ! 302: sd->len--; ! 303: myF->usedSpace -= 1; ! 304: } else { ! 305: Rep *rr = myF->getMt(); ! 306: if (rr) { ! 307: sd->immutable(); ! 308: rr->immutable(); ! 309: rr->start = sd->start; ! 310: myF->usedSpace += (rr->len = sd->len - 1); ! 311: } else ! 312: rr = new Rep (sd->start, sd->len - 1); ! 313: sd->refDecr(); ! 314: d = rr; ! 315: } ! 316: } ! 317: return TRUE; ! 318: } ! 319: ! 320: String& ! 321: String::put(const char c) /* append or put */ ! 322: { ! 323: register Rep *sd = d; ! 324: register sdlen = sd->len; ! 325: switch (sdlen) { ! 326: case 0: ! 327: d = &oneChar[(unsigned char) c]; ! 328: break; ! 329: case 1: ! 330: Rep *rr = new Rep(2); ! 331: *rr->start = *sd->start; ! 332: rr->start[1] = c; ! 333: d = rr; ! 334: break; ! 335: case MAXSTRINGLENGTH: ! 336: error (1, "String::put: String overflow"); ! 337: break; ! 338: default: ! 339: if (sd->refCount == 1 && !sd->is_constant() && sd->extend(1)) ! 340: sd->start[sdlen] = c; ! 341: else { ! 342: Rep *rr = sd->canCat(1); ! 343: if (rr) ! 344: rr->start[rr->len-1] = c; ! 345: else { ! 346: rr = new Rep (sdlen + 1); ! 347: my_mcpy(rr->start, sd->start, sdlen); ! 348: rr->start[sdlen] = c; ! 349: } ! 350: sd->refDecr(); ! 351: d = rr; ! 352: } ! 353: break; ! 354: } ! 355: return *this; ! 356: } ! 357: ! 358: String& ! 359: String::put(const char *p) /* append */ ! 360: { ! 361: register Rep *sd = d; ! 362: register sdlen = sd->len; ! 363: register soodlen = strlen(p); ! 364: if (sdlen + soodlen > MAXSTRINGLENGTH) ! 365: error(1, "String::put: overflow"); ! 366: if (sdlen == 0) return *this = p; ! 367: if (soodlen == 0) return *this; ! 368: if (sd->refCount == 1 && !sd->is_constant()) { ! 369: char *oldEnd = sd->start+sdlen; ! 370: if (sd->extend(soodlen)) { ! 371: my_mcpy(oldEnd, p, soodlen); ! 372: return *this; ! 373: } ! 374: } ! 375: Rep *temp = new Rep(sdlen + soodlen); ! 376: my_mcpy(temp->start, sd->start, sdlen); ! 377: my_mcpy(temp->start+sdlen, p, soodlen); ! 378: sd->refDecr(); ! 379: d = temp; ! 380: return *this; ! 381: } ! 382: ! 383: String& ! 384: String::put(const String& oo) /* append */ ! 385: { ! 386: register Rep *sd = d; ! 387: register Rep *sood = oo.d; ! 388: register sdlen = sd->len; ! 389: register soodlen = sood->len; ! 390: if (sdlen + soodlen > MAXSTRINGLENGTH) ! 391: error(1, "String::put: overflow"); ! 392: if (sdlen == 0) return *this = oo; ! 393: if (soodlen == 0) return *this; ! 394: if (sd->refCount == 1 && !sd->is_constant()) { ! 395: char *oldEnd = sd->start+sdlen; ! 396: if (sd->extend(soodlen)) { ! 397: my_mcpy(oldEnd, sood->start, soodlen); ! 398: return *this; ! 399: } ! 400: } ! 401: Rep *temp = new Rep(sdlen + soodlen); ! 402: my_mcpy(temp->start, sd->start, sdlen); ! 403: my_mcpy(temp->start+sdlen, sood->start, soodlen); ! 404: sd->refDecr(); ! 405: d = temp; ! 406: return *this; ! 407: } ! 408: ! 409: // unget(c) sticks c onto the front of the String ! 410: String& ! 411: String::unget (const char c) ! 412: { ! 413: register Rep *sd = d; ! 414: register sdlen = sd->len; ! 415: switch (sdlen) { ! 416: case 0: ! 417: d = &oneChar[(unsigned char) c]; ! 418: break; ! 419: case 1: ! 420: Rep *rr = new Rep (2); ! 421: *rr->start = c; ! 422: rr->start[1] = *sd->start; ! 423: d = rr; ! 424: break; ! 425: case MAXSTRINGLENGTH: ! 426: error(1, "String::unget: String overflow"); ! 427: break; ! 428: default: ! 429: if (sd->refCount == 1 && !sd->is_constant() && sd->extend(1)) { ! 430: my_Mcpy(sd->start+1, sd->start, sdlen); ! 431: *sd->start = c; ! 432: } else { ! 433: Rep *rr; ! 434: rr = new Rep (sdlen + 1); ! 435: my_mcpy (rr->start+1, sd->start, sdlen); ! 436: *rr->start = c; ! 437: sd->refDecr(); ! 438: d = rr; ! 439: } ! 440: } ! 441: return *this; ! 442: } ! 443: ! 444: String& ! 445: String::unget (const String& oo) /* prepend */ ! 446: { ! 447: register Rep *sd = d; ! 448: register Rep *sood = oo.d; ! 449: register sdlen = sd->len; ! 450: register soodlen = sood->len; ! 451: if (sdlen + soodlen > MAXSTRINGLENGTH) ! 452: error(1, "String.operator-=: overflow"); ! 453: if (soodlen == 0) return *this; ! 454: if (sdlen == 0) return *this = oo; ! 455: if (sd->refCount == 1 && !sd->is_constant()) { ! 456: if (sd->extend(soodlen)) { ! 457: my_Mcpy(sd->start+soodlen, sd->start, sdlen); ! 458: my_mcpy(sd->start, sood->start, soodlen); ! 459: return *this; ! 460: } ! 461: } ! 462: Rep *temp = new Rep(sdlen + soodlen); ! 463: my_mcpy(temp->start, sood->start, soodlen); ! 464: my_mcpy(temp->start+soodlen, sd->start, sdlen); ! 465: sd->refDecr(); ! 466: d = temp; ! 467: return *this; ! 468: } ! 469: ! 470: istream& ! 471: operator>>(istream& ii, String& ss) ! 472: { ! 473: ss = ""; ! 474: if (!(ii >> WS)) ! 475: return ii; ! 476: char c; ! 477: while (ii.get(c)) { ! 478: if (isspace(c)) { ! 479: ii.putback(c); ! 480: break; ! 481: } ! 482: ss.put(c); ! 483: } ! 484: return ii; ! 485: } ! 486: ! 487: String ! 488: sgets(istream& ii) ! 489: { ! 490: char c; ! 491: String ans; ! 492: while (ii.get(c) && c != '\n') ! 493: ans.put(c); ! 494: return ans; ! 495: } ! 496: ! 497: void ! 498: String::dump(char *s) _const ! 499: { ! 500: my_mcpy(s, d->start, d->len); ! 501: s[d->len] = '\0'; ! 502: } ! 503:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.