En my open-source plain C code yo uso esta estructura sencilla de leer y analizar los datos de un búfer de cadena:Aplicada de pato a escribir en C plano
typedef struct lts_LoadState
{
const unsigned char * pos;
size_t unread;
} lts_LoadState;
se accede a la memoria intermedia con 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);
Nota : ltsLS_unread
se puede reemplazar con return (ltsLS_good(ls)) ? SIZE_MAX : 0
sin romper la implementación actual.
Este código se utiliza para load some data in a custom format from a string buffer. (This puede haber una mejor ilustración.)
ahora tengo que datos de carga no desde un búfer de cadena, pero a partir de un puntero FILE
.
Odiaría copiar y pegar la implementación, y desea reutilizar el código existente en su lugar. (Estoy de acuerdo con la refactorización/adaptación, por supuesto.)
Esto es un material de libro de texto en C++, pero cómo hacerlo en C simple sin incurrir en gastos generales de tiempo de ejecución?
Aquí es una función de ejemplo que utiliza la API de lts_LoadState
y que no se va a copiar y pegar (pero puede ser cambiado, por supuesto, para apoyar tanto búfer de cadena y 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;
}
Estoy pensando en generar código C con algún script, por lo que "copiar y pegar" se realiza automáticamente. Esta es probablemente la forma más fácil. Pero estoy buscando la solución "adecuada" sin generación de código (el preprocesador está bien, por supuesto). –
Terminé usando archivos mapeados en memoria - de esta manera puedo reutilizar exactamente el mismo 'lts_LoadState' y sus funciones de acceso. –