/* $Id: tblock.cc,v 1.3 1997/03/21 20:34:11 dps Exp $ */ /* Dynamically growinf text block */ #ifdef HAVE_CONFIG_H #include "config.h" #endif /* HAVE_CONFIG_H */ #include #include #ifdef HAVE_STRING_H #include #endif /* HAVE_STRING_H */ #ifdef HAVE_STRINGS_H #include #endif /* HAVE_STRINGS_H */ #include #include "tblock.h" const struct tblock::block tblock::dummy_init={0,0,NULL,NULL}; tblock::~tblock(void) { struct block *blk, *nblk; blk=dummy_block.next; while (blk!=NULL) { nblk=blk->next; free(blk->text); free(blk); blk=nblk; } } void tblock::zero(void) { struct block *blk, *nblk; blk=dummy_block.next; while (blk!=NULL) { nblk=blk->next; free(blk->text); free(blk); blk=nblk; } dummy_block=dummy_init; head=&dummy_block; } int tblock::add(char c) { struct block *blk, *nb; blk=head; if (blk->limit==blk->pos) { if ((nb=(struct block *) malloc(sizeof(struct block)))==NULL) return 0; if ((nb->text=(char *) malloc(block_size))==NULL) { free(nb); return 0; } nb->limit=1024; nb->pos=0; nb->next=NULL; head->next=nb; head=nb; } head->text[(head->pos)++]=c; return 1; } int tblock::add(const char *s, int len) { struct block *nb; const char *t; int size; if (*s=='\0') return 1; t=s; while (len>0) { if (head->limit==head->pos) { if ((nb=(struct block *) malloc(sizeof(struct block)))==NULL) return 0; if ((nb->text=(char *) malloc(block_size))==NULL) { free(nb); return 0; } nb->limit=block_size; nb->pos=0; nb->next=NULL; head->next=nb; head=nb; } size=head->limit-head->pos; if (size>len) size=len; memcpy(head->text+head->pos, t, size); head->pos+=size; len-=size; t+=size; } return 1; } const char *tblock::collect(void) const { struct block *blk; char *s,*t; size_t size; size=0; blk=dummy_block.next; while (blk!=NULL) { size+=blk->pos; blk=blk->next; } if ((t=(char *) malloc(size+1))==NULL) { cerr<<"tblock::collect malloc failure\n"; return NULL; } s=t; blk=dummy_block.next; while (blk!=NULL) { memcpy(s, blk->text, blk->pos); s+=blk->pos; blk=blk->next; } *s='\0'; return t; } tblock &tblock::operator=(const tblock &arg) { struct block *nb,*blk; const char *s; blk=dummy_block.next; while (blk!=NULL) { nb=blk->next; free(blk->text); free(blk); blk=nb; } if ((s=arg.collect())==NULL) { cerr<<"tblock:operator= fatal malloc failure\n"; exit(2); } if ((nb=(struct block *) malloc(sizeof(struct block)))==NULL) { cerr<<"tblock:operator= fatal malloc failure\n"; exit(2); } nb->limit=strlen(s)+1; // Limit includes '\0' nb->pos=strlen(s); // Do include '\0' in used characters nb->text=(char *) s; nb->next=NULL; dummy_block.next=nb; head=nb; return *this; } tblock::tblock(const tblock &cpy) { struct block *nb; const char *s; if ((s=cpy.collect())==NULL) { cerr<<"tblock::tblock(const tblock &) fatal malloc failure\n"; exit(2); } if ((nb=(struct block *) malloc(sizeof(struct block)))==NULL) { cerr<<"tblock::tblock(const tblock &) fatal malloc failure\n"; exit(2); } nb->limit=strlen(s)+1; // Inlcude '\0' in limit nb->pos=strlen(s); // DO not include '\0' in used nb->text=(char *) s; nb->next=NULL; dummy_block.next=nb; dummy_block.pos=0; dummy_block.limit=0; dummy_block.text=NULL; head=nb; } tblock::operator const char *() { struct block *nb; const char *s; if (dummy_block.next==head) { *(head->text+head->pos)='\0'; return ((const char *) (head->text)); } if ((s=this->collect())==NULL) { cerr<<"tblock::const char * fatal malloc failure\n"; exit(2); } if ((nb=(struct block *) malloc(sizeof(struct block)))==NULL) { cerr<<"tblock::const char * fatal malloc failure\n"; exit(2); } nb->limit=strlen(s)+1; // Inlcude '\0' in limit nb->pos=strlen(s); // DO not include '\0' in used nb->text=(char *) s; nb->next=NULL; this->zero(); // Wipe current data dummy_block.next=nb; dummy_block.pos=0; dummy_block.limit=0; dummy_block.text=NULL; head=nb; return s; }