|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifndef _MBBUF_H |
|
|
#define _MBBUF_H 1 |
|
|
|
|
|
#ifndef _GL_INLINE_HEADER_BEGIN |
|
|
# error "Please include config.h first." |
|
|
#endif |
|
|
|
|
|
#include <stdio.h> |
|
|
#include <stddef.h> |
|
|
|
|
|
#include "mcel.h" |
|
|
#include "idx.h" |
|
|
|
|
|
_GL_INLINE_HEADER_BEGIN |
|
|
#ifndef MBBUF_INLINE |
|
|
# define MBBUF_INLINE _GL_INLINE |
|
|
#endif |
|
|
|
|
|
|
|
|
#define MBBUF_EOF UINT32_MAX |
|
|
|
|
|
|
|
|
static_assert (MCEL_CHAR_MAX < MBBUF_EOF); |
|
|
|
|
|
typedef struct |
|
|
{ |
|
|
char *buffer; |
|
|
FILE *fp; |
|
|
idx_t size; |
|
|
idx_t length; |
|
|
idx_t offset; |
|
|
} mbbuf_t; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
MBBUF_INLINE void |
|
|
mbbuf_init (mbbuf_t *mbbuf, char *buffer, idx_t size, FILE *fp) |
|
|
{ |
|
|
if (size < MCEL_LEN_MAX) |
|
|
unreachable (); |
|
|
mbbuf->buffer = buffer; |
|
|
mbbuf->fp = fp; |
|
|
mbbuf->size = size; |
|
|
mbbuf->length = 0; |
|
|
mbbuf->offset = 0; |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
MBBUF_INLINE mcel_t |
|
|
mbbuf_get_char (mbbuf_t *mbbuf) |
|
|
{ |
|
|
idx_t available = mbbuf->length - mbbuf->offset; |
|
|
|
|
|
if (available < MCEL_LEN_MAX && ! feof (mbbuf->fp)) |
|
|
{ |
|
|
idx_t start; |
|
|
if (!(0 < available)) |
|
|
start = 0; |
|
|
else |
|
|
{ |
|
|
memmove (mbbuf->buffer, mbbuf->buffer + mbbuf->offset, available); |
|
|
start = available; |
|
|
} |
|
|
mbbuf->length = fread (mbbuf->buffer + start, 1, mbbuf->size - start, |
|
|
mbbuf->fp) + start; |
|
|
mbbuf->offset = 0; |
|
|
available = mbbuf->length - mbbuf->offset; |
|
|
} |
|
|
if (available <= 0) |
|
|
return (mcel_t) { .ch = MBBUF_EOF }; |
|
|
mcel_t g = mcel_scan (mbbuf->buffer + mbbuf->offset, |
|
|
mbbuf->buffer + mbbuf->length); |
|
|
if (! g.err) |
|
|
mbbuf->offset += g.len; |
|
|
else |
|
|
{ |
|
|
|
|
|
g.ch = mbbuf->buffer[mbbuf->offset++]; |
|
|
} |
|
|
return g; |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
MBBUF_INLINE char * |
|
|
mbbuf_char_offset (mbbuf_t *mbbuf, mcel_t g) |
|
|
{ |
|
|
if (mbbuf->offset < g.len) |
|
|
unreachable (); |
|
|
return mbbuf->buffer + (mbbuf->offset - g.len); |
|
|
} |
|
|
|
|
|
_GL_INLINE_HEADER_END |
|
|
|
|
|
#endif |
|
|
|