This is itbuff.c in view mode; [Download] [Up]
/* * tbuff.c * * Manage dynamic temporary buffers. * Note that some temp-buffs are never freed, for speed * * To do: add 'itb_ins()' and 'itb_del()' to support cursor-level command * editing. * * $Header: /usr2/foxharp/src/pgf/vile/RCS/itbuff.c,v 1.10 1996/08/13 02:10:07 pgf Exp $ * */ #include "estruct.h" #include "edef.h" #define NCHUNK NLINE /*******(testing)************************************************************/ #if NO_LEAKS typedef struct _itb_list { struct _itb_list *link; ITBUFF *buff; } ITB_LIST; static ITB_LIST *all_tbuffs; #define AllocatedBuffer(q) itb_remember(q); #define FreedBuffer(q) itb_forget(q); static void itb_remember(ITBUFF *p) { register ITB_LIST *q = typealloc(ITB_LIST); q->buff = p; q->link = all_tbuffs; all_tbuffs = q; } static void itb_forget(ITBUFF *p) { register ITB_LIST *q, *r; for (q = all_tbuffs, r = 0; q != 0; r = q, q = q->link) if (q->buff == p) { if (r != 0) r->link = q->link; else all_tbuffs = q->link; free((char *)q); break; } } void itb_leaks(void) { while (all_tbuffs != 0) { ITBUFF *q = all_tbuffs->buff; FreedBuffer(q); itb_free(&q); } } #else #define AllocatedBuffer(q) #define FreedBuffer(q) #endif /*******(initialization)*****************************************************/ /* * ensure that the given temp-buff has as much space as specified */ ITBUFF * itb_alloc(ITBUFF **p, ALLOC_T n) { register ITBUFF *q = *p; if (q == 0) { q = *p = typealloc(ITBUFF); q->itb_data = typeallocn(int, q->itb_size = n); q->itb_used = 0; q->itb_last = 0; q->itb_endc = abortc; AllocatedBuffer(q) } else if (n >= q->itb_size) { q->itb_data = typereallocn(int, q->itb_data, q->itb_size = (n*2)); } return q; } /* * (re)initialize a temp-buff */ ITBUFF * itb_init(ITBUFF **p, int c) { register ITBUFF *q = *p; if (q == 0) q = itb_alloc(p, NCHUNK); q->itb_used = 0; q->itb_last = 0; q->itb_endc = c; /* code to return if no-more-data */ return (*p = q); } /* * deallocate a temp-buff */ void itb_free(ITBUFF **p) { register ITBUFF *q = *p; if (q != 0) { FreedBuffer(q) free((char *)(q->itb_data)); free((char *)q); } *p = 0; } /*******(storage)************************************************************/ /* * put a character c at the nth position of the temp-buff. make it the last. */ static ITBUFF * itb_put(ITBUFF **p, ALLOC_T n, int c) { register ITBUFF *q; if ((q = itb_alloc(p, n+1)) != 0) { q->itb_data[n] = c; q->itb_used = n+1; } return q; } /* * stuff the nth character into the temp-buff -- assumes space already there * it's sort of the opposite of itb_peek */ void itb_stuff(ITBUFF *p, int c) { if (p->itb_last < p->itb_used) p->itb_data[p->itb_last] = c; else p->itb_endc = c; } /* * append a character to the temp-buff */ ITBUFF * itb_append(ITBUFF **p, int c) { register ITBUFF *q = *p; register ALLOC_T n = (q != 0) ? q->itb_used : 0; return itb_put(p, n, c); } /* * Copy one temp-buff to another */ ITBUFF * itb_copy(ITBUFF **d, ITBUFF *s) { ITBUFF *p; if (s != 0) { if ((p = itb_init(d, s->itb_endc)) != 0) { int *ptr = s->itb_data; ALLOC_T len = s->itb_used; while ((len-- != 0) && itb_append(&p, *ptr++) != 0) ; } } else p = itb_init(d, abortc); return p; } /* * append a binary data to the temp-buff */ ITBUFF * itb_bappend(ITBUFF **p, const char *s, ALLOC_T len) { while ((len-- != 0) && itb_append(p, (int)(*s++)) != 0) ; return *p; } #if NEEDED /* * append a string to the temp-buff */ ITBUFF * itb_sappend( ITBUFF **p, const char *s) { if (!s) return *p; while (*s && itb_append(p, (int)(*s++)) != 0) ; return *p; } void itb_delete(ITBUFF *p, ALLOC_T cnt) { int *from, *to, *used; to = &p->itb_data[p->itb_last]; from = to + cnt; used = &p->itb_data[p->itb_used]; if (from >= used) { p->itb_used = p->itb_last; return; } while (from < used) { *to++ = *from++; } p->itb_used -= cnt; } ITBUFF * itb_insert(ITBUFF **p, int c) { register ITBUFF *q = *p; int *last, *to; /* force enough room for another character */ itb_put(p, q->itb_used, 0 /* any value */ ); /* copy up */ to = &q->itb_data[q->itb_used-1]; last = &q->itb_data[q->itb_last]; while (to > last) { *to = *(to-1); to--; } /* put in the new one */ itb_stuff(q, c); return *p; } #endif /* NEEDED */ /*******(retrieval)************************************************************/ /* * get the nth character from the temp-buff */ int itb_get(ITBUFF *p, ALLOC_T n) { register int c = abortc; if (p != 0) c = (n < p->itb_used) ? p->itb_data[n] : p->itb_endc; return c; } #if NEEDED /* * undo the last 'itb_put' */ void itb_unput(ITBUFF *p) { if (p != 0 && p->itb_used != 0) p->itb_used -= 1; } #endif /*******(iterators)************************************************************/ /* * Reset the iteration-count */ static ALLOC_T itb_seek(ITBUFF *p, ALLOC_T seekto, int whence) { ALLOC_T olast; if (p == 0) return 0; olast = p->itb_last; if (whence == 0) p->itb_last = seekto; else if (whence == 1) p->itb_last += seekto; else if (whence == 2) p->itb_last = p->itb_used - seekto; return olast; } void itb_first(ITBUFF *p) { (void)itb_seek(p, 0, 0); } /* * Returns true iff the iteration-count has not gone past the end of temp-buff. */ int itb_more(ITBUFF *p) { return (p != 0) ? (p->itb_last < p->itb_used) : FALSE; } /* * get the next character from the temp-buff */ int itb_next(ITBUFF *p) { if (p != 0) return itb_get(p, p->itb_last++); return abortc; } /* * get the last character from the temp-buff, and shorten * (opposite of itb_append) */ int itb_last(ITBUFF *p) { int c; if (p != 0 && p->itb_used > 0) { c = itb_get(p, p->itb_used-1); p->itb_used--; return c; } return abortc; } #if NEEDED /* * undo a itb_next */ void itb_unnext(ITBUFF *p) { if (p == 0) return; if (p->itb_last > 0) p->itb_last--; } #endif /* * get the next character from the temp-buff w/o incrementing index */ int itb_peek(ITBUFF *p) { if (p != 0) return itb_get(p, p->itb_last); return abortc; } /*******(bulk-data)************************************************************/ /* * returns the length of the data */ ALLOC_T itb_length(ITBUFF *p) { return (p != 0) ? p->itb_used : 0; }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.