#include #include #include #include #define MAXLINE 65536 #include "linesender.h" struct linesender { void (*send)(const void *, int, void *); void *arg; char *b; int a; int l; } ; LINESENDER *linesender_open(void (*send)(const void *, int, void *), void *arg) { LINESENDER *m; m = malloc(sizeof(LINESENDER)); m->send = send; m->arg = arg; m->b = 0; m->a = 0; return(m); } void linesender_close(LINESENDER *m) { free(m); } static void append(LINESENDER *m, const void *data, int len) { if (len < 1) return; if (m->l+len > MAXLINE) abort(); if (m->l+len > m->a) m->b = realloc(m->b,m->a=m->l+len); bcopy(data,m->b+m->l,len); m->l += len; } void send_line(LINESENDER *m, ...) { va_list ap; send_open(m); va_start(ap,m); send_append_v(m,ap); va_end(ap); send_send(m); } void send_append(LINESENDER *m, ...) { va_list ap; va_start(ap,m); send_append_v(m,ap); va_end(ap); } void send_open(LINESENDER *m) { m->l = 0; } void send_send(LINESENDER *m) { char lentext[16]; int lenlen; lenlen = (m->l > 0) ? sprintf(&lentext[0],"%d",m->l) : 0; lentext[lenlen++] = '~'; (*m->send)(&lentext[0],lenlen,m->arg); (*m->send)(m->b,m->l,m->arg); } void send_append_v(LINESENDER *m, va_list ap) { int key; while (1) { key = va_arg(ap,int); switch (key) { case SL__END: return; break; case SL__BLOCK: { const void *data; int len; data = va_arg(ap,const void *); len = va_arg(ap,int); if (len == SL_STRLEN) len = strlen(data); if (len < 1) break; append(m,data,len); } break; case SL__STRING: { const void *data; int len; char lentext[16]; int lenlen; data = va_arg(ap,const void *); len = va_arg(ap,int); if (len == SL_STRLEN) len = strlen(data); lenlen = (len > 0) ? sprintf(&lentext[0],"%d",len) : 0; append(m,&lentext[0],lenlen); append(m,"\"",1); append(m,data,len); } break; case SL__OCTET: { /* XXX C demands we break abstract type-correctness here... */ unsigned char v; v = va_arg(ap,/*unsigned char*/int); append(m,&v,1); } break; case SL__NUMBER: { unsigned int v; char vtext[16]; int vlen; v = va_arg(ap,unsigned int); vlen = (v > 0) ? sprintf(&vtext[0],"%u",v) : 0; append(m,&vtext[0],vlen); append(m,"#",1); } break; default: abort(); break; } } } const void *sl__const_void_p(const void *arg) { return(arg); } int sl__int(int arg) { return(arg); } unsigned int sl__unsigned_int(unsigned int arg) { return(arg); } unsigned char sl__unsigned_char(unsigned char arg) { return(arg); }