#include "vchdr.h"
static char* Version = "\r\n@(#)$Id: vcodex (AT&T Shannon Laboratory - Kiem-Phong Vo) 2008-11-04 $\r\n";
#if __STD_C
Vcodex_t* vcopen(Vcdisc_t* disc, Vcmethod_t* meth, Void_t* init,
Vcodex_t* coder, int flags)
#else
Vcodex_t* vcopen(disc, meth, init, coder, flags)
Vcdisc_t* disc;
Vcmethod_t* meth;
Void_t* init;
Vcodex_t* coder;
int flags;
#endif
{
Vcodex_t* vc = (Vcodex_t*)Version;
if((flags&VC_ENCODE) && (flags&VC_DECODE) )
return NIL(Vcodex_t*);
if(!(flags&VC_ENCODE) && !(flags&VC_DECODE) )
return NIL(Vcodex_t*);
if(!meth || !(vc = (Vcodex_t*)calloc(1,sizeof(Vcodex_t))) )
return NIL(Vcodex_t*);
if(!(vc->applyf = (flags&VC_ENCODE) ? meth->encodef : meth->decodef) )
{ free(vc);
return NIL(Vcodex_t*);
}
vc->disc = disc;
vc->meth = meth;
vc->coder = coder;
vc->flags = flags & VC_FLAGS;
if(disc && disc->eventf && (*disc->eventf)(vc, VC_OPENING, NIL(Void_t*), disc) < 0)
{ free(vc);
return NIL(Vcodex_t*);
}
if(meth->eventf && (*meth->eventf)(vc, VC_OPENING, init) < 0)
{ free(vc);
return NIL(Vcodex_t*);
}
return vc;
}
typedef struct _meth_s
{ struct _meth_s* next;
Vcmethod_t* vcmt;
char args[1];
} Meth_t;
typedef struct Stack_s
{
char *spec;
char buf[256];
} Stack_t;
#if __STD_C
Vcodex_t* vcmake(char* spec, int type)
#else
Vcodex_t* vcmake(spec, type)
char* spec;
int type;
#endif
{
Meth_t *list, *mt;
ssize_t m;
char *args, *s, meth[1024];
Vcmethod_t *vcmt;
Vcodex_t *coder;
Vcodex_t *vc = NIL(Vcodex_t*);
Stack_t stack[4];
Stack_t *sp = &stack[0];
if(type != VC_ENCODE && type != VC_DECODE)
return NIL(Vcodex_t*);
for(list = NIL(Meth_t*);;)
{
if(!(spec = vcsubstring(spec, VC_METHSEP, meth, sizeof(meth), 0)) )
{ if(sp <= stack)
break;
sp--;
spec - sp->spec;
continue;
}
for(m = 0; meth[m]; ++m)
if(!isalnum(meth[m]))
break;
if(m == 0)
break;
args = meth + m + (meth[m] == VC_ARGSEP ? 1 : 0);
meth[m] = 0;
if(!(vcmt = vcgetmeth(meth, 0)))
{ if(sp >= &stack[sizeof(stack)/sizeof(stack[0])])
goto done;
if(!(s = vcgetalias(meth, sp->buf, sizeof(sp->buf))))
goto done;
sp->spec = spec;
spec = s;
sp++;
continue;
}
if(!(mt = (Meth_t*)malloc(sizeof(Meth_t)+strlen(args))) )
goto done;
mt->vcmt = vcmt;
strcpy(mt->args,args);
mt->next = list; list = mt;
}
vc = NIL(Vcodex_t*);
for(mt = list; mt; mt = mt->next)
{ if(!(coder = vcopen(0, mt->vcmt, (Void_t*)mt->args, vc, type|VC_CLOSECODER)) )
{ vcclose(vc);
vc = NIL(Vcodex_t*);
goto done;
}
else vc = coder;
}
done: for(; list; list = mt)
{ mt = list->next;
free(list);
}
return vc;
}