typedef struct CanonicalizationMap {
const char *id; /* input ID */
const char *canonicalID; /* canonicalized output ID */
- const char *keyword; /* keyword, or NULL if none */
- const char *value; /* keyword value, or NULL if kw==NULL */
} CanonicalizationMap;
/**
* different semantic kinds of transformations.
*/
static const CanonicalizationMap CANONICALIZE_MAP[] = {
- { "", "en_US_POSIX", NULL, NULL }, /* .NET name */
- { "c", "en_US_POSIX", NULL, NULL }, /* POSIX name */
- { "posix", "en_US_POSIX", NULL, NULL }, /* POSIX name (alias of C) */
- { "art_LOJBAN", "jbo", NULL, NULL }, /* registered name */
- { "az_AZ_CYRL", "az_Cyrl_AZ", NULL, NULL }, /* .NET name */
- { "az_AZ_LATN", "az_Latn_AZ", NULL, NULL }, /* .NET name */
- { "ca_ES_PREEURO", "ca_ES", "currency", "ESP" },
- { "de__PHONEBOOK", "de", "collation", "phonebook" }, /* Old ICU name */
- { "de_AT_PREEURO", "de_AT", "currency", "ATS" },
- { "de_DE_PREEURO", "de_DE", "currency", "DEM" },
- { "de_LU_PREEURO", "de_LU", "currency", "LUF" },
- { "el_GR_PREEURO", "el_GR", "currency", "GRD" },
- { "en_BE_PREEURO", "en_BE", "currency", "BEF" },
- { "en_IE_PREEURO", "en_IE", "currency", "IEP" },
- { "es__TRADITIONAL", "es", "collation", "traditional" }, /* Old ICU name */
- { "es_ES_PREEURO", "es_ES", "currency", "ESP" },
- { "eu_ES_PREEURO", "eu_ES", "currency", "ESP" },
- { "fi_FI_PREEURO", "fi_FI", "currency", "FIM" },
- { "fr_BE_PREEURO", "fr_BE", "currency", "BEF" },
- { "fr_FR_PREEURO", "fr_FR", "currency", "FRF" },
- { "fr_LU_PREEURO", "fr_LU", "currency", "LUF" },
- { "ga_IE_PREEURO", "ga_IE", "currency", "IEP" },
- { "gl_ES_PREEURO", "gl_ES", "currency", "ESP" },
- { "hi__DIRECT", "hi", "collation", "direct" }, /* Old ICU name */
- { "it_IT_PREEURO", "it_IT", "currency", "ITL" },
- { "ja_JP_TRADITIONAL", "ja_JP", "calendar", "japanese" }, /* Old ICU name */
- { "nb_NO_NY", "nn_NO", NULL, NULL }, /* "markus said this was ok" :-) */
- { "nl_BE_PREEURO", "nl_BE", "currency", "BEF" },
- { "nl_NL_PREEURO", "nl_NL", "currency", "NLG" },
- { "pt_PT_PREEURO", "pt_PT", "currency", "PTE" },
- { "sr_SP_CYRL", "sr_Cyrl_RS", NULL, NULL }, /* .NET name */
- { "sr_SP_LATN", "sr_Latn_RS", NULL, NULL }, /* .NET name */
- { "sr_YU_CYRILLIC", "sr_Cyrl_RS", NULL, NULL }, /* Linux name */
- { "th_TH_TRADITIONAL", "th_TH", "calendar", "buddhist" }, /* Old ICU name */
- { "uz_UZ_CYRILLIC", "uz_Cyrl_UZ", NULL, NULL }, /* Linux name */
- { "uz_UZ_CYRL", "uz_Cyrl_UZ", NULL, NULL }, /* .NET name */
- { "uz_UZ_LATN", "uz_Latn_UZ", NULL, NULL }, /* .NET name */
- { "zh_CHS", "zh_Hans", NULL, NULL }, /* .NET name */
- { "zh_CHT", "zh_Hant", NULL, NULL }, /* .NET name */
- { "zh_GAN", "gan", NULL, NULL }, /* registered name */
- { "zh_GUOYU", "zh", NULL, NULL }, /* registered name */
- { "zh_HAKKA", "hak", NULL, NULL }, /* registered name */
- { "zh_MIN_NAN", "nan", NULL, NULL }, /* registered name */
- { "zh_WUU", "wuu", NULL, NULL }, /* registered name */
- { "zh_XIANG", "hsn", NULL, NULL }, /* registered name */
- { "zh_YUE", "yue", NULL, NULL }, /* registered name */
-};
-
-typedef struct VariantMap {
- const char *variant; /* input ID */
- const char *keyword; /* keyword, or NULL if none */
- const char *value; /* keyword value, or NULL if kw==NULL */
-} VariantMap;
-
-static const VariantMap VARIANT_MAP[] = {
- { "EURO", "currency", "EUR" },
- { "PINYIN", "collation", "pinyin" }, /* Solaris variant */
- { "STROKE", "collation", "stroke" } /* Solaris variant */
+ { "", "en_US_POSIX" }, /* .NET name */ // open ICU 64 deleted, we restore
+ { "c", "en_US_POSIX" }, /* POSIX name */ // open ICU 64 deleted, we restore
+ { "posix", "en_US_POSIX" }, /* POSIX name (alias of C) */ // open ICU 64 deleted, we restore
+ { "art_LOJBAN", "jbo" }, /* registered name */
+ { "hy__AREVELA", "hy" }, /* Registered IANA variant */
+ { "hy__AREVMDA", "hyw" }, /* Registered IANA variant */
+ { "zh_GAN", "gan" }, /* registered name */
+ { "zh_GUOYU", "zh" }, /* registered name */
+ { "zh_HAKKA", "hak" }, /* registered name */
+ { "zh_MIN_NAN", "nan" }, /* registered name */
+ { "zh_WUU", "wuu" }, /* registered name */
+ { "zh_XIANG", "hsn" }, /* registered name */
+ { "zh_YUE", "yue" }, /* registered name */
};
/* ### BCP47 Conversion *******************************************/
return uprv_strcmp(leftString, rightString);
}
-/**
- * Both addKeyword and addValue must already be in canonical form.
- * Either both addKeyword and addValue are NULL, or neither is NULL.
- * If they are not NULL they must be zero terminated.
- * If addKeyword is not NULL is must have length small enough to fit in KeywordStruct.keyword.
- */
static int32_t
_getKeywords(const char *localeID,
char prev,
char *keywords, int32_t keywordCapacity,
char *values, int32_t valuesCapacity, int32_t *valLen,
UBool valuesToo,
- const char* addKeyword,
- const char* addValue,
UErrorCode *status)
{
KeywordStruct keywordList[ULOC_MAX_NO_KEYWORDS];
}
} while(pos);
- /* Handle addKeyword/addValue. */
- if (addKeyword != NULL) {
- UBool duplicate = FALSE;
- U_ASSERT(addValue != NULL);
- /* Search for duplicate; if found, do nothing. Explicit keyword
- overrides addKeyword. */
- for (j=0; j<numKeywords; ++j) {
- if (uprv_strcmp(keywordList[j].keyword, addKeyword) == 0) {
- duplicate = TRUE;
- break;
- }
- }
- if (!duplicate) {
- if (numKeywords == maxKeywords) {
- *status = U_INTERNAL_PROGRAM_ERROR;
- return 0;
- }
- uprv_strcpy(keywordList[numKeywords].keyword, addKeyword);
- keywordList[numKeywords].keywordLen = (int32_t)uprv_strlen(addKeyword);
- keywordList[numKeywords].valueStart = addValue;
- keywordList[numKeywords].valueLen = (int32_t)uprv_strlen(addValue);
- ++numKeywords;
- }
- } else {
- U_ASSERT(addValue == NULL);
- }
-
/* now we have a list of keywords */
/* we need to sort it */
uprv_sortArray(keywordList, numKeywords, sizeof(KeywordStruct), compareKeywordStructs, NULL, FALSE, status);
}
keywordsLen += keywordList[i].keywordLen + 1;
if(valuesToo) {
- if(keywordsLen + keywordList[i].valueLen < keywordCapacity) {
+ if(keywordsLen + keywordList[i].valueLen <= keywordCapacity) {
uprv_strncpy(keywords+keywordsLen, keywordList[i].valueStart, keywordList[i].valueLen);
}
keywordsLen += keywordList[i].valueLen;
UErrorCode *status) {
return _getKeywords(localeID, prev, keywords, keywordCapacity,
values, valuesCapacity, valLen, valuesToo,
- NULL, NULL, status);
+ status);
}
U_CAPI int32_t U_EXPORT2
keyValuePrefix = ';'; /* for any subsequent key-value pair */
updatedKeysAndValues.append(localeKeywordNameBuffer, keyValueLen, *status);
updatedKeysAndValues.append('=', *status);
- updatedKeysAndValues.append(nextEqualsign, keyValueTail-nextEqualsign, *status);
+ updatedKeysAndValues.append(nextEqualsign, static_cast<int32_t>(keyValueTail-nextEqualsign), *status);
}
if (!nextSeparator && keywordValueLen > 0 && !handledInputKeyAndValue) {
/* append new entry at the end, it sorts later than existing entries */
*/
#define _isTerminator(a) ((a==0)||(a=='.')||(a=='@'))
-static char* _strnchr(const char* str, int32_t len, char c) {
- U_ASSERT(str != 0 && len >= 0);
- while (len-- != 0) {
- char d = *str;
- if (d == c) {
- return (char*) str;
- } else if (d == 0) {
- break;
- }
- ++str;
- }
- return NULL;
-}
-
/**
* Lookup 'key' in the array 'list'. The array 'list' should contain
* a NULL entry, followed by more entries, and a second NULL entry.
return _getVariantEx(localeID, prev, variant, variantCapacity, FALSE);
}
-/**
- * Delete ALL instances of a variant from the given list of one or
- * more variants. Example: "FOO_EURO_BAR_EURO" => "FOO_BAR".
- * @param variants the source string of one or more variants,
- * separated by '_'. This will be MODIFIED IN PLACE. Not zero
- * terminated; if it is, trailing zero will NOT be maintained.
- * @param variantsLen length of variants
- * @param toDelete variant to delete, without separators, e.g. "EURO"
- * or "PREEURO"; not zero terminated
- * @param toDeleteLen length of toDelete
- * @return number of characters deleted from variants
- */
-static int32_t
-_deleteVariant(char* variants, int32_t variantsLen,
- const char* toDelete, int32_t toDeleteLen)
-{
- int32_t delta = 0; /* number of chars deleted */
- for (;;) {
- UBool flag = FALSE;
- if (variantsLen < toDeleteLen) {
- return delta;
- }
- if (uprv_strncmp(variants, toDelete, toDeleteLen) == 0 &&
- (variantsLen == toDeleteLen ||
- (flag=(variants[toDeleteLen] == '_'))))
- {
- int32_t d = toDeleteLen + (flag?1:0);
- variantsLen -= d;
- delta += d;
- if (variantsLen > 0) {
- uprv_memmove(variants, variants+d, variantsLen);
- }
- } else {
- char* p = _strnchr(variants, variantsLen, '_');
- if (p == NULL) {
- return delta;
- }
- ++p;
- variantsLen -= (int32_t)(p - variants);
- variants = p;
- }
- }
-}
-
/* Keyword enumeration */
typedef struct UKeywordsContext {
const char* tmpLocaleID;
const char* keywordAssign = NULL;
const char* separatorIndicator = NULL;
- const char* addKeyword = NULL;
- const char* addValue = NULL;
char* name;
char* variant = NULL; /* pointer into name, or NULL */
len = (int32_t)uprv_strlen(d);
if (name != NULL) {
- uprv_strncpy(name, d, len);
+ uprv_memcpy(name, d, len);
}
} else if(_isIDSeparator(*tmpLocaleID)) {
const char *scriptID;
}
}
- /* Handle generic variants first */
- if (variant) {
- for (j=0; j<UPRV_LENGTHOF(VARIANT_MAP); j++) {
- const char* variantToCompare = VARIANT_MAP[j].variant;
- int32_t n = (int32_t)uprv_strlen(variantToCompare);
- int32_t variantLen = _deleteVariant(variant, uprv_min(variantSize, (nameCapacity-len)), variantToCompare, n);
- len -= variantLen;
- if (variantLen > 0) {
- if (len > 0 && name[len-1] == '_') { /* delete trailing '_' */
- --len;
- }
- addKeyword = VARIANT_MAP[j].keyword;
- addValue = VARIANT_MAP[j].value;
- break;
- }
- }
- if (len > 0 && len <= nameCapacity && name[len-1] == '_') { /* delete trailing '_' */
- --len;
- }
- }
-
/* Look up the ID in the canonicalization map */
for (j=0; j<UPRV_LENGTHOF(CANONICALIZE_MAP); j++) {
const char* id = CANONICALIZE_MAP[j].id;
break; /* Don't remap "" if keywords present */
}
len = _copyCount(name, nameCapacity, CANONICALIZE_MAP[j].canonicalID);
- if (CANONICALIZE_MAP[j].keyword) {
- addKeyword = CANONICALIZE_MAP[j].keyword;
- addValue = CANONICALIZE_MAP[j].value;
- }
break;
}
}
++len;
++fieldCount;
len += _getKeywords(tmpLocaleID+1, '@', (len<nameCapacity ? name+len : NULL), nameCapacity-len,
- NULL, 0, NULL, TRUE, addKeyword, addValue, err);
- } else if (addKeyword != NULL) {
- U_ASSERT(addValue != NULL && len < nameCapacity);
- /* inelegant but works -- later make _getKeywords do this? */
- len += _copyCount(name+len, nameCapacity-len, "@");
- len += _copyCount(name+len, nameCapacity-len, addKeyword);
- len += _copyCount(name+len, nameCapacity-len, "=");
- len += _copyCount(name+len, nameCapacity-len, addValue);
+ NULL, 0, NULL, TRUE, err);
}
}
if(i>0 && parent != localeID) {
uprv_memcpy(parent, localeID, uprv_min(i, parentCapacity));
}
+
return u_terminateChars(parent, parentCapacity, i, err);
}
return 0;
}
- // Attempt platform lookup if available
- lcid = uprv_convertToLCIDPlatform(localeID);
- if (lcid > 0)
- {
+ // First, attempt Windows platform lookup if available, but fall
+ // through to catch any special cases (ICU vs Windows name differences).
+ lcid = uprv_convertToLCIDPlatform(localeID, &status);
+ if (U_FAILURE(status)) {
+ return 0;
+ }
+ if (lcid > 0) {
// Windows found an LCID, return that
return lcid;
}
uloc_getLanguage(localeID, langID, sizeof(langID), &status);
- if (U_FAILURE(status)) {
+ if (U_FAILURE(status) || status == U_STRING_NOT_TERMINATED_WARNING) {
return 0;
}
/* eat spaces prior to semi */
for(t=(paramEnd-1);(paramEnd>s)&&isspace(*t);t--)
;
- int32_t slen = ((t+1)-s);
+ int32_t slen = static_cast<int32_t>(((t+1)-s));
if(slen > ULOC_FULLNAME_CAPACITY) {
*status = U_BUFFER_OVERFLOW_ERROR;
return -1; // too big