111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert/*
211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * This code was written by Rich Felker in 2010; no copyright is claimed.
311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * This code is in the public domain. Attribution is appreciated but
411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * unnecessary.
511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert */
611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include <wchar.h>
811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include <errno.h>
911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
1011cd02dfb91661c65134cac258cf5924270e9d2Dan Albertsize_t wcrtomb(char *restrict s, wchar_t wc, mbstate_t *restrict st)
1111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert{
1211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert	if (!s) return 1;
1311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert	if ((unsigned)wc < 0x80) {
1411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert		*s = wc;
1511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert		return 1;
1611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert	} else if ((unsigned)wc < 0x800) {
1711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert		*s++ = 0xc0 | (wc>>6);
1811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert		*s = 0x80 | (wc&0x3f);
1911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert		return 2;
2011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert	} else if ((unsigned)wc < 0xd800 || (unsigned)wc-0xe000 < 0x2000) {
2111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert		*s++ = 0xe0 | (wc>>12);
2211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert		*s++ = 0x80 | ((wc>>6)&0x3f);
2311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert		*s = 0x80 | (wc&0x3f);
2411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert		return 3;
2511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert	} else if ((unsigned)wc-0x10000 < 0x100000) {
2611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert		*s++ = 0xf0 | (wc>>18);
2711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert		*s++ = 0x80 | ((wc>>12)&0x3f);
2811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert		*s++ = 0x80 | ((wc>>6)&0x3f);
2911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert		*s = 0x80 | (wc&0x3f);
3011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert		return 4;
3111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert	}
3211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert	errno = EILSEQ;
3311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert	return -1;
3411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
35