home *** CD-ROM | disk | FTP | other *** search
- /*
- bbchain.c jdc 11/08/88
-
- % block chain routines
-
- OWL 1.1
- Copyright (c) 1988, by Oakland Group, Inc.
- ALL RIGHTS RESERVED.
-
- Revision History:
- -----------------
- 12/13/88 jmd Added casts to orealloc call
- 6/14/89 gam Added some comments
- 7/20/89 jdc Added b->next->row = -1L in bbc_work, offset == 0
- */
-
- #include "oakhead.h"
-
- #include "bbcdecl.h"
-
- bbc_type bbc_Open(esize, bsize, asize)
- unsigned int esize;
- unsigned int bsize;
- unsigned int asize;
- {
- bbc_type bbc;
-
- if ((bbc = (bbc_type) omalloc(OA_BBCHAIN, sizeof(bbc_struct))) == NULL) {
- return(NULL);
- }
- bbc->esize = esize;
- bbc->bsize = bsize * esize;
- bbc->asize = asize * esize;
- if ( bbc->asize > bbc->bsize ) {
- bbc->asize = bbc->bsize;
- }
- if ( (bbc->b = bblock_open(bbc, (long)bbc->asize, NULL, 0)) == NULL ) {
- ofree(OA_BBCHAIN, (VOID *)bbc);
- return(NULL);
- }
- return(bbc);
- }
-
- long bbc_work(bbc, offset, line, chr, len, mode)
- bbc_type bbc;
- long offset; /* in ELEMENTS */
- char *line, chr;
- long len; /* in ELEMENTS */
- int mode; /* BBC_SET, BBC_INSERT, BBC_GET */
- /*
- if line == NULL then bbset, else bbcpy
- */
- {
- bblock_type b;
- char *t;
- unsigned int end;
- int i;
- long count = 0L;
-
- if ( len <= 0L ) return(0L);
-
- len *= bbc->esize;
- offset *= bbc->esize;
-
- b = bbc->b;
- offset += (long)b->off;
-
- while ( offset > b->len ) {
- if ( b->next == NULL ) {
- break;
- }
- else {
- offset -= b->len;
- b = b->next;
- }
- }
- if ( mode == BBC_INSERT ) {
- if ( offset == 0L && b->prev != NULL ) {
- if ( b->prev->len + len <= bbc->bsize ) {
- b = b->prev;
- offset = b->len;
- if ( bbc->b == b->next ) {
- bbc->b = b;
- b->row = b->next->row;
- b->off = b->len;
- b->next->row = -1L;
- }
- }
- }
- if ( (unsigned int)offset == bbc->bsize && b->next != NULL ) {
- offset = 0L;
- b = b->next;
- }
- if ( b->len + (unsigned int)len > bbc->bsize ) {
- if ( bblock_split(bbc, b, offset) == NULL
- || bblock_grow(bbc, b, len) == NULL ) {
- return(0L);
- }
- /* if ( b->off >= b->len ) {} ??? */
- }
- else {
- if ( bblock_grow(bbc, b, len) == NULL ) {
- return(0L);
- }
- t = b->start + (unsigned int)offset;
- memmove(t + (unsigned int)len, t, b->len - (unsigned int)offset);
- b->len += (unsigned int)len;
- }
- }
- while (TRUE) {
- t = b->start;
- end = b->len;
- if ( mode == BBC_GET )
- ;
- else if ( mode == BBC_INSERT || b->next == NULL )
- end = b->size;
- if ( (long)end > offset + (len - count))
- end = (unsigned int)(offset + (len - count));
- else if ( end - offset < bbc->esize )
- end = (unsigned int)offset;
-
- if ( line == NULL ) {
- for ( i = (unsigned int)offset; i < end; i++, count++ ) {
- t[i] = chr;
- }
- }
- else if ( mode == BBC_GET ) {
- for ( i = (unsigned int)offset; i < end; i++, count++ ) {
- line[(unsigned int)count] = t[i];
- }
- }
- else {
- for ( i = (unsigned int)offset; i < end; i++, count++ ) {
- t[i] = line[(unsigned int)count];
- }
- }
- if ( i > b->len )
- b->len = i;
- if ( count >= len )
- break;
- if ( b->next == NULL ) {
- if ( mode == BBC_GET ) {
- break;
- }
- if ( bblock_grow(bbc, b, len) == NULL ) {
- return(count);
- }
- offset = (long)b->len;
- }
- else {
- b = b->next;
- offset = 0L;
- }
- }
- return(count);
- }
-
- boolean bbc_Attr(bbc, offset, attr, len)
- bbc_type bbc;
- long offset; /* in ELEMENTS */
- byte attr;
- long len; /* in ELEMENTS */
- {
- bblock_type b;
-
- if ( len <= 0L ) return(TRUE);
-
- len *= bbc->esize;
- offset *= bbc->esize;
-
- b = bbc->b;
- offset += (long)b->off;
-
- while ( offset >= b->len ) {
- if ( b->next == NULL ) {
- break;
- }
- else {
- offset -= b->len;
- b = b->next;
- }
- }
-
- if ( attr != b->attr && offset > 0 ) {
- if ( (b = bblock_split(bbc, b, offset)) == NULL ) {
- return(FALSE);
- }
- if ( b->prev->off >= b->prev->len ) {
- b->off = b->prev->off - b->prev->len;
- b->row = b->prev->row;
- b->prev->row = -1;
- b->prev->off = 0;
- if ( bbc->b == b->prev ) {
- bbc->b = b;
- }
- }
- }
- while ( b != NULL && len > 0L ) {
- if ( b->attr != attr && len < (long)b->len ) {
- if ( bblock_split(bbc, b, len) == NULL ) {
- return(FALSE);
- }
- }
- b->attr = attr;
- len -= (long)b->len;
- b = b->next;
- }
- return(TRUE);
- }
-
- long bbc_Del(bbc, offset, len)
- bbc_type bbc;
- long offset; /* in ELEMENTS */
- long len; /* in ELEMENTS */
- /*
- returns: number of elements deleted
- */
- {
- bblock_type b, f;
- long count;
-
- if ( len <= 0L ) return(0L);
-
- len *= bbc->esize;
- offset *= bbc->esize;
-
- b = bbc->b;
- offset += (long)b->off;
-
- while ( offset >= b->len ) {
- if ( b->next == NULL ) {
- break;
- }
- else {
- offset -= b->len;
- b = b->next;
- }
- }
-
- if ( offset > 0 ) {
- if ( (b = bblock_split(bbc, b, offset)) == NULL ) {
- return(0L);
- }
- if ( b->prev->off >= b->prev->len ) {
- b->off = b->prev->off - b->prev->len;
- b->row = b->prev->row;
- b->prev->row = -1;
- b->prev->off = b->prev->len - 1;
- if ( bbc->b == b->prev ) {
- bbc->b = b;
- }
- }
- }
- count = 0L;
- while ( b != NULL && len > 0 ) {
- if ( len < (long)b->len ) {
- if ( bblock_split(bbc, b, len) == NULL ) {
- return(0L);
- }
- }
- count += (long)b->len;
- len -= (long)b->len;
-
- if ( b->prev == NULL ) {
- if ( b->next == NULL ) {
- /* don't free the last block */
- b->len = 0;
- b->off = 0;
- b->row = 0L;
- break;
- }
- }
- else {
- b->prev->next = b->next;
- }
- if ( b->next != NULL ) {
- b->next->prev = b->prev;
- }
- f = b;
- b = b->next;
- if ( f == bbc->b ) {
- if ( b != NULL ) {
- b->row = f->row;
- b->off = 0;
- bbc->b = b;
- }
- else {
- bbc->b = f->prev;
- }
- }
- ofree(OA_BBDATA, (VOID *)f->start);
- ofree(OA_BBLOCK, (VOID *)f);
- }
- return(count/(long)bbc->esize);
- }
-
- void bbc_Close(bbc)
- bbc_type bbc;
- {
- bbc->b = bblock_rewind(bbc->b);
-
- bblock_close(bbc->b, BBC_BELOW);
-
- ofree(OA_BBCHAIN, (VOID *)bbc);
- }
-
- bblock_type bblock_open(bbc, size, prev, attr)
- bbc_type bbc;
- long size;
- bblock_type prev;
- byte attr;
- /*
- */
- {
- bblock_type b, top;
- long asize;
- int first = TRUE;
-
- top = prev;
-
- while ( size > 0L ) {
-
- asize = size;
- if ( asize > (long)bbc->bsize ) {
- asize = (long)bbc->bsize;
- }
- else if ( asize < (long)bbc->asize ) {
- asize = (long)bbc->asize;
- }
- if ((b = (bblock_type) omalloc(OA_BBLOCK, sizeof(struct bblock_struct))) == NULL) {
- return(NULL);
- }
- if ((b->start = (char *) omalloc(OA_BBDATA, (unsigned int)asize)) == NULL ) {
- ofree(OA_BBLOCK, (VOID *)b);
- return(NULL);
- }
- if ( first ) {
- top = b;
- first = FALSE;
- }
- b->prev = prev; /* insert new bblock into chain */
- if (prev == NULL) {
- b->next = NULL;
- }
- else {
- b->next = prev->next;
- if (prev->next != NULL)
- prev->next->prev = b;
- prev->next = b;
- }
- b->size = (unsigned int)asize;
- b->len = 0;
- b->off = 0;
- b->row = -1L;
- b->attr = attr;
-
- size -= asize;
- prev = b;
- }
- return(top);
- }
-
- bblock_type bblock_grow(bbc, b, size)
- bbc_type bbc;
- bblock_type b;
- long size;
- /*
- */
- {
- long asize;
-
- size += b->len;
- if ( size <= (long)b->size )
- return(b);
-
- if ( size > b->size ) {
-
- asize = size;
- if ( asize > (long)bbc->bsize ) {
- asize = (long)bbc->bsize;
- }
- else if ( asize < (long)bbc->asize ) {
- asize = (long)bbc->asize;
- }
- if ((b->start = (char *) orealloc(OA_BBDATA, b->start, (unsigned int)asize)) == NULL ) {
- /* try to recoup */
- b->start = (char *) orealloc(OA_BBDATA, b->start, b->size);
- return(NULL);
- }
- b->size = (unsigned int)asize;
- }
- size -= (long)b->size;
-
- if ( bblock_open(bbc, size, b, b->attr) == NULL ) {
- return(NULL);
- }
- return(b);
- }
-
- bblock_type bblock_split(bbc, top, offset)
- bbc_type bbc;
- bblock_type top;
- long offset;
- /*
- */
- {
- bblock_type b;
- struct bblock_struct temp;
- long len;
- int copy;
-
- b = top;
- if ( (len = (long)top->len - offset) > 0 ) {
-
- if ( (b = bblock_open(bbc, len, top, top->attr)) == NULL ) {
- return(NULL);
- }
- if ( offset == 0 ) {
- /* swap blocks' innards */
- copy = sizeof(struct bblock_struct) - 2*sizeof(bblock_type);
- memcpy((VOID *)&(temp.start), (VOID *)&(b->start), copy);
- memcpy((VOID *)&(b->start), (VOID *)&(top->start), copy);
- memcpy((VOID *)&(top->start), (VOID *)&(temp.start), copy);
- top->row = b->row;
- }
- else {
- memcpy(b->start, top->start + (unsigned int)offset, (unsigned int)len);
- b->len = (unsigned int)len;
- top->len = (unsigned int)offset;
- }
- }
- return(b);
- }
-
- void bblock_close(b, flag)
- bblock_type b;
- int flag;
- /*
- flag == BBC_SINGLE: close only b,
- else BBC_BELOW : close b and below.
- */
- {
- bblock_type f;
-
- while ( b != NULL ) {
-
- if ( b->next != NULL ) {
- b->next->prev = b->prev;
- }
- if ( b->prev != NULL ) {
- b->prev->next = b->next;
- }
- if ( flag == BBC_SINGLE ) {
- break;
- }
- f = b;
- b = b->next;
- ofree(OA_BBDATA, (VOID *)f->start);
- ofree(OA_BBLOCK, (VOID *)f);
- }
- }
-
- bblock_type bblock_rewind(b)
- bblock_type b;
- /*
- sets b to the first block in its chain
- */
- {
- while ( b->prev != NULL ) {
- b = b->prev;
- }
- return(b);
- }
-
- int bbpeek(bp)
- bbpeek_type bp;
- /*
- get a peek at strings in blocks
-
- returns valid ptr length
- */
- {
- int ret;
- bblock_type b;
-
- b = bp->b;
- while ( bp->off < 0 ) {
- if ( b->prev == NULL ) {
- return(0);
- }
- else {
- b = b->prev;
- bp->off += b->len;
- }
- }
- while ( (ret = (int)b->len - bp->off) <= 0 ) {
- if ( b->next == NULL ) {
- return(0);
- }
- else {
- bp->off -= b->len;
- b = b->next;
- }
- }
- if ( bp->len < (long)ret )
- ret = (int)(bp->len);
- bp->p = b->start + bp->off;
- bp->b = b;
-
- return(ret);
- }
-
-