[PATCH v2 3/3] kernel32: Implement NormalizeString API function.
Sergio Gómez Del Real
sdelreal at codeweavers.com
Wed Apr 11 09:21:02 CDT 2018
Signed-off-by: Sergio Gómez Del Real <sdelreal at codeweavers.com>
---
dlls/kernel32/locale.c | 88 +++++++++++++++++++++++++++++++++++++++++---
dlls/kernel32/tests/locale.c | 42 ++++++++++-----------
2 files changed, 102 insertions(+), 28 deletions(-)
diff --git a/dlls/kernel32/locale.c b/dlls/kernel32/locale.c
index 5a6ff35b75..b85f9d3f9a 100644
--- a/dlls/kernel32/locale.c
+++ b/dlls/kernel32/locale.c
@@ -5357,15 +5357,93 @@ INT WINAPI GetUserDefaultLocaleName(LPWSTR localename, int buffersize)
return LCIDToLocaleName(userlcid, localename, buffersize, 0);
}
+static inline int is_valid_norm(NORM_FORM norm)
+{
+ if (norm == NormalizationC || norm == NormalizationD ||
+ norm == NormalizationKC || norm == NormalizationKD)
+ return 1;
+ else
+ return 0;
+}
+
/******************************************************************************
* NormalizeString (KERNEL32.@)
+ *
+ * Normalizes a string according to a Unicode Normalization Form.
+ *
+ * PARAMS
+ * norm [I] Normalization Form
+ * src [I] Source string to normalize
+ * srclen [I] Length of source string (if -1, source string is null-terminated)
+ * dst [O] Buffer to write normalized source string (can be NULL)
+ * dstlen [I] Length of dst string (can be 0)
+ *
+ * RETURNS
+ * Success: If dstlen is 0, return size needed, else return size of normalized string.
+ * Failure: ret <= 0. Use GetLastError to determine error.
*/
-INT WINAPI NormalizeString(NORM_FORM NormForm, LPCWSTR lpSrcString, INT cwSrcLength,
- LPWSTR lpDstString, INT cwDstLength)
+INT WINAPI NormalizeString(NORM_FORM norm, LPCWSTR src, INT srclen,
+ LPWSTR dst, INT dstlen)
{
- FIXME("%x %p %d %p %d\n", NormForm, lpSrcString, cwSrcLength, lpDstString, cwDstLength);
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
- return 0;
+ extern int wine_unicode_decompose_string( int compat, const WCHAR *src,
+ int srclen, WCHAR *dst, int dstlen );
+ extern int unicode_canonical_composition( WCHAR *str, UINT strlen );
+ extern void unicode_canon_order( WCHAR *str, int strlen );
+
+ WCHAR *decomp = NULL;
+ INT compat = 0;
+ INT needed_len;
+
+ if (src == NULL || !is_valid_norm( norm ))
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return 0;
+ }
+
+ if (norm == NormalizationKC || norm == NormalizationKD) compat++;
+
+ if (srclen == -1) srclen = strlenW( src ) + 1;
+
+ needed_len = wine_unicode_decompose_string( compat, src, srclen, NULL, 0 );
+
+ if (needed_len < 0)
+ {
+ SetLastError(ERROR_NO_UNICODE_TRANSLATION);
+ return needed_len;
+ }
+
+ if (norm == NormalizationC || norm == NormalizationKC)
+ {
+ decomp = HeapAlloc( GetProcessHeap(), 0, needed_len * sizeof( WCHAR ) );
+ wine_unicode_decompose_string( compat, src, srclen, decomp, needed_len );
+ unicode_canon_order( decomp, needed_len );
+ needed_len = unicode_canonical_composition( decomp, needed_len );
+ }
+
+ if (dstlen < needed_len && dstlen > 0)
+ {
+ if (decomp) HeapFree(GetProcessHeap(), 0, decomp);
+ SetLastError(ERROR_INSUFFICIENT_BUFFER);
+ return -1;
+ }
+ else if (dstlen <= 0)
+ {
+ if (decomp) HeapFree(GetProcessHeap(), 0, decomp);
+ return needed_len;
+ }
+
+ if (norm == NormalizationC || norm == NormalizationKC)
+ {
+ memcpy( dst, decomp, sizeof(WCHAR) * needed_len );
+ HeapFree(GetProcessHeap(), 0, decomp);
+ return needed_len;
+ }
+ else
+ {
+ int decomp_len = wine_unicode_decompose_string( compat, src, srclen, dst, needed_len );
+ unicode_canon_order( dst, needed_len );
+ return decomp_len;
+ }
}
/******************************************************************************
diff --git a/dlls/kernel32/tests/locale.c b/dlls/kernel32/tests/locale.c
index b9b36d8a13..99edb19e97 100644
--- a/dlls/kernel32/tests/locale.c
+++ b/dlls/kernel32/tests/locale.c
@@ -5610,10 +5610,8 @@ static void test_NormalizeString(void)
return;
}
- todo_wine {
- dstlen = pNormalizeString( NormalizationD, ptest->str, -1, dst, 1 );
- ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Should have failed with ERROR_INSUFFICIENT_BUFFER");
- }
+ dstlen = pNormalizeString( NormalizationD, ptest->str, -1, dst, 1 );
+ ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Should have failed with ERROR_INSUFFICIENT_BUFFER");
/*
* For each string, first test passing -1 as srclen to NormalizeString,
@@ -5627,26 +5625,24 @@ static void test_NormalizeString(void)
for (i = 0; i < 4; i++)
{
- todo_wine {
- dstlen = pNormalizeString( norm_forms[i], ptest->str, -1, NULL, 0 );
- if (dstlen)
- {
- dstlen = pNormalizeString( norm_forms[i], ptest->str, -1, dst, dstlen );
- ok(dstlen == strlenW( ptest->expected[i] )+1, "Copied length differed: was %d, should be %d\n",
- dstlen, strlenW( ptest->expected[i] )+1);
- str_cmp = strncmpW( ptest->expected[i], dst, dstlen+1 );
- ok( str_cmp == 0, "test failed: returned value was %d\n", str_cmp );
- }
+ dstlen = pNormalizeString( norm_forms[i], ptest->str, -1, NULL, 0 );
+ if (dstlen)
+ {
+ dstlen = pNormalizeString( norm_forms[i], ptest->str, -1, dst, dstlen );
+ ok(dstlen == strlenW( ptest->expected[i] )+1, "Copied length differed: was %d, should be %d\n",
+ dstlen, strlenW( ptest->expected[i] )+1);
+ str_cmp = strncmpW( ptest->expected[i], dst, dstlen+1 );
+ ok( str_cmp == 0, "test failed: returned value was %d\n", str_cmp );
+ }
- dstlen = pNormalizeString( norm_forms[i], ptest->str, strlenW(ptest->str), NULL, 0 );
- if (dstlen)
- {
- dstlen = pNormalizeString( norm_forms[i], ptest->str, strlenW(ptest->str), dst, dstlen );
- ok(dstlen == strlenW( ptest->expected[i] ), "Copied length differed: was %d, should be %d\n",
- dstlen, strlenW( ptest->expected[i] ));
- str_cmp = strncmpW( ptest->expected[i], dst, dstlen );
- ok( str_cmp == 0, "test failed: returned value was %d\n", str_cmp );
- }
+ dstlen = pNormalizeString( norm_forms[i], ptest->str, strlenW(ptest->str), NULL, 0 );
+ if (dstlen)
+ {
+ dstlen = pNormalizeString( norm_forms[i], ptest->str, strlenW(ptest->str), dst, dstlen );
+ ok(dstlen == strlenW( ptest->expected[i] ), "Copied length differed: was %d, should be %d\n",
+ dstlen, strlenW( ptest->expected[i] ));
+ str_cmp = strncmpW( ptest->expected[i], dst, dstlen );
+ ok( str_cmp == 0, "test failed: returned value was %d\n", str_cmp );
}
}
ptest++;
--
2.14.1
More information about the wine-devel
mailing list