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