diff options
author | Thomas Voss <mail@thomasvoss.com> | 2024-03-31 20:07:51 +0200 |
---|---|---|
committer | Thomas Voss <mail@thomasvoss.com> | 2024-03-31 20:07:51 +0200 |
commit | a61379f455b80236e251c56c32a16748f2d35af3 (patch) | |
tree | 74183bcd4d2b55961945e6db7b9099e16a34b37d /lib | |
parent | d79a16a7d172ece3b01bf78ab7c6db02dc9cf267 (diff) |
Remove the need for a state in freadrune()
Diffstat (limited to 'lib')
-rw-r--r-- | lib/mbio/freadrune.c | 54 |
1 files changed, 40 insertions, 14 deletions
diff --git a/lib/mbio/freadrune.c b/lib/mbio/freadrune.c index efa42b3..5c24f52 100644 --- a/lib/mbio/freadrune.c +++ b/lib/mbio/freadrune.c @@ -1,23 +1,49 @@ -#include <macros.h> #include <stdio.h> #include <string.h> +#include "macros.h" #include "mbio.h" #include "mbstring.h" +#include "rune.h" + +#define RETURN_INVAL \ + do { \ + *ch = RUNE_ERROR; \ + return 3; \ + } while (false) int -freadrune(rune *ch, u8_io_state *st, FILE *stream) +freadrune(rune *ch, FILE *stream) { - size_t n, need; - need = lengthof(st->_buf) - st->_fill; - st->_fill += n = fread(st->_buf + st->_fill, 1, need, stream); - if (n < need && ferror(stream)) - return -1; - if (st->_fill == 0) - return 0; - - int w = u8tor(ch, st->_buf); - memmove(st->_buf, st->_buf + w, lengthof(st->_buf) - w); - st->_fill -= w; - return w; + int c, n = 0; + char8_t buf[U8_LEN_MAX]; + + if ((c = fgetc(stream)) == EOF) + goto eof_or_err; + + buf[0] = (char8_t)c; + n = u8byte1(c) ? 0 : u8byte2(c) ? 1 : u8byte3(c) ? 2 : u8byte4(c) ? 3 : 4; + + if (n == 0) { + *ch = buf[0]; + return 1; + } else if (n == 4) + RETURN_INVAL; + + for (int i = 0; i < n; i++) { + if ((c = fgetc(stream)) == EOF) + goto eof_or_err; + if (!u8bytec(c)) + RETURN_INVAL; + buf[i + 1] = c; + } + + return u8tor(ch, buf); + +eof_or_err: + if (ferror(stream)) + return MBERR; + if (n == 0) + return MBEOF; + RETURN_INVAL; } |