mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-08 16:58:38 +09:00
Issue #1971 - Part 2: Update ICU source to 63.2.
This commit is contained in:
parent
8df84683be
commit
1e69214382
3160 changed files with 275815 additions and 234203 deletions
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (C) 2016 and later: Unicode, Inc. and others.
|
||||
// © 2016 and later: Unicode, Inc. and others.
|
||||
// License & terms of use: http://www.unicode.org/copyright.html
|
||||
/*
|
||||
**********************************************************************
|
||||
|
|
@ -44,10 +44,11 @@
|
|||
#include "uarrsort.h"
|
||||
#include "uenumimp.h"
|
||||
#include "uassert.h"
|
||||
#include "charstr.h"
|
||||
|
||||
#include <stdio.h> /* for sprintf */
|
||||
|
||||
using namespace icu;
|
||||
U_NAMESPACE_USE
|
||||
|
||||
/* ### Declarations **************************************************/
|
||||
|
||||
|
|
@ -97,18 +98,19 @@ locale_getKeywords(const char *localeID,
|
|||
*/
|
||||
/* Generated using org.unicode.cldr.icu.GenerateISO639LanguageTables */
|
||||
/* ISO639 table version is 20150505 */
|
||||
/* Subsequent hand addition of selected languages */
|
||||
static const char * const LANGUAGES[] = {
|
||||
"aa", "ab", "ace", "ach", "ada", "ady", "ae", "aeb",
|
||||
"af", "afh", "agq", "ain", "ak", "akk", "akz", "ale",
|
||||
"aln", "alt", "am", "an", "ang", "anp", "ar", "arc",
|
||||
"arn", "aro", "arp", "arq", "arw", "ary", "arz", "as",
|
||||
"arn", "aro", "arp", "arq", "ars", "arw", "ary", "arz", "as",
|
||||
"asa", "ase", "ast", "av", "avk", "awa", "ay", "az",
|
||||
"ba", "bal", "ban", "bar", "bas", "bax", "bbc", "bbj",
|
||||
"be", "bej", "bem", "bew", "bez", "bfd", "bfq", "bg",
|
||||
"bgn", "bho", "bi", "bik", "bin", "bjn", "bkm", "bla",
|
||||
"bm", "bn", "bo", "bpy", "bqi", "br", "bra", "brh",
|
||||
"brx", "bs", "bss", "bua", "bug", "bum", "byn", "byv",
|
||||
"ca", "cad", "car", "cay", "cch", "ce", "ceb", "cgg",
|
||||
"ca", "cad", "car", "cay", "cch", "ccp", "ce", "ceb", "cgg",
|
||||
"ch", "chb", "chg", "chk", "chm", "chn", "cho", "chp",
|
||||
"chr", "chy", "ckb", "co", "cop", "cps", "cr", "crh",
|
||||
"cs", "csb", "cu", "cv", "cy",
|
||||
|
|
@ -212,18 +214,19 @@ static const char* const REPLACEMENT_LANGUAGES[]={
|
|||
*/
|
||||
/* Generated using org.unicode.cldr.icu.GenerateISO639LanguageTables */
|
||||
/* ISO639 table version is 20150505 */
|
||||
/* Subsequent hand addition of selected languages */
|
||||
static const char * const LANGUAGES_3[] = {
|
||||
"aar", "abk", "ace", "ach", "ada", "ady", "ave", "aeb",
|
||||
"afr", "afh", "agq", "ain", "aka", "akk", "akz", "ale",
|
||||
"aln", "alt", "amh", "arg", "ang", "anp", "ara", "arc",
|
||||
"arn", "aro", "arp", "arq", "arw", "ary", "arz", "asm",
|
||||
"arn", "aro", "arp", "arq", "ars", "arw", "ary", "arz", "asm",
|
||||
"asa", "ase", "ast", "ava", "avk", "awa", "aym", "aze",
|
||||
"bak", "bal", "ban", "bar", "bas", "bax", "bbc", "bbj",
|
||||
"bel", "bej", "bem", "bew", "bez", "bfd", "bfq", "bul",
|
||||
"bgn", "bho", "bis", "bik", "bin", "bjn", "bkm", "bla",
|
||||
"bam", "ben", "bod", "bpy", "bqi", "bre", "bra", "brh",
|
||||
"brx", "bos", "bss", "bua", "bug", "bum", "byn", "byv",
|
||||
"cat", "cad", "car", "cay", "cch", "che", "ceb", "cgg",
|
||||
"cat", "cad", "car", "cay", "cch", "ccp", "che", "ceb", "cgg",
|
||||
"cha", "chb", "chg", "chk", "chm", "chn", "cho", "chp",
|
||||
"chr", "chy", "ckb", "cos", "cop", "cps", "cre", "crh",
|
||||
"ces", "csb", "chu", "chv", "cym",
|
||||
|
|
@ -528,14 +531,16 @@ static const VariantMap VARIANT_MAP[] = {
|
|||
#define _hasBCP47Extension(id) (id && uprv_strstr(id, "@") == NULL && getShortestSubtagLength(localeID) == 1)
|
||||
/* Converts the BCP47 id to Unicode id. Does nothing to id if conversion fails */
|
||||
#define _ConvertBCP47(finalID, id, buffer, length,err) \
|
||||
if (uloc_forLanguageTag(id, buffer, length, NULL, err) <= 0 || U_FAILURE(*err)) { \
|
||||
if (uloc_forLanguageTag(id, buffer, length, NULL, err) <= 0 || \
|
||||
U_FAILURE(*err) || *err == U_STRING_NOT_TERMINATED_WARNING) { \
|
||||
finalID=id; \
|
||||
if (*err == U_STRING_NOT_TERMINATED_WARNING) { *err = U_BUFFER_OVERFLOW_ERROR; } \
|
||||
} else { \
|
||||
finalID=buffer; \
|
||||
}
|
||||
/* Gets the size of the shortest subtag in the given localeID. */
|
||||
static int32_t getShortestSubtagLength(const char *localeID) {
|
||||
int32_t localeIDLength = uprv_strlen(localeID);
|
||||
int32_t localeIDLength = static_cast<int32_t>(uprv_strlen(localeID));
|
||||
int32_t length = localeIDLength;
|
||||
int32_t tmpLength = 0;
|
||||
int32_t i;
|
||||
|
|
@ -560,6 +565,10 @@ static int32_t getShortestSubtagLength(const char *localeID) {
|
|||
}
|
||||
|
||||
/* ### Keywords **************************************************/
|
||||
#define UPRV_ISDIGIT(c) (((c) >= '0') && ((c) <= '9'))
|
||||
#define UPRV_ISALPHANUM(c) (uprv_isASCIILetter(c) || UPRV_ISDIGIT(c) )
|
||||
/* Punctuation/symbols allowed in legacy key values */
|
||||
#define UPRV_OK_VALUE_PUNCTUATION(c) ((c) == '_' || (c) == '-' || (c) == '+' || (c) == '/')
|
||||
|
||||
#define ULOC_KEYWORD_BUFFER_LEN 25
|
||||
#define ULOC_MAX_NO_KEYWORDS 25
|
||||
|
|
@ -596,20 +605,26 @@ locale_getKeywordsStart(const char *localeID) {
|
|||
*/
|
||||
static int32_t locale_canonKeywordName(char *buf, const char *keywordName, UErrorCode *status)
|
||||
{
|
||||
int32_t i;
|
||||
int32_t keywordNameLen = (int32_t)uprv_strlen(keywordName);
|
||||
int32_t keywordNameLen = 0;
|
||||
|
||||
if(keywordNameLen >= ULOC_KEYWORD_BUFFER_LEN) {
|
||||
/* keyword name too long for internal buffer */
|
||||
*status = U_INTERNAL_PROGRAM_ERROR;
|
||||
return 0;
|
||||
for (; *keywordName != 0; keywordName++) {
|
||||
if (!UPRV_ISALPHANUM(*keywordName)) {
|
||||
*status = U_ILLEGAL_ARGUMENT_ERROR; /* malformed keyword name */
|
||||
return 0;
|
||||
}
|
||||
if (keywordNameLen < ULOC_KEYWORD_BUFFER_LEN - 1) {
|
||||
buf[keywordNameLen++] = uprv_tolower(*keywordName);
|
||||
} else {
|
||||
/* keyword name too long for internal buffer */
|
||||
*status = U_INTERNAL_PROGRAM_ERROR;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* normalize the keyword name */
|
||||
for(i = 0; i < keywordNameLen; i++) {
|
||||
buf[i] = uprv_tolower(keywordName[i]);
|
||||
if (keywordNameLen == 0) {
|
||||
*status = U_ILLEGAL_ARGUMENT_ERROR; /* empty keyword name */
|
||||
return 0;
|
||||
}
|
||||
buf[i] = 0;
|
||||
buf[keywordNameLen] = 0; /* terminate */
|
||||
|
||||
return keywordNameLen;
|
||||
}
|
||||
|
|
@ -783,7 +798,7 @@ _getKeywords(const char *localeID,
|
|||
}
|
||||
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;
|
||||
|
|
@ -837,23 +852,15 @@ uloc_getKeywordValue(const char* localeID,
|
|||
const char* nextSeparator = NULL;
|
||||
char keywordNameBuffer[ULOC_KEYWORD_BUFFER_LEN];
|
||||
char localeKeywordNameBuffer[ULOC_KEYWORD_BUFFER_LEN];
|
||||
int32_t i = 0;
|
||||
int32_t result = 0;
|
||||
|
||||
if(status && U_SUCCESS(*status) && localeID) {
|
||||
char tempBuffer[ULOC_FULLNAME_CAPACITY];
|
||||
const char* tmpLocaleID;
|
||||
|
||||
if (_hasBCP47Extension(localeID)) {
|
||||
_ConvertBCP47(tmpLocaleID, localeID, tempBuffer, sizeof(tempBuffer), status);
|
||||
} else {
|
||||
tmpLocaleID=localeID;
|
||||
}
|
||||
|
||||
startSearchHere = uprv_strchr(tmpLocaleID, '@'); /* TODO: REVISIT: shouldn't this be locale_getKeywordsStart ? */
|
||||
if(startSearchHere == NULL) {
|
||||
/* no keywords, return at once */
|
||||
return 0;
|
||||
if (keywordName == NULL || keywordName[0] == 0) {
|
||||
*status = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
return 0;
|
||||
}
|
||||
|
||||
locale_canonKeywordName(keywordNameBuffer, keywordName, status);
|
||||
|
|
@ -861,63 +868,92 @@ uloc_getKeywordValue(const char* localeID,
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (_hasBCP47Extension(localeID)) {
|
||||
_ConvertBCP47(tmpLocaleID, localeID, tempBuffer, sizeof(tempBuffer), status);
|
||||
} else {
|
||||
tmpLocaleID=localeID;
|
||||
}
|
||||
|
||||
startSearchHere = locale_getKeywordsStart(tmpLocaleID);
|
||||
if(startSearchHere == NULL) {
|
||||
/* no keywords, return at once */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* find the first keyword */
|
||||
while(startSearchHere) {
|
||||
startSearchHere++;
|
||||
/* skip leading spaces (allowed?) */
|
||||
const char* keyValueTail;
|
||||
int32_t keyValueLen;
|
||||
|
||||
startSearchHere++; /* skip @ or ; */
|
||||
nextSeparator = uprv_strchr(startSearchHere, '=');
|
||||
if(!nextSeparator) {
|
||||
*status = U_ILLEGAL_ARGUMENT_ERROR; /* key must have =value */
|
||||
return 0;
|
||||
}
|
||||
/* strip leading & trailing spaces (TC decided to tolerate these) */
|
||||
while(*startSearchHere == ' ') {
|
||||
startSearchHere++;
|
||||
}
|
||||
nextSeparator = uprv_strchr(startSearchHere, '=');
|
||||
/* need to normalize both keyword and keyword name */
|
||||
if(!nextSeparator) {
|
||||
break;
|
||||
keyValueTail = nextSeparator;
|
||||
while (keyValueTail > startSearchHere && *(keyValueTail-1) == ' ') {
|
||||
keyValueTail--;
|
||||
}
|
||||
if(nextSeparator - startSearchHere >= ULOC_KEYWORD_BUFFER_LEN) {
|
||||
/* now keyValueTail points to first char after the keyName */
|
||||
/* copy & normalize keyName from locale */
|
||||
if (startSearchHere == keyValueTail) {
|
||||
*status = U_ILLEGAL_ARGUMENT_ERROR; /* empty keyword name in passed-in locale */
|
||||
return 0;
|
||||
}
|
||||
keyValueLen = 0;
|
||||
while (startSearchHere < keyValueTail) {
|
||||
if (!UPRV_ISALPHANUM(*startSearchHere)) {
|
||||
*status = U_ILLEGAL_ARGUMENT_ERROR; /* malformed keyword name */
|
||||
return 0;
|
||||
}
|
||||
if (keyValueLen < ULOC_KEYWORD_BUFFER_LEN - 1) {
|
||||
localeKeywordNameBuffer[keyValueLen++] = uprv_tolower(*startSearchHere++);
|
||||
} else {
|
||||
/* keyword name too long for internal buffer */
|
||||
*status = U_INTERNAL_PROGRAM_ERROR;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
for(i = 0; i < nextSeparator - startSearchHere; i++) {
|
||||
localeKeywordNameBuffer[i] = uprv_tolower(startSearchHere[i]);
|
||||
}
|
||||
/* trim trailing spaces */
|
||||
while(startSearchHere[i-1] == ' ') {
|
||||
i--;
|
||||
U_ASSERT(i>=0);
|
||||
}
|
||||
localeKeywordNameBuffer[i] = 0;
|
||||
localeKeywordNameBuffer[keyValueLen] = 0; /* terminate */
|
||||
|
||||
startSearchHere = uprv_strchr(nextSeparator, ';');
|
||||
|
||||
if(uprv_strcmp(keywordNameBuffer, localeKeywordNameBuffer) == 0) {
|
||||
nextSeparator++;
|
||||
/* current entry matches the keyword. */
|
||||
nextSeparator++; /* skip '=' */
|
||||
/* First strip leading & trailing spaces (TC decided to tolerate these) */
|
||||
while(*nextSeparator == ' ') {
|
||||
nextSeparator++;
|
||||
}
|
||||
keyValueTail = (startSearchHere)? startSearchHere: nextSeparator + uprv_strlen(nextSeparator);
|
||||
while(keyValueTail > nextSeparator && *(keyValueTail-1) == ' ') {
|
||||
keyValueTail--;
|
||||
}
|
||||
/* Now copy the value, but check well-formedness */
|
||||
if (nextSeparator == keyValueTail) {
|
||||
*status = U_ILLEGAL_ARGUMENT_ERROR; /* empty key value name in passed-in locale */
|
||||
return 0;
|
||||
}
|
||||
keyValueLen = 0;
|
||||
while (nextSeparator < keyValueTail) {
|
||||
if (!UPRV_ISALPHANUM(*nextSeparator) && !UPRV_OK_VALUE_PUNCTUATION(*nextSeparator)) {
|
||||
*status = U_ILLEGAL_ARGUMENT_ERROR; /* malformed key value */
|
||||
return 0;
|
||||
}
|
||||
if (keyValueLen < bufferCapacity) {
|
||||
/* Should we lowercase value to return here? Tests expect as-is. */
|
||||
buffer[keyValueLen++] = *nextSeparator++;
|
||||
} else { /* keep advancing so we return correct length in case of overflow */
|
||||
keyValueLen++;
|
||||
nextSeparator++;
|
||||
}
|
||||
}
|
||||
/* we actually found the keyword. Copy the value */
|
||||
if(startSearchHere && startSearchHere - nextSeparator < bufferCapacity) {
|
||||
while(*(startSearchHere-1) == ' ') {
|
||||
startSearchHere--;
|
||||
}
|
||||
uprv_strncpy(buffer, nextSeparator, startSearchHere - nextSeparator);
|
||||
result = u_terminateChars(buffer, bufferCapacity, (int32_t)(startSearchHere - nextSeparator), status);
|
||||
} else if(!startSearchHere && (int32_t)uprv_strlen(nextSeparator) < bufferCapacity) { /* last item in string */
|
||||
i = (int32_t)uprv_strlen(nextSeparator);
|
||||
while(nextSeparator[i - 1] == ' ') {
|
||||
i--;
|
||||
}
|
||||
uprv_strncpy(buffer, nextSeparator, i);
|
||||
result = u_terminateChars(buffer, bufferCapacity, i, status);
|
||||
} else {
|
||||
/* give a bigger buffer, please */
|
||||
*status = U_BUFFER_OVERFLOW_ERROR;
|
||||
if(startSearchHere) {
|
||||
result = (int32_t)(startSearchHere - nextSeparator);
|
||||
} else {
|
||||
result = (int32_t)uprv_strlen(nextSeparator);
|
||||
}
|
||||
}
|
||||
result = u_terminateChars(buffer, bufferCapacity, keyValueLen, status);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
@ -936,46 +972,59 @@ uloc_setKeywordValue(const char* keywordName,
|
|||
int32_t keywordValueLen;
|
||||
int32_t bufLen;
|
||||
int32_t needLen = 0;
|
||||
int32_t foundValueLen;
|
||||
int32_t keywordAtEnd = 0; /* is the keyword at the end of the string? */
|
||||
char keywordNameBuffer[ULOC_KEYWORD_BUFFER_LEN];
|
||||
char keywordValueBuffer[ULOC_KEYWORDS_CAPACITY+1];
|
||||
char localeKeywordNameBuffer[ULOC_KEYWORD_BUFFER_LEN];
|
||||
int32_t i = 0;
|
||||
int32_t rc;
|
||||
char* nextSeparator = NULL;
|
||||
char* nextEqualsign = NULL;
|
||||
char* startSearchHere = NULL;
|
||||
char* keywordStart = NULL;
|
||||
char *insertHere = NULL;
|
||||
CharString updatedKeysAndValues;
|
||||
int32_t updatedKeysAndValuesLen;
|
||||
UBool handledInputKeyAndValue = FALSE;
|
||||
char keyValuePrefix = '@';
|
||||
|
||||
if(U_FAILURE(*status)) {
|
||||
return -1;
|
||||
}
|
||||
if(bufferCapacity>1) {
|
||||
bufLen = (int32_t)uprv_strlen(buffer);
|
||||
} else {
|
||||
if (keywordName == NULL || keywordName[0] == 0 || bufferCapacity <= 1) {
|
||||
*status = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
return 0;
|
||||
}
|
||||
bufLen = (int32_t)uprv_strlen(buffer);
|
||||
if(bufferCapacity<bufLen) {
|
||||
/* The capacity is less than the length?! Is this NULL terminated? */
|
||||
*status = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
return 0;
|
||||
}
|
||||
if(keywordValue && !*keywordValue) {
|
||||
keywordValue = NULL;
|
||||
}
|
||||
if(keywordValue) {
|
||||
keywordValueLen = (int32_t)uprv_strlen(keywordValue);
|
||||
} else {
|
||||
keywordValueLen = 0;
|
||||
}
|
||||
keywordNameLen = locale_canonKeywordName(keywordNameBuffer, keywordName, status);
|
||||
if(U_FAILURE(*status)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
keywordValueLen = 0;
|
||||
if(keywordValue) {
|
||||
while (*keywordValue != 0) {
|
||||
if (!UPRV_ISALPHANUM(*keywordValue) && !UPRV_OK_VALUE_PUNCTUATION(*keywordValue)) {
|
||||
*status = U_ILLEGAL_ARGUMENT_ERROR; /* malformed key value */
|
||||
return 0;
|
||||
}
|
||||
if (keywordValueLen < ULOC_KEYWORDS_CAPACITY) {
|
||||
/* Should we force lowercase in value to set? */
|
||||
keywordValueBuffer[keywordValueLen++] = *keywordValue++;
|
||||
} else {
|
||||
/* keywordValue too long for internal buffer */
|
||||
*status = U_INTERNAL_PROGRAM_ERROR;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
keywordValueBuffer[keywordValueLen] = 0; /* terminate */
|
||||
|
||||
startSearchHere = (char*)locale_getKeywordsStart(buffer);
|
||||
if(startSearchHere == NULL || (startSearchHere[1]==0)) {
|
||||
if(!keywordValue) { /* no keywords = nothing to remove */
|
||||
if(keywordValueLen == 0) { /* no keywords = nothing to remove */
|
||||
return bufLen;
|
||||
}
|
||||
|
||||
|
|
@ -990,133 +1039,137 @@ uloc_setKeywordValue(const char* keywordName,
|
|||
*status = U_BUFFER_OVERFLOW_ERROR;
|
||||
return needLen; /* no change */
|
||||
}
|
||||
*startSearchHere = '@';
|
||||
startSearchHere++;
|
||||
*startSearchHere++ = '@';
|
||||
uprv_strcpy(startSearchHere, keywordNameBuffer);
|
||||
startSearchHere += keywordNameLen;
|
||||
*startSearchHere = '=';
|
||||
startSearchHere++;
|
||||
uprv_strcpy(startSearchHere, keywordValue);
|
||||
startSearchHere+=keywordValueLen;
|
||||
*startSearchHere++ = '=';
|
||||
uprv_strcpy(startSearchHere, keywordValueBuffer);
|
||||
return needLen;
|
||||
} /* end shortcut - no @ */
|
||||
|
||||
keywordStart = startSearchHere;
|
||||
/* search for keyword */
|
||||
while(keywordStart) {
|
||||
keywordStart++;
|
||||
/* skip leading spaces (allowed?) */
|
||||
const char* keyValueTail;
|
||||
int32_t keyValueLen;
|
||||
|
||||
keywordStart++; /* skip @ or ; */
|
||||
nextEqualsign = uprv_strchr(keywordStart, '=');
|
||||
if (!nextEqualsign) {
|
||||
*status = U_ILLEGAL_ARGUMENT_ERROR; /* key must have =value */
|
||||
return 0;
|
||||
}
|
||||
/* strip leading & trailing spaces (TC decided to tolerate these) */
|
||||
while(*keywordStart == ' ') {
|
||||
keywordStart++;
|
||||
}
|
||||
nextEqualsign = uprv_strchr(keywordStart, '=');
|
||||
/* need to normalize both keyword and keyword name */
|
||||
if(!nextEqualsign) {
|
||||
break;
|
||||
keyValueTail = nextEqualsign;
|
||||
while (keyValueTail > keywordStart && *(keyValueTail-1) == ' ') {
|
||||
keyValueTail--;
|
||||
}
|
||||
if(nextEqualsign - keywordStart >= ULOC_KEYWORD_BUFFER_LEN) {
|
||||
/* keyword name too long for internal buffer */
|
||||
*status = U_INTERNAL_PROGRAM_ERROR;
|
||||
/* now keyValueTail points to first char after the keyName */
|
||||
/* copy & normalize keyName from locale */
|
||||
if (keywordStart == keyValueTail) {
|
||||
*status = U_ILLEGAL_ARGUMENT_ERROR; /* empty keyword name in passed-in locale */
|
||||
return 0;
|
||||
}
|
||||
for(i = 0; i < nextEqualsign - keywordStart; i++) {
|
||||
localeKeywordNameBuffer[i] = uprv_tolower(keywordStart[i]);
|
||||
keyValueLen = 0;
|
||||
while (keywordStart < keyValueTail) {
|
||||
if (!UPRV_ISALPHANUM(*keywordStart)) {
|
||||
*status = U_ILLEGAL_ARGUMENT_ERROR; /* malformed keyword name */
|
||||
return 0;
|
||||
}
|
||||
if (keyValueLen < ULOC_KEYWORD_BUFFER_LEN - 1) {
|
||||
localeKeywordNameBuffer[keyValueLen++] = uprv_tolower(*keywordStart++);
|
||||
} else {
|
||||
/* keyword name too long for internal buffer */
|
||||
*status = U_INTERNAL_PROGRAM_ERROR;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/* trim trailing spaces */
|
||||
while(keywordStart[i-1] == ' ') {
|
||||
i--;
|
||||
}
|
||||
U_ASSERT(i>=0 && i<ULOC_KEYWORD_BUFFER_LEN);
|
||||
localeKeywordNameBuffer[i] = 0;
|
||||
localeKeywordNameBuffer[keyValueLen] = 0; /* terminate */
|
||||
|
||||
nextSeparator = uprv_strchr(nextEqualsign, ';');
|
||||
|
||||
/* start processing the value part */
|
||||
nextEqualsign++; /* skip '=' */
|
||||
/* First strip leading & trailing spaces (TC decided to tolerate these) */
|
||||
while(*nextEqualsign == ' ') {
|
||||
nextEqualsign++;
|
||||
}
|
||||
keyValueTail = (nextSeparator)? nextSeparator: nextEqualsign + uprv_strlen(nextEqualsign);
|
||||
while(keyValueTail > nextEqualsign && *(keyValueTail-1) == ' ') {
|
||||
keyValueTail--;
|
||||
}
|
||||
if (nextEqualsign == keyValueTail) {
|
||||
*status = U_ILLEGAL_ARGUMENT_ERROR; /* empty key value in passed-in locale */
|
||||
return 0;
|
||||
}
|
||||
|
||||
rc = uprv_strcmp(keywordNameBuffer, localeKeywordNameBuffer);
|
||||
if(rc == 0) {
|
||||
nextEqualsign++;
|
||||
while(*nextEqualsign == ' ') {
|
||||
nextEqualsign++;
|
||||
/* Current entry matches the input keyword. Update the entry */
|
||||
if(keywordValueLen > 0) { /* updating a value */
|
||||
updatedKeysAndValues.append(keyValuePrefix, *status);
|
||||
keyValuePrefix = ';'; /* for any subsequent key-value pair */
|
||||
updatedKeysAndValues.append(keywordNameBuffer, keywordNameLen, *status);
|
||||
updatedKeysAndValues.append('=', *status);
|
||||
updatedKeysAndValues.append(keywordValueBuffer, keywordValueLen, *status);
|
||||
} /* else removing this entry, don't emit anything */
|
||||
handledInputKeyAndValue = TRUE;
|
||||
} else {
|
||||
/* input keyword sorts earlier than current entry, add before current entry */
|
||||
if (rc < 0 && keywordValueLen > 0 && !handledInputKeyAndValue) {
|
||||
/* insert new entry at this location */
|
||||
updatedKeysAndValues.append(keyValuePrefix, *status);
|
||||
keyValuePrefix = ';'; /* for any subsequent key-value pair */
|
||||
updatedKeysAndValues.append(keywordNameBuffer, keywordNameLen, *status);
|
||||
updatedKeysAndValues.append('=', *status);
|
||||
updatedKeysAndValues.append(keywordValueBuffer, keywordValueLen, *status);
|
||||
handledInputKeyAndValue = TRUE;
|
||||
}
|
||||
/* we actually found the keyword. Change the value */
|
||||
if (nextSeparator) {
|
||||
keywordAtEnd = 0;
|
||||
foundValueLen = (int32_t)(nextSeparator - nextEqualsign);
|
||||
} else {
|
||||
keywordAtEnd = 1;
|
||||
foundValueLen = (int32_t)uprv_strlen(nextEqualsign);
|
||||
}
|
||||
if(keywordValue) { /* adding a value - not removing */
|
||||
if(foundValueLen == keywordValueLen) {
|
||||
uprv_strncpy(nextEqualsign, keywordValue, keywordValueLen);
|
||||
return bufLen; /* no change in size */
|
||||
} else if(foundValueLen > keywordValueLen) {
|
||||
int32_t delta = foundValueLen - keywordValueLen;
|
||||
if(nextSeparator) { /* RH side */
|
||||
uprv_memmove(nextSeparator - delta, nextSeparator, bufLen-(nextSeparator-buffer));
|
||||
}
|
||||
uprv_strncpy(nextEqualsign, keywordValue, keywordValueLen);
|
||||
bufLen -= delta;
|
||||
buffer[bufLen]=0;
|
||||
return bufLen;
|
||||
} else { /* FVL < KVL */
|
||||
int32_t delta = keywordValueLen - foundValueLen;
|
||||
if((bufLen+delta) >= bufferCapacity) {
|
||||
*status = U_BUFFER_OVERFLOW_ERROR;
|
||||
return bufLen+delta;
|
||||
}
|
||||
if(nextSeparator) { /* RH side */
|
||||
uprv_memmove(nextSeparator+delta,nextSeparator, bufLen-(nextSeparator-buffer));
|
||||
}
|
||||
uprv_strncpy(nextEqualsign, keywordValue, keywordValueLen);
|
||||
bufLen += delta;
|
||||
buffer[bufLen]=0;
|
||||
return bufLen;
|
||||
}
|
||||
} else { /* removing a keyword */
|
||||
if(keywordAtEnd) {
|
||||
/* zero out the ';' or '@' just before startSearchhere */
|
||||
keywordStart[-1] = 0;
|
||||
return (int32_t)((keywordStart-buffer)-1); /* (string length without keyword) minus separator */
|
||||
} else {
|
||||
uprv_memmove(keywordStart, nextSeparator+1, bufLen-((nextSeparator+1)-buffer));
|
||||
keywordStart[bufLen-((nextSeparator+1)-buffer)]=0;
|
||||
return (int32_t)(bufLen-((nextSeparator+1)-keywordStart));
|
||||
}
|
||||
}
|
||||
} else if(rc<0){ /* end match keyword */
|
||||
/* could insert at this location. */
|
||||
insertHere = keywordStart;
|
||||
/* copy the current entry */
|
||||
updatedKeysAndValues.append(keyValuePrefix, *status);
|
||||
keyValuePrefix = ';'; /* for any subsequent key-value pair */
|
||||
updatedKeysAndValues.append(localeKeywordNameBuffer, keyValueLen, *status);
|
||||
updatedKeysAndValues.append('=', *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 */
|
||||
updatedKeysAndValues.append(keyValuePrefix, *status);
|
||||
/* skip keyValuePrefix update, no subsequent key-value pair */
|
||||
updatedKeysAndValues.append(keywordNameBuffer, keywordNameLen, *status);
|
||||
updatedKeysAndValues.append('=', *status);
|
||||
updatedKeysAndValues.append(keywordValueBuffer, keywordValueLen, *status);
|
||||
handledInputKeyAndValue = TRUE;
|
||||
}
|
||||
keywordStart = nextSeparator;
|
||||
} /* end loop searching */
|
||||
|
||||
if(!keywordValue) {
|
||||
return bufLen; /* removal of non-extant keyword - no change */
|
||||
/* Any error from updatedKeysAndValues.append above would be internal and not due to
|
||||
* problems with the passed-in locale. So if we did encounter problems with the
|
||||
* passed-in locale above, those errors took precedence and overrode any error
|
||||
* status from updatedKeysAndValues.append, and also caused a return of 0. If there
|
||||
* are errors here they are from updatedKeysAndValues.append; they do cause an
|
||||
* error return but the passed-in locale is unmodified and the original bufLen is
|
||||
* returned.
|
||||
*/
|
||||
if (!handledInputKeyAndValue || U_FAILURE(*status)) {
|
||||
/* if input key/value specified removal of a keyword not present in locale, or
|
||||
* there was an error in CharString.append, leave original locale alone. */
|
||||
return bufLen;
|
||||
}
|
||||
|
||||
/* we know there is at least one keyword. */
|
||||
needLen = bufLen+1+keywordNameLen+1+keywordValueLen;
|
||||
updatedKeysAndValuesLen = updatedKeysAndValues.length();
|
||||
/* needLen = length of the part before '@' + length of updated key-value part including '@' */
|
||||
needLen = (int32_t)(startSearchHere - buffer) + updatedKeysAndValuesLen;
|
||||
if(needLen >= bufferCapacity) {
|
||||
*status = U_BUFFER_OVERFLOW_ERROR;
|
||||
return needLen; /* no change */
|
||||
}
|
||||
|
||||
if(insertHere) {
|
||||
uprv_memmove(insertHere+(1+keywordNameLen+1+keywordValueLen), insertHere, bufLen-(insertHere-buffer));
|
||||
keywordStart = insertHere;
|
||||
} else {
|
||||
keywordStart = buffer+bufLen;
|
||||
*keywordStart = ';';
|
||||
keywordStart++;
|
||||
}
|
||||
uprv_strncpy(keywordStart, keywordNameBuffer, keywordNameLen);
|
||||
keywordStart += keywordNameLen;
|
||||
*keywordStart = '=';
|
||||
keywordStart++;
|
||||
uprv_strncpy(keywordStart, keywordValue, keywordValueLen); /* terminates. */
|
||||
keywordStart+=keywordValueLen;
|
||||
if(insertHere) {
|
||||
*keywordStart = ';';
|
||||
keywordStart++;
|
||||
if (updatedKeysAndValuesLen > 0) {
|
||||
uprv_strncpy(startSearchHere, updatedKeysAndValues.data(), updatedKeysAndValuesLen);
|
||||
}
|
||||
buffer[needLen]=0;
|
||||
return needLen;
|
||||
|
|
@ -1447,7 +1500,7 @@ _deleteVariant(char* variants, int32_t variantsLen,
|
|||
}
|
||||
if (uprv_strncmp(variants, toDelete, toDeleteLen) == 0 &&
|
||||
(variantsLen == toDeleteLen ||
|
||||
(flag=(variants[toDeleteLen] == '_'))))
|
||||
(flag=(variants[toDeleteLen] == '_')) != 0))
|
||||
{
|
||||
int32_t d = toDeleteLen + (flag?1:0);
|
||||
variantsLen -= d;
|
||||
|
|
@ -2119,6 +2172,20 @@ uloc_getLCID(const char* localeID)
|
|||
{
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
char langID[ULOC_FULLNAME_CAPACITY];
|
||||
uint32_t lcid = 0;
|
||||
|
||||
/* Check for incomplete id. */
|
||||
if (!localeID || uprv_strlen(localeID) < 2) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Attempt platform lookup if available
|
||||
lcid = uprv_convertToLCIDPlatform(localeID);
|
||||
if (lcid > 0)
|
||||
{
|
||||
// Windows found an LCID, return that
|
||||
return lcid;
|
||||
}
|
||||
|
||||
uloc_getLanguage(localeID, langID, sizeof(langID), &status);
|
||||
if (U_FAILURE(status)) {
|
||||
|
|
@ -2345,7 +2412,7 @@ uloc_acceptLanguageFromHTTP(char *result, int32_t resultAvailable, UAcceptResult
|
|||
/* 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
|
||||
|
|
@ -2423,7 +2490,7 @@ uloc_acceptLanguage(char *result, int32_t resultAvailable,
|
|||
#if defined(ULOC_DEBUG)
|
||||
fprintf(stderr,"%02d: %s\n", i, acceptList[i]);
|
||||
#endif
|
||||
while((l=uenum_next(availableLocales, NULL, status))) {
|
||||
while((l=uenum_next(availableLocales, NULL, status)) != NULL) {
|
||||
#if defined(ULOC_DEBUG)
|
||||
fprintf(stderr," %s\n", l);
|
||||
#endif
|
||||
|
|
@ -2463,7 +2530,7 @@ uloc_acceptLanguage(char *result, int32_t resultAvailable,
|
|||
#if defined(ULOC_DEBUG)
|
||||
fprintf(stderr,"Try: [%s]", fallbackList[i]);
|
||||
#endif
|
||||
while((l=uenum_next(availableLocales, NULL, status))) {
|
||||
while((l=uenum_next(availableLocales, NULL, status)) != NULL) {
|
||||
#if defined(ULOC_DEBUG)
|
||||
fprintf(stderr," %s\n", l);
|
||||
#endif
|
||||
|
|
@ -2529,9 +2596,6 @@ uloc_toUnicodeLocaleType(const char* keyword, const char* value)
|
|||
return bcpType;
|
||||
}
|
||||
|
||||
#define UPRV_ISDIGIT(c) (((c) >= '0') && ((c) <= '9'))
|
||||
#define UPRV_ISALPHANUM(c) (uprv_isASCIILetter(c) || UPRV_ISDIGIT(c) )
|
||||
|
||||
static UBool
|
||||
isWellFormedLegacyKey(const char* legacyKey)
|
||||
{
|
||||
|
|
@ -2574,11 +2638,10 @@ uloc_toLegacyKey(const char* keyword)
|
|||
// Checks if the specified locale key is well-formed with the legacy locale syntax.
|
||||
//
|
||||
// Note:
|
||||
// Neither ICU nor LDML/CLDR provides the definition of keyword syntax.
|
||||
// However, a key should not contain '=' obviously. For now, all existing
|
||||
// keys are using ASCII alphabetic letters only. We won't add any new key
|
||||
// that is not compatible with the BCP 47 syntax. Therefore, we assume
|
||||
// a valid key consist from [0-9a-zA-Z], no symbols.
|
||||
// LDML/CLDR provides some definition of keyword syntax in
|
||||
// * http://www.unicode.org/reports/tr35/#Unicode_locale_identifier and
|
||||
// * http://www.unicode.org/reports/tr35/#Old_Locale_Extension_Syntax
|
||||
// Keys can only consist of [0-9a-zA-Z].
|
||||
if (isWellFormedLegacyKey(keyword)) {
|
||||
return keyword;
|
||||
}
|
||||
|
|
@ -2594,12 +2657,11 @@ uloc_toLegacyType(const char* keyword, const char* value)
|
|||
// Checks if the specified locale type is well-formed with the legacy locale syntax.
|
||||
//
|
||||
// Note:
|
||||
// Neither ICU nor LDML/CLDR provides the definition of keyword syntax.
|
||||
// However, a type should not contain '=' obviously. For now, all existing
|
||||
// types are using ASCII alphabetic letters with a few symbol letters. We won't
|
||||
// add any new type that is not compatible with the BCP 47 syntax except timezone
|
||||
// IDs. For now, we assume a valid type start with [0-9a-zA-Z], but may contain
|
||||
// '-' '_' '/' in the middle.
|
||||
// LDML/CLDR provides some definition of keyword syntax in
|
||||
// * http://www.unicode.org/reports/tr35/#Unicode_locale_identifier and
|
||||
// * http://www.unicode.org/reports/tr35/#Old_Locale_Extension_Syntax
|
||||
// Values (types) can only consist of [0-9a-zA-Z], plus for legacy values
|
||||
// we allow [/_-+] in the middle (e.g. "Etc/GMT+1", "Asia/Tel_Aviv")
|
||||
if (isWellFormedLegacyType(value)) {
|
||||
return value;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue