From 91675f0352ae7ca1f5a541df8b0bd9d2f3ac225c Mon Sep 17 00:00:00 2001 From: Daniel Lehman Date: Mon, 15 Aug 2016 10:54:20 -0700 Subject: [PATCH] kernel32: Add GetNumberFormatEx Signed-off-by: Daniel Lehman --- dlls/kernel32/kernel32.spec | 2 +- dlls/kernel32/lcformat.c | 19 +++++ dlls/kernel32/tests/locale.c | 185 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 205 insertions(+), 1 deletion(-) diff --git a/dlls/kernel32/kernel32.spec b/dlls/kernel32/kernel32.spec index 1d435ee..8a20240 100644 --- a/dlls/kernel32/kernel32.spec +++ b/dlls/kernel32/kernel32.spec @@ -751,7 +751,7 @@ # @ stub GetNumaProximityNode # @ stub GetNumaProximityNodeEx @ stdcall GetNumberFormatA(long long str ptr ptr long) -# @ stub GetNumberFormatEx +@ stdcall GetNumberFormatEx(wstr long wstr ptr ptr long) @ stdcall GetNumberFormatW(long long wstr ptr ptr long) @ stdcall GetNumberOfConsoleFonts() @ stdcall GetNumberOfConsoleInputEvents(long ptr) diff --git a/dlls/kernel32/lcformat.c b/dlls/kernel32/lcformat.c index c8a9746..057b733 100644 --- a/dlls/kernel32/lcformat.c +++ b/dlls/kernel32/lcformat.c @@ -1345,6 +1345,25 @@ error: } /************************************************************************** + * GetNumberFormatEx (KERNEL32.@) + */ +INT WINAPI GetNumberFormatEx(LPCWSTR name, DWORD flags, + LPCWSTR value, const NUMBERFMTW *format, + LPWSTR number, int numout) +{ + LCID lcid; + + TRACE("(%s,0x%08x,%s,%p,%p,%d)\n", debugstr_w(name), flags, + debugstr_w(value), format, number, numout); + + lcid = LocaleNameToLCID(name, 0); + if (!lcid) + return 0; + + return GetNumberFormatW(lcid, flags, value, format, number, numout); +} + +/************************************************************************** * GetCurrencyFormatA (KERNEL32.@) * * Format a currency string for a given locale. diff --git a/dlls/kernel32/tests/locale.c b/dlls/kernel32/tests/locale.c index 4f472db..7cb7859 100644 --- a/dlls/kernel32/tests/locale.c +++ b/dlls/kernel32/tests/locale.c @@ -99,6 +99,7 @@ static BOOL (WINAPI *pEnumSystemGeoID)(GEOCLASS, GEOID, GEO_ENUMPROC); static BOOL (WINAPI *pGetSystemPreferredUILanguages)(DWORD, ULONG*, WCHAR*, ULONG*); static BOOL (WINAPI *pGetThreadPreferredUILanguages)(DWORD, ULONG*, WCHAR*, ULONG*); static WCHAR (WINAPI *pRtlUpcaseUnicodeChar)(WCHAR); +static INT (WINAPI *pGetNumberFormatEx)(LPCWSTR, DWORD, LPCWSTR, const NUMBERFMTW *, LPWSTR, int); static void InitFunctionPointers(void) { @@ -129,6 +130,7 @@ static void InitFunctionPointers(void) X(EnumSystemGeoID); X(GetSystemPreferredUILanguages); X(GetThreadPreferredUILanguages); + X(GetNumberFormatEx); mod = GetModuleHandleA("ntdll"); X(RtlUpcaseUnicodeChar); @@ -1590,6 +1592,188 @@ static void test_GetNumberFormatA(void) } } +static void test_GetNumberFormatEx(void) +{ + int ret; + NUMBERFMTW format; + static WCHAR dotW[] = {'.',0}; + static WCHAR commaW[] = {',',0}; + static const WCHAR enW[] = {'e','n','-','U','S',0}; + static const WCHAR frW[] = {'f','r','-','F','R',0}; + static const WCHAR bogusW[] = {'b','o','g','u','s',0}; + WCHAR buffer[BUFFER_SIZE], input[BUFFER_SIZE], Expected[BUFFER_SIZE]; + + if (!pGetNumberFormatEx) + { + win_skip("GetNumberFormatEx is not available.\n"); + return; + } + + STRINGSW("23",""); /* NULL output, length > 0 --> Error */ + ret = pGetNumberFormatEx(enW, 0, input, NULL, NULL, COUNTOF(buffer)); + ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER, + "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); + + STRINGSW("23,53",""); /* Invalid character --> Error */ + ret = pGetNumberFormatEx(enW, 0, input, NULL, buffer, COUNTOF(buffer)); + ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER, + "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); + + STRINGSW("--",""); /* Double '-' --> Error */ + ret = pGetNumberFormatEx(enW, 0, input, NULL, buffer, COUNTOF(buffer)); + ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER, + "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); + + STRINGSW("0-",""); /* Trailing '-' --> Error */ + ret = pGetNumberFormatEx(enW, 0, input, NULL, buffer, COUNTOF(buffer)); + ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER, + "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); + + STRINGSW("0..",""); /* Double '.' --> Error */ + ret = pGetNumberFormatEx(enW, 0, input, NULL, buffer, COUNTOF(buffer)); + ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER, + "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); + + STRINGSW(" 0.1",""); /* Leading space --> Error */ + ret = pGetNumberFormatEx(enW, 0, input, NULL, buffer, COUNTOF(buffer)); + ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER, + "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); + + STRINGSW("1234","1"); /* Length too small --> Write up to length chars */ + ret = pGetNumberFormatEx(enW, NUO, input, NULL, buffer, 2); + ok( !ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, + "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError()); + + STRINGSW("23",""); /* Bogus locale --> Error */ + ret = pGetNumberFormatEx(bogusW, NUO, input, NULL, buffer, COUNTOF(buffer)); + ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER, + "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); + + memset(&format, 0, sizeof(format)); + + STRINGSW("2353",""); /* Format and flags given --> Error */ + ret = pGetNumberFormatEx(enW, NUO, input, &format, buffer, COUNTOF(buffer)); + ok( !ret, "Expected ret == 0, got %d\n", ret); + ok( GetLastError() == ERROR_INVALID_FLAGS || GetLastError() == ERROR_INVALID_PARAMETER, + "Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError()); + + STRINGSW("2353",""); /* Invalid format --> Error */ + ret = pGetNumberFormatEx(enW, 0, input, &format, buffer, COUNTOF(buffer)); + ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER, + "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); + + STRINGSW("2353","2,353.00"); /* Valid number */ + ret = pGetNumberFormatEx(enW, NUO, input, NULL, buffer, COUNTOF(buffer)); + ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError()); + EXPECT_LENW; EXPECT_EQW; + + STRINGSW("-2353","-2,353.00"); /* Valid negative number */ + ret = pGetNumberFormatEx(enW, NUO, input, NULL, buffer, COUNTOF(buffer)); + ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError()); + EXPECT_LENW; EXPECT_EQW; + + STRINGSW("-353","-353.00"); /* test for off by one error in grouping */ + ret = pGetNumberFormatEx(enW, NUO, input, NULL, buffer, COUNTOF(buffer)); + ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError()); + EXPECT_LENW; EXPECT_EQW; + + STRINGSW("2353.1","2,353.10"); /* Valid real number */ + ret = pGetNumberFormatEx(enW, NUO, input, NULL, buffer, COUNTOF(buffer)); + ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError()); + EXPECT_LENW; EXPECT_EQW; + + STRINGSW("2353.111","2,353.11"); /* Too many DP --> Truncated */ + ret = pGetNumberFormatEx(enW, NUO, input, NULL, buffer, COUNTOF(buffer)); + ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError()); + EXPECT_LENW; EXPECT_EQW; + + STRINGSW("2353.119","2,353.12"); /* Too many DP --> Rounded */ + ret = pGetNumberFormatEx(enW, NUO, input, NULL, buffer, COUNTOF(buffer)); + ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError()); + EXPECT_LENW; EXPECT_EQW; + + format.NumDigits = 0; /* No decimal separator */ + format.LeadingZero = 0; + format.Grouping = 0; /* No grouping char */ + format.NegativeOrder = 0; + format.lpDecimalSep = dotW; + format.lpThousandSep = commaW; + + STRINGSW("2353","2353"); /* No decimal or grouping chars expected */ + ret = pGetNumberFormatEx(enW, 0, input, &format, buffer, COUNTOF(buffer)); + ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError()); + EXPECT_LENW; EXPECT_EQW; + + format.NumDigits = 1; /* 1 DP --> Expect decimal separator */ + STRINGSW("2353","2353.0"); + ret = pGetNumberFormatEx(enW, 0, input, &format, buffer, COUNTOF(buffer)); + ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError()); + EXPECT_LENW; EXPECT_EQW; + + format.Grouping = 2; /* Group by 100's */ + STRINGSW("2353","23,53.0"); + ret = pGetNumberFormatEx(enW, 0, input, &format, buffer, COUNTOF(buffer)); + ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError()); + EXPECT_LENW; EXPECT_EQW; + + STRINGSW("235","235.0"); /* Grouping of a positive number */ + format.Grouping = 3; + ret = pGetNumberFormatEx(enW, 0, input, &format, buffer, COUNTOF(buffer)); + ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError()); + EXPECT_LENW; EXPECT_EQW; + + STRINGSW("-235","-235.0"); /* Grouping of a negative number */ + format.NegativeOrder = NEG_LEFT; + ret = pGetNumberFormatEx(enW, 0, input, &format, buffer, COUNTOF(buffer)); + ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError()); + EXPECT_LENW; EXPECT_EQW; + + format.LeadingZero = 1; /* Always provide leading zero */ + STRINGSW(".5","0.5"); + ret = pGetNumberFormatEx(enW, 0, input, &format, buffer, COUNTOF(buffer)); + ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError()); + EXPECT_LENW; EXPECT_EQW; + + format.NegativeOrder = NEG_PARENS; + STRINGSW("-1","(1.0)"); + ret = pGetNumberFormatEx(enW, 0, input, &format, buffer, COUNTOF(buffer)); + ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError()); + EXPECT_LENW; EXPECT_EQW; + + format.NegativeOrder = NEG_LEFT; + STRINGSW("-1","-1.0"); + ret = pGetNumberFormatEx(enW, 0, input, &format, buffer, COUNTOF(buffer)); + ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError()); + EXPECT_LENW; EXPECT_EQW; + + format.NegativeOrder = NEG_LEFT_SPACE; + STRINGSW("-1","- 1.0"); + ret = pGetNumberFormatEx(enW, 0, input, &format, buffer, COUNTOF(buffer)); + ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError()); + EXPECT_LENW; EXPECT_EQW; + + format.NegativeOrder = NEG_RIGHT; + STRINGSW("-1","1.0-"); + ret = pGetNumberFormatEx(enW, 0, input, &format, buffer, COUNTOF(buffer)); + ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError()); + EXPECT_LENW; EXPECT_EQW; + + format.NegativeOrder = NEG_RIGHT_SPACE; + STRINGSW("-1","1.0 -"); + ret = pGetNumberFormatEx(enW, 0, input, &format, buffer, COUNTOF(buffer)); + ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError()); + EXPECT_LENW; EXPECT_EQW; + + if (pIsValidLocaleName(frW)) + { + STRINGSW("-12345","-12 345,00"); /* Try French formatting */ + Expected[3] = 160; /* Non breaking space */ + ret = pGetNumberFormatEx(frW, NUO, input, NULL, buffer, COUNTOF(buffer)); + ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError()); + EXPECT_LENW; EXPECT_EQW; + } +} + struct comparestringa_entry { LCID lcid; DWORD flags; @@ -4850,6 +5034,7 @@ START_TEST(locale) test_GetDateFormatW(); test_GetCurrencyFormatA(); /* Also tests the W version */ test_GetNumberFormatA(); /* Also tests the W version */ + test_GetNumberFormatEx(); test_CompareStringA(); test_CompareStringW(); test_CompareStringEx(); -- 1.9.5