summaryrefslogtreecommitdiff
path: root/fgetwc_fix.c
blob: 76cf52b446e77e27cfbe658492e7c05b81cf5c46 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
/* This file contains a fixed implementation of fgetwc since glibc's one is a little segfaulty when used on fmemopen'ed files. */

#include <stdlib.h>
#include <wchar.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>

#include "fgetwc_fix.h"

/* code blatantly ripped from newlib. If you are from newlib: newlib rocks, keep going! */
wint_t _fgetwc_fixed(FILE *fp) {
	wchar_t wc;
	size_t res;
	size_t nconv = 0;
	char buf[MB_CUR_MAX];
	mbstate_t mbstate;
	memset(&mbstate, 0, sizeof(mbstate));

	while((buf[nconv++] = fgetc(fp)) != EOF){
		res = mbrtowc(&wc, buf, nconv, &mbstate);
		if (res == (size_t)-1) /* invalid sequence */
			break;
		else if (res == (size_t)-2) /* incomplete sequence */
			continue;
		else if (res == 0)
			return L'\0';
		else
			return wc;
	}

	errno = EILSEQ;
	return WEOF;
}