Annotation of researchv10no/cmd/cfront/libstring/rep.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.