65 lines
1.4 KiB
C
65 lines
1.4 KiB
C
|
|
#include "CgeStr.h"
|
||
|
|
|
||
|
|
#define INVALID_RUNE 0xFFFD
|
||
|
|
|
||
|
|
int CgeUtf16Encode(uint32_t rune, uint16_t* data) {
|
||
|
|
if (rune <= 0xFFFF) {
|
||
|
|
if (rune >= 0xD800 && rune <= 0xDFFF)
|
||
|
|
return -1;
|
||
|
|
data[0] = (uint16_t)rune;
|
||
|
|
return 1;
|
||
|
|
}
|
||
|
|
if (rune <= 0x10FFFF) {
|
||
|
|
uint32_t x = rune - 0x10000;
|
||
|
|
data[0] = (uint16_t)(0xD800 + (x >> 10));
|
||
|
|
data[1] = (uint16_t)(0xDC00 + (x & 0x3FF));
|
||
|
|
return 2;
|
||
|
|
}
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
|
||
|
|
int CgeUtf16EncodeLax(uint32_t rune, uint16_t* data) {
|
||
|
|
int result;
|
||
|
|
|
||
|
|
result = CgeUtf16Encode(rune, data);
|
||
|
|
if (result == -1)
|
||
|
|
result = CgeUtf16Encode(INVALID_RUNE, data);
|
||
|
|
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
|
||
|
|
int CgeUtf16Decode(const uint16_t* data, size_t size, uint32_t* rune) {
|
||
|
|
uint16_t trail, lead = data[0];
|
||
|
|
|
||
|
|
if (size == 0)
|
||
|
|
return -1;
|
||
|
|
|
||
|
|
if (lead < 0xD800 || lead > 0xDFFF) {
|
||
|
|
*rune = lead;
|
||
|
|
return 1;
|
||
|
|
} else if (lead >= 0xD800 && lead <= 0xDBFF) {
|
||
|
|
if (size < 2)
|
||
|
|
return -1;
|
||
|
|
|
||
|
|
trail = data[1];
|
||
|
|
if (trail >= 0xDC00 && trail <= 0xDFFF) {
|
||
|
|
*rune = 0x10000 + ((lead & 0x3FF) << 10) + (trail & 0x3FF);
|
||
|
|
return 2;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
|
||
|
|
int CgeUtf16DecodeLax(const uint16_t* data, size_t size, uint32_t* rune) {
|
||
|
|
int result;
|
||
|
|
|
||
|
|
result = CgeUtf16Decode(data, size, rune);
|
||
|
|
if (result == -1) {
|
||
|
|
*rune = INVALID_RUNE;
|
||
|
|
result = 1;
|
||
|
|
}
|
||
|
|
|
||
|
|
return result;
|
||
|
|
}
|