summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarti Maria <marti.maria@littlecms.com>2022-01-05 16:48:30 +0100
committerMarti Maria <marti.maria@littlecms.com>2022-01-05 16:48:30 +0100
commit4ce24635d9422be4de4f2da3fa7825e1f163ac82 (patch)
treecd86a0771dad1f26fc95c62d4e6eb1d9fc1c210e
parent1b6875a9701bc603b06f8950d77fae6368f6bf2b (diff)
downloadlcms2-4ce24635d9422be4de4f2da3fa7825e1f163ac82.tar.gz
better utf16 to wchar_t
Try to promote correctly to utf8 to wchar_t when unicode is 32 bits
-rw-r--r--src/cmstypes.c47
1 files changed, 47 insertions, 0 deletions
diff --git a/src/cmstypes.c b/src/cmstypes.c
index e20c362..658e9cd 100644
--- a/src/cmstypes.c
+++ b/src/cmstypes.c
@@ -134,15 +134,62 @@ cmsBool _cmsWriteWCharArray(cmsIOHANDLER* io, cmsUInt32Number n, const wchar_t*
return TRUE;
}
+// Try to promote correctly to wchar_t when 32 bits
+cmsINLINE cmsBool is_surrogate(cmsUInt32Number uc) { return (uc - 0xd800u) < 2048u; }
+cmsINLINE cmsBool is_high_surrogate(cmsUInt32Number uc) { return (uc & 0xfffffc00) == 0xd800; }
+cmsINLINE cmsBool is_low_surrogate(cmsUInt32Number uc) { return (uc & 0xfffffc00) == 0xdc00; }
+
+cmsINLINE cmsUInt32Number surrogate_to_utf32(cmsUInt32Number high, cmsUInt32Number low)
+{
+ return (high << 10) + low - 0x35fdc00;
+}
+
+cmsINLINE cmsBool convert_utf16_to_utf32(cmsIOHANDLER* io, cmsInt32Number n, wchar_t* output)
+{
+ cmsUInt16Number uc;
+
+ while (n > 0)
+ {
+ if (!_cmsReadUInt16Number(io, &uc)) return FALSE;
+ n--;
+
+ if (!is_surrogate(uc))
+ {
+ *output++ = (wchar_t)uc;
+ }
+ else {
+
+ cmsUInt16Number low;
+
+ if (!_cmsReadUInt16Number(io, &low)) return FALSE;
+ n--;
+
+ if (is_high_surrogate(uc) && is_low_surrogate(low))
+ *output++ = (wchar_t)surrogate_to_utf32(uc, low);
+ else
+ return FALSE; // Corrupted string, just ignore
+ }
+ }
+
+ return TRUE;
+}
+
+
// Auxiliary to read an array of wchar_t
static
cmsBool _cmsReadWCharArray(cmsIOHANDLER* io, cmsUInt32Number n, wchar_t* Array)
{
cmsUInt32Number i;
cmsUInt16Number tmp;
+ cmsBool is32 = sizeof(wchar_t) > sizeof(cmsUInt16Number);
_cmsAssert(io != NULL);
+ if (is32 && Array != NULL)
+ {
+ return convert_utf16_to_utf32(io, n, Array);
+ }
+
for (i=0; i < n; i++) {
if (Array != NULL) {