在
my open-source plain C code中,我使用这个简单的结构来读取和解析字符串缓冲区中的数据:
typedef struct lts_LoadState { const unsigned char * pos; size_t unread; } lts_LoadState;
使用this simple API访问缓冲区:
/* Initialize buffer */ void ltsLS_init(lts_LoadState * ls,const unsigned char * data,size_t len); /* Do we have something to read? (Actually a macro.) */ BOOL ltsLS_good(ls); /* How much do we have to read? (Actually a macro.) */ size_t ltsLS_unread(ls); /* Eat given number of characters,return pointer to beginning of eaten data */ const unsigned char * ltsLS_eat(lts_LoadState * ls,size_t len);
注意:ltsLS_unread可以替换为return(ltsLS_good(ls))? SIZE_MAX:0而不会破坏当前的实现.
此代码用于load some data in a custom format from a string buffer.(This可能是一个更好的例子.)
现在我需要不是从字符串缓冲区加载数据,而是从FILE指针加载数据.
我不想复制粘贴实现,而是希望重用现有代码. (当然,我可以重构/改编它.)
这是C语言中的教科书,但是如何在普通的C中做到这一点而不会产生运行时开销?
下面是一个使用lts_LoadState API并且不能进行复制粘贴的示例函数(当然,可以更改为支持字符串缓冲区和FILE *):
static int ltsLS_readline( lts_LoadState * ls,const unsigned char ** dest,size_t * len ) { const unsigned char * origin = ls->pos; unsigned char last = 0; size_t read = 0; while (ltsLS_good(ls)) { if (ltsLS_unread(ls) > 0) { unsigned char b = *ls->pos; /* OK,this should be ltsLS_eat_char macro. */ ++ls->pos; --ls->unread; if (b == '\n') { *dest = origin; *len = (last == '\r') ? read - 1 : read; return LUATEXTS_ESUCCESS; } last = b; ++read; } else { ls->unread = 0; ls->pos = NULL; } } return LUATEXTS_ECLIPPED; }
解决方法
听起来你想要函数变量,你可以将它作为参数传递. C可以做到,但语法不是很漂亮.
可能有一点运行时开销,但不多.