the other day, we had to extend C style IO to use defined types. Let the code says how we made that work
#include<stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
typedef struct tagProcessor
{
char name[32]; //max length 31
void (*pf)(va_list* pva); //there must be one and only one expression arg_va(*pva, T) within pf;
struct tagProcessor* next;
}type_processor;
type_processor** processorList()
{
static type_processor* theList = 0;
return &theList;
}
//if multiple registratoins for a type, only the last registraton is meanfull
//we don't provide unregister function for now,
//though a unregister function is not hard to add
type_processor const* regProcessor(char const* type_name, void (*pf)(va_list*))
{
type_processor** list;
type_processor* tp = (type_processor*)malloc(sizeof(type_processor));
if(tp)
{
strncpy(tp->name, type_name, sizeof(tp->name)-1);
tp->name[sizeof(tp->name)-1] = 0;
tp->pf = pf;
list = processorList();
tp->next = *list;
*list = tp;
}
return tp;
}
type_processor const* findRegEntry(char const* name)
{
type_processor* tp = *processorList();
while(tp && 0 != strcmp(tp->name, name))
{
tp = tp->next;
}
return tp;
}
//types are delimeted by space(s)
void run(char* types, ...)
{
type_processor const* tp;
char type[sizeof(tp->name)], *p;
va_list vl;
va_start(vl,types);
if(types)
{
while(*types)
{
while(isspace(*types)) ++types; //skip spaces at the begining
p = type;
while(!isspace(*types) && *types)
{
*p++ = *types++;
}
*p = 0;
if(p == types) //no more data to process
{
break;
}
tp = findRegEntry(type);
if(tp)
{
if(tp->pf)
{
tp->pf(&vl);
}
//else
}
//else
}
}
va_end(vl);
}
typedef struct tagABC
{
int a;
double b;
char c;
}ABC;
void processABC(va_list* pvl)
{
ABC abc = va_arg(*pvl, ABC);
printf("%d %lf %c\n", abc.a, abc.b, abc.c);
}
void processABCPointer(va_list* pvl)
{
ABC* abc = va_arg(*pvl, ABC*);
printf("%d %lf %c\n", abc->a, abc->b, abc->c);
}
void processInt(va_list* pvl)
{
printf("%d\n", va_arg(*pvl, int));
}
int main()
{
regProcessor("ABC", processABC);
regProcessor("ABC*", processABCPointer);
regProcessor("int", processInt);
ABC abc = {56, 78.5, 'L'};
run("int ABC int ABC*", (int)5, abc, (int)6, &abc);
return 0;
}