|
|
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.