home *** CD-ROM | disk | FTP | other *** search
- /*
- bbchain.c jdc 11/08/88
-
- % block chain routines
-
- OWL 1.2
- 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
-
- 11/07/89 jdc changed > to >= in offset loop for bbc_work
- 11/09/89 jdc fixed that
- 11/29/89 jmd preened, added casts
- 3/03/90 jdc changed char's to byte's
- 3/19/90 jdc fixed b->len == 0 problem?!?
- 3/28/90 jmd ansi-fied
- 4/28/90 jdc tried to fix the realloc failure problem
- 5/04/90 jdc fixed grow error, preened
- 6/06/90 jmd/pm rewrote loop bblock_close to avoid VMS error
- */
-
- #include "oakhead.h"
-
- #include "bbcdecl.h"
-
- bbc_type bbc_Open(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);
- }
- if (bsize % 2 != 0) {
- bsize += 1;
- }
-
- if (asize > bsize) {
- asize = bsize;
- }
- else if (bsize % asize != 0) {
- asize = bsize / 2;
- }
-
- bbc->esize = esize;
- bbc->bsize = bsize * esize;
- bbc->asize = asize * esize;
-
- 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_type bbc, long offset, char *line, byte chr, long len, int mode)
- /*
- if line == NULL then bbset, else bbcpy
-
- 'offset' is in ELEMENTS
- 'len' is in ELEMENTS
- 'mode' either BBC_SET, BBC_INSERT, or BBC_GET
- */
- {
- bblock_type b;
- char *t;
- unsigned int end, 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) { /* find the block we want */
- if (b->next == NULL) { /* point the the end */
- break;
- }
- else {
- offset -= b->len;
- b = b->next;
- }
- }
-
- if (mode == BBC_ENDINS) {
- if (offset == b->len && b->next != NULL) {
- /* begin filling in the next block */
-
- offset -= b->len;
- b = b->next;
- }
- mode = BBC_INSERT;
- }
- else if (mode == BBC_INSERT && offset == 0L && b->prev != NULL
- && b->prev->len + len <= bbc->bsize) {
-
- /* try to back-fill in not an implict ENDINS */
-
- 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 (mode == BBC_INSERT) {
-
- if ((unsigned int)offset == bbc->bsize && b->next != NULL) {
- offset = 0L;
- b = b->next;
- }
- i = b->len + (unsigned int)len;
-
- if (i > bbc->bsize) {
-
- if (bblock_split(bbc, b, offset) == NULL
- || bblock_grow(bbc, b, len) == NULL) {
-
- return(0L);
- }
- }
- else {
- if (i > b->size && bblock_grow(bbc, b, len) == NULL) {
- return(0L);
- }
- t = b->start + (unsigned int)offset;
- memmove((VOID *) (t + (unsigned int)len), t, b->len - (unsigned int)offset);
- b->len += (unsigned int)len;
- }
- }
-
- while (TRUE) { /* loop through blocks */
-
- t = b->start;
- i = (unsigned int)offset;
- end = (mode == BBC_INSERT || b->next == NULL) ? b->size : b->len;
- if (end > i + (unsigned int)len) {
- end = i + (unsigned int)len;
- }
-
- if (line == NULL) {
- for (; i < end; i++, count++) {
- t[i] = chr;
- }
- }
- else if (mode == BBC_GET) {
- for (; i < end; i++, count++) {
- line[(unsigned int)count] = t[i];
- }
- }
- else { /* mode == BBC_SET || BBC_INSERT */
- for (; i < end; i++, count++) {
- t[i] = line[(unsigned int)count];
- }
- }
-
- if (i > b->len) {
- b->len = i;
- }
-
- len -= (i - offset);
-
- if (len <= 0) { /* done*/
- 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_type bbc, long offset, byte attr, long len)
- /*
- 'offset' and 'len' are 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_type bbc, long offset, long len)
- /*
- returns: number of elements deleted
- 'offset' and 'len' are in ELEMENTS
- */
- {
- 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_type bbc)
- {
- bbc->b = bblock_rewind(bbc->b);
-
- bblock_close(bbc->b, BBC_BELOW);
-
- ofree(OA_BBCHAIN, (VOID *)bbc);
- }
-
- bblock_type bblock_open(bbc_type bbc, long size, bblock_type prev, byte attr)
- /*
- */
- {
- bblock_type b, top;
- long asize;
- int first = TRUE;
-
- top = prev;
- if (size > 0 && size % bbc->asize > 0) {
- /* grow by muliples of asize */
- asize = (size / bbc->asize + 1) * bbc->asize;
- }
-
- while (size > 0L) {
-
- asize = size;
- if (asize > (long)bbc->bsize) {
- asize = (long)bbc->bsize;
- }
- 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_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, doesn't work!
- * b->start = (char *) orealloc(OA_BBDATA, b->start, b->size);
- * let's try something else
- */
- if (b->next != NULL) {
- b->next->prev = b->prev;
- }
- if (b->prev != NULL) {
- b->prev->next = b->next;
- }
- if (bbc->b == b) {
- bbc->b = (b->prev == NULL) ? b->next:b->prev;
- }
- ofree(OA_BBLOCK, (VOID *)b);
- 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_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((VOID *) b->start, (VOID *) (top->start + (unsigned int)offset), (unsigned int)len);
- b->len = (unsigned int)len;
- top->len = (unsigned int)offset;
- }
- }
- return(b);
- }
-
- void bblock_close(bblock_type b, int flag)
- /*
- flag == BBC_SINGLE: close only b,
- else BBC_BELOW : close b and below.
- */
- {
- bblock_type next;
-
- 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;
- }
-
- next = b->next;
- ofree(OA_BBDATA, (VOID *)b->start);
- ofree(OA_BBLOCK, (VOID *)b);
- b = next;
- }
- }
-
- bblock_type bblock_rewind(bblock_type b)
- /*
- sets b to the first block in its chain
- */
- {
- while (b->prev != NULL) {
- b = b->prev;
- }
- return(b);
- }
-
- int bbpeek(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);
- }
-
-
-