libunic/fromchar_unicode.c

70 lines
1.7 KiB
C
Raw Permalink Normal View History

2022-05-31 15:28:37 +03:00
/* This software is licensed by the MIT License, see LICENSE file */
/* Copyright © 2022 Gregory Lirent */
#include "build.h"
const char* fromchar_unicode(unsigned int* uc, const char* s) {
unsigned char* p;
unsigned int v;
unsigned char n;
if (*(p = (void*)s) <= 0x7f) {
*uc = *s;
return s + 1;
}
memcpy(&v, s, 4);
*uc = 0;
if (IS_LITTLE_ENDIAN) {
if ((v&0x0000c0e0) == 0x000080c0) {
n = 2;
*uc |= *(p++)&0x1f;
} else {
if ((v&0x00c0c0f0) == 0x008080e0) {
n = 3;
*uc |= *(p++)&0x0f;
} else if ((v&0xc0c0c0f8) == 0x808080f0) {
n = 4;
*uc |= *(p++)&0x07;
*uc <<= 6;
*uc |= *(p++)&0x3f;
} else return (void*)(size_t)(*uc = 0);
*uc <<= 6;
*uc |= *(p++)&0x3f;
}
} else {
if ((v&0xe0c00000) == 0xc0800000) {
n = 2;
*uc |= *(p++)&0x1f;
} else {
if ((v&0xf8c0c0c0) == 0xf0808080) {
n = 3;
*uc |= *(p++)&0x0f;
} else if ((v&0xf0c0c000) == 0xe0808000) {
n = 4;
*uc |= *(p++)&0x07;
*uc <<= 6;
*uc |= *(p++)&0x3f;
} else return (void*)(size_t)(*uc = 0);
*uc <<= 6;
*uc |= *(p++)&0x3f;
}
}
*uc <<= 6;
*uc |= *(p++)&0x3f;
#ifndef UNICODE_CHARSIZE_CHECK_DISABLE
if ((n == 2 && *uc > 0x0007ff) ||
(n == 3 && *uc > 0x00ffff) ||
(n == 4 && *uc > 0x10ffff))
return (void*)(size_t)(*uc = 0);
#endif
return s + n;
}