| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| |
|
|
| #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 |
|
|