This is tbuff.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 'tb_ins()' and 'tb_del()' to support cursor-level command * editing. * * $Header: /usr2/foxharp/src/pgf/vile/RCS/tbuff.c,v 1.27 1996/08/13 02:10:07 pgf Exp $ * */ #include "estruct.h" #include "edef.h" #define NCHUNK NLINE /*******(testing)************************************************************/ #if NO_LEAKS typedef struct _tb_list { struct _tb_list *link; TBUFF *buff; } TB_LIST; static TB_LIST *all_tbuffs; #define AllocatedBuffer(q) tb_remember(q); #define FreedBuffer(q) tb_forget(q); static void tb_remember(TBUFF *p) { register TB_LIST *q = typealloc(TB_LIST); q->buff = p; q->link = all_tbuffs; all_tbuffs = q; } static void tb_forget(TBUFF *p) { register TB_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 tb_leaks(void) { while (all_tbuffs != 0) { TBUFF *q = all_tbuffs->buff; FreedBuffer(q); tb_free(&q); } } #else #define AllocatedBuffer(q) #define FreedBuffer(q) #endif /*******(initialization)*****************************************************/ /* * ensure that the given temp-buff has as much space as specified */ TBUFF * tb_alloc(TBUFF **p, ALLOC_T n) { register TBUFF *q = *p; if (q == 0) { q = *p = typealloc(TBUFF); q->tb_data = typeallocn(char, q->tb_size = n); q->tb_used = 0; q->tb_last = 0; q->tb_endc = abortc; AllocatedBuffer(q) } else if (n >= q->tb_size) { q->tb_data = typereallocn(char, q->tb_data, q->tb_size = (n*2)); } return q; } /* * (re)initialize a temp-buff */ TBUFF * tb_init(TBUFF **p, int c) { register TBUFF *q = *p; if (q == 0) q = tb_alloc(p, NCHUNK); q->tb_used = 0; q->tb_last = 0; q->tb_endc = c; /* code to return if no-more-data */ return (*p = q); } /* * deallocate a temp-buff */ void tb_free(TBUFF **p) { register TBUFF *q = *p; if (q != 0) { FreedBuffer(q) free(q->tb_data); free((char *)q); } *p = 0; } /*******(storage)************************************************************/ /* * put a character c at the nth position of the temp-buff */ static TBUFF * tb_put(TBUFF **p, ALLOC_T n, int c) { register TBUFF *q; if ((q = tb_alloc(p, n+1)) != 0) { q->tb_data[n] = (char)c; q->tb_used = n+1; } return q; } #if NEEDED /* * stuff the nth character into the temp-buff -- assumes space already there * it's sort of the opposite of tb_peek */ void tb_stuff(TBUFF *p, int c) { if (p->tb_last < p->tb_used) p->tb_data[p->tb_last] = c; else p->tb_endc = c; } #endif /* * append a character to the temp-buff */ TBUFF * tb_append(TBUFF **p, int c) { register TBUFF *q = *p; register ALLOC_T n = (q != 0) ? q->tb_used : 0; return tb_put(p, n, c); } /* * Copy one temp-buff to another */ TBUFF * tb_copy(TBUFF **d, TBUFF *s) { register TBUFF *p; if (s != 0) { if ((p = tb_init(d, s->tb_endc)) != 0) p = tb_bappend(d, s->tb_data, s->tb_used); } else p = tb_init(d, abortc); return p; } /* * append a binary data to the temp-buff */ TBUFF * tb_bappend(TBUFF **p, const char *s, ALLOC_T len) { while ((len-- != 0) && tb_append(p, (int)(*s++)) != 0) ; return *p; } /* * append a string to the temp-buff */ TBUFF * tb_sappend(TBUFF **p, const char *s) { if (!s) return *p; while (*s && tb_append(p, (int)(*s++)) != 0) ; return *p; } /* * copy a string to the temp-buff, including a null */ TBUFF * tb_scopy(TBUFF **p, const char *s) { (void) tb_init(p, EOS); (void) tb_sappend(p, s); return tb_append(p, EOS); } /*******(retrieval)************************************************************/ #if DISP_X11 /* * get the nth character from the temp-buff */ int tb_get(TBUFF *p, ALLOC_T n) { register int c = abortc; if (p != 0) c = (n < p->tb_used) ? p->tb_data[n] : p->tb_endc; return char2int(c); } #endif /* * undo the last 'tb_put' */ void tb_unput(TBUFF *p) { if (p != 0 && p->tb_used != 0) p->tb_used -= 1; } /*******(iterators)************************************************************/ #if NEEDED /* * Reset the iteration-count */ void tb_first(TBUFF *p) { if (p != 0) p->tb_last = 0; } #endif #if DISP_X11 /* * Returns true iff the iteration-count has not gone past the end of temp-buff. */ int tb_more(TBUFF *p) { return (p != 0) ? (p->tb_last < p->tb_used) : FALSE; } /* * get the next character from the temp-buff */ int tb_next(TBUFF *p) { if (p != 0) return tb_get(p, p->tb_last++); return abortc; } #endif #if NEEDED /* * undo a tb_next */ void tb_unnext(TBUFF *p) { if (p == 0) return; if (p->tb_last > 0) p->tb_last--; } /* * get the next character from the temp-buff w/o incrementing index */ int tb_peek(TBUFF *p) { if (p != 0) return tb_get(p, p->tb_last); return abortc; } #endif /* NEEDED */ /*******(bulk-data)************************************************************/ /* * returns a pointer to data, assumes it is one long string */ char * tb_values(TBUFF *p) { return (p != 0) ? p->tb_data : 0; } /* * returns the length of the data */ ALLOC_T tb_length(TBUFF *p) { return (p != 0) ? p->tb_used : 0; }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.