私のオープンソースのプレーンな C コードでは、次の単純な構造を使用して、文字列バッファーからデータを読み取り、解析します。
typedef struct lts_LoadState
{
const unsigned char * pos;
size_t unread;
} lts_LoadState;
この単純な 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
このコードは、一部のデータを文字列バッファからカスタム形式でロードするために使用されます。(こちらの方がわかりやすいかもしれません。)
ここで、文字列バッファーからではなく、FILE
ポインターからデータをロードする必要があります。
実装をコピーして貼り付けるのは嫌いで、代わりに既存のコードを再利用したいと考えています。(もちろん、リファクタリング/適応は問題ありません。)
これは C++ の教科書的なものですが、実行時のオーバーヘッドを発生させずに単純な C でそれを行うにはどうすればよいでしょうか?
APIを使用する関数の例を次に示します。この関数はlts_LoadState
コピー アンド ペーストできません (もちろん、文字列バッファと の両方をサポートするように変更することはできます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;
}