ICU-700 Windows locale mapping works better now with variants

X-SVN-Rev: 2828
This commit is contained in:
George Rhoten 2000-10-28 00:39:54 +00:00
parent 87ef71b49b
commit fa4d7c34d9
4 changed files with 193 additions and 61 deletions

View File

@ -4,7 +4,7 @@
* Corporation and others. All Rights Reserved.
**********************************************************************
*/
// $Revision: 1.16 $
// $Revision: 1.17 $
//
// Provides functionality for mapping between
// LCID and Posix IDs.
@ -55,16 +55,28 @@ struct ILcidPosixElement
struct ILcidPosixMap
{
uint32_t hostID(const char* fromPosixID) const;
const char* posixID(uint32_t fromHostID) const;
// static const char* fgWildCard;
/**
* Searches for a Windows LCID
*
* @param posixid the Posix style locale id.
* @param status gets set to U_ILLEGAL_ARGUMENT_ERROR when the Posix ID has
* no equivalent Windows LCID.
* @return the LCID
*/
uint32_t hostID(const char* fromPosixID) const;
// uint16_t hostLangID;
// const char *posixLangID;
/**
* Do not call this function. It is called by hostID.
* The function is not private because this struct must stay as a C struct,
* and this is an internal class.
*/
uint32_t searchPosixIDmap(const char* posixID, UErrorCode* status) const;
uint32_t numRegions;
const ILcidPosixElement* regionMaps;
};
/////////////////////////////////////////////////
@ -299,9 +311,9 @@ static const ILcidPosixElement sv[] = {
{0x041d, "sv_SE"}
};
ILCID_POSIX_ELEMENT_ARRAY(0x0441, sw, sw_KE) // The MSJDK documentation says the default country is Kenya.
ILCID_POSIX_ELEMENT_ARRAY(0x0441, sw, sw_KE)// The MSJDK documentation says the default country is Kenya.
ILCID_POSIX_ELEMENT_ARRAY(0x0449, ta, ta_IN)
ILCID_POSIX_ELEMENT_ARRAY(0x044a, te, te_IN) //Todo: Data does not exist
ILCID_POSIX_ELEMENT_ARRAY(0x044a, te, te_IN)
ILCID_POSIX_ELEMENT_ARRAY(0x041e, th, th_TH)
ILCID_POSIX_ELEMENT_ARRAY(0x041f, tr, tr_TR)
ILCID_POSIX_ELEMENT_ARRAY(0x0444, tt, tt_RU) //Todo: Data does not exist
@ -663,7 +675,7 @@ IGlobalLocales::convertToLCID(const char* posixID, UErrorCode* status)
uint32_t mid;
uint32_t high = LocaleCount - 1;
int32_t compVal;
char langID[256];
char langID[ULOC_FULLNAME_CAPACITY];
// Check for incomplete id.
if (!posixID || uprv_strlen(posixID) < 2)
@ -694,7 +706,7 @@ IGlobalLocales::convertToLCID(const char* posixID, UErrorCode* status)
// no match found
*status = U_ILLEGAL_ARGUMENT_ERROR;
return 0;
return 0; // return international (root)
}
@ -703,17 +715,87 @@ IGlobalLocales::convertToLCID(const char* posixID, UErrorCode* status)
uint32_t
ILcidPosixMap::hostID(const char* posixID) const
{
uint32_t low = 1;
uint32_t mid;
uint32_t high = numRegions;
int32_t compVal;
UErrorCode status = U_ZERO_ERROR;
char hostID[ULOC_FULLNAME_CAPACITY];
char *hostPtr = hostID;
uint32_t value;
uint32_t hostLen = strlen(posixID);
int32_t size, hostSize;
// Check for incomplete id. All LCIDs have a default country,
// and a 0x0400 in 0xFC00 indicates a default country.
// So Windows may not like hostLangID without a default
// country.
if (!numRegions || strlen(posixID) < 5)
if (!numRegions || hostLen < 5)
return regionMaps->hostID;
if (hostLen >= ULOC_FULLNAME_CAPACITY)
hostLen = ULOC_FULLNAME_CAPACITY - 1;
// We do this because the posixID may have a '-' separator and
// incorrect string case
hostSize = uloc_getLanguage(posixID,
hostID,
ULOC_LANG_CAPACITY + 1,
&status);
if (U_SUCCESS(status))
{
hostPtr += hostSize;
hostPtr[-1] = '_';
size = uloc_getCountry(posixID,
hostPtr,
ULOC_COUNTRY_CAPACITY + 1,
&status);
hostSize += size - 1;
if (U_SUCCESS(status) && hostSize < hostLen)
{
hostPtr += size;
hostPtr[-1] = '_';
uloc_getVariant(posixID, hostPtr, hostLen - size, &status);
}
}
// Try to find it the first time.
value = searchPosixIDmap(hostID, &status);
if (U_SUCCESS(status)) {
return value;
}
// Couldn't find it. Cut off the last part of the locale
while (hostPtr > hostID && *hostPtr != '_')
{
hostPtr--;
}
if (*hostPtr == '_')
{
*hostPtr = 0;
}
// Try it again without the last part of the locale
status = U_ZERO_ERROR;
value = searchPosixIDmap(hostID, &status);
if (U_SUCCESS(status)) {
return value;
}
// No match found. Return the language
return regionMaps->hostID;
}
/**
* Searches for a Windows LCID
*
* @param posixid the Posix style locale id.
* @param status gets set to U_ILLEGAL_ARGUMENT_ERROR when the Posix ID has
* no equivalent Windows LCID.
* @return the LCID
*/
uint32_t
ILcidPosixMap::searchPosixIDmap(const char* posixID, UErrorCode* status) const
{
uint32_t low = 1;
uint32_t mid;
uint32_t high = numRegions;
int32_t compVal;
// Binary search for the map entry
// The element at index 0 is always the POSIX wild card,
@ -733,9 +815,11 @@ ILcidPosixMap::hostID(const char* posixID) const
}
//no match found
*status = U_ILLEGAL_ARGUMENT_ERROR;
return regionMaps->hostID;
}
const char*
ILcidPosixMap::posixID(uint32_t hostID) const
{

View File

@ -6,7 +6,7 @@
*
*****************************************************************************************
*/
// $Revision: 1.10 $
// $Revision: 1.11 $
//===============================================================================
//
// File locmap.hpp : Locale Mapping Classes
@ -46,6 +46,7 @@ public:
* @param hostid the Windows LCID number.
* @param status gets set to U_ILLEGAL_ARGUMENT_ERROR when the LCID has no
* equivalent ICU locale.
* @return ICU locale
*/
static const char* convertToPosix(uint32_t hostid, UErrorCode* status);
@ -56,6 +57,7 @@ public:
* @param posixid the Posix style locale id.
* @param status gets set to U_ILLEGAL_ARGUMENT_ERROR when the Posix ID has
* no equivalent Windows LCID.
* @return the LCID
*/
static uint32_t convertToLCID(const char* posixID, UErrorCode* status);
@ -66,6 +68,7 @@ public:
* ID.
*
* @param hostid the Windows LCID number.
* @return the language part of the LCID
*/
static inline uint16_t languageLCID(uint32_t hostID) {return LANGUAGE_LCID(hostID);}
@ -78,7 +81,7 @@ protected:
static void initializeMapRegions(void);
private:
static uint32_t LocaleCount;
static ILcidPosixMap* PosixIDmap;

View File

@ -14,10 +14,90 @@
#include "cstring.h"
#include "unicode/resbund.h"
static void
testLCID(const char *localeName);
static void
testLCID(const char *localeName,
const UnicodeString &posixName,
uint32_t *errors,
uint32_t *warnings)
{
UErrorCode status = U_ZERO_ERROR;
uint32_t lcid;
uint32_t expectedLCID;
char lcidStringC[1024];
ResourceBundle posixLocale((char *)0, Locale(posixName), status);
if(status != U_ZERO_ERROR) {
if(U_SUCCESS(status)) {
printf("ERROR: Locale %-5s not installed, and it should be!\n", localeName);
} else {
printf("%%%%%%% Unexpected error %d %%%%%%%", u_errorName(status));
}
(*errors)++;
return;
}
UnicodeString lcidString(posixLocale.getStringEx("LocaleID", status));
if (U_FAILURE(status)) {
printf("ERROR: %s does not have a LocaleID (%s)\n", localeName, u_errorName(status));
(*errors)++;
return;
}
lcidString.extract(0, lcidString.length(), lcidStringC, "");
lcidStringC[lcidString.length()] = '\0';
expectedLCID = uprv_strtoul(lcidStringC, NULL, 16);
lcid = IGlobalLocales::convertToLCID(localeName, &status);
if (U_FAILURE(status)) {
printf("WARNING: %-5s does not have an LCID mapping\n", localeName);
(*warnings)++;
return;
}
status = U_ZERO_ERROR;
uprv_strcpy(lcidStringC, IGlobalLocales::convertToPosix(expectedLCID, &status));
if (U_FAILURE(status)) {
printf("ERROR: %.4x does not have a POSIX mapping due to %s\n", expectedLCID, u_errorName(status));
(*errors)++;
}
if(lcid != expectedLCID) {
printf("ERROR: Locale %-5s wrongfully has 0x%.4x instead of 0x%.4x for LCID\n", localeName, expectedLCID, lcid);
(*errors)++;
}
if(strcmp(localeName, lcidStringC) != 0) {
char langName[1024];
char langLCID[1024];
uloc_getLanguage(localeName, langName, sizeof(langName), &status);
uloc_getLanguage(lcidStringC, langLCID, sizeof(langLCID), &status);
if (expectedLCID == lcid && strcmp(langName, langLCID) == 0) {
printf("WARNING: %-5s resolves to %s (0x%.4x)\n", localeName, lcidStringC, lcid);
(*warnings)++;
}
else if (expectedLCID == lcid) {
printf("ERROR: 0x%.4x is from %-5s and the number resolves wrongfully to %s\n", expectedLCID, localeName, lcidStringC);
(*errors)++;
}
else {
printf("ERROR: 0x%.4x is from %-5s and the number resolves wrongfully to %s. It should be 0x%x.\n", expectedLCID, localeName, lcidStringC, lcid);
(*errors)++;
}
} else {
//printf("0x%x is from %s and it resolves correctly to %s(0x%x)\n", expectedLCID, localeName, lcidStringC, lcid);
//printf("%s: %x->%x\n", localeName, expectedLCID, lcid);
}
}
int main() {
UErrorCode status = U_ZERO_ERROR;
ResourceBundle index((char *)0, Locale("index"), status);
uint32_t errors = 0;
uint32_t warnings = 0;
if(U_SUCCESS(status)) {
ResourceBundle installedLocales = index.get("InstalledLocales", status);
@ -25,51 +105,11 @@ int main() {
installedLocales.resetIterator();
while(installedLocales.hasNext()) {
char localeName[1024];
uint32_t lcid;
UnicodeString posixName = installedLocales.getNextString(status);
posixName.extract(0, posixName.length(), localeName, "");
localeName[posixName.length()] = '\0';
ResourceBundle posixLocale((char *)0, Locale(posixName), status);
if(status == U_ZERO_ERROR) {
UnicodeString lcidString = posixLocale.getStringEx("LocaleID", status);
char lcidStringC[1024];
lcidString.extract(0, lcidString.length(), lcidStringC, "");
lcidStringC[lcidString.length()] = '\0';
uint32_t expectedLCID = uprv_strtoul(lcidStringC, NULL, 16);
status = U_ZERO_ERROR;
lcid = IGlobalLocales::convertToLCID(localeName, &status);
if (U_FAILURE(status)) {
printf("WARNING: %s does not have an LCID mapping (%s)\n", localeName, u_errorName(status));
status = U_ZERO_ERROR;
}
else {
status = U_ZERO_ERROR;
uprv_strcpy(lcidStringC, IGlobalLocales::convertToPosix(expectedLCID, &status));
if (U_FAILURE(status)) {
printf("ERROR: %x does not have an POSIX mapping due to error %s\n", expectedLCID, u_errorName(status));
}
if(strcmp(localeName, lcidStringC) == 0) {
//printf("0x%x is from %s and it resolves correctly to %s(0x%x)\n", expectedLCID, localeName, lcidStringC, lcid);
//printf("%s: %x->%x\n", localeName, expectedLCID, lcid);
} else {
printf("ERROR: 0x%x is from %s and it resolves wrongfully to %s, it should have (0x%x)\n", expectedLCID, localeName, lcidStringC, lcid);
//printf("Name mismatch: %s vs. %s: %x->%x\n", localeName, lcidStringC, expectedLCID, lcid);
errors++;
}
if(lcid != expectedLCID) {
printf("ERROR: Locale %s wrongfully has 0x%x instead of 0x%x for LCID\n", localeName, expectedLCID, lcid);
//printf("LCID mismatch: %s: %x->%x\n", localeName, expectedLCID, lcid);
errors++;
}
}
} else if(U_SUCCESS(status)) {
printf("ERROR: Locale %s not installed, and it should be!\n", localeName);
errors++;
} else {
printf("%%%%%%% Unexpected error %d %%%%%%%", status);
}
testLCID(localeName, posixName, &errors, &warnings);
}
}
}
@ -79,6 +119,10 @@ int main() {
printf("There were no errors\n");
}
if(warnings > 0) {
printf("There were %d warning(s)\n", warnings);
}
char temp;
scanf("%c", &temp);

View File

@ -39,9 +39,10 @@ RSC=rc.exe
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
# ADD CPP /nologo /W3 /GX /O2 /I "../../../include" /I "../../common" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
@ -49,7 +50,7 @@ BSC32=bscmake.exe
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
# ADD LINK32 icuuc17.lib /nologo /subsystem:console /machine:I386 /libpath:"../../../lib" /libpath:"../../common/Release"
!ELSEIF "$(CFG)" == "lcid - Win32 Debug"
@ -73,7 +74,7 @@ BSC32=bscmake.exe
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
# ADD LINK32 icuuc.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"../../../lib/debug" /libpath:"../../common/debug"
# ADD LINK32 icuuc17d.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept /libpath:"../../../lib" /libpath:"../../common/debug"
# SUBTRACT LINK32 /incremental:no
!ENDIF