Annotation of researchv10no/cmd/cfront/libstring/rep.c, revision 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.