Прикладной дак-тип в простом C

В моем открытом исходном коде на 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 без накладных расходов во время выполнения?


Вот пример функции, использующей lts_LoadStateAPI, которую нельзя копировать и вставлять (но, конечно, ее можно изменить, чтобы она поддерживала как строковый буфер, так и 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;
}

8
задан Alexander Gladysh 3 April 2012 в 21:47
поделиться