HelenOS sources
This source file includes following definitions.
- _set_ilseq
- _is_low_surrogate
- _is_high_surrogate
- _is_surrogate
- c32rtomb
- mbrtoc16
- c16rtomb
#include <assert.h>
#include <errno.h>
#include <limits.h>
#include <stdbool.h>
#include <uchar.h>
#if __STDC_HOSTED__
#include <fibril.h>
#endif
static void _set_ilseq()
{
#ifdef errno
errno = EILSEQ;
#endif
}
static bool _is_low_surrogate(char16_t c)
{
return c >= 0xDC00 && c < 0xE000;
}
static bool _is_high_surrogate(char16_t c)
{
return c >= 0xD800 && c < 0xDC00;
}
static bool _is_surrogate(char16_t c)
{
return c >= 0xD800 && c < 0xE000;
}
#define UTF8_CONT(c, shift) (0x80 | (((c) >> (shift)) & 0x3F))
size_t c32rtomb(char *s, char32_t c, mbstate_t *mb)
{
if (!s) {
return 1;
}
if (c < 0x80) {
s[0] = c;
return 1;
}
if (c < 0x800) {
s[0] = 0b11000000 | (c >> 6);
s[1] = UTF8_CONT(c, 0);
return 2;
}
if (c < 0x10000) {
if (_is_surrogate(c)) {
_set_ilseq();
return UCHAR_ILSEQ;
}
s[0] = 0b11100000 | (c >> 12);
s[1] = UTF8_CONT(c, 6);
s[2] = UTF8_CONT(c, 0);
return 3;
}
if (c < 0x110000) {
s[0] = 0b11110000 | (c >> 18);
s[1] = UTF8_CONT(c, 12);
s[2] = UTF8_CONT(c, 6);
s[3] = UTF8_CONT(c, 0);
return 4;
}
_set_ilseq();
return UCHAR_ILSEQ;
}
size_t mbrtoc16(char16_t *c, const char *s, size_t n, mbstate_t *mb)
{
#if __STDC_HOSTED__
static fibril_local mbstate_t global_state = { };
if (!mb)
mb = &global_state;
#else
assert(mb);
#endif
char16_t dummy;
if (!c)
c = &dummy;
if (!s) {
if (mb->state) {
_set_ilseq();
return UCHAR_ILSEQ;
} else {
return 0;
}
}
if ((mb->state & 0xD000) == 0xD000) {
*c = mb->state;
mb->state = 0;
return UCHAR_CONTINUED;
}
char32_t c32 = 0;
size_t ret = mbrtoc32(&c32, s, n, mb);
if (ret < INT_MAX) {
if (c32 < 0x10000) {
*c = c32;
} else {
mb->state = (c32 & 0x3FF) + 0xDC00;
*c = (c32 >> 10) + 0xD7C0;
}
return ret;
}
return ret;
}
size_t c16rtomb(char *s, char16_t c, mbstate_t *mb)
{
#if __STDC_HOSTED__
static fibril_local mbstate_t global_state = { };
if (!mb)
mb = &global_state;
#else
assert(mb);
#endif
if (!s) {
if (mb->state) {
_set_ilseq();
return UCHAR_ILSEQ;
} else {
return 1;
}
}
if (!_is_surrogate(c)) {
if (mb->state) {
_set_ilseq();
return UCHAR_ILSEQ;
}
return c32rtomb(s, c, mb);
}
if (!mb->state) {
mb->state = c;
return 0;
}
char32_t c32;
if (_is_low_surrogate(mb->state) && _is_high_surrogate(c)) {
c32 = ((c - 0xD7C0) << 10) | (mb->state - 0xDC00);
} else if (_is_high_surrogate(mb->state) && _is_low_surrogate(c)) {
c32 = ((mb->state - 0xD7C0) << 10) | (c - 0xDC00);
} else {
_set_ilseq();
return UCHAR_ILSEQ;
}
mb->state = 0;
return c32rtomb(s, c32, mb);
}
HelenOS homepage, sources at GitHub