Piotr Caban : kernel32: Added IdnToAscii implementation.
Alexandre Julliard
julliard at winehq.org
Mon Apr 30 14:13:08 CDT 2012
Module: wine
Branch: master
Commit: 04ad71ee05a76507906b5e4f064bf9e0d2b0bb62
URL: http://source.winehq.org/git/wine.git/?a=commit;h=04ad71ee05a76507906b5e4f064bf9e0d2b0bb62
Author: Piotr Caban <piotr at codeweavers.com>
Date: Mon Apr 30 17:27:46 2012 +0200
kernel32: Added IdnToAscii implementation.
---
dlls/kernel32/locale.c | 154 +++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 151 insertions(+), 3 deletions(-)
diff --git a/dlls/kernel32/locale.c b/dlls/kernel32/locale.c
index e546000..73eebd4 100644
--- a/dlls/kernel32/locale.c
+++ b/dlls/kernel32/locale.c
@@ -3881,16 +3881,164 @@ BOOL WINAPI IsNormalizedString(NORM_FORM NormForm, LPCWSTR lpString, INT cwLengt
return FALSE;
}
+enum {
+ BASE = 36,
+ TMIN = 1,
+ TMAX = 26,
+ SKEW = 38,
+ DAMP = 700,
+ INIT_BIAS = 72,
+ INIT_N = 128
+};
+
+static inline INT adapt(INT delta, INT numpoints, BOOL firsttime)
+{
+ INT k;
+
+ delta /= (firsttime ? DAMP : 2);
+ delta += delta/numpoints;
+
+ for(k=0; delta>((BASE-TMIN)*TMAX)/2; k+=BASE)
+ delta /= BASE-TMIN;
+ return k+((BASE-TMIN+1)*delta)/(delta+SKEW);
+}
+
/******************************************************************************
* IdnToAscii (KERNEL32.@)
+ * Implementation of Punycode based on RFC 3492.
*/
INT WINAPI IdnToAscii(DWORD dwFlags, LPCWSTR lpUnicodeCharStr, INT cchUnicodeChar,
LPWSTR lpASCIICharStr, INT cchASCIIChar)
{
- FIXME("%x %p %d %p %d\n", dwFlags, lpUnicodeCharStr, cchUnicodeChar,
+ static const WCHAR prefixW[] = {'x','n','-','-'};
+
+ WCHAR *norm_str;
+ INT i, label_start, label_end, norm_len, out_label, out = 0;
+
+ TRACE("%x %p %d %p %d\n", dwFlags, lpUnicodeCharStr, cchUnicodeChar,
lpASCIICharStr, cchASCIIChar);
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
- return 0;
+
+ norm_len = IdnToNameprepUnicode(dwFlags, lpUnicodeCharStr, cchUnicodeChar, NULL, 0);
+ if(!norm_len)
+ return 0;
+ norm_str = HeapAlloc(GetProcessHeap(), 0, norm_len*sizeof(WCHAR));
+ if(!norm_str) {
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ return 0;
+ }
+ norm_len = IdnToNameprepUnicode(dwFlags, lpUnicodeCharStr,
+ cchUnicodeChar, norm_str, norm_len);
+ if(!norm_len) {
+ HeapFree(GetProcessHeap(), 0, norm_str);
+ return 0;
+ }
+
+ for(label_start=0; label_start<norm_len;) {
+ INT n = INIT_N, bias = INIT_BIAS;
+ INT delta = 0, b = 0, h;
+
+ out_label = out;
+ for(i=label_start; i<norm_len && norm_str[i]!='.' && norm_str[i]!='\0'; i++)
+ if(norm_str[i] < 0x80)
+ b++;
+ label_end = i;
+
+ if(b == label_end-label_start) {
+ if(label_end < norm_len)
+ b++;
+ if(!lpASCIICharStr) {
+ out += b;
+ }else if(out+b <= cchASCIIChar) {
+ memcpy(lpASCIICharStr+out, norm_str+label_start, b*sizeof(WCHAR));
+ out += b;
+ }else {
+ HeapFree(GetProcessHeap(), 0, norm_str);
+ SetLastError(ERROR_INSUFFICIENT_BUFFER);
+ return 0;
+ }
+ label_start = label_end+1;
+ continue;
+ }
+
+ if(!lpASCIICharStr) {
+ out += 5+b; /* strlen(xn--...-) */
+ }else if(out+5+b <= cchASCIIChar) {
+ memcpy(lpASCIICharStr+out, prefixW, sizeof(prefixW));
+ out += 4;
+ for(i=label_start; i<label_end; i++)
+ if(norm_str[i] < 0x80)
+ lpASCIICharStr[out++] = norm_str[i];
+ lpASCIICharStr[out++] = '-';
+ }else {
+ HeapFree(GetProcessHeap(), 0, norm_str);
+ SetLastError(ERROR_INSUFFICIENT_BUFFER);
+ return 0;
+ }
+ if(!b)
+ out--;
+
+ for(h=b; h<label_end-label_start;) {
+ INT m = 0xffff, q, k;
+
+ for(i=label_start; i<label_end; i++) {
+ if(norm_str[i]>=n && m>norm_str[i])
+ m = norm_str[i];
+ }
+ delta += (m-n)*(h+1);
+ n = m;
+
+ for(i=label_start; i<label_end; i++) {
+ if(norm_str[i] < n) {
+ delta++;
+ }else if(norm_str[i] == n) {
+ for(q=delta, k=BASE; ; k+=BASE) {
+ INT t = k<=bias ? TMIN : k>=bias+TMAX ? TMAX : k-bias;
+ INT disp = q<t ? q : t+(q-t)%(BASE-t);
+ if(!lpASCIICharStr) {
+ out++;
+ }else if(out+1 <= cchASCIIChar) {
+ lpASCIICharStr[out++] = disp<='z'-'a' ?
+ 'a'+disp : '0'+disp-'z'+'a'-1;
+ }else {
+ HeapFree(GetProcessHeap(), 0, norm_str);
+ SetLastError(ERROR_INSUFFICIENT_BUFFER);
+ return 0;
+ }
+ if(q < t)
+ break;
+ q = (q-t)/(BASE-t);
+ }
+ bias = adapt(delta, h+1, h==b);
+ delta = 0;
+ h++;
+ }
+ }
+ delta++;
+ n++;
+ }
+
+ if(out-out_label > 63) {
+ HeapFree(GetProcessHeap(), 0, norm_str);
+ SetLastError(ERROR_INVALID_NAME);
+ return 0;
+ }
+
+ if(label_end < norm_len) {
+ if(!lpASCIICharStr) {
+ out++;
+ }else if(out+1 <= cchASCIIChar) {
+ lpASCIICharStr[out++] = norm_str[label_end];
+ }else {
+ HeapFree(GetProcessHeap(), 0, norm_str);
+ SetLastError(ERROR_INSUFFICIENT_BUFFER);
+ return 0;
+ }
+ }
+ label_start = label_end+1;
+ }
+
+ HeapFree(GetProcessHeap(), 0, norm_str);
+ return out;
}
/******************************************************************************
More information about the wine-cvs
mailing list