[1/2] ntdll: Implement RtlUnicodeToUTF8N.
Thomas Faber
thomas.faber at reactos.org
Thu May 21 18:37:00 CDT 2015
From 32b6d2c64ef3be489ca0d2ab3b380f3565479ffb Mon Sep 17 00:00:00 2001
From: Thomas Faber <thomas.faber at reactos.org>
Date: Thu, 21 May 2015 12:48:41 -0400
Subject: ntdll: Implement RtlUnicodeToUTF8N.
---
dlls/ntdll/ntdll.spec | 1 +
dlls/ntdll/rtlstr.c | 111 +++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 112 insertions(+), 0 deletions(-)
diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec
index 6d86157..316f875 100644
--- a/dlls/ntdll/ntdll.spec
+++ b/dlls/ntdll/ntdll.spec
@@ -915,6 +915,7 @@
@ stdcall RtlUnicodeToMultiByteN(ptr long ptr ptr long)
@ stdcall RtlUnicodeToMultiByteSize(ptr ptr long)
@ stdcall RtlUnicodeToOemN(ptr long ptr ptr long)
+@ stdcall RtlUnicodeToUTF8N(ptr long ptr ptr long)
@ stdcall RtlUniform(ptr)
# @ stub RtlUnlockBootStatusData
@ stdcall RtlUnlockHeap(long)
diff --git a/dlls/ntdll/rtlstr.c b/dlls/ntdll/rtlstr.c
index 01b4446..5286b81 100644
--- a/dlls/ntdll/rtlstr.c
+++ b/dlls/ntdll/rtlstr.c
@@ -2163,3 +2163,114 @@ NTSTATUS WINAPI RtlHashUnicodeString(PCUNICODE_STRING string, BOOLEAN case_insen
return STATUS_SUCCESS;
}
+
+/******************************************************************************
+ * RtlUnicodeToUTF8N [NTDLL.@]
+ */
+NTSTATUS WINAPI RtlUnicodeToUTF8N(CHAR *utf8_dest, ULONG utf8_bytes_max,
+ ULONG *utf8_bytes_written,
+ const WCHAR *uni_src, ULONG uni_bytes)
+{
+ NTSTATUS status;
+ ULONG i;
+ ULONG written;
+ ULONG ch;
+ BYTE utf8_ch[4];
+ ULONG utf8_ch_len;
+
+ if (!uni_src)
+ return STATUS_INVALID_PARAMETER_4;
+ if (!utf8_bytes_written)
+ return STATUS_INVALID_PARAMETER;
+ if (utf8_dest && uni_bytes % sizeof(WCHAR))
+ return STATUS_INVALID_PARAMETER_5;
+
+ written = 0;
+ status = STATUS_SUCCESS;
+
+ for (i = 0; i < uni_bytes / sizeof(WCHAR); i++)
+ {
+ /* decode UTF-16 into ch */
+ ch = uni_src[i];
+ if (ch >= 0xdc00 && ch <= 0xdfff)
+ {
+ ch = 0xfffd;
+ status = STATUS_SOME_NOT_MAPPED;
+ }
+ else if (ch >= 0xd800 && ch <= 0xdbff)
+ {
+ if (i + 1 < uni_bytes / sizeof(WCHAR))
+ {
+ ch -= 0xd800;
+ ch <<= 10;
+ if (uni_src[i + 1] >= 0xdc00 && uni_src[i + 1] <= 0xdfff)
+ {
+ ch |= uni_src[i + 1] - 0xdc00;
+ ch += 0x010000;
+ i++;
+ }
+ else
+ {
+ ch = 0xfffd;
+ status = STATUS_SOME_NOT_MAPPED;
+ }
+ }
+ else
+ {
+ ch = 0xfffd;
+ status = STATUS_SOME_NOT_MAPPED;
+ }
+ }
+
+ /* encode ch as UTF-8 */
+ assert(ch <= 0x10ffff);
+ if (ch < 0x80)
+ {
+ utf8_ch[0] = ch & 0x7f;
+ utf8_ch_len = 1;
+ }
+ else if (ch < 0x800)
+ {
+ utf8_ch[0] = 0xc0 | (ch >> 6 & 0x1f);
+ utf8_ch[1] = 0x80 | (ch >> 0 & 0x3f);
+ utf8_ch_len = 2;
+ }
+ else if (ch < 0x10000)
+ {
+ utf8_ch[0] = 0xe0 | (ch >> 12 & 0x0f);
+ utf8_ch[1] = 0x80 | (ch >> 6 & 0x3f);
+ utf8_ch[2] = 0x80 | (ch >> 0 & 0x3f);
+ utf8_ch_len = 3;
+ }
+ else if (ch < 0x200000)
+ {
+ utf8_ch[0] = 0xf0 | (ch >> 18 & 0x07);
+ utf8_ch[1] = 0x80 | (ch >> 12 & 0x3f);
+ utf8_ch[2] = 0x80 | (ch >> 6 & 0x3f);
+ utf8_ch[3] = 0x80 | (ch >> 0 & 0x3f);
+ utf8_ch_len = 4;
+ }
+
+ if (!utf8_dest)
+ {
+ written += utf8_ch_len;
+ continue;
+ }
+
+ if (utf8_bytes_max >= utf8_ch_len)
+ {
+ memcpy(utf8_dest, utf8_ch, utf8_ch_len);
+ utf8_dest += utf8_ch_len;
+ utf8_bytes_max -= utf8_ch_len;
+ written += utf8_ch_len;
+ }
+ else
+ {
+ utf8_bytes_max = 0;
+ status = STATUS_BUFFER_TOO_SMALL;
+ }
+ }
+
+ *utf8_bytes_written = written;
+ return status;
+}
--
1.7.1
More information about the wine-patches
mailing list