diff options
Diffstat (limited to 'Build/source/libs/icu/icu-src/source')
191 files changed, 8016 insertions, 1815 deletions
diff --git a/Build/source/libs/icu/icu-src/source/common/BUILD b/Build/source/libs/icu/icu-src/source/common/BUILD.bazel index e385d3b243f..e385d3b243f 100644 --- a/Build/source/libs/icu/icu-src/source/common/BUILD +++ b/Build/source/libs/icu/icu-src/source/common/BUILD.bazel diff --git a/Build/source/libs/icu/icu-src/source/common/brkeng.cpp b/Build/source/libs/icu/icu-src/source/common/brkeng.cpp index 52e9c53621d..dc9fb99bf19 100644 --- a/Build/source/libs/icu/icu-src/source/common/brkeng.cpp +++ b/Build/source/libs/icu/icu-src/source/common/brkeng.cpp @@ -79,6 +79,7 @@ UnhandledEngine::findBreaks( UText *text, int32_t /* startPos */, int32_t endPos, UVector32 &/*foundBreaks*/, + UBool /* isPhraseBreaking */, UErrorCode &status) const { if (U_FAILURE(status)) return 0; UChar32 c = utext_current32(text); diff --git a/Build/source/libs/icu/icu-src/source/common/brkeng.h b/Build/source/libs/icu/icu-src/source/common/brkeng.h index 6843f1cc953..127ba59e186 100644 --- a/Build/source/libs/icu/icu-src/source/common/brkeng.h +++ b/Build/source/libs/icu/icu-src/source/common/brkeng.h @@ -75,6 +75,7 @@ class LanguageBreakEngine : public UMemory { int32_t startPos, int32_t endPos, UVector32 &foundBreaks, + UBool isPhraseBreaking, UErrorCode &status) const = 0; }; @@ -194,6 +195,7 @@ class UnhandledEngine : public LanguageBreakEngine { int32_t startPos, int32_t endPos, UVector32 &foundBreaks, + UBool isPhraseBreaking, UErrorCode &status) const override; /** diff --git a/Build/source/libs/icu/icu-src/source/common/brkiter.cpp b/Build/source/libs/icu/icu-src/source/common/brkiter.cpp index 8b228acf2c3..8a1915880ee 100644 --- a/Build/source/libs/icu/icu-src/source/common/brkiter.cpp +++ b/Build/source/libs/icu/icu-src/source/common/brkiter.cpp @@ -30,6 +30,7 @@ #include "unicode/ures.h" #include "unicode/ustring.h" #include "unicode/filteredbrk.h" +#include "bytesinkutil.h" #include "ucln_cmn.h" #include "cstring.h" #include "umutex.h" @@ -115,7 +116,7 @@ BreakIterator::buildInstance(const Locale& loc, const char *type, UErrorCode &st } // Create a RuleBasedBreakIterator - result = new RuleBasedBreakIterator(file, status); + result = new RuleBasedBreakIterator(file, uprv_strstr(type, "phrase") != NULL, status); // If there is a result, set the valid locale and actual locale, and the kind if (U_SUCCESS(status) && result != NULL) { @@ -408,7 +409,6 @@ BreakIterator::makeInstance(const Locale& loc, int32_t kind, UErrorCode& status) if (U_FAILURE(status)) { return NULL; } - char lbType[kKeyValueLenMax]; BreakIterator *result = NULL; switch (kind) { @@ -428,18 +428,29 @@ BreakIterator::makeInstance(const Locale& loc, int32_t kind, UErrorCode& status) break; case UBRK_LINE: { + char lb_lw[kKeyValueLenMax]; UTRACE_ENTRY(UTRACE_UBRK_CREATE_LINE); - uprv_strcpy(lbType, "line"); - char lbKeyValue[kKeyValueLenMax] = {0}; + uprv_strcpy(lb_lw, "line"); UErrorCode kvStatus = U_ZERO_ERROR; - int32_t kLen = loc.getKeywordValue("lb", lbKeyValue, kKeyValueLenMax, kvStatus); - if (U_SUCCESS(kvStatus) && kLen > 0 && (uprv_strcmp(lbKeyValue,"strict")==0 || uprv_strcmp(lbKeyValue,"normal")==0 || uprv_strcmp(lbKeyValue,"loose")==0)) { - uprv_strcat(lbType, "_"); - uprv_strcat(lbType, lbKeyValue); + CharString value; + CharStringByteSink valueSink(&value); + loc.getKeywordValue("lb", valueSink, kvStatus); + if (U_SUCCESS(kvStatus) && (value == "strict" || value == "normal" || value == "loose")) { + uprv_strcat(lb_lw, "_"); + uprv_strcat(lb_lw, value.data()); } - result = BreakIterator::buildInstance(loc, lbType, status); + // lw=phrase is only supported in Japanese. + if (uprv_strcmp(loc.getLanguage(), "ja") == 0) { + value.clear(); + loc.getKeywordValue("lw", valueSink, kvStatus); + if (U_SUCCESS(kvStatus) && value == "phrase") { + uprv_strcat(lb_lw, "_"); + uprv_strcat(lb_lw, value.data()); + } + } + result = BreakIterator::buildInstance(loc, lb_lw, status); - UTRACE_DATA1(UTRACE_INFO, "lb=%s", lbKeyValue); + UTRACE_DATA1(UTRACE_INFO, "lb_lw=%s", lb_lw); UTRACE_EXIT_STATUS(status); } break; diff --git a/Build/source/libs/icu/icu-src/source/common/common.vcxproj b/Build/source/libs/icu/icu-src/source/common/common.vcxproj index fdc0e8d71fd..6b0a60e46c1 100644 --- a/Build/source/libs/icu/icu-src/source/common/common.vcxproj +++ b/Build/source/libs/icu/icu-src/source/common/common.vcxproj @@ -58,7 +58,7 @@ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> </ClCompile> <Link> - <OutputFile>..\..\$(IcuBinOutputDir)\icuuc70d.dll</OutputFile> + <OutputFile>..\..\$(IcuBinOutputDir)\icuuc71d.dll</OutputFile> <ProgramDatabaseFile>.\..\..\$(IcuLibOutputDir)\icuucd.pdb</ProgramDatabaseFile> <ImportLibrary>..\..\$(IcuLibOutputDir)\icuucd.lib</ImportLibrary> </Link> @@ -70,7 +70,7 @@ <FunctionLevelLinking>true</FunctionLevelLinking> </ClCompile> <Link> - <OutputFile>..\..\$(IcuBinOutputDir)\icuuc70.dll</OutputFile> + <OutputFile>..\..\$(IcuBinOutputDir)\icuuc71.dll</OutputFile> <ProgramDatabaseFile>.\..\..\$(IcuLibOutputDir)\icuuc.pdb</ProgramDatabaseFile> <ImportLibrary>..\..\$(IcuLibOutputDir)\icuuc.lib</ImportLibrary> </Link> diff --git a/Build/source/libs/icu/icu-src/source/common/common_uwp.vcxproj b/Build/source/libs/icu/icu-src/source/common/common_uwp.vcxproj index 09743e6babc..dcd95b8c318 100644 --- a/Build/source/libs/icu/icu-src/source/common/common_uwp.vcxproj +++ b/Build/source/libs/icu/icu-src/source/common/common_uwp.vcxproj @@ -125,7 +125,7 @@ <Link> <EnableCOMDATFolding>true</EnableCOMDATFolding> <AdditionalDependencies>vccorlib.lib;msvcrt.lib;vcruntime.lib;%(AdditionalDependencies)</AdditionalDependencies> - <OutputFile>..\..\$(IcuBinOutputDir)\icuuc70.dll</OutputFile> + <OutputFile>..\..\$(IcuBinOutputDir)\icuuc71.dll</OutputFile> <ProgramDatabaseFile>.\..\..\$(IcuLibOutputDir)\icuuc.pdb</ProgramDatabaseFile> <ImportLibrary>..\..\$(IcuLibOutputDir)\icuuc.lib</ImportLibrary> </Link> @@ -148,7 +148,7 @@ <Link> <GenerateDebugInformation>true</GenerateDebugInformation> <AdditionalDependencies>vccorlibd.lib;msvcrtd.lib;vcruntimed.lib;%(AdditionalDependencies)</AdditionalDependencies> - <OutputFile>..\..\$(IcuBinOutputDir)\icuuc70d.dll</OutputFile> + <OutputFile>..\..\$(IcuBinOutputDir)\icuuc71d.dll</OutputFile> <ProgramDatabaseFile>.\..\..\$(IcuLibOutputDir)\icuucd.pdb</ProgramDatabaseFile> <ImportLibrary>..\..\$(IcuLibOutputDir)\icuucd.lib</ImportLibrary> </Link> diff --git a/Build/source/libs/icu/icu-src/source/common/dictbe.cpp b/Build/source/libs/icu/icu-src/source/common/dictbe.cpp index 4d158e3226d..4fdbdf2760f 100644 --- a/Build/source/libs/icu/icu-src/source/common/dictbe.cpp +++ b/Build/source/libs/icu/icu-src/source/common/dictbe.cpp @@ -17,7 +17,10 @@ #include "dictbe.h" #include "unicode/uniset.h" #include "unicode/chariter.h" +#include "unicode/resbund.h" #include "unicode/ubrk.h" +#include "unicode/usetiter.h" +#include "ubrkimpl.h" #include "utracimp.h" #include "uvectr32.h" #include "uvector.h" @@ -48,6 +51,7 @@ DictionaryBreakEngine::findBreaks( UText *text, int32_t startPos, int32_t endPos, UVector32 &foundBreaks, + UBool isPhraseBreaking, UErrorCode& status) const { if (U_FAILURE(status)) return 0; (void)startPos; // TODO: remove this param? @@ -68,7 +72,7 @@ DictionaryBreakEngine::findBreaks( UText *text, } rangeStart = start; rangeEnd = current; - result = divideUpDictionaryRange(text, rangeStart, rangeEnd, foundBreaks, status); + result = divideUpDictionaryRange(text, rangeStart, rangeEnd, foundBreaks, isPhraseBreaking, status); utext_setNativeIndex(text, current); return result; @@ -199,13 +203,13 @@ ThaiBreakEngine::ThaiBreakEngine(DictionaryMatcher *adoptDictionary, UErrorCode { UTRACE_ENTRY(UTRACE_UBRK_CREATE_BREAK_ENGINE); UTRACE_DATA1(UTRACE_INFO, "dictbe=%s", "Thai"); - fThaiWordSet.applyPattern(UNICODE_STRING_SIMPLE("[[:Thai:]&[:LineBreak=SA:]]"), status); + UnicodeSet thaiWordSet(UnicodeString(u"[[:Thai:]&[:LineBreak=SA:]]"), status); if (U_SUCCESS(status)) { - setCharacters(fThaiWordSet); + setCharacters(thaiWordSet); } - fMarkSet.applyPattern(UNICODE_STRING_SIMPLE("[[:Thai:]&[:LineBreak=SA:]&[:M:]]"), status); + fMarkSet.applyPattern(UnicodeString(u"[[:Thai:]&[:LineBreak=SA:]&[:M:]]"), status); fMarkSet.add(0x0020); - fEndWordSet = fThaiWordSet; + fEndWordSet = thaiWordSet; fEndWordSet.remove(0x0E31); // MAI HAN-AKAT fEndWordSet.remove(0x0E40, 0x0E44); // SARA E through SARA AI MAIMALAI fBeginWordSet.add(0x0E01, 0x0E2E); // KO KAI through HO NOKHUK @@ -230,6 +234,7 @@ ThaiBreakEngine::divideUpDictionaryRange( UText *text, int32_t rangeStart, int32_t rangeEnd, UVector32 &foundBreaks, + UBool /* isPhraseBreaking */, UErrorCode& status) const { if (U_FAILURE(status)) return 0; utext_setNativeIndex(text, rangeStart); @@ -441,13 +446,13 @@ LaoBreakEngine::LaoBreakEngine(DictionaryMatcher *adoptDictionary, UErrorCode &s { UTRACE_ENTRY(UTRACE_UBRK_CREATE_BREAK_ENGINE); UTRACE_DATA1(UTRACE_INFO, "dictbe=%s", "Laoo"); - fLaoWordSet.applyPattern(UNICODE_STRING_SIMPLE("[[:Laoo:]&[:LineBreak=SA:]]"), status); + UnicodeSet laoWordSet(UnicodeString(u"[[:Laoo:]&[:LineBreak=SA:]]"), status); if (U_SUCCESS(status)) { - setCharacters(fLaoWordSet); + setCharacters(laoWordSet); } - fMarkSet.applyPattern(UNICODE_STRING_SIMPLE("[[:Laoo:]&[:LineBreak=SA:]&[:M:]]"), status); + fMarkSet.applyPattern(UnicodeString(u"[[:Laoo:]&[:LineBreak=SA:]&[:M:]]"), status); fMarkSet.add(0x0020); - fEndWordSet = fLaoWordSet; + fEndWordSet = laoWordSet; fEndWordSet.remove(0x0EC0, 0x0EC4); // prefix vowels fBeginWordSet.add(0x0E81, 0x0EAE); // basic consonants (including holes for corresponding Thai characters) fBeginWordSet.add(0x0EDC, 0x0EDD); // digraph consonants (no Thai equivalent) @@ -469,6 +474,7 @@ LaoBreakEngine::divideUpDictionaryRange( UText *text, int32_t rangeStart, int32_t rangeEnd, UVector32 &foundBreaks, + UBool /* isPhraseBreaking */, UErrorCode& status) const { if (U_FAILURE(status)) return 0; if ((rangeEnd - rangeStart) < LAO_MIN_WORD_SPAN) { @@ -637,14 +643,13 @@ BurmeseBreakEngine::BurmeseBreakEngine(DictionaryMatcher *adoptDictionary, UErro { UTRACE_ENTRY(UTRACE_UBRK_CREATE_BREAK_ENGINE); UTRACE_DATA1(UTRACE_INFO, "dictbe=%s", "Mymr"); - fBurmeseWordSet.applyPattern(UNICODE_STRING_SIMPLE("[[:Mymr:]&[:LineBreak=SA:]]"), status); + fBeginWordSet.add(0x1000, 0x102A); // basic consonants and independent vowels + fEndWordSet.applyPattern(UnicodeString(u"[[:Mymr:]&[:LineBreak=SA:]]"), status); + fMarkSet.applyPattern(UnicodeString(u"[[:Mymr:]&[:LineBreak=SA:]&[:M:]]"), status); + fMarkSet.add(0x0020); if (U_SUCCESS(status)) { - setCharacters(fBurmeseWordSet); + setCharacters(fEndWordSet); } - fMarkSet.applyPattern(UNICODE_STRING_SIMPLE("[[:Mymr:]&[:LineBreak=SA:]&[:M:]]"), status); - fMarkSet.add(0x0020); - fEndWordSet = fBurmeseWordSet; - fBeginWordSet.add(0x1000, 0x102A); // basic consonants and independent vowels // Compact for caching. fMarkSet.compact(); @@ -662,6 +667,7 @@ BurmeseBreakEngine::divideUpDictionaryRange( UText *text, int32_t rangeStart, int32_t rangeEnd, UVector32 &foundBreaks, + UBool /* isPhraseBreaking */, UErrorCode& status ) const { if (U_FAILURE(status)) return 0; if ((rangeEnd - rangeStart) < BURMESE_MIN_WORD_SPAN) { @@ -830,13 +836,13 @@ KhmerBreakEngine::KhmerBreakEngine(DictionaryMatcher *adoptDictionary, UErrorCod { UTRACE_ENTRY(UTRACE_UBRK_CREATE_BREAK_ENGINE); UTRACE_DATA1(UTRACE_INFO, "dictbe=%s", "Khmr"); - fKhmerWordSet.applyPattern(UNICODE_STRING_SIMPLE("[[:Khmr:]&[:LineBreak=SA:]]"), status); + UnicodeSet khmerWordSet(UnicodeString(u"[[:Khmr:]&[:LineBreak=SA:]]"), status); if (U_SUCCESS(status)) { - setCharacters(fKhmerWordSet); + setCharacters(khmerWordSet); } - fMarkSet.applyPattern(UNICODE_STRING_SIMPLE("[[:Khmr:]&[:LineBreak=SA:]&[:M:]]"), status); + fMarkSet.applyPattern(UnicodeString(u"[[:Khmr:]&[:LineBreak=SA:]&[:M:]]"), status); fMarkSet.add(0x0020); - fEndWordSet = fKhmerWordSet; + fEndWordSet = khmerWordSet; fBeginWordSet.add(0x1780, 0x17B3); //fBeginWordSet.add(0x17A3, 0x17A4); // deprecated vowels //fEndWordSet.remove(0x17A5, 0x17A9); // Khmer independent vowels that can't end a word @@ -867,6 +873,7 @@ KhmerBreakEngine::divideUpDictionaryRange( UText *text, int32_t rangeStart, int32_t rangeEnd, UVector32 &foundBreaks, + UBool /* isPhraseBreaking */, UErrorCode& status ) const { if (U_FAILURE(status)) return 0; if ((rangeEnd - rangeStart) < KHMER_MIN_WORD_SPAN) { @@ -1050,25 +1057,27 @@ CjkBreakEngine::CjkBreakEngine(DictionaryMatcher *adoptDictionary, LanguageType : DictionaryBreakEngine(), fDictionary(adoptDictionary) { UTRACE_ENTRY(UTRACE_UBRK_CREATE_BREAK_ENGINE); UTRACE_DATA1(UTRACE_INFO, "dictbe=%s", "Hani"); - // Korean dictionary only includes Hangul syllables - fHangulWordSet.applyPattern(UNICODE_STRING_SIMPLE("[\\uac00-\\ud7a3]"), status); - fHanWordSet.applyPattern(UNICODE_STRING_SIMPLE("[:Han:]"), status); - fKatakanaWordSet.applyPattern(UNICODE_STRING_SIMPLE("[[:Katakana:]\\uff9e\\uff9f]"), status); - fHiraganaWordSet.applyPattern(UNICODE_STRING_SIMPLE("[:Hiragana:]"), status); nfkcNorm2 = Normalizer2::getNFKCInstance(status); - - if (U_SUCCESS(status)) { - // handle Korean and Japanese/Chinese using different dictionaries - if (type == kKorean) { + // Korean dictionary only includes Hangul syllables + fHangulWordSet.applyPattern(UnicodeString(u"[\\uac00-\\ud7a3]"), status); + fHangulWordSet.compact(); + // Digits, open puncutation and Alphabetic characters. + fDigitOrOpenPunctuationOrAlphabetSet.applyPattern( + UnicodeString(u"[[:Nd:][:Pi:][:Ps:][:Alphabetic:]]"), status); + fDigitOrOpenPunctuationOrAlphabetSet.compact(); + fClosePunctuationSet.applyPattern(UnicodeString(u"[[:Pc:][:Pd:][:Pe:][:Pf:][:Po:]]"), status); + fClosePunctuationSet.compact(); + + // handle Korean and Japanese/Chinese using different dictionaries + if (type == kKorean) { + if (U_SUCCESS(status)) { setCharacters(fHangulWordSet); - } else { //Chinese and Japanese - UnicodeSet cjSet; - cjSet.addAll(fHanWordSet); - cjSet.addAll(fKatakanaWordSet); - cjSet.addAll(fHiraganaWordSet); - cjSet.add(0xFF70); // HALFWIDTH KATAKANA-HIRAGANA PROLONGED SOUND MARK - cjSet.add(0x30FC); // KATAKANA-HIRAGANA PROLONGED SOUND MARK + } + } else { //Chinese and Japanese + UnicodeSet cjSet(UnicodeString(u"[[:Han:][:Hiragana:][:Katakana:]\\u30fc\\uff70\\uff9e\\uff9f]"), status); + if (U_SUCCESS(status)) { setCharacters(cjSet); + initJapanesePhraseParameter(status); } } UTRACE_EXIT_STATUS(status); @@ -1096,14 +1105,12 @@ static inline bool isKatakana(UChar32 value) { (value >= 0xFF66 && value <= 0xFF9f); } - // Function for accessing internal utext flags. // Replicates an internal UText function. static inline int32_t utext_i32_flag(int32_t bitIndex) { return (int32_t)1 << bitIndex; } - /* * @param text A UText representing the text @@ -1117,6 +1124,7 @@ CjkBreakEngine::divideUpDictionaryRange( UText *inText, int32_t rangeStart, int32_t rangeEnd, UVector32 &foundBreaks, + UBool isPhraseBreaking, UErrorCode& status) const { if (U_FAILURE(status)) return 0; if (rangeStart >= rangeEnd) { @@ -1347,6 +1355,31 @@ CjkBreakEngine::divideUpDictionaryRange( UText *inText, if ((uint32_t)bestSnlp.elementAti(numCodePts) == kuint32max) { t_boundary.addElement(numCodePts, status); numBreaks++; + } else if (isPhraseBreaking) { + t_boundary.addElement(numCodePts, status); + if(U_SUCCESS(status)) { + numBreaks++; + int32_t prevIdx = numCodePts; + + int32_t codeUnitIdx = -1; + int32_t prevCodeUnitIdx = -1; + int32_t length = -1; + for (int32_t i = prev.elementAti(numCodePts); i > 0; i = prev.elementAti(i)) { + codeUnitIdx = inString.moveIndex32(0, i); + prevCodeUnitIdx = inString.moveIndex32(0, prevIdx); + // Calculate the length by using the code unit. + length = prevCodeUnitIdx - codeUnitIdx; + prevIdx = i; + // Keep the breakpoint if the pattern is not in the fSkipSet and continuous Katakana + // characters don't occur. + if (!fSkipSet.containsKey(inString.tempSubString(codeUnitIdx, length)) + && (!isKatakana(inString.char32At(inString.moveIndex32(codeUnitIdx, -1))) + || !isKatakana(inString.char32At(codeUnitIdx)))) { + t_boundary.addElement(i, status); + numBreaks++; + } + } + } } else { for (int32_t i = numCodePts; i > 0; i = prev.elementAti(i)) { t_boundary.addElement(i, status); @@ -1367,7 +1400,8 @@ CjkBreakEngine::divideUpDictionaryRange( UText *inText, // while reversing t_boundary and pushing values to foundBreaks. int32_t prevCPPos = -1; int32_t prevUTextPos = -1; - for (int32_t i = numBreaks-1; i >= 0; i--) { + int32_t correctedNumBreaks = 0; + for (int32_t i = numBreaks - 1; i >= 0; i--) { int32_t cpPos = t_boundary.elementAti(i); U_ASSERT(cpPos > prevCPPos); int32_t utextPos = inputMap.isValid() ? inputMap->elementAti(cpPos) : cpPos + rangeStart; @@ -1375,7 +1409,15 @@ CjkBreakEngine::divideUpDictionaryRange( UText *inText, if (utextPos > prevUTextPos) { // Boundaries are added to foundBreaks output in ascending order. U_ASSERT(foundBreaks.size() == 0 || foundBreaks.peeki() < utextPos); - foundBreaks.push(utextPos, status); + // In phrase breaking, there has to be a breakpoint between Cj character and close + // punctuation. + // E.g.[携帯電話]正しい選択 -> [携帯▁電話]▁正しい▁選択 -> breakpoint between ] and 正 + if (utextPos != rangeStart + || (isPhraseBreaking && utextPos > 0 + && fClosePunctuationSet.contains(utext_char32At(inText, utextPos - 1)))) { + foundBreaks.push(utextPos, status); + correctedNumBreaks++; + } } else { // Normalization expanded the input text, the dictionary found a boundary // within the expansion, giving two boundaries with the same index in the @@ -1387,9 +1429,52 @@ CjkBreakEngine::divideUpDictionaryRange( UText *inText, } (void)prevCPPos; // suppress compiler warnings about unused variable + UChar32 nextChar = utext_char32At(inText, rangeEnd); + if (!foundBreaks.isEmpty() && foundBreaks.peeki() == rangeEnd) { + // In phrase breaking, there has to be a breakpoint between Cj character and + // the number/open punctuation. + // E.g. る文字「そうだ、京都」->る▁文字▁「そうだ、▁京都」-> breakpoint between 字 and「 + // E.g. 乗車率90%程度だろうか -> 乗車▁率▁90%▁程度だろうか -> breakpoint between 率 and 9 + // E.g. しかもロゴがUnicode! -> しかも▁ロゴが▁Unicode!-> breakpoint between が and U + if (isPhraseBreaking) { + if (!fDigitOrOpenPunctuationOrAlphabetSet.contains(nextChar)) { + foundBreaks.popi(); + correctedNumBreaks--; + } + } else { + foundBreaks.popi(); + correctedNumBreaks--; + } + } + // inString goes out of scope // inputMap goes out of scope - return numBreaks; + return correctedNumBreaks; +} + +void CjkBreakEngine::initJapanesePhraseParameter(UErrorCode& error) { + loadJapaneseExtensions(error); + loadHiragana(error); +} + +void CjkBreakEngine::loadJapaneseExtensions(UErrorCode& error) { + const char* tag = "extensions"; + ResourceBundle ja(U_ICUDATA_BRKITR, "ja", error); + if (U_SUCCESS(error)) { + ResourceBundle bundle = ja.get(tag, error); + while (U_SUCCESS(error) && bundle.hasNext()) { + fSkipSet.puti(bundle.getNextString(error), 1, error); + } + } +} + +void CjkBreakEngine::loadHiragana(UErrorCode& error) { + UnicodeSet hiraganaWordSet(UnicodeString(u"[:Hiragana:]"), error); + hiraganaWordSet.compact(); + UnicodeSetIterator iterator(hiraganaWordSet); + while (iterator.next()) { + fSkipSet.puti(UnicodeString(iterator.getCodepoint()), 1, error); + } } #endif diff --git a/Build/source/libs/icu/icu-src/source/common/dictbe.h b/Build/source/libs/icu/icu-src/source/common/dictbe.h index 4e70ed38171..ca1a3c28b7b 100644 --- a/Build/source/libs/icu/icu-src/source/common/dictbe.h +++ b/Build/source/libs/icu/icu-src/source/common/dictbe.h @@ -15,6 +15,7 @@ #include "unicode/utext.h" #include "brkeng.h" +#include "hash.h" #include "uvectr32.h" U_NAMESPACE_BEGIN @@ -80,6 +81,7 @@ class DictionaryBreakEngine : public LanguageBreakEngine { int32_t startPos, int32_t endPos, UVector32 &foundBreaks, + UBool isPhraseBreaking, UErrorCode& status ) const override; protected: @@ -105,6 +107,7 @@ class DictionaryBreakEngine : public LanguageBreakEngine { int32_t rangeStart, int32_t rangeEnd, UVector32 &foundBreaks, + UBool isPhraseBreaking, UErrorCode& status) const = 0; }; @@ -127,7 +130,6 @@ class ThaiBreakEngine : public DictionaryBreakEngine { * @internal */ - UnicodeSet fThaiWordSet; UnicodeSet fEndWordSet; UnicodeSet fBeginWordSet; UnicodeSet fSuffixSet; @@ -164,6 +166,7 @@ class ThaiBreakEngine : public DictionaryBreakEngine { int32_t rangeStart, int32_t rangeEnd, UVector32 &foundBreaks, + UBool isPhraseBreaking, UErrorCode& status) const override; }; @@ -186,7 +189,6 @@ class LaoBreakEngine : public DictionaryBreakEngine { * @internal */ - UnicodeSet fLaoWordSet; UnicodeSet fEndWordSet; UnicodeSet fBeginWordSet; UnicodeSet fMarkSet; @@ -222,6 +224,7 @@ class LaoBreakEngine : public DictionaryBreakEngine { int32_t rangeStart, int32_t rangeEnd, UVector32 &foundBreaks, + UBool isPhraseBreaking, UErrorCode& status) const override; }; @@ -244,7 +247,6 @@ class BurmeseBreakEngine : public DictionaryBreakEngine { * @internal */ - UnicodeSet fBurmeseWordSet; UnicodeSet fEndWordSet; UnicodeSet fBeginWordSet; UnicodeSet fMarkSet; @@ -280,6 +282,7 @@ class BurmeseBreakEngine : public DictionaryBreakEngine { int32_t rangeStart, int32_t rangeEnd, UVector32 &foundBreaks, + UBool isPhraseBreaking, UErrorCode& status) const override; }; @@ -302,7 +305,6 @@ class KhmerBreakEngine : public DictionaryBreakEngine { * @internal */ - UnicodeSet fKhmerWordSet; UnicodeSet fEndWordSet; UnicodeSet fBeginWordSet; UnicodeSet fMarkSet; @@ -338,6 +340,7 @@ class KhmerBreakEngine : public DictionaryBreakEngine { int32_t rangeStart, int32_t rangeEnd, UVector32 &foundBreaks, + UBool isPhraseBreaking, UErrorCode& status) const override; }; @@ -366,13 +369,22 @@ class CjkBreakEngine : public DictionaryBreakEngine { * @internal */ UnicodeSet fHangulWordSet; - UnicodeSet fHanWordSet; - UnicodeSet fKatakanaWordSet; - UnicodeSet fHiraganaWordSet; + UnicodeSet fDigitOrOpenPunctuationOrAlphabetSet; + UnicodeSet fClosePunctuationSet; DictionaryMatcher *fDictionary; const Normalizer2 *nfkcNorm2; + private: + // Load Japanese extensions. + void loadJapaneseExtensions(UErrorCode& error); + // Load Japanese Hiragana. + void loadHiragana(UErrorCode& error); + // Initialize fSkipSet by loading Japanese Hiragana and extensions. + void initJapanesePhraseParameter(UErrorCode& error); + + Hashtable fSkipSet; + public: /** @@ -404,6 +416,7 @@ class CjkBreakEngine : public DictionaryBreakEngine { int32_t rangeStart, int32_t rangeEnd, UVector32 &foundBreaks, + UBool isPhraseBreaking, UErrorCode& status) const override; }; diff --git a/Build/source/libs/icu/icu-src/source/common/localematcher.cpp b/Build/source/libs/icu/icu-src/source/common/localematcher.cpp index 3d178dfbaf1..2cad708d99f 100644 --- a/Build/source/libs/icu/icu-src/source/common/localematcher.cpp +++ b/Build/source/libs/icu/icu-src/source/common/localematcher.cpp @@ -168,12 +168,9 @@ void LocaleMatcher::Builder::clearSupportedLocales() { bool LocaleMatcher::Builder::ensureSupportedLocaleVector() { if (U_FAILURE(errorCode_)) { return false; } if (supportedLocales_ != nullptr) { return true; } - supportedLocales_ = new UVector(uprv_deleteUObject, nullptr, errorCode_); + LocalPointer<UVector> lpSupportedLocales(new UVector(uprv_deleteUObject, nullptr, errorCode_), errorCode_); if (U_FAILURE(errorCode_)) { return false; } - if (supportedLocales_ == nullptr) { - errorCode_ = U_MEMORY_ALLOCATION_ERROR; - return false; - } + supportedLocales_ = lpSupportedLocales.orphan(); return true; } @@ -187,9 +184,8 @@ LocaleMatcher::Builder &LocaleMatcher::Builder::setSupportedLocalesFromListStrin for (int32_t i = 0; i < length; ++i) { Locale *locale = list.orphanLocaleAt(i); if (locale == nullptr) { continue; } - supportedLocales_->addElementX(locale, errorCode_); + supportedLocales_->adoptElement(locale, errorCode_); if (U_FAILURE(errorCode_)) { - delete locale; break; } } @@ -197,35 +193,21 @@ LocaleMatcher::Builder &LocaleMatcher::Builder::setSupportedLocalesFromListStrin } LocaleMatcher::Builder &LocaleMatcher::Builder::setSupportedLocales(Locale::Iterator &locales) { - if (U_FAILURE(errorCode_)) { return *this; } - clearSupportedLocales(); - if (!ensureSupportedLocaleVector()) { return *this; } - while (locales.hasNext()) { - const Locale &locale = locales.next(); - Locale *clone = locale.clone(); - if (clone == nullptr) { - errorCode_ = U_MEMORY_ALLOCATION_ERROR; - break; - } - supportedLocales_->addElementX(clone, errorCode_); - if (U_FAILURE(errorCode_)) { - delete clone; - break; + if (ensureSupportedLocaleVector()) { + clearSupportedLocales(); + while (locales.hasNext() && U_SUCCESS(errorCode_)) { + const Locale &locale = locales.next(); + LocalPointer<Locale> clone (locale.clone(), errorCode_); + supportedLocales_->adoptElement(clone.orphan(), errorCode_); } } return *this; } LocaleMatcher::Builder &LocaleMatcher::Builder::addSupportedLocale(const Locale &locale) { - if (!ensureSupportedLocaleVector()) { return *this; } - Locale *clone = locale.clone(); - if (clone == nullptr) { - errorCode_ = U_MEMORY_ALLOCATION_ERROR; - return *this; - } - supportedLocales_->addElementX(clone, errorCode_); - if (U_FAILURE(errorCode_)) { - delete clone; + if (ensureSupportedLocaleVector()) { + LocalPointer<Locale> clone(locale.clone(), errorCode_); + supportedLocales_->adoptElement(clone.orphan(), errorCode_); } return *this; } diff --git a/Build/source/libs/icu/icu-src/source/common/locid.cpp b/Build/source/libs/icu/icu-src/source/common/locid.cpp index e8859c7048b..73bb8d8aec1 100644 --- a/Build/source/libs/icu/icu-src/source/common/locid.cpp +++ b/Build/source/libs/icu/icu-src/source/common/locid.cpp @@ -1204,14 +1204,11 @@ AliasReplacer::parseLanguageReplacement( // We have multiple field so we have to allocate and parse CharString* str = new CharString( replacement, (int32_t)uprv_strlen(replacement), status); + LocalPointer<CharString> lpStr(str, status); + toBeFreed.adoptElement(lpStr.orphan(), status); if (U_FAILURE(status)) { return; } - if (str == nullptr) { - status = U_MEMORY_ALLOCATION_ERROR; - return; - } - toBeFreed.addElementX(str, status); char* data = str->data(); replacedLanguage = (const char*) data; char* endOfField = uprv_strchr(data, '_'); @@ -1420,12 +1417,9 @@ AliasReplacer::replaceTerritory(UVector& toBeFreed, UErrorCode& status) (int32_t)(firstSpace - replacement), status), status); } if (U_FAILURE(status)) { return false; } - if (item.isNull()) { - status = U_MEMORY_ALLOCATION_ERROR; - return false; - } replacedRegion = item->data(); - toBeFreed.addElementX(item.orphan(), status); + toBeFreed.adoptElement(item.orphan(), status); + if (U_FAILURE(status)) { return false; } } U_ASSERT(!same(region, replacedRegion)); region = replacedRegion; @@ -1659,10 +1653,10 @@ AliasReplacer::replace(const Locale& locale, CharString& out, UErrorCode& status while ((end = uprv_strchr(start, SEP_CHAR)) != nullptr && U_SUCCESS(status)) { *end = NULL_CHAR; // null terminate inside variantsBuff - variants.addElementX(start, status); + variants.addElement(start, status); start = end + 1; } - variants.addElementX(start, status); + variants.addElement(start, status); } if (U_FAILURE(status)) { return false; } diff --git a/Build/source/libs/icu/icu-src/source/common/lstmbe.cpp b/Build/source/libs/icu/icu-src/source/common/lstmbe.cpp index 3793abceb3f..f6114cdfe25 100644 --- a/Build/source/libs/icu/icu-src/source/common/lstmbe.cpp +++ b/Build/source/libs/icu/icu-src/source/common/lstmbe.cpp @@ -1,8 +1,8 @@ // © 2021 and later: Unicode, Inc. and others. // License & terms of use: http://www.unicode.org/copyright.html +#include <complex> #include <utility> -#include <ctgmath> #include "unicode/utypes.h" @@ -639,6 +639,7 @@ LSTMBreakEngine::divideUpDictionaryRange( UText *text, int32_t startPos, int32_t endPos, UVector32 &foundBreaks, + UBool /* isPhraseBreaking */, UErrorCode& status) const { if (U_FAILURE(status)) return 0; int32_t beginFoundBreakSize = foundBreaks.size(); diff --git a/Build/source/libs/icu/icu-src/source/common/lstmbe.h b/Build/source/libs/icu/icu-src/source/common/lstmbe.h index c3f7ecf8154..ffdf805eca2 100644 --- a/Build/source/libs/icu/icu-src/source/common/lstmbe.h +++ b/Build/source/libs/icu/icu-src/source/common/lstmbe.h @@ -62,6 +62,7 @@ protected: int32_t rangeStart, int32_t rangeEnd, UVector32 &foundBreaks, + UBool isPhraseBreaking, UErrorCode& status) const override; private: const LSTMData* fData; diff --git a/Build/source/libs/icu/icu-src/source/common/normalizer2impl.cpp b/Build/source/libs/icu/icu-src/source/common/normalizer2impl.cpp index 5bfd49e8cb9..e6bd75e7173 100644 --- a/Build/source/libs/icu/icu-src/source/common/normalizer2impl.cpp +++ b/Build/source/libs/icu/icu-src/source/common/normalizer2impl.cpp @@ -2496,15 +2496,18 @@ void CanonIterData::addToStartSet(UChar32 origin, UChar32 decompLead, UErrorCode // origin is not the first character, or it is U+0000. UnicodeSet *set; if((canonValue&CANON_HAS_SET)==0) { - set=new UnicodeSet; - if(set==NULL) { - errorCode=U_MEMORY_ALLOCATION_ERROR; + LocalPointer<UnicodeSet> lpSet(new UnicodeSet, errorCode); + set=lpSet.getAlias(); + if(U_FAILURE(errorCode)) { return; } UChar32 firstOrigin=(UChar32)(canonValue&CANON_VALUE_MASK); canonValue=(canonValue&~CANON_VALUE_MASK)|CANON_HAS_SET|(uint32_t)canonStartSets.size(); umutablecptrie_set(mutableTrie, decompLead, canonValue, &errorCode); - canonStartSets.addElementX(set, errorCode); + canonStartSets.adoptElement(lpSet.orphan(), errorCode); + if (U_FAILURE(errorCode)) { + return; + } if(firstOrigin!=0) { set->add(firstOrigin); } diff --git a/Build/source/libs/icu/icu-src/source/common/rbbi.cpp b/Build/source/libs/icu/icu-src/source/common/rbbi.cpp index f65177f2323..cae8d154b30 100644 --- a/Build/source/libs/icu/icu-src/source/common/rbbi.cpp +++ b/Build/source/libs/icu/icu-src/source/common/rbbi.cpp @@ -82,6 +82,19 @@ RuleBasedBreakIterator::RuleBasedBreakIterator(RBBIDataHeader* data, UErrorCode } } +//------------------------------------------------------------------------------- +// +// Constructor from a UDataMemory handle to precompiled break rules +// stored in an ICU data file. This construcotr is private API, +// only for internal use. +// +//------------------------------------------------------------------------------- +RuleBasedBreakIterator::RuleBasedBreakIterator(UDataMemory* udm, UBool isPhraseBreaking, + UErrorCode &status) : RuleBasedBreakIterator(udm, status) +{ + fIsPhraseBreaking = isPhraseBreaking; +} + // // Construct from precompiled binary rules (tables). This constructor is public API, // taking the rules as a (const uint8_t *) to match the type produced by getBinaryRules(). @@ -322,6 +335,7 @@ void RuleBasedBreakIterator::init(UErrorCode &status) { fBreakCache = nullptr; fDictionaryCache = nullptr; fLookAheadMatches = nullptr; + fIsPhraseBreaking = false; // Note: IBM xlC is unable to assign or initialize member fText from UTEXT_INITIALIZER. // fText = UTEXT_INITIALIZER; diff --git a/Build/source/libs/icu/icu-src/source/common/rbbi_cache.cpp b/Build/source/libs/icu/icu-src/source/common/rbbi_cache.cpp index 6bfe3feca49..26d82df7811 100644 --- a/Build/source/libs/icu/icu-src/source/common/rbbi_cache.cpp +++ b/Build/source/libs/icu/icu-src/source/common/rbbi_cache.cpp @@ -163,7 +163,7 @@ void RuleBasedBreakIterator::DictionaryCache::populateDictionary(int32_t startPo // Ask the language object if there are any breaks. It will add them to the cache and // leave the text pointer on the other side of its range, ready to search for the next one. if (lbe != NULL) { - foundBreakCount += lbe->findBreaks(text, rangeStart, rangeEnd, fBreaks, status); + foundBreakCount += lbe->findBreaks(text, rangeStart, rangeEnd, fBreaks, fBI->fIsPhraseBreaking, status); } // Reload the loop variables for the next go-round diff --git a/Build/source/libs/icu/icu-src/source/common/serv.cpp b/Build/source/libs/icu/icu-src/source/common/serv.cpp index 0c54a4dce99..c26dbca1a9c 100644 --- a/Build/source/libs/icu/icu-src/source/common/serv.cpp +++ b/Build/source/libs/icu/icu-src/source/common/serv.cpp @@ -625,10 +625,7 @@ ICUService::getVisibleIDs(UVector& result, const UnicodeString* matchID, UErrorC } } - LocalPointer<UnicodeString> idClone(new UnicodeString(*id), status); - if (U_SUCCESS(status) && idClone->isBogus()) { - status = U_MEMORY_ALLOCATION_ERROR; - } + LocalPointer<UnicodeString> idClone(id->clone(), status); result.adoptElement(idClone.orphan(), status); } delete fallbackKey; diff --git a/Build/source/libs/icu/icu-src/source/common/servls.cpp b/Build/source/libs/icu/icu-src/source/common/servls.cpp index 7108afd4a52..98f0a8a12b0 100644 --- a/Build/source/libs/icu/icu-src/source/common/servls.cpp +++ b/Build/source/libs/icu/icu-src/source/common/servls.cpp @@ -179,7 +179,8 @@ private: length = other._ids.size(); for(i = 0; i < length; ++i) { - _ids.addElementX(((UnicodeString *)other._ids.elementAt(i))->clone(), status); + LocalPointer<UnicodeString> clonedId(((UnicodeString *)other._ids.elementAt(i))->clone(), status); + _ids.adoptElement(clonedId.orphan(), status); } if(U_SUCCESS(status)) { diff --git a/Build/source/libs/icu/icu-src/source/common/servnotf.cpp b/Build/source/libs/icu/icu-src/source/common/servnotf.cpp index 342e0d9f24d..d9fb3887520 100644 --- a/Build/source/libs/icu/icu-src/source/common/servnotf.cpp +++ b/Build/source/libs/icu/icu-src/source/common/servnotf.cpp @@ -49,7 +49,11 @@ ICUNotifier::addListener(const EventListener* l, UErrorCode& status) if (acceptsListener(*l)) { Mutex lmx(¬ifyLock); if (listeners == NULL) { - listeners = new UVector(5, status); + LocalPointer<UVector> lpListeners(new UVector(5, status), status); + if (U_FAILURE(status)) { + return; + } + listeners = lpListeners.orphan(); } else { for (int i = 0, e = listeners->size(); i < e; ++i) { const EventListener* el = (const EventListener*)(listeners->elementAt(i)); @@ -59,7 +63,7 @@ ICUNotifier::addListener(const EventListener* l, UErrorCode& status) } } - listeners->addElementX((void*)l, status); // cast away const + listeners->addElement((void*)l, status); // cast away const } #ifdef NOTIFIER_DEBUG else { @@ -102,13 +106,11 @@ ICUNotifier::removeListener(const EventListener *l, UErrorCode& status) void ICUNotifier::notifyChanged(void) { + Mutex lmx(¬ifyLock); if (listeners != NULL) { - Mutex lmx(¬ifyLock); - if (listeners != NULL) { - for (int i = 0, e = listeners->size(); i < e; ++i) { - EventListener* el = (EventListener*)listeners->elementAt(i); - notifyListener(*el); - } + for (int i = 0, e = listeners->size(); i < e; ++i) { + EventListener* el = (EventListener*)listeners->elementAt(i); + notifyListener(*el); } } } diff --git a/Build/source/libs/icu/icu-src/source/common/ubrk.cpp b/Build/source/libs/icu/icu-src/source/common/ubrk.cpp index bb5bdd1b501..f4e064961f3 100644 --- a/Build/source/libs/icu/icu-src/source/common/ubrk.cpp +++ b/Build/source/libs/icu/icu-src/source/common/ubrk.cpp @@ -168,7 +168,7 @@ ubrk_safeClone( BreakIterator *newBI = ((BreakIterator *)bi)->clone(); if (newBI == NULL) { *status = U_MEMORY_ALLOCATION_ERROR; - } else { + } else if (pBufferSize != NULL) { *status = U_SAFECLONE_ALLOCATED_WARNING; } return (UBreakIterator *)newBI; @@ -176,15 +176,7 @@ ubrk_safeClone( U_CAPI UBreakIterator * U_EXPORT2 ubrk_clone(const UBreakIterator *bi, UErrorCode *status) { - if (U_FAILURE(*status)) { - return nullptr; - } - BreakIterator *newBI = ((BreakIterator *)bi)->clone(); - if (newBI == nullptr) { - *status = U_MEMORY_ALLOCATION_ERROR; - return nullptr; - } - return (UBreakIterator *)newBI; + return ubrk_safeClone(bi, nullptr, nullptr, status); } diff --git a/Build/source/libs/icu/icu-src/source/common/ucase.cpp b/Build/source/libs/icu/icu-src/source/common/ucase.cpp index 4aa856507aa..388c86b1bba 100644 --- a/Build/source/libs/icu/icu-src/source/common/ucase.cpp +++ b/Build/source/libs/icu/icu-src/source/common/ucase.cpp @@ -22,27 +22,14 @@ #include "unicode/utypes.h" #include "unicode/unistr.h" #include "unicode/uset.h" -#include "unicode/udata.h" /* UDataInfo */ #include "unicode/utf16.h" -#include "ucmndata.h" /* DataHeader */ -#include "udatamem.h" -#include "umutex.h" -#include "uassert.h" #include "cmemory.h" -#include "utrie2.h" +#include "uassert.h" #include "ucase.h" +#include "umutex.h" +#include "utrie2.h" -struct UCaseProps { - UDataMemory *mem; - const int32_t *indexes; - const uint16_t *exceptions; - const uint16_t *unfold; - - UTrie2 trie; - uint8_t formatVersion[4]; -}; - -/* ucase_props_data.h is machine-generated by gencase --csource */ +/* ucase_props_data.h is machine-generated by genprops/casepropsbuilder.cpp */ #define INCLUDED_FROM_UCASE_CPP #include "ucase_props_data.h" @@ -77,6 +64,13 @@ ucase_addPropertyStarts(const USetAdder *sa, UErrorCode *pErrorCode) { /* data access primitives --------------------------------------------------- */ +U_CAPI const struct UCaseProps * U_EXPORT2 +ucase_getSingleton(int32_t *pExceptionsLength, int32_t *pUnfoldLength) { + *pExceptionsLength = UPRV_LENGTHOF(ucase_props_exceptions); + *pUnfoldLength = UPRV_LENGTHOF(ucase_props_unfold); + return &ucase_props_singleton; +} + U_CFUNC const UTrie2 * U_EXPORT2 ucase_getTrie() { return &ucase_props_singleton.trie; @@ -690,7 +684,7 @@ ucase_isCaseSensitive(UChar32 c) { * - The general category of C is * Nonspacing Mark (Mn), or Enclosing Mark (Me), or Format Control (Cf), or * Letter Modifier (Lm), or Symbol Modifier (Sk) - * - C is one of the following characters + * - C is one of the following characters * U+0027 APOSTROPHE * U+00AD SOFT HYPHEN (SHY) * U+2019 RIGHT SINGLE QUOTATION MARK @@ -1064,6 +1058,8 @@ ucase_toFullLower(UChar32 c, // The sign of the result has meaning, input must be non-negative so that it can be returned as is. U_ASSERT(c >= 0); UChar32 result=c; + // Reset the output pointer in case it was uninitialized. + *pString=nullptr; uint16_t props=UTRIE2_GET16(&ucase_props_singleton.trie, c); if(!UCASE_HAS_EXCEPTION(props)) { if(UCASE_IS_UPPER_OR_TITLE(props)) { @@ -1148,7 +1144,6 @@ ucase_toFullLower(UChar32 c, 0307; ; 0307; 0307; tr After_I; # COMBINING DOT ABOVE 0307; ; 0307; 0307; az After_I; # COMBINING DOT ABOVE */ - *pString=nullptr; return 0; /* remove the dot (continue without output) */ } else if(loc==UCASE_LOC_TURKISH && c==0x49 && !isFollowedByDotAbove(iter, context)) { /* @@ -1215,6 +1210,8 @@ toUpperOrTitle(UChar32 c, // The sign of the result has meaning, input must be non-negative so that it can be returned as is. U_ASSERT(c >= 0); UChar32 result=c; + // Reset the output pointer in case it was uninitialized. + *pString=nullptr; uint16_t props=UTRIE2_GET16(&ucase_props_singleton.trie, c); if(!UCASE_HAS_EXCEPTION(props)) { if(UCASE_GET_TYPE(props)==UCASE_LOWER) { @@ -1252,7 +1249,6 @@ toUpperOrTitle(UChar32 c, 0307; 0307; ; ; lt After_Soft_Dotted; # COMBINING DOT ABOVE */ - *pString=nullptr; return 0; /* remove the dot (continue without output) */ } else if(c==0x0587) { // See ICU-13416: @@ -1449,6 +1445,8 @@ ucase_toFullFolding(UChar32 c, // The sign of the result has meaning, input must be non-negative so that it can be returned as is. U_ASSERT(c >= 0); UChar32 result=c; + // Reset the output pointer in case it was uninitialized. + *pString=nullptr; uint16_t props=UTRIE2_GET16(&ucase_props_singleton.trie, c); if(!UCASE_HAS_EXCEPTION(props)) { if(UCASE_IS_UPPER_OR_TITLE(props)) { @@ -1542,7 +1540,7 @@ U_CAPI UChar32 U_EXPORT2 u_tolower(UChar32 c) { return ucase_tolower(c); } - + /* Transforms the Unicode character to its upper case equivalent.*/ U_CAPI UChar32 U_EXPORT2 u_toupper(UChar32 c) { diff --git a/Build/source/libs/icu/icu-src/source/common/ucase.h b/Build/source/libs/icu/icu-src/source/common/ucase.h index a018f82b81b..7bf57fd3706 100644 --- a/Build/source/libs/icu/icu-src/source/common/ucase.h +++ b/Build/source/libs/icu/icu-src/source/common/ucase.h @@ -312,6 +312,21 @@ UCaseMapFull(UChar32 c, U_CDECL_END +/* for icuexportdata -------------------------------------------------------- */ + +struct UCaseProps { + void *mem; // TODO: was unused, and type UDataMemory -- remove + const int32_t *indexes; + const uint16_t *exceptions; + const uint16_t *unfold; + + UTrie2 trie; + uint8_t formatVersion[4]; +}; + +U_CAPI const struct UCaseProps * U_EXPORT2 +ucase_getSingleton(int32_t *pExceptionsLength, int32_t *pUnfoldLength); + /* file definitions --------------------------------------------------------- */ #define UCASE_DATA_NAME "ucase" diff --git a/Build/source/libs/icu/icu-src/source/common/ucasemap.cpp b/Build/source/libs/icu/icu-src/source/common/ucasemap.cpp index ed72bda828f..95b55d56a02 100644 --- a/Build/source/libs/icu/icu-src/source/common/ucasemap.cpp +++ b/Build/source/libs/icu/icu-src/source/common/ucasemap.cpp @@ -112,8 +112,7 @@ ucasemap_setLocale(UCaseMap *csm, const char *locale, UErrorCode *pErrorCode) { if(length==sizeof(csm->locale)) { *pErrorCode=U_BUFFER_OVERFLOW_ERROR; } - if(U_SUCCESS(*pErrorCode)) { - csm->caseLocale=UCASE_LOC_UNKNOWN; + if(U_SUCCESS(*pErrorCode)) { csm->caseLocale = ucase_getCaseLocale(csm->locale); } else { csm->locale[0]=0; @@ -420,6 +419,97 @@ void toUpper(int32_t caseLocale, uint32_t options, #if !UCONFIG_NO_BREAK_ITERATION +namespace { + +constexpr uint8_t ACUTE_BYTE0 = u8"\u0301"[0]; + +constexpr uint8_t ACUTE_BYTE1 = u8"\u0301"[1]; + +/** + * Input: c is a letter I with or without acute accent. + * start is the index in src after c, and is less than segmentLimit. + * If a plain i/I is followed by a plain j/J, + * or an i/I with acute (precomposed or decomposed) is followed by a j/J with acute, + * then we output accordingly. + * + * @return the src index after the titlecased sequence, or the start index if no Dutch IJ + */ +int32_t maybeTitleDutchIJ(const uint8_t *src, UChar32 c, int32_t start, int32_t segmentLimit, + ByteSink &sink, uint32_t options, icu::Edits *edits, UErrorCode &errorCode) { + U_ASSERT(start < segmentLimit); + + int32_t index = start; + bool withAcute = false; + + // If the conditions are met, then the following variables tell us what to output. + int32_t unchanged1 = 0; // code units before the j, or the whole sequence (0..3) + bool doTitleJ = false; // true if the j needs to be titlecased + int32_t unchanged2 = 0; // after the j (0 or 1) + + // next character after the first letter + UChar32 c2; + c2 = src[index++]; + + // Is the first letter an i/I with accent? + if (c == u'I') { + if (c2 == ACUTE_BYTE0 && index < segmentLimit && src[index++] == ACUTE_BYTE1) { + withAcute = true; + unchanged1 = 2; // ACUTE is 2 code units in UTF-8 + if (index == segmentLimit) { return start; } + c2 = src[index++]; + } + } else { // Í + withAcute = true; + } + + // Is the next character a j/J? + if (c2 == u'j') { + doTitleJ = true; + } else if (c2 == u'J') { + ++unchanged1; + } else { + return start; + } + + // A plain i/I must be followed by a plain j/J. + // An i/I with acute must be followed by a j/J with acute. + if (withAcute) { + if ((index + 1) >= segmentLimit || src[index++] != ACUTE_BYTE0 || src[index++] != ACUTE_BYTE1) { + return start; + } + if (doTitleJ) { + unchanged2 = 2; // ACUTE is 2 code units in UTF-8 + } else { + unchanged1 = unchanged1 + 2; // ACUTE is 2 code units in UTF-8 + } + } + + // There must not be another combining mark. + if (index < segmentLimit) { + int32_t cp; + int32_t i = index; + U8_NEXT(src, i, segmentLimit, cp); + uint32_t typeMask = U_GET_GC_MASK(cp); + if ((typeMask & U_GC_M_MASK) != 0) { + return start; + } + } + + // Output the rest of the Dutch IJ. + ByteSinkUtil::appendUnchanged(src + start, unchanged1, sink, options, edits, errorCode); + start += unchanged1; + if (doTitleJ) { + ByteSinkUtil::appendCodePoint(1, u'J', sink, edits); + ++start; + } + ByteSinkUtil::appendUnchanged(src + start, unchanged2, sink, options, edits, errorCode); + + U_ASSERT(start + unchanged2 == index); + return index; +} + +} // namespace + U_CFUNC void U_CALLCONV ucasemap_internalUTF8ToTitle( int32_t caseLocale, uint32_t options, BreakIterator *iter, @@ -504,19 +594,14 @@ ucasemap_internalUTF8ToTitle( } /* Special case Dutch IJ titlecasing */ - if (titleStart+1 < index && - caseLocale == UCASE_LOC_DUTCH && - (src[titleStart] == 0x0049 || src[titleStart] == 0x0069)) { - if (src[titleStart+1] == 0x006A) { - ByteSinkUtil::appendCodePoint(1, 0x004A, sink, edits); - titleLimit++; - } else if (src[titleStart+1] == 0x004A) { - // Keep the capital J from getting lowercased. - if (!ByteSinkUtil::appendUnchanged(src+titleStart+1, 1, - sink, options, edits, errorCode)) { - return; - } - titleLimit++; + if (titleLimit < index && + caseLocale == UCASE_LOC_DUTCH) { + if (c < 0) { + c = ~c; + } + + if (c == u'I' || c == u'Í') { + titleLimit = maybeTitleDutchIJ(src, c, titleLimit, index, sink, options, edits, errorCode); } } diff --git a/Build/source/libs/icu/icu-src/source/common/ucnv.cpp b/Build/source/libs/icu/icu-src/source/common/ucnv.cpp index 5dcf35e0438..019bcb6a79c 100644 --- a/Build/source/libs/icu/icu-src/source/common/ucnv.cpp +++ b/Build/source/libs/icu/icu-src/source/common/ucnv.cpp @@ -252,7 +252,10 @@ ucnv_safeClone(const UConverter* cnv, void *stackBuffer, int32_t *pBufferSize, U UTRACE_EXIT_STATUS(*status); return NULL; } - *status = U_SAFECLONE_ALLOCATED_WARNING; + // If pBufferSize was NULL as the input, pBufferSize is set to &stackBufferSize in this function. + if (pBufferSize != &stackBufferSize) { + *status = U_SAFECLONE_ALLOCATED_WARNING; + } /* record the fact that memory was allocated */ *pBufferSize = bufferSizeNeeded; @@ -317,7 +320,11 @@ ucnv_safeClone(const UConverter* cnv, void *stackBuffer, int32_t *pBufferSize, U return localConverter; } - +U_CAPI UConverter* U_EXPORT2 +ucnv_clone(const UConverter* cnv, UErrorCode *status) +{ + return ucnv_safeClone(cnv, nullptr, nullptr, status); +} /*Decreases the reference counter in the shared immutable section of the object *and frees the mutable part*/ diff --git a/Build/source/libs/icu/icu-src/source/common/ucurr.cpp b/Build/source/libs/icu/icu-src/source/common/ucurr.cpp index 67aab4e8ffe..6e489e0563d 100644 --- a/Build/source/libs/icu/icu-src/source/common/ucurr.cpp +++ b/Build/source/libs/icu/icu-src/source/common/ucurr.cpp @@ -254,7 +254,7 @@ currSymbolsEquiv_cleanup(void) } /** - * Deleter for OlsonToMetaMappingEntry + * Deleter for IsoCodeEntry */ static void U_CALLCONV deleteIsoCodeEntry(void *obj) { diff --git a/Build/source/libs/icu/icu-src/source/common/uloc.cpp b/Build/source/libs/icu/icu-src/source/common/uloc.cpp index c8a3f1ff731..99c6a0af39d 100644 --- a/Build/source/libs/icu/icu-src/source/common/uloc.cpp +++ b/Build/source/libs/icu/icu-src/source/common/uloc.cpp @@ -186,10 +186,10 @@ NULL }; static const char* const DEPRECATED_LANGUAGES[]={ - "in", "iw", "ji", "jw", NULL, NULL + "in", "iw", "ji", "jw", "mo", NULL, NULL }; static const char* const REPLACEMENT_LANGUAGES[]={ - "id", "he", "yi", "jv", NULL, NULL + "id", "he", "yi", "jv", "ro", NULL, NULL }; /** @@ -444,7 +444,7 @@ static const char * const COUNTRIES_3[] = { /* "VA", "VC", "VE", "VG", "VI", "VN", "VU", "WF", */ "VAT", "VCT", "VEN", "VGB", "VIR", "VNM", "VUT", "WLF", /* "WS", "XK", "YE", "YT", "ZA", "ZM", "ZW", */ - "WSM", "XXK", "YEM", "MYT", "ZAF", "ZMB", "ZWE", + "WSM", "XKK", "YEM", "MYT", "ZAF", "ZMB", "ZWE", NULL, /* "AN", "BU", "CS", "FX", "RO", "SU", "TP", "YD", "YU", "ZR" */ "ANT", "BUR", "SCG", "FXX", "ROM", "SUN", "TMP", "YMD", "YUG", "ZAR", diff --git a/Build/source/libs/icu/icu-src/source/common/unicode/localematcher.h b/Build/source/libs/icu/icu-src/source/common/unicode/localematcher.h index 252bb7fdc20..0f7e04a3afd 100644 --- a/Build/source/libs/icu/icu-src/source/common/unicode/localematcher.h +++ b/Build/source/libs/icu/icu-src/source/common/unicode/localematcher.h @@ -461,13 +461,13 @@ public: * Option for whether to include or ignore one-way (fallback) match data. * By default, they are included. * - * @param direction the match direction to set. + * @param matchDirection the match direction to set. * @return this Builder object * @stable ICU 67 */ - Builder &setDirection(ULocMatchDirection direction) { + Builder &setDirection(ULocMatchDirection matchDirection) { if (U_SUCCESS(errorCode_)) { - direction_ = direction; + direction_ = matchDirection; } return *this; } diff --git a/Build/source/libs/icu/icu-src/source/common/unicode/rbbi.h b/Build/source/libs/icu/icu-src/source/common/unicode/rbbi.h index 0ce93819f54..0bad0d3897c 100644 --- a/Build/source/libs/icu/icu-src/source/common/unicode/rbbi.h +++ b/Build/source/libs/icu/icu-src/source/common/unicode/rbbi.h @@ -147,6 +147,11 @@ private: */ int32_t *fLookAheadMatches; + /** + * A flag to indicate if phrase based breaking is enabled. + */ + UBool fIsPhraseBreaking; + //======================================================================= // constructors //======================================================================= @@ -163,6 +168,21 @@ private: */ RuleBasedBreakIterator(RBBIDataHeader* data, UErrorCode &status); + /** + * This constructor uses the udata interface to create a BreakIterator + * whose internal tables live in a memory-mapped file. "image" is an + * ICU UDataMemory handle for the pre-compiled break iterator tables. + * @param image handle to the memory image for the break iterator data. + * Ownership of the UDataMemory handle passes to the Break Iterator, + * which will be responsible for closing it when it is no longer needed. + * @param status Information on any errors encountered. + * @param isPhraseBreaking true if phrase based breaking is required, otherwise false. + * @see udata_open + * @see #getBinaryRules + * @internal (private) + */ + RuleBasedBreakIterator(UDataMemory* image, UBool isPhraseBreaking, UErrorCode &status); + /** @internal */ friend class RBBIRuleBuilder; /** @internal */ diff --git a/Build/source/libs/icu/icu-src/source/common/unicode/ubrk.h b/Build/source/libs/icu/icu-src/source/common/unicode/ubrk.h index c603f7c13f3..2b3dc7aa576 100644 --- a/Build/source/libs/icu/icu-src/source/common/unicode/ubrk.h +++ b/Build/source/libs/icu/icu-src/source/common/unicode/ubrk.h @@ -312,11 +312,12 @@ ubrk_openBinaryRules(const uint8_t *binaryRules, int32_t rulesLength, * If *pBufferSize is not enough for a stack-based safe clone, * new memory will be allocated. * @param status to indicate whether the operation went on smoothly or there were errors - * An informational status value, U_SAFECLONE_ALLOCATED_ERROR, is used if any allocations were necessary. + * An informational status value, U_SAFECLONE_ALLOCATED_ERROR, is used + * if pBufferSize != NULL and any allocations were necessary * @return pointer to the new clone * @deprecated ICU 69 Use ubrk_clone() instead. */ -U_CAPI UBreakIterator * U_EXPORT2 +U_DEPRECATED UBreakIterator * U_EXPORT2 ubrk_safeClone( const UBreakIterator *bi, void *stackBuffer, @@ -325,21 +326,17 @@ ubrk_safeClone( #endif /* U_HIDE_DEPRECATED_API */ -#ifndef U_HIDE_DRAFT_API - /** * Thread safe cloning operation. * @param bi iterator to be cloned * @param status to indicate whether the operation went on smoothly or there were errors * @return pointer to the new clone - * @draft ICU 69 + * @stable ICU 69 */ U_CAPI UBreakIterator * U_EXPORT2 ubrk_clone(const UBreakIterator *bi, UErrorCode *status); -#endif // U_HIDE_DRAFT_API - #ifndef U_HIDE_DEPRECATED_API /** diff --git a/Build/source/libs/icu/icu-src/source/common/unicode/ucnv.h b/Build/source/libs/icu/icu-src/source/common/unicode/ucnv.h index 2687c984d43..20c173b6628 100644 --- a/Build/source/libs/icu/icu-src/source/common/unicode/ucnv.h +++ b/Build/source/libs/icu/icu-src/source/common/unicode/ucnv.h @@ -477,7 +477,7 @@ ucnv_openCCSID(int32_t codepage, * * <p>The name will NOT be looked up in the alias mechanism, nor will the converter be * stored in the converter cache or the alias table. The only way to open further converters - * is call this function multiple times, or use the ucnv_safeClone() function to clone a + * is call this function multiple times, or use the ucnv_clone() function to clone a * 'primary' converter.</p> * * <p>A future version of ICU may add alias table lookups and/or caching @@ -493,7 +493,7 @@ ucnv_openCCSID(int32_t codepage, * @return the created Unicode converter object, or <TT>NULL</TT> if an error occurred * @see udata_open * @see ucnv_open - * @see ucnv_safeClone + * @see ucnv_clone * @see ucnv_close * @stable ICU 2.2 */ @@ -502,6 +502,20 @@ ucnv_openPackage(const char *packageName, const char *converterName, UErrorCode /** * Thread safe converter cloning operation. + * + * You must ucnv_close() the clone. + * + * @param cnv converter to be cloned + * @param status to indicate whether the operation went on smoothly or there were errors + * @return pointer to the new clone + * @stable ICU 71 + */ +U_CAPI UConverter* U_EXPORT2 ucnv_clone(const UConverter *cnv, UErrorCode *status); + +#ifndef U_HIDE_DEPRECATED_API + +/** + * Thread safe converter cloning operation. * For most efficient operation, pass in a stackBuffer (and a *pBufferSize) * with at least U_CNV_SAFECLONE_BUFFERSIZE bytes of space. * If the buffer size is sufficient, then the clone will use the stack buffer; @@ -532,21 +546,19 @@ ucnv_openPackage(const char *packageName, const char *converterName, UErrorCode * pointer to size of allocated space. * @param status to indicate whether the operation went on smoothly or there were errors * An informational status value, U_SAFECLONE_ALLOCATED_WARNING, - * is used if any allocations were necessary. + * is used if pBufferSize != NULL and any allocations were necessary * However, it is better to check if *pBufferSize grew for checking for * allocations because warning codes can be overridden by subsequent * function calls. * @return pointer to the new clone - * @stable ICU 2.0 + * @deprecated ICU 71 Use ucnv_clone() instead. */ -U_CAPI UConverter * U_EXPORT2 +U_DEPRECATED UConverter * U_EXPORT2 ucnv_safeClone(const UConverter *cnv, void *stackBuffer, int32_t *pBufferSize, UErrorCode *status); -#ifndef U_HIDE_DEPRECATED_API - /** * \def U_CNV_SAFECLONE_BUFFERSIZE * Definition of a buffer size that is designed to be large enough for diff --git a/Build/source/libs/icu/icu-src/source/common/unicode/uniset.h b/Build/source/libs/icu/icu-src/source/common/unicode/uniset.h index 730337a3535..310c7c8d201 100644 --- a/Build/source/libs/icu/icu-src/source/common/unicode/uniset.h +++ b/Build/source/libs/icu/icu-src/source/common/unicode/uniset.h @@ -1229,7 +1229,6 @@ public: */ UnicodeSet& retain(UChar32 c); -#ifndef U_HIDE_DRAFT_API /** * Retains only the specified string from this set if it is present. * Upon return this set will be empty if it did not contain s, or @@ -1238,10 +1237,9 @@ public: * * @param s the source string * @return this object, for chaining - * @draft ICU 69 + * @stable ICU 69 */ UnicodeSet& retain(const UnicodeString &s); -#endif // U_HIDE_DRAFT_API /** * Removes the specified range from this set if it is present. diff --git a/Build/source/libs/icu/icu-src/source/common/unicode/urename.h b/Build/source/libs/icu/icu-src/source/common/unicode/urename.h index 4605f632ea8..d9f9b8f336c 100644 --- a/Build/source/libs/icu/icu-src/source/common/unicode/urename.h +++ b/Build/source/libs/icu/icu-src/source/common/unicode/urename.h @@ -567,6 +567,7 @@ #define ucase_addStringCaseClosure U_ICU_ENTRY_POINT_RENAME(ucase_addStringCaseClosure) #define ucase_fold U_ICU_ENTRY_POINT_RENAME(ucase_fold) #define ucase_getCaseLocale U_ICU_ENTRY_POINT_RENAME(ucase_getCaseLocale) +#define ucase_getSingleton U_ICU_ENTRY_POINT_RENAME(ucase_getSingleton) #define ucase_getTrie U_ICU_ENTRY_POINT_RENAME(ucase_getTrie) #define ucase_getType U_ICU_ENTRY_POINT_RENAME(ucase_getType) #define ucase_getTypeOrIgnorable U_ICU_ENTRY_POINT_RENAME(ucase_getTypeOrIgnorable) @@ -630,6 +631,7 @@ #define ucnv_cbFromUWriteUChars U_ICU_ENTRY_POINT_RENAME(ucnv_cbFromUWriteUChars) #define ucnv_cbToUWriteSub U_ICU_ENTRY_POINT_RENAME(ucnv_cbToUWriteSub) #define ucnv_cbToUWriteUChars U_ICU_ENTRY_POINT_RENAME(ucnv_cbToUWriteUChars) +#define ucnv_clone U_ICU_ENTRY_POINT_RENAME(ucnv_clone) #define ucnv_close U_ICU_ENTRY_POINT_RENAME(ucnv_close) #define ucnv_compareNames U_ICU_ENTRY_POINT_RENAME(ucnv_compareNames) #define ucnv_convert U_ICU_ENTRY_POINT_RENAME(ucnv_convert) @@ -725,6 +727,7 @@ #define ucnvsel_selectForString U_ICU_ENTRY_POINT_RENAME(ucnvsel_selectForString) #define ucnvsel_selectForUTF8 U_ICU_ENTRY_POINT_RENAME(ucnvsel_selectForUTF8) #define ucnvsel_serialize U_ICU_ENTRY_POINT_RENAME(ucnvsel_serialize) +#define ucol_clone U_ICU_ENTRY_POINT_RENAME(ucol_clone) #define ucol_cloneBinary U_ICU_ENTRY_POINT_RENAME(ucol_cloneBinary) #define ucol_close U_ICU_ENTRY_POINT_RENAME(ucol_close) #define ucol_closeElements U_ICU_ENTRY_POINT_RENAME(ucol_closeElements) @@ -904,6 +907,7 @@ #define udatpg_getBestPattern U_ICU_ENTRY_POINT_RENAME(udatpg_getBestPattern) #define udatpg_getBestPatternWithOptions U_ICU_ENTRY_POINT_RENAME(udatpg_getBestPatternWithOptions) #define udatpg_getDateTimeFormat U_ICU_ENTRY_POINT_RENAME(udatpg_getDateTimeFormat) +#define udatpg_getDateTimeFormatForStyle U_ICU_ENTRY_POINT_RENAME(udatpg_getDateTimeFormatForStyle) #define udatpg_getDecimal U_ICU_ENTRY_POINT_RENAME(udatpg_getDecimal) #define udatpg_getDefaultHourCycle U_ICU_ENTRY_POINT_RENAME(udatpg_getDefaultHourCycle) #define udatpg_getFieldDisplayName U_ICU_ENTRY_POINT_RENAME(udatpg_getFieldDisplayName) @@ -918,6 +922,7 @@ #define udatpg_setAppendItemFormat U_ICU_ENTRY_POINT_RENAME(udatpg_setAppendItemFormat) #define udatpg_setAppendItemName U_ICU_ENTRY_POINT_RENAME(udatpg_setAppendItemName) #define udatpg_setDateTimeFormat U_ICU_ENTRY_POINT_RENAME(udatpg_setDateTimeFormat) +#define udatpg_setDateTimeFormatForStyle U_ICU_ENTRY_POINT_RENAME(udatpg_setDateTimeFormatForStyle) #define udatpg_setDecimal U_ICU_ENTRY_POINT_RENAME(udatpg_setDecimal) #define udict_swap U_ICU_ENTRY_POINT_RENAME(udict_swap) #define udtitvfmt_close U_ICU_ENTRY_POINT_RENAME(udtitvfmt_close) diff --git a/Build/source/libs/icu/icu-src/source/common/unicode/uset.h b/Build/source/libs/icu/icu-src/source/common/unicode/uset.h index 2ef352ef563..33332f2d362 100644 --- a/Build/source/libs/icu/icu-src/source/common/unicode/uset.h +++ b/Build/source/libs/icu/icu-src/source/common/unicode/uset.h @@ -628,7 +628,6 @@ uset_removeRange(USet* set, UChar32 start, UChar32 end); U_CAPI void U_EXPORT2 uset_removeString(USet* set, const UChar* str, int32_t strLen); -#ifndef U_HIDE_DRAFT_API /** * Removes EACH of the characters in this string. Note: "ch" == {"c", "h"} * A frozen set will not be modified. @@ -636,11 +635,10 @@ uset_removeString(USet* set, const UChar* str, int32_t strLen); * @param set the object to be modified * @param str the string * @param length the length of the string, or -1 if NUL-terminated - * @draft ICU 69 + * @stable ICU 69 */ U_CAPI void U_EXPORT2 uset_removeAllCodePoints(USet *set, const UChar *str, int32_t length); -#endif // U_HIDE_DRAFT_API /** * Removes from this set all of its elements that are contained in the @@ -671,7 +669,6 @@ uset_removeAll(USet* set, const USet* removeSet); U_CAPI void U_EXPORT2 uset_retain(USet* set, UChar32 start, UChar32 end); -#ifndef U_HIDE_DRAFT_API /** * Retains only the specified string from this set if it is present. * Upon return this set will be empty if it did not contain s, or @@ -681,7 +678,7 @@ uset_retain(USet* set, UChar32 start, UChar32 end); * @param set the object to be modified * @param str the string * @param length the length of the string, or -1 if NUL-terminated - * @draft ICU 69 + * @stable ICU 69 */ U_CAPI void U_EXPORT2 uset_retainString(USet *set, const UChar *str, int32_t length); @@ -693,11 +690,10 @@ uset_retainString(USet *set, const UChar *str, int32_t length); * @param set the object to be modified * @param str the string * @param length the length of the string, or -1 if NUL-terminated - * @draft ICU 69 + * @stable ICU 69 */ U_CAPI void U_EXPORT2 uset_retainAllCodePoints(USet *set, const UChar *str, int32_t length); -#endif // U_HIDE_DRAFT_API /** * Retains only the elements in this set that are contained in the @@ -741,7 +737,6 @@ uset_compact(USet* set); U_CAPI void U_EXPORT2 uset_complement(USet* set); -#ifndef U_HIDE_DRAFT_API /** * Complements the specified range in this set. Any character in * the range will be removed if it is in this set, or will be @@ -753,7 +748,7 @@ uset_complement(USet* set); * @param set the object to be modified * @param start first character, inclusive, of range * @param end last character, inclusive, of range - * @draft ICU 69 + * @stable ICU 69 */ U_CAPI void U_EXPORT2 uset_complementRange(USet *set, UChar32 start, UChar32 end); @@ -766,7 +761,7 @@ uset_complementRange(USet *set, UChar32 start, UChar32 end); * @param set the object to be modified * @param str the string * @param length the length of the string, or -1 if NUL-terminated - * @draft ICU 69 + * @stable ICU 69 */ U_CAPI void U_EXPORT2 uset_complementString(USet *set, const UChar *str, int32_t length); @@ -778,11 +773,10 @@ uset_complementString(USet *set, const UChar *str, int32_t length); * @param set the object to be modified * @param str the string * @param length the length of the string, or -1 if NUL-terminated - * @draft ICU 69 + * @stable ICU 69 */ U_CAPI void U_EXPORT2 uset_complementAllCodePoints(USet *set, const UChar *str, int32_t length); -#endif // U_HIDE_DRAFT_API /** * Complements in this set all elements contained in the specified diff --git a/Build/source/libs/icu/icu-src/source/common/unicode/uvernum.h b/Build/source/libs/icu/icu-src/source/common/unicode/uvernum.h index 42e8865d7e3..2706e0b0606 100644 --- a/Build/source/libs/icu/icu-src/source/common/unicode/uvernum.h +++ b/Build/source/libs/icu/icu-src/source/common/unicode/uvernum.h @@ -60,7 +60,7 @@ * This value will change in the subsequent releases of ICU * @stable ICU 2.4 */ -#define U_ICU_VERSION_MAJOR_NUM 70 +#define U_ICU_VERSION_MAJOR_NUM 71 /** The current ICU minor version as an integer. * This value will change in the subsequent releases of ICU @@ -86,7 +86,7 @@ * This value will change in the subsequent releases of ICU * @stable ICU 2.6 */ -#define U_ICU_VERSION_SUFFIX _70 +#define U_ICU_VERSION_SUFFIX _71 /** * \def U_DEF2_ICU_ENTRY_POINT_RENAME @@ -139,7 +139,7 @@ * This value will change in the subsequent releases of ICU * @stable ICU 2.4 */ -#define U_ICU_VERSION "70.1" +#define U_ICU_VERSION "71.1" /** * The current ICU library major version number as a string, for library name suffixes. @@ -152,13 +152,13 @@ * * @stable ICU 2.6 */ -#define U_ICU_VERSION_SHORT "70" +#define U_ICU_VERSION_SHORT "71" #ifndef U_HIDE_INTERNAL_API /** Data version in ICU4C. * @internal ICU 4.4 Internal Use Only **/ -#define U_ICU_DATA_VERSION "70.1" +#define U_ICU_DATA_VERSION "71.1" #endif /* U_HIDE_INTERNAL_API */ /*=========================================================================== diff --git a/Build/source/libs/icu/icu-src/source/common/unistr.cpp b/Build/source/libs/icu/icu-src/source/common/unistr.cpp index 077b4d6ef20..c18665928d8 100644 --- a/Build/source/libs/icu/icu-src/source/common/unistr.cpp +++ b/Build/source/libs/icu/icu-src/source/common/unistr.cpp @@ -334,7 +334,8 @@ Replaceable::clone() const { // UnicodeString overrides clone() with a real implementation UnicodeString * UnicodeString::clone() const { - return new UnicodeString(*this); + LocalPointer<UnicodeString> clonedString(new UnicodeString(*this)); + return clonedString.isValid() && !clonedString->isBogus() ? clonedString.orphan() : nullptr; } //======================================== @@ -1976,7 +1977,12 @@ The vector deleting destructor is already a part of UObject, but defining it here makes sure that it is included with this object file. This makes sure that static library dependencies are kept to a minimum. */ +#if defined(__clang__) || U_GCC_MAJOR_MINOR >= 1100 +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-function" static void uprv_UnicodeStringDummy(void) { delete [] (new UnicodeString[2]); } +#pragma GCC diagnostic pop +#endif #endif diff --git a/Build/source/libs/icu/icu-src/source/common/uposixdefs.h b/Build/source/libs/icu/icu-src/source/common/uposixdefs.h index 2ac6ac48cf4..6af520bf9f1 100644 --- a/Build/source/libs/icu/icu-src/source/common/uposixdefs.h +++ b/Build/source/libs/icu/icu-src/source/common/uposixdefs.h @@ -1,4 +1,4 @@ -// © 2016 and later: Unicode, Inc. and others +// © 2016 and later: Unicode, Inc. and others. // License & terms of use: http://www.unicode.org/copyright.html /* ******************************************************************************* @@ -51,9 +51,6 @@ * Make sure things like readlink and such functions work. * Poorly upgraded Solaris machines can't have this defined. * Cleanly installed Solaris can use this #define. - * [Experience with TeX Live is that it always causes failure. - * http://tug.org/pipermail/tlbuild/2013q1/002493.html - * http://tug.org/pipermail/tlbuild/2013q1/002536.html ] * * z/OS needs this definition for timeval and to get usleep. */ diff --git a/Build/source/libs/icu/icu-src/source/common/ustrcase.cpp b/Build/source/libs/icu/icu-src/source/common/ustrcase.cpp index 36b19e75f2d..43910ea5209 100644 --- a/Build/source/libs/icu/icu-src/source/common/ustrcase.cpp +++ b/Build/source/libs/icu/icu-src/source/common/ustrcase.cpp @@ -36,6 +36,12 @@ #include "ustr_imp.h" #include "uassert.h" +/** + * Code point for COMBINING ACUTE ACCENT + * @internal + */ +#define ACUTE u'\u0301' + U_NAMESPACE_BEGIN namespace { @@ -396,6 +402,94 @@ U_NAMESPACE_USE #if !UCONFIG_NO_BREAK_ITERATION +namespace { + +/** + * Input: c is a letter I with or without acute accent. + * start is the index in src after c, and is less than segmentLimit. + * If a plain i/I is followed by a plain j/J, + * or an i/I with acute (precomposed or decomposed) is followed by a j/J with acute, + * then we output accordingly. + * + * @return the src index after the titlecased sequence, or the start index if no Dutch IJ + */ +int32_t maybeTitleDutchIJ(const UChar *src, UChar32 c, int32_t start, int32_t segmentLimit, + UChar *dest, int32_t &destIndex, int32_t destCapacity, uint32_t options, + icu::Edits *edits) { + U_ASSERT(start < segmentLimit); + + int32_t index = start; + bool withAcute = false; + + // If the conditions are met, then the following variables tell us what to output. + int32_t unchanged1 = 0; // code units before the j, or the whole sequence (0..3) + bool doTitleJ = false; // true if the j needs to be titlecased + int32_t unchanged2 = 0; // after the j (0 or 1) + + // next character after the first letter + UChar c2 = src[index++]; + + // Is the first letter an i/I with accent? + if (c == u'I') { + if (c2 == ACUTE) { + withAcute = true; + unchanged1 = 1; + if (index == segmentLimit) { return start; } + c2 = src[index++]; + } + } else { // Í + withAcute = true; + } + + // Is the next character a j/J? + if (c2 == u'j') { + doTitleJ = true; + } else if (c2 == u'J') { + ++unchanged1; + } else { + return start; + } + + // A plain i/I must be followed by a plain j/J. + // An i/I with acute must be followed by a j/J with acute. + if (withAcute) { + if (index == segmentLimit || src[index++] != ACUTE) { return start; } + if (doTitleJ) { + unchanged2 = 1; + } else { + ++unchanged1; + } + } + + // There must not be another combining mark. + if (index < segmentLimit) { + int32_t cp; + int32_t i = index; + U16_NEXT(src, i, segmentLimit, cp); + uint32_t typeMask = U_GET_GC_MASK(cp); + if ((typeMask & U_GC_M_MASK) != 0) { + return start; + } + } + + // Output the rest of the Dutch IJ. + destIndex = appendUnchanged(dest, destIndex, destCapacity, src + start, unchanged1, options, edits); + start += unchanged1; + if (doTitleJ) { + destIndex = appendUChar(dest, destIndex, destCapacity, u'J'); + if (edits != nullptr) { + edits->addReplace(1, 1); + } + ++start; + } + destIndex = appendUnchanged(dest, destIndex, destCapacity, src + start, unchanged2, options, edits); + + U_ASSERT(start + unchanged2 == index); + return index; +} + +} // namespace + U_CFUNC int32_t U_CALLCONV ustrcase_internalToTitle(int32_t caseLocale, uint32_t options, BreakIterator *iter, UChar *dest, int32_t destCapacity, @@ -412,14 +506,14 @@ ustrcase_internalToTitle(int32_t caseLocale, uint32_t options, BreakIterator *it csc.limit=srcLength; int32_t destIndex=0; int32_t prev=0; - UBool isFirstIndex=TRUE; + bool isFirstIndex=true; /* titlecasing loop */ while(prev<srcLength) { /* find next index where to titlecase */ int32_t index; if(isFirstIndex) { - isFirstIndex=FALSE; + isFirstIndex=false; index=iter->first(); } else { index=iter->next(); @@ -446,7 +540,7 @@ ustrcase_internalToTitle(int32_t caseLocale, uint32_t options, BreakIterator *it // Stop with titleStart<titleLimit<=index // if there is a character to be titlecased, // or else stop with titleStart==titleLimit==index. - UBool toCased = (options&U_TITLECASE_ADJUST_TO_CASED) != 0; + bool toCased = (options&U_TITLECASE_ADJUST_TO_CASED) != 0; while (toCased ? UCASE_NONE==ucase_getType(c) : !ustrcase_isLNS(c)) { titleStart=titleLimit; if(titleLimit==index) { @@ -479,27 +573,15 @@ ustrcase_internalToTitle(int32_t caseLocale, uint32_t options, BreakIterator *it /* Special case Dutch IJ titlecasing */ if (titleStart+1 < index && - caseLocale == UCASE_LOC_DUTCH && - (src[titleStart] == 0x0049 || src[titleStart] == 0x0069)) { - if (src[titleStart+1] == 0x006A) { - destIndex=appendUChar(dest, destIndex, destCapacity, 0x004A); - if(destIndex<0) { - errorCode=U_INDEX_OUTOFBOUNDS_ERROR; - return 0; - } - if(edits!=NULL) { - edits->addReplace(1, 1); - } - titleLimit++; - } else if (src[titleStart+1] == 0x004A) { - // Keep the capital J from getting lowercased. - destIndex=appendUnchanged(dest, destIndex, destCapacity, - src+titleStart+1, 1, options, edits); - if(destIndex<0) { - errorCode=U_INDEX_OUTOFBOUNDS_ERROR; - return 0; - } - titleLimit++; + caseLocale == UCASE_LOC_DUTCH) { + if (c < 0) { + c = ~c; + } + + if (c == u'I' || c == u'Í') { + titleLimit = maybeTitleDutchIJ(src, c, titleStart + 1, index, + dest, destIndex, destCapacity, options, + edits); } } diff --git a/Build/source/libs/icu/icu-src/source/common/uvector.cpp b/Build/source/libs/icu/icu-src/source/common/uvector.cpp index 4da8b864e1b..844463921ef 100644 --- a/Build/source/libs/icu/icu-src/source/common/uvector.cpp +++ b/Build/source/libs/icu/icu-src/source/common/uvector.cpp @@ -99,14 +99,6 @@ bool UVector::operator==(const UVector& other) const { return true; } -// TODO: delete this function once all call sites have been migrated to the -// new addElement(). -void UVector::addElementX(void* obj, UErrorCode &status) { - if (ensureCapacityX(count + 1, status)) { - elements[count++].pointer = obj; - } -} - void UVector::addElement(void* obj, UErrorCode &status) { U_ASSERT(deleter == nullptr); if (ensureCapacity(count + 1, status)) { @@ -331,38 +323,6 @@ int32_t UVector::indexOf(UElement key, int32_t startIndex, int8_t hint) const { return -1; } -UBool UVector::ensureCapacityX(int32_t minimumCapacity, UErrorCode &status) { - if (minimumCapacity < 0) { - status = U_ILLEGAL_ARGUMENT_ERROR; - return FALSE; - } - if (capacity < minimumCapacity) { - if (capacity > (INT32_MAX - 1) / 2) { // integer overflow check - status = U_ILLEGAL_ARGUMENT_ERROR; - return FALSE; - } - int32_t newCap = capacity * 2; - if (newCap < minimumCapacity) { - newCap = minimumCapacity; - } - if (newCap > (int32_t)(INT32_MAX / sizeof(UElement))) { // integer overflow check - // We keep the original memory contents on bad minimumCapacity. - status = U_ILLEGAL_ARGUMENT_ERROR; - return FALSE; - } - UElement* newElems = (UElement *)uprv_realloc(elements, sizeof(UElement)*newCap); - if (newElems == nullptr) { - // We keep the original contents on the memory failure on realloc or bad minimumCapacity. - status = U_MEMORY_ALLOCATION_ERROR; - return FALSE; - } - elements = newElems; - capacity = newCap; - } - return TRUE; -} - - UBool UVector::ensureCapacity(int32_t minimumCapacity, UErrorCode &status) { if (U_FAILURE(status)) { return false; @@ -370,7 +330,7 @@ UBool UVector::ensureCapacity(int32_t minimumCapacity, UErrorCode &status) { if (minimumCapacity < 0) { status = U_ILLEGAL_ARGUMENT_ERROR; return false; - } + } if (capacity < minimumCapacity) { if (capacity > (INT32_MAX - 1) / 2) { // integer overflow check status = U_ILLEGAL_ARGUMENT_ERROR; @@ -396,6 +356,7 @@ UBool UVector::ensureCapacity(int32_t minimumCapacity, UErrorCode &status) { } return true; } + /** * Change the size of this vector as follows: If newSize is smaller, * then truncate the array, possibly deleting held elements for i >= diff --git a/Build/source/libs/icu/icu-src/source/common/uvector.h b/Build/source/libs/icu/icu-src/source/common/uvector.h index f61fcc2be60..1eb7d136e7a 100644 --- a/Build/source/libs/icu/icu-src/source/common/uvector.h +++ b/Build/source/libs/icu/icu-src/source/common/uvector.h @@ -123,12 +123,6 @@ public: // java.util.Vector API //------------------------------------------------------------ - /* - * Old version of addElement, with non-standard error handling. - * Will be removed once all uses have been switched to the new addElement(). - */ - void addElementX(void* obj, UErrorCode &status); - /** * Add an element at the end of the vector. * For use only with vectors that do not adopt their elements, which is to say, @@ -197,12 +191,6 @@ public: inline UBool isEmpty(void) const {return count == 0;} - /* - * Old version of ensureCapacity, with non-standard error handling. - * Will be removed once all uses have been switched to the new ensureCapacity(). - */ - UBool ensureCapacityX(int32_t minimumCapacity, UErrorCode &status); - UBool ensureCapacity(int32_t minimumCapacity, UErrorCode &status); /** diff --git a/Build/source/libs/icu/icu-src/source/common/uvectr32.cpp b/Build/source/libs/icu/icu-src/source/common/uvectr32.cpp index a77ecb689fd..2b4d0b8a75a 100644 --- a/Build/source/libs/icu/icu-src/source/common/uvectr32.cpp +++ b/Build/source/libs/icu/icu-src/source/common/uvectr32.cpp @@ -83,7 +83,7 @@ void UVector32::assign(const UVector32& other, UErrorCode &ec) { } -bool UVector32::operator==(const UVector32& other) { +bool UVector32::operator==(const UVector32& other) const { int32_t i; if (count != other.count) return false; for (i=0; i<count; ++i) { diff --git a/Build/source/libs/icu/icu-src/source/common/uvectr32.h b/Build/source/libs/icu/icu-src/source/common/uvectr32.h index f08c2ade765..ecefb7af3ea 100644 --- a/Build/source/libs/icu/icu-src/source/common/uvectr32.h +++ b/Build/source/libs/icu/icu-src/source/common/uvectr32.h @@ -86,12 +86,12 @@ public: * equal if they are of the same size and all elements are equal, * as compared using this object's comparer. */ - bool operator==(const UVector32& other); + bool operator==(const UVector32& other) const; /** * Equivalent to !operator==() */ - inline bool operator!=(const UVector32& other); + inline bool operator!=(const UVector32& other) const; //------------------------------------------------------------ // java.util.Vector API @@ -268,7 +268,7 @@ inline int32_t UVector32::lastElementi(void) const { return elementAti(count-1); } -inline bool UVector32::operator!=(const UVector32& other) { +inline bool UVector32::operator!=(const UVector32& other) const { return !operator==(other); } diff --git a/Build/source/libs/icu/icu-src/source/configure b/Build/source/libs/icu/icu-src/source/configure index b7709d56556..421ef87c249 100755 --- a/Build/source/libs/icu/icu-src/source/configure +++ b/Build/source/libs/icu/icu-src/source/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for ICU 70.1. +# Generated by GNU Autoconf 2.69 for ICU 71.1. # # Report bugs to <http://icu-project.org/bugs>. # @@ -582,8 +582,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='ICU' PACKAGE_TARNAME='International Components for Unicode' -PACKAGE_VERSION='70.1' -PACKAGE_STRING='ICU 70.1' +PACKAGE_VERSION='71.1' +PACKAGE_STRING='ICU 71.1' PACKAGE_BUGREPORT='http://icu-project.org/bugs' PACKAGE_URL='http://icu-project.org' @@ -1375,7 +1375,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures ICU 70.1 to adapt to many kinds of systems. +\`configure' configures ICU 71.1 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1442,7 +1442,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of ICU 70.1:";; + short | recursive ) echo "Configuration of ICU 71.1:";; esac cat <<\_ACEOF @@ -1580,7 +1580,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -ICU configure 70.1 +ICU configure 71.1 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -2326,7 +2326,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by ICU $as_me 70.1, which was +It was created by ICU $as_me 71.1, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -6160,12 +6160,6 @@ $as_echo "$as_me: Adding CXXFLAGS option -std=c++11" >&6;} else CXXFLAGS="$OLD_CXXFLAGS" fi -# TL: why? http://bugs.icu-project.org/trac/ticket/13543 -# case "${host}" in -# *-*-solaris*) -# CXXFLAGS="$OLD_CXXFLAGS" -# ;; -# esac fi fi @@ -8607,7 +8601,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by ICU $as_me 70.1, which was +This file was extended by ICU $as_me 71.1, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -8661,7 +8655,7 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -ICU config.status 70.1 +ICU config.status 71.1 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" diff --git a/Build/source/libs/icu/icu-src/source/configure.ac b/Build/source/libs/icu/icu-src/source/configure.ac index 22c11af06a3..ba97cbc286a 100644 --- a/Build/source/libs/icu/icu-src/source/configure.ac +++ b/Build/source/libs/icu/icu-src/source/configure.ac @@ -527,11 +527,6 @@ if [[ "$GXX" = yes ]]; then else CXXFLAGS="$OLD_CXXFLAGS" fi - case "${host}" in - *-*-solaris*) - CXXFLAGS="$OLD_CXXFLAGS" - ;; - esac fi fi diff --git a/Build/source/libs/icu/icu-src/source/data/cldr-icu-readme.txt b/Build/source/libs/icu/icu-src/source/data/cldr-icu-readme.txt index 93ba253d715..72821872e1c 100644 --- a/Build/source/libs/icu/icu-src/source/data/cldr-icu-readme.txt +++ b/Build/source/libs/icu/icu-src/source/data/cldr-icu-readme.txt @@ -138,24 +138,52 @@ export ICU4C_DIR=$HOME/icu-myfork/icu4c export ICU4J_ROOT=$HOME/icu-myfork/icu4j export TOOLS_ROOT=$HOME/icu-myfork/tools -# 2. Build and install the CLDR jar +# 1d. Directory for logs/notes (create if does not exist) -cd $TOOLS_ROOT/cldr -ant install-cldr-libs +export NOTES=...(some directory)... +mkdir -p $NOTES -See the $TOOLS_ROOT/cldr/lib/README.txt file for more information on the CLDR -jar and the install-cldr-jars.sh script. - -# 3. Configure ICU4C, build and test without new data first, to verify that +# 2a. Configure ICU4C, build and test without new data first, to verify that # there are no pre-existing errors. Here <platform> is the runConfigureICU # code for the platform you are building, e.g. Linux, MacOSX, Cygwin. +# (optionally build with debug enabled) cd $ICU4C_DIR/source -./runConfigureICU <platform> +./runConfigureICU [--enable-debug] <platform> make clean -make check 2>&1 | tee /tmp/icu4c-oldData-makeCheck.txt +make check 2>&1 | tee $NOTES/icu4c-oldData-makeCheck.txt + +# 2b. Now with ICU4J, build and test without new data first, to verify that +# there are no pre-existing errors (or at least to have the pre-existing errors +# as a base for comparison): + +cd $ICU4J_ROOT +ant clean +ant check 2>&1 | tee $NOTES/icu4j-oldData-antCheck.txt + +# 3. Make pre-adjustments as necessary +# 3a. Copy latest relevant CLDR dtds to ICU +cp -p $CLDR_DIR/common/dtd/ldml.dtd $ICU4C_DIR/source/data/dtd/cldr/common/dtd/ +cp -p $CLDR_DIR/common/dtd/ldmlICU.dtd $ICU4C_DIR/source/data/dtd/cldr/common/dtd/ + +# 3b. Update the cldr-icu tooling to use the latest tagged version of ICU +open $TOOLS_ROOT/cldr/cldr-to-icu/pom.xml +# search for icu4j-for-cldr and update to the latest tagged version per instructions + +# 3c. Update the build for any new icu version, added locales, etc. +open $TOOLS_ROOT/cldr/cldr-to-icu/build-icu-data.xml +# update icuVersion, icuDataVersion if necessary +# update lists of locales to include if necessary + +# 4. Build and install the CLDR jar -# 4a. Generate the CLDR production data. This process uses ant with ICU's +cd $TOOLS_ROOT/cldr +ant install-cldr-libs + +See the $TOOLS_ROOT/cldr/lib/README.txt file for more information on the CLDR +jar and the install-cldr-jars.sh script. + +# 5a. Generate the CLDR production data. This process uses ant with ICU's # data/build.xml # # Running "ant cleanprod" is necessary to clean out the production data directory @@ -167,9 +195,9 @@ make check 2>&1 | tee /tmp/icu4c-oldData-makeCheck.txt cd $ICU4C_DIR/source/data ant cleanprod ant setup -ant proddata 2>&1 | tee /tmp/cldr-newData-proddataLog.txt +ant proddata 2>&1 | tee $NOTES/cldr-newData-proddataLog.txt -# 4b. Build the new ICU4C data files; these include .txt files and .py files. +# 5b. Build the new ICU4C data files; these include .txt files and .py files. # These new files will replace whatever was already present in the ICU4C sources. # This process uses the LdmlConverter in $TOOLS_ROOT/cldr/cldr-to-icu/; # see $TOOLS_ROOT/cldr/cldr-to-icu/README.txt @@ -187,59 +215,58 @@ ant proddata 2>&1 | tee /tmp/cldr-newData-proddataLog.txt # build-icu-data.xml file, such as adding new locales etc. cd $TOOLS_ROOT/cldr/cldr-to-icu -ant -f build-icu-data.xml -DcldrDataDir="$CLDR_TMP_DIR/production" | tee /tmp/cldr-newData-builddataLog.txt +ant -f build-icu-data.xml -DcldrDataDir="$CLDR_TMP_DIR/production" | tee $NOTES/cldr-newData-builddataLog.txt -# 4c. Update the CLDR testData files needed by ICU4C and ICU4J tests, ensuring +# 5c. Update the CLDR testData files needed by ICU4C and ICU4J tests, ensuring # they're representative of the newest CLDR data. cd $TOOLS_ROOT/cldr ant copy-cldr-testdata -# 4d. Copy from CLDR common/testData/localeIdentifiers/localeCanonicalization.txt +# 5d. Copy from CLDR common/testData/localeIdentifiers/localeCanonicalization.txt # into icu4c/source/test/testdata/localeCanonicalization.txt # and icu4j/main/tests/core/src/com/ibm/icu/dev/data/unicode/localeCanonicalization.txt # and add the following line to the beginning of these two files # # File copied from cldr common/testData/localeIdentifiers/localeCanonicalization.txt -# 4e. For the time being, manually re-add the lstm entries in data/brkitr/root.txt - +# 5e. For the time being, manually re-add the lstm entries in data/brkitr/root.txt open $ICU4C_DIR/source/data/brkitr/root.txt -# paste the following block at the end, after the dictionaries block> +# paste the following block after the dictionaries block and before the final closing '}': lstm{ Thai{"Thai_graphclust_model4_heavy.res"} Mymr{"Burmese_graphclust_model5_heavy.res"} } -# 5. Check which data files have modifications, which have been added or removed +# 6. Check which data files have modifications, which have been added or removed # (if there are no changes, you may not need to proceed further). Make sure the # list seems reasonable. -cd $ICU4C_DIR/source/data +cd $ICU4C_DIR/.. git status -# 5a. You may also want to check which files were modified in CLDR production data: +# 6a. You may also want to check which files were modified in CLDR production data: cd $CLDR_TMP_DIR git status -# 6. Fix any errors, investigate any warnings. +# 7. Fix any errors, investigate any warnings. # # Fixing may entail modifying CLDR source data or TOOLS_ROOT config files or # tooling. -# 7. Now rebuild ICU4C with the new data and run make check tests. +# 8. Now rebuild ICU4C with the new data and run make check tests. # Again, keep a log so you can investigate the errors. cd $ICU4C_DIR/source -# 7a. If any files were added or removed (likely), re-run configure: -./runConfigureICU <platform> +# 8a. If any files were added or removed (likely), re-run configure: +./runConfigureICU [--enable-debug] <platform> make clean -# 7b. Now do the rebuild. -make check 2>&1 | tee /tmp/icu4c-newData-makeCheck.txt +# 8b. Now do the rebuild. +make check 2>&1 | tee $NOTES/icu4c-newData-makeCheck.txt -# 8. Investigate each test case failure. The first run processing new CLDR data +# 9. Investigate each test case failure. The first run processing new CLDR data # from the Survey Tool can result in thousands of failures (in many cases, one # CLDR data fix can resolve hundreds of test failures). If the error is caused # by bad CLDR data, then file a CLDR bug, fix the data, and regenerate from @@ -249,9 +276,9 @@ make check 2>&1 | tee /tmp/icu4c-newData-makeCheck.txt # Note that if the new data has any differences in structure, you will have to # update test/testdata/structLocale.txt or /tsutil/cldrtest/TestLocaleStructure # may fail. -# Repeat steps 4-7 until there are no errors. +# Repeat steps 4-8 until there are no errors. -# 9. You can also run the make check tests in exhaustive mode. As an alternative +# 10. You can also run the make check tests in exhaustive mode. As an alternative # you can run them as part of the pre-merge tests by adding the following as a # comment in the pull request: "/azp run CI-Exhaustive". You should do one or the # other; the exhaustive tests are *not* run automatically on each pull request, @@ -260,17 +287,10 @@ make check 2>&1 | tee /tmp/icu4c-newData-makeCheck.txt cd $ICU4C_DIR/source export INTLTEST_OPTS="-e" export CINTLTST_OPTS="-e" -make check 2>&1 | tee /tmp/icu4c-newData-makeCheckEx.txt - -# 10. Again, investigate each failure, fixing CLDR data or ICU test cases as -# appropriate, and repeating steps 4-7 and 9 until there are no errors. - -# 11. Now with ICU4J, build and test without new data first, to verify that -# there are no pre-existing errors (or at least to have the pre-existing errors -# as a base for comparison): +make check 2>&1 | tee $NOTES/icu4c-newData-makeCheckEx.txt -cd $ICU4J_ROOT -ant check 2>&1 | tee /tmp/icu4j-oldData-antCheck.txt +# 11. Again, investigate each failure, fixing CLDR data or ICU test cases as +# appropriate, and repeating steps 4-8 and 10 until there are no errors. # 12. Transfer the data to ICU4J: cd $ICU4C_DIR/source @@ -291,7 +311,7 @@ make icu4j-data-install # Keep a log so you can investigate the errors. cd $ICU4J_ROOT -ant check 2>&1 | tee /tmp/icu4j-newData-antCheck.txt +ant check 2>&1 | tee $NOTES/icu4j-newData-antCheck.txt # 14. Investigate test case failures; fix test cases and repeat from step 12, # or fix CLDR data and repeat from step 4, as appropriate, until there are no diff --git a/Build/source/libs/icu/icu-src/source/data/dtd/cldr/common/dtd/ldml.dtd b/Build/source/libs/icu/icu-src/source/data/dtd/cldr/common/dtd/ldml.dtd new file mode 100644 index 00000000000..c59fead460b --- /dev/null +++ b/Build/source/libs/icu/icu-src/source/data/dtd/cldr/common/dtd/ldml.dtd @@ -0,0 +1,3208 @@ +<!-- +Copyright © 1991-2022 Unicode, Inc. +For terms of use, see http://www.unicode.org/copyright.html +SPDX-License-Identifier: Unicode-DFS-2016 +CLDR data files are interpreted according to the LDML specification (http://unicode.org/reports/tr35/) +--> + +<!ELEMENT ldml ( identity, ( alias | ( fallback*, localeDisplayNames?, layout?, contextTransforms?, characters?, delimiters?, measurement?, dates?, numbers?, units?, listPatterns?, collations?, posix?, characterLabels?, segmentations?, rbnf?, typographicNames?, annotations?, metadata?, references?, special* ) ) ) > +<!ATTLIST ldml version CDATA #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST ldml draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> + +<!-- ######################################################### --> + +<!ELEMENT identity ( alias | ( version, generation?, language, script?, territory?, variant?, special* ) ) > +<!ATTLIST identity draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> + +<!-- ######################################################### --> +<!-- # These elements are common to almost all elements defined --> + +<!ELEMENT alias ( special* ) > +<!ATTLIST alias source NMTOKEN #REQUIRED > + <!--@MATCH:literal/locale--> + <!--@VALUE--> +<!ATTLIST alias path CDATA #IMPLIED > + <!--@MATCH:regex/\.\..*--> + <!--@VALUE--> +<!ATTLIST alias alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST alias draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> + +<!ELEMENT special ANY > + +<!ELEMENT version EMPTY > +<!ATTLIST version number CDATA #REQUIRED > + <!--@MATCH:regex/\$Revision.*\$--> + <!--@METADATA--> +<!ATTLIST version cldrVersion CDATA #FIXED "41" > + <!--@MATCH:any--> + <!--@VALUE--> +<!ATTLIST version draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> + +<!ELEMENT generation EMPTY > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST generation date CDATA #REQUIRED > + <!--@VALUE--> + <!--@DEPRECATED--> +<!ATTLIST generation draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> + +<!ELEMENT language ( #PCDATA ) > +<!ATTLIST language type NMTOKEN #REQUIRED > + <!--@MATCH:validity/locale--> +<!ATTLIST language alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/long, secondary, short, variant, menu--> +<!ATTLIST language draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED:true, false--> +<!ATTLIST language references CDATA #IMPLIED > + <!--@METADATA--> + +<!ELEMENT script ( #PCDATA ) > +<!ATTLIST script type NMTOKEN #REQUIRED > + <!--@MATCH:validity/script--> +<!ATTLIST script alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/secondary, short, stand-alone, variant--> +<!ATTLIST script draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED:true, false--> +<!ATTLIST script references CDATA #IMPLIED > + <!--@METADATA--> + +<!ELEMENT territory ( #PCDATA ) > +<!ATTLIST territory type NMTOKEN #REQUIRED > + <!--@MATCH:validity/region--> +<!ATTLIST territory alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/short, variant--> +<!ATTLIST territory draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED:true, false--> +<!ATTLIST territory references CDATA #IMPLIED > + <!--@METADATA--> + +<!ELEMENT variant ( #PCDATA ) > +<!ATTLIST variant type NMTOKEN #REQUIRED > + <!--@MATCH:validity/variant--> +<!ATTLIST variant alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/secondary, variant--> +<!ATTLIST variant draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED:true, false--> +<!ATTLIST variant references CDATA #IMPLIED > + <!--@METADATA--> + +<!-- ######################################################### --> + +<!ELEMENT fallback ( #PCDATA ) > + <!--@DEPRECATED--> +<!ATTLIST fallback alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> + <!--@DEPRECATED--> +<!ATTLIST fallback draft (approved | contributed | provisional | unconfirmed) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST fallback references CDATA #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> + +<!ELEMENT localeDisplayNames ( alias | ( localeDisplayPattern?, languages?, scripts?, territories?, subdivisions?, variants?, keys?, types?, transformNames?, measurementSystemNames?, codePatterns?, special* ) ) > +<!ATTLIST localeDisplayNames draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> + +<!ELEMENT localeDisplayPattern ( alias | ( localePattern*, localeSeparator*, localeKeyTypePattern*, special* ) ) > +<!ATTLIST localeDisplayPattern alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST localeDisplayPattern draft (approved | contributed | provisional | unconfirmed) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST localeDisplayPattern references CDATA #IMPLIED > + <!--@METADATA--> + +<!ELEMENT localePattern ( #PCDATA ) > +<!ATTLIST localePattern alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST localePattern draft (approved | contributed | provisional | unconfirmed) #IMPLIED > + <!--@METADATA--> +<!ATTLIST localePattern references CDATA #IMPLIED > + <!--@METADATA--> + +<!ELEMENT localeSeparator ( #PCDATA ) > +<!ATTLIST localeSeparator alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST localeSeparator draft (approved | contributed | provisional | unconfirmed) #IMPLIED > + <!--@METADATA--> +<!ATTLIST localeSeparator references CDATA #IMPLIED > + <!--@METADATA--> + +<!ELEMENT localeKeyTypePattern ( #PCDATA ) > +<!ATTLIST localeKeyTypePattern alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST localeKeyTypePattern draft (approved | contributed | provisional | unconfirmed) #IMPLIED > + <!--@METADATA--> +<!ATTLIST localeKeyTypePattern references CDATA #IMPLIED > + <!--@METADATA--> + +<!-- # Either 1 alias OR any specials, any order, zero or more language --> + +<!ELEMENT languages ( alias | ( language | special )* ) > +<!ATTLIST languages draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST languages standard CDATA #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST languages references CDATA #IMPLIED > + <!--@METADATA--> +<!ATTLIST languages validSubLocales CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> + +<!-- # Either 1 alias OR any specials, any order, zero or more script --> + +<!ELEMENT scripts ( alias | ( script | special )* ) > +<!ATTLIST scripts draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST scripts standard CDATA #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST scripts references CDATA #IMPLIED > + <!--@METADATA--> +<!ATTLIST scripts validSubLocales CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> + +<!-- # Either 1 alias OR any specials, any order, zero or more territory --> + +<!ELEMENT territories ( alias | ( territory | special )* ) > +<!ATTLIST territories draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST territories standard CDATA #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST territories references CDATA #IMPLIED > + <!--@METADATA--> +<!ATTLIST territories validSubLocales CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> + +<!ELEMENT subdivisions ( alias | ( subdivision | special )* ) > +<!ATTLIST subdivisions draft (approved | contributed | provisional | unconfirmed) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST subdivisions references CDATA #IMPLIED > + <!--@METADATA--> + +<!ELEMENT subdivision ( #PCDATA ) > +<!ATTLIST subdivision type NMTOKEN #REQUIRED > + <!--@MATCH:or/validity/subdivision||literal/AS, AW, AX, BL, CP, CW, GF, GP, GU, HK, IC, MF, MO, MP, MQ, NC, PF, PM, PR, RE, SX, TA, TF, TW, UM, VI, WF, YT, itsd, no50--> +<!ATTLIST subdivision alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST subdivision draft (approved | contributed | provisional | unconfirmed) #IMPLIED > + <!--@METADATA--> + +<!-- # Either 1 alias OR any specials, any order, zero or more variant --> + +<!ELEMENT variants ( alias | ( variant | special )* ) > +<!ATTLIST variants draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST variants standard CDATA #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST variants references CDATA #IMPLIED > + <!--@METADATA--> +<!ATTLIST variants validSubLocales CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> + +<!-- # Either 1 alias OR any specials, any order, zero or more key --> + +<!ELEMENT keys ( alias | ( key | special )* ) > +<!ATTLIST keys draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST keys standard CDATA #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST keys references CDATA #IMPLIED > + <!--@METADATA--> +<!ATTLIST keys validSubLocales CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> + +<!ELEMENT key ( #PCDATA ) > +<!ATTLIST key type NMTOKEN #REQUIRED > + <!--@MATCH:or/bcp47/anykey||literal/t--> +<!ATTLIST key alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST key draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED:true, false--> +<!ATTLIST key references CDATA #IMPLIED > + <!--@METADATA--> + +<!-- # Either 1 alias OR any specials, any order, zero or more type --> + +<!ELEMENT types ( alias | ( type | special )* ) > +<!ATTLIST types draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST types standard CDATA #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST types references CDATA #IMPLIED > + <!--@METADATA--> +<!ATTLIST types validSubLocales CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> + +<!ELEMENT type ( #PCDATA ) > +<!ATTLIST type key NMTOKEN #REQUIRED > + <!--@MATCH:bcp47/anykey--> +<!ATTLIST type type NMTOKEN #REQUIRED > + <!--@MATCH:bcp47/anyvalue--> +<!ATTLIST type alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/short, variant--> +<!ATTLIST type draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED:true, false--> +<!ATTLIST type references CDATA #IMPLIED > + <!--@METADATA--> + +<!ELEMENT transformNames ( alias | ( transformName | special )* ) > + <!--@DEPRECATED--> +<!ATTLIST transformNames draft (approved | contributed | provisional | unconfirmed) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST transformNames references CDATA #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> + +<!ELEMENT transformName ( #PCDATA ) > + <!--@DEPRECATED--> +<!ATTLIST transformName type NMTOKEN #REQUIRED > + <!--@DEPRECATED--> +<!ATTLIST transformName alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> + <!--@DEPRECATED--> +<!ATTLIST transformName draft (approved | contributed | provisional | unconfirmed) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST transformName references CDATA #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> + +<!-- # Either 1 alias OR any specials, any order, zero or more measurementSystemName --> + +<!ELEMENT measurementSystemNames ( alias | ( measurementSystemName | special )* ) > +<!ATTLIST measurementSystemNames draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST measurementSystemNames references CDATA #IMPLIED > + <!--@METADATA--> +<!ATTLIST measurementSystemNames validSubLocales CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> + +<!ELEMENT measurementSystemName ( #PCDATA ) > +<!ATTLIST measurementSystemName type (US | metric | UK) #REQUIRED > +<!ATTLIST measurementSystemName alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST measurementSystemName draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED:true, false--> +<!ATTLIST measurementSystemName references CDATA #IMPLIED > + <!--@METADATA--> + +<!ELEMENT codePatterns ( alias | ( codePattern | special )* ) > + +<!ELEMENT codePattern ( #PCDATA ) > +<!ATTLIST codePattern type NMTOKEN #REQUIRED > + <!--@MATCH:literal/language, script, territory--> +<!ATTLIST codePattern alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST codePattern draft (approved | contributed | provisional | unconfirmed) #IMPLIED > + <!--@METADATA--> +<!ATTLIST codePattern references CDATA #IMPLIED > + <!--@METADATA--> + +<!-- ######################################################### --> +<!-- # layout and orientation are script specific, so validSublocales attribute is not required --> + +<!ELEMENT layout ( alias | ( orientation*, inList*, inText*, special* ) ) > +<!ATTLIST layout draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST layout references CDATA #IMPLIED > + <!--@METADATA--> + +<!ELEMENT orientation ( alias | ( characterOrder*, lineOrder*, special* ) ) > +<!ATTLIST orientation characters (left-to-right | right-to-left | top-to-bottom | bottom-to-top) #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> +<!ATTLIST orientation lines (left-to-right | right-to-left | top-to-bottom | bottom-to-top) #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> +<!ATTLIST orientation alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST orientation draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST orientation standard CDATA #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST orientation references CDATA #IMPLIED > + <!--@METADATA--> + +<!ELEMENT characterOrder ( #PCDATA ) > +<!ATTLIST characterOrder alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST characterOrder draft (approved | contributed | provisional | unconfirmed) #IMPLIED > + <!--@METADATA--> + +<!ELEMENT lineOrder ( #PCDATA ) > +<!ATTLIST lineOrder alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST lineOrder draft (approved | contributed | provisional | unconfirmed) #IMPLIED > + <!--@METADATA--> + +<!ELEMENT inList ( #PCDATA ) > + <!--@DEPRECATED--> +<!ATTLIST inList casing (titlecase-words | titlecase-firstword | lowercase-words | mixed) #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> +<!ATTLIST inList alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> + <!--@DEPRECATED--> +<!ATTLIST inList draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST inList references CDATA #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> + +<!ELEMENT inText ( #PCDATA ) > + <!--@DEPRECATED--> +<!ATTLIST inText type (languages | scripts | territories | variants | keys | types | measurementSystemNames | monthWidth | dayWidth | quarterWidth | long | fields | currency) #IMPLIED > + <!--@DEPRECATED--> +<!ATTLIST inText alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> + <!--@DEPRECATED--> +<!ATTLIST inText draft (approved | contributed | provisional | unconfirmed) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST inText references CDATA #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> + +<!-- ######################################################### --> + +<!ELEMENT contextTransforms ( alias | ( contextTransformUsage*, special* ) ) > +<!ATTLIST contextTransforms alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST contextTransforms draft (approved | contributed | provisional | unconfirmed) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST contextTransforms references CDATA #IMPLIED > + <!--@METADATA--> +<!ATTLIST contextTransforms validSubLocales CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> + +<!ELEMENT contextTransformUsage ( alias | ( contextTransform*, special* ) ) > +<!ATTLIST contextTransformUsage type CDATA #REQUIRED > + <!--@MATCH:literal/calendar-field, currencyName, day-format-except-narrow, day-standalone-except-narrow, era-abbr, era-name, keyValue, languages, month-format-except-narrow, month-standalone-except-narrow, number-spellout, relative, script, typographicNames--> +<!ATTLIST contextTransformUsage alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST contextTransformUsage draft (approved | contributed | provisional | unconfirmed) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST contextTransformUsage references CDATA #IMPLIED > + <!--@METADATA--> +<!ATTLIST contextTransformUsage validSubLocales CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> + +<!ELEMENT contextTransform ( #PCDATA ) > +<!ATTLIST contextTransform type (uiListOrMenu | stand-alone) #REQUIRED > +<!ATTLIST contextTransform alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST contextTransform draft (approved | contributed | provisional | unconfirmed) #IMPLIED > + <!--@METADATA--> +<!ATTLIST contextTransform references CDATA #IMPLIED > + <!--@METADATA--> + +<!-- ######################################################### --> + +<!ELEMENT characters ( alias | ( exemplarCharacters*, ellipsis*, moreInformation*, stopwords*, indexLabels*, mapping*, parseLenients*, special* ) ) > +<!ATTLIST characters draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> + +<!ELEMENT exemplarCharacters ( #PCDATA | cp )* > +<!ATTLIST exemplarCharacters type (auxiliary | standard | punctuation | currencySymbol | index | numbers) #IMPLIED > + <!--@DEPRECATED:currencySymbol--> +<!ATTLIST exemplarCharacters alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST exemplarCharacters draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> +<!ATTLIST exemplarCharacters standard CDATA #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST exemplarCharacters references CDATA #IMPLIED > + <!--@METADATA--> +<!ATTLIST exemplarCharacters validSubLocales CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> + +<!-- # This element can occur anywhere there may be localizable data --> + +<!ELEMENT cp ( special* ) > + <!--@DEPRECATED--> +<!ATTLIST cp hex NMTOKEN #REQUIRED > + <!--@VALUE--> + <!--@DEPRECATED--> + +<!ELEMENT ellipsis ( #PCDATA ) > +<!ATTLIST ellipsis type (initial | medial | final | word-initial | word-medial | word-final) #REQUIRED > +<!ATTLIST ellipsis alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST ellipsis draft (approved | contributed | provisional | unconfirmed) #IMPLIED > + <!--@METADATA--> +<!ATTLIST ellipsis references CDATA #IMPLIED > + <!--@METADATA--> + +<!ELEMENT moreInformation ( #PCDATA ) > +<!ATTLIST moreInformation alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST moreInformation draft (approved | contributed | provisional | unconfirmed) #IMPLIED > + <!--@METADATA--> +<!ATTLIST moreInformation references CDATA #IMPLIED > + <!--@METADATA--> + +<!ELEMENT stopwords ( stopwordList* ) > + <!--@DEPRECATED--> + +<!ELEMENT stopwordList ( #PCDATA ) > + <!--@DEPRECATED--> +<!ATTLIST stopwordList type NMTOKEN #REQUIRED > + <!--@DEPRECATED--> +<!ATTLIST stopwordList alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> + <!--@DEPRECATED--> +<!ATTLIST stopwordList draft (approved | contributed | provisional | unconfirmed) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST stopwordList references CDATA #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> + +<!ELEMENT indexLabels ( indexSeparator*, compressedIndexSeparator*, indexRangePattern*, indexLabelBefore*, indexLabelAfter*, indexLabel* ) > + <!--@DEPRECATED--> + +<!ELEMENT indexSeparator ( #PCDATA ) > + <!--@DEPRECATED--> +<!ATTLIST indexSeparator alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> + <!--@DEPRECATED--> +<!ATTLIST indexSeparator draft (approved | contributed | provisional | unconfirmed) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST indexSeparator references CDATA #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> + +<!ELEMENT compressedIndexSeparator ( #PCDATA ) > + <!--@DEPRECATED--> +<!ATTLIST compressedIndexSeparator alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> + <!--@DEPRECATED--> +<!ATTLIST compressedIndexSeparator draft (approved | contributed | provisional | unconfirmed) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST compressedIndexSeparator references CDATA #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> + +<!ELEMENT indexRangePattern ( #PCDATA ) > + <!--@DEPRECATED--> +<!ATTLIST indexRangePattern alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> + <!--@DEPRECATED--> +<!ATTLIST indexRangePattern draft (approved | contributed | provisional | unconfirmed) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST indexRangePattern references CDATA #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> + +<!ELEMENT indexLabelBefore ( #PCDATA ) > + <!--@DEPRECATED--> +<!ATTLIST indexLabelBefore alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> + <!--@DEPRECATED--> +<!ATTLIST indexLabelBefore draft (approved | contributed | provisional | unconfirmed) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST indexLabelBefore references CDATA #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> + +<!ELEMENT indexLabelAfter ( #PCDATA ) > + <!--@DEPRECATED--> +<!ATTLIST indexLabelAfter alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> + <!--@DEPRECATED--> +<!ATTLIST indexLabelAfter draft (approved | contributed | provisional | unconfirmed) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST indexLabelAfter references CDATA #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> + +<!ELEMENT indexLabel ( #PCDATA ) > + <!--@DEPRECATED--> +<!ATTLIST indexLabel indexSource CDATA #IMPLIED > + <!--@DEPRECATED--> +<!ATTLIST indexLabel priority (1 | 2 | 3) #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> +<!ATTLIST indexLabel alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> + <!--@DEPRECATED--> +<!ATTLIST indexLabel draft (approved | contributed | provisional | unconfirmed) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST indexLabel references CDATA #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> + +<!ELEMENT mapping ( special* ) > + <!--@DEPRECATED--> +<!ATTLIST mapping registry NMTOKEN #REQUIRED > + <!--@DEPRECATED--> +<!ATTLIST mapping type NMTOKEN #IMPLIED > + <!-- use choice instead --> + <!--@VALUE--> + <!--@DEPRECATED--> +<!ATTLIST mapping choice NMTOKEN #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> +<!ATTLIST mapping alt NMTOKENS #IMPLIED > + <!--@DEPRECATED--> +<!ATTLIST mapping draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST mapping standard CDATA #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST mapping references CDATA #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST mapping validSubLocales CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> + +<!ELEMENT parseLenients ( alias | ( parseLenient*, special* ) ) > +<!ATTLIST parseLenients scope (general | number | date) #REQUIRED > +<!ATTLIST parseLenients level (lenient | stricter) #REQUIRED > + +<!ELEMENT parseLenient ( #PCDATA ) > +<!ATTLIST parseLenient sample CDATA #REQUIRED > + <!--@MATCH:any--> +<!ATTLIST parseLenient alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST parseLenient draft (approved | contributed | provisional | unconfirmed) #IMPLIED > + <!--@METADATA--> + +<!-- ######################################################### --> + +<!ELEMENT delimiters ( alias | ( quotationStart*, quotationEnd*, alternateQuotationStart*, alternateQuotationEnd*, special* ) ) > +<!ATTLIST delimiters alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST delimiters draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST delimiters standard CDATA #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST delimiters references CDATA #IMPLIED > + <!--@METADATA--> +<!ATTLIST delimiters validSubLocales CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> + +<!ELEMENT quotationStart ( #PCDATA | cp )* > +<!ATTLIST quotationStart alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST quotationStart draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> +<!ATTLIST quotationStart references CDATA #IMPLIED > + <!--@METADATA--> + +<!ELEMENT quotationEnd ( #PCDATA | cp )* > +<!ATTLIST quotationEnd alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST quotationEnd draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> +<!ATTLIST quotationEnd references CDATA #IMPLIED > + <!--@METADATA--> + +<!ELEMENT alternateQuotationStart ( #PCDATA | cp )* > +<!ATTLIST alternateQuotationStart alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST alternateQuotationStart draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> +<!ATTLIST alternateQuotationStart references CDATA #IMPLIED > + <!--@METADATA--> + +<!ELEMENT alternateQuotationEnd ( #PCDATA | cp )* > +<!ATTLIST alternateQuotationEnd alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST alternateQuotationEnd draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> +<!ATTLIST alternateQuotationEnd references CDATA #IMPLIED > + <!--@METADATA--> + +<!-- ######################################################### --> + +<!ELEMENT measurement ( alias | ( measurementSystem*, paperSize*, special* ) ) > + <!-- use measurementData in supplemental instead --> + <!--@DEPRECATED--> +<!ATTLIST measurement alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> + <!--@DEPRECATED--> +<!ATTLIST measurement draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST measurement standard CDATA #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST measurement references CDATA #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST measurement validSubLocales CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> + +<!ELEMENT measurementSystem ( special* ) > + <!-- use measurementSystem in supplemental instead --> + <!--@DEPRECATED--> +<!ATTLIST measurementSystem type (metric | US | UK) #REQUIRED > + <!-- use choice instead --> + <!--@VALUE--> + <!--@DEPRECATED--> +<!ATTLIST measurementSystem choice (metric | US | UK) #IMPLIED > + <!-- really required, but needs to be optional to support type also --> + <!--@VALUE--> + <!--@DEPRECATED--> +<!ATTLIST measurementSystem alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> + <!--@DEPRECATED--> +<!ATTLIST measurementSystem draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST measurementSystem standard CDATA #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST measurementSystem references CDATA #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST measurementSystem validSubLocales CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> + +<!ELEMENT paperSize ( alias | ( height*, width*, special* ) ) > + <!-- use paperSize in supplemental instead --> + <!--@DEPRECATED--> +<!ATTLIST paperSize alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> + <!--@DEPRECATED--> +<!ATTLIST paperSize draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST paperSize standard CDATA #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST paperSize references CDATA #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST paperSize validSubLocales CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> + +<!ELEMENT height ( #PCDATA ) > + <!--@DEPRECATED--> +<!ATTLIST height alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> + <!--@DEPRECATED--> +<!ATTLIST height draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST height references CDATA #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> + +<!ELEMENT width ( #PCDATA ) > + <!--@DEPRECATED--> +<!ATTLIST width alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> + <!--@DEPRECATED--> +<!ATTLIST width draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST width references CDATA #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> + +<!-- ######################################################### --> + +<!ELEMENT dates ( alias | ( localizedPatternChars*, dateRangePattern*, calendars?, fields?, timeZoneNames?, special* ) ) > +<!ATTLIST dates alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST dates draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST dates standard CDATA #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST dates references CDATA #IMPLIED > + <!--@METADATA--> +<!ATTLIST dates validSubLocales CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> + +<!ELEMENT localizedPatternChars ( #PCDATA | cp )* > + <!--@DEPRECATED--> +<!ATTLIST localizedPatternChars alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> + <!--@DEPRECATED--> +<!ATTLIST localizedPatternChars draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST localizedPatternChars standard CDATA #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST localizedPatternChars references CDATA #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST localizedPatternChars validSubLocales CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> + +<!ELEMENT dateRangePattern ( #PCDATA ) > + <!-- use intervalFormats. --> + <!--@DEPRECATED--> +<!ATTLIST dateRangePattern alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> + <!--@DEPRECATED--> +<!ATTLIST dateRangePattern draft (approved | contributed | provisional | unconfirmed) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST dateRangePattern standard CDATA #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST dateRangePattern references CDATA #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST dateRangePattern validSubLocales CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> + +<!ELEMENT calendars ( alias | ( default*, calendar*, special* ) ) > + <!-- use calendarPreferenceData instead of default element --> +<!ATTLIST calendars draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST calendars validSubLocales CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> + +<!ELEMENT default ( special* ) > + <!--@DEPRECATED--> +<!ATTLIST default type NMTOKEN #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> +<!ATTLIST default choice NMTOKEN #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> +<!ATTLIST default alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> + <!--@DEPRECATED--> +<!ATTLIST default draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST default references CDATA #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> + +<!ELEMENT calendar ( alias | ( months?, monthNames?, monthAbbr?, monthPatterns?, days?, dayNames?, dayAbbr?, quarters?, week?, am*, pm*, dayPeriods?, eras?, cyclicNameSets?, dateFormats?, timeFormats?, dateTimeFormats?, fields*, special* ) ) > + <!-- use of fields is deprecated here --> +<!ATTLIST calendar type NMTOKEN #REQUIRED > + <!--@MATCH:bcp47/ca--> +<!ATTLIST calendar alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST calendar draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST calendar standard CDATA #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST calendar references CDATA #IMPLIED > + <!--@METADATA--> +<!ATTLIST calendar validSubLocales CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> + +<!ELEMENT months ( alias | ( default*, monthContext*, special* ) ) > +<!ATTLIST months alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST months draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST months standard CDATA #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST months references CDATA #IMPLIED > + <!--@METADATA--> +<!ATTLIST months validSubLocales CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> + +<!ELEMENT monthContext ( alias | ( default*, monthWidth*, special* ) ) > +<!ATTLIST monthContext type (format | stand-alone) #REQUIRED > +<!ATTLIST monthContext alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST monthContext draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST monthContext standard CDATA #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST monthContext references CDATA #IMPLIED > + <!--@METADATA--> +<!ATTLIST monthContext validSubLocales CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> + +<!ELEMENT monthWidth ( alias | ( month*, special* ) ) > +<!ATTLIST monthWidth type (abbreviated | narrow | wide) #REQUIRED > +<!ATTLIST monthWidth alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST monthWidth draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST monthWidth standard CDATA #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST monthWidth references CDATA #IMPLIED > + <!--@METADATA--> +<!ATTLIST monthWidth validSubLocales CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> + +<!ELEMENT month ( #PCDATA | cp )* > +<!ATTLIST month type (1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13) #REQUIRED > +<!ATTLIST month yeartype (standard | leap) #IMPLIED > +<!ATTLIST month alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST month draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> +<!ATTLIST month references CDATA #IMPLIED > + <!--@METADATA--> + +<!ELEMENT monthNames ( alias | ( month*, special* ) ) > + <!--@DEPRECATED--> +<!ATTLIST monthNames draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> + +<!ELEMENT monthAbbr ( alias | ( month*, special* ) ) > + <!--@DEPRECATED--> +<!ATTLIST monthAbbr draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> + +<!ELEMENT monthPatterns ( alias | ( monthPatternContext*, special* ) ) > +<!ATTLIST monthPatterns alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST monthPatterns draft (approved | contributed | provisional | unconfirmed) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST monthPatterns references CDATA #IMPLIED > + <!--@METADATA--> +<!ATTLIST monthPatterns validSubLocales CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> + +<!ELEMENT monthPatternContext ( alias | ( monthPatternWidth*, special* ) ) > +<!ATTLIST monthPatternContext type (format | stand-alone | numeric) #REQUIRED > +<!ATTLIST monthPatternContext alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST monthPatternContext draft (approved | contributed | provisional | unconfirmed) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST monthPatternContext references CDATA #IMPLIED > + <!--@METADATA--> +<!ATTLIST monthPatternContext validSubLocales CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> + +<!ELEMENT monthPatternWidth ( alias | ( monthPattern*, special* ) ) > +<!ATTLIST monthPatternWidth type (abbreviated | narrow | wide | all) #REQUIRED > +<!ATTLIST monthPatternWidth alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST monthPatternWidth draft (approved | contributed | provisional | unconfirmed) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST monthPatternWidth references CDATA #IMPLIED > + <!--@METADATA--> +<!ATTLIST monthPatternWidth validSubLocales CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> + +<!ELEMENT monthPattern ( #PCDATA ) > +<!ATTLIST monthPattern type (leap | standardAfterLeap | combined) #REQUIRED > +<!ATTLIST monthPattern alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST monthPattern draft (approved | contributed | provisional | unconfirmed) #IMPLIED > + <!--@METADATA--> +<!ATTLIST monthPattern references CDATA #IMPLIED > + <!--@METADATA--> + +<!ELEMENT days ( alias | ( default*, dayContext*, special* ) ) > +<!ATTLIST days alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST days draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST days standard CDATA #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST days references CDATA #IMPLIED > + <!--@METADATA--> +<!ATTLIST days validSubLocales CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> + +<!ELEMENT dayContext ( alias | ( default*, dayWidth*, special* ) ) > +<!ATTLIST dayContext type (format | stand-alone) #REQUIRED > +<!ATTLIST dayContext alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST dayContext draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST dayContext standard CDATA #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST dayContext references CDATA #IMPLIED > + <!--@METADATA--> +<!ATTLIST dayContext validSubLocales CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> + +<!ELEMENT dayWidth ( alias | ( day*, special* ) ) > +<!ATTLIST dayWidth type (abbreviated | narrow | short | wide) #REQUIRED > +<!ATTLIST dayWidth alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST dayWidth draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST dayWidth standard CDATA #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST dayWidth references CDATA #IMPLIED > + <!--@METADATA--> +<!ATTLIST dayWidth validSubLocales CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> + +<!ELEMENT day ( #PCDATA ) > +<!ATTLIST day type (sun | mon | tue | wed | thu | fri | sat) #REQUIRED > +<!ATTLIST day alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST day draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED:true, false--> +<!ATTLIST day references CDATA #IMPLIED > + <!--@METADATA--> + +<!ELEMENT dayNames ( alias | ( day*, special* ) ) > + <!--@DEPRECATED--> +<!ATTLIST dayNames draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> + +<!ELEMENT dayAbbr ( alias | ( day*, special* ) ) > + <!--@DEPRECATED--> +<!ATTLIST dayAbbr draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> + +<!ELEMENT quarters ( alias | ( default*, quarterContext*, special* ) ) > +<!ATTLIST quarters alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST quarters draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST quarters references CDATA #IMPLIED > + <!--@METADATA--> +<!ATTLIST quarters validSubLocales CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> + +<!ELEMENT quarterContext ( alias | ( default*, quarterWidth*, special* ) ) > +<!ATTLIST quarterContext type (format | stand-alone) #REQUIRED > +<!ATTLIST quarterContext alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST quarterContext draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST quarterContext references CDATA #IMPLIED > + <!--@METADATA--> +<!ATTLIST quarterContext validSubLocales CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> + +<!ELEMENT quarterWidth ( alias | ( quarter*, special* ) ) > +<!ATTLIST quarterWidth type (abbreviated | narrow | wide) #REQUIRED > +<!ATTLIST quarterWidth alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST quarterWidth draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST quarterWidth references CDATA #IMPLIED > + <!--@METADATA--> +<!ATTLIST quarterWidth validSubLocales CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> + +<!ELEMENT quarter ( #PCDATA ) > +<!ATTLIST quarter type (1 | 2 | 3 | 4) #REQUIRED > +<!ATTLIST quarter alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST quarter draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED:true, false--> +<!ATTLIST quarter references CDATA #IMPLIED > + <!--@METADATA--> + +<!ELEMENT week ( alias | ( minDays*, firstDay*, weekendStart*, weekendEnd*, special* ) ) > + <!-- use supplemental weekData --> + <!--@DEPRECATED--> +<!ATTLIST week alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> + <!--@DEPRECATED--> +<!ATTLIST week draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST week standard CDATA #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST week references CDATA #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST week validSubLocales CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> + +<!ELEMENT minDays ( special* ) > + <!--@DEPRECATED--> +<!ATTLIST minDays count (1 | 2 | 3 | 4 | 5 | 6 | 7) #REQUIRED > + <!--@DEPRECATED--> +<!ATTLIST minDays alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> + <!--@DEPRECATED--> +<!ATTLIST minDays draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST minDays references CDATA #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> + +<!ELEMENT firstDay ( special* ) > + <!-- use supplemental data --> + <!--@DEPRECATED--> +<!ATTLIST firstDay day (sun | mon | tue | wed | thu | fri | sat) #REQUIRED > + <!--@VALUE--> + <!--@DEPRECATED--> +<!ATTLIST firstDay alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> + <!--@DEPRECATED--> +<!ATTLIST firstDay draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST firstDay references CDATA #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> + +<!ELEMENT weekendStart ( special* ) > + <!-- use supplemental data --> + <!--@DEPRECATED--> +<!ATTLIST weekendStart day (sun | mon | tue | wed | thu | fri | sat) #REQUIRED > + <!--@VALUE--> + <!--@DEPRECATED--> +<!ATTLIST weekendStart time CDATA "00:00" > + <!--@VALUE--> + <!--@DEPRECATED--> +<!ATTLIST weekendStart alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> + <!--@DEPRECATED--> +<!ATTLIST weekendStart draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST weekendStart references CDATA #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> + +<!ELEMENT weekendEnd ( special* ) > + <!-- use supplemental data --> + <!--@DEPRECATED--> +<!ATTLIST weekendEnd day (sun | mon | tue | wed | thu | fri | sat) #REQUIRED > + <!--@VALUE--> + <!--@DEPRECATED--> +<!ATTLIST weekendEnd time CDATA "24:00" > + <!--@VALUE--> + <!--@DEPRECATED--> +<!ATTLIST weekendEnd alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> + <!--@DEPRECATED--> +<!ATTLIST weekendEnd draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST weekendEnd references CDATA #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> + +<!ELEMENT am ( #PCDATA ) > + <!-- use dayPeriods --> + <!--@DEPRECATED--> +<!ATTLIST am alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> + <!--@DEPRECATED--> +<!ATTLIST am draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST am references CDATA #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST am validSubLocales CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> + +<!ELEMENT pm ( #PCDATA ) > + <!-- use dayPeriods --> + <!--@DEPRECATED--> +<!ATTLIST pm alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> + <!--@DEPRECATED--> +<!ATTLIST pm draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST pm references CDATA #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST pm validSubLocales CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> + +<!ELEMENT dayPeriods ( alias | ( dayPeriodContext*, special* ) ) > +<!ATTLIST dayPeriods draft (approved | contributed | provisional | unconfirmed) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST dayPeriods references CDATA #IMPLIED > + <!--@METADATA--> + +<!ELEMENT dayPeriodContext ( alias | ( dayPeriodWidth*, special* ) ) > +<!ATTLIST dayPeriodContext type NMTOKEN #REQUIRED > + <!--@MATCH:literal/format, stand-alone--> +<!ATTLIST dayPeriodContext draft (approved | contributed | provisional | unconfirmed) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST dayPeriodContext references CDATA #IMPLIED > + <!--@METADATA--> + +<!ELEMENT dayPeriodWidth ( alias | ( dayPeriod*, special* ) ) > +<!ATTLIST dayPeriodWidth type (abbreviated | narrow | wide) #REQUIRED > +<!ATTLIST dayPeriodWidth draft (approved | contributed | provisional | unconfirmed) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST dayPeriodWidth references CDATA #IMPLIED > + <!--@METADATA--> + +<!ELEMENT dayPeriod ( #PCDATA ) > +<!ATTLIST dayPeriod type NMTOKEN #REQUIRED > + <!--@MATCH:literal/afternoon1, afternoon2, am, evening1, evening2, midnight, morning1, morning2, night1, night2, noon, pm--> +<!ATTLIST dayPeriod alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST dayPeriod draft (approved | contributed | provisional | unconfirmed) #IMPLIED > + <!--@METADATA--> +<!ATTLIST dayPeriod references CDATA #IMPLIED > + <!--@METADATA--> + +<!ELEMENT eras ( alias | ( eraNames?, eraAbbr?, eraNarrow?, special* ) ) > +<!ATTLIST eras alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST eras draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST eras standard CDATA #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST eras references CDATA #IMPLIED > + <!--@METADATA--> +<!ATTLIST eras validSubLocales CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> + +<!ELEMENT eraNames ( alias | ( era*, special* ) ) > +<!ATTLIST eraNames alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST eraNames draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST eraNames references CDATA #IMPLIED > + <!--@METADATA--> +<!ATTLIST eraNames validSubLocales CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> + +<!ELEMENT era ( #PCDATA ) > +<!ATTLIST era type NMTOKEN #REQUIRED > + <!--@MATCH:range/0~237--> +<!ATTLIST era alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST era draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED:true, false--> +<!ATTLIST era references CDATA #IMPLIED > + <!--@METADATA--> + +<!ELEMENT eraAbbr ( alias | ( era*, special* ) ) > +<!ATTLIST eraAbbr alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST eraAbbr draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST eraAbbr references CDATA #IMPLIED > + <!--@METADATA--> +<!ATTLIST eraAbbr validSubLocales CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> + +<!ELEMENT eraNarrow ( alias | ( era*, special* ) ) > +<!ATTLIST eraNarrow alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST eraNarrow draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST eraNarrow references CDATA #IMPLIED > + <!--@METADATA--> +<!ATTLIST eraNarrow validSubLocales CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> + +<!ELEMENT cyclicNameSets ( alias | ( cyclicNameSet*, special* ) ) > +<!ATTLIST cyclicNameSets alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST cyclicNameSets draft (approved | contributed | provisional | unconfirmed) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST cyclicNameSets references CDATA #IMPLIED > + <!--@METADATA--> +<!ATTLIST cyclicNameSets validSubLocales CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> + +<!ELEMENT cyclicNameSet ( alias | ( cyclicNameContext*, special* ) ) > +<!ATTLIST cyclicNameSet type (years | months | days | dayParts | zodiacs | solarTerms) #REQUIRED > +<!ATTLIST cyclicNameSet alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST cyclicNameSet draft (approved | contributed | provisional | unconfirmed) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST cyclicNameSet references CDATA #IMPLIED > + <!--@METADATA--> +<!ATTLIST cyclicNameSet validSubLocales CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> + +<!ELEMENT cyclicNameContext ( alias | ( cyclicNameWidth*, special* ) ) > +<!ATTLIST cyclicNameContext type (format | stand-alone) #REQUIRED > +<!ATTLIST cyclicNameContext alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST cyclicNameContext draft (approved | contributed | provisional | unconfirmed) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST cyclicNameContext references CDATA #IMPLIED > + <!--@METADATA--> +<!ATTLIST cyclicNameContext validSubLocales CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> + +<!ELEMENT cyclicNameWidth ( alias | ( cyclicName*, special* ) ) > +<!ATTLIST cyclicNameWidth type (abbreviated | narrow | wide) #REQUIRED > +<!ATTLIST cyclicNameWidth alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST cyclicNameWidth draft (approved | contributed | provisional | unconfirmed) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST cyclicNameWidth references CDATA #IMPLIED > + <!--@METADATA--> +<!ATTLIST cyclicNameWidth validSubLocales CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> + +<!ELEMENT cyclicName ( #PCDATA ) > +<!ATTLIST cyclicName type NMTOKEN #REQUIRED > + <!--@MATCH:range/1~60--> +<!ATTLIST cyclicName alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST cyclicName draft (approved | contributed | provisional | unconfirmed) #IMPLIED > + <!--@METADATA--> +<!ATTLIST cyclicName references CDATA #IMPLIED > + <!--@METADATA--> + +<!ELEMENT dateFormats ( alias | ( default*, dateFormatLength*, special* ) ) > +<!ATTLIST dateFormats draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST dateFormats validSubLocales CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> + +<!ELEMENT dateFormatLength ( alias | ( default*, dateFormat*, special* ) ) > +<!ATTLIST dateFormatLength type (full | long | medium | short) #REQUIRED > +<!ATTLIST dateFormatLength alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST dateFormatLength draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST dateFormatLength standard CDATA #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST dateFormatLength references CDATA #IMPLIED > + <!--@METADATA--> +<!ATTLIST dateFormatLength validSubLocales CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> + +<!ELEMENT dateFormat ( alias | ( pattern*, datetimeSkeleton*, displayName*, special* ) ) > +<!ATTLIST dateFormat type NMTOKEN "standard" > + <!--@MATCH:literal/standard--> +<!ATTLIST dateFormat alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST dateFormat draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST dateFormat standard CDATA #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST dateFormat references CDATA #IMPLIED > + <!--@METADATA--> +<!ATTLIST dateFormat validSubLocales CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> + +<!ELEMENT pattern ( #PCDATA ) > +<!ATTLIST pattern type NMTOKEN "standard" > + <!--@MATCH:literal/1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000, 10000000000, 100000000000, 1000000000000, 10000000000000, 100000000000000, approximately, atLeast, atMost, range, standard--> +<!ATTLIST pattern numbers CDATA #IMPLIED > + <!-- TODO: generalize this to be any (M=|d=)?<numberSystem> --> + <!--@MATCH:literal/M=romanlow, d=hanidays, hanidec, hebr, y=jpanyear--> + <!--@VALUE--> +<!ATTLIST pattern count (0 | 1 | zero | one | two | few | many | other) #IMPLIED > + <!-- Only used for decimalFormats type="1000..." --> +<!ATTLIST pattern alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST pattern draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED:true, false--> +<!ATTLIST pattern references CDATA #IMPLIED > + <!--@METADATA--> + +<!ELEMENT datetimeSkeleton ( #PCDATA ) > +<!ATTLIST datetimeSkeleton numbers CDATA #IMPLIED > + <!-- TODO: generalize this to be any (M=|d=)?<numberSystem> --> + <!--@MATCH:literal/M=romanlow, d=hanidays, hanidec, hebr, y=jpanyear--> + <!--@VALUE--> +<!ATTLIST datetimeSkeleton alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST datetimeSkeleton draft (approved | contributed | provisional | unconfirmed) #IMPLIED > + <!--@METADATA--> +<!ATTLIST datetimeSkeleton references CDATA #IMPLIED > + <!--@METADATA--> + +<!ELEMENT displayName ( #PCDATA ) > +<!ATTLIST displayName count (0 | 1 | zero | one | two | few | many | other) #IMPLIED > + <!-- only for currencies --> +<!ATTLIST displayName alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST displayName draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED:true, false--> +<!ATTLIST displayName references CDATA #IMPLIED > + <!--@METADATA--> + +<!ELEMENT timeFormats ( alias | ( default*, timeFormatLength*, special* ) ) > +<!ATTLIST timeFormats draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST timeFormats validSubLocales CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> + +<!ELEMENT timeFormatLength ( alias | ( default*, timeFormat*, special* ) ) > +<!ATTLIST timeFormatLength type (full | long | medium | short) #REQUIRED > +<!ATTLIST timeFormatLength alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST timeFormatLength draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST timeFormatLength standard CDATA #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST timeFormatLength references CDATA #IMPLIED > + <!--@METADATA--> +<!ATTLIST timeFormatLength validSubLocales CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> + +<!ELEMENT timeFormat ( alias | ( pattern*, datetimeSkeleton*, displayName*, special* ) ) > +<!ATTLIST timeFormat type NMTOKEN "standard" > + <!--@MATCH:literal/standard--> +<!ATTLIST timeFormat alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST timeFormat draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST timeFormat standard CDATA #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST timeFormat references CDATA #IMPLIED > + <!--@METADATA--> +<!ATTLIST timeFormat validSubLocales CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> + +<!ELEMENT dateTimeFormats ( alias | ( default*, dateTimeFormatLength*, availableFormats*, appendItems*, intervalFormats*, special* ) ) > +<!ATTLIST dateTimeFormats draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST dateTimeFormats validSubLocales CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> + +<!ELEMENT dateTimeFormatLength ( alias | ( default*, dateTimeFormat*, special* ) ) > +<!ATTLIST dateTimeFormatLength type (full | long | medium | short) #IMPLIED > +<!ATTLIST dateTimeFormatLength alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST dateTimeFormatLength draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST dateTimeFormatLength standard CDATA #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST dateTimeFormatLength references CDATA #IMPLIED > + <!--@METADATA--> +<!ATTLIST dateTimeFormatLength validSubLocales CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> + +<!ELEMENT dateTimeFormat ( alias | ( pattern*, displayName*, special* ) ) > +<!ATTLIST dateTimeFormat type NMTOKEN "standard" > + <!--@MATCH:literal/standard--> +<!ATTLIST dateTimeFormat alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST dateTimeFormat draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST dateTimeFormat standard CDATA #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST dateTimeFormat references CDATA #IMPLIED > + <!--@METADATA--> +<!ATTLIST dateTimeFormat validSubLocales CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> + +<!ELEMENT availableFormats ( alias | ( dateFormatItem*, special* ) ) > +<!ATTLIST availableFormats alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST availableFormats draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST availableFormats references CDATA #IMPLIED > + <!--@METADATA--> +<!ATTLIST availableFormats validSubLocales CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> + +<!ELEMENT dateFormatItem ( #PCDATA ) > +<!ATTLIST dateFormatItem id CDATA #REQUIRED > + <!-- TODO rationalize this list --> + <!--@MATCH:literal/Bh, Bhm, Bhms, E, EBhm, EBhms, EEEEd, EHm, EHms, Ed, Ehm, Ehms, Gy, GyM, GyMEEEEd, GyMMM, GyMMMEEEEd, GyMMMEd, GyMMMM, GyMMMMEd, GyMMMMd, GyMMMd, GyMd, H, HHmm, HHmmZ, HHmmss, Hm, HmZ, Hmm, Hms, Hmsv, Hmsvvvv, Hmv, Hmvvvv, M, MEEEEd, MEd, MMM, MMMEEEEd, MMMEd, MMMM, MMMMEEEEd, MMMMEd, MMMMW, MMMMd, MMMMdd, MMMd, MMMdd, MMd, MMdd, Md, Mdd, UM, UMMM, UMMMd, UMd, d, h, hhmm, hhmmss, hm, hms, hmsv, hmsvvvv, hmv, hmvvvv, mmss, ms, y, yM, yMEEEEd, yMEd, yMM, yMMM, yMMMEEEEd, yMMMEd, yMMMM, yMMMMEEEEd, yMMMMEd, yMMMMccccd, yMMMMd, yMMMd, yMMdd, yMd, yQ, yQQQ, yQQQQ, yw, yyyy, yyyyM, yyyyMEEEEd, yyyyMEd, yyyyMM, yyyyMMM, yyyyMMMEEEEd, yyyyMMMEd, yyyyMMMM, yyyyMMMMEd, yyyyMMMMccccd, yyyyMMMMd, yyyyMMMd, yyyyMMdd, yyyyMd, yyyyQQQ, yyyyQQQQ--> +<!ATTLIST dateFormatItem count (zero | one | two | few | many | other) #IMPLIED > +<!ATTLIST dateFormatItem alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST dateFormatItem draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED:true, false--> +<!ATTLIST dateFormatItem references CDATA #IMPLIED > + <!--@METADATA--> + +<!ELEMENT appendItems ( alias | ( appendItem*, special* ) ) > +<!ATTLIST appendItems alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST appendItems draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST appendItems references CDATA #IMPLIED > + <!--@METADATA--> +<!ATTLIST appendItems validSubLocales CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> + +<!ELEMENT appendItem ( #PCDATA ) > +<!ATTLIST appendItem request CDATA #REQUIRED > + <!--@MATCH:literal/Day, Day-Of-Week, Era, Hour, Minute, Month, Quarter, Second, Timezone, Week, Year--> +<!ATTLIST appendItem alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST appendItem draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED:true, false--> +<!ATTLIST appendItem references CDATA #IMPLIED > + <!--@METADATA--> + +<!ELEMENT intervalFormats ( alias | ( intervalFormatFallback*, intervalFormatItem*, special* ) ) > +<!ATTLIST intervalFormats alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST intervalFormats draft (approved | contributed | provisional | unconfirmed) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST intervalFormats references CDATA #IMPLIED > + <!--@METADATA--> +<!ATTLIST intervalFormats validSubLocales CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> + +<!ELEMENT intervalFormatFallback ( #PCDATA ) > +<!ATTLIST intervalFormatFallback alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST intervalFormatFallback draft (approved | contributed | provisional | unconfirmed) #IMPLIED > + <!--@METADATA--> +<!ATTLIST intervalFormatFallback references CDATA #IMPLIED > + <!--@METADATA--> +<!ATTLIST intervalFormatFallback validSubLocales CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> + +<!ELEMENT intervalFormatItem ( alias | ( greatestDifference*, special* ) ) > +<!ATTLIST intervalFormatItem id NMTOKEN #REQUIRED > + <!-- TODO: check to see if this should be minimized --> + <!--@MATCH:literal/Bh, Bhm, Gy, GyM, GyMEd, GyMMM, GyMMMEd, GyMMMd, GyMd, H, Hm, Hmv, Hv, M, MEd, MMM, MMMEEEEd, MMMEd, MMMM, MMMMEd, MMMMd, MMMd, Md, d, h, hm, hmv, hv, y, yM, yMEd, yMMM, yMMMEEEEd, yMMMEd, yMMMM, yMMMMEEEEd, yMMMMEd, yMMMMd, yMMMd, yMd, GGGGGyM, GGGGGyMEd, GGGGGyMd, GyMMMM, GyMMMMEd, GyMMMMd--> +<!ATTLIST intervalFormatItem alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST intervalFormatItem draft (approved | contributed | provisional | unconfirmed) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST intervalFormatItem references CDATA #IMPLIED > + <!--@METADATA--> +<!ATTLIST intervalFormatItem validSubLocales CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> + +<!ELEMENT greatestDifference ( #PCDATA ) > +<!ATTLIST greatestDifference id NMTOKEN #REQUIRED > + <!--@MATCH:literal/B, G, H, M, a, d, h, m, y--> +<!ATTLIST greatestDifference alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST greatestDifference draft (approved | contributed | provisional | unconfirmed) #IMPLIED > + <!--@METADATA--> +<!ATTLIST greatestDifference references CDATA #IMPLIED > + <!--@METADATA--> +<!ATTLIST greatestDifference validSubLocales CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> + +<!ELEMENT fields ( alias | ( field*, special* ) ) > +<!ATTLIST fields alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST fields draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST fields standard CDATA #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST fields references CDATA #IMPLIED > + <!--@METADATA--> +<!ATTLIST fields validSubLocales CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> + +<!ELEMENT field ( alias | ( displayName*, relative*, relativeTime*, relativePeriod*, special* ) ) > +<!ATTLIST field type (era | era-short | era-narrow | year | year-short | year-narrow | quarter | quarter-short | quarter-narrow | month | month-short | month-narrow | week | week-short | week-narrow | weekOfMonth | weekOfMonth-short | weekOfMonth-narrow | day | day-short | day-narrow | dayOfYear | dayOfYear-short | dayOfYear-narrow | weekday | weekday-short | weekday-narrow | weekdayOfMonth | weekdayOfMonth-short | weekdayOfMonth-narrow | sun | sun-short | sun-narrow | mon | mon-short | mon-narrow | tue | tue-short | tue-narrow | wed | wed-short | wed-narrow | thu | thu-short | thu-narrow | fri | fri-short | fri-narrow | sat | sat-short | sat-narrow | dayperiod | dayperiod-short | dayperiod-narrow | hour | hour-short | hour-narrow | minute | minute-short | minute-narrow | second | second-short | second-narrow | zone | zone-short | zone-narrow) #REQUIRED > +<!ATTLIST field alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST field draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST field standard CDATA #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST field references CDATA #IMPLIED > + <!--@METADATA--> +<!ATTLIST field validSubLocales CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> + +<!ELEMENT relative ( #PCDATA ) > +<!ATTLIST relative type NMTOKEN #REQUIRED > + <!-- TODO: determine whether to allow 3 --> + <!--@MATCH:range/-2~3--> +<!ATTLIST relative alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST relative draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED:true, false--> +<!ATTLIST relative references CDATA #IMPLIED > + <!--@METADATA--> +<!ATTLIST relative validSubLocales CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> + +<!ELEMENT relativeTime ( alias | ( relativeTimePattern*, special* ) ) > +<!ATTLIST relativeTime type NMTOKEN #REQUIRED > + <!--@MATCH:literal/future, past--> +<!ATTLIST relativeTime alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST relativeTime draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST relativeTime references CDATA #IMPLIED > + <!--@METADATA--> +<!ATTLIST relativeTime validSubLocales CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> + +<!ELEMENT relativeTimePattern ( #PCDATA ) > +<!ATTLIST relativeTimePattern count (zero | one | two | few | many | other) #REQUIRED > +<!ATTLIST relativeTimePattern alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST relativeTimePattern draft (approved | contributed | provisional | unconfirmed) #IMPLIED > + <!--@METADATA--> +<!ATTLIST relativeTimePattern references CDATA #IMPLIED > + <!--@METADATA--> +<!ATTLIST relativeTimePattern validSubLocales CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> + +<!ELEMENT relativePeriod ( #PCDATA ) > +<!ATTLIST relativePeriod alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST relativePeriod draft (approved | contributed | provisional | unconfirmed) #IMPLIED > + <!--@METADATA--> + +<!ELEMENT timeZoneNames ( alias | ( hourFormat*, hoursFormat*, gmtFormat*, gmtZeroFormat*, regionFormat*, fallbackFormat*, fallbackRegionFormat*, abbreviationFallback*, preferenceOrdering*, singleCountries*, default*, zone*, metazone*, special* ) ) > +<!ATTLIST timeZoneNames draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST timeZoneNames validSubLocales CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> + +<!ELEMENT hourFormat ( #PCDATA ) > +<!ATTLIST hourFormat alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST hourFormat draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED:true, false--> +<!ATTLIST hourFormat references CDATA #IMPLIED > + <!--@METADATA--> + +<!ELEMENT hoursFormat ( #PCDATA ) > + <!--@DEPRECATED--> +<!ATTLIST hoursFormat alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> + <!--@DEPRECATED--> +<!ATTLIST hoursFormat draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST hoursFormat references CDATA #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> + +<!ELEMENT gmtFormat ( #PCDATA ) > +<!ATTLIST gmtFormat alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST gmtFormat draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED:true, false--> +<!ATTLIST gmtFormat references CDATA #IMPLIED > + <!--@METADATA--> + +<!ELEMENT gmtZeroFormat ( #PCDATA ) > +<!ATTLIST gmtZeroFormat alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST gmtZeroFormat draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED:true, false--> +<!ATTLIST gmtZeroFormat references CDATA #IMPLIED > + <!--@METADATA--> + +<!ELEMENT regionFormat ( #PCDATA ) > +<!ATTLIST regionFormat type (standard | daylight) #IMPLIED > +<!ATTLIST regionFormat alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST regionFormat draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED:true, false--> +<!ATTLIST regionFormat references CDATA #IMPLIED > + <!--@METADATA--> + +<!ELEMENT fallbackFormat ( #PCDATA ) > +<!ATTLIST fallbackFormat alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST fallbackFormat draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED:true, false--> +<!ATTLIST fallbackFormat references CDATA #IMPLIED > + <!--@METADATA--> + +<!ELEMENT fallbackRegionFormat ( #PCDATA ) > + <!--@DEPRECATED--> +<!ATTLIST fallbackRegionFormat alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> + <!--@DEPRECATED--> +<!ATTLIST fallbackRegionFormat draft (approved | contributed | provisional | unconfirmed) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST fallbackRegionFormat references CDATA #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> + +<!ELEMENT abbreviationFallback EMPTY > + <!--@DEPRECATED--> +<!ATTLIST abbreviationFallback type (GMT | standard) #IMPLIED > + <!-- use choice instead --> + <!--@VALUE--> + <!--@DEPRECATED--> +<!ATTLIST abbreviationFallback choice (GMT | standard) #IMPLIED > + <!-- really required, but needs to be optional to support type also --> + <!--@VALUE--> + <!--@DEPRECATED--> +<!ATTLIST abbreviationFallback alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> + <!--@DEPRECATED--> +<!ATTLIST abbreviationFallback draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST abbreviationFallback references CDATA #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> + +<!ELEMENT preferenceOrdering EMPTY > + <!-- use metazones instead --> + <!--@DEPRECATED--> +<!ATTLIST preferenceOrdering type CDATA #IMPLIED > + <!-- use choice instead --> + <!--@VALUE--> + <!--@DEPRECATED--> +<!ATTLIST preferenceOrdering choice CDATA #IMPLIED > + <!-- really required, but needs to be optional to support type also --> + <!--@VALUE--> + <!--@DEPRECATED--> +<!ATTLIST preferenceOrdering alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> + <!--@DEPRECATED--> +<!ATTLIST preferenceOrdering draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST preferenceOrdering references CDATA #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> + +<!ELEMENT singleCountries EMPTY > + <!--@DEPRECATED--> +<!ATTLIST singleCountries list CDATA #REQUIRED > + <!--@VALUE--> + <!--@DEPRECATED--> +<!ATTLIST singleCountries alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> + <!--@DEPRECATED--> +<!ATTLIST singleCountries draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST singleCountries references CDATA #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> + +<!ELEMENT zone ( alias | ( long*, short*, commonlyUsed*, exemplarCity*, special* ) ) > +<!ATTLIST zone type CDATA #REQUIRED > + <!--@MATCH:bcp47/tz--> +<!ATTLIST zone alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST zone draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST zone standard CDATA #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST zone references CDATA #IMPLIED > + <!--@METADATA--> +<!ATTLIST zone validSubLocales CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> + +<!ELEMENT long ( alias | ( generic*, standard*, daylight*, special* ) ) > +<!ATTLIST long alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST long draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST long references CDATA #IMPLIED > + <!--@METADATA--> +<!ATTLIST long validSubLocales CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> + +<!ELEMENT generic ( #PCDATA ) > +<!ATTLIST generic alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST generic draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED:true, false--> +<!ATTLIST generic references CDATA #IMPLIED > + <!--@METADATA--> + +<!ELEMENT standard ( #PCDATA ) > +<!ATTLIST standard alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST standard draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED:true, false--> +<!ATTLIST standard references CDATA #IMPLIED > + <!--@METADATA--> + +<!ELEMENT daylight ( #PCDATA ) > +<!ATTLIST daylight alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST daylight draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED:true, false--> +<!ATTLIST daylight references CDATA #IMPLIED > + <!--@METADATA--> + +<!ELEMENT short ( alias | ( generic*, standard*, daylight*, special* ) ) > +<!ATTLIST short alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST short draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST short references CDATA #IMPLIED > + <!--@METADATA--> +<!ATTLIST short validSubLocales CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> + +<!ELEMENT commonlyUsed ( #PCDATA ) > + <!--@DEPRECATED--> +<!ATTLIST commonlyUsed used (true | false) #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> +<!ATTLIST commonlyUsed alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> + <!--@DEPRECATED--> +<!ATTLIST commonlyUsed draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST commonlyUsed references CDATA #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> + +<!ELEMENT exemplarCity ( #PCDATA ) > +<!ATTLIST exemplarCity alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/formal, secondary--> +<!ATTLIST exemplarCity draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED:true, false--> +<!ATTLIST exemplarCity references CDATA #IMPLIED > + <!--@METADATA--> + +<!ELEMENT metazone ( alias | ( long*, short*, commonlyUsed*, special* ) ) > +<!ATTLIST metazone type CDATA #REQUIRED > + <!--@MATCH:metazone--> +<!ATTLIST metazone alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST metazone draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST metazone standard CDATA #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST metazone references CDATA #IMPLIED > + <!--@METADATA--> +<!ATTLIST metazone validSubLocales CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> + +<!-- ######################################################### --> + +<!ELEMENT numbers ( alias | ( defaultNumberingSystem*, otherNumberingSystems*, minimumGroupingDigits*, symbols*, decimalFormats*, scientificFormats*, percentFormats*, currencyFormats*, currencies?, miscPatterns*, minimalPairs*, special* ) ) > +<!ATTLIST numbers alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST numbers draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST numbers standard CDATA #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST numbers references CDATA #IMPLIED > + <!--@METADATA--> +<!ATTLIST numbers validSubLocales CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> + +<!ELEMENT defaultNumberingSystem ( #PCDATA ) > +<!ATTLIST defaultNumberingSystem alt NMTOKENS #IMPLIED > + <!--@MATCH:bcp47/nu--> +<!ATTLIST defaultNumberingSystem draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED:true, false--> +<!ATTLIST defaultNumberingSystem references CDATA #IMPLIED > + <!--@METADATA--> + +<!ELEMENT otherNumberingSystems ( alias | ( native*, traditional*, finance*, special* ) ) > +<!ATTLIST otherNumberingSystems alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST otherNumberingSystems draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> + +<!ELEMENT native ( #PCDATA ) > +<!ATTLIST native alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST native draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED:true, false--> + +<!ELEMENT traditional ( #PCDATA ) > +<!ATTLIST traditional alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST traditional draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED:true, false--> + +<!ELEMENT finance ( #PCDATA ) > +<!ATTLIST finance alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST finance draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED:true, false--> + +<!ELEMENT minimumGroupingDigits ( #PCDATA ) > +<!ATTLIST minimumGroupingDigits alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST minimumGroupingDigits draft (approved | contributed | provisional | unconfirmed) #IMPLIED > + <!--@METADATA--> +<!ATTLIST minimumGroupingDigits references CDATA #IMPLIED > + <!--@METADATA--> + +<!ELEMENT symbols ( alias | ( decimal*, group*, list*, percentSign*, nativeZeroDigit*, patternDigit*, plusSign*, minusSign*, approximatelySign*, exponential*, superscriptingExponent*, perMille*, infinity*, nan*, currencyDecimal*, currencyGroup*, timeSeparator*, special* ) ) > +<!ATTLIST symbols alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST symbols draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST symbols standard CDATA #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST symbols references CDATA #IMPLIED > + <!--@METADATA--> +<!ATTLIST symbols validSubLocales CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> +<!ATTLIST symbols numberSystem CDATA #IMPLIED > + <!--@MATCH:bcp47/nu--> + +<!ELEMENT decimal ( #PCDATA ) > +<!ATTLIST decimal alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST decimal draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED:true, false--> +<!ATTLIST decimal references CDATA #IMPLIED > + <!--@METADATA--> +<!ATTLIST decimal numberSystem CDATA #IMPLIED > + <!--@DEPRECATED--> + +<!ELEMENT group ( #PCDATA ) > +<!ATTLIST group alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST group draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED:true, false--> +<!ATTLIST group references CDATA #IMPLIED > + <!--@METADATA--> +<!ATTLIST group numberSystem CDATA #IMPLIED > + <!--@DEPRECATED--> + +<!ELEMENT list ( #PCDATA ) > +<!ATTLIST list alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST list draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED:true, false--> +<!ATTLIST list references CDATA #IMPLIED > + <!--@METADATA--> +<!ATTLIST list numberSystem CDATA #IMPLIED > + <!--@DEPRECATED--> + +<!ELEMENT percentSign ( #PCDATA ) > +<!ATTLIST percentSign alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST percentSign draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED:true, false--> +<!ATTLIST percentSign references CDATA #IMPLIED > + <!--@METADATA--> +<!ATTLIST percentSign numberSystem CDATA #IMPLIED > + <!--@DEPRECATED--> + +<!ELEMENT nativeZeroDigit ( #PCDATA ) > + <!--@DEPRECATED--> +<!ATTLIST nativeZeroDigit alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> + <!--@DEPRECATED--> +<!ATTLIST nativeZeroDigit draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST nativeZeroDigit references CDATA #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST nativeZeroDigit numberSystem CDATA #IMPLIED > + <!--@DEPRECATED--> + +<!ELEMENT patternDigit ( #PCDATA ) > + <!--@DEPRECATED--> +<!ATTLIST patternDigit alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> + <!--@DEPRECATED--> +<!ATTLIST patternDigit draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST patternDigit references CDATA #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST patternDigit numberSystem CDATA #IMPLIED > + <!--@DEPRECATED--> + +<!ELEMENT plusSign ( #PCDATA ) > +<!ATTLIST plusSign alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST plusSign draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED:true, false--> +<!ATTLIST plusSign references CDATA #IMPLIED > + <!--@METADATA--> +<!ATTLIST plusSign numberSystem CDATA #IMPLIED > + <!--@DEPRECATED--> + +<!ELEMENT minusSign ( #PCDATA ) > +<!ATTLIST minusSign alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST minusSign draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED:true, false--> +<!ATTLIST minusSign references CDATA #IMPLIED > + <!--@METADATA--> +<!ATTLIST minusSign numberSystem CDATA #IMPLIED > + <!--@DEPRECATED--> + +<!ELEMENT approximatelySign ( #PCDATA ) > +<!ATTLIST approximatelySign alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST approximatelySign draft (approved | contributed | provisional | unconfirmed) #IMPLIED > + <!--@METADATA--> +<!ATTLIST approximatelySign references CDATA #IMPLIED > + <!--@METADATA--> + +<!ELEMENT exponential ( #PCDATA ) > +<!ATTLIST exponential alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST exponential draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED:true, false--> +<!ATTLIST exponential references CDATA #IMPLIED > + <!--@METADATA--> +<!ATTLIST exponential numberSystem CDATA #IMPLIED > + <!--@DEPRECATED--> + +<!ELEMENT superscriptingExponent ( #PCDATA ) > +<!ATTLIST superscriptingExponent alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST superscriptingExponent draft (approved | contributed | provisional | unconfirmed) #IMPLIED > + <!--@METADATA--> +<!ATTLIST superscriptingExponent references CDATA #IMPLIED > + <!--@METADATA--> + +<!ELEMENT perMille ( #PCDATA ) > +<!ATTLIST perMille alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST perMille draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED:true, false--> +<!ATTLIST perMille references CDATA #IMPLIED > + <!--@METADATA--> +<!ATTLIST perMille numberSystem CDATA #IMPLIED > + <!--@DEPRECATED--> + +<!ELEMENT infinity ( #PCDATA ) > +<!ATTLIST infinity alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST infinity draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED:true, false--> +<!ATTLIST infinity references CDATA #IMPLIED > + <!--@METADATA--> +<!ATTLIST infinity numberSystem CDATA #IMPLIED > + <!--@DEPRECATED--> + +<!ELEMENT nan ( #PCDATA ) > +<!ATTLIST nan alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST nan draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED:true, false--> +<!ATTLIST nan references CDATA #IMPLIED > + <!--@METADATA--> +<!ATTLIST nan numberSystem CDATA #IMPLIED > + <!--@DEPRECATED--> + +<!ELEMENT currencyDecimal ( #PCDATA ) > +<!ATTLIST currencyDecimal alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST currencyDecimal draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED:true, false--> +<!ATTLIST currencyDecimal references CDATA #IMPLIED > + <!--@METADATA--> +<!ATTLIST currencyDecimal numberSystem CDATA #IMPLIED > + <!--@DEPRECATED--> + +<!ELEMENT currencyGroup ( #PCDATA ) > +<!ATTLIST currencyGroup alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST currencyGroup draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED:true, false--> +<!ATTLIST currencyGroup references CDATA #IMPLIED > + <!--@METADATA--> +<!ATTLIST currencyGroup numberSystem CDATA #IMPLIED > + <!--@DEPRECATED--> + +<!ELEMENT timeSeparator ( #PCDATA ) > +<!ATTLIST timeSeparator alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST timeSeparator draft (approved | contributed | provisional | unconfirmed) #IMPLIED > + <!--@METADATA--> +<!ATTLIST timeSeparator references CDATA #IMPLIED > + <!--@METADATA--> + +<!ELEMENT decimalFormats ( alias | ( default*, decimalFormatLength*, special* ) ) > +<!ATTLIST decimalFormats draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST decimalFormats validSubLocales CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> +<!ATTLIST decimalFormats numberSystem CDATA #IMPLIED > + <!--@MATCH:bcp47/nu--> + +<!ELEMENT decimalFormatLength ( alias | ( default*, decimalFormat*, special* ) ) > +<!ATTLIST decimalFormatLength type (full | long | medium | short) #IMPLIED > +<!ATTLIST decimalFormatLength alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST decimalFormatLength draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST decimalFormatLength standard CDATA #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST decimalFormatLength references CDATA #IMPLIED > + <!--@METADATA--> +<!ATTLIST decimalFormatLength validSubLocales CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> + +<!ELEMENT decimalFormat ( alias | ( pattern*, special* ) ) > +<!ATTLIST decimalFormat type NMTOKEN "standard" > + <!--@MATCH:literal/standard--> +<!ATTLIST decimalFormat alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST decimalFormat draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST decimalFormat standard CDATA #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST decimalFormat references CDATA #IMPLIED > + <!--@METADATA--> +<!ATTLIST decimalFormat validSubLocales CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> + +<!ELEMENT scientificFormats ( alias | ( default*, scientificFormatLength*, special* ) ) > +<!ATTLIST scientificFormats draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST scientificFormats validSubLocales CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> +<!ATTLIST scientificFormats numberSystem CDATA #IMPLIED > + <!--@MATCH:bcp47/nu--> + +<!ELEMENT scientificFormatLength ( alias | ( default*, scientificFormat*, special* ) ) > +<!ATTLIST scientificFormatLength type (full | long | medium | short) #IMPLIED > +<!ATTLIST scientificFormatLength alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST scientificFormatLength draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST scientificFormatLength standard CDATA #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST scientificFormatLength references CDATA #IMPLIED > + <!--@METADATA--> +<!ATTLIST scientificFormatLength validSubLocales CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> + +<!ELEMENT scientificFormat ( alias | ( pattern*, special* ) ) > +<!ATTLIST scientificFormat type NMTOKEN "standard" > + <!--@MATCH:literal/standard--> +<!ATTLIST scientificFormat alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST scientificFormat draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST scientificFormat standard CDATA #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST scientificFormat references CDATA #IMPLIED > + <!--@METADATA--> +<!ATTLIST scientificFormat validSubLocales CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> + +<!ELEMENT percentFormats ( alias | ( default*, percentFormatLength*, special* ) ) > +<!ATTLIST percentFormats draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST percentFormats validSubLocales CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> +<!ATTLIST percentFormats numberSystem CDATA #IMPLIED > + <!--@MATCH:bcp47/nu--> + +<!ELEMENT percentFormatLength ( alias | ( default*, percentFormat*, special* ) ) > +<!ATTLIST percentFormatLength type (full | long | medium | short) #IMPLIED > +<!ATTLIST percentFormatLength alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST percentFormatLength draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST percentFormatLength standard CDATA #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST percentFormatLength references CDATA #IMPLIED > + <!--@METADATA--> +<!ATTLIST percentFormatLength validSubLocales CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> + +<!ELEMENT percentFormat ( alias | ( pattern*, special* ) ) > +<!ATTLIST percentFormat type NMTOKEN "standard" > + <!--@MATCH:literal/standard--> +<!ATTLIST percentFormat alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST percentFormat draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST percentFormat standard CDATA #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST percentFormat references CDATA #IMPLIED > + <!--@METADATA--> +<!ATTLIST percentFormat validSubLocales CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> + +<!ELEMENT currencyFormats ( alias | ( default*, currencySpacing*, currencyFormatLength*, unitPattern*, special* ) ) > +<!ATTLIST currencyFormats draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST currencyFormats validSubLocales CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> +<!ATTLIST currencyFormats numberSystem CDATA #IMPLIED > + <!--@MATCH:bcp47/nu--> + +<!ELEMENT currencySpacing ( alias | ( beforeCurrency*, afterCurrency*, special* ) ) > + +<!ELEMENT beforeCurrency ( alias | ( currencyMatch*, surroundingMatch*, insertBetween*, special* ) ) > + +<!ELEMENT currencyMatch ( #PCDATA ) > +<!ATTLIST currencyMatch alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST currencyMatch draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED:true, false--> +<!ATTLIST currencyMatch references CDATA #IMPLIED > + <!--@METADATA--> + +<!ELEMENT surroundingMatch ( #PCDATA ) > +<!ATTLIST surroundingMatch alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST surroundingMatch draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED:true, false--> +<!ATTLIST surroundingMatch references CDATA #IMPLIED > + <!--@METADATA--> + +<!ELEMENT insertBetween ( #PCDATA ) > +<!ATTLIST insertBetween alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST insertBetween draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED:true, false--> +<!ATTLIST insertBetween references CDATA #IMPLIED > + <!--@METADATA--> + +<!ELEMENT afterCurrency ( alias | ( currencyMatch*, surroundingMatch*, insertBetween*, special* ) ) > + +<!ELEMENT currencyFormatLength ( alias | ( default*, currencyFormat*, special* ) ) > +<!ATTLIST currencyFormatLength type (full | long | medium | short) #IMPLIED > +<!ATTLIST currencyFormatLength alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST currencyFormatLength draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST currencyFormatLength standard CDATA #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST currencyFormatLength references CDATA #IMPLIED > + <!--@METADATA--> +<!ATTLIST currencyFormatLength validSubLocales CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> + +<!ELEMENT currencyFormat ( alias | ( pattern*, special* ) ) > +<!ATTLIST currencyFormat type NMTOKEN "standard" > + <!--@MATCH:literal/accounting, standard--> +<!ATTLIST currencyFormat alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST currencyFormat draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST currencyFormat standard CDATA #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST currencyFormat references CDATA #IMPLIED > + <!--@METADATA--> +<!ATTLIST currencyFormat validSubLocales CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> + +<!ELEMENT unitPattern ( #PCDATA ) > +<!ATTLIST unitPattern count (0 | 1 | zero | one | two | few | many | other) #REQUIRED > +<!ATTLIST unitPattern case NMTOKENS #IMPLIED > + <!--@MATCH:literal/ablative, accusative, comitative, dative, ergative, genitive, instrumental, locative, locativecopulative, nominative, oblique, prepositional, sociative, vocative, elative, illative, partitive, terminative, translative--> +<!ATTLIST unitPattern alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST unitPattern draft (approved | contributed | provisional | unconfirmed) #IMPLIED > + <!--@METADATA--> +<!ATTLIST unitPattern references CDATA #IMPLIED > + <!--@METADATA--> +<!ATTLIST unitPattern validSubLocales CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> + +<!ELEMENT currencies ( alias | ( default?, currency*, special* ) ) > +<!ATTLIST currencies draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST currencies validSubLocales CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> + +<!ELEMENT currency ( alias | ( ( ( pattern+, displayName*, symbol* ) | ( displayName+, symbol*, pattern* ) | ( symbol+, pattern* ) )?, decimal*, group*, special* ) ) > + +<!-- # warning: pattern appears twice in the above. The first is for consistency with all other cases of + pattern + displayName; the second is for backwards compatibility --> +<!ATTLIST currency type NMTOKEN "standard" > + <!--@MATCH:validity/currency--> +<!ATTLIST currency alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST currency draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST currency references CDATA #IMPLIED > + <!--@METADATA--> +<!ATTLIST currency validSubLocales CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> + +<!ELEMENT symbol ( #PCDATA ) > +<!ATTLIST symbol choice (true | false) #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> +<!ATTLIST symbol alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/formal, narrow, variant--> +<!ATTLIST symbol draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED:true, false--> +<!ATTLIST symbol references CDATA #IMPLIED > + <!--@METADATA--> + +<!ELEMENT miscPatterns ( alias | ( default*, pattern*, special* ) ) > +<!ATTLIST miscPatterns draft (approved | contributed | provisional | unconfirmed) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST miscPatterns numberSystem CDATA #IMPLIED > + <!--@MATCH:bcp47/nu--> + +<!ELEMENT minimalPairs ( alias | ( pluralMinimalPairs*, ordinalMinimalPairs*, caseMinimalPairs*, genderMinimalPairs*, special* ) ) > +<!ATTLIST minimalPairs alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST minimalPairs draft (approved | contributed | provisional | unconfirmed) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> + +<!ELEMENT pluralMinimalPairs ( #PCDATA ) > +<!ATTLIST pluralMinimalPairs count NMTOKEN #REQUIRED > + <!--@MATCH:literal/few, many, one, other, two, zero--> +<!ATTLIST pluralMinimalPairs alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST pluralMinimalPairs draft (approved | contributed | provisional | unconfirmed) #IMPLIED > + <!--@METADATA--> + +<!ELEMENT ordinalMinimalPairs ( #PCDATA ) > +<!ATTLIST ordinalMinimalPairs ordinal NMTOKEN #REQUIRED > + <!--@MATCH:literal/few, many, one, other, two, zero--> +<!ATTLIST ordinalMinimalPairs alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST ordinalMinimalPairs draft (approved | contributed | provisional | unconfirmed) #IMPLIED > + <!--@METADATA--> + +<!ELEMENT caseMinimalPairs ( #PCDATA ) > +<!ATTLIST caseMinimalPairs case NMTOKEN #REQUIRED > + <!--@MATCH:literal/ablative, accusative, comitative, dative, ergative, genitive, instrumental, locative, locativecopulative, nominative, oblique, prepositional, sociative, vocative, elative, illative, partitive, terminative, translative--> +<!ATTLIST caseMinimalPairs alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST caseMinimalPairs draft (approved | contributed | provisional | unconfirmed) #IMPLIED > + <!--@METADATA--> + +<!ELEMENT genderMinimalPairs ( #PCDATA ) > +<!ATTLIST genderMinimalPairs gender NMTOKEN #REQUIRED > + <!--@MATCH:literal/animate, common, feminine, inanimate, masculine, neuter, personal--> +<!ATTLIST genderMinimalPairs alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST genderMinimalPairs draft (approved | contributed | provisional | unconfirmed) #IMPLIED > + <!--@METADATA--> + +<!-- ######################################################### --> + +<!ELEMENT units ( alias | ( unit*, unitLength*, durationUnit*, special* ) ) > +<!ATTLIST units alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST units draft (approved | contributed | provisional | unconfirmed) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST units references CDATA #IMPLIED > + <!--@METADATA--> +<!ATTLIST units validSubLocales CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> + +<!ELEMENT unit ( alias | ( gender*, displayName*, unitPattern*, perUnitPattern*, special* ) ) > +<!ATTLIST unit type NMTOKEN #REQUIRED > + <!--@MATCH:validity/unit--> +<!ATTLIST unit alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST unit draft (approved | contributed | provisional | unconfirmed) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST unit references CDATA #IMPLIED > + <!--@METADATA--> +<!ATTLIST unit validSubLocales CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> + +<!ELEMENT gender ( #PCDATA ) > +<!ATTLIST gender alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/animate, common, feminine, inanimate, masculine, neuter, personal--> +<!ATTLIST gender draft (approved | contributed | provisional | unconfirmed) #IMPLIED > + <!--@METADATA--> + +<!ELEMENT perUnitPattern ( #PCDATA ) > +<!ATTLIST perUnitPattern alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST perUnitPattern draft (approved | contributed | provisional | unconfirmed) #IMPLIED > + <!--@METADATA--> +<!ATTLIST perUnitPattern references CDATA #IMPLIED > + <!--@METADATA--> + +<!ELEMENT unitLength ( alias | ( compoundUnit*, unit*, coordinateUnit*, special* ) ) > +<!ATTLIST unitLength type (long | short | narrow) #REQUIRED > +<!ATTLIST unitLength alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST unitLength draft (approved | contributed | provisional | unconfirmed) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST unitLength references CDATA #IMPLIED > + <!--@METADATA--> +<!ATTLIST unitLength validSubLocales CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> + +<!ELEMENT compoundUnit ( alias | ( compoundUnitPattern1*, compoundUnitPattern*, unitPrefixPattern*, special* ) ) > +<!ATTLIST compoundUnit type NMTOKEN #REQUIRED > + <!--@MATCH:or/regex/10p-?[0-9]{1,2}||regex/1024p[1-8]||literal/per, times, power2, power3--> +<!ATTLIST compoundUnit alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST compoundUnit draft (approved | contributed | provisional | unconfirmed) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST compoundUnit references CDATA #IMPLIED > + <!--@METADATA--> +<!ATTLIST compoundUnit validSubLocales CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> + +<!ELEMENT compoundUnitPattern1 ( #PCDATA ) > +<!ATTLIST compoundUnitPattern1 count (0 | 1 | zero | one | two | few | many | other) #IMPLIED > +<!ATTLIST compoundUnitPattern1 gender NMTOKENS #IMPLIED > + <!--@MATCH:literal/animate, common, feminine, inanimate, masculine, neuter, personal--> +<!ATTLIST compoundUnitPattern1 case NMTOKENS #IMPLIED > + <!--@MATCH:literal/ablative, accusative, comitative, dative, ergative, genitive, instrumental, locative, locativecopulative, nominative, oblique, prepositional, sociative, vocative--> +<!ATTLIST compoundUnitPattern1 alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST compoundUnitPattern1 draft (approved | contributed | provisional | unconfirmed) #IMPLIED > + <!--@METADATA--> +<!ATTLIST compoundUnitPattern1 references CDATA #IMPLIED > + <!--@METADATA--> + +<!ELEMENT compoundUnitPattern ( #PCDATA ) > +<!ATTLIST compoundUnitPattern case NMTOKENS #IMPLIED > + <!--@MATCH:literal/ablative, accusative, comitative, dative, ergative, genitive, instrumental, locative, locativecopulative, nominative, oblique, prepositional, sociative, vocative--> +<!ATTLIST compoundUnitPattern alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST compoundUnitPattern draft (approved | contributed | provisional | unconfirmed) #IMPLIED > + <!--@METADATA--> +<!ATTLIST compoundUnitPattern references CDATA #IMPLIED > + <!--@METADATA--> +<!ATTLIST compoundUnitPattern validSubLocales CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> + +<!ELEMENT unitPrefixPattern ( #PCDATA ) > +<!ATTLIST unitPrefixPattern alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST unitPrefixPattern draft (approved | contributed | provisional | unconfirmed) #IMPLIED > + <!--@METADATA--> +<!ATTLIST unitPrefixPattern references CDATA #IMPLIED > + <!--@METADATA--> + +<!ELEMENT coordinateUnit ( alias | ( displayName*, coordinateUnitPattern*, special* ) ) > +<!ATTLIST coordinateUnit alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST coordinateUnit draft (approved | contributed | provisional | unconfirmed) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> + +<!ELEMENT coordinateUnitPattern ( #PCDATA ) > +<!ATTLIST coordinateUnitPattern type (north | east | south | west) #REQUIRED > +<!ATTLIST coordinateUnitPattern alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST coordinateUnitPattern draft (approved | contributed | provisional | unconfirmed) #IMPLIED > + <!--@METADATA--> + +<!ELEMENT durationUnit ( alias | ( durationUnitPattern*, special* ) ) > +<!ATTLIST durationUnit type NMTOKEN #REQUIRED > + <!--@MATCH:literal/hm, hms, ms--> +<!ATTLIST durationUnit alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST durationUnit draft (approved | contributed | provisional | unconfirmed) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST durationUnit references CDATA #IMPLIED > + <!--@METADATA--> + +<!ELEMENT durationUnitPattern ( #PCDATA ) > +<!ATTLIST durationUnitPattern alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST durationUnitPattern draft (approved | contributed | provisional | unconfirmed) #IMPLIED > + <!--@METADATA--> +<!ATTLIST durationUnitPattern references CDATA #IMPLIED > + <!--@METADATA--> +<!ATTLIST durationUnitPattern validSubLocales CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> + +<!ELEMENT listPatterns ( alias | ( listPattern*, special* ) ) > +<!ATTLIST listPatterns alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST listPatterns draft (approved | contributed | provisional | unconfirmed) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST listPatterns references CDATA #IMPLIED > + <!--@METADATA--> +<!ATTLIST listPatterns validSubLocales CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> + +<!ELEMENT listPattern ( alias | ( listPatternPart*, special* ) ) > +<!ATTLIST listPattern type NMTOKEN #IMPLIED > + <!--@MATCH:literal/or, or-narrow, or-short, standard-narrow, standard-short, unit, unit-narrow, unit-short--> +<!ATTLIST listPattern alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST listPattern draft (approved | contributed | provisional | unconfirmed) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST listPattern references CDATA #IMPLIED > + <!--@METADATA--> +<!ATTLIST listPattern validSubLocales CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> + +<!ELEMENT listPatternPart ( #PCDATA ) > +<!ATTLIST listPatternPart type (start | middle | end | 2 | 3) #REQUIRED > +<!ATTLIST listPatternPart alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST listPatternPart draft (approved | contributed | provisional | unconfirmed) #IMPLIED > + <!--@METADATA--> +<!ATTLIST listPatternPart references CDATA #IMPLIED > + <!--@METADATA--> +<!ATTLIST listPatternPart validSubLocales CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> + +<!-- ######################################################### --> + +<!ELEMENT collations ( alias | ( defaultCollation?, default*, collation*, special* ) ) > +<!ATTLIST collations version NMTOKEN #IMPLIED > + <!--@METADATA--> +<!ATTLIST collations draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!-- should be DEPRECATED, but needs some cleanup first --> + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST collations validSubLocales CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> + +<!ELEMENT defaultCollation ( #PCDATA ) > +<!ATTLIST defaultCollation alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST defaultCollation draft (approved | contributed | provisional | unconfirmed) #IMPLIED > + <!--@METADATA--> + +<!ELEMENT collation ( alias | ( base?, import*, settings?, suppress_contractions?, optimize?, ( cr* | rules? ), special* ) ) > +<!ATTLIST collation type NMTOKEN "standard" > + <!--@MATCH:or/bcp47/co||regex/private-.*||literal/digits-after--> +<!ATTLIST collation visibility (internal | external) #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> +<!ATTLIST collation alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/proposed, short, variant--> +<!ATTLIST collation draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> +<!ATTLIST collation standard CDATA #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST collation references CDATA #IMPLIED > + <!--@MATCH:any--> + <!--@METADATA--> +<!ATTLIST collation validSubLocales CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> + +<!ELEMENT base ( alias | special ) > + <!--@ORDERED--> + <!--@DEPRECATED--> + +<!ELEMENT import EMPTY > + <!-- deprecated, see CLDR ticket #8289 --> + <!--@DEPRECATED--> +<!ATTLIST import source CDATA #REQUIRED > + <!--@VALUE--> + <!--@DEPRECATED--> +<!ATTLIST import type CDATA #IMPLIED > + <!--@DEPRECATED--> +<!ATTLIST import draft (approved | contributed | provisional | unconfirmed) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST import references CDATA #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> + +<!ELEMENT settings ( special* ) > + <!-- deprecated, see CLDR ticket #8289 --> + <!--@ORDERED--> + <!--@DEPRECATED--> +<!ATTLIST settings strength (primary | secondary | tertiary | quaternary | identical) #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> +<!ATTLIST settings alternate (non-ignorable | shifted) #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> +<!ATTLIST settings backwards (on | off) #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> +<!ATTLIST settings normalization (on | off) #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> +<!ATTLIST settings caseLevel (on | off) #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> +<!ATTLIST settings caseFirst (upper | lower | off) #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> +<!ATTLIST settings hiraganaQuarternary (on | off) #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> +<!ATTLIST settings hiraganaQuaternary (on | off) #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> +<!ATTLIST settings maxVariable (space | punct | symbol | currency) #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> +<!ATTLIST settings numeric (on | off) #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> +<!ATTLIST settings private (true | false) #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> +<!ATTLIST settings variableTop CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> +<!ATTLIST settings reorder NMTOKENS #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> + +<!ELEMENT suppress_contractions ( #PCDATA | cp )* > + <!-- deprecated, see CLDR ticket #8289 --> + <!--@ORDERED--> + <!--@DEPRECATED--> + +<!ELEMENT optimize ( #PCDATA | cp )* > + <!-- deprecated, see CLDR ticket #8289 --> + <!--@ORDERED--> + <!--@DEPRECATED--> + +<!ELEMENT cr ( #PCDATA ) > +<!ATTLIST cr alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST cr draft (approved | contributed | provisional | unconfirmed) #IMPLIED > + <!--@METADATA--> +<!ATTLIST cr references CDATA #IMPLIED > + <!--@METADATA--> + +<!-- # Use the cr element instead, with ICU syntax. --> + +<!ELEMENT rules ( alias | ( ( reset | import ), ( reset | import | p | pc | s | sc | t | tc | q | qc | i | ic | x )* ) ) > + <!--@ORDERED--> + <!--@DEPRECATED--> + +<!ELEMENT reset ( #PCDATA | cp | first_variable | last_variable | first_tertiary_ignorable | last_tertiary_ignorable | first_secondary_ignorable | last_secondary_ignorable | first_primary_ignorable | last_primary_ignorable | first_non_ignorable | last_non_ignorable | first_trailing | last_trailing )* > + <!--@ORDERED--> + <!--@DEPRECATED--> +<!ATTLIST reset before NMTOKEN #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> + +<!ELEMENT first_variable EMPTY > + <!--@DEPRECATED--> + +<!ELEMENT last_variable EMPTY > + <!--@DEPRECATED--> + +<!ELEMENT first_tertiary_ignorable EMPTY > + <!--@DEPRECATED--> + +<!ELEMENT last_tertiary_ignorable EMPTY > + <!--@ORDERED--> + <!--@DEPRECATED--> + +<!ELEMENT first_secondary_ignorable EMPTY > + <!--@DEPRECATED--> + +<!ELEMENT last_secondary_ignorable EMPTY > + <!--@ORDERED--> + <!--@DEPRECATED--> + +<!ELEMENT first_primary_ignorable EMPTY > + <!--@DEPRECATED--> + +<!ELEMENT last_primary_ignorable EMPTY > + <!--@DEPRECATED--> + +<!ELEMENT first_non_ignorable EMPTY > + <!--@DEPRECATED--> + +<!ELEMENT last_non_ignorable EMPTY > + <!--@ORDERED--> + <!--@DEPRECATED--> + +<!ELEMENT first_trailing EMPTY > + <!--@DEPRECATED--> + +<!ELEMENT last_trailing EMPTY > + <!--@DEPRECATED--> + +<!ELEMENT p ( #PCDATA | cp | last_variable )* > + <!--@ORDERED--> + <!--@DEPRECATED--> + +<!ELEMENT pc ( #PCDATA | cp | last_variable )* > + <!--@ORDERED--> + <!--@DEPRECATED--> + +<!ELEMENT s ( #PCDATA | cp | last_variable )* > + <!--@ORDERED--> + <!--@DEPRECATED--> + +<!ELEMENT sc ( #PCDATA | cp | last_variable )* > + <!--@ORDERED--> + <!--@DEPRECATED--> + +<!ELEMENT t ( #PCDATA | cp | last_variable )* > + <!--@ORDERED--> + <!--@DEPRECATED--> + +<!ELEMENT tc ( #PCDATA | cp | last_variable )* > + <!--@ORDERED--> + <!--@DEPRECATED--> + +<!ELEMENT q ( #PCDATA | cp | last_variable )* > + <!--@DEPRECATED--> + +<!ELEMENT qc ( #PCDATA | cp | last_variable )* > + <!--@DEPRECATED--> + +<!ELEMENT i ( #PCDATA | cp | last_variable )* > + <!--@ORDERED--> + <!--@DEPRECATED--> + +<!ELEMENT ic ( #PCDATA | cp | last_variable )* > + <!--@ORDERED--> + <!--@DEPRECATED--> + +<!ELEMENT x ( context?, ( p | pc | s | sc | t | tc | q | qc | i | ic )*, extend? ) > + <!--@ORDERED--> + <!--@DEPRECATED--> + +<!ELEMENT context ( #PCDATA | cp )* > + <!--@ORDERED--> + <!--@DEPRECATED--> + +<!ELEMENT extend ( #PCDATA | cp )* > + <!--@ORDERED--> + <!--@DEPRECATED--> + +<!-- ######################################################### --> + +<!ELEMENT posix ( alias | ( messages*, special* ) ) > +<!ATTLIST posix draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST posix references CDATA #IMPLIED > + <!--@METADATA--> +<!ATTLIST posix validSubLocales CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> + +<!ELEMENT messages ( alias | ( yesstr*, nostr*, yesexpr*, noexpr*, special* ) ) > +<!ATTLIST messages alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST messages draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST messages references CDATA #IMPLIED > + <!--@METADATA--> +<!ATTLIST messages validSubLocales CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> + +<!ELEMENT yesstr ( #PCDATA ) > +<!ATTLIST yesstr alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST yesstr draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED:true, false--> +<!ATTLIST yesstr references CDATA #IMPLIED > + <!--@METADATA--> + +<!ELEMENT nostr ( #PCDATA ) > +<!ATTLIST nostr alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST nostr draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED:true, false--> +<!ATTLIST nostr references CDATA #IMPLIED > + <!--@METADATA--> + +<!ELEMENT yesexpr ( #PCDATA ) > + <!--@DEPRECATED--> +<!ATTLIST yesexpr alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> + <!--@DEPRECATED--> +<!ATTLIST yesexpr draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST yesexpr references CDATA #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> + +<!ELEMENT noexpr ( #PCDATA ) > + <!--@DEPRECATED--> +<!ATTLIST noexpr alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> + <!--@DEPRECATED--> +<!ATTLIST noexpr draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST noexpr references CDATA #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> + +<!ELEMENT characterLabels ( alias | ( characterLabelPattern*, characterLabel*, special* ) ) > + +<!ELEMENT characterLabelPattern ( #PCDATA ) > +<!ATTLIST characterLabelPattern type NMTOKEN #REQUIRED > + <!--@MATCH:literal/all, category-list, compatibility, enclosed, extended, historic, miscellaneous, other, scripts, strokes, subscript, superscript--> +<!ATTLIST characterLabelPattern count (0 | 1 | zero | one | two | few | many | other) #IMPLIED > + <!-- count only used for certain patterns" --> +<!ATTLIST characterLabelPattern alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST characterLabelPattern draft (approved | contributed | provisional | unconfirmed) #IMPLIED > + <!--@METADATA--> + +<!ELEMENT characterLabel ( #PCDATA ) > +<!ATTLIST characterLabel type NMTOKEN #REQUIRED > + <!--@MATCH:literal/activities, african_scripts, american_scripts, animal, animals_nature, arrows, body, box_drawing, braille, building, bullets_stars, consonantal_jamo, currency_symbols, dash_connector, digits, dingbats, divination_symbols, downwards_arrows, downwards_upwards_arrows, east_asian_scripts, emoji, european_scripts, female, flag, flags, food_drink, format, format_whitespace, full_width_form_variant, geometric_shapes, half_width_form_variant, han_characters, han_radicals, hanja, hanzi_simplified, hanzi_traditional, heart, historic_scripts, ideographic_desc_characters, japanese_kana, kanbun, kanji, keycap, leftwards_arrows, leftwards_rightwards_arrows, letterlike_symbols, limited_use, male, math_symbols, middle_eastern_scripts, miscellaneous, modern_scripts, modifier, musical_symbols, nature, nonspacing, numbers, objects, other, paired, person, phonetic_alphabet, pictographs, place, plant, punctuation, rightwards_arrows, sign_standard_symbols, small_form_variant, smiley, smileys_people, south_asian_scripts, southeast_asian_scripts, spacing, sport, symbols, technical_symbols, tone_marks, travel, travel_places, upwards_arrows, variant_forms, vocalic_jamo, weather, western_asian_scripts, whitespace--> +<!ATTLIST characterLabel alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST characterLabel draft (approved | contributed | provisional | unconfirmed) #IMPLIED > + <!--@METADATA--> + +<!ELEMENT segmentations ( alias | ( segmentation*, special* ) ) > +<!ATTLIST segmentations alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST segmentations draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST segmentations references CDATA #IMPLIED > + <!--@METADATA--> +<!ATTLIST segmentations validSubLocales CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> + +<!ELEMENT segmentation ( alias | ( variables?, segmentRules?, exceptions?, suppressions? ) | special* ) > +<!ATTLIST segmentation type NMTOKEN #REQUIRED > + <!--@MATCH:literal/GraphemeClusterBreak, LineBreak, SentenceBreak, WordBreak--> +<!ATTLIST segmentation alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST segmentation draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST segmentation references CDATA #IMPLIED > + <!--@METADATA--> +<!ATTLIST segmentation validSubLocales CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> + +<!ELEMENT variables ( alias | ( variable*, special* ) ) > + +<!ELEMENT variable ( #PCDATA ) > + <!--@ORDERED--> +<!ATTLIST variable id CDATA #REQUIRED > + <!--@MATCH:regex/\$[a-zA-Z0-9_]+--> +<!ATTLIST variable alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST variable draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED:true, false--> +<!ATTLIST variable references CDATA #IMPLIED > + <!--@METADATA--> + +<!ELEMENT segmentRules ( alias | ( rule*, special* ) ) > + +<!ELEMENT rule ( #PCDATA ) > +<!ATTLIST rule id NMTOKEN #REQUIRED > + <!--@MATCH:range/0.0~9999.0--> +<!ATTLIST rule alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST rule draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED:true, false--> +<!ATTLIST rule references CDATA #IMPLIED > + <!--@METADATA--> + +<!ELEMENT exceptions ( exception* ) > + <!-- use suppressions instead --> + <!--@DEPRECATED--> + +<!ELEMENT exception ( #PCDATA ) > + <!--@ORDERED--> + <!--@DEPRECATED--> +<!ATTLIST exception draft (approved | contributed | provisional | unconfirmed) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> + +<!ELEMENT suppressions ( alias | ( suppression*, special* ) ) > +<!ATTLIST suppressions type NMTOKEN "standard" > + <!--@MATCH:literal/standard--> +<!ATTLIST suppressions draft (approved | contributed | provisional | unconfirmed) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> + +<!ELEMENT suppression ( #PCDATA ) > + <!--@ORDERED--> +<!ATTLIST suppression alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST suppression draft (approved | contributed | provisional | unconfirmed) #IMPLIED > + <!--@METADATA--> + +<!ELEMENT rbnf ( alias | ( rulesetGrouping*, special* ) ) > + +<!ELEMENT rulesetGrouping ( alias | ( ruleset*, special* ) ) > +<!ATTLIST rulesetGrouping type NMTOKEN #REQUIRED > + <!--@MATCH:literal/NumberingSystemRules, OrdinalRules, SpelloutRules--> +<!ATTLIST rulesetGrouping draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + +<!ELEMENT ruleset ( alias | ( rbnfrule*, special* ) ) > + <!--@ORDERED--> +<!ATTLIST ruleset type NMTOKEN #REQUIRED > + <!--@MATCH:regex/(ord-M-)?[\-0-9a-z]+--> +<!ATTLIST ruleset access (public | private) #IMPLIED > + <!--@VALUE--> +<!ATTLIST ruleset allowsParsing (true | false) #IMPLIED > + <!--@VALUE--> +<!ATTLIST ruleset draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> + +<!ELEMENT rbnfrule ( #PCDATA ) > + <!--@ORDERED--> +<!ATTLIST rbnfrule value CDATA #REQUIRED > + <!--@MATCH:or/range/-1.0E20~1.0E20||literal/-x, 0, 0.x, NaN, -Inf, Inf, x,x, x.x--> + <!--@VALUE--> +<!ATTLIST rbnfrule radix CDATA #IMPLIED > + <!--@MATCH:literal/1,000, 100, 1000, 100000, 20--> + <!--@VALUE--> +<!ATTLIST rbnfrule decexp CDATA #IMPLIED > + <!--@VALUE--> +<!ATTLIST rbnfrule alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST rbnfrule draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED:true, false--> + +<!ELEMENT typographicNames ( alias | ( axisName*, styleName*, featureName*, special* ) ) > + +<!ELEMENT axisName ( #PCDATA ) > +<!ATTLIST axisName type (ital | opsz | slnt | wdth | wght) #REQUIRED > +<!ATTLIST axisName alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST axisName draft (approved | contributed | provisional | unconfirmed) #IMPLIED > + <!--@METADATA--> + +<!ELEMENT styleName ( #PCDATA ) > +<!ATTLIST styleName type (ital | opsz | slnt | wdth | wght) #REQUIRED > +<!ATTLIST styleName subtype NMTOKEN #REQUIRED > + <!--@MATCH:literal/-12, 0, 1, 100, 112.5, 12, 125, 144, 150, 18, 200, 24, 300, 350, 380, 400, 50, 500, 600, 62.5, 700, 72, 75, 8, 800, 87.5, 900, 950--> +<!ATTLIST styleName alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/compressed, demi, extended, heavy, narrow, short, ultra, ultrablack, ultraheavy, wide--> +<!ATTLIST styleName draft (approved | contributed | provisional | unconfirmed) #IMPLIED > + <!--@METADATA--> + +<!ELEMENT featureName ( #PCDATA ) > +<!ATTLIST featureName type (afrc | cpsp | dlig | frac | lnum | onum | ordn | pnum | smcp | tnum | zero) #REQUIRED > +<!ATTLIST featureName alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/short, variant--> +<!ATTLIST featureName draft (approved | contributed | provisional | unconfirmed) #IMPLIED > + <!--@METADATA--> + +<!ELEMENT annotations ( alias | ( annotation*, special* ) ) > + +<!ELEMENT annotation ( #PCDATA ) > +<!ATTLIST annotation cp CDATA #REQUIRED > + <!--@MATCH:any--> +<!ATTLIST annotation tts CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> +<!ATTLIST annotation type (tts) #IMPLIED > +<!ATTLIST annotation alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST annotation draft (approved | contributed | provisional | unconfirmed) #IMPLIED > + <!--@METADATA--> + +<!-- ######################################################### --> +<!-- # This element contains metadata for Survey Tool internal use (optimization, etc). --> + +<!ELEMENT metadata ( alias | ( casingData?, special* ) ) > + <!--@METADATA--> + +<!ELEMENT casingData ( alias | ( casingItem*, special* ) ) > + <!--@METADATA--> + +<!ELEMENT casingItem ( #PCDATA ) > +<!ATTLIST casingItem type CDATA #REQUIRED > + <!--@MATCH:any--> +<!ATTLIST casingItem override (true | false) #IMPLIED > + <!--@VALUE--> +<!ATTLIST casingItem forceError (true | false) #IMPLIED > + <!--@VALUE--> +<!ATTLIST casingItem alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> +<!ATTLIST casingItem draft (approved | contributed | provisional | unconfirmed) #IMPLIED > + <!--@METADATA--> + +<!ELEMENT references ( reference* ) > + <!--@METADATA--> + <!--@DEPRECATED--> + +<!ELEMENT reference ( #PCDATA ) > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST reference type NMTOKEN #REQUIRED > + <!--@DEPRECATED--> +<!ATTLIST reference uri CDATA #IMPLIED > + <!--@VALUE--> + <!--@DEPRECATED--> +<!ATTLIST reference alt NMTOKENS #IMPLIED > + <!--@MATCH:literal/variant--> + <!--@DEPRECATED--> +<!ATTLIST reference draft (approved | contributed | provisional | unconfirmed | true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> +<!ATTLIST reference standard (true | false) #IMPLIED > + <!--@METADATA--> + <!--@DEPRECATED--> diff --git a/Build/source/libs/icu/icu-src/source/data/dtd/cldr/common/dtd/ldmlICU.dtd b/Build/source/libs/icu/icu-src/source/data/dtd/cldr/common/dtd/ldmlICU.dtd new file mode 100644 index 00000000000..e8abdedcbab --- /dev/null +++ b/Build/source/libs/icu/icu-src/source/data/dtd/cldr/common/dtd/ldmlICU.dtd @@ -0,0 +1,125 @@ +<!-- +Copyright © 1991-2021 Unicode, Inc. +For terms of use, see http://www.unicode.org/copyright.html +SPDX-License-Identifier: Unicode-DFS-2016 +CLDR data files are interpreted according to the LDML specification (http://unicode.org/reports/tr35/) +--> + +<!-- +NOTE: Unlike the other DTDs, this file is manually maintained. +--> + +<!-- ######################################################### --> +<!-- The alias, default, special and cp elements are already defined in ldml.dtd. Defining them here as well would break locale conversion. --> +<!-- ######################################################### --> + +<!-- ICU Specific elements --> +<!-- ######################################################### --> +<!ATTLIST special xmlns:icu CDATA #IMPLIED> +<!ATTLIST special icu:version CDATA #IMPLIED> + +<!ELEMENT icu:version EMPTY> +<!ATTLIST icu:version icu:specialVersion CDATA #FIXED "41" > +<!ATTLIST icu:version icu:requiredLDMLVersion CDATA #FIXED "41" > + +<!-- ICU Scripts --> + +<!ELEMENT icu:scripts (alias | icu:script* ) > +<!ATTLIST icu:scripts draft ( true | false ) #IMPLIED > +<!ATTLIST icu:scripts standard CDATA #IMPLIED > + +<!ELEMENT icu:script ( #PCDATA ) > +<!ATTLIST icu:script type NMTOKEN #REQUIRED > +<!ATTLIST icu:script draft ( true | false ) #IMPLIED > + +<!-- RBNF data --> +<!ELEMENT icu:ruleBasedNumberFormats ( alias | (default?, icu:ruleBasedNumberFormat*)) > + +<!-- Either bare data or any number of cp --> +<!ELEMENT icu:ruleBasedNumberFormat (#PCDATA | cp)* > +<!ATTLIST icu:ruleBasedNumberFormat type NMTOKEN #IMPLIED > + +<!-- RBBI data --> +<!ELEMENT icu:breakIteratorData (alias | (icu:boundaries?, icu:dictionaries?, icu:extensions?, icu:lstm?)) > + +<!ELEMENT icu:boundaries (alias | (icu:grapheme?, icu:word?, icu:line*, icu:sentence?, icu:title?, icu:xgc?)) > + +<!ELEMENT icu:dictionaries (alias | (icu:dictionary*)) > + +<!ELEMENT icu:extensions (alias | (icu:extension*)) > + +<!ELEMENT icu:extension ( #PCDATA ) > + <!--@ORDERED--> + +<!ELEMENT icu:lstm (alias | (icu:lstmdata*)) > + +<!ELEMENT icu:lstmdata ( #PCDATA ) > +<!ATTLIST icu:lstmdata icu:dependency NMTOKEN #IMPLIED > +<!ATTLIST icu:lstmdata type NMTOKEN #REQUIRED > + +<!ELEMENT icu:dictionary ( #PCDATA ) > +<!ATTLIST icu:dictionary icu:dependency NMTOKEN #IMPLIED > +<!ATTLIST icu:dictionary type NMTOKEN #REQUIRED > + +<!ELEMENT icu:grapheme ( #PCDATA ) > +<!ATTLIST icu:grapheme icu:class NMTOKEN #IMPLIED > +<!ATTLIST icu:grapheme icu:append NMTOKEN #IMPLIED > +<!ATTLIST icu:grapheme icu:import NMTOKEN #IMPLIED > +<!ATTLIST icu:grapheme icu:dependency NMTOKEN #IMPLIED > + +<!ELEMENT icu:word ( #PCDATA ) > +<!ATTLIST icu:word icu:class NMTOKEN #IMPLIED > +<!ATTLIST icu:word icu:append NMTOKEN #IMPLIED > +<!ATTLIST icu:word icu:import NMTOKEN #IMPLIED > +<!ATTLIST icu:word icu:dependency NMTOKEN #IMPLIED > + +<!ELEMENT icu:line ( #PCDATA ) > +<!ATTLIST icu:line icu:class NMTOKEN #IMPLIED > +<!ATTLIST icu:line icu:append NMTOKEN #IMPLIED > +<!ATTLIST icu:line icu:import NMTOKEN #IMPLIED > +<!ATTLIST icu:line icu:dependency NMTOKEN #IMPLIED > +<!ATTLIST icu:line alt NMTOKENS #IMPLIED > + +<!ELEMENT icu:sentence ( #PCDATA ) > +<!ATTLIST icu:sentence icu:class NMTOKEN #IMPLIED > +<!ATTLIST icu:sentence icu:append NMTOKEN #IMPLIED > +<!ATTLIST icu:sentence icu:import NMTOKEN #IMPLIED > +<!ATTLIST icu:sentence icu:dependency NMTOKEN #IMPLIED > + +<!ELEMENT icu:title ( #PCDATA ) > +<!ATTLIST icu:title icu:class NMTOKEN #IMPLIED > +<!ATTLIST icu:title icu:append NMTOKEN #IMPLIED > +<!ATTLIST icu:title icu:import NMTOKEN #IMPLIED > +<!ATTLIST icu:title icu:dependency NMTOKEN #IMPLIED > + +<!ELEMENT icu:xgc ( #PCDATA ) > +<!ATTLIST icu:xgc icu:class NMTOKEN #IMPLIED > +<!ATTLIST icu:xgc icu:append NMTOKEN #IMPLIED > +<!ATTLIST icu:xgc icu:import NMTOKEN #IMPLIED > +<!ATTLIST icu:xgc icu:dependency NMTOKEN #IMPLIED > + +<!--deprecated --> +<!ELEMENT icu:breakDictionaryData EMPTY > +<!ATTLIST icu:breakDictionaryData icu:class NMTOKEN #IMPLIED > +<!ATTLIST icu:breakDictionaryData icu:import NMTOKEN #IMPLIED > +<!ATTLIST icu:breakDictionaryData icu:importFile CDATA #IMPLIED > + +<!-- RBT data --> +<!ELEMENT icu:transforms ( alias | (default?, icu:transform*)) > +<!ELEMENT icu:transform ( #PCDATA |cp )* > +<!ATTLIST icu:transform type NMTOKEN #REQUIRED > + +<!-- leap month information, all deprecated --> +<!ELEMENT icu:isLeapMonth ( alias | (icu:nonLeapSymbol?, icu:leapSymbol? ))> <!-- deprecated --> +<!ELEMENT icu:nonLeapSymbol ( #PCDATA ) > <!-- deprecated --> +<!ELEMENT icu:leapSymbol ( #PCDATA ) > <!-- deprecated --> + +<!-- UCA Rules --> +<!ELEMENT icu:UCARules EMPTY > +<!ATTLIST icu:UCARules icu:uca_rules CDATA #REQUIRED > + +<!-- Dependencies Rules --> +<!ELEMENT icu:depends EMPTY > +<!ATTLIST icu:depends icu:dependency CDATA #REQUIRED > + +<!-- ######################################################### --> diff --git a/Build/source/libs/icu/icu-src/source/data/in/icudt70l.dat b/Build/source/libs/icu/icu-src/source/data/in/icudt71l.dat Binary files differindex b0d5cf5cc98..113bc3d0fd3 100644 --- a/Build/source/libs/icu/icu-src/source/data/in/icudt70l.dat +++ b/Build/source/libs/icu/icu-src/source/data/in/icudt71l.dat diff --git a/Build/source/libs/icu/icu-src/source/data/makedata.mak b/Build/source/libs/icu/icu-src/source/data/makedata.mak index e8a33ff85dd..3825da92b9b 100644 --- a/Build/source/libs/icu/icu-src/source/data/makedata.mak +++ b/Build/source/libs/icu/icu-src/source/data/makedata.mak @@ -12,11 +12,11 @@ ############################################################################## # Keep the following in sync with the version - see common/unicode/uvernum.h -U_ICUDATA_NAME=icudt70 +U_ICUDATA_NAME=icudt71 ############################################################################## !IF "$(UWP)" == "UWP" # Optionally change the name of the data file for the UWP version. -U_ICUDATA_NAME=icudt70 +U_ICUDATA_NAME=icudt71 !ENDIF U_ICUDATA_ENDIAN_SUFFIX=l UNICODE_VERSION=14.0 @@ -142,13 +142,20 @@ TESTDATABLD=$(ICUP)\source\test\testdata\out\build ICUTOOLS=$(ICUP)\source\tools !MESSAGE ICU tools path is $(ICUTOOLS) +NATIVE_ARM= +!IF "$(PROCESSOR_ARCHITECTURE)" == "ARM64" || "$(PROCESSOR_ARCHITEW6432)" == "ARM64" +NATIVE_ARM=ARM64 +!ELSE IF "$(PROCESSOR_ARCHITECTURE)" == "ARM" || "$(PROCESSOR_ARCHITEW6432)" == "ARM" +NATIVE_ARM=ARM +!ENDIF + # ARM_CROSS_BUILD # In order to support cross-compiling for ARM/ARM64 using the x64 tools # we need to know if we're building the ARM/ARM64 data DLL, otherwise # the existence of the x64 bits will cause us to think we are already done. # Note: This is only for the "regular" builds, the UWP builds have a separate project file entirely. ARM_CROSS_BUILD= -!IF "$(UWP)" == "" +!IF "$(UWP)" == "" && "$(NATIVE_ARM)" == "" !IF "$(CFG)" == "ARM\Release" || "$(CFG)" == "ARM\Debug" ARM_CROSS_BUILD=ARM ARM_CROSSBUILD_TS=$(ICUTMP)\$(ARM_CROSS_BUILD).timestamp @@ -185,6 +192,18 @@ CFGTOOLS=x64\Debug !IF "$(CFG)" == "x86\Release" || "$(CFG)" == "x86\Debug" PATH = $(ICUP)\bin;$(PATH) ICUPBIN=$(ICUP)\bin +# Use these path whether or not it's UWP build. +!ELSE IF "$(NATIVE_ARM)" != "" +!IF "$(CFG)" == "ARM\Release" || "$(CFG)" == "ARM\Debug" +PATH = $(ICUP)\binARM;$(PATH) +ICUPBIN=$(ICUP)\binARM +!ELSE IF "$(CFG)" == "ARM64\Release" || "$(CFG)" == "ARM64\Debug" +PATH = $(ICUP)\binARM64;$(PATH) +ICUPBIN=$(ICUP)\binARM64 +!ELSE +!ERROR Cross-build from ARM to x86 is not supported! +!ENDIF +# Build x86_64 or cross-build ARM !ELSE PATH = $(ICUP)\bin64;$(PATH) ICUPBIN=$(ICUP)\bin64 diff --git a/Build/source/libs/icu/icu-src/source/data/unidata/norm2/BUILD b/Build/source/libs/icu/icu-src/source/data/unidata/norm2/BUILD.bazel index 049e19bd41a..049e19bd41a 100644 --- a/Build/source/libs/icu/icu-src/source/data/unidata/norm2/BUILD +++ b/Build/source/libs/icu/icu-src/source/data/unidata/norm2/BUILD.bazel diff --git a/Build/source/libs/icu/icu-src/source/data/unidata/ucdterms.txt b/Build/source/libs/icu/icu-src/source/data/unidata/ucdterms.txt deleted file mode 100644 index 34ecc1bf9b5..00000000000 --- a/Build/source/libs/icu/icu-src/source/data/unidata/ucdterms.txt +++ /dev/null @@ -1,47 +0,0 @@ -UNICODE, INC. LICENSE AGREEMENT - DATA FILES AND SOFTWARE - -Unicode Data Files include all data files under the directories -http://www.unicode.org/Public/ and http://www.unicode.org/reports/. -Unicode Software includes any source code under the directories -http://www.unicode.org/Public/ and http://www.unicode.org/reports/. - -NOTICE TO USER: Carefully read the following legal agreement. BY DOWNLOADING, -INSTALLING, COPYING OR OTHERWISE USING UNICODE INC.'S DATA FILES ("DATA FILES"), -AND/OR SOFTWARE ("SOFTWARE"), YOU UNEQUIVOCALLY ACCEPT, AND AGREE TO BE BOUND -BY, ALL OF THE TERMS AND CONDITIONS OF THIS AGREEMENT. IF YOU DO NOT AGREE, -DO NOT DOWNLOAD, INSTALL, COPY, DISTRIBUTE OR USE THE DATA FILES OR SOFTWARE. - -COPYRIGHT AND PERMISSION NOTICE - -Copyright (C) 2016 and later: Unicode, Inc. and others. -License & terms of use: http://www.unicode.org/copyright.html -Copyright (c) 1991-2004 Unicode, Inc. All rights reserved. Distributed under the -Terms of Use in http://www.unicode.org/copyright.html. - -Permission is hereby granted, free of charge, to any person obtaining a copy of -the Unicode data files and associated documentation (the "Data Files") or -Unicode software and associated documentation (the "Software") to deal in the -Data Files or Software without restriction, including without limitation the -rights to use, copy, modify, merge, publish, distribute, and/or sell copies of -the Data Files or Software, and to permit persons to whom the Data Files or -Software are furnished to do so, provided that (a) the above copyright notice(s) -and this permission notice appear in all copies of the Data Files or Software, -(b) both the above copyright notice(s) and this permission notice appear in -associated documentation, and (c) there is clear notice in each modified Data -File or in the Software as well as in the documentation associated with the Data -File(s) or Software that the data or software has been modified. - -THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD -PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS -NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL -DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, -WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING -OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THE DATA FILES OR -SOFTWARE. - -Except as contained in this notice, the name of a copyright holder shall not be -used in advertising or otherwise to promote the sale, use or other dealings in -these Data Files or Software without prior written authorization of the -copyright holder. diff --git a/Build/source/libs/icu/icu-src/source/extra/uconv/makedata.mak b/Build/source/libs/icu/icu-src/source/extra/uconv/makedata.mak index b30f59728b5..81fcc908ee6 100644 --- a/Build/source/libs/icu/icu-src/source/extra/uconv/makedata.mak +++ b/Build/source/libs/icu/icu-src/source/extra/uconv/makedata.mak @@ -51,8 +51,16 @@ PKGMODE=static ICD=$(ICUDATA)^\ DATA_PATH=$(ICUP)\data^\ +NATIVE_ARM= +!IF "$(PROCESSOR_ARCHITECTURE)" == "ARM64" || "$(PROCESSOR_ARCHITEW6432)" == "ARM64" +NATIVE_ARM=ARM64 +!ELSE IF "$(PROCESSOR_ARCHITECTURE)" == "ARM" || "$(PROCESSOR_ARCHITEW6432)" == "ARM" +NATIVE_ARM=ARM +!ENDIF + # Use the x64 tools for building ARM and ARM64. # Note: This is similar to the TOOLS CFG PATH in source\data\makedata.mak +!IF "$(NATIVE_ARM)" == "" !IF "$(CFG)" == "x64\Release" || "$(CFG)" == "x64\Debug" || "$(CFG)" == "ARM\Release" || "$(CFG)" == "ARM\Debug" || "$(CFG)" == "ARM64\Release" || "$(CFG)" == "ARM64\Debug" ICUTOOLS=$(ICUP)\bin64 PATH = $(ICUP)\bin64;$(PATH) @@ -60,6 +68,15 @@ PATH = $(ICUP)\bin64;$(PATH) ICUTOOLS=$(ICUP)\bin PATH = $(ICUP)\bin;$(PATH) !ENDIF +!ELSE +!IF "$(CFG)" == "ARM\Release" || "$(CFG)" == "ARM\Debug" +ICUTOOLS=$(ICUP)\binARM +PATH = $(ICUP)\binARM;$(PATH) +!ELSE +ICUTOOLS=$(ICUP)\binARM64 +PATH = $(ICUP)\binARM64;$(PATH) +!ENDIF +!ENDIF # If building ARM/ARM, then we need to pass the arch as an argument. EXTRA_PKGDATA_ARGUMENTS= diff --git a/Build/source/libs/icu/icu-src/source/i18n/BUILD b/Build/source/libs/icu/icu-src/source/i18n/BUILD.bazel index 2d85cdb180e..2d85cdb180e 100644 --- a/Build/source/libs/icu/icu-src/source/i18n/BUILD +++ b/Build/source/libs/icu/icu-src/source/i18n/BUILD.bazel diff --git a/Build/source/libs/icu/icu-src/source/i18n/alphaindex.cpp b/Build/source/libs/icu/icu-src/source/i18n/alphaindex.cpp index 34407f677a6..88d63675a7c 100644 --- a/Build/source/libs/icu/icu-src/source/i18n/alphaindex.cpp +++ b/Build/source/libs/icu/icu-src/source/i18n/alphaindex.cpp @@ -451,12 +451,11 @@ BucketList *AlphabeticIndex::createBucketList(UErrorCode &errorCode) const { bucketList->setDeleter(uprv_deleteUObject); // underflow bucket - Bucket *bucket = new Bucket(getUnderflowLabel(), emptyString_, U_ALPHAINDEX_UNDERFLOW); - if (bucket == NULL) { - errorCode = U_MEMORY_ALLOCATION_ERROR; + LocalPointer<Bucket> bucket(new Bucket(getUnderflowLabel(), emptyString_, U_ALPHAINDEX_UNDERFLOW), errorCode); + if (U_FAILURE(errorCode)) { return NULL; } - bucketList->addElementX(bucket, errorCode); + bucketList->adoptElement(bucket.orphan(), errorCode); if (U_FAILURE(errorCode)) { return NULL; } UnicodeString temp; @@ -481,28 +480,24 @@ BucketList *AlphabeticIndex::createBucketList(UErrorCode &errorCode) const { if (skippedScript && bucketList->size() > 1) { // We are skipping one or more scripts, // and we are not just getting out of the underflow label. - bucket = new Bucket(getInflowLabel(), inflowBoundary, U_ALPHAINDEX_INFLOW); - if (bucket == NULL) { - errorCode = U_MEMORY_ALLOCATION_ERROR; - return NULL; - } - bucketList->addElementX(bucket, errorCode); + bucket.adoptInsteadAndCheckErrorCode( + new Bucket(getInflowLabel(), inflowBoundary, U_ALPHAINDEX_INFLOW), errorCode); + bucketList->adoptElement(bucket.orphan(), errorCode); + if (U_FAILURE(errorCode)) { return nullptr; } } } // Add a bucket with the current label. - bucket = new Bucket(fixLabel(current, temp), current, U_ALPHAINDEX_NORMAL); - if (bucket == NULL) { - errorCode = U_MEMORY_ALLOCATION_ERROR; - return NULL; - } - bucketList->addElementX(bucket, errorCode); + bucket.adoptInsteadAndCheckErrorCode( + new Bucket(fixLabel(current, temp), current, U_ALPHAINDEX_NORMAL), errorCode); + bucketList->adoptElement(bucket.orphan(), errorCode); + if (U_FAILURE(errorCode)) { return nullptr; } // Remember ASCII and Pinyin buckets for Pinyin redirects. UChar c; if (current.length() == 1 && 0x41 <= (c = current.charAt(0)) && c <= 0x5A) { // A-Z - asciiBuckets[c - 0x41] = bucket; + asciiBuckets[c - 0x41] = (Bucket *)bucketList->lastElement(); } else if (current.length() == BASE_LENGTH + 1 && current.startsWith(BASE, BASE_LENGTH) && 0x41 <= (c = current.charAt(BASE_LENGTH)) && c <= 0x5A) { - pinyinBuckets[c - 0x41] = bucket; + pinyinBuckets[c - 0x41] = (Bucket *)bucketList->lastElement(); hasPinyin = TRUE; } // Check for multiple primary weights. @@ -526,15 +521,16 @@ BucketList *AlphabeticIndex::createBucketList(UErrorCode &errorCode) const { // to the previous single-character bucket. // For example, after ... Q R S Sch we add Sch\uFFFF->S // and after ... Q R S Sch Sch\uFFFF St we add St\uFFFF->S. - bucket = new Bucket(emptyString_, + bucket.adoptInsteadAndCheckErrorCode(new Bucket(emptyString_, UnicodeString(current).append((UChar)0xFFFF), - U_ALPHAINDEX_NORMAL); - if (bucket == NULL) { - errorCode = U_MEMORY_ALLOCATION_ERROR; + U_ALPHAINDEX_NORMAL), + errorCode); + if (U_FAILURE(errorCode)) { return NULL; } bucket->displayBucket_ = singleBucket; - bucketList->addElementX(bucket, errorCode); + bucketList->adoptElement(bucket.orphan(), errorCode); + if (U_FAILURE(errorCode)) { return nullptr; } hasInvisibleBuckets = TRUE; break; } @@ -553,12 +549,10 @@ BucketList *AlphabeticIndex::createBucketList(UErrorCode &errorCode) const { return bl; } // overflow bucket - bucket = new Bucket(getOverflowLabel(), *scriptUpperBoundary, U_ALPHAINDEX_OVERFLOW); - if (bucket == NULL) { - errorCode = U_MEMORY_ALLOCATION_ERROR; - return NULL; - } - bucketList->addElementX(bucket, errorCode); // final + bucket.adoptInsteadAndCheckErrorCode( + new Bucket(getOverflowLabel(), *scriptUpperBoundary, U_ALPHAINDEX_OVERFLOW), errorCode); + bucketList->adoptElement(bucket.orphan(), errorCode); // final + if (U_FAILURE(errorCode)) { return nullptr; } if (hasPinyin) { // Redirect Pinyin buckets. @@ -589,7 +583,7 @@ BucketList *AlphabeticIndex::createBucketList(UErrorCode &errorCode) const { int32_t i = bucketList->size() - 1; Bucket *nextBucket = getBucket(*bucketList, i); while (--i > 0) { - bucket = getBucket(*bucketList, i); + Bucket *bucket = getBucket(*bucketList, i); if (bucket->displayBucket_ != NULL) { continue; // skip invisible buckets } @@ -609,9 +603,9 @@ BucketList *AlphabeticIndex::createBucketList(UErrorCode &errorCode) const { // Do not call publicBucketList->setDeleter(): // This vector shares its objects with the bucketList. for (int32_t j = 0; j < bucketList->size(); ++j) { - bucket = getBucket(*bucketList, j); + Bucket *bucket = getBucket(*bucketList, j); if (bucket->displayBucket_ == NULL) { - publicBucketList->addElementX(bucket, errorCode); + publicBucketList->addElement(bucket, errorCode); } } if (U_FAILURE(errorCode)) { return NULL; } @@ -679,13 +673,13 @@ void AlphabeticIndex::initBuckets(UErrorCode &errorCode) { bucket = bucket->displayBucket_; } if (bucket->records_ == NULL) { - bucket->records_ = new UVector(errorCode); - if (bucket->records_ == NULL) { - errorCode = U_MEMORY_ALLOCATION_ERROR; + LocalPointer<UVector> records(new UVector(errorCode), errorCode); + if (U_FAILURE(errorCode)) { return; } + bucket->records_ = records.orphan(); } - bucket->records_->addElementX(r, errorCode); + bucket->records_->addElement(r, errorCode); } } @@ -1011,12 +1005,11 @@ UVector *AlphabeticIndex::firstStringsInScript(UErrorCode &status) { // and the one for unassigned implicit weights (Cn). continue; } - UnicodeString *s = new UnicodeString(boundary); - if (s == NULL) { - status = U_MEMORY_ALLOCATION_ERROR; - return NULL; + LocalPointer<UnicodeString> s(new UnicodeString(boundary), status); + dest->adoptElement(s.orphan(), status); + if (U_FAILURE(status)) { + return nullptr; } - dest->addElementX(s, status); } return dest.orphan(); } @@ -1067,19 +1060,18 @@ AlphabeticIndex & AlphabeticIndex::addRecord(const UnicodeString &name, const vo return *this; } if (inputList_ == NULL) { - inputList_ = new UVector(status); - if (inputList_ == NULL) { - status = U_MEMORY_ALLOCATION_ERROR; + LocalPointer<UVector> inputList(new UVector(status), status); + if (U_FAILURE(status)) { return *this; } + inputList_ = inputList.orphan(); inputList_->setDeleter(alphaIndex_deleteRecord); } - Record *r = new Record(name, data); - if (r == NULL) { - status = U_MEMORY_ALLOCATION_ERROR; + LocalPointer<Record> r(new Record(name, data), status); + inputList_->adoptElement(r.orphan(), status); + if (U_FAILURE(status)) { return *this; } - inputList_->addElementX(r, status); clearBuckets(); //std::string ss; //std::string ss2; diff --git a/Build/source/libs/icu/icu-src/source/i18n/collationdatabuilder.cpp b/Build/source/libs/icu/icu-src/source/i18n/collationdatabuilder.cpp index 25050aa777e..b10de993c27 100644 --- a/Build/source/libs/icu/icu-src/source/i18n/collationdatabuilder.cpp +++ b/Build/source/libs/icu/icu-src/source/i18n/collationdatabuilder.cpp @@ -522,12 +522,11 @@ CollationDataBuilder::addConditionalCE32(const UnicodeString &context, uint32_t errorCode = U_BUFFER_OVERFLOW_ERROR; return -1; } - ConditionalCE32 *cond = new ConditionalCE32(context, ce32); - if(cond == NULL) { - errorCode = U_MEMORY_ALLOCATION_ERROR; + LocalPointer<ConditionalCE32> cond(new ConditionalCE32(context, ce32), errorCode); + conditionalCE32s.adoptElement(cond.orphan(), errorCode); + if(U_FAILURE(errorCode)) { return -1; } - conditionalCE32s.addElementX(cond, errorCode); return index; } diff --git a/Build/source/libs/icu/icu-src/source/i18n/csdetect.cpp b/Build/source/libs/icu/icu-src/source/i18n/csdetect.cpp index 84f0776542d..d866eb66286 100644 --- a/Build/source/libs/icu/icu-src/source/i18n/csdetect.cpp +++ b/Build/source/libs/icu/icu-src/source/i18n/csdetect.cpp @@ -270,6 +270,11 @@ const CharsetMatch * const *CharsetDetector::detectAll(int32_t &maxMatchesFound, maxMatchesFound = resultCount; + if (maxMatchesFound == 0) { + status = U_INVALID_CHAR_FOUND; + return NULL; + } + return resultArray; } diff --git a/Build/source/libs/icu/icu-src/source/i18n/double-conversion-ieee.h b/Build/source/libs/icu/icu-src/source/i18n/double-conversion-ieee.h index 31c35867de5..2940acb1698 100644 --- a/Build/source/libs/icu/icu-src/source/i18n/double-conversion-ieee.h +++ b/Build/source/libs/icu/icu-src/source/i18n/double-conversion-ieee.h @@ -164,11 +164,19 @@ class Double { } bool IsQuietNan() const { +#if (defined(__mips__) && !defined(__mips_nan2008)) || defined(__hppa__) + return IsNan() && ((AsUint64() & kQuietNanBit) == 0); +#else return IsNan() && ((AsUint64() & kQuietNanBit) != 0); +#endif } bool IsSignalingNan() const { +#if (defined(__mips__) && !defined(__mips_nan2008)) || defined(__hppa__) + return IsNan() && ((AsUint64() & kQuietNanBit) != 0); +#else return IsNan() && ((AsUint64() & kQuietNanBit) == 0); +#endif } @@ -250,7 +258,12 @@ class Double { private: static const int kDenormalExponent = -kExponentBias + 1; static const uint64_t kInfinity = DOUBLE_CONVERSION_UINT64_2PART_C(0x7FF00000, 00000000); +#if (defined(__mips__) && !defined(__mips_nan2008)) || defined(__hppa__) + static const uint64_t kNaN = DOUBLE_CONVERSION_UINT64_2PART_C(0x7FF7FFFF, FFFFFFFF); +#else static const uint64_t kNaN = DOUBLE_CONVERSION_UINT64_2PART_C(0x7FF80000, 00000000); +#endif + const uint64_t d64_; @@ -350,11 +363,19 @@ class Single { } bool IsQuietNan() const { +#if (defined(__mips__) && !defined(__mips_nan2008)) || defined(__hppa__) + return IsNan() && ((AsUint32() & kQuietNanBit) == 0); +#else return IsNan() && ((AsUint32() & kQuietNanBit) != 0); +#endif } bool IsSignalingNan() const { +#if (defined(__mips__) && !defined(__mips_nan2008)) || defined(__hppa__) + return IsNan() && ((AsUint32() & kQuietNanBit) != 0); +#else return IsNan() && ((AsUint32() & kQuietNanBit) == 0); +#endif } @@ -424,7 +445,11 @@ class Single { static const int kDenormalExponent = -kExponentBias + 1; static const int kMaxExponent = 0xFF - kExponentBias; static const uint32_t kInfinity = 0x7F800000; +#if (defined(__mips__) && !defined(__mips_nan2008)) || defined(__hppa__) + static const uint32_t kNaN = 0x7FBFFFFF; +#else static const uint32_t kNaN = 0x7FC00000; +#endif const uint32_t d32_; diff --git a/Build/source/libs/icu/icu-src/source/i18n/double-conversion-utils.h b/Build/source/libs/icu/icu-src/source/i18n/double-conversion-utils.h index 7f23e0a8250..11c92717c10 100644 --- a/Build/source/libs/icu/icu-src/source/i18n/double-conversion-utils.h +++ b/Build/source/libs/icu/icu-src/source/i18n/double-conversion-utils.h @@ -37,6 +37,9 @@ #ifndef DOUBLE_CONVERSION_UTILS_H_ #define DOUBLE_CONVERSION_UTILS_H_ +// Use DOUBLE_CONVERSION_NON_PREFIXED_MACROS to get unprefixed macros as was +// the case in double-conversion releases prior to 3.1.6 + #include <cstdlib> #include <cstring> @@ -46,9 +49,17 @@ #define DOUBLE_CONVERSION_ASSERT(condition) \ U_ASSERT(condition) #endif +#if defined(DOUBLE_CONVERSION_NON_PREFIXED_MACROS) && !defined(ASSERT) +#define ASSERT DOUBLE_CONVERSION_ASSERT +#endif + #ifndef DOUBLE_CONVERSION_UNIMPLEMENTED #define DOUBLE_CONVERSION_UNIMPLEMENTED() (abort()) #endif +#if defined(DOUBLE_CONVERSION_NON_PREFIXED_MACROS) && !defined(UNIMPLEMENTED) +#define UNIMPLEMENTED DOUBLE_CONVERSION_UNIMPLEMENTED +#endif + #ifndef DOUBLE_CONVERSION_NO_RETURN #ifdef _MSC_VER #define DOUBLE_CONVERSION_NO_RETURN __declspec(noreturn) @@ -56,6 +67,10 @@ #define DOUBLE_CONVERSION_NO_RETURN __attribute__((noreturn)) #endif #endif +#if defined(DOUBLE_CONVERSION_NON_PREFIXED_MACROS) && !defined(NO_RETURN) +#define NO_RETURN DOUBLE_CONVERSION_NO_RETURN +#endif + #ifndef DOUBLE_CONVERSION_UNREACHABLE #ifdef _MSC_VER void DOUBLE_CONVERSION_NO_RETURN abort_noreturn(); @@ -65,6 +80,9 @@ inline void abort_noreturn() { abort(); } #define DOUBLE_CONVERSION_UNREACHABLE() (abort()) #endif #endif +#if defined(DOUBLE_CONVERSION_NON_PREFIXED_MACROS) && !defined(UNREACHABLE) +#define UNREACHABLE DOUBLE_CONVERSION_UNREACHABLE +#endif // Not all compilers support __has_attribute and combining a check for both // ifdef and __has_attribute on the same preprocessor line isn't portable. @@ -81,12 +99,18 @@ inline void abort_noreturn() { abort(); } #define DOUBLE_CONVERSION_UNUSED #endif #endif +#if defined(DOUBLE_CONVERSION_NON_PREFIXED_MACROS) && !defined(UNUSED) +#define UNUSED DOUBLE_CONVERSION_UNUSED +#endif #if DOUBLE_CONVERSION_HAS_ATTRIBUTE(uninitialized) #define DOUBLE_CONVERSION_STACK_UNINITIALIZED __attribute__((uninitialized)) #else #define DOUBLE_CONVERSION_STACK_UNINITIALIZED #endif +#if defined(DOUBLE_CONVERSION_NON_PREFIXED_MACROS) && !defined(STACK_UNINITIALIZED) +#define STACK_UNINITIALIZED DOUBLE_CONVERSION_STACK_UNINITIALIZED +#endif // Double operations detection based on target architecture. // Linux uses a 80bit wide floating point stack on x86. This induces double @@ -127,7 +151,7 @@ int main(int argc, char** argv) { defined(_MIPS_ARCH_MIPS32R2) || defined(__ARMEB__) ||\ defined(__AARCH64EL__) || defined(__aarch64__) || defined(__AARCH64EB__) || \ defined(__riscv) || defined(__e2k__) || \ - defined(__or1k__) || defined(__arc__) || \ + defined(__or1k__) || defined(__arc__) || defined(__ARC64__) || \ defined(__microblaze__) || defined(__XTENSA__) || \ defined(__EMSCRIPTEN__) || defined(__wasm32__) #define DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS 1 @@ -144,6 +168,9 @@ int main(int argc, char** argv) { #else #error Target architecture was not detected as supported by Double-Conversion. #endif +#if defined(DOUBLE_CONVERSION_NON_PREFIXED_MACROS) && !defined(CORRECT_DOUBLE_OPERATIONS) +#define CORRECT_DOUBLE_OPERATIONS DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS +#endif #if defined(_WIN32) && !defined(__MINGW32__) @@ -169,7 +196,9 @@ typedef uint16_t uc16; // Usage: instead of writing 0x1234567890123456 // write DOUBLE_CONVERSION_UINT64_2PART_C(0x12345678,90123456); #define DOUBLE_CONVERSION_UINT64_2PART_C(a, b) (((static_cast<uint64_t>(a) << 32) + 0x##b##u)) - +#if defined(DOUBLE_CONVERSION_NON_PREFIXED_MACROS) && !defined(UINT64_2PART_C) +#define UINT64_2PART_C DOUBLE_CONVERSION_UINT64_2PART_C +#endif // The expression DOUBLE_CONVERSION_ARRAY_SIZE(a) is a compile-time constant of type // size_t which represents the number of elements of the given @@ -180,6 +209,9 @@ typedef uint16_t uc16; ((sizeof(a) / sizeof(*(a))) / \ static_cast<size_t>(!(sizeof(a) % sizeof(*(a))))) #endif +#if defined(DOUBLE_CONVERSION_NON_PREFIXED_MACROS) && !defined(ARRAY_SIZE) +#define ARRAY_SIZE DOUBLE_CONVERSION_ARRAY_SIZE +#endif // A macro to disallow the evil copy constructor and operator= functions // This should be used in the private: declarations for a class @@ -188,6 +220,9 @@ typedef uint16_t uc16; TypeName(const TypeName&); \ void operator=(const TypeName&) #endif +#if defined(DOUBLE_CONVERSION_NON_PREFIXED_MACROS) && !defined(DC_DISALLOW_COPY_AND_ASSIGN) +#define DC_DISALLOW_COPY_AND_ASSIGN DOUBLE_CONVERSION_DISALLOW_COPY_AND_ASSIGN +#endif // A macro to disallow all the implicit constructors, namely the // default constructor, copy constructor and operator= functions. @@ -200,6 +235,9 @@ typedef uint16_t uc16; TypeName(); \ DOUBLE_CONVERSION_DISALLOW_COPY_AND_ASSIGN(TypeName) #endif +#if defined(DOUBLE_CONVERSION_NON_PREFIXED_MACROS) && !defined(DC_DISALLOW_IMPLICIT_CONSTRUCTORS) +#define DC_DISALLOW_IMPLICIT_CONSTRUCTORS DOUBLE_CONVERSION_DISALLOW_IMPLICIT_CONSTRUCTORS +#endif // ICU PATCH: Wrap in ICU namespace U_NAMESPACE_BEGIN diff --git a/Build/source/libs/icu/icu-src/source/i18n/dtfmtsym.cpp b/Build/source/libs/icu/icu-src/source/i18n/dtfmtsym.cpp index ab5f2b612c1..134b919f06e 100644 --- a/Build/source/libs/icu/icu-src/source/i18n/dtfmtsym.cpp +++ b/Build/source/libs/icu/icu-src/source/i18n/dtfmtsym.cpp @@ -1574,26 +1574,20 @@ struct CalendarDataSink : public ResourceSink { errorCode); if (U_FAILURE(errorCode)) { return; } } - LocalPointer<UnicodeString> aliasRelativePathCopy(new UnicodeString(aliasRelativePath), errorCode); - resourcesToVisitNext->addElementX(aliasRelativePathCopy.getAlias(), errorCode); + LocalPointer<UnicodeString> aliasRelativePathCopy(aliasRelativePath.clone(), errorCode); + resourcesToVisitNext->adoptElement(aliasRelativePathCopy.orphan(), errorCode); if (U_FAILURE(errorCode)) { return; } - // Only release ownership after resourcesToVisitNext takes it (no error happened): - aliasRelativePathCopy.orphan(); continue; } else if (aliasType == SAME_CALENDAR) { // Register same-calendar alias if (arrays.get(aliasRelativePath) == NULL && maps.get(aliasRelativePath) == NULL) { - LocalPointer<UnicodeString> aliasRelativePathCopy(new UnicodeString(aliasRelativePath), errorCode); - aliasPathPairs.addElementX(aliasRelativePathCopy.getAlias(), errorCode); + LocalPointer<UnicodeString> aliasRelativePathCopy(aliasRelativePath.clone(), errorCode); + aliasPathPairs.adoptElement(aliasRelativePathCopy.orphan(), errorCode); if (U_FAILURE(errorCode)) { return; } - // Only release ownership after aliasPathPairs takes it (no error happened): - aliasRelativePathCopy.orphan(); - LocalPointer<UnicodeString> keyUStringCopy(new UnicodeString(keyUString), errorCode); - aliasPathPairs.addElementX(keyUStringCopy.getAlias(), errorCode); + LocalPointer<UnicodeString> keyUStringCopy(keyUString.clone(), errorCode); + aliasPathPairs.adoptElement(keyUStringCopy.orphan(), errorCode); if (U_FAILURE(errorCode)) { return; } - // Only release ownership after aliasPathPairs takes it (no error happened): - keyUStringCopy.orphan(); } continue; } @@ -1760,16 +1754,12 @@ struct CalendarDataSink : public ResourceSink { if (U_FAILURE(errorCode)) { return; } if (aliasType == SAME_CALENDAR) { // Store the alias path and the current path on aliasPathPairs - LocalPointer<UnicodeString> aliasRelativePathCopy(new UnicodeString(aliasRelativePath), errorCode); - aliasPathPairs.addElementX(aliasRelativePathCopy.getAlias(), errorCode); + LocalPointer<UnicodeString> aliasRelativePathCopy(aliasRelativePath.clone(), errorCode); + aliasPathPairs.adoptElement(aliasRelativePathCopy.orphan(), errorCode); if (U_FAILURE(errorCode)) { return; } - // Only release ownership after aliasPathPairs takes it (no error happened): - aliasRelativePathCopy.orphan(); - LocalPointer<UnicodeString> pathCopy(new UnicodeString(path), errorCode); - aliasPathPairs.addElementX(pathCopy.getAlias(), errorCode); + LocalPointer<UnicodeString> pathCopy(path.clone(), errorCode); + aliasPathPairs.adoptElement(pathCopy.orphan(), errorCode); if (U_FAILURE(errorCode)) { return; } - // Only release ownership after aliasPathPairs takes it (no error happened): - pathCopy.orphan(); // Drop the latest key on the path and continue path.retainBetween(0, pathLength); diff --git a/Build/source/libs/icu/icu-src/source/i18n/dtitvfmt.cpp b/Build/source/libs/icu/icu-src/source/i18n/dtitvfmt.cpp index 298fb62be0c..d51ddcd5c70 100644 --- a/Build/source/libs/icu/icu-src/source/i18n/dtitvfmt.cpp +++ b/Build/source/libs/icu/icu-src/source/i18n/dtitvfmt.cpp @@ -965,16 +965,22 @@ DateIntervalFormat::normalizeHourMetacharacters(const UnicodeString& skeleton) c UnicodeString result = skeleton; UChar hourMetachar = u'\0'; + UChar dayPeriodChar = u'\0'; int32_t metacharStart = 0; int32_t metacharCount = 0; for (int32_t i = 0; i < result.length(); i++) { UChar c = result[i]; - if (c == LOW_J || c == CAP_J || c == CAP_C) { + if (c == LOW_J || c == CAP_J || c == CAP_C || c == LOW_H || c == CAP_H || c == LOW_K || c == CAP_K) { if (hourMetachar == u'\0') { hourMetachar = c; metacharStart = i; } ++metacharCount; + } else if (c == LOW_A || c == LOW_B || c == CAP_B) { + if (dayPeriodChar == u'\0') { + dayPeriodChar = c; + } + ++metacharCount; } else { if (hourMetachar != u'\0') { break; @@ -985,7 +991,6 @@ DateIntervalFormat::normalizeHourMetacharacters(const UnicodeString& skeleton) c if (hourMetachar != u'\0') { UErrorCode err = U_ZERO_ERROR; UChar hourChar = CAP_H; - UChar dayPeriodChar = LOW_A; UnicodeString convertedPattern = DateFormat::getBestPattern(fLocale, UnicodeString(hourMetachar), err); if (U_SUCCESS(err)) { @@ -1012,6 +1017,8 @@ DateIntervalFormat::normalizeHourMetacharacters(const UnicodeString& skeleton) c dayPeriodChar = LOW_B; } else if (convertedPattern.indexOf(CAP_B) != -1) { dayPeriodChar = CAP_B; + } else if (dayPeriodChar == u'\0') { + dayPeriodChar = LOW_A; } } diff --git a/Build/source/libs/icu/icu-src/source/i18n/dtptngen.cpp b/Build/source/libs/icu/icu-src/source/i18n/dtptngen.cpp index 6aee1750f90..e781c6e26f5 100644 --- a/Build/source/libs/icu/icu-src/source/i18n/dtptngen.cpp +++ b/Build/source/libs/icu/icu-src/source/i18n/dtptngen.cpp @@ -273,8 +273,6 @@ static const char* const CLDR_FIELD_WIDTH[] = { // [UDATPG_WIDTH_COUNT] "", "-short", "-narrow" }; -// TODO(ticket:13619): remove when definition uncommented in dtptngen.h. -static const int32_t UDATPG_WIDTH_COUNT = UDATPG_NARROW + 1; static constexpr UDateTimePGDisplayWidth UDATPG_WIDTH_APPENDITEM = UDATPG_WIDE; static constexpr int32_t UDATPG_FIELD_KEY_MAX = 24; // max length of CLDR field tag (type + width) @@ -393,10 +391,13 @@ DateTimePatternGenerator::operator=(const DateTimePatternGenerator& other) { *fp = *(other.fp); dtMatcher->copyFrom(other.dtMatcher->skeleton); *distanceInfo = *(other.distanceInfo); - dateTimeFormat = other.dateTimeFormat; + for (int32_t style = UDAT_FULL; style <= UDAT_SHORT; style++) { + dateTimeFormat[style] = other.dateTimeFormat[style]; + } decimal = other.decimal; - // NUL-terminate for the C API. - dateTimeFormat.getTerminatedBuffer(); + for (int32_t style = UDAT_FULL; style <= UDAT_SHORT; style++) { + dateTimeFormat[style].getTerminatedBuffer(); // NUL-terminate for the C API. + } decimal.getTerminatedBuffer(); delete skipMatcher; if ( other.skipMatcher == nullptr ) { @@ -430,7 +431,12 @@ DateTimePatternGenerator::operator==(const DateTimePatternGenerator& other) cons return true; } if ((pLocale==other.pLocale) && (patternMap->equals(*other.patternMap)) && - (dateTimeFormat==other.dateTimeFormat) && (decimal==other.decimal)) { + (decimal==other.decimal)) { + for (int32_t style = UDAT_FULL; style <= UDAT_SHORT; style++) { + if (dateTimeFormat[style] != other.dateTimeFormat[style]) { + return false; + } + } for ( int32_t i=0 ; i<UDATPG_FIELD_COUNT; ++i ) { if (appendItemFormats[i] != other.appendItemFormats[i]) { return false; @@ -1199,7 +1205,21 @@ DateTimePatternGenerator::getBestPattern(const UnicodeString& patternForm, UDate } resultPattern.remove(); status = U_ZERO_ERROR; - dtFormat=getDateTimeFormat(); + // determine which dateTimeFormat to use + PtnSkeleton* reqSkeleton = dtMatcher->getSkeletonPtr(); + UDateFormatStyle style = UDAT_SHORT; + int32_t monthFieldLen = reqSkeleton->baseOriginal.getFieldLength(UDATPG_MONTH_FIELD); + if (monthFieldLen == 4) { + if (reqSkeleton->baseOriginal.getFieldLength(UDATPG_WEEKDAY_FIELD) > 0) { + style = UDAT_FULL; + } else { + style = UDAT_LONG; + } + } else if (monthFieldLen == 3) { + style = UDAT_MEDIUM; + } + // and now use it to compose date and time + dtFormat=getDateTimeFormat(style, status); SimpleFormatter(dtFormat, 2, 2, status).format(timePattern, datePattern, resultPattern, status); return resultPattern; } @@ -1335,14 +1355,45 @@ DateTimePatternGenerator::addCanonicalItems(UErrorCode& status) { void DateTimePatternGenerator::setDateTimeFormat(const UnicodeString& dtFormat) { - dateTimeFormat = dtFormat; - // NUL-terminate for the C API. - dateTimeFormat.getTerminatedBuffer(); + UErrorCode status = U_ZERO_ERROR; + for (int32_t style = UDAT_FULL; style <= UDAT_SHORT; style++) { + setDateTimeFormat((UDateFormatStyle)style, dtFormat, status); + } } const UnicodeString& DateTimePatternGenerator::getDateTimeFormat() const { - return dateTimeFormat; + UErrorCode status = U_ZERO_ERROR; + return getDateTimeFormat(UDAT_MEDIUM, status); +} + +void +DateTimePatternGenerator::setDateTimeFormat(UDateFormatStyle style, const UnicodeString& dtFormat, UErrorCode& status) { + if (U_FAILURE(status)) { + return; + } + if (style < UDAT_FULL || style > UDAT_SHORT) { + status = U_ILLEGAL_ARGUMENT_ERROR; + return; + } + dateTimeFormat[style] = dtFormat; + // Note for the following: getTerminatedBuffer() can re-allocate the UnicodeString + // buffer so we do this here before clients request a const ref to the UnicodeString + // or its buffer. + dateTimeFormat[style].getTerminatedBuffer(); // NUL-terminate for the C API. +} + +const UnicodeString& +DateTimePatternGenerator::getDateTimeFormat(UDateFormatStyle style, UErrorCode& status) const { + static const UnicodeString emptyString = UNICODE_STRING_SIMPLE(""); + if (U_FAILURE(status)) { + return emptyString; + } + if (style < UDAT_FULL || style > UDAT_SHORT) { + status = U_ILLEGAL_ARGUMENT_ERROR; + return emptyString; + } + return dateTimeFormat[style]; } void @@ -1378,13 +1429,15 @@ DateTimePatternGenerator::setDateTimeFromCalendar(const Locale& locale, UErrorCo } if (U_FAILURE(status)) { return; } - if (ures_getSize(dateTimePatterns.getAlias()) <= DateFormat::kDateTime) + if (ures_getSize(dateTimePatterns.getAlias()) <= DateFormat::kDateTimeOffset + DateFormat::kShort) { status = U_INVALID_FORMAT_ERROR; return; } - resStr = ures_getStringByIndex(dateTimePatterns.getAlias(), (int32_t)DateFormat::kDateTime, &resStrLen, &status); - setDateTimeFormat(UnicodeString(TRUE, resStr, resStrLen)); + for (int32_t style = UDAT_FULL; style <= UDAT_SHORT; style++) { + resStr = ures_getStringByIndex(dateTimePatterns.getAlias(), (int32_t)DateFormat::kDateTimeOffset + style, &resStrLen, &status); + setDateTimeFormat((UDateFormatStyle)style, UnicodeString(TRUE, resStr, resStrLen), status); + } } void @@ -2788,16 +2841,17 @@ DTSkeletonEnumeration::DTSkeletonEnumeration(PatternMap& patternMap, dtStrEnum t break; } if ( !isCanonicalItem(s) ) { - LocalPointer<UnicodeString> newElem(new UnicodeString(s), status); + LocalPointer<UnicodeString> newElem(s.clone(), status); if (U_FAILURE(status)) { return; } - fSkeletons->addElementX(newElem.getAlias(), status); + fSkeletons->addElement(newElem.getAlias(), status); if (U_FAILURE(status)) { fSkeletons.adoptInstead(nullptr); return; } - newElem.orphan(); // fSkeletons vector now owns the UnicodeString. + newElem.orphan(); // fSkeletons vector now owns the UnicodeString (although it + // does not use a deleter function to manage the ownership). } curElem = curElem->next.getAlias(); } @@ -2865,12 +2919,13 @@ DTRedundantEnumeration::add(const UnicodeString& pattern, UErrorCode& status) { if (U_FAILURE(status)) { return; } - fPatterns->addElementX(newElem.getAlias(), status); + fPatterns->addElement(newElem.getAlias(), status); if (U_FAILURE(status)) { fPatterns.adoptInstead(nullptr); return; } - newElem.orphan(); // fPatterns now owns the string. + newElem.orphan(); // fPatterns now owns the string, although a UVector + // deleter function is not used to manage that ownership. } const UnicodeString* diff --git a/Build/source/libs/icu/icu-src/source/i18n/formattedval_sbimpl.cpp b/Build/source/libs/icu/icu-src/source/i18n/formattedval_sbimpl.cpp index 70ffacac4b7..72197cdd8c7 100644 --- a/Build/source/libs/icu/icu-src/source/i18n/formattedval_sbimpl.cpp +++ b/Build/source/libs/icu/icu-src/source/i18n/formattedval_sbimpl.cpp @@ -230,6 +230,11 @@ bool FormattedValueStringBuilderImpl::nextPositionImpl(ConstrainedFieldPosition& if (si + 1 < spanIndicesCount) { nextSpanStart = spanIndices[si + 1].start; } + if (length == 0) { + // ICU-21871: Don't return fields on empty spans + i--; + continue; + } if (cfpos.matchesField(spanCategory, spanValue)) { fieldStart = i - fString.fZero; int32_t end = fieldStart + length; diff --git a/Build/source/libs/icu/icu-src/source/i18n/i18n.vcxproj b/Build/source/libs/icu/icu-src/source/i18n/i18n.vcxproj index 3471cf3e55d..23b8527cf0e 100644 --- a/Build/source/libs/icu/icu-src/source/i18n/i18n.vcxproj +++ b/Build/source/libs/icu/icu-src/source/i18n/i18n.vcxproj @@ -60,7 +60,7 @@ </ClCompile> <Link> <AdditionalDependencies>icuucd.lib;%(AdditionalDependencies)</AdditionalDependencies> - <OutputFile>..\..\$(IcuBinOutputDir)\icuin70d.dll</OutputFile> + <OutputFile>..\..\$(IcuBinOutputDir)\icuin71d.dll</OutputFile> <ProgramDatabaseFile>.\..\..\$(IcuLibOutputDir)\icuind.pdb</ProgramDatabaseFile> <ImportLibrary>..\..\$(IcuLibOutputDir)\icuind.lib</ImportLibrary> </Link> @@ -73,7 +73,7 @@ </ClCompile> <Link> <AdditionalDependencies>icuuc.lib;%(AdditionalDependencies)</AdditionalDependencies> - <OutputFile>..\..\$(IcuBinOutputDir)\icuin70.dll</OutputFile> + <OutputFile>..\..\$(IcuBinOutputDir)\icuin71.dll</OutputFile> <ProgramDatabaseFile>.\..\..\$(IcuLibOutputDir)\icuin.pdb</ProgramDatabaseFile> <ImportLibrary>..\..\$(IcuLibOutputDir)\icuin.lib</ImportLibrary> </Link> diff --git a/Build/source/libs/icu/icu-src/source/i18n/i18n_uwp.vcxproj b/Build/source/libs/icu/icu-src/source/i18n/i18n_uwp.vcxproj index c7358d72e59..ca0f335927b 100644 --- a/Build/source/libs/icu/icu-src/source/i18n/i18n_uwp.vcxproj +++ b/Build/source/libs/icu/icu-src/source/i18n/i18n_uwp.vcxproj @@ -186,7 +186,7 @@ <ProgramDataBaseFileName>.\x86\ReleaseUWP/</ProgramDataBaseFileName> </ClCompile> <Link> - <OutputFile>..\..\bin32uwp\icuin70.dll</OutputFile> + <OutputFile>..\..\bin32uwp\icuin71.dll</OutputFile> <ProgramDatabaseFile>.\..\..\lib32uwp\icuin.pdb</ProgramDatabaseFile> <ImportLibrary>..\..\lib32uwp\icuin.lib</ImportLibrary> <AdditionalDependencies>..\..\lib32uwp\icuuc.lib;%(AdditionalDependencies)</AdditionalDependencies> @@ -203,7 +203,7 @@ <ProgramDataBaseFileName>.\x86\DebugUWP/</ProgramDataBaseFileName> </ClCompile> <Link> - <OutputFile>..\..\bin32uwp\icuin70d.dll</OutputFile> + <OutputFile>..\..\bin32uwp\icuin71d.dll</OutputFile> <ProgramDatabaseFile>.\..\..\lib32uwp\icuind.pdb</ProgramDatabaseFile> <ImportLibrary>..\..\lib32uwp\icuind.lib</ImportLibrary> <AdditionalDependencies>..\..\lib32uwp\icuucd.lib;%(AdditionalDependencies)</AdditionalDependencies> @@ -220,7 +220,7 @@ <ProgramDataBaseFileName>.\x64\ReleaseUWP/</ProgramDataBaseFileName> </ClCompile> <Link> - <OutputFile>..\..\bin64uwp\icuin70.dll</OutputFile> + <OutputFile>..\..\bin64uwp\icuin71.dll</OutputFile> <ProgramDatabaseFile>.\..\..\lib64uwp\icuin.pdb</ProgramDatabaseFile> <ImportLibrary>..\..\lib64uwp\icuin.lib</ImportLibrary> <AdditionalDependencies>..\..\lib64uwp\icuuc.lib;%(AdditionalDependencies)</AdditionalDependencies> @@ -237,7 +237,7 @@ <ProgramDataBaseFileName>.\x64\DebugUWP/</ProgramDataBaseFileName> </ClCompile> <Link> - <OutputFile>..\..\bin64uwp\icuin70d.dll</OutputFile> + <OutputFile>..\..\bin64uwp\icuin71d.dll</OutputFile> <ProgramDatabaseFile>.\..\..\lib64uwp\icuind.pdb</ProgramDatabaseFile> <ImportLibrary>..\..\lib64uwp\icuind.lib</ImportLibrary> <AdditionalDependencies>..\..\lib64uwp\icuucd.lib;%(AdditionalDependencies)</AdditionalDependencies> @@ -254,7 +254,7 @@ <ProgramDataBaseFileName>.\ARM\ReleaseUWP/</ProgramDataBaseFileName> </ClCompile> <Link> - <OutputFile>..\..\binARMuwp\icuin70.dll</OutputFile> + <OutputFile>..\..\binARMuwp\icuin71.dll</OutputFile> <ProgramDatabaseFile>.\..\..\libARMuwp\icuin.pdb</ProgramDatabaseFile> <ImportLibrary>..\..\libARMuwp\icuin.lib</ImportLibrary> <AdditionalDependencies>..\..\libARMuwp\icuuc.lib;%(AdditionalDependencies)</AdditionalDependencies> @@ -271,7 +271,7 @@ <ProgramDataBaseFileName>.\ARM\DebugUWP/</ProgramDataBaseFileName> </ClCompile> <Link> - <OutputFile>..\..\binARMuwp\icuin70d.dll</OutputFile> + <OutputFile>..\..\binARMuwp\icuin71d.dll</OutputFile> <ProgramDatabaseFile>.\..\..\libARMuwp\icuind.pdb</ProgramDatabaseFile> <ImportLibrary>..\..\libARMuwp\icuind.lib</ImportLibrary> <AdditionalDependencies>..\..\libARMuwp\icuucd.lib;%(AdditionalDependencies)</AdditionalDependencies> @@ -288,7 +288,7 @@ <ProgramDataBaseFileName>.\ARM64\ReleaseUWP/</ProgramDataBaseFileName> </ClCompile> <Link> - <OutputFile>..\..\binARM64uwp\icuin70.dll</OutputFile> + <OutputFile>..\..\binARM64uwp\icuin71.dll</OutputFile> <ProgramDatabaseFile>.\..\..\libARM64uwp\icuin.pdb</ProgramDatabaseFile> <ImportLibrary>..\..\libARM64uwp\icuin.lib</ImportLibrary> <AdditionalDependencies>..\..\libARM64uwp\icuuc.lib;%(AdditionalDependencies)</AdditionalDependencies> @@ -305,7 +305,7 @@ <ProgramDataBaseFileName>.\ARM64\DebugUWP/</ProgramDataBaseFileName> </ClCompile> <Link> - <OutputFile>..\..\binARM64uwp\icuin70d.dll</OutputFile> + <OutputFile>..\..\binARM64uwp\icuin71d.dll</OutputFile> <ProgramDatabaseFile>.\..\..\libARM64uwp\icuind.pdb</ProgramDatabaseFile> <ImportLibrary>..\..\libARM64uwp\icuind.lib</ImportLibrary> <AdditionalDependencies>..\..\libARM64uwp\icuucd.lib;%(AdditionalDependencies)</AdditionalDependencies> diff --git a/Build/source/libs/icu/icu-src/source/i18n/measunit_extra.cpp b/Build/source/libs/icu/icu-src/source/i18n/measunit_extra.cpp index 82811190079..2df9edee96a 100644 --- a/Build/source/libs/icu/icu-src/source/i18n/measunit_extra.cpp +++ b/Build/source/libs/icu/icu-src/source/i18n/measunit_extra.cpp @@ -615,7 +615,7 @@ private: // Set to true when we've seen a "-per-" or a "per-", after which all units // are in the denominator. Until we find an "-and-", at which point the - // identifier is invalid pending TODO(CLDR-13700). + // identifier is invalid pending TODO(CLDR-13701). bool fAfterPer = false; Parser() : fSource(""), fTrie(u"") {} @@ -669,7 +669,7 @@ private: * dimensionality. * * Returns an error if we parse both compound units and "-and-", since mixed - * compound units are not yet supported - TODO(CLDR-13700). + * compound units are not yet supported - TODO(CLDR-13701). * * @param result Will be overwritten by the result, if status shows success. * @param sawAnd If an "-and-" was parsed prior to finding the "single diff --git a/Build/source/libs/icu/icu-src/source/i18n/msgfmt.cpp b/Build/source/libs/icu/icu-src/source/i18n/msgfmt.cpp index b8cb2e2ca56..13a5a089516 100644 --- a/Build/source/libs/icu/icu-src/source/i18n/msgfmt.cpp +++ b/Build/source/libs/icu/icu-src/source/i18n/msgfmt.cpp @@ -854,19 +854,21 @@ StringEnumeration* MessageFormat::getFormatNames(UErrorCode& status) { if (U_FAILURE(status)) return NULL; - UVector *fFormatNames = new UVector(status); + LocalPointer<UVector> formatNames(new UVector(status), status); if (U_FAILURE(status)) { - status = U_MEMORY_ALLOCATION_ERROR; - return NULL; + return nullptr; } - fFormatNames->setDeleter(uprv_deleteUObject); + formatNames->setDeleter(uprv_deleteUObject); for (int32_t partIndex = 0; (partIndex = nextTopLevelArgStart(partIndex)) >= 0;) { - fFormatNames->addElementX(new UnicodeString(getArgName(partIndex + 1)), status); + LocalPointer<UnicodeString> name(getArgName(partIndex + 1).clone(), status); + formatNames->adoptElement(name.orphan(), status); + if (U_FAILURE(status)) return nullptr; } - StringEnumeration* nameEnumerator = new FormatNameEnumeration(fFormatNames, status); - return nameEnumerator; + LocalPointer<StringEnumeration> nameEnumerator( + new FormatNameEnumeration(std::move(formatNames), status), status); + return U_SUCCESS(status) ? nameEnumerator.orphan() : nullptr; } // ------------------------------------- @@ -1912,9 +1914,9 @@ void MessageFormat::DummyFormat::parseObject(const UnicodeString&, } -FormatNameEnumeration::FormatNameEnumeration(UVector *fNameList, UErrorCode& /*status*/) { +FormatNameEnumeration::FormatNameEnumeration(LocalPointer<UVector> nameList, UErrorCode& /*status*/) { pos=0; - fFormatNames = fNameList; + fFormatNames = std::move(nameList); } const UnicodeString* @@ -1936,7 +1938,6 @@ FormatNameEnumeration::count(UErrorCode& /*status*/) const { } FormatNameEnumeration::~FormatNameEnumeration() { - delete fFormatNames; } MessageFormat::PluralSelectorProvider::PluralSelectorProvider(const MessageFormat &mf, UPluralType t) diff --git a/Build/source/libs/icu/icu-src/source/i18n/msgfmt_impl.h b/Build/source/libs/icu/icu-src/source/i18n/msgfmt_impl.h index 57988389132..80cb8a691eb 100644 --- a/Build/source/libs/icu/icu-src/source/i18n/msgfmt_impl.h +++ b/Build/source/libs/icu/icu-src/source/i18n/msgfmt_impl.h @@ -26,7 +26,7 @@ U_NAMESPACE_BEGIN class FormatNameEnumeration : public StringEnumeration { public: - FormatNameEnumeration(UVector *fFormatNames, UErrorCode& status); + FormatNameEnumeration(LocalPointer<UVector> fFormatNames, UErrorCode& status); virtual ~FormatNameEnumeration(); static UClassID U_EXPORT2 getStaticClassID(void); virtual UClassID getDynamicClassID(void) const override; @@ -35,7 +35,7 @@ public: virtual int32_t count(UErrorCode& status) const override; private: int32_t pos; - UVector *fFormatNames; + LocalPointer<UVector> fFormatNames; }; U_NAMESPACE_END diff --git a/Build/source/libs/icu/icu-src/source/i18n/number_affixutils.cpp b/Build/source/libs/icu/icu-src/source/i18n/number_affixutils.cpp index f9c154c885c..5f5ff4c3a63 100644 --- a/Build/source/libs/icu/icu-src/source/i18n/number_affixutils.cpp +++ b/Build/source/libs/icu/icu-src/source/i18n/number_affixutils.cpp @@ -135,8 +135,7 @@ Field AffixUtils::getFieldForType(AffixPatternType type) { case TYPE_PLUS_SIGN: return {UFIELD_CATEGORY_NUMBER, UNUM_SIGN_FIELD}; case TYPE_APPROXIMATELY_SIGN: - // TODO: Introduce a new field for the approximately sign? - return {UFIELD_CATEGORY_NUMBER, UNUM_SIGN_FIELD}; + return {UFIELD_CATEGORY_NUMBER, UNUM_APPROXIMATELY_SIGN_FIELD}; case TYPE_PERCENT: return {UFIELD_CATEGORY_NUMBER, UNUM_PERCENT_FIELD}; case TYPE_PERMILLE: diff --git a/Build/source/libs/icu/icu-src/source/i18n/number_compact.cpp b/Build/source/libs/icu/icu-src/source/i18n/number_compact.cpp index 62692f444df..60cd7bedf66 100644 --- a/Build/source/libs/icu/icu-src/source/i18n/number_compact.cpp +++ b/Build/source/libs/icu/icu-src/source/i18n/number_compact.cpp @@ -157,8 +157,8 @@ void CompactData::getUniquePatterns(UVector &output, UErrorCode &status) const { } // The string was not found; add it to the UVector. - // ANDY: This requires a const_cast. Why? - output.addElementX(const_cast<UChar *>(pattern), status); + // Note: must cast off const from pattern to store it in a UVector, which expects (void *) + output.addElement(const_cast<UChar *>(pattern), status); continue_outer: continue; diff --git a/Build/source/libs/icu/icu-src/source/i18n/number_decimalquantity.cpp b/Build/source/libs/icu/icu-src/source/i18n/number_decimalquantity.cpp index 6a2847b1c18..b40e1276c35 100644 --- a/Build/source/libs/icu/icu-src/source/i18n/number_decimalquantity.cpp +++ b/Build/source/libs/icu/icu-src/source/i18n/number_decimalquantity.cpp @@ -181,20 +181,22 @@ uint64_t DecimalQuantity::getPositionFingerprint() const { return fingerprint; } -void DecimalQuantity::roundToIncrement(double roundingIncrement, RoundingMode roundingMode, - UErrorCode& status) { +void DecimalQuantity::roundToIncrement( + uint64_t increment, + digits_t magnitude, + RoundingMode roundingMode, + UErrorCode& status) { // Do not call this method with an increment having only a 1 or a 5 digit! // Use a more efficient call to either roundToMagnitude() or roundToNickel(). // Check a few popular rounding increments; a more thorough check is in Java. - U_ASSERT(roundingIncrement != 0.01); - U_ASSERT(roundingIncrement != 0.05); - U_ASSERT(roundingIncrement != 0.1); - U_ASSERT(roundingIncrement != 0.5); - U_ASSERT(roundingIncrement != 1); - U_ASSERT(roundingIncrement != 5); + U_ASSERT(increment != 1); + U_ASSERT(increment != 5); + DecimalQuantity incrementDQ; + incrementDQ.setToLong(increment); + incrementDQ.adjustMagnitude(magnitude); DecNum incrementDN; - incrementDN.setTo(roundingIncrement, status); + incrementDQ.toDecNum(incrementDN, status); if (U_FAILURE(status)) { return; } // Divide this DecimalQuantity by the increment, round, then multiply back. @@ -254,6 +256,12 @@ bool DecimalQuantity::adjustMagnitude(int32_t delta) { return false; } +int32_t DecimalQuantity::adjustToZeroScale() { + int32_t retval = scale; + scale = 0; + return retval; +} + double DecimalQuantity::getPluralOperand(PluralOperand operand) const { // If this assertion fails, you need to call roundToInfinity() or some other rounding method. // See the comment at the top of this file explaining the "isApproximate" field. @@ -549,6 +557,65 @@ void DecimalQuantity::_setToDecNum(const DecNum& decnum, UErrorCode& status) { } } +DecimalQuantity DecimalQuantity::fromExponentString(UnicodeString num, UErrorCode& status) { + if (num.indexOf(u'e') >= 0 || num.indexOf(u'c') >= 0 + || num.indexOf(u'E') >= 0 || num.indexOf(u'C') >= 0) { + int32_t ePos = num.lastIndexOf('e'); + if (ePos < 0) { + ePos = num.lastIndexOf('c'); + } + if (ePos < 0) { + ePos = num.lastIndexOf('E'); + } + if (ePos < 0) { + ePos = num.lastIndexOf('C'); + } + int32_t expNumPos = ePos + 1; + UnicodeString exponentStr = num.tempSubString(expNumPos, num.length() - expNumPos); + + // parse exponentStr into exponent, but note that parseAsciiInteger doesn't handle the minus sign + bool isExpStrNeg = num[expNumPos] == u'-'; + int32_t exponentParsePos = isExpStrNeg ? 1 : 0; + int32_t exponent = ICU_Utility::parseAsciiInteger(exponentStr, exponentParsePos); + exponent = isExpStrNeg ? -exponent : exponent; + + // Compute the decNumber representation + UnicodeString fractionStr = num.tempSubString(0, ePos); + CharString fracCharStr = CharString(); + fracCharStr.appendInvariantChars(fractionStr, status); + DecNum decnum; + decnum.setTo(fracCharStr.toStringPiece(), status); + + // Clear and set this DecimalQuantity instance + DecimalQuantity dq; + dq.setToDecNum(decnum, status); + int32_t numFracDigit = getVisibleFractionCount(fractionStr); + dq.setMinFraction(numFracDigit); + dq.adjustExponent(exponent); + + return dq; + } else { + DecimalQuantity dq; + int numFracDigit = getVisibleFractionCount(num); + + CharString numCharStr = CharString(); + numCharStr.appendInvariantChars(num, status); + dq.setToDecNumber(numCharStr.toStringPiece(), status); + + dq.setMinFraction(numFracDigit); + return dq; + } +} + +int32_t DecimalQuantity::getVisibleFractionCount(UnicodeString value) { + int decimalPos = value.indexOf('.') + 1; + if (decimalPos == 0) { + return 0; + } else { + return value.length() - decimalPos; + } +} + int64_t DecimalQuantity::toLong(bool truncateIfOverflow) const { // NOTE: Call sites should be guarded by fitsInLong(), like this: // if (dq.fitsInLong()) { /* use dq.toLong() */ } else { /* use some fallback */ } @@ -948,6 +1015,44 @@ UnicodeString DecimalQuantity::toPlainString() const { return sb; } + +UnicodeString DecimalQuantity::toExponentString() const { + U_ASSERT(!isApproximate); + UnicodeString sb; + if (isNegative()) { + sb.append(u'-'); + } + + int32_t upper = scale + precision - 1; + int32_t lower = scale; + if (upper < lReqPos - 1) { + upper = lReqPos - 1; + } + if (lower > rReqPos) { + lower = rReqPos; + } + int32_t p = upper; + if (p < 0) { + sb.append(u'0'); + } + for (; p >= 0; p--) { + sb.append(u'0' + getDigitPos(p - scale)); + } + if (lower < 0) { + sb.append(u'.'); + } + for(; p >= lower; p--) { + sb.append(u'0' + getDigitPos(p - scale)); + } + + if (exponent != 0) { + sb.append(u'c'); + ICU_Utility::appendNumber(sb, exponent); + } + + return sb; +} + UnicodeString DecimalQuantity::toScientificString() const { U_ASSERT(!isApproximate); UnicodeString result; diff --git a/Build/source/libs/icu/icu-src/source/i18n/number_decimalquantity.h b/Build/source/libs/icu/icu-src/source/i18n/number_decimalquantity.h index 107c09a96a5..862addf5d6c 100644 --- a/Build/source/libs/icu/icu-src/source/i18n/number_decimalquantity.h +++ b/Build/source/libs/icu/icu-src/source/i18n/number_decimalquantity.h @@ -81,11 +81,15 @@ class U_I18N_API DecimalQuantity : public IFixedDecimal, public UMemory { * * <p>If rounding to a power of ten, use the more efficient {@link #roundToMagnitude} instead. * - * @param roundingIncrement The increment to which to round. + * @param increment The increment to which to round. + * @param magnitude The power of 10 to which to round. * @param roundingMode The {@link RoundingMode} to use if rounding is necessary. */ - void roundToIncrement(double roundingIncrement, RoundingMode roundingMode, - UErrorCode& status); + void roundToIncrement( + uint64_t increment, + digits_t magnitude, + RoundingMode roundingMode, + UErrorCode& status); /** Removes all fraction digits. */ void truncate(); @@ -141,6 +145,13 @@ class U_I18N_API DecimalQuantity : public IFixedDecimal, public UMemory { bool adjustMagnitude(int32_t delta); /** + * Scales the number such that the least significant nonzero digit is at magnitude 0. + * + * @return The previous magnitude of the least significant digit. + */ + int32_t adjustToZeroScale(); + + /** * @return The power of ten corresponding to the most significant nonzero digit. * The number must not be zero. */ @@ -234,6 +245,9 @@ class U_I18N_API DecimalQuantity : public IFixedDecimal, public UMemory { /** Internal method if the caller already has a DecNum. */ DecimalQuantity &setToDecNum(const DecNum& n, UErrorCode& status); + /** Returns a DecimalQuantity after parsing the input string. */ + static DecimalQuantity fromExponentString(UnicodeString n, UErrorCode& status); + /** * Appends a digit, optionally with one or more leading zeros, to the end of the value represented * by this DecimalQuantity. @@ -315,6 +329,10 @@ class U_I18N_API DecimalQuantity : public IFixedDecimal, public UMemory { /** Returns the string without exponential notation. Slightly slower than toScientificString(). */ UnicodeString toPlainString() const; + /** Returns the string using ASCII digits and using exponential notation for non-zero + exponents, following the UTS 35 specification for plural rule samples. */ + UnicodeString toExponentString() const; + /** Visible for testing */ inline bool isUsingBytes() { return usingBytes; } @@ -518,6 +536,8 @@ class U_I18N_API DecimalQuantity : public IFixedDecimal, public UMemory { void _setToDecNum(const DecNum& dn, UErrorCode& status); + static int32_t getVisibleFractionCount(UnicodeString value); + void convertToAccurateDouble(); /** Ensure that a byte array of at least 40 digits is allocated. */ diff --git a/Build/source/libs/icu/icu-src/source/i18n/number_longnames.cpp b/Build/source/libs/icu/icu-src/source/i18n/number_longnames.cpp index 5a4cf6321c8..b4e96504ded 100644 --- a/Build/source/libs/icu/icu-src/source/i18n/number_longnames.cpp +++ b/Build/source/libs/icu/icu-src/source/i18n/number_longnames.cpp @@ -431,13 +431,33 @@ void getMeasureData(const Locale &locale, subKey.append(unit.getType(), status); subKey.append("/", status); + // Check if unitSubType is an alias or not. + LocalUResourceBundlePointer aliasBundle(ures_open(U_ICUDATA_ALIAS, "metadata", &status)); + + UErrorCode aliasStatus = status; + StackUResourceBundle aliasFillIn; + CharString aliasKey; + aliasKey.append("alias/unit/", aliasStatus); + aliasKey.append(unit.getSubtype(), aliasStatus); + aliasKey.append("/replacement", aliasStatus); + ures_getByKeyWithFallback(aliasBundle.getAlias(), aliasKey.data(), aliasFillIn.getAlias(), + &aliasStatus); + CharString unitSubType; + if (!U_FAILURE(aliasStatus)) { + // This means the subType is an alias. Then, replace unitSubType with the replacement. + auto replacement = ures_getUnicodeString(aliasFillIn.getAlias(), &status); + unitSubType.appendInvariantChars(replacement, status); + } else { + unitSubType.append(unit.getSubtype(), status); + } + // Map duration-year-person, duration-week-person, etc. to duration-year, duration-week, ... // TODO(ICU-20400): Get duration-*-person data properly with aliases. - int32_t subtypeLen = static_cast<int32_t>(uprv_strlen(unit.getSubtype())); - if (subtypeLen > 7 && uprv_strcmp(unit.getSubtype() + subtypeLen - 7, "-person") == 0) { - subKey.append({unit.getSubtype(), subtypeLen - 7}, status); + int32_t subtypeLen = static_cast<int32_t>(uprv_strlen(unitSubType.data())); + if (subtypeLen > 7 && uprv_strcmp(unitSubType.data() + subtypeLen - 7, "-person") == 0) { + subKey.append({unitSubType.data(), subtypeLen - 7}, status); } else { - subKey.append({unit.getSubtype(), subtypeLen}, status); + subKey.append({unitSubType.data(), subtypeLen}, status); } if (width != UNUM_UNIT_WIDTH_FULL_NAME) { diff --git a/Build/source/libs/icu/icu-src/source/i18n/number_mapper.cpp b/Build/source/libs/icu/icu-src/source/i18n/number_mapper.cpp index 2d4d47a094d..350c431dfdd 100644 --- a/Build/source/libs/icu/icu-src/source/i18n/number_mapper.cpp +++ b/Build/source/libs/icu/icu-src/source/i18n/number_mapper.cpp @@ -134,7 +134,8 @@ MacroProps NumberPropertyMapper::oldToNew(const DecimalFormatProperties& propert if (PatternStringUtils::ignoreRoundingIncrement(roundingIncrement, maxFrac)) { precision = Precision::constructFraction(minFrac, maxFrac); } else { - precision = Precision::constructIncrement(roundingIncrement, minFrac); + // Convert the double increment to an integer increment + precision = Precision::increment(roundingIncrement).withMinFraction(minFrac); } } else if (explicitMinMaxSig) { minSig = minSig < 1 ? 1 : minSig > kMaxIntFracSig ? kMaxIntFracSig : minSig; @@ -293,9 +294,14 @@ MacroProps NumberPropertyMapper::oldToNew(const DecimalFormatProperties& propert } else if (rounding_.fType == Precision::PrecisionType::RND_INCREMENT || rounding_.fType == Precision::PrecisionType::RND_INCREMENT_ONE || rounding_.fType == Precision::PrecisionType::RND_INCREMENT_FIVE) { - increment_ = rounding_.fUnion.increment.fIncrement; minFrac_ = rounding_.fUnion.increment.fMinFrac; + // If incrementRounding is used, maxFrac is set equal to minFrac maxFrac_ = rounding_.fUnion.increment.fMinFrac; + // Convert the integer increment to a double + DecimalQuantity dq; + dq.setToLong(rounding_.fUnion.increment.fIncrement); + dq.adjustMagnitude(rounding_.fUnion.increment.fIncrementMagnitude); + increment_ = dq.toDouble(); } else if (rounding_.fType == Precision::PrecisionType::RND_SIGNIFICANT) { minSig_ = rounding_.fUnion.fracSig.fMinSig; maxSig_ = rounding_.fUnion.fracSig.fMaxSig; diff --git a/Build/source/libs/icu/icu-src/source/i18n/number_output.cpp b/Build/source/libs/icu/icu-src/source/i18n/number_output.cpp index 2c2c25eaedb..78006da8c42 100644 --- a/Build/source/libs/icu/icu-src/source/i18n/number_output.cpp +++ b/Build/source/libs/icu/icu-src/source/i18n/number_output.cpp @@ -39,6 +39,49 @@ MeasureUnit FormattedNumber::getOutputUnit(UErrorCode& status) const { return fData->outputUnit; } +NounClass FormattedNumber::getNounClass(UErrorCode &status) const { + UPRV_FORMATTED_VALUE_METHOD_GUARD(NounClass::OTHER); + const char *nounClass = fData->gender; + + // if it is not exist, return `OTHER` + if (uprv_strcmp(nounClass, "") == 0) { + return NounClass::OTHER; + } + + if (uprv_strcmp(nounClass, "neuter") == 0) { + return NounClass::NEUTER; + } + + if (uprv_strcmp(nounClass, "feminine") == 0) { + return NounClass::FEMININE; + } + + if (uprv_strcmp(nounClass, "masculine") == 0) { + return NounClass::MASCULINE; + } + + if (uprv_strcmp(nounClass, "animate") == 0) { + return NounClass::ANIMATE; + } + + if (uprv_strcmp(nounClass, "inanimate") == 0) { + return NounClass::INANIMATE; + } + + if (uprv_strcmp(nounClass, "personal") == 0) { + return NounClass::PERSONAL; + } + + if (uprv_strcmp(nounClass, "common") == 0) { + return NounClass::COMMON; + } + + // In case there is no matching, this means there are noun classes + // that are not supported yet. + status = U_INTERNAL_PROGRAM_ERROR; + return NounClass::OTHER; +} + const char *FormattedNumber::getGender(UErrorCode &status) const { UPRV_FORMATTED_VALUE_METHOD_GUARD("") return fData->gender; diff --git a/Build/source/libs/icu/icu-src/source/i18n/number_patternstring.cpp b/Build/source/libs/icu/icu-src/source/i18n/number_patternstring.cpp index e819d39e967..2738895d8ad 100644 --- a/Build/source/libs/icu/icu-src/source/i18n/number_patternstring.cpp +++ b/Build/source/libs/icu/icu-src/source/i18n/number_patternstring.cpp @@ -750,7 +750,7 @@ UnicodeString PatternStringUtils::propertiesToPatternString(const DecimalFormatP int32_t groupingLength = grouping1 + grouping2 + 1; // Figure out the digits we need to put in the pattern. - double roundingInterval = properties.roundingIncrement; + double increment = properties.roundingIncrement; UnicodeString digitsString; int32_t digitsStringScale = 0; if (maxSig != uprv_min(dosMax, -1)) { @@ -761,14 +761,14 @@ UnicodeString PatternStringUtils::propertiesToPatternString(const DecimalFormatP while (digitsString.length() < maxSig) { digitsString.append(u'#'); } - } else if (roundingInterval != 0.0 && !ignoreRoundingIncrement(roundingInterval,maxFrac)) { - // Rounding Interval. - digitsStringScale = -roundingutils::doubleFractionLength(roundingInterval, nullptr); - // TODO: Check for DoS here? + } else if (increment != 0.0 && !ignoreRoundingIncrement(increment,maxFrac)) { + // Rounding Increment. DecimalQuantity incrementQuantity; - incrementQuantity.setToDouble(roundingInterval); + incrementQuantity.setToDouble(increment); + incrementQuantity.roundToInfinity(); + digitsStringScale = incrementQuantity.getLowerDisplayMagnitude(); incrementQuantity.adjustMagnitude(-digitsStringScale); - incrementQuantity.roundToMagnitude(0, kDefaultMode, status); + incrementQuantity.setMinInteger(minInt - digitsStringScale); UnicodeString str = incrementQuantity.toPlainString(); if (str.charAt(0) == u'-') { // TODO: Unsupported operation exception or fail silently? diff --git a/Build/source/libs/icu/icu-src/source/i18n/number_rounding.cpp b/Build/source/libs/icu/icu-src/source/i18n/number_rounding.cpp index 877df63c8f6..a9b3f16c050 100644 --- a/Build/source/libs/icu/icu-src/source/i18n/number_rounding.cpp +++ b/Build/source/libs/icu/icu-src/source/i18n/number_rounding.cpp @@ -36,27 +36,24 @@ void number::impl::parseIncrementOption(const StringSegment &segment, // Utilize DecimalQuantity/decNumber to parse this for us. DecimalQuantity dq; UErrorCode localStatus = U_ZERO_ERROR; - DecNum decnum; - decnum.setTo({buffer.data(), buffer.length()}, localStatus); - dq.setToDecNum(decnum, localStatus); - if (U_FAILURE(localStatus) || decnum.isSpecial()) { + dq.setToDecNumber({buffer.data(), buffer.length()}, localStatus); + if (U_FAILURE(localStatus) || dq.isNaN() || dq.isInfinite()) { // throw new SkeletonSyntaxException("Invalid rounding increment", segment, e); status = U_NUMBER_SKELETON_SYNTAX_ERROR; return; } - double increment = dq.toDouble(); - - // We also need to figure out how many digits. Do a brute force string operation. - int decimalOffset = 0; - while (decimalOffset < segment.length() && segment.charAt(decimalOffset) != '.') { - decimalOffset++; - } - if (decimalOffset == segment.length()) { - outPrecision = Precision::increment(increment); - } else { - int32_t fractionLength = segment.length() - decimalOffset - 1; - outPrecision = Precision::increment(increment).withMinFraction(fractionLength); + // Now we break apart the number into a mantissa and exponent (magnitude). + int32_t magnitude = dq.adjustToZeroScale(); + // setToDecNumber drops trailing zeros, so we search for the '.' manually. + for (int32_t i=0; i<buffer.length(); i++) { + if (buffer[i] == '.') { + int32_t newMagnitude = i - buffer.length() + 1; + dq.adjustMagnitude(magnitude - newMagnitude); + magnitude = newMagnitude; + break; + } } + outPrecision = Precision::incrementExact(dq.toLong(), magnitude); } namespace { @@ -94,34 +91,6 @@ int32_t getDisplayMagnitudeSignificant(const DecimalQuantity &value, int minSig) MultiplierProducer::~MultiplierProducer() = default; -digits_t roundingutils::doubleFractionLength(double input, int8_t* singleDigit) { - char buffer[DoubleToStringConverter::kBase10MaximalLength + 1]; - bool sign; // unused; always positive - int32_t length; - int32_t point; - DoubleToStringConverter::DoubleToAscii( - input, - DoubleToStringConverter::DtoaMode::SHORTEST, - 0, - buffer, - sizeof(buffer), - &sign, - &length, - &point - ); - - if (singleDigit == nullptr) { - // no-op - } else if (length == 1) { - *singleDigit = buffer[0] - '0'; - } else { - *singleDigit = -1; - } - - return static_cast<digits_t>(length - point); -} - - Precision Precision::unlimited() { return Precision(RND_NONE, {}); } @@ -204,7 +173,19 @@ Precision Precision::trailingZeroDisplay(UNumberTrailingZeroDisplay trailingZero IncrementPrecision Precision::increment(double roundingIncrement) { if (roundingIncrement > 0.0) { - return constructIncrement(roundingIncrement, 0); + DecimalQuantity dq; + dq.setToDouble(roundingIncrement); + dq.roundToInfinity(); + int32_t magnitude = dq.adjustToZeroScale(); + return constructIncrement(dq.toLong(), magnitude); + } else { + return {U_NUMBER_ARG_OUTOFBOUNDS_ERROR}; + } +} + +IncrementPrecision Precision::incrementExact(uint64_t mantissa, int16_t magnitude) { + if (mantissa > 0.0) { + return constructIncrement(mantissa, magnitude); } else { return {U_NUMBER_ARG_OUTOFBOUNDS_ERROR}; } @@ -226,7 +207,8 @@ Precision FractionPrecision::withSignificantDigits( *this, minSignificantDigits, maxSignificantDigits, - priority); + priority, + false); } else { return {U_NUMBER_ARG_OUTOFBOUNDS_ERROR}; } @@ -239,7 +221,8 @@ Precision FractionPrecision::withMinDigits(int32_t minSignificantDigits) const { *this, 1, minSignificantDigits, - UNUM_ROUNDING_PRIORITY_RELAXED); + UNUM_ROUNDING_PRIORITY_RELAXED, + true); } else { return {U_NUMBER_ARG_OUTOFBOUNDS_ERROR}; } @@ -251,7 +234,8 @@ Precision FractionPrecision::withMaxDigits(int32_t maxSignificantDigits) const { return constructFractionSignificant(*this, 1, maxSignificantDigits, - UNUM_ROUNDING_PRIORITY_STRICT); + UNUM_ROUNDING_PRIORITY_STRICT, + true); } else { return {U_NUMBER_ARG_OUTOFBOUNDS_ERROR}; } @@ -266,8 +250,8 @@ Precision Precision::withCurrency(const CurrencyUnit ¤cy, UErrorCode &stat int32_t minMaxFrac = ucurr_getDefaultFractionDigitsForUsage( isoCode, fUnion.currencyUsage, &status); Precision retval = (increment != 0.0) - ? static_cast<Precision>(constructIncrement(increment, minMaxFrac)) - : static_cast<Precision>(constructFraction(minMaxFrac, minMaxFrac)); + ? Precision::increment(increment) + : static_cast<Precision>(Precision::fixedFraction(minMaxFrac)); retval.fTrailingZeroDisplay = fTrailingZeroDisplay; return retval; } @@ -285,7 +269,9 @@ Precision CurrencyPrecision::withCurrency(const CurrencyUnit ¤cy) const { Precision IncrementPrecision::withMinFraction(int32_t minFrac) const { if (fType == RND_ERROR) { return *this; } // no-op in error state if (minFrac >= 0 && minFrac <= kMaxIntFracSig) { - return constructIncrement(fUnion.increment.fIncrement, minFrac); + IncrementPrecision copy = *this; + copy.fUnion.increment.fMinFrac = minFrac; + return copy; } else { return {U_NUMBER_ARG_OUTOFBOUNDS_ERROR}; } @@ -318,35 +304,34 @@ Precision::constructFractionSignificant( const FractionPrecision &base, int32_t minSig, int32_t maxSig, - UNumberRoundingPriority priority) { + UNumberRoundingPriority priority, + bool retain) { FractionSignificantSettings settings = base.fUnion.fracSig; settings.fMinSig = static_cast<digits_t>(minSig); settings.fMaxSig = static_cast<digits_t>(maxSig); settings.fPriority = priority; + settings.fRetain = retain; PrecisionUnion union_; union_.fracSig = settings; return {RND_FRACTION_SIGNIFICANT, union_}; } -IncrementPrecision Precision::constructIncrement(double increment, int32_t minFrac) { +IncrementPrecision Precision::constructIncrement(uint64_t increment, digits_t magnitude) { IncrementSettings settings; // Note: For number formatting, fIncrement is used for RND_INCREMENT but not // RND_INCREMENT_ONE or RND_INCREMENT_FIVE. However, fIncrement is used in all // three when constructing a skeleton. settings.fIncrement = increment; - settings.fMinFrac = static_cast<digits_t>(minFrac); - // One of the few pre-computed quantities: - // Note: it is possible for minFrac to be more than maxFrac... (misleading) - int8_t singleDigit; - settings.fMaxFrac = roundingutils::doubleFractionLength(increment, &singleDigit); + settings.fIncrementMagnitude = magnitude; + settings.fMinFrac = magnitude > 0 ? 0 : -magnitude; PrecisionUnion union_; union_.increment = settings; - if (singleDigit == 1) { + if (increment == 1) { // NOTE: In C++, we must return the correct value type with the correct union. // It would be invalid to return a RND_FRACTION here because the methods on the // IncrementPrecision type assume that the union is backed by increment data. return {RND_INCREMENT_ONE, union_}; - } else if (singleDigit == 5) { + } else if (increment == 5) { return {RND_INCREMENT_FIVE, union_}; } else { return {RND_INCREMENT, union_}; @@ -457,6 +442,23 @@ void RoundingImpl::apply(impl::DecimalQuantity &value, UErrorCode& status) const break; case Precision::RND_FRACTION_SIGNIFICANT: { + // From ECMA-402: + /* + Let sResult be ToRawPrecision(...). + Let fResult be ToRawFixed(...). + If intlObj.[[RoundingType]] is morePrecision, then + If sResult.[[RoundingMagnitude]] ≤ fResult.[[RoundingMagnitude]], then + Let result be sResult. + Else, + Let result be fResult. + Else, + Assert: intlObj.[[RoundingType]] is lessPrecision. + If sResult.[[RoundingMagnitude]] ≤ fResult.[[RoundingMagnitude]], then + Let result be fResult. + Else, + Let result be sResult. + */ + int32_t roundingMag1 = getRoundingMagnitudeFraction(fPrecision.fUnion.fracSig.fMaxFrac); int32_t roundingMag2 = getRoundingMagnitudeSignificant(value, fPrecision.fUnion.fracSig.fMaxSig); int32_t roundingMag; @@ -465,11 +467,35 @@ void RoundingImpl::apply(impl::DecimalQuantity &value, UErrorCode& status) const } else { roundingMag = uprv_max(roundingMag1, roundingMag2); } - value.roundToMagnitude(roundingMag, fRoundingMode, status); + if (!value.isZeroish()) { + int32_t upperMag = value.getMagnitude(); + value.roundToMagnitude(roundingMag, fRoundingMode, status); + if (!value.isZeroish() && value.getMagnitude() != upperMag && roundingMag1 == roundingMag2) { + // roundingMag2 needs to be the magnitude after rounding + roundingMag2 += 1; + } + } int32_t displayMag1 = getDisplayMagnitudeFraction(fPrecision.fUnion.fracSig.fMinFrac); int32_t displayMag2 = getDisplayMagnitudeSignificant(value, fPrecision.fUnion.fracSig.fMinSig); - int32_t displayMag = uprv_min(displayMag1, displayMag2); + int32_t displayMag; + if (fPrecision.fUnion.fracSig.fRetain) { + // withMinDigits + withMaxDigits + displayMag = uprv_min(displayMag1, displayMag2); + } else if (fPrecision.fUnion.fracSig.fPriority == UNUM_ROUNDING_PRIORITY_RELAXED) { + if (roundingMag2 <= roundingMag1) { + displayMag = displayMag2; + } else { + displayMag = displayMag1; + } + } else { + U_ASSERT(fPrecision.fUnion.fracSig.fPriority == UNUM_ROUNDING_PRIORITY_STRICT); + if (roundingMag2 <= roundingMag1) { + displayMag = displayMag1; + } else { + displayMag = displayMag2; + } + } resolvedMinFraction = uprv_max(0, -displayMag); break; @@ -478,6 +504,7 @@ void RoundingImpl::apply(impl::DecimalQuantity &value, UErrorCode& status) const case Precision::RND_INCREMENT: value.roundToIncrement( fPrecision.fUnion.increment.fIncrement, + fPrecision.fUnion.increment.fIncrementMagnitude, fRoundingMode, status); resolvedMinFraction = fPrecision.fUnion.increment.fMinFrac; @@ -485,7 +512,7 @@ void RoundingImpl::apply(impl::DecimalQuantity &value, UErrorCode& status) const case Precision::RND_INCREMENT_ONE: value.roundToMagnitude( - -fPrecision.fUnion.increment.fMaxFrac, + fPrecision.fUnion.increment.fIncrementMagnitude, fRoundingMode, status); resolvedMinFraction = fPrecision.fUnion.increment.fMinFrac; @@ -493,7 +520,7 @@ void RoundingImpl::apply(impl::DecimalQuantity &value, UErrorCode& status) const case Precision::RND_INCREMENT_FIVE: value.roundToNickel( - -fPrecision.fUnion.increment.fMaxFrac, + fPrecision.fUnion.increment.fIncrementMagnitude, fRoundingMode, status); resolvedMinFraction = fPrecision.fUnion.increment.fMinFrac; diff --git a/Build/source/libs/icu/icu-src/source/i18n/number_roundingutils.h b/Build/source/libs/icu/icu-src/source/i18n/number_roundingutils.h index 06fadd29fd5..66571272545 100644 --- a/Build/source/libs/icu/icu-src/source/i18n/number_roundingutils.h +++ b/Build/source/libs/icu/icu-src/source/i18n/number_roundingutils.h @@ -174,15 +174,6 @@ inline bool roundsAtMidpoint(int roundingMode) { } } -/** - * Computes the number of fraction digits in a double. Used for computing maxFrac for an increment. - * Calls into the DoubleToStringConverter library to do so. - * - * @param singleDigit An output parameter; set to a number if that is the - * only digit in the double, or -1 if there is more than one digit. - */ -digits_t doubleFractionLength(double input, int8_t* singleDigit); - } // namespace roundingutils diff --git a/Build/source/libs/icu/icu-src/source/i18n/number_skeletons.cpp b/Build/source/libs/icu/icu-src/source/i18n/number_skeletons.cpp index de70c5cedff..c51831b6823 100644 --- a/Build/source/libs/icu/icu-src/source/i18n/number_skeletons.cpp +++ b/Build/source/libs/icu/icu-src/source/i18n/number_skeletons.cpp @@ -1344,8 +1344,9 @@ bool blueprint_helpers::parseFracSigOption(const StringSegment& segment, MacroPr // @, @@, @@@ maxSig = minSig; } - UNumberRoundingPriority priority; + auto& oldPrecision = static_cast<const FractionPrecision&>(macros.precision); if (offset < segment.length()) { + UNumberRoundingPriority priority; if (maxSig == -1) { // The wildcard character is not allowed with the priority annotation status = U_NUMBER_SKELETON_SYNTAX_ERROR; @@ -1367,22 +1368,19 @@ bool blueprint_helpers::parseFracSigOption(const StringSegment& segment, MacroPr status = U_NUMBER_SKELETON_SYNTAX_ERROR; return false; } + macros.precision = oldPrecision.withSignificantDigits(minSig, maxSig, priority); } else if (maxSig == -1) { // withMinDigits - maxSig = minSig; - minSig = 1; - priority = UNUM_ROUNDING_PRIORITY_RELAXED; + macros.precision = oldPrecision.withMinDigits(minSig); } else if (minSig == 1) { // withMaxDigits - priority = UNUM_ROUNDING_PRIORITY_STRICT; + macros.precision = oldPrecision.withMaxDigits(maxSig); } else { // Digits options with both min and max sig require the priority option status = U_NUMBER_SKELETON_SYNTAX_ERROR; return false; } - auto& oldPrecision = static_cast<const FractionPrecision&>(macros.precision); - macros.precision = oldPrecision.withSignificantDigits(minSig, maxSig, priority); return true; } @@ -1399,12 +1397,16 @@ void blueprint_helpers::parseIncrementOption(const StringSegment &segment, Macro number::impl::parseIncrementOption(segment, macros.precision, status); } -void blueprint_helpers::generateIncrementOption(double increment, int32_t minFrac, UnicodeString& sb, - UErrorCode&) { +void blueprint_helpers::generateIncrementOption( + uint32_t increment, + digits_t incrementMagnitude, + int32_t minFrac, + UnicodeString& sb, + UErrorCode&) { // Utilize DecimalQuantity/double_conversion to format this for us. DecimalQuantity dq; - dq.setToDouble(increment); - dq.roundToInfinity(); + dq.setToLong(increment); + dq.adjustMagnitude(incrementMagnitude); dq.setMinFraction(minFrac); sb.append(dq.toPlainString()); } @@ -1617,11 +1619,21 @@ bool GeneratorHelpers::precision(const MacroProps& macros, UnicodeString& sb, UE const Precision::FractionSignificantSettings& impl = macros.precision.fUnion.fracSig; blueprint_helpers::generateFractionStem(impl.fMinFrac, impl.fMaxFrac, sb, status); sb.append(u'/'); - blueprint_helpers::generateDigitsStem(impl.fMinSig, impl.fMaxSig, sb, status); - if (impl.fPriority == UNUM_ROUNDING_PRIORITY_RELAXED) { - sb.append(u'r'); + if (impl.fRetain) { + if (impl.fPriority == UNUM_ROUNDING_PRIORITY_RELAXED) { + // withMinDigits + blueprint_helpers::generateDigitsStem(impl.fMaxSig, -1, sb, status); + } else { + // withMaxDigits + blueprint_helpers::generateDigitsStem(1, impl.fMaxSig, sb, status); + } } else { - sb.append(u's'); + blueprint_helpers::generateDigitsStem(impl.fMinSig, impl.fMaxSig, sb, status); + if (impl.fPriority == UNUM_ROUNDING_PRIORITY_RELAXED) { + sb.append(u'r'); + } else { + sb.append(u's'); + } } } else if (macros.precision.fType == Precision::RND_INCREMENT || macros.precision.fType == Precision::RND_INCREMENT_ONE @@ -1630,6 +1642,7 @@ bool GeneratorHelpers::precision(const MacroProps& macros, UnicodeString& sb, UE sb.append(u"precision-increment/", -1); blueprint_helpers::generateIncrementOption( impl.fIncrement, + impl.fIncrementMagnitude, impl.fMinFrac, sb, status); diff --git a/Build/source/libs/icu/icu-src/source/i18n/number_skeletons.h b/Build/source/libs/icu/icu-src/source/i18n/number_skeletons.h index be41f1b3237..27f69cd48c3 100644 --- a/Build/source/libs/icu/icu-src/source/i18n/number_skeletons.h +++ b/Build/source/libs/icu/icu-src/source/i18n/number_skeletons.h @@ -286,7 +286,7 @@ bool parseTrailingZeroOption(const StringSegment& segment, MacroProps& macros, U void parseIncrementOption(const StringSegment& segment, MacroProps& macros, UErrorCode& status); void -generateIncrementOption(double increment, int32_t minFrac, UnicodeString& sb, UErrorCode& status); +generateIncrementOption(uint32_t increment, digits_t incrementMagnitude, int32_t minFrac, UnicodeString& sb, UErrorCode& status); void parseIntegerWidthOption(const StringSegment& segment, MacroProps& macros, UErrorCode& status); diff --git a/Build/source/libs/icu/icu-src/source/i18n/numsys.cpp b/Build/source/libs/icu/icu-src/source/i18n/numsys.cpp index 44aaf8e2a5f..934149039c5 100644 --- a/Build/source/libs/icu/icu-src/source/i18n/numsys.cpp +++ b/Build/source/libs/icu/icu-src/source/i18n/numsys.cpp @@ -313,12 +313,7 @@ U_CFUNC void initNumsysNames(UErrorCode &status) { } const char *nsName = ures_getKey(nsCurrent.getAlias()); LocalPointer<UnicodeString> newElem(new UnicodeString(nsName, -1, US_INV), status); - if (U_SUCCESS(status)) { - numsysNames->addElementX(newElem.getAlias(), status); - if (U_SUCCESS(status)) { - newElem.orphan(); // on success, the numsysNames vector owns newElem. - } - } + numsysNames->adoptElement(newElem.orphan(), status); } ures_close(numberingSystemsInfo); diff --git a/Build/source/libs/icu/icu-src/source/i18n/plurrule.cpp b/Build/source/libs/icu/icu-src/source/i18n/plurrule.cpp index 336292c5458..7d1037f8bdd 100644 --- a/Build/source/libs/icu/icu-src/source/i18n/plurrule.cpp +++ b/Build/source/libs/icu/icu-src/source/i18n/plurrule.cpp @@ -1548,14 +1548,9 @@ PluralKeywordEnumeration::PluralKeywordEnumeration(RuleChain *header, UErrorCode UBool addKeywordOther = TRUE; RuleChain *node = header; while (node != nullptr) { - auto newElem = new UnicodeString(node->fKeyword); - if (newElem == nullptr) { - status = U_MEMORY_ALLOCATION_ERROR; - return; - } - fKeywordNames.addElementX(newElem, status); + LocalPointer<UnicodeString> newElem(node->fKeyword.clone(), status); + fKeywordNames.adoptElement(newElem.orphan(), status); if (U_FAILURE(status)) { - delete newElem; return; } if (0 == node->fKeyword.compare(PLURAL_KEYWORD_OTHER, 5)) { @@ -1565,14 +1560,9 @@ PluralKeywordEnumeration::PluralKeywordEnumeration(RuleChain *header, UErrorCode } if (addKeywordOther) { - auto newElem = new UnicodeString(PLURAL_KEYWORD_OTHER); - if (newElem == nullptr) { - status = U_MEMORY_ALLOCATION_ERROR; - return; - } - fKeywordNames.addElementX(newElem, status); + LocalPointer<UnicodeString> newElem(new UnicodeString(PLURAL_KEYWORD_OTHER), status); + fKeywordNames.adoptElement(newElem.orphan(), status); if (U_FAILURE(status)) { - delete newElem; return; } } diff --git a/Build/source/libs/icu/icu-src/source/i18n/rbt_set.cpp b/Build/source/libs/icu/icu-src/source/i18n/rbt_set.cpp index abc4413c2c6..6835c03a698 100644 --- a/Build/source/libs/icu/icu-src/source/i18n/rbt_set.cpp +++ b/Build/source/libs/icu/icu-src/source/i18n/rbt_set.cpp @@ -163,16 +163,13 @@ U_NAMESPACE_BEGIN /** * Construct a new empty rule set. */ -TransliterationRuleSet::TransliterationRuleSet(UErrorCode& status) : UMemory() { - ruleVector = new UVector(&_deleteRule, NULL, status); +TransliterationRuleSet::TransliterationRuleSet(UErrorCode& status) : + UMemory(), ruleVector(nullptr), rules(nullptr), index {}, maxContextLength(0) { + LocalPointer<UVector> lpRuleVector(new UVector(_deleteRule, nullptr, status), status); if (U_FAILURE(status)) { return; } - if (ruleVector == NULL) { - status = U_MEMORY_ALLOCATION_ERROR; - } - rules = NULL; - maxContextLength = 0; + ruleVector = lpRuleVector.orphan(); } /** @@ -180,27 +177,24 @@ TransliterationRuleSet::TransliterationRuleSet(UErrorCode& status) : UMemory() { */ TransliterationRuleSet::TransliterationRuleSet(const TransliterationRuleSet& other) : UMemory(other), - ruleVector(0), - rules(0), + ruleVector(nullptr), + rules(nullptr), maxContextLength(other.maxContextLength) { int32_t i, len; uprv_memcpy(index, other.index, sizeof(index)); UErrorCode status = U_ZERO_ERROR; - ruleVector = new UVector(&_deleteRule, NULL, status); - if (other.ruleVector != 0 && ruleVector != 0 && U_SUCCESS(status)) { + LocalPointer<UVector> lpRuleVector(new UVector(_deleteRule, nullptr, status), status); + if (U_FAILURE(status)) { + return; + } + ruleVector = lpRuleVector.orphan(); + if (other.ruleVector != nullptr && U_SUCCESS(status)) { len = other.ruleVector->size(); for (i=0; i<len && U_SUCCESS(status); ++i) { - TransliterationRule *tempTranslitRule = new TransliterationRule(*(TransliterationRule*)other.ruleVector->elementAt(i)); - // Null pointer test - if (tempTranslitRule == NULL) { - status = U_MEMORY_ALLOCATION_ERROR; - break; - } - ruleVector->addElementX(tempTranslitRule, status); - if (U_FAILURE(status)) { - break; - } + LocalPointer<TransliterationRule> tempTranslitRule( + new TransliterationRule(*(TransliterationRule*)other.ruleVector->elementAt(i)), status); + ruleVector->adoptElement(tempTranslitRule.orphan(), status); } } if (other.rules != 0 && U_SUCCESS(status)) { @@ -247,11 +241,11 @@ int32_t TransliterationRuleSet::getMaximumContextLength(void) const { */ void TransliterationRuleSet::addRule(TransliterationRule* adoptedRule, UErrorCode& status) { + LocalPointer<TransliterationRule> lpAdoptedRule(adoptedRule); + ruleVector->adoptElement(lpAdoptedRule.orphan(), status); if (U_FAILURE(status)) { - delete adoptedRule; return; } - ruleVector->addElementX(adoptedRule, status); int32_t len; if ((len = adoptedRule->getContextLength()) > maxContextLength) { @@ -316,7 +310,7 @@ void TransliterationRuleSet::freeze(UParseError& parseError,UErrorCode& status) for (j=0; j<n; ++j) { if (indexValue[j] >= 0) { if (indexValue[j] == x) { - v.addElementX(ruleVector->elementAt(j), status); + v.addElement(ruleVector->elementAt(j), status); } } else { // If the indexValue is < 0, then the first key character is @@ -325,13 +319,16 @@ void TransliterationRuleSet::freeze(UParseError& parseError,UErrorCode& status) // rarely, so we seldom treat this code path. TransliterationRule* r = (TransliterationRule*) ruleVector->elementAt(j); if (r->matchesIndexValue((uint8_t)x)) { - v.addElementX(r, status); + v.addElement(r, status); } } } } uprv_free(indexValue); index[256] = v.size(); + if (U_FAILURE(status)) { + return; + } /* Freeze things into an array. */ diff --git a/Build/source/libs/icu/icu-src/source/i18n/region.cpp b/Build/source/libs/icu/icu-src/source/i18n/region.cpp index 2e013708bb8..277a22fd091 100644 --- a/Build/source/libs/icu/icu-src/source/i18n/region.cpp +++ b/Build/source/libs/icu/icu-src/source/i18n/region.cpp @@ -39,11 +39,6 @@ U_CDECL_BEGIN -static void U_CALLCONV -deleteRegion(void *obj) { - delete (icu::Region *)obj; -} - /** * Cleanup callback func */ @@ -90,7 +85,8 @@ void U_CALLCONV Region::loadRegionData(UErrorCode &status) { LocalPointer<UVector> continents(new UVector(uprv_deleteUObject, uhash_compareUnicodeString, status), status); LocalPointer<UVector> groupings(new UVector(uprv_deleteUObject, uhash_compareUnicodeString, status), status); - allRegions = new UVector(uprv_deleteUObject, uhash_compareUnicodeString, status); + LocalPointer<UVector> lpAllRegions(new UVector(uprv_deleteUObject, uhash_compareUnicodeString, status), status); + allRegions = lpAllRegions.orphan(); LocalUResourceBundlePointer metadata(ures_openDirect(NULL,"metadata",&status)); LocalUResourceBundlePointer metadataAlias(ures_getByKey(metadata.getAlias(),"alias",NULL,&status)); @@ -109,16 +105,17 @@ void U_CALLCONV Region::loadRegionData(UErrorCode &status) { LocalUResourceBundlePointer worldContainment(ures_getByKey(territoryContainment.getAlias(),"001",NULL,&status)); LocalUResourceBundlePointer groupingContainment(ures_getByKey(territoryContainment.getAlias(),"grouping",NULL,&status)); + ucln_i18n_registerCleanup(UCLN_I18N_REGION, region_cleanup); if (U_FAILURE(status)) { return; } // now, initialize - uhash_setValueDeleter(newRegionIDMap.getAlias(), deleteRegion); // regionIDMap owns objs - uhash_setKeyDeleter(newRegionAliases.getAlias(), uprv_deleteUObject); // regionAliases owns the string keys + uhash_setValueDeleter(newRegionIDMap.getAlias(), uprv_deleteUObject); // regionIDMap owns objs + uhash_setKeyDeleter(newRegionAliases.getAlias(), uprv_deleteUObject); // regionAliases owns the string keys - while ( ures_hasNext(regionRegular.getAlias()) ) { + while (U_SUCCESS(status) && ures_hasNext(regionRegular.getAlias())) { UnicodeString regionName = ures_getNextUnicodeString(regionRegular.getAlias(),NULL,&status); int32_t rangeMarkerLocation = regionName.indexOf(RANGE_MARKER); UChar buf[6]; @@ -126,18 +123,18 @@ void U_CALLCONV Region::loadRegionData(UErrorCode &status) { if ( rangeMarkerLocation > 0 ) { UChar endRange = regionName.charAt(rangeMarkerLocation+1); buf[rangeMarkerLocation] = 0; - while ( buf[rangeMarkerLocation-1] <= endRange ) { + while (U_SUCCESS(status) && buf[rangeMarkerLocation-1] <= endRange) { LocalPointer<UnicodeString> newRegion(new UnicodeString(buf), status); - allRegions->addElementX(newRegion.orphan(),status); + allRegions->adoptElement(newRegion.orphan(), status); buf[rangeMarkerLocation-1]++; } } else { LocalPointer<UnicodeString> newRegion(new UnicodeString(regionName), status); - allRegions->addElementX(newRegion.orphan(),status); + allRegions->adoptElement(newRegion.orphan(), status); } } - while ( ures_hasNext(regionMacro.getAlias()) ) { + while (U_SUCCESS(status) && ures_hasNext(regionMacro.getAlias())) { UnicodeString regionName = ures_getNextUnicodeString(regionMacro.getAlias(),NULL,&status); int32_t rangeMarkerLocation = regionName.indexOf(RANGE_MARKER); UChar buf[6]; @@ -145,25 +142,29 @@ void U_CALLCONV Region::loadRegionData(UErrorCode &status) { if ( rangeMarkerLocation > 0 ) { UChar endRange = regionName.charAt(rangeMarkerLocation+1); buf[rangeMarkerLocation] = 0; - while ( buf[rangeMarkerLocation-1] <= endRange ) { + while ( buf[rangeMarkerLocation-1] <= endRange && U_SUCCESS(status)) { LocalPointer<UnicodeString> newRegion(new UnicodeString(buf), status); - allRegions->addElementX(newRegion.orphan(),status); + allRegions->adoptElement(newRegion.orphan(),status); buf[rangeMarkerLocation-1]++; } } else { LocalPointer<UnicodeString> newRegion(new UnicodeString(regionName), status); - allRegions->addElementX(newRegion.orphan(),status); + allRegions->adoptElement(newRegion.orphan(),status); } } - while ( ures_hasNext(regionUnknown.getAlias()) ) { - LocalPointer<UnicodeString> regionName (new UnicodeString(ures_getNextUnicodeString(regionUnknown.getAlias(),NULL,&status),status)); - allRegions->addElementX(regionName.orphan(),status); + while (U_SUCCESS(status) && ures_hasNext(regionUnknown.getAlias())) { + LocalPointer<UnicodeString> regionName ( + new UnicodeString(ures_getNextUnicodeString(regionUnknown.getAlias(), nullptr, &status), status)); + allRegions->adoptElement(regionName.orphan(),status); } - while ( ures_hasNext(worldContainment.getAlias()) ) { + while (U_SUCCESS(status) && ures_hasNext(worldContainment.getAlias())) { UnicodeString *continentName = new UnicodeString(ures_getNextUnicodeString(worldContainment.getAlias(),NULL,&status)); - continents->addElementX(continentName,status); + continents->adoptElement(continentName,status); + } + if (U_FAILURE(status)) { + return; } for ( int32_t i = 0 ; i < allRegions->size() ; i++ ) { @@ -191,22 +192,32 @@ void U_CALLCONV Region::loadRegionData(UErrorCode &status) { } UResourceBundle *groupingBundle = nullptr; - while ( ures_hasNext(groupingContainment.getAlias()) ) { + while (U_SUCCESS(status) && ures_hasNext(groupingContainment.getAlias())) { groupingBundle = ures_getNextResource(groupingContainment.getAlias(), groupingBundle, &status); if (U_FAILURE(status)) { break; } UnicodeString *groupingName = new UnicodeString(ures_getKey(groupingBundle), -1, US_INV); - groupings->addElementX(groupingName,status); - Region *grouping = (Region *) uhash_get(newRegionIDMap.getAlias(),groupingName); + LocalPointer<UnicodeString> lpGroupingName(groupingName, status); + groupings->adoptElement(lpGroupingName.orphan(), status); + if (U_FAILURE(status)) { + break; + } + Region *grouping = (Region *) uhash_get(newRegionIDMap.getAlias(), groupingName); if (grouping != NULL) { - for (int32_t i = 0; i < ures_getSize(groupingBundle); i++) { + for (int32_t i = 0; i < ures_getSize(groupingBundle) && U_SUCCESS(status); i++) { UnicodeString child = ures_getUnicodeStringByIndex(groupingBundle, i, &status); if (U_SUCCESS(status)) { if (grouping->containedRegions == NULL) { - grouping->containedRegions = new UVector(uprv_deleteUObject, uhash_compareUnicodeString, status); + LocalPointer<UVector> lpContainedRegions( + new UVector(uprv_deleteUObject, uhash_compareUnicodeString, status), status); + grouping->containedRegions = lpContainedRegions.orphan(); + if (U_FAILURE(status)) { + break; + } } - grouping->containedRegions->addElementX(new UnicodeString(child), status); + LocalPointer<UnicodeString> lpChildCopy(new UnicodeString(child), status); + grouping->containedRegions->adoptElement(lpChildCopy.orphan(), status); } } } @@ -214,7 +225,7 @@ void U_CALLCONV Region::loadRegionData(UErrorCode &status) { ures_close(groupingBundle); // Process the territory aliases - while ( ures_hasNext(territoryAlias.getAlias()) ) { + while (U_SUCCESS(status) && ures_hasNext(territoryAlias.getAlias())) { LocalUResourceBundlePointer res(ures_getNextResource(territoryAlias.getAlias(),NULL,&status)); const char *aliasFrom = ures_getKey(res.getAlias()); LocalPointer<UnicodeString> aliasFromStr(new UnicodeString(aliasFrom, -1, US_INV), status); @@ -259,7 +270,7 @@ void U_CALLCONV Region::loadRegionData(UErrorCode &status) { } UnicodeString currentRegion; //currentRegion.remove(); TODO: was already 0 length? - for (int32_t i = 0 ; i < aliasTo.length() ; i++ ) { + for (int32_t i = 0 ; i < aliasTo.length() && U_SUCCESS(status); i++ ) { if ( aliasTo.charAt(i) != 0x0020 ) { currentRegion.append(aliasTo.charAt(i)); } @@ -267,7 +278,7 @@ void U_CALLCONV Region::loadRegionData(UErrorCode &status) { Region *target = (Region *)uhash_get(newRegionIDMap.getAlias(),(void *)¤tRegion); if (target) { LocalPointer<UnicodeString> preferredValue(new UnicodeString(target->idStr), status); - aliasFromRegion->preferredValues->addElementX((void *)preferredValue.orphan(),status); // may add null if err + aliasFromRegion->preferredValues->adoptElement(preferredValue.orphan(),status); // may add null if err } currentRegion.remove(); } @@ -276,9 +287,9 @@ void U_CALLCONV Region::loadRegionData(UErrorCode &status) { } // Process the code mappings - This will allow us to assign numeric codes to most of the territories. - while ( ures_hasNext(codeMappings.getAlias()) ) { + while (U_SUCCESS(status) && ures_hasNext(codeMappings.getAlias())) { UResourceBundle *mapping = ures_getNextResource(codeMappings.getAlias(),NULL,&status); - if ( ures_getType(mapping) == URES_ARRAY && ures_getSize(mapping) == 3) { + if (U_SUCCESS(status) && ures_getType(mapping) == URES_ARRAY && ures_getSize(mapping) == 3) { UnicodeString codeMappingID = ures_getUnicodeStringByIndex(mapping,0,&status); UnicodeString codeMappingNumber = ures_getUnicodeStringByIndex(mapping,1,&status); UnicodeString codeMapping3Letter = ures_getUnicodeStringByIndex(mapping,2,&status); @@ -356,15 +367,23 @@ void U_CALLCONV Region::loadRegionData(UErrorCode &status) { // Add the child region to the set of regions contained by the parent if (parentRegion->containedRegions == NULL) { - parentRegion->containedRegions = new UVector(uprv_deleteUObject, uhash_compareUnicodeString, status); + LocalPointer<UVector> lpContainedRegions( + new UVector(uprv_deleteUObject, uhash_compareUnicodeString, status), status); + parentRegion->containedRegions = lpContainedRegions.orphan(); + if (U_FAILURE(status)) { + return; + } } LocalPointer<UnicodeString> childStr(new UnicodeString(), status); - if( U_FAILURE(status) ) { + if (U_FAILURE(status)) { return; // error out } childStr->fastCopyFrom(childRegion->idStr); - parentRegion->containedRegions->addElementX((void *)childStr.orphan(),status); + parentRegion->containedRegions->adoptElement(childStr.orphan(),status); + if (U_FAILURE(status)) { + return; + } // Set the parent region to be the containing region of the child. // Regions of type GROUPING can't be set as the parent, since another region @@ -388,10 +407,9 @@ void U_CALLCONV Region::loadRegionData(UErrorCode &status) { if( U_FAILURE(status) ) { return; // error out } - availableRegions[ar->fType]->addElementX((void *)arString.orphan(),status); + availableRegions[ar->fType]->adoptElement(arString.orphan(), status); } - ucln_i18n_registerCleanup(UCLN_I18N_REGION, region_cleanup); // copy hashtables numericCodeMap = newNumericCodeMap.orphan(); regionIDMap = newRegionIDMap.orphan(); @@ -402,6 +420,7 @@ void Region::cleanupRegionData() { for (int32_t i = 0 ; i < URGN_LIMIT ; i++ ) { if ( availableRegions[i] ) { delete availableRegions[i]; + availableRegions[i] = nullptr; } } @@ -417,7 +436,6 @@ void Region::cleanupRegionData() { uhash_close(regionIDMap); } if (allRegions) { - allRegions->removeAllElements(); // Don't need the temporary list anymore. delete allRegions; allRegions = NULL; } @@ -615,33 +633,30 @@ Region::getContainedRegions(UErrorCode &status) const { StringEnumeration* Region::getContainedRegions( URegionType type, UErrorCode &status ) const { umtx_initOnce(gRegionDataInitOnce, &loadRegionData, status); // returns immediately if U_FAILURE(status) + + UVector result(nullptr, uhash_compareChars, status); + LocalPointer<StringEnumeration> cr(getContainedRegions(status), status); if (U_FAILURE(status)) { - return NULL; + return nullptr; } - UVector *result = new UVector(NULL, uhash_compareChars, status); - - StringEnumeration *cr = getContainedRegions(status); - - for ( int32_t i = 0 ; i < cr->count(status) ; i++ ) { - const char *regionId = cr->next(NULL,status); - const Region *r = Region::getInstance(regionId,status); + const char *regionId; + while((regionId = cr->next(nullptr, status)) != nullptr && U_SUCCESS(status)) { + const Region *r = Region::getInstance(regionId, status); if ( r->getType() == type) { - result->addElementX((void *)&r->idStr,status); + result.addElement(const_cast<UnicodeString *>(&r->idStr), status); } else { - StringEnumeration *children = r->getContainedRegions(type, status); - for ( int32_t j = 0 ; j < children->count(status) ; j++ ) { - const char *id2 = children->next(NULL,status); + LocalPointer<StringEnumeration> children(r->getContainedRegions(type, status)); + const char *id2; + while(U_SUCCESS(status) && ((id2 = children->next(nullptr, status)) != nullptr)) { const Region *r2 = Region::getInstance(id2,status); - result->addElementX((void *)&r2->idStr,status); + result.addElement(const_cast<UnicodeString *>(&r2->idStr), status); } - delete children; } } - delete cr; - StringEnumeration* resultEnumeration = new RegionNameEnumeration(result,status); - delete result; - return resultEnumeration; + LocalPointer<StringEnumeration> resultEnumeration( + new RegionNameEnumeration(&result, status), status); + return U_SUCCESS(status) ? resultEnumeration.orphan() : nullptr; } /** @@ -706,18 +721,21 @@ Region::getType() const { return fType; } -RegionNameEnumeration::RegionNameEnumeration(UVector *fNameList, UErrorCode& status) { - pos=0; - if (fNameList && U_SUCCESS(status)) { - fRegionNames = new UVector(uprv_deleteUObject, uhash_compareUnicodeString, fNameList->size(),status); - for ( int32_t i = 0 ; i < fNameList->size() ; i++ ) { - UnicodeString* this_region_name = (UnicodeString *)fNameList->elementAt(i); - UnicodeString* new_region_name = new UnicodeString(*this_region_name); - fRegionNames->addElementX((void *)new_region_name,status); +RegionNameEnumeration::RegionNameEnumeration(UVector *nameList, UErrorCode& status) : + pos(0), fRegionNames(nullptr) { + // TODO: https://unicode-org.atlassian.net/browse/ICU-21829 + // Is all of the copying going on here really necessary? + if (nameList && U_SUCCESS(status)) { + LocalPointer<UVector> regionNames( + new UVector(uprv_deleteUObject, uhash_compareUnicodeString, nameList->size(), status), status); + for ( int32_t i = 0 ; U_SUCCESS(status) && i < nameList->size() ; i++ ) { + UnicodeString* this_region_name = (UnicodeString *)nameList->elementAt(i); + LocalPointer<UnicodeString> new_region_name(new UnicodeString(*this_region_name), status); + regionNames->adoptElement(new_region_name.orphan(), status); + } + if (U_SUCCESS(status)) { + fRegionNames = regionNames.orphan(); } - } - else { - fRegionNames = NULL; } } diff --git a/Build/source/libs/icu/icu-src/source/i18n/region_impl.h b/Build/source/libs/icu/icu-src/source/i18n/region_impl.h index 62acaa4511b..b6a281393f8 100644 --- a/Build/source/libs/icu/icu-src/source/i18n/region_impl.h +++ b/Build/source/libs/icu/icu-src/source/i18n/region_impl.h @@ -26,7 +26,11 @@ U_NAMESPACE_BEGIN class RegionNameEnumeration : public StringEnumeration { public: - RegionNameEnumeration(UVector *fNameList, UErrorCode& status); + /** + * Construct an string enumeration over the supplied name list. + * Makes a copy of the supplied input name list; does not retain a reference to the original. + */ + RegionNameEnumeration(UVector *nameList, UErrorCode& status); virtual ~RegionNameEnumeration(); static UClassID U_EXPORT2 getStaticClassID(void); virtual UClassID getDynamicClassID(void) const override; diff --git a/Build/source/libs/icu/icu-src/source/i18n/smpdtfmt.cpp b/Build/source/libs/icu/icu-src/source/i18n/smpdtfmt.cpp index 91748d82f9f..c1e943a0949 100644 --- a/Build/source/libs/icu/icu-src/source/i18n/smpdtfmt.cpp +++ b/Build/source/libs/icu/icu-src/source/i18n/smpdtfmt.cpp @@ -3792,6 +3792,9 @@ int32_t SimpleDateFormat::subParse(const UnicodeString& text, int32_t& start, UC src = &text; } parseInt(*src, number, pos, allowNegative,currentNumberFormat); + if (!isLenient() && pos.getIndex() < start + count) { + return -start; + } if (pos.getIndex() != parseStart) { int32_t val = number.getLong(); diff --git a/Build/source/libs/icu/icu-src/source/i18n/tmutfmt.cpp b/Build/source/libs/icu/icu-src/source/i18n/tmutfmt.cpp index 057bb634ebb..f0335a81f50 100644 --- a/Build/source/libs/icu/icu-src/source/i18n/tmutfmt.cpp +++ b/Build/source/libs/icu/icu-src/source/i18n/tmutfmt.cpp @@ -320,14 +320,14 @@ void TimeUnitFormat::setup(UErrorCode& err) { initDataMembers(err); - UVector pluralCounts(0, uhash_compareUnicodeString, 6, err); + UVector pluralCounts(nullptr, uhash_compareUnicodeString, 6, err); LocalPointer<StringEnumeration> keywords(getPluralRules().getKeywords(err), err); if (U_FAILURE(err)) { return; } UnicodeString* pluralCount; while ((pluralCount = const_cast<UnicodeString*>(keywords->snext(err))) != NULL) { - pluralCounts.addElementX(pluralCount, err); + pluralCounts.addElement(pluralCount, err); } readFromCurrentLocale(UTMUTFMT_FULL_STYLE, gUnitsTag, pluralCounts, err); checkConsistency(UTMUTFMT_FULL_STYLE, gUnitsTag, err); diff --git a/Build/source/libs/icu/icu-src/source/i18n/tzfmt.cpp b/Build/source/libs/icu/icu-src/source/i18n/tzfmt.cpp index ef3cfad80ce..9d046c30c8f 100644 --- a/Build/source/libs/icu/icu-src/source/i18n/tzfmt.cpp +++ b/Build/source/libs/icu/icu-src/source/i18n/tzfmt.cpp @@ -2459,7 +2459,7 @@ TimeZoneFormat::parseOffsetPattern(const UnicodeString& pattern, OffsetFields re if (itemType != GMTOffsetField::TEXT) { if (GMTOffsetField::isValid(itemType, itemLength)) { GMTOffsetField* fld = GMTOffsetField::createTimeField(itemType, static_cast<uint8_t>(itemLength), status); - result->addElementX(fld, status); + result->adoptElement(fld, status); if (U_FAILURE(status)) { break; } @@ -2485,7 +2485,7 @@ TimeZoneFormat::parseOffsetPattern(const UnicodeString& pattern, OffsetFields re if (itemType == GMTOffsetField::TEXT) { if (text.length() > 0) { GMTOffsetField* textfld = GMTOffsetField::createText(text, status); - result->addElementX(textfld, status); + result->adoptElement(textfld, status); if (U_FAILURE(status)) { break; } @@ -2494,7 +2494,7 @@ TimeZoneFormat::parseOffsetPattern(const UnicodeString& pattern, OffsetFields re } else { if (GMTOffsetField::isValid(itemType, itemLength)) { GMTOffsetField* fld = GMTOffsetField::createTimeField(itemType, static_cast<uint8_t>(itemLength), status); - result->addElementX(fld, status); + result->adoptElement(fld, status); if (U_FAILURE(status)) { break; } @@ -2512,7 +2512,7 @@ TimeZoneFormat::parseOffsetPattern(const UnicodeString& pattern, OffsetFields re if (itemType != GMTOffsetField::TEXT) { if (GMTOffsetField::isValid(itemType, itemLength)) { GMTOffsetField* fld = GMTOffsetField::createTimeField(itemType, static_cast<uint8_t>(itemLength), status); - result->addElementX(fld, status); + result->adoptElement(fld, status); if (U_FAILURE(status)) { break; } @@ -2532,12 +2532,12 @@ TimeZoneFormat::parseOffsetPattern(const UnicodeString& pattern, OffsetFields re if (itemType == GMTOffsetField::TEXT) { if (text.length() > 0) { GMTOffsetField* tfld = GMTOffsetField::createText(text, status); - result->addElementX(tfld, status); + result->adoptElement(tfld, status); } } else { if (GMTOffsetField::isValid(itemType, itemLength)) { GMTOffsetField* fld = GMTOffsetField::createTimeField(itemType, static_cast<uint8_t>(itemLength), status); - result->addElementX(fld, status); + result->adoptElement(fld, status); } else { status = U_ILLEGAL_ARGUMENT_ERROR; } diff --git a/Build/source/libs/icu/icu-src/source/i18n/tzgnames.cpp b/Build/source/libs/icu/icu-src/source/i18n/tzgnames.cpp index ed5f42d7bc1..d5ee45ced78 100644 --- a/Build/source/libs/icu/icu-src/source/i18n/tzgnames.cpp +++ b/Build/source/libs/icu/icu-src/source/i18n/tzgnames.cpp @@ -229,30 +229,27 @@ GNameSearchHandler::handleMatch(int32_t matchLength, const CharacterNode *node, if ((nameinfo->type & fTypes) != 0) { // matches a requested type if (fResults == NULL) { - fResults = new UVector(uprv_free, NULL, status); - if (fResults == NULL) { - status = U_MEMORY_ALLOCATION_ERROR; + LocalPointer<UVector> lpResults(new UVector(uprv_free, NULL, status), status); + if (U_FAILURE(status)) { + return false; } + fResults = lpResults.orphan(); } - if (U_SUCCESS(status)) { - U_ASSERT(fResults != NULL); - GMatchInfo *gmatch = (GMatchInfo *)uprv_malloc(sizeof(GMatchInfo)); - if (gmatch == NULL) { - status = U_MEMORY_ALLOCATION_ERROR; - } else { - // add the match to the vector - gmatch->gnameInfo = nameinfo; - gmatch->matchLength = matchLength; - gmatch->timeType = UTZFMT_TIME_TYPE_UNKNOWN; - fResults->addElementX(gmatch, status); - if (U_FAILURE(status)) { - uprv_free(gmatch); - } else { - if (matchLength > fMaxMatchLen) { - fMaxMatchLen = matchLength; - } - } - } + GMatchInfo *gmatch = (GMatchInfo *)uprv_malloc(sizeof(GMatchInfo)); + if (gmatch == NULL) { + status = U_MEMORY_ALLOCATION_ERROR; + return false; + } + // add the match to the vector + gmatch->gnameInfo = nameinfo; + gmatch->matchLength = matchLength; + gmatch->timeType = UTZFMT_TIME_TYPE_UNKNOWN; + fResults->adoptElement(gmatch, status); + if (U_FAILURE(status)) { + return false; + } + if (matchLength > fMaxMatchLen) { + fMaxMatchLen = matchLength; } } } diff --git a/Build/source/libs/icu/icu-src/source/i18n/tznames.cpp b/Build/source/libs/icu/icu-src/source/i18n/tznames.cpp index 5c504d01cb6..781f1cc161f 100644 --- a/Build/source/libs/icu/icu-src/source/i18n/tznames.cpp +++ b/Build/source/libs/icu/icu-src/source/i18n/tznames.cpp @@ -414,15 +414,12 @@ TimeZoneNames::MatchInfoCollection::addZone(UTimeZoneNameType nameType, int32_t if (U_FAILURE(status)) { return; } - MatchInfo* matchInfo = new MatchInfo(nameType, matchLength, &tzID, NULL); - if (matchInfo == NULL) { - status = U_MEMORY_ALLOCATION_ERROR; - return; - } - matches(status)->addElementX(matchInfo, status); + LocalPointer <MatchInfo> matchInfo(new MatchInfo(nameType, matchLength, &tzID, NULL), status); + UVector *matchesVec = matches(status); if (U_FAILURE(status)) { - delete matchInfo; + return; } + matchesVec->adoptElement(matchInfo.orphan(), status); } void @@ -431,15 +428,12 @@ TimeZoneNames::MatchInfoCollection::addMetaZone(UTimeZoneNameType nameType, int3 if (U_FAILURE(status)) { return; } - MatchInfo* matchInfo = new MatchInfo(nameType, matchLength, NULL, &mzID); - if (matchInfo == NULL) { - status = U_MEMORY_ALLOCATION_ERROR; - return; - } - matches(status)->addElementX(matchInfo, status); + LocalPointer<MatchInfo> matchInfo(new MatchInfo(nameType, matchLength, NULL, &mzID), status); + UVector *matchesVec = matches(status); if (U_FAILURE(status)) { - delete matchInfo; + return; } + matchesVec->adoptElement(matchInfo.orphan(), status); } int32_t diff --git a/Build/source/libs/icu/icu-src/source/i18n/tznames_impl.cpp b/Build/source/libs/icu/icu-src/source/i18n/tznames_impl.cpp index d450b745648..69991dfef4b 100644 --- a/Build/source/libs/icu/icu-src/source/i18n/tznames_impl.cpp +++ b/Build/source/libs/icu/icu-src/source/i18n/tznames_impl.cpp @@ -148,19 +148,29 @@ CharacterNode::addValue(void *value, UObjectDeleter *valueDeleter, UErrorCode &s if (!fHasValuesVector) { // There is only one value so far, and not in a vector yet. // Create a vector and add the old value. - UVector *values = new UVector(valueDeleter, NULL, DEFAULT_CHARACTERNODE_CAPACITY, status); + LocalPointer<UVector> values( + new UVector(valueDeleter, NULL, DEFAULT_CHARACTERNODE_CAPACITY, status), status); if (U_FAILURE(status)) { if (valueDeleter) { valueDeleter(value); } return; } - values->addElementX(fValues, status); - fValues = values; + if (values->hasDeleter()) { + values->adoptElement(fValues, status); + } else { + values->addElement(fValues, status); + } + fValues = values.orphan(); fHasValuesVector = TRUE; } // Add the new value. - ((UVector *)fValues)->addElementX(value, status); + UVector *values = (UVector *)fValues; + if (values->hasDeleter()) { + values->adoptElement(value, status); + } else { + values->addElement(value, status); + } } } @@ -219,10 +229,8 @@ void TextTrieMap::put(const UChar *key, void *value, UErrorCode &status) { fIsEmpty = FALSE; if (fLazyContents == NULL) { - fLazyContents = new UVector(status); - if (fLazyContents == NULL) { - status = U_MEMORY_ALLOCATION_ERROR; - } + LocalPointer<UVector> lpLazyContents(new UVector(status), status); + fLazyContents = lpLazyContents.orphan(); } if (U_FAILURE(status)) { if (fValueDeleter) { @@ -233,7 +241,7 @@ TextTrieMap::put(const UChar *key, void *value, UErrorCode &status) { U_ASSERT(fLazyContents != NULL); UChar *s = const_cast<UChar *>(key); - fLazyContents->addElementX(s, status); + fLazyContents->addElement(s, status); if (U_FAILURE(status)) { if (fValueDeleter) { fValueDeleter((void*) key); @@ -241,7 +249,7 @@ TextTrieMap::put(const UChar *key, void *value, UErrorCode &status) { return; } - fLazyContents->addElementX(value, status); + fLazyContents->addElement(value, status); } void @@ -854,7 +862,7 @@ class MetaZoneIDsEnumeration : public StringEnumeration { public: MetaZoneIDsEnumeration(); MetaZoneIDsEnumeration(const UVector& mzIDs); - MetaZoneIDsEnumeration(UVector* mzIDs); + MetaZoneIDsEnumeration(LocalPointer<UVector> mzIDs); virtual ~MetaZoneIDsEnumeration(); static UClassID U_EXPORT2 getStaticClassID(void); virtual UClassID getDynamicClassID(void) const override; @@ -865,7 +873,7 @@ private: int32_t fLen; int32_t fPos; const UVector* fMetaZoneIDs; - UVector *fLocalVector; + LocalPointer<UVector> fLocalVector; }; UOBJECT_DEFINE_RTTI_IMPLEMENTATION(MetaZoneIDsEnumeration) @@ -879,8 +887,9 @@ MetaZoneIDsEnumeration::MetaZoneIDsEnumeration(const UVector& mzIDs) fLen = fMetaZoneIDs->size(); } -MetaZoneIDsEnumeration::MetaZoneIDsEnumeration(UVector *mzIDs) -: fLen(0), fPos(0), fMetaZoneIDs(mzIDs), fLocalVector(mzIDs) { +MetaZoneIDsEnumeration::MetaZoneIDsEnumeration(LocalPointer<UVector> mzIDs) +: fLen(0), fPos(0), fMetaZoneIDs(nullptr), fLocalVector(std::move(mzIDs)) { + fMetaZoneIDs = fLocalVector.getAlias(); if (fMetaZoneIDs) { fLen = fMetaZoneIDs->size(); } @@ -906,9 +915,6 @@ MetaZoneIDsEnumeration::count(UErrorCode& /*status*/) const { } MetaZoneIDsEnumeration::~MetaZoneIDsEnumeration() { - if (fLocalVector) { - delete fLocalVector; - } } @@ -1153,28 +1159,23 @@ TimeZoneNamesImpl::_getAvailableMetaZoneIDs(const UnicodeString& tzID, UErrorCod return new MetaZoneIDsEnumeration(); } - MetaZoneIDsEnumeration *senum = NULL; - UVector* mzIDs = new UVector(NULL, uhash_compareUChars, status); - if (mzIDs == NULL) { - status = U_MEMORY_ALLOCATION_ERROR; - } + LocalPointer<MetaZoneIDsEnumeration> senum; + LocalPointer<UVector> mzIDs(new UVector(NULL, uhash_compareUChars, status), status); if (U_SUCCESS(status)) { - U_ASSERT(mzIDs != NULL); + U_ASSERT(mzIDs.isValid()); for (int32_t i = 0; U_SUCCESS(status) && i < mappings->size(); i++) { OlsonToMetaMappingEntry *map = (OlsonToMetaMappingEntry *)mappings->elementAt(i); const UChar *mzID = map->mzid; if (!mzIDs->contains((void *)mzID)) { - mzIDs->addElementX((void *)mzID, status); + mzIDs->addElement((void *)mzID, status); } } if (U_SUCCESS(status)) { - senum = new MetaZoneIDsEnumeration(mzIDs); - } else { - delete mzIDs; + senum.adoptInsteadAndCheckErrorCode(new MetaZoneIDsEnumeration(std::move(mzIDs)), status); } } - return senum; + return U_SUCCESS(status) ? senum.orphan() : nullptr; } UnicodeString& diff --git a/Build/source/libs/icu/icu-src/source/i18n/ucol.cpp b/Build/source/libs/icu/icu-src/source/i18n/ucol.cpp index f59333ede3c..8e1df8d5577 100644 --- a/Build/source/libs/icu/icu-src/source/i18n/ucol.cpp +++ b/Build/source/libs/icu/icu-src/source/i18n/ucol.cpp @@ -96,12 +96,18 @@ ucol_safeClone(const UCollator *coll, void * /*stackBuffer*/, int32_t * pBufferS if (newColl == NULL) { *status = U_MEMORY_ALLOCATION_ERROR; return nullptr; - } else { + } else if (pBufferSize != NULL) { *status = U_SAFECLONE_ALLOCATED_WARNING; } return newColl->toUCollator(); } +U_CAPI UCollator* U_EXPORT2 +ucol_clone(const UCollator *coll, UErrorCode *status) +{ + return ucol_safeClone(coll, nullptr, nullptr, status); +} + U_CAPI void U_EXPORT2 ucol_close(UCollator *coll) { diff --git a/Build/source/libs/icu/icu-src/source/i18n/udatpg.cpp b/Build/source/libs/icu/icu-src/source/i18n/udatpg.cpp index 332636a9388..9e61a120768 100644 --- a/Build/source/libs/icu/icu-src/source/i18n/udatpg.cpp +++ b/Build/source/libs/icu/icu-src/source/i18n/udatpg.cpp @@ -210,12 +210,47 @@ udatpg_setDateTimeFormat(const UDateTimePatternGenerator *dtpg, U_CAPI const UChar * U_EXPORT2 udatpg_getDateTimeFormat(const UDateTimePatternGenerator *dtpg, int32_t *pLength) { - const UnicodeString &result=((const DateTimePatternGenerator *)dtpg)->getDateTimeFormat(); - if(pLength!=NULL) { + UErrorCode status = U_ZERO_ERROR; + return udatpg_getDateTimeFormatForStyle(dtpg, UDAT_MEDIUM, pLength, &status); +} + +U_CAPI void U_EXPORT2 +udatpg_setDateTimeFormatForStyle(UDateTimePatternGenerator *udtpg, + UDateFormatStyle style, + const UChar *dateTimeFormat, int32_t length, + UErrorCode *pErrorCode) { + if (U_FAILURE(*pErrorCode)) { + return; + } else if (dateTimeFormat==nullptr) { + *pErrorCode = U_ILLEGAL_ARGUMENT_ERROR; + return; + } + DateTimePatternGenerator *dtpg = reinterpret_cast<DateTimePatternGenerator *>(udtpg); + UnicodeString dtFormatString((UBool)(length<0), dateTimeFormat, length); + dtpg->setDateTimeFormat(style, dtFormatString, *pErrorCode); +} + +U_CAPI const UChar* U_EXPORT2 +udatpg_getDateTimeFormatForStyle(const UDateTimePatternGenerator *udtpg, + UDateFormatStyle style, int32_t *pLength, + UErrorCode *pErrorCode) { + static const UChar emptyString[] = { (UChar)0 }; + if (U_FAILURE(*pErrorCode)) { + if (pLength !=nullptr) { + *pLength = 0; + } + return emptyString; + } + const DateTimePatternGenerator *dtpg = reinterpret_cast<const DateTimePatternGenerator *>(udtpg); + const UnicodeString &result = dtpg->getDateTimeFormat(style, *pErrorCode); + if (pLength != nullptr) { *pLength=result.length(); } + // Note: The UnicodeString for the dateTimeFormat string in the DateTimePatternGenerator + // was NUL-terminated what it was set, to avoid doing it here which could re-allocate + // the buffe and affect and cont references to the string or its buffer. return result.getBuffer(); -} + } U_CAPI void U_EXPORT2 udatpg_setDecimal(UDateTimePatternGenerator *dtpg, diff --git a/Build/source/libs/icu/icu-src/source/i18n/unicode/basictz.h b/Build/source/libs/icu/icu-src/source/i18n/unicode/basictz.h index 250ea309279..d9f85e45eef 100644 --- a/Build/source/libs/icu/icu-src/source/i18n/unicode/basictz.h +++ b/Build/source/libs/icu/icu-src/source/i18n/unicode/basictz.h @@ -152,17 +152,15 @@ public: virtual void getSimpleRulesNear(UDate date, InitialTimeZoneRule*& initial, AnnualTimeZoneRule*& std, AnnualTimeZoneRule*& dst, UErrorCode& status) const; -#ifndef U_FORCE_HIDE_DRAFT_API /** * Get time zone offsets from local wall time. - * @draft ICU 69 + * @stable ICU 69 */ virtual void getOffsetFromLocal( UDate date, UTimeZoneLocalOption nonExistingTimeOpt, UTimeZoneLocalOption duplicatedTimeOpt, int32_t& rawOffset, int32_t& dstOffset, UErrorCode& status) const; -#endif /* U_FORCE_HIDE_DRAFT_API */ #ifndef U_HIDE_INTERNAL_API /** diff --git a/Build/source/libs/icu/icu-src/source/i18n/unicode/dtptngen.h b/Build/source/libs/icu/icu-src/source/i18n/unicode/dtptngen.h index 250a0e089fe..6be0e2a571c 100644 --- a/Build/source/libs/icu/icu-src/source/i18n/unicode/dtptngen.h +++ b/Build/source/libs/icu/icu-src/source/i18n/unicode/dtptngen.h @@ -311,6 +311,11 @@ public: * for those two skeletons, so the result is put together with this pattern, * resulting in "d-MMM h:mm". * + * There are four DateTimeFormats in a DateTimePatternGenerator object, + * corresponding to date styles UDAT_FULL..UDAT_SHORT. This method sets + * all of them to the specified pattern. To set them individually, see + * setDateTimeFormat(UDateFormatStyle style, ...). + * * @param dateTimeFormat * message format pattern, here {1} will be replaced by the date * pattern and {0} will be replaced by the time pattern. @@ -320,11 +325,66 @@ public: /** * Getter corresponding to setDateTimeFormat. + * + * There are four DateTimeFormats in a DateTimePatternGenerator object, + * corresponding to date styles UDAT_FULL..UDAT_SHORT. This method gets + * the style for UDAT_MEDIUM (the default). To get them individually, see + * getDateTimeFormat(UDateFormatStyle style). + * * @return DateTimeFormat. * @stable ICU 3.8 */ const UnicodeString& getDateTimeFormat() const; +#if !UCONFIG_NO_FORMATTING +#ifndef U_HIDE_DRAFT_API + /** + * dateTimeFormats are message patterns used to compose combinations of date + * and time patterns. There are four length styles, corresponding to the + * inferred style of the date pattern; these are UDateFormatStyle values: + * - UDAT_FULL (for date pattern with weekday and long month), else + * - UDAT_LONG (for a date pattern with long month), else + * - UDAT_MEDIUM (for a date pattern with abbreviated month), else + * - UDAT_SHORT (for any other date pattern). + * For details on dateTimeFormats, see + * https://www.unicode.org/reports/tr35/tr35-dates.html#dateTimeFormats. + * The default pattern in the root locale for all styles is "{1} {0}". + * + * @param style + * one of DateFormat.FULL..DateFormat.SHORT. Error if out of range. + * @param dateTimeFormat + * the new dateTimeFormat to set for the the specified style + * @param status + * in/out parameter; if no failure status is already set, + * it will be set according to result of the function (e.g. + * U_ILLEGAL_ARGUMENT_ERROR for style out of range). + * @draft ICU 71 + */ + void setDateTimeFormat(UDateFormatStyle style, const UnicodeString& dateTimeFormat, + UErrorCode& status); + + /** + * Getter corresponding to setDateTimeFormat. + * + * @param style + * one of UDAT_FULL..UDAT_SHORT. Error if out of range. + * @param status + * in/out parameter; if no failure status is already set, + * it will be set according to result of the function (e.g. + * U_ILLEGAL_ARGUMENT_ERROR for style out of range). + * @return + * the current dateTimeFormat for the the specified style, or + * empty string in case of error. The UnicodeString reference, + * or the contents of the string, may no longer be valid if + * setDateTimeFormat is called, or the DateTimePatternGenerator + * object is deleted. + * @draft ICU 71 + */ + const UnicodeString& getDateTimeFormat(UDateFormatStyle style, + UErrorCode& status) const; +#endif /* U_HIDE_DRAFT_API */ +#endif /* #if !UCONFIG_NO_FORMATTING */ + /** * Return the best pattern matching the input skeleton. It is guaranteed to * have all of the fields in the skeleton. @@ -545,8 +605,7 @@ private: */ DateTimePatternGenerator& operator=(const DateTimePatternGenerator& other); - // TODO(ticket:13619): re-enable when UDATPG_NARROW no longer in draft mode. - // static const int32_t UDATPG_WIDTH_COUNT = UDATPG_NARROW + 1; + static const int32_t UDATPG_WIDTH_COUNT = UDATPG_NARROW + 1; Locale pLocale; // pattern locale FormatParser *fp; @@ -554,9 +613,8 @@ private: DistanceInfo *distanceInfo; PatternMap *patternMap; UnicodeString appendItemFormats[UDATPG_FIELD_COUNT]; - // TODO(ticket:13619): [3] -> UDATPG_WIDTH_COUNT - UnicodeString fieldDisplayNames[UDATPG_FIELD_COUNT][3]; - UnicodeString dateTimeFormat; + UnicodeString fieldDisplayNames[UDATPG_FIELD_COUNT][UDATPG_WIDTH_COUNT]; + UnicodeString dateTimeFormat[4]; UnicodeString decimal; DateTimeMatcher *skipMatcher; Hashtable *fAvailableFormatKeyHash; diff --git a/Build/source/libs/icu/icu-src/source/i18n/unicode/measunit.h b/Build/source/libs/icu/icu-src/source/i18n/unicode/measunit.h index 61da62e71f2..b7e8e1676a4 100644 --- a/Build/source/libs/icu/icu-src/source/i18n/unicode/measunit.h +++ b/Build/source/libs/icu/icu-src/source/i18n/unicode/measunit.h @@ -77,14 +77,13 @@ enum UMeasureUnitComplexity { }; -#ifndef U_HIDE_DRAFT_API /** * Enumeration for SI and binary prefixes, e.g. "kilo-", "nano-", "mebi-". * * Enum values should be treated as opaque: use umeas_getPrefixPower() and * umeas_getPrefixBase() to find their corresponding values. * - * @draft ICU 69 + * @stable ICU 69 * @see umeas_getPrefixBase * @see umeas_getPrefixPower */ @@ -96,14 +95,14 @@ typedef enum UMeasurePrefix { * implementation detail and should not be relied upon: use * umeas_getPrefixPower() to obtain meaningful values. * - * @draft ICU 69 + * @stable ICU 69 */ UMEASURE_PREFIX_ONE = 30 + 0, /** * SI prefix: yotta, 10^24. * - * @draft ICU 69 + * @stable ICU 69 */ UMEASURE_PREFIX_YOTTA = UMEASURE_PREFIX_ONE + 24, @@ -119,133 +118,133 @@ typedef enum UMeasurePrefix { /** * SI prefix: zetta, 10^21. * - * @draft ICU 69 + * @stable ICU 69 */ UMEASURE_PREFIX_ZETTA = UMEASURE_PREFIX_ONE + 21, /** * SI prefix: exa, 10^18. * - * @draft ICU 69 + * @stable ICU 69 */ UMEASURE_PREFIX_EXA = UMEASURE_PREFIX_ONE + 18, /** * SI prefix: peta, 10^15. * - * @draft ICU 69 + * @stable ICU 69 */ UMEASURE_PREFIX_PETA = UMEASURE_PREFIX_ONE + 15, /** * SI prefix: tera, 10^12. * - * @draft ICU 69 + * @stable ICU 69 */ UMEASURE_PREFIX_TERA = UMEASURE_PREFIX_ONE + 12, /** * SI prefix: giga, 10^9. * - * @draft ICU 69 + * @stable ICU 69 */ UMEASURE_PREFIX_GIGA = UMEASURE_PREFIX_ONE + 9, /** * SI prefix: mega, 10^6. * - * @draft ICU 69 + * @stable ICU 69 */ UMEASURE_PREFIX_MEGA = UMEASURE_PREFIX_ONE + 6, /** * SI prefix: kilo, 10^3. * - * @draft ICU 69 + * @stable ICU 69 */ UMEASURE_PREFIX_KILO = UMEASURE_PREFIX_ONE + 3, /** * SI prefix: hecto, 10^2. * - * @draft ICU 69 + * @stable ICU 69 */ UMEASURE_PREFIX_HECTO = UMEASURE_PREFIX_ONE + 2, /** * SI prefix: deka, 10^1. * - * @draft ICU 69 + * @stable ICU 69 */ UMEASURE_PREFIX_DEKA = UMEASURE_PREFIX_ONE + 1, /** * SI prefix: deci, 10^-1. * - * @draft ICU 69 + * @stable ICU 69 */ UMEASURE_PREFIX_DECI = UMEASURE_PREFIX_ONE + -1, /** * SI prefix: centi, 10^-2. * - * @draft ICU 69 + * @stable ICU 69 */ UMEASURE_PREFIX_CENTI = UMEASURE_PREFIX_ONE + -2, /** * SI prefix: milli, 10^-3. * - * @draft ICU 69 + * @stable ICU 69 */ UMEASURE_PREFIX_MILLI = UMEASURE_PREFIX_ONE + -3, /** * SI prefix: micro, 10^-6. * - * @draft ICU 69 + * @stable ICU 69 */ UMEASURE_PREFIX_MICRO = UMEASURE_PREFIX_ONE + -6, /** * SI prefix: nano, 10^-9. * - * @draft ICU 69 + * @stable ICU 69 */ UMEASURE_PREFIX_NANO = UMEASURE_PREFIX_ONE + -9, /** * SI prefix: pico, 10^-12. * - * @draft ICU 69 + * @stable ICU 69 */ UMEASURE_PREFIX_PICO = UMEASURE_PREFIX_ONE + -12, /** * SI prefix: femto, 10^-15. * - * @draft ICU 69 + * @stable ICU 69 */ UMEASURE_PREFIX_FEMTO = UMEASURE_PREFIX_ONE + -15, /** * SI prefix: atto, 10^-18. * - * @draft ICU 69 + * @stable ICU 69 */ UMEASURE_PREFIX_ATTO = UMEASURE_PREFIX_ONE + -18, /** * SI prefix: zepto, 10^-21. * - * @draft ICU 69 + * @stable ICU 69 */ UMEASURE_PREFIX_ZEPTO = UMEASURE_PREFIX_ONE + -21, /** * SI prefix: yocto, 10^-24. * - * @draft ICU 69 + * @stable ICU 69 */ UMEASURE_PREFIX_YOCTO = UMEASURE_PREFIX_ONE + -24, @@ -270,7 +269,7 @@ typedef enum UMeasurePrefix { /** * Binary prefix: kibi, 1024^1. * - * @draft ICU 69 + * @stable ICU 69 */ UMEASURE_PREFIX_KIBI = UMEASURE_PREFIX_INTERNAL_ONE_BIN + 1, @@ -286,49 +285,49 @@ typedef enum UMeasurePrefix { /** * Binary prefix: mebi, 1024^2. * - * @draft ICU 69 + * @stable ICU 69 */ UMEASURE_PREFIX_MEBI = UMEASURE_PREFIX_INTERNAL_ONE_BIN + 2, /** * Binary prefix: gibi, 1024^3. * - * @draft ICU 69 + * @stable ICU 69 */ UMEASURE_PREFIX_GIBI = UMEASURE_PREFIX_INTERNAL_ONE_BIN + 3, /** * Binary prefix: tebi, 1024^4. * - * @draft ICU 69 + * @stable ICU 69 */ UMEASURE_PREFIX_TEBI = UMEASURE_PREFIX_INTERNAL_ONE_BIN + 4, /** * Binary prefix: pebi, 1024^5. * - * @draft ICU 69 + * @stable ICU 69 */ UMEASURE_PREFIX_PEBI = UMEASURE_PREFIX_INTERNAL_ONE_BIN + 5, /** * Binary prefix: exbi, 1024^6. * - * @draft ICU 69 + * @stable ICU 69 */ UMEASURE_PREFIX_EXBI = UMEASURE_PREFIX_INTERNAL_ONE_BIN + 6, /** * Binary prefix: zebi, 1024^7. * - * @draft ICU 69 + * @stable ICU 69 */ UMEASURE_PREFIX_ZEBI = UMEASURE_PREFIX_INTERNAL_ONE_BIN + 7, /** * Binary prefix: yobi, 1024^8. * - * @draft ICU 69 + * @stable ICU 69 */ UMEASURE_PREFIX_YOBI = UMEASURE_PREFIX_INTERNAL_ONE_BIN + 8, @@ -347,7 +346,7 @@ typedef enum UMeasurePrefix { * base is 10 for SI prefixes (kilo, micro) and 1024 for binary prefixes (kibi, * mebi). * - * @draft ICU 69 + * @stable ICU 69 */ U_CAPI int32_t U_EXPORT2 umeas_getPrefixBase(UMeasurePrefix unitPrefix); @@ -355,12 +354,10 @@ U_CAPI int32_t U_EXPORT2 umeas_getPrefixBase(UMeasurePrefix unitPrefix); * Returns the exponent of the factor associated with the given unit prefix, for * example 3 for kilo, -6 for micro, 1 for kibi, 2 for mebi, 3 for gibi. * - * @draft ICU 69 + * @stable ICU 69 */ U_CAPI int32_t U_EXPORT2 umeas_getPrefixPower(UMeasurePrefix unitPrefix); -#endif // U_HIDE_DRAFT_API - /** * A unit such as length, mass, volume, currency, etc. A unit is * coupled with a numeric amount to produce a Measure. @@ -481,7 +478,6 @@ class U_I18N_API MeasureUnit: public UObject { */ UMeasureUnitComplexity getComplexity(UErrorCode& status) const; -#ifndef U_HIDE_DRAFT_API /** * Creates a MeasureUnit which is this SINGLE unit augmented with the specified prefix. * For example, UMEASURE_PREFIX_KILO for "kilo", or UMEASURE_PREFIX_KIBI for "kibi". @@ -494,7 +490,7 @@ class U_I18N_API MeasureUnit: public UObject { * @param prefix The prefix, from UMeasurePrefix. * @param status Set if this is not a SINGLE unit or if another error occurs. * @return A new SINGLE unit. - * @draft ICU 69 + * @stable ICU 69 */ MeasureUnit withPrefix(UMeasurePrefix prefix, UErrorCode& status) const; @@ -510,10 +506,9 @@ class U_I18N_API MeasureUnit: public UObject { * @return The prefix of this SINGLE unit, from UMeasurePrefix. * @see umeas_getPrefixBase * @see umeas_getPrefixPower - * @draft ICU 69 + * @stable ICU 69 */ UMeasurePrefix getPrefix(UErrorCode& status) const; -#endif // U_HIDE_DRAFT_API /** * Creates a MeasureUnit which is this SINGLE unit augmented with the specified dimensionality @@ -989,23 +984,21 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit getKarat(); -#ifndef U_HIDE_DRAFT_API /** * Returns by pointer, unit of concentr: milligram-ofglucose-per-deciliter. * Caller owns returned value and must free it. * Also see {@link #getMilligramOfglucosePerDeciliter()}. * @param status ICU error code. - * @draft ICU 69 + * @stable ICU 69 */ static MeasureUnit *createMilligramOfglucosePerDeciliter(UErrorCode &status); /** * Returns by value, unit of concentr: milligram-ofglucose-per-deciliter. * Also see {@link #createMilligramOfglucosePerDeciliter()}. - * @draft ICU 69 + * @stable ICU 69 */ static MeasureUnit getMilligramOfglucosePerDeciliter(); -#endif /* U_HIDE_DRAFT_API */ /** * Returns by pointer, unit of concentr: milligram-per-deciliter. diff --git a/Build/source/libs/icu/icu-src/source/i18n/unicode/numberformatter.h b/Build/source/libs/icu/icu-src/source/i18n/unicode/numberformatter.h index ece433b55f0..711064ece8d 100644 --- a/Build/source/libs/icu/icu-src/source/i18n/unicode/numberformatter.h +++ b/Build/source/libs/icu/icu-src/source/i18n/unicode/numberformatter.h @@ -22,6 +22,7 @@ #include "unicode/parseerr.h" #include "unicode/plurrule.h" #include "unicode/ucurr.h" +#include "unicode/unounclass.h" #include "unicode/unum.h" #include "unicode/unumberformatter.h" #include "unicode/uobject.h" @@ -640,6 +641,33 @@ class U_I18N_API Precision : public UMemory { */ static IncrementPrecision increment(double roundingIncrement); +#ifndef U_HIDE_DRAFT_API + /** + * Version of `Precision::increment()` that takes an integer at a particular power of 10. + * + * To round to the nearest 0.5 and display 2 fraction digits, with this function, you should write one of the following: + * + * <pre> + * Precision::incrementExact(5, -1).withMinFraction(2) + * Precision::incrementExact(50, -2).withMinFraction(2) + * Precision::incrementExact(50, -2) + * </pre> + * + * This is analagous to ICU4J `Precision.increment(new BigDecimal("0.50"))`. + * + * This behavior is modeled after ECMA-402. For more information, see: + * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat/NumberFormat#roundingincrement + * + * @param mantissa + * The increment to which to round numbers. + * @param magnitude + * The power of 10 of the ones digit of the mantissa. + * @return A precision for chaining or passing to the NumberFormatter precision() setter. + * @draft ICU 71 + */ + static IncrementPrecision incrementExact(uint64_t mantissa, int16_t magnitude); +#endif // U_HIDE_DRAFT_API + /** * Show numbers rounded and padded according to the rules for the currency unit. The most common * rounding precision settings for currencies include <code>Precision::fixedFraction(2)</code>, @@ -659,16 +687,14 @@ class U_I18N_API Precision : public UMemory { */ static CurrencyPrecision currency(UCurrencyUsage currencyUsage); -#ifndef U_HIDE_DRAFT_API /** * Configure how trailing zeros are displayed on numbers. For example, to hide trailing zeros * when the number is an integer, use UNUM_TRAILING_ZERO_HIDE_IF_WHOLE. * * @param trailingZeroDisplay Option to configure the display of trailing zeros. - * @draft ICU 69 + * @stable ICU 69 */ Precision trailingZeroDisplay(UNumberTrailingZeroDisplay trailingZeroDisplay) const; -#endif // U_HIDE_DRAFT_API private: enum PrecisionType { @@ -707,16 +733,23 @@ class U_I18N_API Precision : public UMemory { impl::digits_t fMaxSig; /** @internal (private) */ UNumberRoundingPriority fPriority; + /** + * Whether to retain trailing zeros based on the looser strategy. + * @internal (private) + */ + bool fRetain; } fracSig; /** @internal (private) */ struct IncrementSettings { // For RND_INCREMENT, RND_INCREMENT_ONE, and RND_INCREMENT_FIVE + // Note: This is a union, so we shouldn't own memory, since + // the default destructor would leak it. /** @internal (private) */ - double fIncrement; + uint64_t fIncrement; /** @internal (private) */ - impl::digits_t fMinFrac; + impl::digits_t fIncrementMagnitude; /** @internal (private) */ - impl::digits_t fMaxFrac; + impl::digits_t fMinFrac; } increment; UCurrencyUsage currencyUsage; // For RND_CURRENCY UErrorCode errorCode; // For RND_ERROR @@ -759,9 +792,10 @@ class U_I18N_API Precision : public UMemory { const FractionPrecision &base, int32_t minSig, int32_t maxSig, - UNumberRoundingPriority priority); + UNumberRoundingPriority priority, + bool retain); - static IncrementPrecision constructIncrement(double increment, int32_t minFrac); + static IncrementPrecision constructIncrement(uint64_t increment, impl::digits_t magnitude); static CurrencyPrecision constructCurrency(UCurrencyUsage usage); @@ -801,7 +835,6 @@ class U_I18N_API Precision : public UMemory { */ class U_I18N_API FractionPrecision : public Precision { public: -#ifndef U_HIDE_DRAFT_API /** * Override maximum fraction digits with maximum significant digits depending on the magnitude * of the number. See UNumberRoundingPriority. @@ -814,13 +847,12 @@ class U_I18N_API FractionPrecision : public Precision { * How to disambiguate between fraction digits and significant digits. * @return A precision for chaining or passing to the NumberFormatter precision() setter. * - * @draft ICU 69 + * @stable ICU 69 */ Precision withSignificantDigits( int32_t minSignificantDigits, int32_t maxSignificantDigits, UNumberRoundingPriority priority) const; -#endif // U_HIDE_DRAFT_API /** * Ensure that no less than this number of significant digits are retained when rounding @@ -1170,22 +1202,26 @@ class U_I18N_API Scale : public UMemory { namespace impl { -// Do not enclose entire StringProp with #ifndef U_HIDE_INTERNAL_API, needed for a protected field +// Do not enclose entire StringProp with #ifndef U_HIDE_INTERNAL_API, needed for a protected field. +// And do not enclose its class boilerplate within #ifndef U_HIDE_INTERNAL_API. /** * Manages NumberFormatterSettings::usage()'s char* instance on the heap. * @internal */ class U_I18N_API StringProp : public UMemory { -#ifndef U_HIDE_INTERNAL_API - public: /** @internal */ + ~StringProp(); + + /** @internal */ StringProp(const StringProp &other); /** @internal */ StringProp &operator=(const StringProp &other); +#ifndef U_HIDE_INTERNAL_API + /** @internal */ StringProp(StringProp &&src) U_NOEXCEPT; @@ -1193,9 +1229,6 @@ class U_I18N_API StringProp : public UMemory { StringProp &operator=(StringProp &&src) U_NOEXCEPT; /** @internal */ - ~StringProp(); - - /** @internal */ int16_t length() const { return fLength; } @@ -2735,14 +2768,20 @@ class U_I18N_API FormattedNumber : public UMemory, public FormattedValue { */ MeasureUnit getOutputUnit(UErrorCode& status) const; -#ifndef U_HIDE_INTERNAL_API +#ifndef U_HIDE_DRAFT_API + /** - * Gets the gender of the formatted output. Returns "" when the gender is - * unknown, or for ungendered languages. + * Gets the noun class of the formatted output. Returns `OTHER` when the noun class + * is not supported yet. * - * @internal ICU 69 technology preview. + * @return `NounClass` + * @draft ICU 71. */ - const char *getGender(UErrorCode& status) const; + NounClass getNounClass(UErrorCode &status) const; + +#endif // U_HIDE_DRAFT_API + +#ifndef U_HIDE_INTERNAL_API /** * Gets the raw DecimalQuantity for plural rule selection. @@ -2758,6 +2797,18 @@ class U_I18N_API FormattedNumber : public UMemory, public FormattedValue { #endif /* U_HIDE_INTERNAL_API */ +#ifndef U_HIDE_DEPRECATED_API + + /** + * Gets the gender of the formatted output. Returns "" when the gender is + * unknown, or for ungendered languages. + * + * @deprecated This API is for ICU internal use only. + */ + const char *getGender(UErrorCode &status) const; + +#endif /* U_HIDE_DEPRECATED_API */ + private: // Can't use LocalPointer because UFormattedNumberData is forward-declared const impl::UFormattedNumberData *fData; diff --git a/Build/source/libs/icu/icu-src/source/i18n/unicode/rbtz.h b/Build/source/libs/icu/icu-src/source/i18n/unicode/rbtz.h index 1eca70c338b..4fbf330cef1 100644 --- a/Build/source/libs/icu/icu-src/source/i18n/unicode/rbtz.h +++ b/Build/source/libs/icu/icu-src/source/i18n/unicode/rbtz.h @@ -303,16 +303,14 @@ public: virtual void getTimeZoneRules(const InitialTimeZoneRule*& initial, const TimeZoneRule* trsrules[], int32_t& trscount, UErrorCode& status) const override; -#ifndef U_FORCE_HIDE_DRAFT_API /** * Get time zone offsets from local wall time. - * @draft ICU 69 + * @stable ICU 69 */ virtual void getOffsetFromLocal( UDate date, UTimeZoneLocalOption nonExistingTimeOpt, UTimeZoneLocalOption duplicatedTimeOpt, int32_t& rawOffset, int32_t& dstOffset, UErrorCode& status) const override; -#endif /* U_FORCE_HIDE_DRAFT_API */ private: void deleteRules(void); diff --git a/Build/source/libs/icu/icu-src/source/i18n/unicode/simpletz.h b/Build/source/libs/icu/icu-src/source/i18n/unicode/simpletz.h index f5c155de466..f73d823ee58 100644 --- a/Build/source/libs/icu/icu-src/source/i18n/unicode/simpletz.h +++ b/Build/source/libs/icu/icu-src/source/i18n/unicode/simpletz.h @@ -620,16 +620,14 @@ public: virtual void getOffset(UDate date, UBool local, int32_t& rawOffset, int32_t& dstOffset, UErrorCode& ec) const override; -#ifndef U_FORCE_HIDE_DRAFT_API /** * Get time zone offsets from local wall time. - * @draft ICU 69 + * @stable ICU 69 */ virtual void getOffsetFromLocal( UDate date, UTimeZoneLocalOption nonExistingTimeOpt, UTimeZoneLocalOption duplicatedTimeOpt, int32_t& rawOffset, int32_t& dstOffset, UErrorCode& status) const override; -#endif /* U_FORCE_HIDE_DRAFT_API */ /** * Returns the TimeZone's raw GMT offset (i.e., the number of milliseconds to add diff --git a/Build/source/libs/icu/icu-src/source/i18n/unicode/ucal.h b/Build/source/libs/icu/icu-src/source/i18n/unicode/ucal.h index 94abae83919..3a4fb69fc3e 100644 --- a/Build/source/libs/icu/icu-src/source/i18n/unicode/ucal.h +++ b/Build/source/libs/icu/icu-src/source/i18n/unicode/ucal.h @@ -1617,25 +1617,23 @@ U_CAPI int32_t U_EXPORT2 ucal_getTimeZoneIDForWindowsID(const UChar* winid, int32_t len, const char* region, UChar* id, int32_t idCapacity, UErrorCode* status); -#ifndef U_FORCE_HIDE_DRAFT_API /** * Options used by ucal_getTimeZoneOffsetFromLocal and BasicTimeZone::getOffsetFromLocal() * to specify how to interpret an input time when it does not exist, or when it is ambiguous, * around a time zone transition. - * @draft ICU 69 + * @stable ICU 69 */ enum UTimeZoneLocalOption { -#ifndef U_HIDE_DRAFT_API /** * An input time is always interpreted as local time before * a time zone transition. - * @draft ICU 69 + * @stable ICU 69 */ UCAL_TZ_LOCAL_FORMER = 0x04, /** * An input time is always interpreted as local time after * a time zone transition. - * @draft ICU 69 + * @stable ICU 69 */ UCAL_TZ_LOCAL_LATTER = 0x0C, /** @@ -1644,7 +1642,7 @@ enum UTimeZoneLocalOption { * sides of a time zone transition are standard time, * or daylight saving time, the local time before the * transition is used. - * @draft ICU 69 + * @stable ICU 69 */ UCAL_TZ_LOCAL_STANDARD_FORMER = UCAL_TZ_LOCAL_FORMER | 0x01, /** @@ -1653,7 +1651,7 @@ enum UTimeZoneLocalOption { * sides of a time zone transition are standard time, * or daylight saving time, the local time after the * transition is used. - * @draft ICU 69 + * @stable ICU 69 */ UCAL_TZ_LOCAL_STANDARD_LATTER = UCAL_TZ_LOCAL_LATTER | 0x01, /** @@ -1662,7 +1660,7 @@ enum UTimeZoneLocalOption { * sides of a time zone transition are standard time, * or daylight saving time, the local time before the * transition is used. - * @draft ICU 69 + * @stable ICU 69 */ UCAL_TZ_LOCAL_DAYLIGHT_FORMER = UCAL_TZ_LOCAL_FORMER | 0x03, /** @@ -1671,19 +1669,11 @@ enum UTimeZoneLocalOption { * sides of a time zone transition are standard time, * or daylight saving time, the local time after the * transition is used. - * @draft ICU 69 + * @stable ICU 69 */ UCAL_TZ_LOCAL_DAYLIGHT_LATTER = UCAL_TZ_LOCAL_LATTER | 0x03, -#else /* U_HIDE_DRAFT_API */ - /** - * Dummy value to prevent empty enum if U_HIDE_DRAFT_API. - * This will go away when draft conditionals are removed. - * @internal - */ - UCAL_TZ_LOCAL_NONE = 0, -#endif /* U_HIDE_DRAFT_API */ }; -typedef enum UTimeZoneLocalOption UTimeZoneLocalOption; /**< @draft ICU 69 */ +typedef enum UTimeZoneLocalOption UTimeZoneLocalOption; /**< @stable ICU 69 */ /** * Returns the time zone raw and GMT offset for the given moment @@ -1710,7 +1700,7 @@ typedef enum UTimeZoneLocalOption UTimeZoneLocalOption; /**< @draft ICU 69 */ * typically one hour. * If the status is set to one of the error code, the value set is unspecified. * @param status A pointer to a UErrorCode to receive any errors. -* @draft ICU 69 +* @stable ICU 69 */ U_CAPI void U_EXPORT2 ucal_getTimeZoneOffsetFromLocal( @@ -1718,7 +1708,6 @@ ucal_getTimeZoneOffsetFromLocal( UTimeZoneLocalOption nonExistingTimeOpt, UTimeZoneLocalOption duplicatedTimeOpt, int32_t* rawOffset, int32_t* dstOffset, UErrorCode* status); -#endif /* U_FORCE_HIDE_DRAFT_API */ #endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/Build/source/libs/icu/icu-src/source/i18n/unicode/ucol.h b/Build/source/libs/icu/icu-src/source/i18n/unicode/ucol.h index 6d22eb6069e..24963312216 100644 --- a/Build/source/libs/icu/icu-src/source/i18n/unicode/ucol.h +++ b/Build/source/libs/icu/icu-src/source/i18n/unicode/ucol.h @@ -397,7 +397,7 @@ typedef enum { * @param status A pointer to a UErrorCode to receive any errors * @return A pointer to a UCollator, or 0 if an error occurred. * @see ucol_openRules - * @see ucol_safeClone + * @see ucol_clone * @see ucol_close * @stable ICU 2.0 */ @@ -425,7 +425,7 @@ ucol_open(const char *loc, UErrorCode *status); * @return A pointer to a UCollator. It is not guaranteed that NULL be returned in case * of error - please use status argument to check for errors. * @see ucol_open - * @see ucol_safeClone + * @see ucol_clone * @see ucol_close * @stable ICU 2.0 */ @@ -521,7 +521,7 @@ ucol_getContractionsAndExpansions( const UCollator *coll, * @param coll The UCollator to close. * @see ucol_open * @see ucol_openRules - * @see ucol_safeClone + * @see ucol_clone * @stable ICU 2.0 */ U_CAPI void U_EXPORT2 @@ -985,7 +985,6 @@ ucol_getShortDefinitionString(const UCollator *coll, * * @deprecated ICU 54 */ - U_DEPRECATED int32_t U_EXPORT2 ucol_normalizeShortDefinitionString(const char *source, char *destination, @@ -1313,6 +1312,20 @@ ucol_restoreVariableTop(UCollator *coll, const uint32_t varTop, UErrorCode *stat /** * Thread safe cloning operation. The result is a clone of a given collator. * @param coll collator to be cloned + * @param status to indicate whether the operation went on smoothly or there were errors + * @return pointer to the new clone + * @see ucol_open + * @see ucol_openRules + * @see ucol_close + * @stable ICU 71 + */ +U_CAPI UCollator* U_EXPORT2 ucol_clone(const UCollator *coll, UErrorCode *status); + +#ifndef U_HIDE_DEPRECATED_API + +/** + * Thread safe cloning operation. The result is a clone of a given collator. + * @param coll collator to be cloned * @param stackBuffer <em>Deprecated functionality as of ICU 52, use NULL.</em><br> * user allocated space for the new clone. * If NULL new memory will be allocated. @@ -1325,21 +1338,20 @@ ucol_restoreVariableTop(UCollator *coll, const uint32_t varTop, UErrorCode *stat * If *pBufferSize is not enough for a stack-based safe clone, * new memory will be allocated. * @param status to indicate whether the operation went on smoothly or there were errors - * An informational status value, U_SAFECLONE_ALLOCATED_ERROR, is used if any - * allocations were necessary. + * An informational status value, U_SAFECLONE_ALLOCATED_ERROR, is used + * if pBufferSize != NULL and any allocations were necessary * @return pointer to the new clone * @see ucol_open * @see ucol_openRules * @see ucol_close - * @stable ICU 2.0 + * @deprecated ICU 71 Use ucol_clone() instead. */ -U_CAPI UCollator* U_EXPORT2 +U_DEPRECATED UCollator* U_EXPORT2 ucol_safeClone(const UCollator *coll, void *stackBuffer, int32_t *pBufferSize, UErrorCode *status); -#ifndef U_HIDE_DEPRECATED_API /** default memory size for the new clone. * @deprecated ICU 52. Do not rely on ucol_safeClone() cloning into any provided buffer. diff --git a/Build/source/libs/icu/icu-src/source/i18n/unicode/udatpg.h b/Build/source/libs/icu/icu-src/source/i18n/unicode/udatpg.h index efe4357bfee..684a905e426 100644 --- a/Build/source/libs/icu/icu-src/source/i18n/unicode/udatpg.h +++ b/Build/source/libs/icu/icu-src/source/i18n/unicode/udatpg.h @@ -492,6 +492,11 @@ udatpg_getFieldDisplayName(const UDateTimePatternGenerator *dtpg, * for those two skeletons, so the result is put together with this pattern, * resulting in "d-MMM h:mm". * + * There are four DateTimeFormats in a UDateTimePatternGenerator object, + * corresponding to date styles UDAT_FULL..UDAT_SHORT. This method sets + * all of them to the specified pattern. To set them individually, see + * udatpg_setDateTimeFormatForStyle. + * * @param dtpg a pointer to UDateTimePatternGenerator. * @param dtFormat * message format pattern, here {1} will be replaced by the date @@ -505,6 +510,12 @@ udatpg_setDateTimeFormat(const UDateTimePatternGenerator *dtpg, /** * Getter corresponding to setDateTimeFormat. + * + * There are four DateTimeFormats in a UDateTimePatternGenerator object, + * corresponding to date styles UDAT_FULL..UDAT_SHORT. This method gets + * the style for UDAT_MEDIUM (the default). To get them individually, see + * udatpg_getDateTimeFormatForStyle. + * * @param dtpg a pointer to UDateTimePatternGenerator. * @param pLength A pointer that will receive the length of the format * @return dateTimeFormat. @@ -514,6 +525,70 @@ U_CAPI const UChar * U_EXPORT2 udatpg_getDateTimeFormat(const UDateTimePatternGenerator *dtpg, int32_t *pLength); +#if !UCONFIG_NO_FORMATTING +#ifndef U_HIDE_DRAFT_API +/** + * dateTimeFormats are message patterns used to compose combinations of date + * and time patterns. There are four length styles, corresponding to the + * inferred style of the date pattern; these are UDateFormatStyle values: + * - UDAT_FULL (for date pattern with weekday and long month), else + * - UDAT_LONG (for a date pattern with long month), else + * - UDAT_MEDIUM (for a date pattern with abbreviated month), else + * - UDAT_SHORT (for any other date pattern). + * For details on dateTimeFormats, see + * https://www.unicode.org/reports/tr35/tr35-dates.html#dateTimeFormats. + * The default pattern in the root locale for all styles is "{1} {0}". + * + * @param udtpg + * a pointer to the UDateTimePatternGenerator + * @param style + * one of UDAT_FULL..UDAT_SHORT. Error if out of range. + * @param dateTimeFormat + * the new dateTimeFormat to set for the the specified style + * @param length + * the length of dateTimeFormat, or -1 if unknown and pattern + * is null-terminated + * @param pErrorCode + * a pointer to the UErrorCode (in/out parameter); if no failure + * status is already set, it will be set according to result of the + * function (e.g. U_ILLEGAL_ARGUMENT_ERROR for style out of range). + * @draft ICU 71 + */ +U_CAPI void U_EXPORT2 +udatpg_setDateTimeFormatForStyle(UDateTimePatternGenerator *udtpg, + UDateFormatStyle style, + const UChar *dateTimeFormat, int32_t length, + UErrorCode *pErrorCode); + +/** + * Getter corresponding to udatpg_setDateTimeFormatForStyle. + * + * @param udtpg + * a pointer to the UDateTimePatternGenerator + * @param style + * one of UDAT_FULL..UDAT_SHORT. Error if out of range. + * @param pLength + * a pointer that will receive the length of the format. May be NULL + * if length is not desired. + * @param pErrorCode + * a pointer to the UErrorCode (in/out parameter); if no failure + * status is already set, it will be set according to result of the + * function (e.g. U_ILLEGAL_ARGUMENT_ERROR for style out of range). + * @return + * pointer to the current dateTimeFormat (0 terminated) for the specified + * style, or empty string in case of error. The pointer and its contents + * may no longer be valid if udatpg_setDateTimeFormat is called, or + * udatpg_setDateTimeFormatForStyle for the same style is called, or the + * UDateTimePatternGenerator object is closed. + * @draft ICU 71 + */ +U_CAPI const UChar* U_EXPORT2 +udatpg_getDateTimeFormatForStyle(const UDateTimePatternGenerator *udtpg, + UDateFormatStyle style, int32_t *pLength, + UErrorCode *pErrorCode); +#endif /* U_HIDE_DRAFT_API */ +#endif /* #if !UCONFIG_NO_FORMATTING */ + /** * The decimal value is used in formatting fractions of seconds. If the * skeleton contains fractional seconds, then this is used with the diff --git a/Build/source/libs/icu/icu-src/source/i18n/unicode/unounclass.h b/Build/source/libs/icu/icu-src/source/i18n/unicode/unounclass.h new file mode 100644 index 00000000000..1721dbd584f --- /dev/null +++ b/Build/source/libs/icu/icu-src/source/i18n/unicode/unounclass.h @@ -0,0 +1,43 @@ +// © 2022 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html + +#ifndef __UNOUNCLASS_H__ +#define __UNOUNCLASS_H__ + +#include "unicode/utypes.h" + +#if U_SHOW_CPLUSPLUS_API + +#if !UCONFIG_NO_FORMATTING + +#include "unicode/uversion.h" + +U_NAMESPACE_BEGIN + +#ifndef U_HIDE_DRAFT_API + +/** + * Represents all the grammatical noun classes that are supported by CLDR. + * + * @draft ICU 71. + */ +enum NounClass { + OTHER = 0, + NEUTER = 1, + FEMININE = 2, + MASCULINE = 3, + ANIMATE = 4, + INANIMATE = 5, + PERSONAL = 6, + COMMON = 7, +}; + +#endif // U_HIDE_DRAFT_API + +U_NAMESPACE_END + +#endif /* #if !UCONFIG_NO_FORMATTING */ + +#endif /* U_SHOW_CPLUSPLUS_API */ + +#endif // __UNOUNCLASS_H__ diff --git a/Build/source/libs/icu/icu-src/source/i18n/unicode/unum.h b/Build/source/libs/icu/icu-src/source/i18n/unicode/unum.h index 14f76168b61..863695591ab 100644 --- a/Build/source/libs/icu/icu-src/source/i18n/unicode/unum.h +++ b/Build/source/libs/icu/icu-src/source/i18n/unicode/unum.h @@ -303,23 +303,21 @@ typedef enum UNumberFormatRoundingMode { * @stable ICU 4.8 */ UNUM_ROUND_UNNECESSARY, -#ifndef U_HIDE_DRAFT_API /** * Rounds ties toward the odd number. - * @draft ICU 69 + * @stable ICU 69 */ UNUM_ROUND_HALF_ODD, /** * Rounds ties toward +∞. - * @draft ICU 69 + * @stable ICU 69 */ UNUM_ROUND_HALF_CEILING, /** * Rounds ties toward -∞. - * @draft ICU 69 + * @stable ICU 69 */ UNUM_ROUND_HALF_FLOOR, -#endif // U_HIDE_DRAFT_API } UNumberFormatRoundingMode; /** The possible number format pad positions. @@ -401,13 +399,24 @@ typedef enum UNumberFormatFields { UNUM_MEASURE_UNIT_FIELD, /** @stable ICU 64 */ UNUM_COMPACT_FIELD, +#ifndef U_HIDE_DRAFT_API + /** + * Approximately sign. In ICU 70, this was categorized under the generic SIGN field. + * @draft ICU 71 + */ + UNUM_APPROXIMATELY_SIGN_FIELD, +#endif // U_HIDE_DRAFT_API #ifndef U_HIDE_DEPRECATED_API /** * One more than the highest normal UNumberFormatFields value. * @deprecated ICU 58 The numeric value may change over time, see ICU ticket #12420. */ - UNUM_FIELD_COUNT = UNUM_SIGN_FIELD + 3 +#ifndef U_HIDE_DRAFT_API + UNUM_FIELD_COUNT = UNUM_COMPACT_FIELD + 2 +#else // U_HIDE_DRAFT_API (for UNUM_APPROXIMATELY_SIGN_FIELD) + UNUM_FIELD_COUNT = UNUM_COMPACT_FIELD + 1 +#endif // U_HIDE_DRAFT_API (for UNUM_APPROXIMATELY_SIGN_FIELD) #endif /* U_HIDE_DEPRECATED_API */ } UNumberFormatFields; diff --git a/Build/source/libs/icu/icu-src/source/i18n/unicode/unumberformatter.h b/Build/source/libs/icu/icu-src/source/i18n/unicode/unumberformatter.h index cb980cd94dd..58a75baf073 100644 --- a/Build/source/libs/icu/icu-src/source/i18n/unicode/unumberformatter.h +++ b/Build/source/libs/icu/icu-src/source/i18n/unicode/unumberformatter.h @@ -78,7 +78,6 @@ * </pre> */ -#ifndef U_FORCE_HIDE_DRAFT_API /** * An enum declaring how to resolve conflicts between maximum fraction digits and maximum * significant digits. @@ -115,24 +114,23 @@ * Here, RELAXED favors Max-Fraction and STRICT favors Max-Significant. Note that this larger * number caused the two modes to favor the opposite result. * - * @draft ICU 69 + * @stable ICU 69 */ typedef enum UNumberRoundingPriority { /** * Favor greater precision by relaxing one of the rounding constraints. * - * @draft ICU 69 + * @stable ICU 69 */ UNUM_ROUNDING_PRIORITY_RELAXED, /** * Favor adherence to all rounding constraints by producing lower precision. * - * @draft ICU 69 + * @stable ICU 69 */ UNUM_ROUNDING_PRIORITY_STRICT, } UNumberRoundingPriority; -#endif // U_FORCE_HIDE_DRAFT_API /** * An enum declaring how to render units, including currencies. Example outputs when formatting 123 USD and 123 @@ -435,21 +433,19 @@ typedef enum UNumberSignDisplay { */ UNUM_SIGN_ACCOUNTING_EXCEPT_ZERO, -#ifndef U_HIDE_DRAFT_API /** * Same as AUTO, but do not show the sign on negative zero. * - * @draft ICU 69 + * @stable ICU 69 */ UNUM_SIGN_NEGATIVE, /** * Same as ACCOUNTING, but do not show the sign on negative zero. * - * @draft ICU 69 + * @stable ICU 69 */ UNUM_SIGN_ACCOUNTING_NEGATIVE, -#endif // U_HIDE_DRAFT_API // Do not conditionalize the following with #ifndef U_HIDE_INTERNAL_API, // needed for unconditionalized struct MacroProps @@ -498,31 +494,29 @@ typedef enum UNumberDecimalSeparatorDisplay { UNUM_DECIMAL_SEPARATOR_COUNT } UNumberDecimalSeparatorDisplay; -#ifndef U_FORCE_HIDE_DRAFT_API /** * An enum declaring how to render trailing zeros. * * - UNUM_TRAILING_ZERO_AUTO: 0.90, 1.00, 1.10 * - UNUM_TRAILING_ZERO_HIDE_IF_WHOLE: 0.90, 1, 1.10 * - * @draft ICU 69 + * @stable ICU 69 */ typedef enum UNumberTrailingZeroDisplay { /** * Display trailing zeros according to the settings for minimum fraction and significant digits. * - * @draft ICU 69 + * @stable ICU 69 */ UNUM_TRAILING_ZERO_AUTO, /** * Same as AUTO, but hide trailing zeros after the decimal separator if they are all zero. * - * @draft ICU 69 + * @stable ICU 69 */ UNUM_TRAILING_ZERO_HIDE_IF_WHOLE, } UNumberTrailingZeroDisplay; -#endif // U_FORCE_HIDE_DRAFT_API struct UNumberFormatter; /** diff --git a/Build/source/libs/icu/icu-src/source/i18n/unicode/vtzone.h b/Build/source/libs/icu/icu-src/source/i18n/unicode/vtzone.h index e7d2f515410..ecf335bbe34 100644 --- a/Build/source/libs/icu/icu-src/source/i18n/unicode/vtzone.h +++ b/Build/source/libs/icu/icu-src/source/i18n/unicode/vtzone.h @@ -264,16 +264,14 @@ public: virtual void getOffset(UDate date, UBool local, int32_t& rawOffset, int32_t& dstOffset, UErrorCode& ec) const override; -#ifndef U_FORCE_HIDE_DRAFT_API /** * Get time zone offsets from local wall time. - * @draft ICU 69 + * @stable ICU 69 */ virtual void getOffsetFromLocal( UDate date, UTimeZoneLocalOption nonExistingTimeOpt, UTimeZoneLocalOption duplicatedTimeOpt, int32_t& rawOffset, int32_t& dstOffset, UErrorCode& status) const override; -#endif /* U_FORCE_HIDE_DRAFT_API */ /** * Sets the TimeZone's raw GMT offset (i.e., the number of milliseconds to add diff --git a/Build/source/libs/icu/icu-src/source/i18n/units_complexconverter.cpp b/Build/source/libs/icu/icu-src/source/i18n/units_complexconverter.cpp index 78cefbf7ebb..ecbe3c78794 100644 --- a/Build/source/libs/icu/icu-src/source/i18n/units_complexconverter.cpp +++ b/Build/source/libs/icu/icu-src/source/i18n/units_complexconverter.cpp @@ -183,7 +183,7 @@ MaybeStackVector<Measure> ComplexUnitsConverter::convert(double quantity, } else { quantity = remainder; } - } + } } applyRounder(intValues, quantity, rounder, status); @@ -210,7 +210,6 @@ MaybeStackVector<Measure> ComplexUnitsConverter::convert(double quantity, } } - // Transfer values into result and return: for(int32_t i = 0, n = unitsConverters_.length(); i < n; ++i) { U_ASSERT(tmpResult[i] != nullptr); @@ -224,6 +223,12 @@ MaybeStackVector<Measure> ComplexUnitsConverter::convert(double quantity, void ComplexUnitsConverter::applyRounder(MaybeStackArray<int64_t, 5> &intValues, double &quantity, icu::number::impl::RoundingImpl *rounder, UErrorCode &status) const { + if (uprv_isInfinite(quantity) || uprv_isNaN(quantity)) { + // Inf and NaN can't be rounded, and calculating `carry` below is known + // to fail on Gentoo on HPPA and OpenSUSE on riscv64. Nothing to do. + return; + } + if (rounder == nullptr) { // Nothing to do for the quantity. return; diff --git a/Build/source/libs/icu/icu-src/source/i18n/units_complexconverter.h b/Build/source/libs/icu/icu-src/source/i18n/units_complexconverter.h index 5c669b45ddd..d56ce8d4ce3 100644 --- a/Build/source/libs/icu/icu-src/source/i18n/units_complexconverter.h +++ b/Build/source/libs/icu/icu-src/source/i18n/units_complexconverter.h @@ -108,13 +108,15 @@ class U_I18N_API ComplexUnitsConverter : public UMemory { MaybeStackVector<Measure> convert(double quantity, icu::number::impl::RoundingImpl *rounder, UErrorCode &status) const; - private: + // TODO(ICU-21937): Make it private after submitting the public units conversion API. MaybeStackVector<UnitsConverter> unitsConverters_; + // TODO(ICU-21937): Make it private after submitting the public units conversion API. // Individual units of mixed units, sorted big to small, with indices // indicating the requested output mixed unit order. MaybeStackVector<MeasureUnitImplWithIndex> units_; + private: // Sorts units_, which must be populated before calling this, and populates // unitsConverters_. void init(const MeasureUnitImpl &inputUnit, const ConversionRates &ratesInfo, UErrorCode &status); diff --git a/Build/source/libs/icu/icu-src/source/i18n/units_converter.cpp b/Build/source/libs/icu/icu-src/source/i18n/units_converter.cpp index 7e946e584bb..82b8eea3d8c 100644 --- a/Build/source/libs/icu/icu-src/source/i18n/units_converter.cpp +++ b/Build/source/libs/icu/icu-src/source/i18n/units_converter.cpp @@ -9,6 +9,7 @@ #include "cmemory.h" #include "double-conversion-string-to-double.h" #include "measunit_impl.h" +#include "putilimp.h" #include "uassert.h" #include "unicode/errorcode.h" #include "unicode/localpointer.h" @@ -588,10 +589,7 @@ double UnitsConverter::convert(double inputValue) const { if (conversionRate_.reciprocal) { if (result == 0) { - // TODO: demonstrate the resulting behaviour in tests... and figure - // out desired behaviour. (Theoretical result should be infinity, - // not 0.) - return 0.0; + return uprv_getInfinity(); } result = 1.0 / result; } @@ -603,10 +601,7 @@ double UnitsConverter::convertInverse(double inputValue) const { double result = inputValue; if (conversionRate_.reciprocal) { if (result == 0) { - // TODO: demonstrate the resulting behaviour in tests... and figure - // out desired behaviour. (Theoretical result should be infinity, - // not 0.) - return 0.0; + return uprv_getInfinity(); } result = 1.0 / result; } diff --git a/Build/source/libs/icu/icu-src/source/i18n/units_router.h b/Build/source/libs/icu/icu-src/source/i18n/units_router.h index b3300f7e277..d9fcffb2aa9 100644 --- a/Build/source/libs/icu/icu-src/source/i18n/units_router.h +++ b/Build/source/libs/icu/icu-src/source/i18n/units_router.h @@ -30,8 +30,6 @@ namespace units { struct RouteResult : UMemory { // A list of measures: a single measure for single units, multiple measures // for mixed units. - // - // TODO(icu-units/icu#21): figure out the right mixed unit API. MaybeStackVector<Measure> measures; // The output unit for this RouteResult. This may be a MIXED unit - for diff --git a/Build/source/libs/icu/icu-src/source/i18n/uspoof_conf.cpp b/Build/source/libs/icu/icu-src/source/i18n/uspoof_conf.cpp index 04081cabfb0..172c0711afb 100644 --- a/Build/source/libs/icu/icu-src/source/i18n/uspoof_conf.cpp +++ b/Build/source/libs/icu/icu-src/source/i18n/uspoof_conf.cpp @@ -63,23 +63,24 @@ U_NAMESPACE_USE // at the same time // -SPUString::SPUString(UnicodeString *s) { - fStr = s; +SPUString::SPUString(LocalPointer<UnicodeString> s) { + fStr = std::move(s); fCharOrStrTableIndex = 0; } SPUString::~SPUString() { - delete fStr; } -SPUStringPool::SPUStringPool(UErrorCode &status) : fVec(NULL), fHash(NULL) { - fVec = new UVector(status); - if (fVec == NULL) { - status = U_MEMORY_ALLOCATION_ERROR; +SPUStringPool::SPUStringPool(UErrorCode &status) : fVec(nullptr), fHash(nullptr) { + LocalPointer<UVector> vec(new UVector(status), status); + if (U_FAILURE(status)) { return; } + vec->setDeleter( + [](void *obj) {delete (SPUString *)obj;}); + fVec = vec.orphan(); fHash = uhash_open(uhash_hashUnicodeString, // key hash function uhash_compareUnicodeString, // Key Comparator NULL, // Value Comparator @@ -88,11 +89,6 @@ SPUStringPool::SPUStringPool(UErrorCode &status) : fVec(NULL), fHash(NULL) { SPUStringPool::~SPUStringPool() { - int i; - for (i=fVec->size()-1; i>=0; i--) { - SPUString *s = static_cast<SPUString *>(fVec->elementAt(i)); - delete s; - } delete fVec; uhash_close(fHash); } @@ -135,18 +131,21 @@ void SPUStringPool::sort(UErrorCode &status) { SPUString *SPUStringPool::addString(UnicodeString *src, UErrorCode &status) { + LocalPointer<UnicodeString> lpSrc(src); + if (U_FAILURE(status)) { + return nullptr; + } SPUString *hashedString = static_cast<SPUString *>(uhash_get(fHash, src)); - if (hashedString != NULL) { - delete src; - } else { - hashedString = new SPUString(src); - if (hashedString == NULL) { - status = U_MEMORY_ALLOCATION_ERROR; - return NULL; - } - uhash_put(fHash, src, hashedString, &status); - fVec->addElementX(hashedString, status); + if (hashedString != nullptr) { + return hashedString; + } + LocalPointer<SPUString> spuStr(new SPUString(std::move(lpSrc)), status); + hashedString = spuStr.getAlias(); + fVec->adoptElement(spuStr.orphan(), status); + if (U_FAILURE(status)) { + return nullptr; } + uhash_put(fHash, src, hashedString, &status); return hashedString; } diff --git a/Build/source/libs/icu/icu-src/source/i18n/uspoof_conf.h b/Build/source/libs/icu/icu-src/source/i18n/uspoof_conf.h index 600d7ea42a4..1eeecdfd5e4 100644 --- a/Build/source/libs/icu/icu-src/source/i18n/uspoof_conf.h +++ b/Build/source/libs/icu/icu-src/source/i18n/uspoof_conf.h @@ -39,11 +39,12 @@ U_NAMESPACE_BEGIN // Instances of SPUString exist during the compilation process only. struct SPUString : public UMemory { - UnicodeString *fStr; // The actual string. - int32_t fCharOrStrTableIndex; // Index into the final runtime data for this - // string (or, for length 1, the single string char - // itself, there being no string table entry for it.) - SPUString(UnicodeString *s); + LocalPointer<UnicodeString> fStr; // The actual string. + int32_t fCharOrStrTableIndex; // Index into the final runtime data for this + // string (or, for length 1, the single string char + // itself, there being no string table entry for it.) + + SPUString(LocalPointer<UnicodeString> s); ~SPUString(); }; diff --git a/Build/source/libs/icu/icu-src/source/i18n/uspoof_impl.cpp b/Build/source/libs/icu/icu-src/source/i18n/uspoof_impl.cpp index b283d813210..f96826f86cc 100644 --- a/Build/source/libs/icu/icu-src/source/i18n/uspoof_impl.cpp +++ b/Build/source/libs/icu/icu-src/source/i18n/uspoof_impl.cpp @@ -945,7 +945,7 @@ uspoof_swap(const UDataSwapper *ds, const void *inData, int32_t length, void *ou uint32_t magic = ds->readUInt32(spoofDH->fMagic); ds->writeUInt32((uint32_t *)&outputDH->fMagic, magic); - if (outputDH->fFormatVersion != spoofDH->fFormatVersion) { + if (inBytes != outBytes) { uprv_memcpy(outputDH->fFormatVersion, spoofDH->fFormatVersion, sizeof(spoofDH->fFormatVersion)); } // swap starting at fLength diff --git a/Build/source/libs/icu/icu-src/source/i18n/vtzone.cpp b/Build/source/libs/icu/icu-src/source/i18n/vtzone.cpp index 9111e08848f..06f0b84c0f5 100644 --- a/Build/source/libs/icu/icu-src/source/i18n/vtzone.cpp +++ b/Build/source/libs/icu/icu-src/source/i18n/vtzone.cpp @@ -24,14 +24,6 @@ U_NAMESPACE_BEGIN -// This is the deleter that will be use to remove TimeZoneRule -U_CDECL_BEGIN -static void U_CALLCONV -deleteTimeZoneRule(void* obj) { - delete (TimeZoneRule*) obj; -} -U_CDECL_END - // Smybol characters used by RFC2445 VTIMEZONE static const UChar COLON = 0x3A; /* : */ static const UChar SEMICOLON = 0x3B; /* ; */ @@ -976,22 +968,19 @@ VTimeZone::VTimeZone(const VTimeZone& source) if (source.vtzlines != nullptr) { UErrorCode status = U_ZERO_ERROR; int32_t size = source.vtzlines->size(); - vtzlines = new UVector(uprv_deleteUObject, uhash_compareUnicodeString, size, status); - if (vtzlines == nullptr) { + LocalPointer<UVector> lpVtzLines( + new UVector(uprv_deleteUObject, uhash_compareUnicodeString, size, status), status); + if (U_FAILURE(status)) { return; } - if (U_SUCCESS(status)) { - for (int32_t i = 0; i < size; i++) { - UnicodeString *line = (UnicodeString*)source.vtzlines->elementAt(i); - vtzlines->addElementX(line->clone(), status); - if (U_FAILURE(status)) { - break; - } + for (int32_t i = 0; i < size; i++) { + UnicodeString *line = ((UnicodeString*)source.vtzlines->elementAt(i))->clone(); + lpVtzLines->adoptElement(line, status); + if (U_FAILURE(status) || line == nullptr) { + return; } } - if (U_FAILURE(status) && vtzlines != nullptr) { - delete vtzlines; - } + vtzlines = lpVtzLines.orphan(); } } @@ -1020,23 +1009,25 @@ VTimeZone::operator=(const VTimeZone& right) { } if (vtzlines != nullptr) { delete vtzlines; + vtzlines = nullptr; } if (right.vtzlines != nullptr) { UErrorCode status = U_ZERO_ERROR; int32_t size = right.vtzlines->size(); - vtzlines = new UVector(uprv_deleteUObject, uhash_compareUnicodeString, size, status); - if (vtzlines != nullptr && U_SUCCESS(status)) { + LocalPointer<UVector> lpVtzLines( + new UVector(uprv_deleteUObject, uhash_compareUnicodeString, size, status), status); + if (U_SUCCESS(status)) { for (int32_t i = 0; i < size; i++) { - UnicodeString *line = (UnicodeString*)right.vtzlines->elementAt(i); - vtzlines->addElementX(line->clone(), status); + LocalPointer<UnicodeString> line( + ((UnicodeString*)right.vtzlines->elementAt(i))->clone(), status); + lpVtzLines->adoptElement(line.orphan(), status); if (U_FAILURE(status)) { break; } } - } - if (U_FAILURE(status) && vtzlines != nullptr) { - delete vtzlines; - vtzlines = nullptr; + if (U_SUCCESS(status)) { + vtzlines = lpVtzLines.orphan(); + } } } tzurl = right.tzurl; @@ -1272,10 +1263,9 @@ VTimeZone::getTimeZoneRules(const InitialTimeZoneRule*& initial, void VTimeZone::load(VTZReader& reader, UErrorCode& status) { - vtzlines = new UVector(uprv_deleteUObject, uhash_compareUnicodeString, DEFAULT_VTIMEZONE_LINES, status); - if (vtzlines == nullptr) { - status = U_MEMORY_ALLOCATION_ERROR; - } + U_ASSERT(vtzlines == nullptr); + LocalPointer<UVector> lpVtzLines( + new UVector(uprv_deleteUObject, uhash_compareUnicodeString, DEFAULT_VTIMEZONE_LINES, status), status); if (U_FAILURE(status)) { return; } @@ -1290,14 +1280,10 @@ VTimeZone::load(VTZReader& reader, UErrorCode& status) { // end of file if (start && line.startsWith(ICAL_END_VTIMEZONE, -1)) { LocalPointer<UnicodeString> element(new UnicodeString(line), status); + lpVtzLines->adoptElement(element.orphan(), status); if (U_FAILURE(status)) { - goto cleanupVtzlines; - } - vtzlines->addElementX(element.getAlias(), status); - if (U_FAILURE(status)) { - goto cleanupVtzlines; + return; } - element.orphan(); // on success, vtzlines owns the object. success = TRUE; } break; @@ -1312,14 +1298,10 @@ VTimeZone::load(VTZReader& reader, UErrorCode& status) { if (start) { if (line.length() > 0) { LocalPointer<UnicodeString> element(new UnicodeString(line), status); + lpVtzLines->adoptElement(element.orphan(), status); if (U_FAILURE(status)) { - goto cleanupVtzlines; + return; } - vtzlines->addElementX(element.getAlias(), status); - if (U_FAILURE(status)) { - goto cleanupVtzlines; - } - element.orphan(); // on success, vtzlines owns the object. } } line.remove(); @@ -1335,28 +1317,20 @@ VTimeZone::load(VTZReader& reader, UErrorCode& status) { if (start) { if (line.startsWith(ICAL_END_VTIMEZONE, -1)) { LocalPointer<UnicodeString> element(new UnicodeString(line), status); + lpVtzLines->adoptElement(element.orphan(), status); if (U_FAILURE(status)) { - goto cleanupVtzlines; - } - vtzlines->addElementX(element.getAlias(), status); - if (U_FAILURE(status)) { - goto cleanupVtzlines; + return; } - element.orphan(); // on success, vtzlines owns the object. success = TRUE; break; } } else { if (line.startsWith(ICAL_BEGIN_VTIMEZONE, -1)) { LocalPointer<UnicodeString> element(new UnicodeString(line), status); + lpVtzLines->adoptElement(element.orphan(), status); if (U_FAILURE(status)) { - goto cleanupVtzlines; - } - vtzlines->addElementX(element.getAlias(), status); - if (U_FAILURE(status)) { - goto cleanupVtzlines; + return; } - element.orphan(); // on success, vtzlines owns the object. line.remove(); start = TRUE; eol = FALSE; @@ -1371,14 +1345,10 @@ VTimeZone::load(VTZReader& reader, UErrorCode& status) { if (U_SUCCESS(status)) { status = U_INVALID_STATE_ERROR; } - goto cleanupVtzlines; + return; } + vtzlines = lpVtzLines.orphan(); parse(status); - return; - -cleanupVtzlines: - delete vtzlines; - vtzlines = nullptr; } // parser state @@ -1398,8 +1368,6 @@ VTimeZone::parse(UErrorCode& status) { status = U_INVALID_STATE_ERROR; return; } - InitialTimeZoneRule *initialRule = nullptr; - RuleBasedTimeZone *rbtz = nullptr; // timezone ID UnicodeString tzid; @@ -1418,28 +1386,16 @@ VTimeZone::parse(UErrorCode& status) { UnicodeString name; // RFC2445 prop name UnicodeString value; // RFC2445 prop value - UVector *dates = nullptr; // list of RDATE or RRULE strings - UVector *rules = nullptr; // list of TimeZoneRule instances - int32_t finalRuleIdx = -1; int32_t finalRuleCount = 0; - rules = new UVector(status); - if (rules == nullptr) { - status = U_MEMORY_ALLOCATION_ERROR; - } - if (U_FAILURE(status)) { - goto cleanupParse; - } - // Set the deleter to remove TimeZoneRule vectors to avoid memory leaks due to unowned TimeZoneRules. - rules->setDeleter(deleteTimeZoneRule); + // Set the deleter on rules to remove TimeZoneRule vectors to avoid memory leaks due to unowned TimeZoneRules. + UVector rules(uprv_deleteUObject, nullptr, status); - dates = new UVector(uprv_deleteUObject, uhash_compareUnicodeString, status); - if (dates == nullptr) { - status = U_MEMORY_ALLOCATION_ERROR; - } + // list of RDATE or RRULE strings + UVector dates(uprv_deleteUObject, uhash_compareUnicodeString, status); if (U_FAILURE(status)) { - goto cleanupParse; + return; } for (n = 0; n < vtzlines->size(); n++) { @@ -1469,18 +1425,18 @@ VTimeZone::parse(UErrorCode& status) { // can be any value. lastmod = parseDateTimeString(value, 0, status); if (U_FAILURE(status)) { - goto cleanupParse; + return; } } else if (name.compare(ICAL_BEGIN, -1) == 0) { UBool isDST = (value.compare(ICAL_DAYLIGHT, -1) == 0); if (value.compare(ICAL_STANDARD, -1) == 0 || isDST) { // tzid must be ready at this point if (tzid.length() == 0) { - goto cleanupParse; + return; } // initialize current zone properties - if (dates->size() != 0) { - dates->removeAllElements(); + if (dates.size() != 0) { + dates.removeAllElements(); } isRRULE = FALSE; from.remove(); @@ -1491,7 +1447,7 @@ VTimeZone::parse(UErrorCode& status) { } else { // BEGIN property other than STANDARD/DAYLIGHT // must not be there. - goto cleanupParse; + return; } } else if (name.compare(ICAL_END, -1) == 0) { break; @@ -1509,50 +1465,42 @@ VTimeZone::parse(UErrorCode& status) { } else if (name.compare(ICAL_RDATE, -1) == 0) { // RDATE mixed with RRULE is not supported if (isRRULE) { - goto cleanupParse; + return; } // RDATE value may contain multiple date delimited // by comma UBool nextDate = TRUE; int32_t dstart = 0; - UnicodeString *dstr = nullptr; + LocalPointer<UnicodeString> dstr; while (nextDate) { int32_t dend = value.indexOf(COMMA, dstart); if (dend == -1) { - dstr = new UnicodeString(value, dstart); + dstr.adoptInsteadAndCheckErrorCode(new UnicodeString(value, dstart), status); nextDate = FALSE; } else { - dstr = new UnicodeString(value, dstart, dend - dstart); - } - if (dstr == nullptr) { - status = U_MEMORY_ALLOCATION_ERROR; - } else { - dates->addElementX(dstr, status); + dstr.adoptInsteadAndCheckErrorCode(new UnicodeString(value, dstart, dend - dstart), status); } + dates.adoptElement(dstr.orphan(), status); if (U_FAILURE(status)) { - goto cleanupParse; + return; } dstart = dend + 1; } } else if (name.compare(ICAL_RRULE, -1) == 0) { // RRULE mixed with RDATE is not supported - if (!isRRULE && dates->size() != 0) { - goto cleanupParse; + if (!isRRULE && dates.size() != 0) { + return; } isRRULE = true; LocalPointer<UnicodeString> element(new UnicodeString(value), status); + dates.adoptElement(element.orphan(), status); if (U_FAILURE(status)) { - goto cleanupParse; - } - dates->addElementX(element.getAlias(), status); - if (U_FAILURE(status)) { - goto cleanupParse; + return; } - element.orphan(); // on success, dates owns the object. } else if (name.compare(ICAL_END, -1) == 0) { // Mandatory properties if (dtstart.length() == 0 || from.length() == 0 || to.length() == 0) { - goto cleanupParse; + return; } // if zonename is not available, create one from tzid if (zonename.length() == 0) { @@ -1560,7 +1508,7 @@ VTimeZone::parse(UErrorCode& status) { } // create a time zone rule - TimeZoneRule *rule = nullptr; + LocalPointer<TimeZoneRule> rule; int32_t fromOffset = 0; int32_t toOffset = 0; int32_t rawOffset = 0; @@ -1571,7 +1519,7 @@ VTimeZone::parse(UErrorCode& status) { fromOffset = offsetStrToMillis(from, status); toOffset = offsetStrToMillis(to, status); if (U_FAILURE(status)) { - goto cleanupParse; + return; } if (dst) { @@ -1592,18 +1540,20 @@ VTimeZone::parse(UErrorCode& status) { // start time start = parseDateTimeString(dtstart, fromOffset, status); if (U_FAILURE(status)) { - goto cleanupParse; + return; } // Create the rule UDate actualStart = MAX_MILLIS; if (isRRULE) { - rule = createRuleByRRULE(zonename, rawOffset, dstSavings, start, dates, fromOffset, status); + rule.adoptInsteadAndCheckErrorCode( + createRuleByRRULE(zonename, rawOffset, dstSavings, start, &dates, fromOffset, status), status); } else { - rule = createRuleByRDATE(zonename, rawOffset, dstSavings, start, dates, fromOffset, status); + rule.adoptInsteadAndCheckErrorCode( + createRuleByRDATE(zonename, rawOffset, dstSavings, start, &dates, fromOffset, status), status); } - if (U_FAILURE(status) || rule == nullptr) { - goto cleanupParse; + if (U_FAILURE(status)) { + return; } else { UBool startAvail = rule->getFirstStart(fromOffset, 0, actualStart); if (startAvail && actualStart < firstStart) { @@ -1626,9 +1576,9 @@ VTimeZone::parse(UErrorCode& status) { } } } - rules->addElementX(rule, status); + rules.adoptElement(rule.orphan(), status); if (U_FAILURE(status)) { - goto cleanupParse; + return; } state = VTZ; } @@ -1636,28 +1586,31 @@ VTimeZone::parse(UErrorCode& status) { } } // Must have at least one rule - if (rules->size() == 0) { - goto cleanupParse; + if (rules.size() == 0) { + return; } // Create a initial rule getDefaultTZName(tzid, FALSE, zonename); - initialRule = new InitialTimeZoneRule(zonename, initialRawOffset, initialDSTSavings); - if (initialRule == nullptr) { - status = U_MEMORY_ALLOCATION_ERROR; - goto cleanupParse; + LocalPointer<InitialTimeZoneRule> initialRule( + new InitialTimeZoneRule(zonename, initialRawOffset, initialDSTSavings), status); + if (U_FAILURE(status)) { + return; } // Finally, create the RuleBasedTimeZone - rbtz = new RuleBasedTimeZone(tzid, initialRule); - if (rbtz == nullptr) { - status = U_MEMORY_ALLOCATION_ERROR; - goto cleanupParse; + // C++ awkwardness on memory allocation failure: the constructor wont be run, meaning + // that initialRule wont be adopted/deleted, as it normally would be. + LocalPointer<RuleBasedTimeZone> rbtz( + new RuleBasedTimeZone(tzid, initialRule.getAlias()), status); + if (U_SUCCESS(status)) { + initialRule.orphan(); + } else { + return; } - initialRule = nullptr; // already adopted by RBTZ, no need to delete - for (n = 0; n < rules->size(); n++) { - TimeZoneRule *r = (TimeZoneRule*)rules->elementAt(n); + for (n = 0; n < rules.size(); n++) { + TimeZoneRule *r = (TimeZoneRule*)rules.elementAt(n); AnnualTimeZoneRule *atzrule = dynamic_cast<AnnualTimeZoneRule *>(r); if (atzrule != nullptr) { if (atzrule->getEndYear() == AnnualTimeZoneRule::MAX_YEAR) { @@ -1669,18 +1622,18 @@ VTimeZone::parse(UErrorCode& status) { if (finalRuleCount > 2) { // Too many final rules status = U_ILLEGAL_ARGUMENT_ERROR; - goto cleanupParse; + return; } if (finalRuleCount == 1) { - if (rules->size() == 1) { + if (rules.size() == 1) { // Only one final rule, only governs the initial rule, // which is already initialized, thus, we do not need to // add this transition rule - rules->removeAllElements(); + rules.removeAllElements(); } else { // Normalize the final rule - AnnualTimeZoneRule *finalRule = (AnnualTimeZoneRule*)rules->elementAt(finalRuleIdx); + AnnualTimeZoneRule *finalRule = (AnnualTimeZoneRule*)rules.elementAt(finalRuleIdx); int32_t tmpRaw = finalRule->getRawOffset(); int32_t tmpDST = finalRule->getDSTSavings(); @@ -1688,11 +1641,11 @@ VTimeZone::parse(UErrorCode& status) { UDate finalStart, start; finalRule->getFirstStart(initialRawOffset, initialDSTSavings, finalStart); start = finalStart; - for (n = 0; n < rules->size(); n++) { + for (n = 0; n < rules.size(); n++) { if (finalRuleIdx == n) { continue; } - TimeZoneRule *r = (TimeZoneRule*)rules->elementAt(n); + TimeZoneRule *r = (TimeZoneRule*)rules.elementAt(n); UDate lastStart; r->getFinalStart(tmpRaw, tmpDST, lastStart); if (lastStart > start) { @@ -1704,78 +1657,58 @@ VTimeZone::parse(UErrorCode& status) { } } - TimeZoneRule *newRule = nullptr; + LocalPointer<TimeZoneRule> newRule; UnicodeString tznam; if (start == finalStart) { // Transform this into a single transition - newRule = new TimeArrayTimeZoneRule( - finalRule->getName(tznam), - finalRule->getRawOffset(), - finalRule->getDSTSavings(), - &finalStart, - 1, - DateTimeRule::UTC_TIME); + newRule.adoptInsteadAndCheckErrorCode( + new TimeArrayTimeZoneRule( + finalRule->getName(tznam), + finalRule->getRawOffset(), + finalRule->getDSTSavings(), + &finalStart, + 1, + DateTimeRule::UTC_TIME), + status); } else { // Update the end year int32_t y, m, d, dow, doy, mid; Grego::timeToFields(start, y, m, d, dow, doy, mid); - newRule = new AnnualTimeZoneRule( - finalRule->getName(tznam), - finalRule->getRawOffset(), - finalRule->getDSTSavings(), - *(finalRule->getRule()), - finalRule->getStartYear(), - y); + newRule.adoptInsteadAndCheckErrorCode( + new AnnualTimeZoneRule( + finalRule->getName(tznam), + finalRule->getRawOffset(), + finalRule->getDSTSavings(), + *(finalRule->getRule()), + finalRule->getStartYear(), + y), + status); } - if (newRule == nullptr) { - status = U_MEMORY_ALLOCATION_ERROR; - goto cleanupParse; + if (U_FAILURE(status)) { + return; } - rules->removeElementAt(finalRuleIdx); - rules->addElementX(newRule, status); + rules.removeElementAt(finalRuleIdx); + rules.adoptElement(newRule.orphan(), status); if (U_FAILURE(status)) { - delete newRule; - goto cleanupParse; + return; } } } - while (!rules->isEmpty()) { - TimeZoneRule *tzr = (TimeZoneRule*)rules->orphanElementAt(0); + while (!rules.isEmpty()) { + TimeZoneRule *tzr = (TimeZoneRule*)rules.orphanElementAt(0); rbtz->addTransitionRule(tzr, status); if (U_FAILURE(status)) { - goto cleanupParse; + return; } } rbtz->complete(status); if (U_FAILURE(status)) { - goto cleanupParse; + return; } - delete rules; - delete dates; - tz = rbtz; + tz = rbtz.orphan(); setID(tzid); - return; - -cleanupParse: - if (rules != nullptr) { - while (!rules->isEmpty()) { - TimeZoneRule *r = (TimeZoneRule*)rules->orphanElementAt(0); - delete r; - } - delete rules; - } - if (dates != nullptr) { - delete dates; - } - if (initialRule != nullptr) { - delete initialRule; - } - if (rbtz != nullptr) { - delete rbtz; - } - return; } void @@ -1809,7 +1742,7 @@ VTimeZone::write(VTZWriter& writer, UErrorCode& status) const { icutzprop.append(u'['); icutzprop.append(icutzver); icutzprop.append(u']'); - customProps.addElementX(&icutzprop, status); + customProps.addElement(&icutzprop, status); } writeZone(writer, *tz, &customProps, status); } @@ -1827,34 +1760,35 @@ VTimeZone::write(UDate start, VTZWriter& writer, UErrorCode& status) const { // Extract rules applicable to dates after the start time getTimeZoneRulesAfter(start, initial, transitionRules, status); + LocalPointer<InitialTimeZoneRule> lpInitial(initial); + LocalPointer<UVector> lpTransitionRules(transitionRules); if (U_FAILURE(status)) { return; } // Create a RuleBasedTimeZone with the subset rule getID(tzid); - RuleBasedTimeZone rbtz(tzid, initial); - if (transitionRules != nullptr) { - while (!transitionRules->isEmpty()) { - TimeZoneRule *tr = (TimeZoneRule*)transitionRules->orphanElementAt(0); + RuleBasedTimeZone rbtz(tzid, lpInitial.orphan()); + if (lpTransitionRules.isValid()) { + U_ASSERT(transitionRules->hasDeleter()); // Assumed for U_FAILURE early return, below. + while (!lpTransitionRules->isEmpty()) { + TimeZoneRule *tr = (TimeZoneRule*)lpTransitionRules->orphanElementAt(0); rbtz.addTransitionRule(tr, status); if (U_FAILURE(status)) { - goto cleanupWritePartial; + return; } } - delete transitionRules; - transitionRules = nullptr; } rbtz.complete(status); if (U_FAILURE(status)) { - goto cleanupWritePartial; + return; } if (olsonzid.length() > 0 && icutzver.length() > 0) { UnicodeString *icutzprop = new UnicodeString(ICU_TZINFO_PROP); if (icutzprop == nullptr) { status = U_MEMORY_ALLOCATION_ERROR; - goto cleanupWritePartial; + return; } icutzprop->append(olsonzid); icutzprop->append((UChar)0x005B/*'['*/); @@ -1862,23 +1796,12 @@ VTimeZone::write(UDate start, VTZWriter& writer, UErrorCode& status) const { icutzprop->append(ICU_TZINFO_PARTIAL, -1); appendMillis(start, *icutzprop); icutzprop->append((UChar)0x005D/*']'*/); - customProps.addElementX(icutzprop, status); + customProps.adoptElement(icutzprop, status); if (U_FAILURE(status)) { - delete icutzprop; - goto cleanupWritePartial; + return; } } writeZone(writer, rbtz, &customProps, status); - return; - -cleanupWritePartial: - if (initial != nullptr) { - delete initial; - } - if (transitionRules != nullptr) { - U_ASSERT(transitionRules->hasDeleter()); - delete transitionRules; - } } void diff --git a/Build/source/libs/icu/icu-src/source/i18n/zonemeta.cpp b/Build/source/libs/icu/icu-src/source/i18n/zonemeta.cpp index b8afa4760f1..e60215c9988 100644 --- a/Build/source/libs/icu/icu-src/source/i18n/zonemeta.cpp +++ b/Build/source/libs/icu/icu-src/source/i18n/zonemeta.cpp @@ -98,20 +98,12 @@ deleteUCharString(void *obj) { } /** - * Deleter for UVector - */ -static void U_CALLCONV -deleteUVector(void *obj) { - delete (icu::UVector*) obj; -} - -/** * Deleter for OlsonToMetaMappingEntry */ static void U_CALLCONV deleteOlsonToMetaMappingEntry(void *obj) { icu::OlsonToMetaMappingEntry *entry = (icu::OlsonToMetaMappingEntry*)obj; - uprv_free(entry); + delete entry; } U_CDECL_END @@ -477,11 +469,11 @@ ZoneMeta::getCanonicalCountry(const UnicodeString &tzid, UnicodeString &country, UErrorCode ec = U_ZERO_ERROR; if (singleZone) { if (!gSingleZoneCountries->contains((void*)region)) { - gSingleZoneCountries->addElementX((void*)region, ec); + gSingleZoneCountries->addElement((void*)region, ec); } } else { if (!gMultiZonesCountries->contains((void*)region)) { - gMultiZonesCountries->addElementX((void*)region, ec); + gMultiZonesCountries->addElement((void*)region, ec); } } } @@ -550,7 +542,7 @@ static void U_CALLCONV olsonToMetaInit(UErrorCode &status) { gOlsonToMeta = NULL; } else { uhash_setKeyDeleter(gOlsonToMeta, deleteUCharString); - uhash_setValueDeleter(gOlsonToMeta, deleteUVector); + uhash_setValueDeleter(gOlsonToMeta, uprv_deleteUObject); } } @@ -625,7 +617,7 @@ ZoneMeta::getMetazoneMappings(const UnicodeString &tzid) { UVector* ZoneMeta::createMetazoneMappings(const UnicodeString &tzid) { - UVector *mzMappings = NULL; + LocalPointer <UVector> mzMappings; UErrorCode status = U_ZERO_ERROR; UnicodeString canonicalID; @@ -677,41 +669,32 @@ ZoneMeta::createMetazoneMappings(const UnicodeString &tzid) { continue; } - OlsonToMetaMappingEntry *entry = (OlsonToMetaMappingEntry*)uprv_malloc(sizeof(OlsonToMetaMappingEntry)); - if (entry == NULL) { - status = U_MEMORY_ALLOCATION_ERROR; + LocalPointer<OlsonToMetaMappingEntry> entry(new OlsonToMetaMappingEntry, status); + if (U_FAILURE(status)) { break; } entry->mzid = mz_name; entry->from = from; entry->to = to; - if (mzMappings == NULL) { - mzMappings = new UVector(deleteOlsonToMetaMappingEntry, NULL, status); + if (mzMappings.isNull()) { + mzMappings.adoptInsteadAndCheckErrorCode( + new UVector(deleteOlsonToMetaMappingEntry, nullptr, status), status); if (U_FAILURE(status)) { - delete mzMappings; - mzMappings = NULL; - uprv_free(entry); break; } } - mzMappings->addElementX(entry, status); + mzMappings->adoptElement(entry.orphan(), status); if (U_FAILURE(status)) { break; } } ures_close(mz); - if (U_FAILURE(status)) { - if (mzMappings != NULL) { - delete mzMappings; - mzMappings = NULL; - } - } } } ures_close(rb); - return mzMappings; + return U_SUCCESS(status) ? mzMappings.orphan() : nullptr; } UnicodeString& U_EXPORT2 @@ -775,6 +758,7 @@ static void U_CALLCONV initAvailableMetaZoneIDs () { // No valueDeleter, because the vector maintain the value objects gMetaZoneIDs = new UVector(NULL, uhash_compareUChars, status); if (U_FAILURE(status) || gMetaZoneIDs == NULL) { + delete gMetaZoneIDs; gMetaZoneIDs = NULL; uhash_close(gMetaZoneIDTable); gMetaZoneIDTable = NULL; @@ -792,20 +776,22 @@ static void U_CALLCONV initAvailableMetaZoneIDs () { } const char *mzID = ures_getKey(res.getAlias()); int32_t len = static_cast<int32_t>(uprv_strlen(mzID)); - UChar *uMzID = (UChar*)uprv_malloc(sizeof(UChar) * (len + 1)); - if (uMzID == NULL) { + LocalMemory<UChar> uMzID((UChar*)uprv_malloc(sizeof(UChar) * (len + 1))); + if (uMzID.isNull()) { status = U_MEMORY_ALLOCATION_ERROR; break; } - u_charsToUChars(mzID, uMzID, len); + u_charsToUChars(mzID, uMzID.getAlias(), len); uMzID[len] = 0; - UnicodeString *usMzID = new UnicodeString(uMzID); - if (uhash_get(gMetaZoneIDTable, usMzID) == NULL) { - gMetaZoneIDs->addElementX((void *)uMzID, status); - uhash_put(gMetaZoneIDTable, (void *)usMzID, (void *)uMzID, &status); - } else { - uprv_free(uMzID); - delete usMzID; + LocalPointer<UnicodeString> usMzID(new UnicodeString(uMzID.getAlias()), status); + if (U_FAILURE(status)) { + break; + } + if (uhash_get(gMetaZoneIDTable, usMzID.getAlias()) == NULL) { + // Note: gMetaZoneIDTable adopts its keys, but not its values. + // gMetaZoneIDs adopts its values. + uhash_put(gMetaZoneIDTable, usMzID.orphan(), uMzID.getAlias(), &status); + gMetaZoneIDs->adoptElement(uMzID.orphan(), status); } } ures_close(bundle); diff --git a/Build/source/libs/icu/icu-src/source/i18n/zonemeta.h b/Build/source/libs/icu/icu-src/source/i18n/zonemeta.h index f21399342b9..dd4fec957fe 100644 --- a/Build/source/libs/icu/icu-src/source/i18n/zonemeta.h +++ b/Build/source/libs/icu/icu-src/source/i18n/zonemeta.h @@ -18,11 +18,11 @@ U_NAMESPACE_BEGIN -typedef struct OlsonToMetaMappingEntry { +struct OlsonToMetaMappingEntry : public UMemory { const UChar *mzid; // const because it's a reference to a resource bundle string. UDate from; UDate to; -} OlsonToMetaMappingEntry; +}; class UVector; class TimeZone; diff --git a/Build/source/libs/icu/icu-src/source/io/io.vcxproj b/Build/source/libs/icu/icu-src/source/io/io.vcxproj index 56957edc8b9..34af85f6d93 100644 --- a/Build/source/libs/icu/icu-src/source/io/io.vcxproj +++ b/Build/source/libs/icu/icu-src/source/io/io.vcxproj @@ -60,7 +60,7 @@ </ClCompile> <Link> <GenerateDebugInformation>true</GenerateDebugInformation> - <OutputFile>..\..\$(IcuBinOutputDir)\icuio70d.dll</OutputFile> + <OutputFile>..\..\$(IcuBinOutputDir)\icuio71d.dll</OutputFile> <ProgramDatabaseFile>..\..\$(IcuLibOutputDir)\icuiod.pdb</ProgramDatabaseFile> <ImportLibrary>..\..\$(IcuLibOutputDir)\icuiod.lib</ImportLibrary> <AdditionalDependencies>icuucd.lib;icuind.lib;%(AdditionalDependencies)</AdditionalDependencies> @@ -73,7 +73,7 @@ <FunctionLevelLinking>true</FunctionLevelLinking> </ClCompile> <Link> - <OutputFile>..\..\$(IcuBinOutputDir)\icuio70.dll</OutputFile> + <OutputFile>..\..\$(IcuBinOutputDir)\icuio71.dll</OutputFile> <ProgramDatabaseFile>..\..\$(IcuLibOutputDir)\icuio.pdb</ProgramDatabaseFile> <ImportLibrary>..\..\$(IcuLibOutputDir)\icuio.lib</ImportLibrary> <AdditionalDependencies>icuuc.lib;icuin.lib;%(AdditionalDependencies)</AdditionalDependencies> diff --git a/Build/source/libs/icu/icu-src/source/io/sprintf.cpp b/Build/source/libs/icu/icu-src/source/io/sprintf.cpp index 3a593abb480..ede31e91517 100644 --- a/Build/source/libs/icu/icu-src/source/io/sprintf.cpp +++ b/Build/source/libs/icu/icu-src/source/io/sprintf.cpp @@ -41,6 +41,12 @@ u_sprintf_write(void *context, int32_t count) { u_localized_print_string *output = (u_localized_print_string *)context; + + /* just calculating buffer size */ + if (output->str == 0) { + return count; + } + int32_t size = ufmt_min(count, output->available); u_strncpy(output->str + (output->len - output->available), str, size); @@ -58,6 +64,12 @@ u_sprintf_pad_and_justify(void *context, int32_t written = 0; int32_t lengthOfResult = resultLen; + /* just calculating buffer size */ + if (output->str == 0 && + info->fWidth != -1 && resultLen < info->fWidth) { + return info->fWidth; + } + resultLen = ufmt_min(resultLen, output->available); /* pad and justify, if needed */ diff --git a/Build/source/libs/icu/icu-src/source/io/ustdio.cpp b/Build/source/libs/icu/icu-src/source/io/ustdio.cpp index d6eb5cf9ec9..a3cb2a5d9cb 100644 --- a/Build/source/libs/icu/icu-src/source/io/ustdio.cpp +++ b/Build/source/libs/icu/icu-src/source/io/ustdio.cpp @@ -628,7 +628,7 @@ ufile_getch32(UFILE *f, UChar32 *c32) /* Fill the buffer if it is empty */ str = &f->str; - if (f && str->fPos + 1 >= str->fLimit) { + if (str->fPos + 1 >= str->fLimit) { ufile_fill_uchar_buffer(f); } diff --git a/Build/source/libs/icu/icu-src/source/layoutex/layoutex.vcxproj b/Build/source/libs/icu/icu-src/source/layoutex/layoutex.vcxproj index 810bbba913c..c9cbce51e79 100644 --- a/Build/source/libs/icu/icu-src/source/layoutex/layoutex.vcxproj +++ b/Build/source/libs/icu/icu-src/source/layoutex/layoutex.vcxproj @@ -54,7 +54,7 @@ <CompileAs>Default</CompileAs> </ClCompile> <Link> - <OutputFile>..\..\bin\iculx70.dll</OutputFile> + <OutputFile>..\..\bin\iculx71.dll</OutputFile> <AdditionalDependencies>icuuc.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalLibraryDirectories>.\..\..\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> <ProgramDatabaseFile>.\..\..\lib\iculx.pdb</ProgramDatabaseFile> @@ -79,7 +79,7 @@ <CompileAs>Default</CompileAs> </ClCompile> <Link> - <OutputFile>..\..\bin\iculx70d.dll</OutputFile> + <OutputFile>..\..\bin\iculx71d.dll</OutputFile> <AdditionalDependencies>icuucd.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalLibraryDirectories>.\..\..\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> <GenerateDebugInformation>true</GenerateDebugInformation> @@ -104,7 +104,7 @@ <CompileAs>Default</CompileAs> </ClCompile> <Link> - <OutputFile>..\..\bin64\iculx70.dll</OutputFile> + <OutputFile>..\..\bin64\iculx71.dll</OutputFile> <AdditionalDependencies>icuuc.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalLibraryDirectories>.\..\..\lib64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> <ProgramDatabaseFile>.\..\..\lib64\iculx.pdb</ProgramDatabaseFile> @@ -127,7 +127,7 @@ <CompileAs>Default</CompileAs> </ClCompile> <Link> - <OutputFile>..\..\bin64\iculx70d.dll</OutputFile> + <OutputFile>..\..\bin64\iculx71d.dll</OutputFile> <AdditionalDependencies>icuucd.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalLibraryDirectories>.\..\..\lib64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> <GenerateDebugInformation>true</GenerateDebugInformation> diff --git a/Build/source/libs/icu/icu-src/source/samples/Makefile.in b/Build/source/libs/icu/icu-src/source/samples/Makefile.in index 374a70f3525..8f2514bfd00 100644 --- a/Build/source/libs/icu/icu-src/source/samples/Makefile.in +++ b/Build/source/libs/icu/icu-src/source/samples/Makefile.in @@ -23,7 +23,7 @@ include @platform_make_fragment@ CLEANFILES = *~ SUBDIRS = date cal -ALLSUBDIRS = break case csdet datefmt msgfmt numfmt props translit ucnv udata ufortune uresb ustring citer uciter8 ugrep +ALLSUBDIRS = cal citer coll csdet date datecal ufortune uresb datefmt msgfmt numfmt props strsrch translit uciter8 ucnv udata ustring dtitvfmtsample dtptngsample plurfmtsample ## List of phony targets .PHONY : all all-local all-recursive install install-local \ diff --git a/Build/source/libs/icu/icu-src/source/samples/case/ucase.c b/Build/source/libs/icu/icu-src/source/samples/case/ucase.c index 439c3c5b684..3cabe22d606 100644 --- a/Build/source/libs/icu/icu-src/source/samples/case/ucase.c +++ b/Build/source/libs/icu/icu-src/source/samples/case/ucase.c @@ -17,6 +17,9 @@ ******************************************************************************* */ +#include <stdio.h> +#include <stdlib.h> + #include "unicode/uchar.h" #include "unicode/ustring.h" #include "unicode/utypes.h" diff --git a/Build/source/libs/icu/icu-src/source/samples/citer/citer.cpp b/Build/source/libs/icu/icu-src/source/samples/citer/citer.cpp index 958fe42587e..f8193707144 100644 --- a/Build/source/libs/icu/icu-src/source/samples/citer/citer.cpp +++ b/Build/source/libs/icu/icu-src/source/samples/citer/citer.cpp @@ -73,7 +73,7 @@ void Test::TestUChariter() { test2->getText(result2); if (result1 != result2) { u_fprintf(out, "iter.getText() != clone.getText()\n"); - } + } u_fprintf(out, "\n"); @@ -95,7 +95,7 @@ void Test::TestUChariter() { u_fprintf(out, "Iterator reached end prematurely"); } else if (c != testText[i]) { - u_fprintf(out, "Character mismatch at position %d\n" + i); + u_fprintf(out, "Character mismatch at position %d\n", i); } if (iter.current() != c) { u_fprintf(out, "current() isn't working right"); @@ -111,7 +111,7 @@ void Test::TestUChariter() { u_fprintf(out, "|"); printUChar(c); - } while (c != CharacterIterator::DONE); + } while (c != CharacterIterator::DONE); delete test2; u_fprintf(out, "\n"); @@ -146,7 +146,7 @@ void Test::TestStringiter() { int32_t i = iter.endIndex(); printUChar(c); - i--; // already printed out the last char + i--; // already printed out the last char if (iter.startIndex() != 0 || iter.endIndex() != u_strlen(testText)) { u_fprintf(out, "startIndex() or endIndex() failed\n"); diff --git a/Build/source/libs/icu/icu-src/source/samples/coll/coll.cpp b/Build/source/libs/icu/icu-src/source/samples/coll/coll.cpp index d8d067a8520..909412f5b67 100644 --- a/Build/source/libs/icu/icu-src/source/samples/coll/coll.cpp +++ b/Build/source/libs/icu/icu-src/source/samples/coll/coll.cpp @@ -45,8 +45,8 @@ const char gHelpString[] = * These global variables are set according to the options specified * on the command line by the user. */ -char * opt_locale = "en_US"; -char * opt_rules = 0; +char const *opt_locale = "en_US"; +char *opt_rules = 0; UBool opt_help = false; UBool opt_norm = false; UBool opt_french = false; @@ -55,8 +55,8 @@ UBool opt_lower = false; UBool opt_upper = false; UBool opt_case = false; int opt_level = 0; -char * opt_source = "abc"; -char * opt_target = "abd"; +char const *opt_source = "abc"; +char const *opt_target = "abd"; UCollator * collator = 0; /** diff --git a/Build/source/libs/icu/icu-src/source/samples/datecal/cal.cpp b/Build/source/libs/icu/icu-src/source/samples/datecal/cal.cpp index ba581b88d80..f8c0ef500bc 100644 --- a/Build/source/libs/icu/icu-src/source/samples/datecal/cal.cpp +++ b/Build/source/libs/icu/icu-src/source/samples/datecal/cal.cpp @@ -17,6 +17,8 @@ #include "unicode/gregocal.h" #include <stdio.h> +using namespace icu; + extern "C" void c_main(); void cpp_main() diff --git a/Build/source/libs/icu/icu-src/source/samples/dtitvfmtsample/Makefile b/Build/source/libs/icu/icu-src/source/samples/dtitvfmtsample/Makefile new file mode 100644 index 00000000000..404c9603c74 --- /dev/null +++ b/Build/source/libs/icu/icu-src/source/samples/dtitvfmtsample/Makefile @@ -0,0 +1,27 @@ +# Copyright (C) 2016 and later: Unicode, Inc. and others. +# License & terms of use: http://www.unicode.org/copyright.html +# +# Copyright (c) 2000-2006 IBM, Inc. and others +# sample code makefile + +# Usage: +# - configure, build, install ICU (make install) +# - make sure "icu-config" (in the ICU installed bin directory) is on +# the path +# - do 'make' in this directory + +#### definitions +# Name of your target +TARGET=dtitvfmtsample + +# All object files (C or C++) +OBJECTS=dtitvfmtsample.o + +#### rules +# Load in standard makefile definitions +include ../defs.mk + +LDFLAGS += $(LDFLAGS_USTDIO) + +# the actual rules (this is a simple sample) +include ../rules.mk diff --git a/Build/source/libs/icu/icu-src/source/samples/dtitvfmtsample/dtitvfmtsample.cpp b/Build/source/libs/icu/icu-src/source/samples/dtitvfmtsample/dtitvfmtsample.cpp index c4f7b18c89e..3644fe01687 100644 --- a/Build/source/libs/icu/icu-src/source/samples/dtitvfmtsample/dtitvfmtsample.cpp +++ b/Build/source/libs/icu/icu-src/source/samples/dtitvfmtsample/dtitvfmtsample.cpp @@ -15,130 +15,130 @@ using namespace std; using namespace icu; static void dtitvfmtPreDefined() { - - u_printf("===============================================================================\n"); - u_printf(" dtitvfmtPreDefined()\n"); + + u_printf("===============================================================================\n"); + u_printf(" dtitvfmtPreDefined()\n"); u_printf("\n"); u_printf(" Use DateIntervalFormat to get date interval format for pre-defined skeletons:\n"); u_printf(" yMMMd, MMMMd, jm per locale\n"); u_printf("===============================================================================\n"); - - //! [dtitvfmtPreDefined] - UFILE *out = u_finit(stdout, NULL, "UTF-8"); - UErrorCode status =U_ZERO_ERROR; - // create 3 Date Intervals - UnicodeString data[] = { - UnicodeString("2007-10-10 10:10:10"), - UnicodeString("2008-10-10 10:10:10"), - UnicodeString("2008-11-10 10:10:10"), - UnicodeString("2008-11-10 15:10:10") - }; - Calendar *cal = Calendar::createInstance(status); - cal->set(2007,10,10,10,10,10); - UDate date1 = cal->getTime(status); - cal->set(2008,10,10,10,10,10); - UDate date2 = cal->getTime(status); - cal->set(2008,11,10,10,10,10); - UDate date3 = cal->getTime(status); - cal->set(2008,11,10,15,10,10); - UDate date4 = cal->getTime(status); + + //! [dtitvfmtPreDefined] + UFILE *out = u_finit(stdout, NULL, "UTF-8"); + UErrorCode status =U_ZERO_ERROR; + // create 3 Date Intervals + UnicodeString data[] = { + UnicodeString("2007-10-10 10:10:10"), + UnicodeString("2008-10-10 10:10:10"), + UnicodeString("2008-11-10 10:10:10"), + UnicodeString("2008-11-10 15:10:10") + }; + Calendar *cal = Calendar::createInstance(status); + cal->set(2007,10,10,10,10,10); + UDate date1 = cal->getTime(status); + cal->set(2008,10,10,10,10,10); + UDate date2 = cal->getTime(status); + cal->set(2008,11,10,10,10,10); + UDate date3 = cal->getTime(status); + cal->set(2008,11,10,15,10,10); + UDate date4 = cal->getTime(status); DateInterval* dtitvsample[] = { - new DateInterval(date1,date2), + new DateInterval(date1,date2), new DateInterval(date2,date3), - new DateInterval(date3,date4), + new DateInterval(date3,date4), }; - UnicodeString skeletons[] = { + UnicodeString skeletons[] = { UnicodeString("yMMMd"), UnicodeString("MMMMd"), UnicodeString("jm"), - 0, - }; + UnicodeString("") + }; u_fprintf(out,"%-10s%-22s%-22s%-35s%-35s\n", "Skeleton","from","to","Date Interval in en_US","Date Interval in Ja"); - int i=0; - UnicodeString formatEn,formatJa; - FieldPosition pos=0; - for (int j=0;skeletons[j]!=NULL ;j++) { - u_fprintf(out,"%-10S%-22S%-22S",skeletons[j].getTerminatedBuffer(),data[i].getTerminatedBuffer(),data[i+1].getTerminatedBuffer()); + int i=0; + UnicodeString formatEn,formatJa; + FieldPosition pos=0; + for (int j=0; !skeletons[j].isEmpty() ;j++) { + u_fprintf(out,"%-10S%-22S%-22S",skeletons[j].getTerminatedBuffer(),data[i].getTerminatedBuffer(),data[i+1].getTerminatedBuffer()); //create a DateIntervalFormat instance for given skeleton, locale - DateIntervalFormat* dtitvfmtEn = DateIntervalFormat::createInstance(skeletons[j], Locale::getEnglish(),status); + DateIntervalFormat* dtitvfmtEn = DateIntervalFormat::createInstance(skeletons[j], Locale::getEnglish(),status); DateIntervalFormat* dtitvfmtJa = DateIntervalFormat::createInstance(skeletons[j], Locale::getJapanese(),status); - formatEn.remove(); - formatJa.remove(); - //get the DateIntervalFormat - dtitvfmtEn->format(dtitvsample[i],formatEn,pos,status); - dtitvfmtJa->format(dtitvsample[i],formatJa,pos,status); - u_fprintf(out,"%-35S%-35S\n", formatEn.getTerminatedBuffer(),formatJa.getTerminatedBuffer()); - delete dtitvfmtEn; - delete dtitvfmtJa; + formatEn.remove(); + formatJa.remove(); + //get the DateIntervalFormat + dtitvfmtEn->format(dtitvsample[i],formatEn,pos,status); + dtitvfmtJa->format(dtitvsample[i],formatJa,pos,status); + u_fprintf(out,"%-35S%-35S\n", formatEn.getTerminatedBuffer(),formatJa.getTerminatedBuffer()); + delete dtitvfmtEn; + delete dtitvfmtJa; i++; } - u_fclose(out); - //! [dtitvfmtPreDefined] + u_fclose(out); + //! [dtitvfmtPreDefined] } static void dtitvfmtCustomized() { - - u_printf("===============================================================================\n"); - u_printf("\n"); - u_printf(" dtitvfmtCustomized()\n"); - u_printf("\n"); + + u_printf("===============================================================================\n"); + u_printf("\n"); + u_printf(" dtitvfmtCustomized()\n"); + u_printf("\n"); u_printf(" Use DateIntervalFormat to create customized date interval format for yMMMd, Hm"); - u_printf("\n"); + u_printf("\n"); u_printf("================================================================================\n"); - //! [dtitvfmtCustomized] - UFILE *out = u_finit(stdout, NULL, "UTF-8"); - UErrorCode status =U_ZERO_ERROR; - UnicodeString data[] = { - UnicodeString("2007-9-10 10:10:10"), - UnicodeString("2007-10-10 10:10:10"), - UnicodeString("2007-10-10 22:10:10") - }; - // to create 2 Date Intervals + //! [dtitvfmtCustomized] + UFILE *out = u_finit(stdout, NULL, "UTF-8"); + UErrorCode status =U_ZERO_ERROR; + UnicodeString data[] = { + UnicodeString("2007-9-10 10:10:10"), + UnicodeString("2007-10-10 10:10:10"), + UnicodeString("2007-10-10 22:10:10") + }; + // to create 2 Date Intervals Calendar *cal1 = Calendar::createInstance(status); - cal1->set(2007,9,10,10,10,10); - Calendar *cal2 = Calendar::createInstance(status); - cal2->set(2007,10,10,10,10,10); - Calendar *cal3 = Calendar::createInstance(status); - cal3->set(2007,10,10,22,10,10); - DateInterval* dtitvsample[] = { - new DateInterval(cal1->getTime(status),cal2->getTime(status)), + cal1->set(2007,9,10,10,10,10); + Calendar *cal2 = Calendar::createInstance(status); + cal2->set(2007,10,10,10,10,10); + Calendar *cal3 = Calendar::createInstance(status); + cal3->set(2007,10,10,22,10,10); + DateInterval* dtitvsample[] = { + new DateInterval(cal1->getTime(status),cal2->getTime(status)), new DateInterval(cal2->getTime(status),cal3->getTime(status)) - }; - UnicodeString skeletons[] = { + }; + UnicodeString skeletons[] = { UnicodeString("yMMMd"), UnicodeString("Hm"), - 0, + UnicodeString("") }; - u_printf("%-10s%-22s%-22s%-45s%-35s\n", "Skeleton", "from","to", "Date Interval in en_US","Date Interval in Ja"); - // Create an empty DateIntervalInfo object + u_printf("%-10s%-22s%-22s%-45s%-35s\n", "Skeleton", "from","to", "Date Interval in en_US","Date Interval in Ja"); + // Create an empty DateIntervalInfo object DateIntervalInfo dtitvinf = DateIntervalInfo(status); - // Set Date Time internal pattern for MONTH, HOUR_OF_DAY + // Set Date Time internal pattern for MONTH, HOUR_OF_DAY dtitvinf.setIntervalPattern("yMMMd", UCAL_MONTH, "y 'Diff' MMM d --- MMM d",status); dtitvinf.setIntervalPattern("Hm", UCAL_HOUR_OF_DAY, "yyyy MMM d HH:mm ~ HH:mm",status); - // Set fallback interval pattern + // Set fallback interval pattern dtitvinf.setFallbackIntervalPattern("{0} ~~~ {1}",status); - // Get the DateIntervalFormat with the custom pattern + // Get the DateIntervalFormat with the custom pattern UnicodeString formatEn,formatJa; - FieldPosition pos=0; - for (int i=0;i<2;i++){ - for (int j=0;skeletons[j]!=NULL;j++) { - u_fprintf(out,"%-10S%-22S%-22S", skeletons[i].getTerminatedBuffer(),data[j].getTerminatedBuffer(), data[j+1].getTerminatedBuffer()); + FieldPosition pos=0; + for (int i=0;i<2;i++){ + for (int j=0;!skeletons[j].isEmpty();j++) { + u_fprintf(out,"%-10S%-22S%-22S", skeletons[i].getTerminatedBuffer(),data[j].getTerminatedBuffer(), data[j+1].getTerminatedBuffer()); DateIntervalFormat* dtitvfmtEn = DateIntervalFormat::createInstance(skeletons[i],Locale::getEnglish(),dtitvinf,status); DateIntervalFormat* dtitvfmtJa = DateIntervalFormat::createInstance(skeletons[i],Locale::getJapanese(),dtitvinf,status); - formatEn.remove(); - formatJa.remove(); - dtitvfmtEn->format(dtitvsample[j],formatEn,pos,status); - dtitvfmtJa->format(dtitvsample[j],formatJa,pos,status); - u_fprintf(out,"%-45S%-35S\n", formatEn.getTerminatedBuffer(),formatJa.getTerminatedBuffer()); + formatEn.remove(); + formatJa.remove(); + dtitvfmtEn->format(dtitvsample[j],formatEn,pos,status); + dtitvfmtJa->format(dtitvsample[j],formatJa,pos,status); + u_fprintf(out,"%-45S%-35S\n", formatEn.getTerminatedBuffer(),formatJa.getTerminatedBuffer()); } } - u_fclose(out); - //! [dtitvfmtCustomized] + u_fclose(out); + //! [dtitvfmtCustomized] } int main (int argc, char* argv[]) { - dtitvfmtPreDefined(); - dtitvfmtCustomized(); - return 0; + dtitvfmtPreDefined(); + dtitvfmtCustomized(); + return 0; } diff --git a/Build/source/libs/icu/icu-src/source/samples/dtptngsample/Makefile b/Build/source/libs/icu/icu-src/source/samples/dtptngsample/Makefile new file mode 100644 index 00000000000..95393190014 --- /dev/null +++ b/Build/source/libs/icu/icu-src/source/samples/dtptngsample/Makefile @@ -0,0 +1,27 @@ +# Copyright (C) 2016 and later: Unicode, Inc. and others. +# License & terms of use: http://www.unicode.org/copyright.html +# +# Copyright (c) 2000-2006 IBM, Inc. and others +# sample code makefile + +# Usage: +# - configure, build, install ICU (make install) +# - make sure "icu-config" (in the ICU installed bin directory) is on +# the path +# - do 'make' in this directory + +#### definitions +# Name of your target +TARGET=dtptngsample + +# All object files (C or C++) +OBJECTS=dtptngsample.o + +#### rules +# Load in standard makefile definitions +include ../defs.mk + +LDFLAGS += $(LDFLAGS_USTDIO) + +# the actual rules (this is a simple sample) +include ../rules.mk diff --git a/Build/source/libs/icu/icu-src/source/samples/dtptngsample/dtptngsample.cpp b/Build/source/libs/icu/icu-src/source/samples/dtptngsample/dtptngsample.cpp index 58d394d57df..1c39f9794f9 100644 --- a/Build/source/libs/icu/icu-src/source/samples/dtptngsample/dtptngsample.cpp +++ b/Build/source/libs/icu/icu-src/source/samples/dtptngsample/dtptngsample.cpp @@ -1,7 +1,7 @@ // © 2016 and later: Unicode, Inc. and others. // License & terms of use: http://www.unicode.org/copyright.html /******************************************************************** - * COPYRIGHT: + * COPYRIGHT: * Copyright (c) 2008-2014, International Business Machines Corporation and * others. All Rights Reserved. ********************************************************************/ @@ -16,151 +16,151 @@ using namespace std; using namespace icu; static void getBestPatternExample() { - - u_printf("========================================================================\n"); - u_printf(" getBestPatternExample()\n"); + + u_printf("========================================================================\n"); + u_printf(" getBestPatternExample()\n"); u_printf("\n"); u_printf(" Use DateTimePatternGenerator to create customized date/time pattern:\n"); u_printf(" yQQQQ,yMMMM, MMMMd, hhmm, jjmm per locale\n"); u_printf("========================================================================\n"); - //! [getBestPatternExample] - UnicodeString skeletons [] = { - UnicodeString("yQQQQ"), // year + full name of quarter, i.e., 4th quarter 1999 + //! [getBestPatternExample] + UnicodeString skeletons [] = { + UnicodeString("yQQQQ"), // year + full name of quarter, i.e., 4th quarter 1999 UnicodeString("yMMMM"), // year + full name of month, i.e., October 1999 UnicodeString("MMMMd"), // full name of month + day of the month, i.e., October 25 UnicodeString("hhmm"), // 12-hour-cycle format, i.e., 1:32 PM UnicodeString("jjmm"), // preferred hour format for the given locale, i.e., 24-hour-cycle format for fr_FR - 0, - }; + 0, + }; + + Locale locales[] = { + Locale ("en_US"), + Locale ("fr_FR"), + Locale ("zh_CN"), + }; - Locale locales[] = { - Locale ("en_US"), - Locale ("fr_FR"), - Locale ("zh_CN"), - }; - - const char* filename = "sample.txt"; - /* open a UTF-8 file for writing */ - UFILE* f = u_fopen(filename, "w", NULL,"UTF-8"); - UnicodeString dateReturned; - UErrorCode status =U_ZERO_ERROR; - Calendar *cal = Calendar::createInstance(status); - cal->set (1999,9,13,23,58,59); - UDate date = cal->getTime(status); - u_fprintf(f, "%-20S%-20S%-20S%-20S\n", UnicodeString("Skeleton").getTerminatedBuffer(),UnicodeString("en_US").getTerminatedBuffer(),UnicodeString("fr_FR").getTerminatedBuffer(),UnicodeString("zh_CN").getTerminatedBuffer()); - for (int i=0;skeletons[i]!=NULL;i++) { - u_fprintf(f, "%-20S",skeletons[i].getTerminatedBuffer()); - for (int j=0;j<sizeof(locales)/sizeof(locales[0]);j++) { - // create a DateTimePatternGenerator instance for given locale - DateTimePatternGenerator *dtfg= DateTimePatternGenerator::createInstance(locales[j],status); - // use getBestPattern method to get the best pattern for the given skeleton - UnicodeString pattern = dtfg->getBestPattern(skeletons[i],status); - // Constructs a SimpleDateFormat with the best pattern generated above and the given locale - SimpleDateFormat *sdf = new SimpleDateFormat(pattern,locales[j],status); - dateReturned.remove(); - // Get the format of the given date - sdf->format(date,dateReturned,status); - /* write Unicode string to file */ - u_fprintf(f, "%-20S", dateReturned.getTerminatedBuffer()); - delete dtfg; - delete sdf; - } - u_fprintf(f,"\n"); - } - /* close the file resource */ - u_fclose(f); - delete cal; - //! [getBestPatternExample] + const char* filename = "sample.txt"; + /* open a UTF-8 file for writing */ + UFILE* f = u_fopen(filename, "w", NULL,"UTF-8"); + UnicodeString dateReturned; + UErrorCode status =U_ZERO_ERROR; + Calendar *cal = Calendar::createInstance(status); + cal->set (1999,9,13,23,58,59); + UDate date = cal->getTime(status); + u_fprintf(f, "%-20S%-20S%-20S%-20S\n", UnicodeString("Skeleton").getTerminatedBuffer(),UnicodeString("en_US").getTerminatedBuffer(),UnicodeString("fr_FR").getTerminatedBuffer(),UnicodeString("zh_CN").getTerminatedBuffer()); + for (int i=0;!skeletons[i].isEmpty();i++) { + u_fprintf(f, "%-20S",skeletons[i].getTerminatedBuffer()); + for (int j=0;j<sizeof(locales)/sizeof(locales[0]);j++) { + // create a DateTimePatternGenerator instance for given locale + DateTimePatternGenerator *dtfg= DateTimePatternGenerator::createInstance(locales[j],status); + // use getBestPattern method to get the best pattern for the given skeleton + UnicodeString pattern = dtfg->getBestPattern(skeletons[i],status); + // Constructs a SimpleDateFormat with the best pattern generated above and the given locale + SimpleDateFormat *sdf = new SimpleDateFormat(pattern,locales[j],status); + dateReturned.remove(); + // Get the format of the given date + sdf->format(date,dateReturned,status); + /* write Unicode string to file */ + u_fprintf(f, "%-20S", dateReturned.getTerminatedBuffer()); + delete dtfg; + delete sdf; + } + u_fprintf(f,"\n"); + } + /* close the file resource */ + u_fclose(f); + delete cal; + //! [getBestPatternExample] } static void addPatternExample() { - - u_printf("========================================================================\n"); + + u_printf("========================================================================\n"); u_printf(" addPatternExample()\n"); - u_printf("\n"); + u_printf("\n"); u_printf(" Use addPattern API to add new '. von' to existing pattern\n"); u_printf("========================================================================\n"); - //! [addPatternExample] - UErrorCode status =U_ZERO_ERROR; - UnicodeString conflictingPattern,dateReturned, pattern; - Locale locale=Locale::getFrance(); - Calendar *cal = Calendar::createInstance(status); - cal->set (1999,9,13,23,58,59); - UDate date = cal->getTime(status); + //! [addPatternExample] + UErrorCode status =U_ZERO_ERROR; + UnicodeString conflictingPattern,dateReturned, pattern; + Locale locale=Locale::getFrance(); + Calendar *cal = Calendar::createInstance(status); + cal->set (1999,9,13,23,58,59); + UDate date = cal->getTime(status); // Create an DateTimePatternGenerator instance for the given locale - DateTimePatternGenerator *dtfg= DateTimePatternGenerator::createInstance(locale,status); - SimpleDateFormat *sdf = new SimpleDateFormat(dtfg->getBestPattern("MMMMddHmm",status),locale,status); + DateTimePatternGenerator *dtfg= DateTimePatternGenerator::createInstance(locale,status); + SimpleDateFormat *sdf = new SimpleDateFormat(dtfg->getBestPattern("MMMMddHmm",status),locale,status); // Add '. von' to the existing pattern dtfg->addPattern("dd'. von' MMMM", true, conflictingPattern,status); // Apply the new pattern sdf->applyPattern(dtfg->getBestPattern("MMMMddHmm",status)); - dateReturned = sdf->format(date, dateReturned, status); - pattern =sdf->toPattern(pattern); - u_printf("%s\n", "New Pattern for FRENCH: "); - u_printf("%S\n", pattern.getTerminatedBuffer()); - u_printf("%s\n", "Date Time in new Pattern: "); - u_printf("%S\n", dateReturned.getTerminatedBuffer()); - delete dtfg; - delete sdf; - delete cal; + dateReturned = sdf->format(date, dateReturned, status); + pattern =sdf->toPattern(pattern); + u_printf("%s\n", "New Pattern for FRENCH: "); + u_printf("%S\n", pattern.getTerminatedBuffer()); + u_printf("%s\n", "Date Time in new Pattern: "); + u_printf("%S\n", dateReturned.getTerminatedBuffer()); + delete dtfg; + delete sdf; + delete cal; - //! [addPatternExample] + //! [addPatternExample] /* output of the sample code: ************************************************************************************************ New Pattern for FRENCH: dd. 'von' MMMM HH:mm Date Time in new Pattern: 13. von octobre 23:58 - + *************************************************************************************************/ - } + } static void replaceFieldTypesExample() { - // Use repalceFieldTypes API to replace zone 'zzzz' with 'vvvv' + // Use repalceFieldTypes API to replace zone 'zzzz' with 'vvvv' u_printf("========================================================================\n"); u_printf(" replaceFieldTypeExample()\n"); u_printf("\n"); u_printf(" Use replaceFieldTypes API to replace zone 'zzzz' with 'vvvv'\n"); u_printf("========================================================================\n"); - //! [replaceFieldTypesExample] - UFILE *out = u_finit(stdout, NULL, "UTF-8"); - UErrorCode status =U_ZERO_ERROR; - UnicodeString pattern,dateReturned; - Locale locale =Locale::getFrance(); - Calendar *cal = Calendar::createInstance(status); - cal->set (1999,9,13,23,58,59); - UDate date = cal->getTime(status); - TimeZone *zone = TimeZone::createTimeZone(UnicodeString("Europe/Paris")); - DateTimePatternGenerator *dtfg = DateTimePatternGenerator::createInstance(locale,status); - SimpleDateFormat *sdf = new SimpleDateFormat("EEEE d MMMM y HH:mm:ss zzzz",locale,status); - sdf->setTimeZone(*zone); - pattern = sdf->toPattern(pattern); - u_fprintf(out, "%S\n", UnicodeString("Pattern before replacement:").getTerminatedBuffer()); - u_fprintf(out, "%S\n", pattern.getTerminatedBuffer()); - dateReturned.remove(); - dateReturned = sdf->format(date, dateReturned, status); - u_fprintf(out, "%S\n", UnicodeString("Date/Time format in fr_FR:").getTerminatedBuffer()); - u_fprintf(out, "%S\n", dateReturned.getTerminatedBuffer()); + //! [replaceFieldTypesExample] + UFILE *out = u_finit(stdout, NULL, "UTF-8"); + UErrorCode status =U_ZERO_ERROR; + UnicodeString pattern,dateReturned; + Locale locale =Locale::getFrance(); + Calendar *cal = Calendar::createInstance(status); + cal->set (1999,9,13,23,58,59); + UDate date = cal->getTime(status); + TimeZone *zone = TimeZone::createTimeZone(UnicodeString("Europe/Paris")); + DateTimePatternGenerator *dtfg = DateTimePatternGenerator::createInstance(locale,status); + SimpleDateFormat *sdf = new SimpleDateFormat("EEEE d MMMM y HH:mm:ss zzzz",locale,status); + sdf->setTimeZone(*zone); + pattern = sdf->toPattern(pattern); + u_fprintf(out, "%S\n", UnicodeString("Pattern before replacement:").getTerminatedBuffer()); + u_fprintf(out, "%S\n", pattern.getTerminatedBuffer()); + dateReturned.remove(); + dateReturned = sdf->format(date, dateReturned, status); + u_fprintf(out, "%S\n", UnicodeString("Date/Time format in fr_FR:").getTerminatedBuffer()); + u_fprintf(out, "%S\n", dateReturned.getTerminatedBuffer()); // Replace zone "zzzz" in the pattern with "vvvv" - UnicodeString newPattern = dtfg->replaceFieldTypes(pattern, "vvvv", status); - // Apply the new pattern - sdf->applyPattern(newPattern); - dateReturned.remove(); - dateReturned = sdf->format(date, dateReturned, status); - u_fprintf(out, "%S\n", UnicodeString("Pattern after replacement:").getTerminatedBuffer()); - u_fprintf(out, "%S\n", newPattern.getTerminatedBuffer()); - u_fprintf(out, "%S\n", UnicodeString("Date/Time format in fr_FR:").getTerminatedBuffer()); - u_fprintf(out, "%S\n", dateReturned.getTerminatedBuffer()); - delete sdf; - delete dtfg; - delete zone; - delete cal; - u_fclose(out); - //! [replaceFieldTypesExample] + UnicodeString newPattern = dtfg->replaceFieldTypes(pattern, "vvvv", status); + // Apply the new pattern + sdf->applyPattern(newPattern); + dateReturned.remove(); + dateReturned = sdf->format(date, dateReturned, status); + u_fprintf(out, "%S\n", UnicodeString("Pattern after replacement:").getTerminatedBuffer()); + u_fprintf(out, "%S\n", newPattern.getTerminatedBuffer()); + u_fprintf(out, "%S\n", UnicodeString("Date/Time format in fr_FR:").getTerminatedBuffer()); + u_fprintf(out, "%S\n", dateReturned.getTerminatedBuffer()); + delete sdf; + delete dtfg; + delete zone; + delete cal; + u_fclose(out); + //! [replaceFieldTypesExample] } int main (int argc, char* argv[]) { - getBestPatternExample(); - addPatternExample(); - replaceFieldTypesExample(); - return 0; + getBestPatternExample(); + addPatternExample(); + replaceFieldTypesExample(); + return 0; } diff --git a/Build/source/libs/icu/icu-src/source/samples/plurfmtsample/Makefile b/Build/source/libs/icu/icu-src/source/samples/plurfmtsample/Makefile new file mode 100644 index 00000000000..ef7d7d4ace8 --- /dev/null +++ b/Build/source/libs/icu/icu-src/source/samples/plurfmtsample/Makefile @@ -0,0 +1,27 @@ +# Copyright (C) 2016 and later: Unicode, Inc. and others. +# License & terms of use: http://www.unicode.org/copyright.html +# +# Copyright (c) 2000-2006 IBM, Inc. and others +# sample code makefile + +# Usage: +# - configure, build, install ICU (make install) +# - make sure "icu-config" (in the ICU installed bin directory) is on +# the path +# - do 'make' in this directory + +#### definitions +# Name of your target +TARGET=plurfmtsample + +# All object files (C or C++) +OBJECTS=plurfmtsample.o + +#### rules +# Load in standard makefile definitions +include ../defs.mk + +LDFLAGS += $(LDFLAGS_USTDIO) + +# the actual rules (this is a simple sample) +include ../rules.mk diff --git a/Build/source/libs/icu/icu-src/source/samples/plurfmtsample/plurfmtsample.cpp b/Build/source/libs/icu/icu-src/source/samples/plurfmtsample/plurfmtsample.cpp index f910c4f56e1..b03e63541d4 100644 --- a/Build/source/libs/icu/icu-src/source/samples/plurfmtsample/plurfmtsample.cpp +++ b/Build/source/libs/icu/icu-src/source/samples/plurfmtsample/plurfmtsample.cpp @@ -19,17 +19,17 @@ using namespace std; using namespace icu; static void PluralFormatExample() { - - u_printf("=============================================================================\n"); - u_printf(" PluralFormatExample()\n"); + + u_printf("=============================================================================\n"); + u_printf(" PluralFormatExample()\n"); u_printf("\n"); u_printf(" Use PluralFormat and Messageformat to get Plural Form for languages below:\n"); u_printf(" English, Slovenian\n"); u_printf("=============================================================================\n"); - - //! [PluralFormatExample] - UErrorCode status =U_ZERO_ERROR; - Locale locEn = Locale("en"); + + //! [PluralFormatExample] + UErrorCode status =U_ZERO_ERROR; + Locale locEn = Locale("en"); Locale locSl = Locale("sl"); UnicodeString patEn = UnicodeString("one{dog} other{dogs}"); // English 'dog' @@ -42,19 +42,19 @@ static void PluralFormatExample() { MessageFormat* msgfmtEn = new MessageFormat("{0,number} {1}", locEn,status); MessageFormat* msgfmtSl = new MessageFormat("{0,number} {1}", locSl,status); - int numbers[] = {0, 1, 2, 3, 4, 5, 10, 100, 101, 102}; - u_printf("Output by using PluralFormat and MessageFormat API\n"); + int numbers[] = {0, 1, 2, 3, 4, 5, 10, 100, 101, 102}; + u_printf("Output by using PluralFormat and MessageFormat API\n"); u_printf("%-16s%-16s%-16s\n","Number", "English","Slovenian"); - + // Use MessageFormat.format () to format the objects and append to the given StringBuffer for (int i=0;i<sizeof(numbers)/sizeof(int);i++) { - UnicodeString msgEn,msgSl; - FieldPosition fpos = 0; - Formattable argEn[]={Formattable(numbers[i]), Formattable(plfmtEn.format(numbers[i],status))}; - Formattable argSl[]={Formattable(numbers[i]), Formattable(plfmtSl.format(numbers[i],status))}; - msgfmtEn->format(argEn,2,msgEn,fpos,status); - msgfmtSl->format(argSl,2,msgSl,fpos,status); - u_printf("%-16d%-16S%-16S\n", numbers[i], msgEn.getTerminatedBuffer(),msgSl.getTerminatedBuffer()); + UnicodeString msgEn,msgSl; + FieldPosition fpos = 0; + Formattable argEn[]={Formattable(numbers[i]), Formattable(plfmtEn.format(numbers[i],status))}; + Formattable argSl[]={Formattable(numbers[i]), Formattable(plfmtSl.format(numbers[i],status))}; + msgfmtEn->format(argEn,2,msgEn,fpos,status); + msgfmtSl->format(argSl,2,msgSl,fpos,status); + u_printf("%-16d%-16S%-16S\n", numbers[i], msgEn.getTerminatedBuffer(),msgSl.getTerminatedBuffer()); } u_printf("\n"); @@ -62,27 +62,27 @@ static void PluralFormatExample() { // Equivalent code with message format pattern UnicodeString msgPatEn = "{0,plural, one{# dog} other{# dogs}}"; UnicodeString msgPatSl = "{0,plural, one{# pes} two{# psa} few{# psi} other{# psov}}"; - - MessageFormat* altMsgfmtEn = new MessageFormat(msgPatEn, locEn,status); + + MessageFormat* altMsgfmtEn = new MessageFormat(msgPatEn, locEn,status); MessageFormat* altMsgfmtSl = new MessageFormat(msgPatSl, locSl,status); u_printf("Same Output by using MessageFormat API only\n"); u_printf("%-16s%-16s%-16s\n","Number", "English","Slovenian"); for (int i=0;i<sizeof(numbers)/sizeof(int);i++) { UnicodeString msgEn,msgSl; - Formattable arg[] = {numbers[i]}; - FieldPosition fPos =0; - altMsgfmtEn->format(arg, 1, msgEn, fPos, status); + Formattable arg[] = {numbers[i]}; + FieldPosition fPos =0; + altMsgfmtEn->format(arg, 1, msgEn, fPos, status); altMsgfmtSl->format(arg, 1, msgSl, fPos,status); u_printf("%-16d%-16S%-16S\n", numbers[i], msgEn.getTerminatedBuffer(), msgSl.getTerminatedBuffer()); } - delete msgfmtEn; - delete msgfmtSl; - delete altMsgfmtEn; - delete altMsgfmtSl; - //! [PluralFormatExample] + delete msgfmtEn; + delete msgfmtSl; + delete altMsgfmtEn; + delete altMsgfmtSl; + //! [PluralFormatExample] - /* output of the sample code: + /* output of the sample code: ******************************************************************** Number English Slovenian 0 0 dogs 0 psov @@ -100,6 +100,6 @@ static void PluralFormatExample() { } int main (int argc, char* argv[]) { - PluralFormatExample(); - return 0; + PluralFormatExample(); + return 0; } diff --git a/Build/source/libs/icu/icu-src/source/samples/readme.txt b/Build/source/libs/icu/icu-src/source/samples/readme.txt index 0ef21771da8..1dfef216d96 100644 --- a/Build/source/libs/icu/icu-src/source/samples/readme.txt +++ b/Build/source/libs/icu/icu-src/source/samples/readme.txt @@ -4,36 +4,46 @@ ## Copyright (c) 2002-2010, International Business Machines Corporation ## and others. All Rights Reserved. -This directory contains sample code -Below is a short description of the contents of this directory. +This directory contains sample code using ICU4C routines. Below is a +short description of the contents of this directory. -break - demonstrates how to use BreakIterators in C and C++. +break - demonstrates how to use BreakIterators in C and C++. -cal - prints out a calendar. +cal - prints out a calendar. case - demonstrates how to do Unicode case conversion in C and C++. +coll - shows how collation compares strings + csdet - demonstrates using ICU's CharSet Detection API -date - prints out the current date, localized. +date - prints out the current date, localized. + +datecal - demonstrates how a calendar object provides information + +datefmt - an exercise using the date formatting API -datefmt - an exercise using the date formatting API +dtitvfmtsample - shows how date interval format uses predefined skeletons -layout - demonstrates the ICU LayoutEngine +dtptngsample - uses DateTimePatternGenerator to create customized date/time pattern + +layout - demonstrates the ICU LayoutEngine (obsolete) -legacy - demonstrates using two versions of ICU in one application +legacy - demonstrates using two versions of ICU in one application (obsolete) msgfmt - demonstrates the use of the Message Format numfmt - demonstrates the use of the number format +plurfmtsample - uses PluralFormat and Messageformat to get Plural Form + props - demonstrates the use of Unicode properties strsrch - demonstrates how to search for patterns in Unicode text using the usearch interface. translit - demonstrates the use of ICU transliteration -uciter8.c - demonstrates how to leniently read 8-bit Unicode text. +uciter8 - demonstrates how to leniently read 8-bit Unicode text. ucnv - demonstrates the use of ICU codepage conversion @@ -41,7 +51,7 @@ udata - demonstrates the use of ICU low level data routines (reader/writer in ufortune - demonstrates packaging and use of resources in an application -ugrep - demonstrates ICU Regular Expressions. +ugrep - demonstrates ICU Regular Expressions. uresb - demonstrates building and loading resource bundles @@ -52,12 +62,11 @@ ustring - demonstrates ICU string manipulation functions * Where can I find more sample code? - The "uconv" utility is a full-featured command line application. - It is normally built with ICU, and is located in icu/source/extra/uconv + It is normally built with ICU, and is located in icu/source/extra/uconv - - The "icuapps" CVS module contains other applications and libraries not - included with ICU. You can check it out from the CVS command line - by using for example, "cvs co icuapps" instead of "cvs co icu", - or through WebCVS at http://dev.icu-project.org/cgi-bin/viewcvs.cgi/icuapps/ + - The "icu-demos" contains other applications and libraries not + included with ICU. You can check it out from https://github.com/unicode-org/icu-demos + using github clone. See the README file for additional information. == * How do I build the samples? @@ -76,7 +85,7 @@ ustring - demonstrates ICU string manipulation functions - be sure 'icu-config' is accessible from the PATH - type 'make all-samples' from this directory (other targets: clean-samples, check-samples) - Note: 'make all-samples' won't work correctly in out of source builds. + Note: 'make all-samples' won't work correctly in out of source builds. - - legacy and layout are not included in these lists, - please see their individual readmes. + Note that legacy and layout are obsolete samples that may not compile or run without + adjustments to their makefiles. diff --git a/Build/source/libs/icu/icu-src/source/samples/strsrch/strsrch.cpp b/Build/source/libs/icu/icu-src/source/samples/strsrch/strsrch.cpp index c5fff0c40ba..c275fef66f9 100644 --- a/Build/source/libs/icu/icu-src/source/samples/strsrch/strsrch.cpp +++ b/Build/source/libs/icu/icu-src/source/samples/strsrch/strsrch.cpp @@ -47,7 +47,7 @@ const char gHelpString[] = * These global variables are set according to the options specified * on the command line by the user. */ -char * opt_locale = "en_US"; +char const *opt_locale = "en_US"; char * opt_rules = 0; UBool opt_help = false; UBool opt_norm = false; @@ -59,8 +59,8 @@ UBool opt_case = false; UBool opt_overlap = false; UBool opt_canonical = false; int opt_level = 0; -char * opt_source = "International Components for Unicode"; -char * opt_pattern = "Unicode"; +char const *opt_source = "International Components for Unicode"; +char const *opt_pattern = "Unicode"; UCollator * collator = 0; UStringSearch * search = 0; UChar rules[100]; diff --git a/Build/source/libs/icu/icu-src/source/stubdata/BUILD b/Build/source/libs/icu/icu-src/source/stubdata/BUILD.bazel index abb73519ec4..abb73519ec4 100644 --- a/Build/source/libs/icu/icu-src/source/stubdata/BUILD +++ b/Build/source/libs/icu/icu-src/source/stubdata/BUILD.bazel diff --git a/Build/source/libs/icu/icu-src/source/stubdata/stubdata.vcxproj b/Build/source/libs/icu/icu-src/source/stubdata/stubdata.vcxproj index 64a6ef1a03a..5607dead597 100644 --- a/Build/source/libs/icu/icu-src/source/stubdata/stubdata.vcxproj +++ b/Build/source/libs/icu/icu-src/source/stubdata/stubdata.vcxproj @@ -56,7 +56,7 @@ <SetChecksum>true</SetChecksum> <TurnOffAssemblyGeneration>true</TurnOffAssemblyGeneration> <!-- Note: stubdata is somewhat odd in that it doesn't suffix the Debug output DLL/LIB with a "d" like common/i18n/etc. --> - <OutputFile>..\..\$(IcuBinOutputDir)\icudt70.dll</OutputFile> + <OutputFile>..\..\$(IcuBinOutputDir)\icudt71.dll</OutputFile> <ProgramDatabaseFile>.\..\..\$(IcuLibOutputDir)\icudt.pdb</ProgramDatabaseFile> <ImportLibrary>..\..\$(IcuLibOutputDir)\icudt.lib</ImportLibrary> </Link> diff --git a/Build/source/libs/icu/icu-src/source/test/cintltst/capitst.c b/Build/source/libs/icu/icu-src/source/test/cintltst/capitst.c index 831236d9dd7..bb49f4d674c 100644 --- a/Build/source/libs/icu/icu-src/source/test/cintltst/capitst.c +++ b/Build/source/libs/icu/icu-src/source/test/cintltst/capitst.c @@ -73,6 +73,7 @@ void addCollAPITest(TestNode** root) /*addTest(root, &TestGetDefaultRules, "tscoll/capitst/TestGetDefaultRules");*/ addTest(root, &TestDecomposition, "tscoll/capitst/TestDecomposition"); addTest(root, &TestSafeClone, "tscoll/capitst/TestSafeClone"); + addTest(root, &TestClone, "tscoll/capitst/TestClone"); addTest(root, &TestCloneBinary, "tscoll/capitst/TestCloneBinary"); addTest(root, &TestGetSetAttr, "tscoll/capitst/TestGetSetAttr"); addTest(root, &TestBounds, "tscoll/capitst/TestBounds"); @@ -806,6 +807,124 @@ void TestSafeClone() { } } +void TestClone() { + UChar test1[6]; + UChar test2[6]; + static const UChar umlautUStr[] = {0x00DC, 0}; + static const UChar oeStr[] = {0x0055, 0x0045, 0}; + UCollator * someCollators [CLONETEST_COLLATOR_COUNT]; + UCollator * someClonedCollators [CLONETEST_COLLATOR_COUNT]; + UCollator * col = NULL; + UErrorCode err = U_ZERO_ERROR; + int8_t idx = 6; /* Leave this here to test buffer alignment in memory*/ + const char sampleRuleChars[] = "&Z < CH"; + UChar sampleRule[sizeof(sampleRuleChars)]; + + u_uastrcpy(test1, "abCda"); + u_uastrcpy(test2, "abcda"); + u_uastrcpy(sampleRule, sampleRuleChars); + + /* one default collator & two complex ones */ + someCollators[0] = ucol_open("en_US", &err); + someCollators[1] = ucol_open("ko", &err); + someCollators[2] = ucol_open("ja_JP", &err); + someCollators[3] = ucol_openRules(sampleRule, -1, UCOL_ON, UCOL_TERTIARY, NULL, &err); + if(U_FAILURE(err)) { + for (idx = 0; idx < CLONETEST_COLLATOR_COUNT; idx++) { + ucol_close(someCollators[idx]); + } + log_data_err("Couldn't open one or more collators\n"); + return; + } + + /* Check the various error & informational states: */ + + /* Null status - just returns NULL */ + if (NULL != ucol_clone(someCollators[0], NULL)) + { + log_err("FAIL: Cloned Collator failed to deal correctly with null status\n"); + } + /* error status - should return 0 & keep error the same */ + err = U_MEMORY_ALLOCATION_ERROR; + if (NULL != ucol_clone(someCollators[0], &err) || err != U_MEMORY_ALLOCATION_ERROR) + { + log_err("FAIL: Cloned Collator failed to deal correctly with incoming error status\n"); + } + err = U_ZERO_ERROR; + + /* Verify we can use this run-time calculated size */ + if (NULL == (col = ucol_clone(someCollators[0], &err)) || U_FAILURE(err)) + { + log_err("FAIL: Collator can't be cloned.\n"); + } + if (col) ucol_close(col); + + if (NULL == (col = ucol_clone(someCollators[0], &err)) || err != U_ZERO_ERROR) + { + log_err("FAIL: Cloned Collator failed to deal correctly\n"); + } + if (col) ucol_close(col); + err = U_ZERO_ERROR; + + /* Null Collator - return NULL & set U_ILLEGAL_ARGUMENT_ERROR */ + if (NULL != ucol_clone(NULL, &err) || err != U_ILLEGAL_ARGUMENT_ERROR) + { + log_err("FAIL: Cloned Collator failed to deal correctly with null Collator pointer\n"); + } + err = U_ZERO_ERROR; + + /* Test that a cloned collator doesn't accidentally use UCA. */ + col=ucol_open("de@collation=phonebook", &err); + someClonedCollators[0] = ucol_clone(col, &err); + doAssert( (ucol_greater(col, umlautUStr, u_strlen(umlautUStr), oeStr, u_strlen(oeStr))), "Original German phonebook collation sorts differently than expected"); + doAssert( (ucol_greater(someClonedCollators[0], umlautUStr, u_strlen(umlautUStr), oeStr, u_strlen(oeStr))), "Cloned German phonebook collation sorts differently than expected"); + if (!ucol_equals(someClonedCollators[0], col)) { + log_err("FAIL: Cloned German phonebook collator is not equal to original.\n"); + } + ucol_close(col); + ucol_close(someClonedCollators[0]); + + err = U_ZERO_ERROR; + + /* change orig & clone & make sure they are independent */ + + for (idx = 0; idx < CLONETEST_COLLATOR_COUNT; idx++) + { + ucol_setStrength(someCollators[idx], UCOL_IDENTICAL); + err = U_ZERO_ERROR; + ucol_close(ucol_clone(someCollators[idx], &err)); + if (err != U_ZERO_ERROR) { + log_err("FAIL: collator number %d was not allocated.\n", idx); + log_err("FAIL: status of Collator[%d] is %d (hex: %x).\n", idx, err, err); + } + + err = U_ZERO_ERROR; + someClonedCollators[idx] = ucol_clone(someCollators[idx], &err); + if (U_FAILURE(err)) { + log_err("FAIL: Unable to clone collator %d - %s\n", idx, u_errorName(err)); + continue; + } + if (!ucol_equals(someClonedCollators[idx], someCollators[idx])) { + log_err("FAIL: Cloned collator is not equal to original at index = %d.\n", idx); + } + + /* Check the usability */ + ucol_setStrength(someCollators[idx], UCOL_PRIMARY); + ucol_setAttribute(someCollators[idx], UCOL_CASE_LEVEL, UCOL_OFF, &err); + + doAssert( (ucol_equal(someCollators[idx], test1, u_strlen(test1), test2, u_strlen(test2))), "Result should be \"abcda\" == \"abCda\""); + + /* Close the original to make sure that the clone is usable. */ + ucol_close(someCollators[idx]); + + ucol_setStrength(someClonedCollators[idx], UCOL_TERTIARY); + ucol_setAttribute(someClonedCollators[idx], UCOL_CASE_LEVEL, UCOL_OFF, &err); + doAssert( (ucol_greater(someClonedCollators[idx], test1, u_strlen(test1), test2, u_strlen(test2))), "Result should be \"abCda\" >>> \"abcda\" "); + + ucol_close(someClonedCollators[idx]); + } +} + void TestCloneBinary(){ UErrorCode err = U_ZERO_ERROR; UCollator * col = ucol_open("en_US", &err); diff --git a/Build/source/libs/icu/icu-src/source/test/cintltst/capitst.h b/Build/source/libs/icu/icu-src/source/test/cintltst/capitst.h index 7f6f558b0d3..5c761fad895 100644 --- a/Build/source/libs/icu/icu-src/source/test/cintltst/capitst.h +++ b/Build/source/libs/icu/icu-src/source/test/cintltst/capitst.h @@ -75,6 +75,11 @@ void TestSafeClone(void); /** + * Test ucol_clone () + **/ + void TestClone(void); + + /** * Test ucol_cloneBinary(), ucol_openBinary() **/ void TestCloneBinary(void); diff --git a/Build/source/libs/icu/icu-src/source/test/cintltst/cbiditst.c b/Build/source/libs/icu/icu-src/source/test/cintltst/cbiditst.c index 6d233130fe0..38be9c50564 100644 --- a/Build/source/libs/icu/icu-src/source/test/cintltst/cbiditst.c +++ b/Build/source/libs/icu/icu-src/source/test/cintltst/cbiditst.c @@ -4591,6 +4591,15 @@ testClassOverride(void) { ubidi_close(pBiDi); return; } + // Quick callback test (API coverage). + if (ubidi_getCustomizedClass(pBiDi, u'A')!=AL || + ubidi_getCustomizedClass(pBiDi, u'H')!=R || + ubidi_getCustomizedClass(pBiDi, u'^')!=PDF || + ubidi_getCustomizedClass(pBiDi, u'~')!=BN) { + log_err("ubidi_getCustomizedClass() returns different values than " + "expected from overrideBidiClass() customClasses[]\n"); + } + verifyCallbackParams(oldFn, oldContext, NULL, NULL, 0); ubidi_getClassCallback(pBiDi, &oldFn, &oldContext); diff --git a/Build/source/libs/icu/icu-src/source/test/cintltst/ccapitst.c b/Build/source/libs/icu/icu-src/source/test/cintltst/ccapitst.c index 50750137908..aee75e6dd9d 100644 --- a/Build/source/libs/icu/icu-src/source/test/cintltst/ccapitst.c +++ b/Build/source/libs/icu/icu-src/source/test/cintltst/ccapitst.c @@ -64,6 +64,7 @@ static void TestJ1968(void); static void TestLMBCSMaxChar(void); #endif +static void TestConvertClone(void); #if !UCONFIG_NO_LEGACY_CONVERSION static void TestConvertSafeCloneCallback(void); #endif @@ -94,6 +95,7 @@ void addTestConvert(TestNode** root) addTest(root, &TestAlias, "tsconv/ccapitst/TestAlias"); addTest(root, &TestDuplicateAlias, "tsconv/ccapitst/TestDuplicateAlias"); addTest(root, &TestConvertSafeClone, "tsconv/ccapitst/TestConvertSafeClone"); + addTest(root, &TestConvertClone, "tsconv/ccapitst/TestConvertClone"); #if !UCONFIG_NO_LEGACY_CONVERSION addTest(root, &TestConvertSafeCloneCallback,"tsconv/ccapitst/TestConvertSafeCloneCallback"); #endif @@ -1901,6 +1903,138 @@ static void TestConvertSafeClone() } } + +static void TestConvertClone() +{ + /* one 'regular' & all the 'private stateful' converters */ + static const char *const names[] = { +#if !UCONFIG_NO_LEGACY_CONVERSION + "ibm-1047", + "ISO_2022,locale=zh,version=1", +#endif + "SCSU", +#if !UCONFIG_NO_LEGACY_CONVERSION + "HZ", + "lmbcs", + "ISCII,version=0", + "ISO_2022,locale=kr,version=1", + "ISO_2022,locale=jp,version=2", +#endif + "BOCU-1", + "UTF-7", +#if !UCONFIG_NO_LEGACY_CONVERSION + "IMAP-mailbox-name", + "ibm-1047-s390" +#else + "IMAP=mailbox-name" +#endif + }; + + char charBuffer[21]; /* Leave at an odd number for alignment testing */ + UConverter * cnv, *cnv2; + UErrorCode err; + + char *pCharBuffer; + const char *pConstCharBuffer; + const char *charBufferLimit = charBuffer + UPRV_LENGTHOF(charBuffer); + UChar uniBuffer[] = {0x0058, 0x0059, 0x005A}; /* "XYZ" */ + UChar uniCharBuffer[20]; + char charSourceBuffer[] = { 0x1b, 0x24, 0x42 }; + const char *pCharSource = charSourceBuffer; + const char *pCharSourceLimit = charSourceBuffer + sizeof(charSourceBuffer); + UChar *pUCharTarget = uniCharBuffer; + UChar *pUCharTargetLimit = uniCharBuffer + UPRV_LENGTHOF(uniCharBuffer); + const UChar * pUniBuffer; + const UChar *uniBufferLimit = uniBuffer + UPRV_LENGTHOF(uniBuffer); + int32_t idx; + + err = U_ZERO_ERROR; + cnv = ucnv_open(names[0], &err); + if(U_SUCCESS(err)) { + /* Check the various error & informational states: */ + + /* Null status - just returns NULL */ + if (NULL != ucnv_clone(cnv, NULL)) + { + log_err("FAIL: Cloned converter failed to deal correctly with null status\n"); + } + /* error status - should return 0 & keep error the same */ + err = U_MEMORY_ALLOCATION_ERROR; + if (NULL != ucnv_clone(cnv, &err) || err != U_MEMORY_ALLOCATION_ERROR) + { + log_err("FAIL: Cloned converter failed to deal correctly with incoming error status\n"); + } + err = U_ZERO_ERROR; + + /* Null buffer size pointer is ok */ + if (NULL == (cnv2 = ucnv_clone(cnv, &err)) || U_FAILURE(err)) + { + log_err("FAIL: Failed to clone.\n"); + } + ucnv_close(cnv2); + err = U_ZERO_ERROR; + + /* Null converter - return NULL & set U_ILLEGAL_ARGUMENT_ERROR */ + if (NULL != ucnv_clone(NULL, &err) || err != U_ILLEGAL_ARGUMENT_ERROR) + { + log_err("FAIL: Cloned converter failed to deal correctly with null converter pointer\n"); + } + + ucnv_close(cnv); + } + + /* Do these cloned converters work at all - shuffle UChars to chars & back again..*/ + for (idx = 0; idx < UPRV_LENGTHOF(names); idx++) + { + err = U_ZERO_ERROR; + cnv = ucnv_open(names[idx], &err); + if(U_FAILURE(err)) { + log_data_err("ucnv_open(\"%s\") failed - %s\n", names[idx], u_errorName(err)); + continue; + } + + cnv2 = ucnv_clone(cnv, &err); + + /* close the original immediately to make sure that the clone works by itself */ + ucnv_close(cnv); + + pCharBuffer = charBuffer; + pUniBuffer = uniBuffer; + + ucnv_fromUnicode(cnv2, + &pCharBuffer, + charBufferLimit, + &pUniBuffer, + uniBufferLimit, + NULL, + TRUE, + &err); + if(U_FAILURE(err)){ + log_err("FAIL: cloned converter failed to do fromU conversion. Error: %s\n",u_errorName(err)); + } + ucnv_toUnicode(cnv2, + &pUCharTarget, + pUCharTargetLimit, + &pCharSource, + pCharSourceLimit, + NULL, + TRUE, + &err + ); + + if(U_FAILURE(err)){ + log_err("FAIL: cloned converter failed to do toU conversion. Error: %s\n",u_errorName(err)); + } + + pConstCharBuffer = charBuffer; + if (uniBuffer [0] != ucnv_getNextUChar(cnv2, &pConstCharBuffer, pCharBuffer, &err)) + { + log_err("FAIL: Cloned converter failed to do conversion. Error: %s\n",u_errorName(err)); + } + ucnv_close(cnv2); + } +} + static void TestCCSID() { #if !UCONFIG_NO_LEGACY_CONVERSION UConverter *cnv; diff --git a/Build/source/libs/icu/icu-src/source/test/cintltst/cdateintervalformattest.c b/Build/source/libs/icu/icu-src/source/test/cintltst/cdateintervalformattest.c index 513989ac6bb..8f157d2f5d4 100644 --- a/Build/source/libs/icu/icu-src/source/test/cintltst/cdateintervalformattest.c +++ b/Build/source/libs/icu/icu-src/source/test/cintltst/cdateintervalformattest.c @@ -368,23 +368,23 @@ static void TestFormatToResult() { { const char* message = "Field position test 1"; - const UChar* expectedString = u"27. September 2010, 15:00 – 2. März 2011, 18:30"; + const UChar* expectedString = u"27. September 2010 um 15:00 – 2. März 2011 um 18:30"; udtitvfmt_formatToResult(fmt, Date201009270800, Date201103021030, fdi, &ec); assertSuccess("Formatting", &ec); static const UFieldPositionWithCategory expectedFieldPositions[] = { // category, field, begin index, end index - {UFIELD_CATEGORY_DATE_INTERVAL_SPAN, 0, 0, 25}, + {UFIELD_CATEGORY_DATE_INTERVAL_SPAN, 0, 0, 27}, {UFIELD_CATEGORY_DATE, UDAT_DATE_FIELD, 0, 2}, {UFIELD_CATEGORY_DATE, UDAT_MONTH_FIELD, 4, 13}, {UFIELD_CATEGORY_DATE, UDAT_YEAR_FIELD, 14, 18}, - {UFIELD_CATEGORY_DATE, UDAT_HOUR_OF_DAY0_FIELD, 20, 22}, - {UFIELD_CATEGORY_DATE, UDAT_MINUTE_FIELD, 23, 25}, - {UFIELD_CATEGORY_DATE_INTERVAL_SPAN, 1, 28, 47}, - {UFIELD_CATEGORY_DATE, UDAT_DATE_FIELD, 28, 29}, - {UFIELD_CATEGORY_DATE, UDAT_MONTH_FIELD, 31, 35}, - {UFIELD_CATEGORY_DATE, UDAT_YEAR_FIELD, 36, 40}, - {UFIELD_CATEGORY_DATE, UDAT_HOUR_OF_DAY0_FIELD, 42, 44}, - {UFIELD_CATEGORY_DATE, UDAT_MINUTE_FIELD, 45, 47}}; + {UFIELD_CATEGORY_DATE, UDAT_HOUR_OF_DAY0_FIELD, 22, 24}, + {UFIELD_CATEGORY_DATE, UDAT_MINUTE_FIELD, 25, 27}, + {UFIELD_CATEGORY_DATE_INTERVAL_SPAN, 1, 30, 51}, + {UFIELD_CATEGORY_DATE, UDAT_DATE_FIELD, 30, 31}, + {UFIELD_CATEGORY_DATE, UDAT_MONTH_FIELD, 33, 37}, + {UFIELD_CATEGORY_DATE, UDAT_YEAR_FIELD, 38, 42}, + {UFIELD_CATEGORY_DATE, UDAT_HOUR_OF_DAY0_FIELD, 46, 48}, + {UFIELD_CATEGORY_DATE, UDAT_MINUTE_FIELD, 49, 51}}; checkMixedFormattedValue( message, udtitvfmt_resultAsValue(fdi, &ec), @@ -438,23 +438,23 @@ static void TestFormatCalendarToResult() { { const char* message = "Field position test 1"; - const UChar* expectedString = u"27. September 2010, 15:00 – 2. März 2011, 18:30"; + const UChar* expectedString = u"27. September 2010 um 15:00 – 2. März 2011 um 18:30"; udtitvfmt_formatCalendarToResult(fmt, ucal1, ucal2, fdi, &ec); assertSuccess("Formatting", &ec); static const UFieldPositionWithCategory expectedFieldPositions[] = { // category, field, begin index, end index - {UFIELD_CATEGORY_DATE_INTERVAL_SPAN, 0, 0, 25}, + {UFIELD_CATEGORY_DATE_INTERVAL_SPAN, 0, 0, 27}, {UFIELD_CATEGORY_DATE, UDAT_DATE_FIELD, 0, 2}, {UFIELD_CATEGORY_DATE, UDAT_MONTH_FIELD, 4, 13}, {UFIELD_CATEGORY_DATE, UDAT_YEAR_FIELD, 14, 18}, - {UFIELD_CATEGORY_DATE, UDAT_HOUR_OF_DAY0_FIELD, 20, 22}, - {UFIELD_CATEGORY_DATE, UDAT_MINUTE_FIELD, 23, 25}, - {UFIELD_CATEGORY_DATE_INTERVAL_SPAN, 1, 28, 47}, - {UFIELD_CATEGORY_DATE, UDAT_DATE_FIELD, 28, 29}, - {UFIELD_CATEGORY_DATE, UDAT_MONTH_FIELD, 31, 35}, - {UFIELD_CATEGORY_DATE, UDAT_YEAR_FIELD, 36, 40}, - {UFIELD_CATEGORY_DATE, UDAT_HOUR_OF_DAY0_FIELD, 42, 44}, - {UFIELD_CATEGORY_DATE, UDAT_MINUTE_FIELD, 45, 47}}; + {UFIELD_CATEGORY_DATE, UDAT_HOUR_OF_DAY0_FIELD, 22, 24}, + {UFIELD_CATEGORY_DATE, UDAT_MINUTE_FIELD, 25, 27}, + {UFIELD_CATEGORY_DATE_INTERVAL_SPAN, 1, 30, 51}, + {UFIELD_CATEGORY_DATE, UDAT_DATE_FIELD, 30, 31}, + {UFIELD_CATEGORY_DATE, UDAT_MONTH_FIELD, 33, 37}, + {UFIELD_CATEGORY_DATE, UDAT_YEAR_FIELD, 38, 42}, + {UFIELD_CATEGORY_DATE, UDAT_HOUR_OF_DAY0_FIELD, 46, 48}, + {UFIELD_CATEGORY_DATE, UDAT_MINUTE_FIELD, 49, 51}}; checkMixedFormattedValue( message, udtitvfmt_resultAsValue(fdi, &ec), @@ -493,23 +493,23 @@ static void TestFormatCalendarToResult() { ucal_setMillis(ucal5, Date158210160000, &ec); // 1 2 3 4 // 012345678901234567890123456789012345678901234567890 - const UChar* expectedString = u"4. Oktober 1582, 00:00 – 16. Oktober 1582, 00:00"; + const UChar* expectedString = u"4. Oktober 1582 um 00:00 – 16. Oktober 1582 um 00:00"; udtitvfmt_formatCalendarToResult(fmt, ucal4, ucal5, fdi, &ec); assertSuccess("Formatting", &ec); static const UFieldPositionWithCategory expectedFieldPositions[] = { // category, field, begin index, end index - {UFIELD_CATEGORY_DATE_INTERVAL_SPAN, 0, 0, 22}, + {UFIELD_CATEGORY_DATE_INTERVAL_SPAN, 0, 0, 24}, {UFIELD_CATEGORY_DATE, UDAT_DATE_FIELD, 0, 1}, {UFIELD_CATEGORY_DATE, UDAT_MONTH_FIELD, 3, 10}, {UFIELD_CATEGORY_DATE, UDAT_YEAR_FIELD, 11, 15}, - {UFIELD_CATEGORY_DATE, UDAT_HOUR_OF_DAY0_FIELD, 17, 19}, - {UFIELD_CATEGORY_DATE, UDAT_MINUTE_FIELD, 20, 22}, - {UFIELD_CATEGORY_DATE_INTERVAL_SPAN, 1, 25, 48}, - {UFIELD_CATEGORY_DATE, UDAT_DATE_FIELD, 25, 27}, - {UFIELD_CATEGORY_DATE, UDAT_MONTH_FIELD, 29, 36}, - {UFIELD_CATEGORY_DATE, UDAT_YEAR_FIELD, 37, 41}, - {UFIELD_CATEGORY_DATE, UDAT_HOUR_OF_DAY0_FIELD, 43, 45}, - {UFIELD_CATEGORY_DATE, UDAT_MINUTE_FIELD, 46, 48}}; + {UFIELD_CATEGORY_DATE, UDAT_HOUR_OF_DAY0_FIELD, 19, 21}, + {UFIELD_CATEGORY_DATE, UDAT_MINUTE_FIELD, 22, 24}, + {UFIELD_CATEGORY_DATE_INTERVAL_SPAN, 1, 27, 52}, + {UFIELD_CATEGORY_DATE, UDAT_DATE_FIELD, 27, 29}, + {UFIELD_CATEGORY_DATE, UDAT_MONTH_FIELD, 31, 38}, + {UFIELD_CATEGORY_DATE, UDAT_YEAR_FIELD, 39, 43}, + {UFIELD_CATEGORY_DATE, UDAT_HOUR_OF_DAY0_FIELD, 47, 49}, + {UFIELD_CATEGORY_DATE, UDAT_MINUTE_FIELD, 50, 52}}; checkMixedFormattedValue( message, udtitvfmt_resultAsValue(fdi, &ec), @@ -527,23 +527,23 @@ static void TestFormatCalendarToResult() { const char* message = "Field position test 4"; // 1 2 3 4 // 012345678901234567890123456789012345678901234567890 - const UChar* expectedString = u"14. Oktober 1582, 00:00 – 16. Oktober 1582, 00:00"; + const UChar* expectedString = u"14. Oktober 1582 um 00:00 – 16. Oktober 1582 um 00:00"; udtitvfmt_formatCalendarToResult(fmt, ucal4, ucal5, fdi, &ec); assertSuccess("Formatting", &ec); static const UFieldPositionWithCategory expectedFieldPositions[] = { // category, field, begin index, end index - {UFIELD_CATEGORY_DATE_INTERVAL_SPAN, 0, 0, 23}, + {UFIELD_CATEGORY_DATE_INTERVAL_SPAN, 0, 0, 25}, {UFIELD_CATEGORY_DATE, UDAT_DATE_FIELD, 0, 2}, {UFIELD_CATEGORY_DATE, UDAT_MONTH_FIELD, 4, 11}, {UFIELD_CATEGORY_DATE, UDAT_YEAR_FIELD, 12, 16}, - {UFIELD_CATEGORY_DATE, UDAT_HOUR_OF_DAY0_FIELD, 18, 20}, - {UFIELD_CATEGORY_DATE, UDAT_MINUTE_FIELD, 21, 23}, - {UFIELD_CATEGORY_DATE_INTERVAL_SPAN, 1, 26, 49}, - {UFIELD_CATEGORY_DATE, UDAT_DATE_FIELD, 26, 28}, - {UFIELD_CATEGORY_DATE, UDAT_MONTH_FIELD, 30, 37}, - {UFIELD_CATEGORY_DATE, UDAT_YEAR_FIELD, 38, 42}, - {UFIELD_CATEGORY_DATE, UDAT_HOUR_OF_DAY0_FIELD, 44, 46}, - {UFIELD_CATEGORY_DATE, UDAT_MINUTE_FIELD, 47, 49}}; + {UFIELD_CATEGORY_DATE, UDAT_HOUR_OF_DAY0_FIELD, 20, 22}, + {UFIELD_CATEGORY_DATE, UDAT_MINUTE_FIELD, 23, 25}, + {UFIELD_CATEGORY_DATE_INTERVAL_SPAN, 1, 28, 53}, + {UFIELD_CATEGORY_DATE, UDAT_DATE_FIELD, 28, 30}, + {UFIELD_CATEGORY_DATE, UDAT_MONTH_FIELD, 32, 39}, + {UFIELD_CATEGORY_DATE, UDAT_YEAR_FIELD, 40, 44}, + {UFIELD_CATEGORY_DATE, UDAT_HOUR_OF_DAY0_FIELD, 48, 50}, + {UFIELD_CATEGORY_DATE, UDAT_MINUTE_FIELD, 51, 53}}; checkMixedFormattedValue( message, udtitvfmt_resultAsValue(fdi, &ec), diff --git a/Build/source/libs/icu/icu-src/source/test/cintltst/cdattst.c b/Build/source/libs/icu/icu-src/source/test/cintltst/cdattst.c index 00b2d6a01a1..2c5d51c64b2 100644 --- a/Build/source/libs/icu/icu-src/source/test/cintltst/cdattst.c +++ b/Build/source/libs/icu/icu-src/source/test/cintltst/cdattst.c @@ -45,6 +45,7 @@ static void TestFormatForFields(void); static void TestForceGannenNumbering(void); static void TestMapDateToCalFields(void); static void TestNarrowQuarters(void); +static void TestExtraneousCharacters(void); void addDateForTest(TestNode** root); @@ -67,6 +68,7 @@ void addDateForTest(TestNode** root) TESTCASE(TestForceGannenNumbering); TESTCASE(TestMapDateToCalFields); TESTCASE(TestNarrowQuarters); + TESTCASE(TestExtraneousCharacters); } /* Testing the DateFormat API */ static void TestDateFormat() @@ -2017,4 +2019,24 @@ static void TestNarrowQuarters(void) { } } +static void TestExtraneousCharacters(void) { + // regression test for ICU-21802 + UErrorCode err = U_ZERO_ERROR; + UCalendar* cal = ucal_open(u"UTC", -1, "en_US", UCAL_GREGORIAN, &err); + UDateFormat* df = udat_open(UDAT_PATTERN, UDAT_PATTERN, "en_US", u"UTC", -1, u"yyyyMMdd", -1, &err); + + if (assertSuccess("Failed to create date formatter and calendar", &err)) { + udat_setLenient(df, false); + + udat_parseCalendar(df, cal, u"2021", -1, NULL, &err); + assertTrue("Success parsing '2021'", err == U_PARSE_ERROR); + + err = U_ZERO_ERROR; + udat_parseCalendar(df, cal, u"2021-", -1, NULL, &err); + assertTrue("Success parsing '2021-'", err == U_PARSE_ERROR); + } + udat_close(df); + ucal_close(cal); +} + #endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/Build/source/libs/icu/icu-src/source/test/cintltst/cldrtest.c b/Build/source/libs/icu/icu-src/source/test/cintltst/cldrtest.c index 7767cf9f097..f83a6f142d8 100644 --- a/Build/source/libs/icu/icu-src/source/test/cintltst/cldrtest.c +++ b/Build/source/libs/icu/icu-src/source/test/cintltst/cldrtest.c @@ -1002,6 +1002,10 @@ static void VerifyTranslation(void) { log_knownIssue("cldrbug:14995", "mai/sd_Deva day names use chars not in exemplars")) { end = 0; } + if (uprv_strncmp(currLoc,"ks_Deva",7) == 0 && + log_knownIssue("cldrbug:15355", "ks_Deva day names use chars not in exemplars")) { + end = 0; + } for (idx = 0; idx < end; idx++) { const UChar *fromBundleStr = ures_getStringByIndex(resArray, idx, &langSize, &errorCode); @@ -1035,6 +1039,10 @@ static void VerifyTranslation(void) { log_knownIssue("cldrbug:14995", "sd_Deva month names use chars not in exemplars")) { end = 0; } + if (uprv_strncmp(currLoc,"ks_Deva",7) == 0 && + log_knownIssue("cldrbug:15355", "ks_Deva month names use chars not in exemplars")) { + end = 0; + } for (idx = 0; idx < end; idx++) { const UChar *fromBundleStr = ures_getStringByIndex(resArray, idx, &langSize, &errorCode); diff --git a/Build/source/libs/icu/icu-src/source/test/cintltst/cloctst.c b/Build/source/libs/icu/icu-src/source/test/cintltst/cloctst.c index 8707babbbee..606e0a2794b 100644 --- a/Build/source/libs/icu/icu-src/source/test/cintltst/cloctst.c +++ b/Build/source/libs/icu/icu-src/source/test/cintltst/cloctst.c @@ -1552,18 +1552,18 @@ static void TestSimpleDisplayNames() static void TestUninstalledISO3Names() { /* This test checks to make sure getISO3Language and getISO3Country work right - even for locales that are not installed. */ + even for locales that are not installed (and some installed ones). */ static const char iso2Languages [][4] = { "am", "ba", "fy", "mr", "rn", - "ss", "tw", "zu" }; + "ss", "tw", "zu", "sr" }; static const char iso3Languages [][5] = { "amh", "bak", "fry", "mar", "run", - "ssw", "twi", "zul" }; + "ssw", "twi", "zul", "srp" }; static const char iso2Countries [][6] = { "am_AF", "ba_BW", "fy_KZ", "mr_MO", "rn_MN", - "ss_SB", "tw_TC", "zu_ZW" }; + "ss_SB", "tw_TC", "zu_ZW", "sr_XK" }; static const char iso3Countries [][4] = { "AFG", "BWA", "KAZ", "MAC", "MNG", - "SLB", "TCA", "ZWE" }; + "SLB", "TCA", "ZWE", "XKK" }; int32_t i; - for (i = 0; i < 8; i++) { + for (i = 0; i < 9; i++) { UErrorCode err = U_ZERO_ERROR; const char *test; test = uloc_getISO3Language(iso2Languages[i]); @@ -1571,7 +1571,7 @@ static void TestUninstalledISO3Names() log_err("Got wrong ISO3 code for %s : Expected \"%s\", got \"%s\". %s\n", iso2Languages[i], iso3Languages[i], test, myErrorName(err)); } - for (i = 0; i < 8; i++) { + for (i = 0; i < 9; i++) { UErrorCode err = U_ZERO_ERROR; const char *test; test = uloc_getISO3Country(iso2Countries[i]); @@ -3207,6 +3207,18 @@ static void TestAcceptLanguage(void) { } } } + + // API coverage + status = U_ZERO_ERROR; + static const char *const supported[] = { "en-US", "en-GB", "de-DE", "ja-JP" }; + const char * desired[] = { "de-LI", "en-IN", "zu", "fr" }; + available = uenum_openCharStringsEnumeration(supported, UPRV_LENGTHOF(supported), &status); + tmp[0]=0; + rc = uloc_acceptLanguage(tmp, 199, &outResult, desired, UPRV_LENGTHOF(desired), available, &status); + if (U_FAILURE(status) || rc != 5 || uprv_strcmp(tmp, "de_DE") != 0 || outResult == ULOC_ACCEPT_FAILED) { + log_err("uloc_acceptLanguage() failed to do a simple match\n"); + } + uenum_close(available); } static const char* LOCALE_ALIAS[][2] = { @@ -7053,6 +7065,14 @@ static void TestUldnNameVariants() { u_errorName(status) ); continue; } + // API coverage: Expect to get back the dialect handling which is + // the first item in the displayOptions test data. + UDialectHandling dh = uldn_getDialectHandling(uldn); + UDisplayContext dhContext = (UDisplayContext)dh; // same numeric values + if (dhContext != uloPtr->displayOptions[0]) { + log_err("uldn_getDialectHandling()=%03X != expected UDisplayContext %03X\n", + dhContext, uloPtr->displayOptions[0]); + } const UldnItem * itemPtr = uloPtr->testItems; int32_t itemCount = uloPtr->countItems; for (; itemCount-- > 0; itemPtr++) { diff --git a/Build/source/libs/icu/icu-src/source/test/cintltst/cnormtst.c b/Build/source/libs/icu/icu-src/source/test/cintltst/cnormtst.c index c16f8a62846..c7830073b23 100644 --- a/Build/source/libs/icu/icu-src/source/test/cintltst/cnormtst.c +++ b/Build/source/libs/icu/icu-src/source/test/cintltst/cnormtst.c @@ -65,6 +65,7 @@ TestGetRawDecomposition(void); static void TestAppendRestoreMiddle(void); static void TestGetEasyToUseInstance(void); +static void TestAPICoverage(void); static const char* const canonTests[][3] = { /* Input*/ /*Decomposed*/ /*Composed*/ @@ -156,6 +157,7 @@ void addNormTest(TestNode** root) addTest(root, &TestGetRawDecomposition, "tsnorm/cnormtst/TestGetRawDecomposition"); addTest(root, &TestAppendRestoreMiddle, "tsnorm/cnormtst/TestAppendRestoreMiddle"); addTest(root, &TestGetEasyToUseInstance, "tsnorm/cnormtst/TestGetEasyToUseInstance"); + addTest(root, &TestAPICoverage, "tsnorm/cnormtst/TestAPICoverage"); } static const char* const modeStrings[]={ @@ -1698,4 +1700,55 @@ TestGetEasyToUseInstance() { } } +static void +TestAPICoverage() { + UErrorCode errorCode = U_ZERO_ERROR; + const UNormalizer2 *n2 = unorm2_getNFDInstance(&errorCode); + if (U_FAILURE(errorCode)) { + log_err_status(errorCode, "unorm2_getNFDInstance() failed: %s\n", u_errorName(errorCode)); + return; + } + + if (!unorm2_hasBoundaryBefore(n2, u'C') || unorm2_hasBoundaryBefore(n2, 0x300)) { + log_err("unorm2_hasBoundaryBefore() returns unexpected results\n"); + } + + if (!unorm2_hasBoundaryAfter(n2, u'C') || unorm2_hasBoundaryAfter(n2, 0x300)) { + log_err("unorm2_hasBoundaryAfter() returns unexpected results\n"); + } + + if (!unorm2_isInert(n2, 0x50005) || unorm2_isInert(n2, 0x300)) { + log_err("unorm2_isInert() returns unexpected results\n"); + } + + errorCode = U_ZERO_ERROR; + if (!unorm2_isNormalized(n2, u"c\u0327\u0300", 3, &errorCode) || + unorm2_isNormalized(n2, u"c\u0300\u0327", 3, &errorCode) || + U_FAILURE(errorCode)) { + log_err("unorm2_isNormalized() returns unexpected results\n"); + } + + errorCode = U_ZERO_ERROR; + if (unorm2_quickCheck(n2, u"c\u0327\u0300", 3, &errorCode) == UNORM_NO || + unorm2_quickCheck(n2, u"c\u0300\u0327", 3, &errorCode) == UNORM_YES || + U_FAILURE(errorCode)) { + log_err("unorm2_quickCheck() returns unexpected results\n"); + } + + errorCode = U_ZERO_ERROR; + if (unorm2_spanQuickCheckYes(n2, u"c\u0327\u0300", 3, &errorCode) != 3 || + unorm2_spanQuickCheckYes(n2, u"c\u0300\u0327", 3, &errorCode) != 1 || + U_FAILURE(errorCode)) { + log_err("unorm2_spanQuickCheckYes() returns unexpected results\n"); + } + + errorCode = U_ZERO_ERROR; + UChar first[10] = { u'c', 0x300, 0, 0, 0, 0, 0, 0, 0, 0 }; + int32_t length = unorm2_normalizeSecondAndAppend( + n2, first, 2, UPRV_LENGTHOF(first), u"\u0327d", 2, &errorCode); + if (U_FAILURE(errorCode) || length != 4 || u_strcmp(first, u"c\u0327\u0300d") != 0) { + log_err("unorm2_normalizeSecondAndAppend() returns unexpected results\n"); + } +} + #endif /* #if !UCONFIG_NO_NORMALIZATION */ diff --git a/Build/source/libs/icu/icu-src/source/test/cintltst/creststn.c b/Build/source/libs/icu/icu-src/source/test/cintltst/creststn.c index f8c50cb1a82..c61f063a950 100644 --- a/Build/source/libs/icu/icu-src/source/test/cintltst/creststn.c +++ b/Build/source/libs/icu/icu-src/source/test/cintltst/creststn.c @@ -2180,7 +2180,7 @@ static void TestFallback() UResourceBundle* myResB = ures_open(NULL,"no_NO_NY",&err); UResourceBundle* resLocID = ures_getByKey(myResB, "Version", NULL, &err); const UChar* version = NULL; - static const UChar versionStr[] = u"40"; // 40 in nn_NO or in a parent bundle/root + static const UChar versionStr[] = u"41"; // 41 in nn_NO or in a parent bundle/root if(U_FAILURE(err)) { log_data_err("Expected success when trying to test no_NO_NY aliased to nn_NO for Version " diff --git a/Build/source/libs/icu/icu-src/source/test/cintltst/ucsdetst.c b/Build/source/libs/icu/icu-src/source/test/cintltst/ucsdetst.c index f65f8d79aa4..b8d3b5f20b8 100644 --- a/Build/source/libs/icu/icu-src/source/test/cintltst/ucsdetst.c +++ b/Build/source/libs/icu/icu-src/source/test/cintltst/ucsdetst.c @@ -402,6 +402,7 @@ static void TestBufferOverflow(void) { } for (idx = 0; idx < UPRV_LENGTHOF(testStrings); idx++) { + status = U_ZERO_ERROR; ucsdet_setText(csd, testStrings[idx], -1, &status); match = ucsdet_detect(csd, &status); diff --git a/Build/source/libs/icu/icu-src/source/test/cintltst/udatpg_test.c b/Build/source/libs/icu/icu-src/source/test/cintltst/udatpg_test.c index 5f15577b264..66cfb41d47f 100644 --- a/Build/source/libs/icu/icu-src/source/test/cintltst/udatpg_test.c +++ b/Build/source/libs/icu/icu-src/source/test/cintltst/udatpg_test.c @@ -46,6 +46,7 @@ static void TestGetFieldDisplayNames(void); static void TestGetDefaultHourCycle(void); static void TestGetDefaultHourCycleOnEmptyInstance(void); static void TestEras(void); +static void TestDateTimePatterns(void); void addDateTimePatternGeneratorTest(TestNode** root) { TESTCASE(TestOpenClose); @@ -56,6 +57,7 @@ void addDateTimePatternGeneratorTest(TestNode** root) { TESTCASE(TestGetDefaultHourCycle); TESTCASE(TestGetDefaultHourCycleOnEmptyInstance); TESTCASE(TestEras); + TESTCASE(TestDateTimePatterns); } /* @@ -614,4 +616,178 @@ static void TestEras(void) { } } +enum { kNumDateTimePatterns = 4 }; + +typedef struct { + const char* localeID; + const UChar* expectPat[kNumDateTimePatterns]; +} DTPLocaleAndResults; + +static void doDTPatternTest(UDateTimePatternGenerator* udtpg, + const UChar** skeletons, + DTPLocaleAndResults* localeAndResultsPtr); + +static void TestDateTimePatterns(void) { + const UChar* skeletons[kNumDateTimePatterns] = { + u"yMMMMEEEEdjmm", // full date, short time + u"yMMMMdjmm", // long date, short time + u"yMMMdjmm", // medium date, short time + u"yMdjmm" // short date, short time + }; + // The following tests some locales in which there are differences between the + // DateTimePatterns of various length styles. + DTPLocaleAndResults localeAndResults[] = { + { "en", { u"EEEE, MMMM d, y 'at' h:mm a", // long != medium + u"MMMM d, y 'at' h:mm a", + u"MMM d, y, h:mm a", + u"M/d/y, h:mm a" } }, + { "fr", { u"EEEE d MMMM y 'à' HH:mm", // medium != short + u"d MMMM y 'à' HH:mm", + u"d MMM y, HH:mm", + u"dd/MM/y HH:mm" } }, + { "ha", { u"EEEE d MMMM, y HH:mm", // full != long + u"d MMMM, y 'da' HH:mm", + u"d MMM, y, HH:mm", + u"y-MM-dd, HH:mm" } }, + { NULL, { NULL, NULL, NULL, NULL } } // terminator + }; + + const UChar* enDTPatterns[kNumDateTimePatterns] = { + u"{1} 'at' {0}", + u"{1} 'at' {0}", + u"{1}, {0}", + u"{1}, {0}" + }; + const UChar* modDTPatterns[kNumDateTimePatterns] = { + u"{1} _0_ {0}", + u"{1} _1_ {0}", + u"{1} _2_ {0}", + u"{1} _3_ {0}" + }; + DTPLocaleAndResults enModResults = { "en", { u"EEEE, MMMM d, y _0_ h:mm a", + u"MMMM d, y _1_ h:mm a", + u"MMM d, y _2_ h:mm a", + u"M/d/y _3_ h:mm a" } + }; + + // Test various locales with standard data + UErrorCode status; + UDateTimePatternGenerator* udtpg; + DTPLocaleAndResults* localeAndResultsPtr = localeAndResults; + for (; localeAndResultsPtr->localeID != NULL; localeAndResultsPtr++) { + status = U_ZERO_ERROR; + udtpg = udatpg_open(localeAndResultsPtr->localeID, &status); + if (U_FAILURE(status)) { + log_data_err("FAIL: udatpg_open for locale %s: %s", localeAndResultsPtr->localeID, myErrorName(status)); + } else { + doDTPatternTest(udtpg, skeletons, localeAndResultsPtr); + udatpg_close(udtpg); + } + } + // Test getting and modifying date-time combining patterns + status = U_ZERO_ERROR; + udtpg = udatpg_open("en", &status); + if (U_FAILURE(status)) { + log_data_err("FAIL: udatpg_open #2 for locale en: %s", myErrorName(status)); + } else { + char bExpect[64]; + char bGet[64]; + const UChar* uGet; + int32_t uGetLen, uExpectLen; + + // Test error: style out of range + status = U_ZERO_ERROR; + uGet = udatpg_getDateTimeFormatForStyle(udtpg, UDAT_NONE, &uGetLen, &status); + if (status != U_ILLEGAL_ARGUMENT_ERROR || uGetLen != 0 || uGet==NULL || *uGet!= 0) { + if (uGet==NULL) { + log_err("FAIL: udatpg_getDateTimeFormatForStyle with invalid style, expected U_ILLEGAL_ARGUMENT_ERROR " + "and ptr to empty string but got %s, len %d, ptr = NULL\n", myErrorName(status), uGetLen); + } else { + log_err("FAIL: udatpg_getDateTimeFormatForStyle with invalid style, expected U_ILLEGAL_ARGUMENT_ERROR " + "and ptr to empty string but got %s, len %d, *ptr = %04X\n", myErrorName(status), uGetLen, *uGet); + } + } + + // Test normal getting and setting + for (int32_t patStyle = 0; patStyle < kNumDateTimePatterns; patStyle++) { + status = U_ZERO_ERROR; + uExpectLen = u_strlen(enDTPatterns[patStyle]); + uGet = udatpg_getDateTimeFormatForStyle(udtpg, patStyle, &uGetLen, &status); + if (U_FAILURE(status)) { + log_err("FAIL udatpg_getDateTimeFormatForStyle %d (en before mod), get %s\n", patStyle, myErrorName(status)); + } else if (uGetLen != uExpectLen || u_strncmp(uGet, enDTPatterns[patStyle], uExpectLen) != 0) { + u_austrcpy(bExpect, enDTPatterns[patStyle]); + u_austrcpy(bGet, uGet); + log_err("ERROR udatpg_getDateTimeFormatForStyle %d (en before mod), expect %d:\"%s\", get %d:\"%s\"\n", + patStyle, uExpectLen, bExpect, uGetLen, bGet); + } + status = U_ZERO_ERROR; + udatpg_setDateTimeFormatForStyle(udtpg, patStyle, modDTPatterns[patStyle], -1, &status); + if (U_FAILURE(status)) { + log_err("FAIL udatpg_setDateTimeFormatForStyle %d (en), get %s\n", patStyle, myErrorName(status)); + } else { + uExpectLen = u_strlen(modDTPatterns[patStyle]); + uGet = udatpg_getDateTimeFormatForStyle(udtpg, patStyle, &uGetLen, &status); + if (U_FAILURE(status)) { + log_err("FAIL udatpg_getDateTimeFormatForStyle %d (en after mod), get %s\n", patStyle, myErrorName(status)); + } else if (uGetLen != uExpectLen || u_strncmp(uGet, modDTPatterns[patStyle], uExpectLen) != 0) { + u_austrcpy(bExpect, modDTPatterns[patStyle]); + u_austrcpy(bGet, uGet); + log_err("ERROR udatpg_getDateTimeFormatForStyle %d (en after mod), expect %d:\"%s\", get %d:\"%s\"\n", + patStyle, uExpectLen, bExpect, uGetLen, bGet); + } + } + } + // Test result of setting + doDTPatternTest(udtpg, skeletons, &enModResults); + // Test old get/set functions + uExpectLen = u_strlen(modDTPatterns[UDAT_MEDIUM]); + uGet = udatpg_getDateTimeFormat(udtpg, &uGetLen); + if (uGetLen != uExpectLen || u_strncmp(uGet, modDTPatterns[UDAT_MEDIUM], uExpectLen) != 0) { + u_austrcpy(bExpect, modDTPatterns[UDAT_MEDIUM]); + u_austrcpy(bGet, uGet); + log_err("ERROR udatpg_getDateTimeFormat (en after mod), expect %d:\"%s\", get %d:\"%s\"\n", + uExpectLen, bExpect, uGetLen, bGet); + } + udatpg_setDateTimeFormat(udtpg, modDTPatterns[UDAT_SHORT], -1); // set all dateTimePatterns to the short format + uExpectLen = u_strlen(modDTPatterns[UDAT_SHORT]); + u_austrcpy(bExpect, modDTPatterns[UDAT_SHORT]); + for (int32_t patStyle = 0; patStyle < kNumDateTimePatterns; patStyle++) { + status = U_ZERO_ERROR; + uGet = udatpg_getDateTimeFormatForStyle(udtpg, patStyle, &uGetLen, &status); + if (U_FAILURE(status)) { + log_err("FAIL udatpg_getDateTimeFormatForStyle %d (en after second mod), get %s\n", patStyle, myErrorName(status)); + } else if (uGetLen != uExpectLen || u_strncmp(uGet, modDTPatterns[UDAT_SHORT], uExpectLen) != 0) { + u_austrcpy(bGet, uGet); + log_err("ERROR udatpg_getDateTimeFormatForStyle %d (en after second mod), expect %d:\"%s\", get %d:\"%s\"\n", + patStyle, uExpectLen, bExpect, uGetLen, bGet); + } + } + + udatpg_close(udtpg); + } +} + +static void doDTPatternTest(UDateTimePatternGenerator* udtpg, + const UChar** skeletons, + DTPLocaleAndResults* localeAndResultsPtr) { + for (int32_t patStyle = 0; patStyle < kNumDateTimePatterns; patStyle++) { + UChar uGet[64]; + int32_t uGetLen, uExpectLen; + UErrorCode status = U_ZERO_ERROR; + uExpectLen = u_strlen(localeAndResultsPtr->expectPat[patStyle]); + uGetLen = udatpg_getBestPattern(udtpg, skeletons[patStyle], -1, uGet, 64, &status); + if (U_FAILURE(status)) { + log_err("FAIL udatpg_getBestPattern locale %s style %d: %s\n", localeAndResultsPtr->localeID, patStyle, myErrorName(status)); + } else if (uGetLen != uExpectLen || u_strncmp(uGet, localeAndResultsPtr->expectPat[patStyle], uExpectLen) != 0) { + char bExpect[64]; + char bGet[64]; + u_austrcpy(bExpect, localeAndResultsPtr->expectPat[patStyle]); + u_austrcpy(bGet, uGet); + log_err("ERROR udatpg_getBestPattern locale %s style %d, expect %d:\"%s\", get %d:\"%s\"\n", + localeAndResultsPtr->localeID, patStyle, uExpectLen, bExpect, uGetLen, bGet); + } + } +} + #endif diff --git a/Build/source/libs/icu/icu-src/source/test/cintltst/ulistfmttest.c b/Build/source/libs/icu/icu-src/source/test/cintltst/ulistfmttest.c index 7fe549f43ba..b0a1f6bc349 100644 --- a/Build/source/libs/icu/icu-src/source/test/cintltst/ulistfmttest.c +++ b/Build/source/libs/icu/icu-src/source/test/cintltst/ulistfmttest.c @@ -20,6 +20,8 @@ static void TestUListFmt(void); static void TestUListFmtToValue(void); static void TestUListOpenStyled(void); +static void TestUList21871_A(void); +static void TestUList21871_B(void); void addUListFmtTest(TestNode** root); @@ -30,6 +32,8 @@ void addUListFmtTest(TestNode** root) TESTCASE(TestUListFmt); TESTCASE(TestUListFmtToValue); TESTCASE(TestUListOpenStyled); + TESTCASE(TestUList21871_A); + TESTCASE(TestUList21871_B); } static const UChar str0[] = { 0x41,0 }; /* "A" */ @@ -250,5 +254,103 @@ static void TestUListOpenStyled() { ulistfmt_closeResult(fl); } +#include <stdio.h> + +static void TestUList21871_A() { + UErrorCode status = U_ZERO_ERROR; + UListFormatter *fmt = ulistfmt_openForType("en", ULISTFMT_TYPE_AND, ULISTFMT_WIDTH_WIDE, &status); + assertSuccess("ulistfmt_openForType", &status); + + const UChar *strs[] = {u"A", u""}; + const int32_t lens[] = {1, 0}; + + UFormattedList *fl = ulistfmt_openResult(&status); + assertSuccess("ulistfmt_openResult", &status); + + ulistfmt_formatStringsToResult(fmt, strs, lens, 2, fl, &status); + assertSuccess("ulistfmt_formatStringsToResult", &status); + + const UFormattedValue *value = ulistfmt_resultAsValue(fl, &status); + assertSuccess("ulistfmt_resultAsValue", &status); + + { + int32_t len; + const UChar *str = ufmtval_getString(value, &len, &status); + assertUEquals("TEST ufmtval_getString", u"A and ", str); + } + + UConstrainedFieldPosition *fpos = ucfpos_open(&status); + assertSuccess("ucfpos_open", &status); + + ucfpos_constrainField(fpos, UFIELD_CATEGORY_LIST, ULISTFMT_ELEMENT_FIELD, &status); + assertSuccess("ucfpos_constrainField", &status); + + bool hasMore = ufmtval_nextPosition(value, fpos, &status); + assertSuccess("ufmtval_nextPosition", &status); + assertTrue("hasMore 1", hasMore); + + int32_t beginIndex, endIndex; + ucfpos_getIndexes(fpos, &beginIndex, &endIndex, &status); + assertSuccess("ufmtval_nextPosition", &status); + assertIntEquals("TEST beginIndex", 0, beginIndex); + assertIntEquals("TEST endIndex", 1, endIndex); + + hasMore = ufmtval_nextPosition(value, fpos, &status); + assertSuccess("ufmtval_nextPosition", &status); + assertTrue("hasMore 2", !hasMore); + + ucfpos_close(fpos); + ulistfmt_closeResult(fl); + ulistfmt_close(fmt); +} + +static void TestUList21871_B() { + UErrorCode status = U_ZERO_ERROR; + UListFormatter *fmt = ulistfmt_openForType("en", ULISTFMT_TYPE_AND, ULISTFMT_WIDTH_WIDE, &status); + assertSuccess("ulistfmt_openForType", &status); + + const UChar *strs[] = {u"", u"B"}; + const int32_t lens[] = {0, 1}; + + UFormattedList *fl = ulistfmt_openResult(&status); + assertSuccess("ulistfmt_openResult", &status); + + ulistfmt_formatStringsToResult(fmt, strs, lens, 2, fl, &status); + assertSuccess("ulistfmt_formatStringsToResult", &status); + + const UFormattedValue *value = ulistfmt_resultAsValue(fl, &status); + assertSuccess("ulistfmt_resultAsValue", &status); + + { + int32_t len; + const UChar *str = ufmtval_getString(value, &len, &status); + assertUEquals("TEST ufmtval_getString", u" and B", str); + } + + UConstrainedFieldPosition *fpos = ucfpos_open(&status); + assertSuccess("ucfpos_open", &status); + + ucfpos_constrainField(fpos, UFIELD_CATEGORY_LIST, ULISTFMT_ELEMENT_FIELD, &status); + assertSuccess("ucfpos_constrainField", &status); + + bool hasMore = ufmtval_nextPosition(value, fpos, &status); + assertSuccess("ufmtval_nextPosition", &status); + assertTrue("hasMore 1", hasMore); + + int32_t beginIndex, endIndex; + ucfpos_getIndexes(fpos, &beginIndex, &endIndex, &status); + assertSuccess("ucfpos_getIndexes", &status); + assertIntEquals("TEST beginIndex", 5, beginIndex); + assertIntEquals("TEST endIndex", 6, endIndex); + + hasMore = ufmtval_nextPosition(value, fpos, &status); + assertSuccess("ufmtval_nextPosition", &status); + assertTrue("hasMore 2", !hasMore); + + ucfpos_close(fpos); + ulistfmt_closeResult(fl); + ulistfmt_close(fmt); +} + #endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/Build/source/libs/icu/icu-src/source/test/cintltst/utexttst.c b/Build/source/libs/icu/icu-src/source/test/cintltst/utexttst.c index 8f3974c9041..6ee85c7057d 100644 --- a/Build/source/libs/icu/icu-src/source/test/cintltst/utexttst.c +++ b/Build/source/libs/icu/icu-src/source/test/cintltst/utexttst.c @@ -292,6 +292,22 @@ static void TestAPI(void) { utext_close(uta); } - + { + // utext_equals() checks for the same type of text provider, + // same string pointer(!), and same index. + status = U_ZERO_ERROR; + const UChar *s = u"aßカ🚲"; + UText *ut1 = utext_openUChars(NULL, s, -1, &status); + UText *ut2 = utext_openUChars(NULL, s, 5, &status); + TEST_SUCCESS(status); + TEST_ASSERT(utext_equals(ut1, ut2)); + UChar32 c = utext_next32(ut1); + TEST_ASSERT(c == u'a'); + TEST_ASSERT(!utext_equals(ut1, ut2)); // indexes out of sync + c = utext_next32(ut2); + TEST_ASSERT(c == u'a'); + TEST_ASSERT(utext_equals(ut1, ut2)); // back in sync + utext_close(ut1); + utext_close(ut2); + } } - diff --git a/Build/source/libs/icu/icu-src/source/test/depstest/dependencies.txt b/Build/source/libs/icu/icu-src/source/test/depstest/dependencies.txt index d15fbe0b399..4653afc1c3f 100644 --- a/Build/source/libs/icu/icu-src/source/test/depstest/dependencies.txt +++ b/Build/source/libs/icu/icu-src/source/test/depstest/dependencies.txt @@ -224,6 +224,7 @@ group: breakiterator normlzr # for dictbe.o, should switch to Normalizer2 uvector32 # for dictbe.o exp_and_tanhf # for lstmbe.o + usetiter # for dictbe.o group: unormcmp # unorm_compare() unormcmp.o diff --git a/Build/source/libs/icu/icu-src/source/test/intltest/csdetest.cpp b/Build/source/libs/icu/icu-src/source/test/intltest/csdetest.cpp index 66f9340b83a..95f19d43d1a 100644 --- a/Build/source/libs/icu/icu-src/source/test/intltest/csdetest.cpp +++ b/Build/source/libs/icu/icu-src/source/test/intltest/csdetest.cpp @@ -109,6 +109,10 @@ void CharsetDetectionTest::runIndexedTest( int32_t index, UBool exec, const char if (exec) Ticket6954Test(); break; + case 10: name = "Ticket21823Test"; + if (exec) Ticket21823Test(); + break; + default: name = ""; break; //needed to end loop } @@ -839,3 +843,22 @@ void CharsetDetectionTest::Ticket6954Test() { TEST_ASSERT(strcmp(name1, "windows-1252")==0); #endif } + + +// Ticket 21823 - Issue with Charset Detector for ill-formed input strings. +// Its fix involves returning a failure based error code +// (U_INVALID_CHAR_FOUND) incase no charsets appear to match the input data. +void CharsetDetectionTest::Ticket21823Test() { + UErrorCode status = U_ZERO_ERROR; + std::string str = "\x80"; + UCharsetDetector* csd = ucsdet_open(&status); + + ucsdet_setText(csd, str.data(), str.length(), &status); + const UCharsetMatch* match = ucsdet_detect(csd, &status); + + if (match == NULL) { + TEST_ASSERT(U_FAILURE(status)); + } + + ucsdet_close(csd); +} diff --git a/Build/source/libs/icu/icu-src/source/test/intltest/csdetest.h b/Build/source/libs/icu/icu-src/source/test/intltest/csdetest.h index 72d1ca92aea..8893b88e591 100644 --- a/Build/source/libs/icu/icu-src/source/test/intltest/csdetest.h +++ b/Build/source/libs/icu/icu-src/source/test/intltest/csdetest.h @@ -33,6 +33,7 @@ public: virtual void IBM420Test(); virtual void Ticket6394Test(); virtual void Ticket6954Test(); + virtual void Ticket21823Test(); private: void checkEncoding(const UnicodeString &testString, diff --git a/Build/source/libs/icu/icu-src/source/test/intltest/dtfmttst.cpp b/Build/source/libs/icu/icu-src/source/test/intltest/dtfmttst.cpp index 16f3002a95e..920ec75c8b9 100644 --- a/Build/source/libs/icu/icu-src/source/test/intltest/dtfmttst.cpp +++ b/Build/source/libs/icu/icu-src/source/test/intltest/dtfmttst.cpp @@ -190,7 +190,7 @@ void DateFormatTest::TestPatterns() { {UDAT_ABBR_UTC_TZ, "ZZZZ", "en", "ZZZZ"}, {UDAT_YEAR_NUM_MONTH_DAY UDAT_ABBR_UTC_TZ, "yMdZZZZ", "en", "M/d/y, ZZZZ"}, - {UDAT_MONTH_DAY UDAT_LOCATION_TZ, "MMMMdVVVV", "en", "MMMM d, VVVV"} + {UDAT_MONTH_DAY UDAT_LOCATION_TZ, "MMMMdVVVV", "en", "MMMM d 'at' VVVV"} }; IcuTestErrorCode errorCode(*this, "TestPatterns()"); diff --git a/Build/source/libs/icu/icu-src/source/test/intltest/dtifmtts.cpp b/Build/source/libs/icu/icu-src/source/test/intltest/dtifmtts.cpp index dc9a78dbe16..605eae43614 100644 --- a/Build/source/libs/icu/icu-src/source/test/intltest/dtifmtts.cpp +++ b/Build/source/libs/icu/icu-src/source/test/intltest/dtifmtts.cpp @@ -1107,8 +1107,23 @@ void DateIntervalFormatTest::testHourMetacharacters() { "de", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "HH", "00\\u201301 Uhr", // k and K (ICU-21154 and ICU-21156) - "en", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "KK", "0 \\u2013 1 AM", - "de", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "kk", "24\\u201301 Uhr", + // (should behave the same as h and H if not overridden in locale ID) + "en", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "KK", "12 \\u2013 1 AM", + "de", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "kk", "00\\u201301 Uhr", + // (overriding hour cycle in locale ID should affect both h and K [or both H and k]) + "en-u-hc-h11", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "hh", "0 \\u2013 1 AM", + "en-u-hc-h11", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "KK", "0 \\u2013 1 AM", + "de-u-hc-h24", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "HH", "24\\u201301 Uhr", + "de-u-hc-h24", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "kk", "24\\u201301 Uhr", + // (overriding hour cycle to h11 should NOT affect H and k; overriding to h24 should NOT affect h and K) + "en", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "HH", "00 \\u2013 01", + "en", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "kk", "00 \\u2013 01", + "en-u-hc-h11", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "HH", "00 \\u2013 01", + "en-u-hc-h11", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "kk", "00 \\u2013 01", + "de", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "hh", "12 \\u2013 1 Uhr AM", + "de", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "KK", "12 \\u2013 1 Uhr AM", + "de-u-hc-h24", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "hh", "12 \\u2013 1 Uhr AM", + "de-u-hc-h24", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "KK", "12 \\u2013 1 Uhr AM", // different lengths of the 'a' field "en", "CE 2010 09 27 10:00:00", "CE 2010 09 27 13:00:00", "ha", "10 AM \\u2013 1 PM", @@ -1163,14 +1178,22 @@ void DateIntervalFormatTest::testHourMetacharacters() { "hi_IN", "CE 2010 09 27 10:00:00", "CE 2010 09 27 13:00:00", "CC", "\\u0938\\u0941\\u092C\\u0939 10 \\u2013 \\u0926\\u094B\\u092A\\u0939\\u0930 1", "hi_IN", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "CC", "\\u0930\\u093E\\u0924 12\\u20131", - // regression test for ICU-21342 - "en_GB", "CE 2010 09 27 00:00:00", "CE 2010 09 27 10:00:00", "kk", "24\\u201310", - "en_GB", "CE 2010 09 27 00:00:00", "CE 2010 09 27 11:00:00", "kk", "24\\u201311", - "en_GB", "CE 2010 09 27 00:00:00", "CE 2010 09 27 12:00:00", "kk", "24\\u201312", - "en_GB", "CE 2010 09 27 00:00:00", "CE 2010 09 27 13:00:00", "kk", "24\\u201313", + // regression test for ICU-21342 + "en-gb-u-hc-h24", "CE 2010 09 27 00:00:00", "CE 2010 09 27 10:00:00", "kk", "24\\u201310", + "en-gb-u-hc-h24", "CE 2010 09 27 00:00:00", "CE 2010 09 27 11:00:00", "kk", "24\\u201311", + "en-gb-u-hc-h24", "CE 2010 09 27 00:00:00", "CE 2010 09 27 12:00:00", "kk", "24\\u201312", + "en-gb-u-hc-h24", "CE 2010 09 27 00:00:00", "CE 2010 09 27 13:00:00", "kk", "24\\u201313", - // regression test for ICU-21343 - "de", "CE 2010 09 27 01:00:00", "CE 2010 09 27 10:00:00", "KK", "1 \\u2013 10 Uhr AM", + // regression test for ICU-21343 + "de", "CE 2010 09 27 01:00:00", "CE 2010 09 27 10:00:00", "KK", "1 \\u2013 10 Uhr AM", + + // regression test for ICU-21154 (single-date ranges should use the same hour cycle as multi-date ranges) + "en", "CE 2010 09 27 00:00:00", "CE 2010 09 27 00:00:00", "hh", "12 AM", + "en", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "hh", "12 \\u2013 1 AM", + "en", "CE 2010 09 27 00:00:00", "CE 2010 09 27 00:00:00", "KK", "12 AM", + "en", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "KK", "12 \\u2013 1 AM", // (this was producing "0 - 1 AM" before) + "en", "CE 2010 09 27 00:00:00", "CE 2010 09 27 00:00:00", "jj", "12 AM", + "en", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "jj", "12 \\u2013 1 AM", }; expect(DATA, UPRV_LENGTHOF(DATA)); } diff --git a/Build/source/libs/icu/icu-src/source/test/intltest/dtptngts.cpp b/Build/source/libs/icu/icu-src/source/test/intltest/dtptngts.cpp index 6fe8af05b60..dde9d4dd3ac 100644 --- a/Build/source/libs/icu/icu-src/source/test/intltest/dtptngts.cpp +++ b/Build/source/libs/icu/icu-src/source/test/intltest/dtptngts.cpp @@ -46,6 +46,7 @@ void IntlTestDateTimePatternGeneratorAPI::runIndexedTest( int32_t index, UBool e TESTCASE(10, testGetDefaultHourCycle_OnEmptyInstance); TESTCASE(11, test_jConsistencyOddLocales); TESTCASE(12, testBestPattern); + TESTCASE(13, testDateTimePatterns); default: name = ""; break; } } @@ -530,7 +531,7 @@ void IntlTestDateTimePatternGeneratorAPI::testAPI(/*char *par*/) format->applyPattern(gen->getBestPattern(UnicodeString("MMMMdHmm"), status)); dateReturned.remove(); dateReturned = format->format(sampleDate, dateReturned, status); - expectedResult=UnicodeString("14. von Oktober, 08:58", -1, US_INV); + expectedResult=UnicodeString("14. von Oktober um 08:58", -1, US_INV); if ( dateReturned != expectedResult ) { errln(UnicodeString("ERROR: Simple test addPattern failed!: d\'. von\' MMMM Got: ") + dateReturned + UnicodeString(" Expected: ") + expectedResult); } @@ -1631,4 +1632,150 @@ void IntlTestDateTimePatternGeneratorAPI::testBestPattern() { } } +void IntlTestDateTimePatternGeneratorAPI::testDateTimePatterns() { + UnicodeString skeletons[kNumDateTimePatterns] = { + UnicodeString("yMMMMEEEEdjmm"), // full date, short time + UnicodeString("yMMMMdjmm"), // long date, short time + UnicodeString("yMMMdjmm"), // medium date, short time + UnicodeString("yMdjmm") // short date, short time + }; + // The following tests some locales in which there are differences between the + // DateTimePatterns of various length styles. + DTPLocaleAndResults localeAndResults[] = { + { "en", { UnicodeString(u"EEEE, MMMM d, y 'at' h:mm a"), // long != medium + UnicodeString(u"MMMM d, y 'at' h:mm a"), + UnicodeString(u"MMM d, y, h:mm a"), + UnicodeString(u"M/d/y, h:mm a") } }, + { "fr", { UnicodeString(u"EEEE d MMMM y 'à' HH:mm"), // medium != short + UnicodeString(u"d MMMM y 'à' HH:mm"), + UnicodeString(u"d MMM y, HH:mm"), + UnicodeString(u"dd/MM/y HH:mm") } }, + { "ha", { UnicodeString(u"EEEE d MMMM, y HH:mm"), // full != long + UnicodeString(u"d MMMM, y 'da' HH:mm"), + UnicodeString(u"d MMM, y, HH:mm"), + UnicodeString(u"y-MM-dd, HH:mm") } }, + { nullptr, { UnicodeString(""), UnicodeString(""), // terminator + UnicodeString(""), UnicodeString("") } }, + }; + + UnicodeString enDTPatterns[kNumDateTimePatterns] = { + UnicodeString(u"{1} 'at' {0}"), + UnicodeString(u"{1} 'at' {0}"), + UnicodeString(u"{1}, {0}"), + UnicodeString(u"{1}, {0}") + }; + UnicodeString modDTPatterns[kNumDateTimePatterns] = { + UnicodeString(u"{1} _0_ {0}"), + UnicodeString(u"{1} _1_ {0}"), + UnicodeString(u"{1} _2_ {0}"), + UnicodeString(u"{1} _3_ {0}") + }; + DTPLocaleAndResults enModResults = { "en", { UnicodeString(u"EEEE, MMMM d, y _0_ h:mm a"), + UnicodeString(u"MMMM d, y _1_ h:mm a"), + UnicodeString(u"MMM d, y _2_ h:mm a"), + UnicodeString(u"M/d/y _3_ h:mm a") } + }; + + // Test various locales with standard data + UErrorCode status; + LocalPointer<DateTimePatternGenerator> dtpg; + DTPLocaleAndResults* localeAndResultsPtr = localeAndResults; + for (; localeAndResultsPtr->localeID != nullptr; localeAndResultsPtr++) { + status = U_ZERO_ERROR; + Locale locale(localeAndResultsPtr->localeID); + dtpg.adoptInstead(DateTimePatternGenerator::createInstance(locale, status)); + if (U_FAILURE(status)) { + dataerrln("FAIL: DateTimePatternGenerator::createInstance for locale %s: %s", + localeAndResultsPtr->localeID, u_errorName(status)); + } else { + doDTPatternTest(dtpg.getAlias(), skeletons, localeAndResultsPtr); + } + } + // Test getting and modifying date-time combining patterns + status = U_ZERO_ERROR; + dtpg.adoptInstead(DateTimePatternGenerator::createInstance(Locale::getEnglish(), status)); + if (U_FAILURE(status)) { + dataerrln("FAIL: DateTimePatternGenerator::createInstance #2 for locale en: %s", u_errorName(status)); + } else { + char bExpect[64]; + char bGet[64]; + // Test style out of range + status = U_ZERO_ERROR; + const UnicodeString& dtFormat0 = dtpg->getDateTimeFormat(UDAT_NONE, status); + int32_t dtFormat0Len = dtFormat0.length(); + if (status != U_ILLEGAL_ARGUMENT_ERROR || dtFormat0Len != 0) { + errln("ERROR: getDateTimeFormat with invalid style, expected U_ILLEGAL_ARGUMENT_ERROR and lero-length string, " + "got %s with length %d", u_errorName(status), dtFormat0Len); + } + // Test normal getting and setting + for (int32_t patStyle = 0; patStyle < kNumDateTimePatterns; patStyle++) { + status = U_ZERO_ERROR; + const UnicodeString& dtFormat1 = dtpg->getDateTimeFormat((UDateFormatStyle)patStyle, status); + if (U_FAILURE(status)) { + errln("FAIL: getDateTimeFormat for en before mod, style %d, get %s", patStyle, u_errorName(status)); + } else if (dtFormat1 != enDTPatterns[patStyle]) { + enDTPatterns[patStyle].extract(0, enDTPatterns[patStyle].length(), bExpect, 64); + dtFormat1.extract(0, dtFormat1.length(), bGet, 64); + errln("ERROR: getDateTimeFormat for en before mod, style %d, expect \"%s\", get \"%s\"", + patStyle, bExpect, bGet); + } + status = U_ZERO_ERROR; + dtpg->setDateTimeFormat((UDateFormatStyle)patStyle, modDTPatterns[patStyle], status); + if (U_FAILURE(status)) { + errln("FAIL: setDateTimeFormat for en, style %d, get %s", patStyle, u_errorName(status)); + } else { + const UnicodeString& dtFormat2 = dtpg->getDateTimeFormat((UDateFormatStyle)patStyle, status); + if (U_FAILURE(status)) { + errln("FAIL: getDateTimeFormat for en after mod, style %d, get %s", patStyle, u_errorName(status)); + } else if (dtFormat2 != modDTPatterns[patStyle]) { + modDTPatterns[patStyle].extract(0, modDTPatterns[patStyle].length(), bExpect, 64); + dtFormat2.extract(0, dtFormat2.length(), bGet, 64); + errln("ERROR: getDateTimeFormat for en after mod, style %d, expect \"%s\", get \"%s\"", + patStyle, bExpect, bGet); + } + } + } + // Test result of setting + doDTPatternTest(dtpg.getAlias(), skeletons, &enModResults); + // Test old get/set functions + const UnicodeString& dtFormat3 = dtpg->getDateTimeFormat(); + if (dtFormat3 != modDTPatterns[UDAT_MEDIUM]) { + modDTPatterns[UDAT_MEDIUM].extract(0, modDTPatterns[UDAT_MEDIUM].length(), bExpect, 64); + dtFormat3.extract(0, dtFormat3.length(), bGet, 64); + errln("ERROR: old getDateTimeFormat for en after mod, expect \"%s\", get \"%s\"", bExpect, bGet); + } + dtpg->setDateTimeFormat(modDTPatterns[UDAT_SHORT]); // set all dateTimePatterns to the short format + modDTPatterns[UDAT_SHORT].extract(0, modDTPatterns[UDAT_SHORT].length(), bExpect, 64); + for (int32_t patStyle = 0; patStyle < kNumDateTimePatterns; patStyle++) { + status = U_ZERO_ERROR; + const UnicodeString& dtFormat4 = dtpg->getDateTimeFormat((UDateFormatStyle)patStyle, status); + if (U_FAILURE(status)) { + errln("FAIL: getDateTimeFormat for en after second mod, style %d, get %s", patStyle, u_errorName(status)); + } else if (dtFormat4 != modDTPatterns[UDAT_SHORT]) { + dtFormat4.extract(0, dtFormat4.length(), bGet, 64); + errln("ERROR: getDateTimeFormat for en after second mod, style %d, expect \"%s\", get \"%s\"", + patStyle, bExpect, bGet); + } + } + } +} + +void IntlTestDateTimePatternGeneratorAPI::doDTPatternTest(DateTimePatternGenerator* dtpg, UnicodeString* skeletons, DTPLocaleAndResults* localeAndResultsPtr) { + for (int32_t patStyle = 0; patStyle < kNumDateTimePatterns; patStyle++) { + UErrorCode status = U_ZERO_ERROR; + UnicodeString getPat = dtpg->getBestPattern(skeletons[patStyle], UDATPG_MATCH_NO_OPTIONS, status); + if (U_FAILURE(status)) { + errln("FAIL: DateTimePatternGenerator::getBestPattern locale %s, style %d: %s", + localeAndResultsPtr->localeID, patStyle, u_errorName(status)); + } else if (getPat != localeAndResultsPtr->expectPat[patStyle]) { + char bExpect[64]; + char bGet[64]; + localeAndResultsPtr->expectPat[patStyle].extract(0, localeAndResultsPtr->expectPat[patStyle].length(), bExpect, 64); + getPat.extract(0, getPat.length(), bGet, 64); + errln("ERROR: DateTimePatternGenerator::getBestPattern locale %s, style %d, expect \"%s\", get \"%s\"", + localeAndResultsPtr->localeID, patStyle, bExpect, bGet); + } + } +} + #endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/Build/source/libs/icu/icu-src/source/test/intltest/dtptngts.h b/Build/source/libs/icu/icu-src/source/test/intltest/dtptngts.h index 4650fd7fcf6..ec700603eb1 100644 --- a/Build/source/libs/icu/icu-src/source/test/intltest/dtptngts.h +++ b/Build/source/libs/icu/icu-src/source/test/intltest/dtptngts.h @@ -13,6 +13,8 @@ #if !UCONFIG_NO_FORMATTING +#include "unicode/dtptngen.h" +#include "unicode/ustring.h" #include "intltest.h" /** @@ -38,6 +40,14 @@ private: void testGetDefaultHourCycle_OnEmptyInstance(); void test_jConsistencyOddLocales(); void testBestPattern(); + void testDateTimePatterns(); + + enum { kNumDateTimePatterns = 4 }; + typedef struct { + const char* localeID; + const UnicodeString expectPat[kNumDateTimePatterns]; + } DTPLocaleAndResults; + void doDTPatternTest(DateTimePatternGenerator* dtpg, UnicodeString* skeletons, DTPLocaleAndResults* localeAndResultsPtr); }; #endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/Build/source/libs/icu/icu-src/source/test/intltest/icusvtst.cpp b/Build/source/libs/icu/icu-src/source/test/intltest/icusvtst.cpp index aa2d9ca05ce..cb863c5b71b 100644 --- a/Build/source/libs/icu/icu-src/source/test/intltest/icusvtst.cpp +++ b/Build/source/libs/icu/icu-src/source/test/intltest/icusvtst.cpp @@ -558,7 +558,7 @@ class TestMultipleKeyStringFactory : public ICUServiceFactory { , _factoryID(factoryID + ": ") { for (int i = 0; i < count; ++i) { - _ids.addElementX(new UnicodeString(ids[i]), _status); + _ids.adoptElement(new UnicodeString(ids[i]), _status); } } diff --git a/Build/source/libs/icu/icu-src/source/test/intltest/incaltst.cpp b/Build/source/libs/icu/icu-src/source/test/intltest/incaltst.cpp index ad75f185f63..250b61c7ac0 100644 --- a/Build/source/libs/icu/icu-src/source/test/intltest/incaltst.cpp +++ b/Build/source/libs/icu/icu-src/source/test/intltest/incaltst.cpp @@ -988,7 +988,7 @@ void IntlCalendarTest::TestConsistencyEthiopicAmeteAlem() { } void IntlCalendarTest::checkConsistency(const char* locale) { // Check 2.5 years in quick mode and 8000 years in exhaustive mode. - int32_t numOfDaysToTest = (quick ? 2.5 : 8000) * 365; + int32_t numOfDaysToTest = static_cast<int32_t>((quick ? 2.5 : 8000) * 365); constexpr int32_t msInADay = 1000*60*60*24; std::string msg("TestConsistency"); IcuTestErrorCode status(*this, (msg + locale).c_str()); diff --git a/Build/source/libs/icu/icu-src/source/test/intltest/intltest.cpp b/Build/source/libs/icu/icu-src/source/test/intltest/intltest.cpp index 7ff28961271..f2956ebcb48 100644 --- a/Build/source/libs/icu/icu-src/source/test/intltest/intltest.cpp +++ b/Build/source/libs/icu/icu-src/source/test/intltest/intltest.cpp @@ -2188,14 +2188,20 @@ UBool IntlTest::assertEqualsNear(const char* message, double expected, double actual, double delta) { + bool bothNaN = std::isnan(expected) && std::isnan(actual); + bool bothPosInf = uprv_isPositiveInfinity(expected) && uprv_isPositiveInfinity(actual); + bool bothNegInf = uprv_isNegativeInfinity(expected) && uprv_isNegativeInfinity(actual); + if (bothPosInf || bothNegInf || bothNaN) { + // We don't care about delta in these cases + return TRUE; + } if (std::isnan(delta) || std::isinf(delta)) { errln((UnicodeString)("FAIL: ") + message + "; nonsensical delta " + delta + - " - delta may not be NaN or Inf"); + " - delta may not be NaN or Inf. (Got " + actual + "; expected " + expected + ".)"); return FALSE; } - bool bothNaN = std::isnan(expected) && std::isnan(actual); double difference = std::abs(expected - actual); - if (expected != actual && (difference > delta || std::isnan(difference)) && !bothNaN) { + if (expected != actual && (difference > delta || std::isnan(difference))) { errln((UnicodeString)("FAIL: ") + message + "; got " + actual + "; expected " + expected + "; acceptable delta " + delta); return FALSE; diff --git a/Build/source/libs/icu/icu-src/source/test/intltest/listformattertest.cpp b/Build/source/libs/icu/icu-src/source/test/intltest/listformattertest.cpp index 831642241e6..1a4ec97f37d 100644 --- a/Build/source/libs/icu/icu-src/source/test/intltest/listformattertest.cpp +++ b/Build/source/libs/icu/icu-src/source/test/intltest/listformattertest.cpp @@ -49,6 +49,7 @@ void ListFormatterTest::runIndexedTest(int32_t index, UBool exec, TESTCASE_AUTO(TestContextual); TESTCASE_AUTO(TestNextPosition); TESTCASE_AUTO(TestInt32Overflow); + TESTCASE_AUTO(Test21871); TESTCASE_AUTO_END; } @@ -276,7 +277,7 @@ void ListFormatterTest::RunTestFieldPositionIteratorWithNItemsPatternShift( const char* testName) { IcuTestErrorCode errorCode(*this, testName); LocalPointer<ListFormatter> formatter(ListFormatter::createInstance( - Locale("ur", "IN"), + Locale("ur", "IN"), // in CLDR 41 alpha1 the "backwards order" patterns in this and other locales were removed. ULISTFMT_TYPE_UNITS, ULISTFMT_WIDTH_NARROW, errorCode)); @@ -329,21 +330,21 @@ void ListFormatterTest::TestFieldPositionIteratorWith3Items() { } void ListFormatterTest::TestFieldPositionIteratorWith3ItemsPatternShift() { - // 0 1 - // 012345678901234 - // "cc bbb a" + // Note: In CLDR 41 alpha1 the "backwards order" patterns in ur_IN (and one or two + // other locales) were removed, ur_IN now just inherits list patterns from ur. + // So this test may no longer be interesting. UnicodeString data[3] = {"a", "bbb", "cc"}; int32_t expected[] = { - ULISTFMT_ELEMENT_FIELD, 7, 8, - ULISTFMT_LITERAL_FIELD, 6, 7, + ULISTFMT_ELEMENT_FIELD, 0, 1, + ULISTFMT_LITERAL_FIELD, 1, 3, ULISTFMT_ELEMENT_FIELD, 3, 6, - ULISTFMT_LITERAL_FIELD, 2, 3, - ULISTFMT_ELEMENT_FIELD, 0, 2 + ULISTFMT_LITERAL_FIELD, 6, 12, + ULISTFMT_ELEMENT_FIELD, 12, 14 }; int32_t tupleCount = sizeof(expected)/(3 * sizeof(*expected)); RunTestFieldPositionIteratorWithNItemsPatternShift( data, 3, expected, tupleCount, - u"cc bbb a", + u"a، bbb، اور cc", "TestFieldPositionIteratorWith3ItemsPatternShift"); } @@ -365,19 +366,19 @@ void ListFormatterTest::TestFieldPositionIteratorWith2Items() { } void ListFormatterTest::TestFieldPositionIteratorWith2ItemsPatternShift() { - // 0 1 - // 01234567890 - // "cc bbb" + // Note: In CLDR 41 alpha1 the "backwards order" patterns in ur_IN (and one or two + // other locales) were removed, ur_IN now just inherits list patterns from ur. + // So this test may no longer be interesting. UnicodeString data[2] = {"bbb", "cc"}; int32_t expected[] = { - ULISTFMT_ELEMENT_FIELD, 3, 6, - ULISTFMT_LITERAL_FIELD, 2, 3, - ULISTFMT_ELEMENT_FIELD, 0, 2 + ULISTFMT_ELEMENT_FIELD, 0, 3, + ULISTFMT_LITERAL_FIELD, 3, 8, + ULISTFMT_ELEMENT_FIELD, 8, 10 }; int32_t tupleCount = sizeof(expected)/(3 * sizeof(*expected)); RunTestFieldPositionIteratorWithNItemsPatternShift( data, 2, expected, tupleCount, - u"cc bbb", + u"bbb اور cc", "TestFieldPositionIteratorWith2ItemsPatternShift"); } @@ -840,4 +841,30 @@ void ListFormatterTest::TestInt32Overflow() { status.expectErrorAndReset(U_INPUT_TOO_LONG_ERROR); } + +void ListFormatterTest::Test21871() { + IcuTestErrorCode status(*this, "Test21871"); + LocalPointer<ListFormatter> fmt(ListFormatter::createInstance("en", status), status); + { + UnicodeString strings[] = {{u"A"}, {u""}}; + FormattedList result = fmt->formatStringsToValue(strings, 2, status); + ConstrainedFieldPosition cfp; + cfp.constrainField(UFIELD_CATEGORY_LIST, ULISTFMT_ELEMENT_FIELD); + assertTrue("nextPosition 1", result.nextPosition(cfp, status)); + assertEquals("start", cfp.getStart(), 0); + assertEquals("limit", cfp.getLimit(), 1); + assertFalse("nextPosition 2", result.nextPosition(cfp, status)); + } + { + UnicodeString strings[] = {{u""}, {u"B"}}; + FormattedList result = fmt->formatStringsToValue(strings, 2, status); + ConstrainedFieldPosition cfp; + cfp.constrainField(UFIELD_CATEGORY_LIST, ULISTFMT_ELEMENT_FIELD); + assertTrue("nextPosition 1", result.nextPosition(cfp, status)); + assertEquals("start", cfp.getStart(), 5); + assertEquals("limit", cfp.getLimit(), 6); + assertFalse("nextPosition 2", result.nextPosition(cfp, status)); + } +} + #endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/Build/source/libs/icu/icu-src/source/test/intltest/listformattertest.h b/Build/source/libs/icu/icu-src/source/test/intltest/listformattertest.h index d6bf3bc0d68..0f0390010e4 100644 --- a/Build/source/libs/icu/icu-src/source/test/intltest/listformattertest.h +++ b/Build/source/libs/icu/icu-src/source/test/intltest/listformattertest.h @@ -56,6 +56,7 @@ class ListFormatterTest : public IntlTestWithFieldPosition { void TestContextual(); void TestNextPosition(); void TestInt32Overflow(); + void Test21871(); private: void CheckFormatting( diff --git a/Build/source/libs/icu/icu-src/source/test/intltest/lstmbetst.cpp b/Build/source/libs/icu/icu-src/source/test/intltest/lstmbetst.cpp index 6c5d5d0ad61..0ffc0fa20e5 100644 --- a/Build/source/libs/icu/icu-src/source/test/intltest/lstmbetst.cpp +++ b/Build/source/libs/icu/icu-src/source/test/intltest/lstmbetst.cpp @@ -153,7 +153,7 @@ void LSTMBETest::runTestFromFile(const char* filename) { dataerrln("%s:%d Error %s Could not allocate UVextor32", __FILE__, __LINE__, u_errorName(status)); return; } - engine->findBreaks(&ut, 0, value.length(), actual, status); + engine->findBreaks(&ut, 0, value.length(), actual, false, status); if (U_FAILURE(status)) { dataerrln("%s:%d Error %s findBreaks failed", __FILE__, __LINE__, u_errorName(status)); return; @@ -288,7 +288,7 @@ void LSTMBETest::runTestWithLargeMemory( const char* model, UScriptCode script) return; } - engine->findBreaks(&ut, 0, text.length(), actual, status); + engine->findBreaks(&ut, 0, text.length(), actual, false, status); utext_close(&ut); text += text; } diff --git a/Build/source/libs/icu/icu-src/source/test/intltest/measfmttest.cpp b/Build/source/libs/icu/icu-src/source/test/intltest/measfmttest.cpp index 003804db9a4..05488b7c360 100644 --- a/Build/source/libs/icu/icu-src/source/test/intltest/measfmttest.cpp +++ b/Build/source/libs/icu/icu-src/source/test/intltest/measfmttest.cpp @@ -2683,7 +2683,7 @@ void MeasureFormatTest::TestCompatible69() { assertSuccess("", status); } -void MeasureFormatTest::TestCompatible70() { +void MeasureFormatTest::TestCompatible70() { // TestCompatible71 would be identical UErrorCode status = U_ZERO_ERROR; LocalPointer<MeasureUnit> measureUnit; MeasureUnit measureUnitValue; @@ -3064,6 +3064,9 @@ void MeasureFormatTest::TestCompatible70() { assertSuccess("", status); } +// TestCompatible71 would be identical to TestCompatible70, +// no need to add it + void MeasureFormatTest::TestBasic() { UErrorCode status = U_ZERO_ERROR; MeasureUnit *ptr1 = MeasureUnit::createArcMinute(status); diff --git a/Build/source/libs/icu/icu-src/source/test/intltest/numbertest.h b/Build/source/libs/icu/icu-src/source/test/intltest/numbertest.h index d6d71543fb6..c0f2e6fd58a 100644 --- a/Build/source/libs/icu/icu-src/source/test/intltest/numbertest.h +++ b/Build/source/libs/icu/icu-src/source/test/intltest/numbertest.h @@ -66,6 +66,7 @@ class NumberFormatterApiTest : public IntlTestWithFieldPosition { void unitUsageSkeletons(); void unitCurrency(); void unitInflections(); + void unitNounClass(); void unitGender(); void unitNotConvertible(); void unitPercent(); @@ -75,6 +76,7 @@ class NumberFormatterApiTest : public IntlTestWithFieldPosition { void roundingFractionFigures(); void roundingOther(); void roundingIncrementRegressionTest(); + void roundingPriorityCoverageTest(); void grouping(); void padding(); void integerWidth(); @@ -99,7 +101,8 @@ class NumberFormatterApiTest : public IntlTestWithFieldPosition { void toObject(); void toDecimalNumber(); void microPropsInternals(); - + void formatUnitsAliases(); + void runIndexedTest(int32_t index, UBool exec, const char *&name, char *par = 0) override; private: @@ -206,6 +209,7 @@ class DecimalQuantityTest : public IntlTest { void testNickelRounding(); void testScientificAndCompactSuppressedExponent(); void testSuppressedExponentUnchangedByInitialScaling(); + void testDecimalQuantityParseFormatRoundTrip(); void runIndexedTest(int32_t index, UBool exec, const char *&name, char *par = 0) override; diff --git a/Build/source/libs/icu/icu-src/source/test/intltest/numbertest_api.cpp b/Build/source/libs/icu/icu-src/source/test/intltest/numbertest_api.cpp index cf8fecc0a28..b477a16e93e 100644 --- a/Build/source/libs/icu/icu-src/source/test/intltest/numbertest_api.cpp +++ b/Build/source/libs/icu/icu-src/source/test/intltest/numbertest_api.cpp @@ -87,6 +87,7 @@ void NumberFormatterApiTest::runIndexedTest(int32_t index, UBool exec, const cha TESTCASE_AUTO(unitUsageSkeletons); TESTCASE_AUTO(unitCurrency); TESTCASE_AUTO(unitInflections); + TESTCASE_AUTO(unitNounClass); TESTCASE_AUTO(unitGender); TESTCASE_AUTO(unitNotConvertible); TESTCASE_AUTO(unitPercent); @@ -99,6 +100,7 @@ void NumberFormatterApiTest::runIndexedTest(int32_t index, UBool exec, const cha TESTCASE_AUTO(roundingFractionFigures); TESTCASE_AUTO(roundingOther); TESTCASE_AUTO(roundingIncrementRegressionTest); + TESTCASE_AUTO(roundingPriorityCoverageTest); TESTCASE_AUTO(grouping); TESTCASE_AUTO(padding); TESTCASE_AUTO(integerWidth); @@ -127,6 +129,7 @@ void NumberFormatterApiTest::runIndexedTest(int32_t index, UBool exec, const cha TESTCASE_AUTO(toObject); TESTCASE_AUTO(toDecimalNumber); TESTCASE_AUTO(microPropsInternals); + TESTCASE_AUTO(formatUnitsAliases); TESTCASE_AUTO_END; } @@ -1747,6 +1750,46 @@ void NumberFormatterApiTest::unitUsage() { 30500, u"350 m"); + assertFormatSingle(u"Fuel consumption: inverted units", // + u"unit/liter-per-100-kilometer usage/vehicle-fuel", // + u"unit/liter-per-100-kilometer usage/vehicle-fuel", // + NumberFormatter::with() // + .unit(MeasureUnit::forIdentifier("liter-per-100-kilometer", status)) // + .usage("vehicle-fuel"), // + Locale("en-US"), // + 6.6, // + "36 mpg"); + + assertFormatSingle(u"Fuel consumption: inverted units, divide-by-zero, en-US", // + u"unit/liter-per-100-kilometer usage/vehicle-fuel", // + u"unit/liter-per-100-kilometer usage/vehicle-fuel", // + NumberFormatter::with() // + .unit(MeasureUnit::forIdentifier("liter-per-100-kilometer", status)) // + .usage("vehicle-fuel"), // + Locale("en-US"), // + 0, // + u"∞ mpg"); + + assertFormatSingle(u"Fuel consumption: inverted units, divide-by-zero, en-ZA", // + u"unit/mile-per-gallon usage/vehicle-fuel", // + u"unit/mile-per-gallon usage/vehicle-fuel", // + NumberFormatter::with() // + .unit(MeasureUnit::forIdentifier("mile-per-gallon", status)) // + .usage("vehicle-fuel"), // + Locale("en-ZA"), // + 0, // + u"∞ l/100 km"); + + assertFormatSingle(u"Fuel consumption: inverted units, divide-by-inf", // + u"unit/mile-per-gallon usage/vehicle-fuel", // + u"unit/mile-per-gallon usage/vehicle-fuel", // + NumberFormatter::with() // + .unit(MeasureUnit::forIdentifier("mile-per-gallon", status)) // + .usage("vehicle-fuel"), // + Locale("de-CH"), // + uprv_getInfinity(), // + u"0 L/100 km"); + // Test calling `.usage("")` should unset the existing usage. // First: without usage assertFormatSingle(u"Rounding Mode propagates: rounding up", @@ -1853,10 +1896,6 @@ void NumberFormatterApiTest::unitUsage() { Locale("en-US"), // 1, // "0.019 psi"); - - // TODO(icu-units#38): improve unit testing coverage. E.g. add vehicle-fuel - // triggering inversion conversion code. Test with 0 too, to see - // divide-by-zero behaviour. } void NumberFormatterApiTest::unitUsageErrorCodes() { @@ -2384,7 +2423,7 @@ void NumberFormatterApiTest::unitInflections() { {"centimeter", "de", nullptr, 1, u"1 Zentimeter"}, {"centimeter", "de", "genitive", 1, u"1 Zentimeters"}, {"centimeter", "de", "dative", 10, u"10 Zentimetern"}, - // TODO(CLDR-14502): check that these inflections are correct, and + // TODO(CLDR-14582): check that these inflections are correct, and // whether CLDR needs any rules for them (presumably CLDR spec // should mention it, if it's a consistent rule): {"meter-and-centimeter", "de", nullptr, 1.01, u"1 Meter, 1 Zentimeter"}, @@ -2401,6 +2440,307 @@ void NumberFormatterApiTest::unitInflections() { // TODO: look at "↑↑↑" cases: check that inheritance is done right. } +using icu::NounClass; +void NumberFormatterApiTest::unitNounClass() { + IcuTestErrorCode status(*this, "unitNounClass"); + const struct TestCase { + const char *locale; + const char *unitIdentifier; + const NounClass expectedNounClass; + } cases[] = { + {"de", "inch", NounClass::MASCULINE}, + {"de", "yard", NounClass::NEUTER}, + {"de", "meter", NounClass::MASCULINE}, + {"de", "liter", NounClass::MASCULINE}, + {"de", "second", NounClass::FEMININE}, + {"de", "minute", NounClass::FEMININE}, + {"de", "hour", NounClass::FEMININE}, + {"de", "day", NounClass::MASCULINE}, + {"de", "year", NounClass::NEUTER}, + {"de", "gram", NounClass::NEUTER}, + {"de", "watt", NounClass::NEUTER}, + {"de", "bit", NounClass::NEUTER}, + {"de", "byte", NounClass::NEUTER}, + + {"fr", "inch", NounClass::MASCULINE}, + {"fr", "yard", NounClass::MASCULINE}, + {"fr", "meter", NounClass::MASCULINE}, + {"fr", "liter", NounClass::MASCULINE}, + {"fr", "second", NounClass::FEMININE}, + {"fr", "minute", NounClass::FEMININE}, + {"fr", "hour", NounClass::FEMININE}, + {"fr", "day", NounClass::MASCULINE}, + {"fr", "year", NounClass::MASCULINE}, + {"fr", "gram", NounClass::MASCULINE}, + + // grammaticalFeatures deriveCompound "per" rule takes the gender of the + // numerator unit: + {"de", "meter-per-hour", NounClass::MASCULINE}, + {"fr", "meter-per-hour", NounClass::MASCULINE}, + {"af", "meter-per-hour", NounClass::OTHER}, // ungendered language + + // French "times" takes gender from first value, German takes the + // second. Prefix and power does not have impact on gender for these + // languages: + {"de", "square-decimeter-square-second", NounClass::FEMININE}, + {"fr", "square-decimeter-square-second", NounClass::MASCULINE}, + + // TODO(icu-units#149): percent and permille bypasses LongNameHandler + // when unitWidth is not FULL_NAME: + // // Gender of per-second might be that of percent? TODO(icu-units#28) + // {"de", "percent", NounClass::NEUTER}, + // {"fr", "percent", NounClass::MASCULINE}, + + // Built-in units whose simple units lack gender in the CLDR data file + {"de", "kilopascal", NounClass::NEUTER}, + {"fr", "kilopascal", NounClass::MASCULINE}, + // {"de", "pascal", NounClass::OTHER}, + // {"fr", "pascal", NounClass::OTHER}, + + // Built-in units that lack gender in the CLDR data file + // {"de", "revolution", NounClass::OTHER}, + // {"de", "radian", NounClass::OTHER}, + // {"de", "arc-minute", NounClass::OTHER}, + // {"de", "arc-second", NounClass::OTHER}, + {"de", "square-yard", NounClass::NEUTER}, // POWER + {"de", "square-inch", NounClass::MASCULINE}, // POWER + // {"de", "dunam", NounClass::OTHER}, + // {"de", "karat", NounClass::OTHER}, + // {"de", "milligram-ofglucose-per-deciliter", NounClass::OTHER}, // COMPOUND, ofglucose + // {"de", "millimole-per-liter", NounClass::OTHER}, // COMPOUND, mole + // {"de", "permillion", NounClass::OTHER}, + // {"de", "permille", NounClass::OTHER}, + // {"de", "permyriad", NounClass::OTHER}, + // {"de", "mole", NounClass::OTHER}, + {"de", "liter-per-kilometer", NounClass::MASCULINE}, // COMPOUND + {"de", "petabyte", NounClass::NEUTER}, // PREFIX + {"de", "terabit", NounClass::NEUTER}, // PREFIX + // {"de", "century", NounClass::OTHER}, + // {"de", "decade", NounClass::OTHER}, + {"de", "millisecond", NounClass::FEMININE}, // PREFIX + {"de", "microsecond", NounClass::FEMININE}, // PREFIX + {"de", "nanosecond", NounClass::FEMININE}, // PREFIX + // {"de", "ampere", NounClass::OTHER}, + // {"de", "milliampere", NounClass::OTHER}, // PREFIX, ampere + // {"de", "ohm", NounClass::OTHER}, + // {"de", "calorie", NounClass::OTHER}, + // {"de", "kilojoule", NounClass::OTHER}, // PREFIX, joule + // {"de", "joule", NounClass::OTHER}, + {"de", "kilowatt-hour", NounClass::FEMININE}, // COMPOUND + // {"de", "electronvolt", NounClass::OTHER}, + // {"de", "british-thermal-unit", NounClass::OTHER}, + // {"de", "therm-us", NounClass::OTHER}, + // {"de", "pound-force", NounClass::OTHER}, + // {"de", "newton", NounClass::OTHER}, + // {"de", "gigahertz", NounClass::OTHER}, // PREFIX, hertz + // {"de", "megahertz", NounClass::OTHER}, // PREFIX, hertz + // {"de", "kilohertz", NounClass::OTHER}, // PREFIX, hertz + // {"de", "hertz", NounClass::OTHER}, + // {"de", "em", NounClass::OTHER}, + // {"de", "pixel", NounClass::OTHER}, + // {"de", "megapixel", NounClass::OTHER}, + // {"de", "pixel-per-centimeter", NounClass::OTHER}, // COMPOUND, pixel + // {"de", "pixel-per-inch", NounClass::OTHER}, // COMPOUND, pixel + // {"de", "dot-per-centimeter", NounClass::OTHER}, // COMPOUND, dot + // {"de", "dot-per-inch", NounClass::OTHER}, // COMPOUND, dot + // {"de", "dot", NounClass::OTHER}, + // {"de", "earth-radius", NounClass::OTHER}, + {"de", "decimeter", NounClass::MASCULINE}, // PREFIX + {"de", "micrometer", NounClass::MASCULINE}, // PREFIX + {"de", "nanometer", NounClass::MASCULINE}, // PREFIX + // {"de", "light-year", NounClass::OTHER}, + // {"de", "astronomical-unit", NounClass::OTHER}, + // {"de", "furlong", NounClass::OTHER}, + // {"de", "fathom", NounClass::OTHER}, + // {"de", "nautical-mile", NounClass::OTHER}, + // {"de", "mile-scandinavian", NounClass::OTHER}, + // {"de", "point", NounClass::OTHER}, + // {"de", "lux", NounClass::OTHER}, + // {"de", "candela", NounClass::OTHER}, + // {"de", "lumen", NounClass::OTHER}, + // {"de", "metric-ton", NounClass::OTHER}, + // {"de", "microgram", NounClass::NEUTER}, // PREFIX + // {"de", "ton", NounClass::OTHER}, + // {"de", "stone", NounClass::OTHER}, + // {"de", "ounce-troy", NounClass::OTHER}, + // {"de", "carat", NounClass::OTHER}, + {"de", "gigawatt", NounClass::NEUTER}, // PREFIX + {"de", "milliwatt", NounClass::NEUTER}, // PREFIX + // {"de", "horsepower", NounClass::OTHER}, + // {"de", "millimeter-ofhg", NounClass::OTHER}, + // {"de", "pound-force-per-square-inch", NounClass::OTHER}, // COMPOUND, pound-force + // {"de", "inch-ofhg", NounClass::OTHER}, + // {"de", "bar", NounClass::OTHER}, + // {"de", "millibar", NounClass::OTHER}, // PREFIX, bar + // {"de", "atmosphere", NounClass::OTHER}, + // {"de", "pascal", NounClass::OTHER}, // PREFIX, kilopascal? neuter? + // {"de", "hectopascal", NounClass::OTHER}, // PREFIX, pascal, neuter? + // {"de", "megapascal", NounClass::OTHER}, // PREFIX, pascal, neuter? + // {"de", "knot", NounClass::OTHER}, + {"de", "pound-force-foot", NounClass::MASCULINE}, // COMPOUND + {"de", "newton-meter", NounClass::MASCULINE}, // COMPOUND + {"de", "cubic-kilometer", NounClass::MASCULINE}, // POWER + {"de", "cubic-yard", NounClass::NEUTER}, // POWER + {"de", "cubic-inch", NounClass::MASCULINE}, // POWER + {"de", "megaliter", NounClass::MASCULINE}, // PREFIX + {"de", "hectoliter", NounClass::MASCULINE}, // PREFIX + // {"de", "pint-metric", NounClass::OTHER}, + // {"de", "cup-metric", NounClass::OTHER}, + {"de", "acre-foot", NounClass::MASCULINE}, // COMPOUND + // {"de", "bushel", NounClass::OTHER}, + // {"de", "barrel", NounClass::OTHER}, + // Units missing gender in German also misses gender in French: + // {"fr", "revolution", NounClass::OTHER}, + // {"fr", "radian", NounClass::OTHER}, + // {"fr", "arc-minute", NounClass::OTHER}, + // {"fr", "arc-second", NounClass::OTHER}, + {"fr", "square-yard", NounClass::MASCULINE}, // POWER + {"fr", "square-inch", NounClass::MASCULINE}, // POWER + // {"fr", "dunam", NounClass::OTHER}, + // {"fr", "karat", NounClass::OTHER}, + {"fr", "milligram-ofglucose-per-deciliter", NounClass::MASCULINE}, // COMPOUND + // {"fr", "millimole-per-liter", NounClass::OTHER}, // COMPOUND, mole + // {"fr", "permillion", NounClass::OTHER}, + // {"fr", "permille", NounClass::OTHER}, + // {"fr", "permyriad", NounClass::OTHER}, + // {"fr", "mole", NounClass::OTHER}, + {"fr", "liter-per-kilometer", NounClass::MASCULINE}, // COMPOUND + // {"fr", "petabyte", NounClass::OTHER}, // PREFIX + // {"fr", "terabit", NounClass::OTHER}, // PREFIX + // {"fr", "century", NounClass::OTHER}, + // {"fr", "decade", NounClass::OTHER}, + {"fr", "millisecond", NounClass::FEMININE}, // PREFIX + {"fr", "microsecond", NounClass::FEMININE}, // PREFIX + {"fr", "nanosecond", NounClass::FEMININE}, // PREFIX + // {"fr", "ampere", NounClass::OTHER}, + // {"fr", "milliampere", NounClass::OTHER}, // PREFIX, ampere + // {"fr", "ohm", NounClass::OTHER}, + // {"fr", "calorie", NounClass::OTHER}, + // {"fr", "kilojoule", NounClass::OTHER}, // PREFIX, joule + // {"fr", "joule", NounClass::OTHER}, + // {"fr", "kilowatt-hour", NounClass::OTHER}, // COMPOUND + // {"fr", "electronvolt", NounClass::OTHER}, + // {"fr", "british-thermal-unit", NounClass::OTHER}, + // {"fr", "therm-us", NounClass::OTHER}, + // {"fr", "pound-force", NounClass::OTHER}, + // {"fr", "newton", NounClass::OTHER}, + // {"fr", "gigahertz", NounClass::OTHER}, // PREFIX, hertz + // {"fr", "megahertz", NounClass::OTHER}, // PREFIX, hertz + // {"fr", "kilohertz", NounClass::OTHER}, // PREFIX, hertz + // {"fr", "hertz", NounClass::OTHER}, + // {"fr", "em", NounClass::OTHER}, + // {"fr", "pixel", NounClass::OTHER}, + // {"fr", "megapixel", NounClass::OTHER}, + // {"fr", "pixel-per-centimeter", NounClass::OTHER}, // COMPOUND, pixel + // {"fr", "pixel-per-inch", NounClass::OTHER}, // COMPOUND, pixel + // {"fr", "dot-per-centimeter", NounClass::OTHER}, // COMPOUND, dot + // {"fr", "dot-per-inch", NounClass::OTHER}, // COMPOUND, dot + // {"fr", "dot", NounClass::OTHER}, + // {"fr", "earth-radius", NounClass::OTHER}, + {"fr", "decimeter", NounClass::MASCULINE}, // PREFIX + {"fr", "micrometer", NounClass::MASCULINE}, // PREFIX + {"fr", "nanometer", NounClass::MASCULINE}, // PREFIX + // {"fr", "light-year", NounClass::OTHER}, + // {"fr", "astronomical-unit", NounClass::OTHER}, + // {"fr", "furlong", NounClass::OTHER}, + // {"fr", "fathom", NounClass::OTHER}, + // {"fr", "nautical-mile", NounClass::OTHER}, + // {"fr", "mile-scandinavian", NounClass::OTHER}, + // {"fr", "point", NounClass::OTHER}, + // {"fr", "lux", NounClass::OTHER}, + // {"fr", "candela", NounClass::OTHER}, + // {"fr", "lumen", NounClass::OTHER}, + // {"fr", "metric-ton", NounClass::OTHER}, + // {"fr", "microgram", NounClass::MASCULINE}, // PREFIX + // {"fr", "ton", NounClass::OTHER}, + // {"fr", "stone", NounClass::OTHER}, + // {"fr", "ounce-troy", NounClass::OTHER}, + // {"fr", "carat", NounClass::OTHER}, + // {"fr", "gigawatt", NounClass::OTHER}, // PREFIX + // {"fr", "milliwatt", NounClass::OTHER}, + // {"fr", "horsepower", NounClass::OTHER}, + {"fr", "millimeter-ofhg", NounClass::MASCULINE}, + // {"fr", "pound-force-per-square-inch", NounClass::OTHER}, // COMPOUND, pound-force + {"fr", "inch-ofhg", NounClass::MASCULINE}, + // {"fr", "bar", NounClass::OTHER}, + // {"fr", "millibar", NounClass::OTHER}, // PREFIX, bar + // {"fr", "atmosphere", NounClass::OTHER}, + // {"fr", "pascal", NounClass::OTHER}, // PREFIX, kilopascal? + // {"fr", "hectopascal", NounClass::OTHER}, // PREFIX, pascal + // {"fr", "megapascal", NounClass::OTHER}, // PREFIX, pascal + // {"fr", "knot", NounClass::OTHER}, + // {"fr", "pound-force-foot", NounClass::OTHER}, + // {"fr", "newton-meter", NounClass::OTHER}, + {"fr", "cubic-kilometer", NounClass::MASCULINE}, // POWER + {"fr", "cubic-yard", NounClass::MASCULINE}, // POWER + {"fr", "cubic-inch", NounClass::MASCULINE}, // POWER + {"fr", "megaliter", NounClass::MASCULINE}, // PREFIX + {"fr", "hectoliter", NounClass::MASCULINE}, // PREFIX + // {"fr", "pint-metric", NounClass::OTHER}, + // {"fr", "cup-metric", NounClass::OTHER}, + {"fr", "acre-foot", NounClass::FEMININE}, // COMPOUND + // {"fr", "bushel", NounClass::OTHER}, + // {"fr", "barrel", NounClass::OTHER}, + // Some more French units missing gender: + // {"fr", "degree", NounClass::OTHER}, + {"fr", "square-meter", NounClass::MASCULINE}, // POWER + // {"fr", "terabyte", NounClass::OTHER}, // PREFIX, byte + // {"fr", "gigabyte", NounClass::OTHER}, // PREFIX, byte + // {"fr", "gigabit", NounClass::OTHER}, // PREFIX, bit + // {"fr", "megabyte", NounClass::OTHER}, // PREFIX, byte + // {"fr", "megabit", NounClass::OTHER}, // PREFIX, bit + // {"fr", "kilobyte", NounClass::OTHER}, // PREFIX, byte + // {"fr", "kilobit", NounClass::OTHER}, // PREFIX, bit + // {"fr", "byte", NounClass::OTHER}, + // {"fr", "bit", NounClass::OTHER}, + // {"fr", "volt", NounClass::OTHER}, + // {"fr", "watt", NounClass::OTHER}, + {"fr", "cubic-meter", NounClass::MASCULINE}, // POWER + + // gender-lacking builtins within compound units + {"de", "newton-meter-per-second", NounClass::MASCULINE}, + + // TODO(ICU-21494): determine whether list genders behave as follows, + // and implement proper getListGender support (covering more than just + // two genders): + // // gender rule for lists of people: de "neutral", fr "maleTaints" + // {"de", "day-and-hour-and-minute", NounClass::NEUTER}, + // {"de", "hour-and-minute", NounClass::FEMININE}, + // {"fr", "day-and-hour-and-minute", NounClass::MASCULINE}, + // {"fr", "hour-and-minute", NounClass::FEMININE}, + }; + + LocalizedNumberFormatter formatter; + FormattedNumber fn; + for (const TestCase &t : cases) { + formatter = NumberFormatter::with() + .unit(MeasureUnit::forIdentifier(t.unitIdentifier, status)) + .locale(Locale(t.locale)); + fn = formatter.formatDouble(1.1, status); + assertEquals(UnicodeString("Testing NounClass with default width, unit: ") + t.unitIdentifier + + ", locale: " + t.locale, + t.expectedNounClass, fn.getNounClass(status)); + status.assertSuccess(); + + formatter = NumberFormatter::with() + .unit(MeasureUnit::forIdentifier(t.unitIdentifier, status)) + .unitWidth(UNUM_UNIT_WIDTH_FULL_NAME) + .locale(Locale(t.locale)); + fn = formatter.formatDouble(1.1, status); + assertEquals(UnicodeString("Testing NounClass with UNUM_UNIT_WIDTH_FULL_NAME, unit: ") + + t.unitIdentifier + ", locale: " + t.locale, + t.expectedNounClass, fn.getNounClass(status)); + status.assertSuccess(); + } + + // Make sure getNounClass does not return garbage for languages without noun classes. + formatter = NumberFormatter::with().locale(Locale::getEnglish()); + fn = formatter.formatDouble(1.1, status); + status.assertSuccess(); + assertEquals("getNounClasses for a not supported language", NounClass::OTHER, + fn.getNounClass(status)); +} + void NumberFormatterApiTest::unitGender() { IcuTestErrorCode status(*this, "unitGender"); @@ -2975,6 +3315,28 @@ void NumberFormatterApiTest::roundingFraction() { Locale::getEnglish(), 1, "1"); + + assertFormatSingle( + u"Hide If Whole with Rounding Mode A (ICU-21881)", + u".00/w rounding-mode-floor", + u".00/w rounding-mode-floor", + NumberFormatter::with().precision(Precision::fixedFraction(2) + .trailingZeroDisplay(UNUM_TRAILING_ZERO_HIDE_IF_WHOLE)) + .roundingMode(UNUM_ROUND_FLOOR), + Locale::getEnglish(), + 3.009, + "3"); + + assertFormatSingle( + u"Hide If Whole with Rounding Mode B (ICU-21881)", + u".00/w rounding-mode-half-up", + u".00/w rounding-mode-half-up", + NumberFormatter::with().precision(Precision::fixedFraction(2) + .trailingZeroDisplay(UNUM_TRAILING_ZERO_HIDE_IF_WHOLE)) + .roundingMode(UNUM_ROUND_HALFUP), + Locale::getEnglish(), + 3.001, + "3"); } void NumberFormatterApiTest::roundingFigures() { @@ -2997,6 +3359,15 @@ void NumberFormatterApiTest::roundingFigures() { u"-98.8"); assertFormatSingle( + u"Fixed Significant at rounding boundary", + u"@@@", + u"@@@", + NumberFormatter::with().precision(Precision::fixedSignificantDigits(3)), + Locale::getEnglish(), + 9.999, + u"10.0"); + + assertFormatSingle( u"Fixed Significant Zero", u"@@@", u"@@@", @@ -3156,7 +3527,7 @@ void NumberFormatterApiTest::roundingFractionFigures() { assertFormatDescending( u"FracSig withSignificantDigits STRICT", u"precision-integer/@#s", - u"./@#", + u"./@#s", NumberFormatter::with().precision(Precision::maxFraction(0) .withSignificantDigits(1, 2, UNUM_ROUNDING_PRIORITY_STRICT)), Locale::getEnglish(), @@ -3180,7 +3551,7 @@ void NumberFormatterApiTest::roundingFractionFigures() { 1, u"1.00"); - // Trailing zeros are always retained: + // Trailing zeros follow the strategy that was chosen: assertFormatSingle( u"FracSig withSignificantDigits Trailing Zeros STRICT", u".0/@@@s", @@ -3189,7 +3560,7 @@ void NumberFormatterApiTest::roundingFractionFigures() { .withSignificantDigits(3, 3, UNUM_ROUNDING_PRIORITY_STRICT)), Locale::getEnglish(), 1, - u"1.00"); + u"1.0"); assertFormatSingle( u"FracSig withSignificantDigits at rounding boundary", @@ -3199,7 +3570,7 @@ void NumberFormatterApiTest::roundingFractionFigures() { .withSignificantDigits(3, 3, UNUM_ROUNDING_PRIORITY_STRICT)), Locale::getEnglish(), 9.99, - u"10.0"); + u"10"); assertFormatSingle( u"FracSig with Trailing Zero Display", @@ -3397,6 +3768,42 @@ void NumberFormatterApiTest::roundingOther() { u"0.0", u"0.0"); + assertFormatSingle( + u"Large integer increment", + u"precision-increment/24000000000000000000000", + u"precision-increment/24000000000000000000000", + NumberFormatter::with().precision(Precision::incrementExact(24, 21)), + Locale::getEnglish(), + 3.1e22, + u"24,000,000,000,000,000,000,000"); + + assertFormatSingle( + u"Quarter rounding", + u"precision-increment/250", + u"precision-increment/250", + NumberFormatter::with().precision(Precision::incrementExact(250, 0)), + Locale::getEnglish(), + 700, + u"750"); + + assertFormatSingle( + u"ECMA-402 limit", + u"precision-increment/.00000000000000000020", + u"precision-increment/.00000000000000000020", + NumberFormatter::with().precision(Precision::incrementExact(20, -20)), + Locale::getEnglish(), + 333e-20, + u"0.00000000000000000340"); + + assertFormatSingle( + u"ECMA-402 limit with increment = 1", + u"precision-increment/.00000000000000000001", + u"precision-increment/.00000000000000000001", + NumberFormatter::with().precision(Precision::incrementExact(1, -20)), + Locale::getEnglish(), + 4321e-21, + u"0.00000000000000000432"); + assertFormatDescending( u"Currency Standard", u"currency/CZK precision-currency-standard", @@ -3583,6 +3990,67 @@ void NumberFormatterApiTest::roundingIncrementRegressionTest() { assertEquals("ICU-21668", u"5,000", increment); } +void NumberFormatterApiTest::roundingPriorityCoverageTest() { + IcuTestErrorCode status(*this, "roundingPriorityCoverageTest"); + struct TestCase { + double input; + const char16_t* expectedRelaxed0113; + const char16_t* expectedStrict0113; + const char16_t* expectedRelaxed1133; + const char16_t* expectedStrict1133; + } cases[] = { + { 0.9999, u"1", u"1", u"1.00", u"1.0" }, + { 9.9999, u"10", u"10", u"10.0", u"10.0" }, + { 99.999, u"100", u"100", u"100.0", u"100" }, + { 999.99, u"1000", u"1000", u"1000.0", u"1000" }, + + { 0, u"0", u"0", u"0.00", u"0.0" }, + + { 9.876, u"9.88", u"9.9", u"9.88", u"9.9" }, + { 9.001, u"9", u"9", u"9.00", u"9.0" }, + }; + for (const auto& cas : cases) { + auto precisionRelaxed0113 = Precision::minMaxFraction(0, 1) + .withSignificantDigits(1, 3, UNUM_ROUNDING_PRIORITY_RELAXED); + auto precisionStrict0113 = Precision::minMaxFraction(0, 1) + .withSignificantDigits(1, 3, UNUM_ROUNDING_PRIORITY_STRICT); + auto precisionRelaxed1133 = Precision::minMaxFraction(1, 1) + .withSignificantDigits(3, 3, UNUM_ROUNDING_PRIORITY_RELAXED); + auto precisionStrict1133 = Precision::minMaxFraction(1, 1) + .withSignificantDigits(3, 3, UNUM_ROUNDING_PRIORITY_STRICT); + + auto messageBase = DoubleToUnicodeString(cas.input); + + auto check = [&]( + const char16_t* name, + const UnicodeString& expected, + const Precision& precision + ) { + assertEquals( + messageBase + name, + expected, + NumberFormatter::withLocale(Locale::getEnglish()) + .precision(precision) + .grouping(UNUM_GROUPING_OFF) + .formatDouble(cas.input, status) + .toString(status) + ); + }; + + check(u" Relaxed 0113", cas.expectedRelaxed0113, precisionRelaxed0113); + if (status.errIfFailureAndReset()) continue; + + check(u" Strict 0113", cas.expectedStrict0113, precisionStrict0113); + if (status.errIfFailureAndReset()) continue; + + check(u" Relaxed 1133", cas.expectedRelaxed1133, precisionRelaxed1133); + if (status.errIfFailureAndReset()) continue; + + check(u" Strict 1133", cas.expectedStrict1133, precisionStrict1133); + if (status.errIfFailureAndReset()) continue; + } +} + void NumberFormatterApiTest::grouping() { assertFormatDescendingBig( u"Western Grouping", @@ -5707,6 +6175,37 @@ void NumberFormatterApiTest::microPropsInternals() { assertEquals("Copy Assigned capacity", 4, copyAssigned.mixedMeasures.getCapacity()); } +void NumberFormatterApiTest::formatUnitsAliases() { + IcuTestErrorCode status(*this, "formatUnitsAliases"); + + struct TestCase { + const MeasureUnit measureUnit; + const UnicodeString expectedFormat; + } testCases[]{ + // Aliases + {MeasureUnit::getMilligramPerDeciliter(), u"2 milligrams per deciliter"}, + {MeasureUnit::getLiterPer100Kilometers(), u"2 liters per 100 kilometers"}, + {MeasureUnit::getPartPerMillion(), u"2 parts per million"}, + {MeasureUnit::getMillimeterOfMercury(), u"2 millimeters of mercury"}, + + // Replacements + {MeasureUnit::getMilligramOfglucosePerDeciliter(), u"2 milligrams per deciliter"}, + {MeasureUnit::forIdentifier("millimeter-ofhg", status), u"2 millimeters of mercury"}, + {MeasureUnit::forIdentifier("liter-per-100-kilometer", status), u"2 liters per 100 kilometers"}, + {MeasureUnit::forIdentifier("permillion", status), u"2 parts per million"}, + }; + + for (const auto &testCase : testCases) { + UnicodeString actualFormat = NumberFormatter::withLocale(icu::Locale::getEnglish()) + .unit(testCase.measureUnit) + .unitWidth(UNumberUnitWidth::UNUM_UNIT_WIDTH_FULL_NAME) + .formatDouble(2.0, status) + .toString(status); + + assertEquals("test unit aliases", testCase.expectedFormat, actualFormat); + } +} + /* For skeleton comparisons: this checks the toSkeleton output for `f` and for * `conciseSkeleton` against the normalized version of `uskeleton` - this does * not round-trip uskeleton itself. @@ -5882,7 +6381,7 @@ NumberFormatterApiTest::assertFormatSingle( // Only compare normalized skeletons: the tests need not provide the normalized forms. // Use the normalized form to construct the testing formatter to ensure no loss of info. UnicodeString normalized = NumberFormatter::forSkeleton(skeleton, status).toSkeleton(status); - assertEquals(message + ": Skeleton:", normalized, f.toSkeleton(status)); + assertEquals(message + ": Skeleton", normalized, f.toSkeleton(status)); LocalizedNumberFormatter l3 = NumberFormatter::forSkeleton(normalized, status).locale(locale); UnicodeString actual3 = l3.formatDouble(input, status).toString(status); assertEquals(message + ": Skeleton Path: '" + normalized + "': " + input, expected, actual3); diff --git a/Build/source/libs/icu/icu-src/source/test/intltest/numbertest_decimalquantity.cpp b/Build/source/libs/icu/icu-src/source/test/intltest/numbertest_decimalquantity.cpp index 7403dda7e75..87cd7707b55 100644 --- a/Build/source/libs/icu/icu-src/source/test/intltest/numbertest_decimalquantity.cpp +++ b/Build/source/libs/icu/icu-src/source/test/intltest/numbertest_decimalquantity.cpp @@ -33,6 +33,7 @@ void DecimalQuantityTest::runIndexedTest(int32_t index, UBool exec, const char * TESTCASE_AUTO(testNickelRounding); TESTCASE_AUTO(testScientificAndCompactSuppressedExponent); TESTCASE_AUTO(testSuppressedExponentUnchangedByInitialScaling); + TESTCASE_AUTO(testDecimalQuantityParseFormatRoundTrip); TESTCASE_AUTO_END; } @@ -101,8 +102,11 @@ void DecimalQuantityTest::testDecimalQuantityBehaviorStandalone() { assertToStringAndHealth(fq, u"<DecimalQuantity 2:-3 long 987654321E-6>"); fq.roundToInfinity(); assertToStringAndHealth(fq, u"<DecimalQuantity 2:-3 long 987654321E-6>"); - fq.roundToIncrement(0.005, RoundingMode::UNUM_ROUND_HALFEVEN, status); + fq.roundToIncrement(4, -3, RoundingMode::UNUM_ROUND_HALFEVEN, status); assertSuccess("Rounding to increment", status); + assertToStringAndHealth(fq, u"<DecimalQuantity 2:-3 long 987656E-3>"); + fq.roundToNickel(-3, RoundingMode::UNUM_ROUND_HALFEVEN, status); + assertSuccess("Rounding to nickel", status); assertToStringAndHealth(fq, u"<DecimalQuantity 2:-3 long 987655E-3>"); fq.roundToMagnitude(-2, RoundingMode::UNUM_ROUND_HALFEVEN, status); assertSuccess("Rounding to magnitude", status); @@ -317,7 +321,7 @@ void DecimalQuantityTest::testUseApproximateDoubleWhenAble() { {1.235, 3, RoundingMode::UNUM_ROUND_CEILING, true}}; UErrorCode status = U_ZERO_ERROR; - for (TestCase cas : cases) { + for (const TestCase& cas : cases) { DecimalQuantity fq; fq.setToDouble(cas.d); assertTrue("Should be using approximate double", !fq.isExplicitExactDouble()); @@ -623,7 +627,7 @@ void DecimalQuantityTest::testScientificAndCompactSuppressedExponent() { // test the actual computed values of the plural operands double expectedNOperand = cas.expectedDouble; - double expectedIOperand = cas.expectedLong; + double expectedIOperand = static_cast<double>(cas.expectedLong); double expectedEOperand = cas.expectedSuppressedScientificExponent; double expectedCOperand = cas.expectedSuppressedCompactExponent; double actualNOperand = dq.getPluralOperand(PLURAL_OPERAND_N); @@ -721,4 +725,52 @@ void DecimalQuantityTest::testSuppressedExponentUnchangedByInitialScaling() { } } + +void DecimalQuantityTest::testDecimalQuantityParseFormatRoundTrip() { + IcuTestErrorCode status(*this, "testDecimalQuantityParseFormatRoundTrip"); + + struct TestCase { + UnicodeString numberString; + } cases[] = { + // number string + { u"0" }, + { u"1" }, + { u"1.0" }, + { u"1.00" }, + { u"1.1" }, + { u"1.10" }, + { u"-1.10" }, + { u"0.0" }, + { u"1c5" }, + { u"1.0c5" }, + { u"1.1c5" }, + { u"1.10c5" }, + { u"0.00" }, + { u"0.1" }, + { u"1c-1" }, + { u"1.0c-1" } + }; + + for (const auto& cas : cases) { + UnicodeString numberString = cas.numberString; + + DecimalQuantity dq = DecimalQuantity::fromExponentString(numberString, status); + UnicodeString roundTrip = dq.toExponentString(); + + assertEquals("DecimalQuantity format(parse(s)) should equal original s", numberString, roundTrip); + } + + DecimalQuantity dq = DecimalQuantity::fromExponentString(u"1c0", status); + assertEquals("Zero ignored for visible exponent", + u"1", + dq.toExponentString()); + + dq.clear(); + dq = DecimalQuantity::fromExponentString(u"1.0c0", status); + assertEquals("Zero ignored for visible exponent", + u"1.0", + dq.toExponentString()); + +} + #endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/Build/source/libs/icu/icu-src/source/test/intltest/numbertest_range.cpp b/Build/source/libs/icu/icu-src/source/test/intltest/numbertest_range.cpp index 08e74df8f52..a47c675c974 100644 --- a/Build/source/libs/icu/icu-src/source/test/intltest/numbertest_range.cpp +++ b/Build/source/libs/icu/icu-src/source/test/intltest/numbertest_range.cpp @@ -811,6 +811,28 @@ void NumberRangeFormatterTest::testFieldPositions() { expectedFieldPositions, UPRV_LENGTHOF(expectedFieldPositions)); } + + { + const char16_t* message = u"Field position with approximately sign"; + const char16_t* expectedString = u"~-100"; + FormattedNumberRange result = assertFormattedRangeEquals( + message, + NumberRangeFormatter::withLocale("en-us"), + -100, + -100, + expectedString); + static const UFieldPositionWithCategory expectedFieldPositions[] = { + // category, field, begin index, end index + {UFIELD_CATEGORY_NUMBER, UNUM_APPROXIMATELY_SIGN_FIELD, 0, 1}, + {UFIELD_CATEGORY_NUMBER, UNUM_SIGN_FIELD, 1, 2}, + {UFIELD_CATEGORY_NUMBER, UNUM_INTEGER_FIELD, 2, 5}}; + checkMixedFormattedValue( + message, + result, + expectedString, + expectedFieldPositions, + UPRV_LENGTHOF(expectedFieldPositions)); + } } void NumberRangeFormatterTest::testCopyMove() { diff --git a/Build/source/libs/icu/icu-src/source/test/intltest/numfmtst.cpp b/Build/source/libs/icu/icu-src/source/test/intltest/numfmtst.cpp index 011cc32dd34..7f271cb3f66 100644 --- a/Build/source/libs/icu/icu-src/source/test/intltest/numfmtst.cpp +++ b/Build/source/libs/icu/icu-src/source/test/intltest/numfmtst.cpp @@ -3357,6 +3357,7 @@ void NumberFormatTest::TestRoundingPattern() { void NumberFormatTest::checkRounding(DecimalFormat* df, double base, int iterations, double increment) { df->setRoundingIncrement(increment); + assertEquals("Rounding increment round-trip", increment, df->getRoundingIncrement()); double lastParsed=INT32_MIN; //Intger.MIN_VALUE for (int i=-iterations; i<=iterations;i++) { double iValue=base+(increment*(i*0.1)); @@ -4889,9 +4890,9 @@ NumberFormatTest::TestParseCurrencyInUCurr() { "Peruvian soles1.00", "Peruvian sol (1863\\u20131965)1.00", "Peruvian soles (1863\\u20131965)1.00", - "Philippine Piso1.00", - "Philippine piso1.00", - "Philippine pisos1.00", + "Philippine Peso1.00", + "Philippine peso1.00", + "Philippine pesos1.00", "Platinum1.00", "Platinum1.00", "Polish Zloty (1950\\u20131995)1.00", @@ -5826,9 +5827,9 @@ NumberFormatTest::TestParseCurrencyInUCurr() { "1.00 Peruvian soles random", "1.00 Peruvian sol (1863\\u20131965) random", "1.00 Peruvian soles (1863\\u20131965) random", - "1.00 Philippine Piso random", - "1.00 Philippine piso random", - "1.00 Philippine pisos random", + "1.00 Philippine Peso random", + "1.00 Philippine peso random", + "1.00 Philippine pesos random", "1.00 Platinum random", "1.00 Platinum random", "1.00 Polish Zloty (1950\\u20131995) random", diff --git a/Build/source/libs/icu/icu-src/source/test/intltest/plurults.cpp b/Build/source/libs/icu/icu-src/source/test/intltest/plurults.cpp index 9131d370317..54cc77a0c9e 100644 --- a/Build/source/libs/icu/icu-src/source/test/intltest/plurults.cpp +++ b/Build/source/libs/icu/icu-src/source/test/intltest/plurults.cpp @@ -919,7 +919,7 @@ PluralRulesTest::testDoubleValue() { const int64_t inputNum = cas.inputNum; const double expVal = cas.expVal; - FixedDecimal fd(inputNum); + FixedDecimal fd(static_cast<double>(inputNum)); UnicodeString message(u"FixedDecimal::doubleValue() for" + Int64ToUnicodeString(inputNum)); assertEquals(message, expVal, fd.doubleValue()); } @@ -963,7 +963,7 @@ PluralRulesTest::testLongValue() { const int64_t inputNum = cas.inputNum; const int64_t expVal = cas.expVal; - FixedDecimal fd(inputNum); + FixedDecimal fd(static_cast<double>(inputNum)); UnicodeString message(u"FixedDecimal::longValue() for" + Int64ToUnicodeString(inputNum)); assertEquals(message, expVal, fd.longValue()); } @@ -982,7 +982,7 @@ PluralRulesTest::testLongValue() { const double inputNum = cas.inputNum; const int64_t expVal = cas.expVal; - FixedDecimal fd(inputNum); + FixedDecimal fd(static_cast<double>(inputNum)); UnicodeString message(u"FixedDecimal::longValue() for" + DoubleToUnicodeString(inputNum)); assertEquals(message, expVal, fd.longValue()); } diff --git a/Build/source/libs/icu/icu-src/source/test/intltest/rbbitst.cpp b/Build/source/libs/icu/icu-src/source/test/intltest/rbbitst.cpp index 73d4393843b..69db5db018c 100644 --- a/Build/source/libs/icu/icu-src/source/test/intltest/rbbitst.cpp +++ b/Build/source/libs/icu/icu-src/source/test/intltest/rbbitst.cpp @@ -149,6 +149,10 @@ void RBBITest::runIndexedTest( int32_t index, UBool exec, const char* &name, cha TESTCASE_AUTO(TestTraceCreateLineNormal); TESTCASE_AUTO(TestTraceCreateLineLoose); TESTCASE_AUTO(TestTraceCreateLineStrict); + TESTCASE_AUTO(TestTraceCreateLineNormalPhrase); + TESTCASE_AUTO(TestTraceCreateLineLoosePhrase); + TESTCASE_AUTO(TestTraceCreateLineStrictPhrase); + TESTCASE_AUTO(TestTraceCreateLinePhrase); TESTCASE_AUTO(TestTraceCreateBreakEngine); #endif @@ -5144,7 +5148,7 @@ void RBBITest::TestTraceCreateLine(void) { LocalPointer<BreakIterator> brkitr( BreakIterator::createLineInstance("zh-CN", status)); status.errIfFailureAndReset(); - assertTestTraceResult(UTRACE_UBRK_CREATE_LINE, ""); + assertTestTraceResult(UTRACE_UBRK_CREATE_LINE, "line"); } void RBBITest::TestTraceCreateLineStrict(void) { @@ -5153,7 +5157,7 @@ void RBBITest::TestTraceCreateLineStrict(void) { LocalPointer<BreakIterator> brkitr( BreakIterator::createLineInstance("zh-CN-u-lb-strict", status)); status.errIfFailureAndReset(); - assertTestTraceResult(UTRACE_UBRK_CREATE_LINE, "strict"); + assertTestTraceResult(UTRACE_UBRK_CREATE_LINE, "line_strict"); } void RBBITest::TestTraceCreateLineNormal(void) { @@ -5162,7 +5166,7 @@ void RBBITest::TestTraceCreateLineNormal(void) { LocalPointer<BreakIterator> brkitr( BreakIterator::createLineInstance("zh-CN-u-lb-normal", status)); status.errIfFailureAndReset(); - assertTestTraceResult(UTRACE_UBRK_CREATE_LINE, "normal"); + assertTestTraceResult(UTRACE_UBRK_CREATE_LINE, "line_normal"); } void RBBITest::TestTraceCreateLineLoose(void) { @@ -5171,7 +5175,43 @@ void RBBITest::TestTraceCreateLineLoose(void) { LocalPointer<BreakIterator> brkitr( BreakIterator::createLineInstance("zh-CN-u-lb-loose", status)); status.errIfFailureAndReset(); - assertTestTraceResult(UTRACE_UBRK_CREATE_LINE, "loose"); + assertTestTraceResult(UTRACE_UBRK_CREATE_LINE, "line_loose"); +} + +void RBBITest::TestTraceCreateLineLoosePhrase(void) { + SetupTestTrace(); + IcuTestErrorCode status(*this, "TestTraceCreateLineLoosePhrase"); + LocalPointer<BreakIterator> brkitr( + BreakIterator::createLineInstance("ja-u-lb-loose-lw-phrase", status)); + status.errIfFailureAndReset(); + assertTestTraceResult(UTRACE_UBRK_CREATE_LINE, "line_loose_phrase"); +} + +void RBBITest::TestTraceCreateLineNormalPhrase(void) { + SetupTestTrace(); + IcuTestErrorCode status(*this, "TestTraceCreateLineNormalPhrase"); + LocalPointer<BreakIterator> brkitr( + BreakIterator::createLineInstance("ja-u-lb-normal-lw-phrase", status)); + status.errIfFailureAndReset(); + assertTestTraceResult(UTRACE_UBRK_CREATE_LINE, "line_normal_phrase"); +} + +void RBBITest::TestTraceCreateLineStrictPhrase(void) { + SetupTestTrace(); + IcuTestErrorCode status(*this, "TestTraceCreateLineStrictPhrase"); + LocalPointer<BreakIterator> brkitr( + BreakIterator::createLineInstance("ja-u-lb-strict-lw-phrase", status)); + status.errIfFailureAndReset(); + assertTestTraceResult(UTRACE_UBRK_CREATE_LINE, "line_strict_phrase"); +} + +void RBBITest::TestTraceCreateLinePhrase(void) { + SetupTestTrace(); + IcuTestErrorCode status(*this, "TestTraceCreateLinePhrase"); + LocalPointer<BreakIterator> brkitr( + BreakIterator::createLineInstance("ja-u-lw-phrase", status)); + status.errIfFailureAndReset(); + assertTestTraceResult(UTRACE_UBRK_CREATE_LINE, "line_phrase"); } void RBBITest::TestTraceCreateBreakEngine(void) { diff --git a/Build/source/libs/icu/icu-src/source/test/intltest/rbbitst.h b/Build/source/libs/icu/icu-src/source/test/intltest/rbbitst.h index acb3e82bbec..d5d52119bc0 100644 --- a/Build/source/libs/icu/icu-src/source/test/intltest/rbbitst.h +++ b/Build/source/libs/icu/icu-src/source/test/intltest/rbbitst.h @@ -105,6 +105,10 @@ public: void TestTraceCreateLineNormal(); void TestTraceCreateLineStrict(); void TestTraceCreateLineLoose(); + void TestTraceCreateLineNormalPhrase(); + void TestTraceCreateLineLoosePhrase(); + void TestTraceCreateLineStrictPhrase(); + void TestTraceCreateLinePhrase(); void TestTraceCreateBreakEngine(); #endif diff --git a/Build/source/libs/icu/icu-src/source/test/intltest/strcase.cpp b/Build/source/libs/icu/icu-src/source/test/intltest/strcase.cpp index 006bcd64ed3..b5eff9f0af8 100644 --- a/Build/source/libs/icu/icu-src/source/test/intltest/strcase.cpp +++ b/Build/source/libs/icu/icu-src/source/test/intltest/strcase.cpp @@ -51,6 +51,7 @@ public: void *iter, const char *localeID, uint32_t options); void TestCasing(); void TestTitleOptions(); + void TestDutchTitle(); void TestFullCaseFoldingIterator(); void TestGreekUpper(); void TestArmenian(); @@ -95,6 +96,7 @@ StringCaseTest::runIndexedTest(int32_t index, UBool exec, const char *&name, cha #if !UCONFIG_NO_BREAK_ITERATION && !UCONFIG_NO_FILE_IO && !UCONFIG_NO_LEGACY_CONVERSION TESTCASE_AUTO(TestCasing); TESTCASE_AUTO(TestTitleOptions); + TESTCASE_AUTO(TestDutchTitle); #endif TESTCASE_AUTO(TestFullCaseFoldingIterator); TESTCASE_AUTO(TestGreekUpper); @@ -451,6 +453,7 @@ StringCaseTest::TestCasingImpl(const UnicodeString &input, } if(result!=output) { dataerrln("error: UnicodeString.%s() got a wrong result for a test case from casing.res", name); + dataerrln(UnicodeString("input = [") + input + "], expected = [" + output + "], actual = [" + result + "]"); } #if !UCONFIG_NO_BREAK_ITERATION if(whichCase==TEST_TITLE && options==0) { @@ -667,6 +670,106 @@ StringCaseTest::TestTitleOptions() { #endif } +#if !UCONFIG_NO_BREAK_ITERATION +void StringCaseTest::TestDutchTitle() { + IcuTestErrorCode errorCode(*this, "TestDutchTitle"); + + Locale nl("nl"); // Dutch + LocalPointer<BreakIterator> iter( + BreakIterator::createWordInstance(nl, errorCode)); + + // Dutch titlecase check in English + TestCasingImpl( + u"ijssel igloo IJMUIDEN", + u"Ijssel Igloo Ijmuiden", + TEST_TITLE, + nullptr, + "en", + 0); + + // Dutch titlecase check in Dutch + TestCasingImpl( + u"ijssel igloo IJMUIDEN", + u"IJssel Igloo IJmuiden", + TEST_TITLE, + nullptr, + "nl", + 0); + + // Dutch titlecase check in Dutch with nolowercase option + if (U_SUCCESS(errorCode)) { + iter->setText(u"ijssel igloo IjMUIdEN iPoD ijenough"); + TestCasingImpl( + u"ijssel igloo IjMUIdEN iPoD ijenough", + u"IJssel Igloo IJMUIdEN IPoD IJenough", + TEST_TITLE, + nullptr, + "nl", + U_TITLECASE_NO_LOWERCASE); + } + + errorCode.reset(); + + // Accented IJ testing + + struct dutchTitleTestCase { + const UnicodeString input; + const UnicodeString expectedFull; + const UnicodeString expectedOnlyChanged; + } dutchTitleTestCases[] = { + // input, expectedFull, expectedOnlyChanged + {u"ij", u"IJ", u"IJ"}, + {u"IJ", u"IJ", u""}, + {u"íj́", u"ÍJ́", u"ÍJ"}, + {u"ÍJ́", u"ÍJ́", u""}, + {u"íJ́", u"ÍJ́", u"Í"}, + {u"Ij́", u"Ij́", u""}, + {u"ij́", u"Ij́", u"I"}, + {u"ïj́", u"Ïj́", u"Ï"}, + {u"íj\u0308", u"Íj\u0308", u"Í"}, + {u"íj́\U0001D16E", u"Íj́\U0001D16E", u"Í"}, + {u"íj\u1ABE", u"Íj\u1ABE", u"Í"}, + + {u"ijabc", u"IJabc", u"IJ"}, + {u"IJabc", u"IJabc", u""}, + {u"íj́abc", u"ÍJ́abc", u"ÍJ"}, + {u"ÍJ́abc", u"ÍJ́abc", u""}, + {u"íJ́abc", u"ÍJ́abc", u"Í"}, + {u"Ij́abc", u"Ij́abc", u""}, + {u"ij́abc", u"Ij́abc", u"I"}, + {u"ïj́abc", u"Ïj́abc", u"Ï"}, + {u"íjabc\u0308", u"Íjabc\u0308", u"Í"}, + {u"íj́abc\U0001D16E", u"ÍJ́abc\U0001D16E", u"ÍJ"}, + {u"íjabc\u1ABE", u"Íjabc\u1ABE", u"Í"}, + + // Bug ICU-21919 + {u"Í", u"Í", u""}, + }; + + for (const auto& cas : dutchTitleTestCases) { + const UnicodeString &input = cas.input; + const UnicodeString &expectedFull = cas.expectedFull; + const UnicodeString &expectedOnlyChanged = cas.expectedOnlyChanged; + + for (const auto& isOnlyChanged : {true, false}) { + uint32_t testOptions = U_TITLECASE_NO_LOWERCASE + | (isOnlyChanged ? U_OMIT_UNCHANGED_TEXT : 0); + + const UnicodeString &expected = isOnlyChanged ? expectedOnlyChanged : expectedFull; + + TestCasingImpl( + input, + expected, + TEST_TITLE, + nullptr, + "nl", + testOptions + ); + } + } +} +#endif + void StringCaseTest::TestFullCaseFoldingIterator() { UnicodeString ffi=UNICODE_STRING_SIMPLE("ffi"); diff --git a/Build/source/libs/icu/icu-src/source/test/intltest/tmsgfmt.cpp b/Build/source/libs/icu/icu-src/source/test/intltest/tmsgfmt.cpp index e55aa8fbe37..66f49822217 100644 --- a/Build/source/libs/icu/icu-src/source/test/intltest/tmsgfmt.cpp +++ b/Build/source/libs/icu/icu-src/source/test/intltest/tmsgfmt.cpp @@ -2051,7 +2051,7 @@ void TestMessageFormat::TestMessageFormatDateSkeleton() { UDate date = LocaleTest::date(2021-1900, UCAL_NOVEMBER, 23, 16, 42, 55); doTheRealDateTimeSkeletonTesting(date, u"{0,date,::MMMMd}", "en", u"November 23", status); - doTheRealDateTimeSkeletonTesting(date, u"{0,date,::yMMMMdjm}", "en", u"November 23, 2021, 4:42 PM", status); + doTheRealDateTimeSkeletonTesting(date, u"{0,date,::yMMMMdjm}", "en", u"November 23, 2021 at 4:42 PM", status); doTheRealDateTimeSkeletonTesting(date, u"{0,date, :: yMMMMd }", "en", u"November 23, 2021", status); doTheRealDateTimeSkeletonTesting(date, u"{0,date,::yMMMMd}", "fr", u"23 novembre 2021", status); doTheRealDateTimeSkeletonTesting(date, u"Expiration: {0,date,::yMMM}!", "en", u"Expiration: Nov 2021!", status); @@ -2065,7 +2065,7 @@ void TestMessageFormat::TestMessageFormatTimeSkeleton() { UDate date = LocaleTest::date(2021-1900, UCAL_NOVEMBER, 23, 16, 42, 55); doTheRealDateTimeSkeletonTesting(date, u"{0,time,::MMMMd}", "en", u"November 23", status); - doTheRealDateTimeSkeletonTesting(date, u"{0,time,::yMMMMdjm}", "en", u"November 23, 2021, 4:42 PM", status); + doTheRealDateTimeSkeletonTesting(date, u"{0,time,::yMMMMdjm}", "en", u"November 23, 2021 at 4:42 PM", status); doTheRealDateTimeSkeletonTesting(date, u"{0,time, :: yMMMMd }", "en", u"November 23, 2021", status); doTheRealDateTimeSkeletonTesting(date, u"{0,time,::yMMMMd}", "fr", u"23 novembre 2021", status); doTheRealDateTimeSkeletonTesting(date, u"Expiration: {0,time,::yMMM}!", "en", u"Expiration: Nov 2021!", status); diff --git a/Build/source/libs/icu/icu-src/source/test/intltest/transtst.cpp b/Build/source/libs/icu/icu-src/source/test/intltest/transtst.cpp index 8a81b5b3377..aaf283f7a4e 100644 --- a/Build/source/libs/icu/icu-src/source/test/intltest/transtst.cpp +++ b/Build/source/libs/icu/icu-src/source/test/intltest/transtst.cpp @@ -3639,7 +3639,7 @@ void TransliteratorTest::TestIncrementalProgress(void) { Transliterator *t = Transliterator::createInstance(id, UTRANS_FORWARD, err, status); if (U_FAILURE(status)) { - dataerrln((UnicodeString)"FAIL: Could not create " + id); + dataerrln((UnicodeString)"FAIL: Could not create " + id + ", status " + u_errorName(status)); delete t; continue; } @@ -3654,19 +3654,38 @@ void TransliteratorTest::TestIncrementalProgress(void) { // 1. Devanagari-Arabic // 2. Any-*/BGN // 2a. Any-*/BGN_1981 - // 3. Any-*/UNGEGN - // 4. Any-*/MNS - // If UCONFIG_NO_BREAK_ITERATION is on, Latin-Thai is also not expected to work. + // 3. Any-*/MNS + // + // 4. If UCONFIG_NO_BREAK_ITERATION is on, Latin-Thai is also not expected to work. + // + // The following are direction="both" transforms with variants, inverting the Any-Xxxx/Variant for + // any of these does not work; see ICU-21911 (not sure whether this is intentional or an ICU bug). + // Unfortunately we do not easily have the info at this point as to whether the original transform + // had direction="both" specified. + // 5. Any-*/UNGEGN + // 6. Any-Ethiopic/* + // 7. Any-Braille/* + // 8. Any-*/Gurage_2013 + // 9. Any-*/Gutgarts + // 10. Any-*/Tekie_Alibekit + // 11. Any-*/Xaleget + // if ( id.compare((UnicodeString)"Devanagari-Arabic/") != 0 && !(id.startsWith((UnicodeString)"Any-") && - (id.endsWith((UnicodeString)"/BGN") || id.endsWith((UnicodeString)"/BGN_1981") || id.endsWith((UnicodeString)"/UNGEGN") || id.endsWith((UnicodeString)"/MNS")) + (id.endsWith((UnicodeString)"/BGN") || id.endsWith((UnicodeString)"/BGN_1981") || id.endsWith((UnicodeString)"/MNS")) ) #if UCONFIG_NO_BREAK_ITERATION && id.compare((UnicodeString)"Latin-Thai/") != 0 #endif + && !(logKnownIssue("21911", "ICU4C cannot create inverse of Any-Xxxx/Variant transform created from both-direction transform") && + id.startsWith((UnicodeString)"Any-") && + (id.endsWith((UnicodeString)"/UNGEGN") || id.startsWith((UnicodeString)"Any-Ethiopic/") || id.startsWith((UnicodeString)"Any-Braille/") || + id.endsWith((UnicodeString)"/Gurage_2013") || id.endsWith((UnicodeString)"/Gutgarts") || id.endsWith((UnicodeString)"/Tekie_Alibekit") || + id.endsWith((UnicodeString)"/Xaleget")) + ) ) { - errln((UnicodeString)"FAIL: Could not create inverse of " + id); + errln((UnicodeString)"FAIL: Could not create inverse of " + id + ", status " + u_errorName(status)); } delete t; delete inv; diff --git a/Build/source/libs/icu/icu-src/source/test/intltest/tztest.cpp b/Build/source/libs/icu/icu-src/source/test/intltest/tztest.cpp index 0d58bab197d..5ae9ae7175c 100644 --- a/Build/source/libs/icu/icu-src/source/test/intltest/tztest.cpp +++ b/Build/source/libs/icu/icu-src/source/test/intltest/tztest.cpp @@ -906,7 +906,7 @@ void TimeZoneTest::TestShortZoneIDs() {"AET", 600, TRUE}, // ICU Link - Australia/Sydney {"SST", 660, FALSE}, // ICU Link - Pacific/Guadalcanal {"NST", 720, TRUE}, // ICU Link - Pacific/Auckland - {"MIT", 780, TRUE}, // ICU Link - Pacific/Apia + {"MIT", 780, FALSE}, // ICU Link - Pacific/Apia {"Etc/Unknown", 0, FALSE}, // CLDR @@ -2036,12 +2036,20 @@ void TimeZoneTest::TestCanonicalIDAPI() { void TimeZoneTest::TestCanonicalID() { - // Some canonical IDs in CLDR are defined as "Link" - // in Olson tzdata. + // Olson (IANA) tzdata used to have very few "Link"s long time ago. + // This test case was written when most of CLDR canonical time zones are + // defined as independent "Zone" in the TZ database. + // Since then, the TZ maintainer found some historic rules in mid 20th century + // were not really reliable, and many zones are now sharing rules. + // As of TZ database release 2022a, there are quite a lot of zones defined + // by "Link" to another zone, so the exception table below becomes really + // big. It might be still useful to make sure CLDR zone aliases are consistent + // with zone rules. static const struct { - const char *alias; - const char *zone; + const char *alias; // link-from + const char *zone; // link-to (A zone ID with "Zone" rule) } excluded1[] = { + {"Africa/Accra", "Africa/Abidjan"}, {"Africa/Addis_Ababa", "Africa/Nairobi"}, {"Africa/Asmera", "Africa/Nairobi"}, {"Africa/Bamako", "Africa/Abidjan"}, @@ -2076,35 +2084,43 @@ void TimeZoneTest::TestCanonicalID() { {"Africa/Ouagadougou", "Africa/Abidjan"}, {"Africa/Porto-Novo", "Africa/Lagos"}, {"Africa/Sao_Tome", "Africa/Abidjan"}, - {"America/Antigua", "America/Port_of_Spain"}, - {"America/Anguilla", "America/Port_of_Spain"}, + {"America/Antigua", "America/Puerto_Rico"}, + {"America/Anguilla", "America/Puerto_Rico"}, + {"America/Aruba", "America/Puerto_Rico"}, + {"America/Atikokan", "America/Panama"}, + {"America/Blanc-Sablon", "America/Puerto_Rico"}, {"America/Cayman", "America/Panama"}, {"America/Coral_Harbour", "America/Panama"}, - {"America/Curacao", "America/Aruba"}, - {"America/Dominica", "America/Port_of_Spain"}, - {"America/Grenada", "America/Port_of_Spain"}, - {"America/Guadeloupe", "America/Port_of_Spain"}, - {"America/Kralendijk", "America/Aruba"}, - {"America/Lower_Princes", "America/Aruba"}, - {"America/Marigot", "America/Port_of_Spain"}, - {"America/Montserrat", "America/Port_of_Spain"}, + {"America/Creston", "America/Phoenix"}, + {"America/Curacao", "America/Puerto_Rico"}, + {"America/Dominica", "America/Puerto_Rico"}, + {"America/Grenada", "America/Puerto_Rico"}, + {"America/Guadeloupe", "America/Puerto_Rico"}, + {"America/Kralendijk", "America/Puerto_Rico"}, + {"America/Lower_Princes", "America/Puerto_Rico"}, + {"America/Marigot", "America/Puerto_Rico"}, + {"America/Montreal", "America/Toronto"}, + {"America/Montserrat", "America/Puerto_Rico"}, + {"America/Nassau", "America/Toronto"}, + {"America/Port_of_Spain", "America/Puerto_Rico"}, {"America/Santa_Isabel", "America/Tijuana"}, {"America/Shiprock", "America/Denver"}, - {"America/St_Barthelemy", "America/Port_of_Spain"}, - {"America/St_Kitts", "America/Port_of_Spain"}, - {"America/St_Lucia", "America/Port_of_Spain"}, - {"America/St_Thomas", "America/Port_of_Spain"}, - {"America/St_Vincent", "America/Port_of_Spain"}, - {"America/Toronto", "America/Montreal"}, - {"America/Tortola", "America/Port_of_Spain"}, + {"America/St_Barthelemy", "America/Puerto_Rico"}, + {"America/St_Kitts", "America/Puerto_Rico"}, + {"America/St_Lucia", "America/Puerto_Rico"}, + {"America/St_Thomas", "America/Puerto_Rico"}, + {"America/St_Vincent", "America/Puerto_Rico"}, + {"America/Tortola", "America/Puerto_Rico"}, {"America/Virgin", "America/Puerto_Rico"}, + {"Antarctica/DumontDUrville", "Pacific/Port_Moresby"}, {"Antarctica/South_Pole", "Antarctica/McMurdo"}, + {"Antarctica/Syowa", "Asia/Riyadh"}, {"Arctic/Longyearbyen", "Europe/Oslo"}, - {"Asia/Kuwait", "Asia/Aden"}, + {"Asia/Aden", "Asia/Riyadh"}, + {"Asia/Kuwait", "Asia/Riyadh"}, {"Asia/Muscat", "Asia/Dubai"}, {"Asia/Phnom_Penh", "Asia/Bangkok"}, {"Asia/Qatar", "Asia/Bahrain"}, - {"Asia/Riyadh", "Asia/Aden"}, {"Asia/Vientiane", "Asia/Bangkok"}, {"Atlantic/Jan_Mayen", "Europe/Oslo"}, {"Atlantic/St_Helena", "Africa/Abidjan"}, diff --git a/Build/source/libs/icu/icu-src/source/test/intltest/units_test.cpp b/Build/source/libs/icu/icu-src/source/test/intltest/units_test.cpp index c65a5e03229..ca41e3b0d03 100644 --- a/Build/source/libs/icu/icu-src/source/test/intltest/units_test.cpp +++ b/Build/source/libs/icu/icu-src/source/test/intltest/units_test.cpp @@ -325,6 +325,12 @@ void UnitsTest::testConverter() { // Fuel Consumption {"cubic-meter-per-meter", "mile-per-gallon", 2.1383143939394E-6, 1.1}, {"cubic-meter-per-meter", "mile-per-gallon", 2.6134953703704E-6, 0.9}, + {"liter-per-100-kilometer", "mile-per-gallon", 6.6, 35.6386}, + {"liter-per-100-kilometer", "mile-per-gallon", 0, uprv_getInfinity()}, + {"mile-per-gallon", "liter-per-100-kilometer", 0, uprv_getInfinity()}, + {"mile-per-gallon", "liter-per-100-kilometer", uprv_getInfinity(), 0}, + // We skip testing -Inf, because the inverse conversion loses the sign: + // {"mile-per-gallon", "liter-per-100-kilometer", -uprv_getInfinity(), 0}, // Test Aliases // Alias is just another name to the same unit. Therefore, converting @@ -348,54 +354,42 @@ void UnitsTest::testConverter() { continue; } + double maxDelta = 1e-6 * uprv_fabs(testCase.expectedValue); + if (testCase.expectedValue == 0) { + maxDelta = 1e-12; + } + double inverseMaxDelta = 1e-6 * uprv_fabs(testCase.inputValue); + if (testCase.inputValue == 0) { + inverseMaxDelta = 1e-12; + } + ConversionRates conversionRates(status); if (status.errIfFailureAndReset("conversionRates(status)")) { continue; } + UnitsConverter converter(source, target, conversionRates, status); if (status.errIfFailureAndReset("UnitsConverter(<%s>, <%s>, ...)", testCase.source, testCase.target)) { continue; } - - double maxDelta = 1e-6 * uprv_fabs(testCase.expectedValue); - if (testCase.expectedValue == 0) { - maxDelta = 1e-12; - } assertEqualsNear(UnicodeString("testConverter: ") + testCase.source + " to " + testCase.target, testCase.expectedValue, converter.convert(testCase.inputValue), maxDelta); - - maxDelta = 1e-6 * uprv_fabs(testCase.inputValue); - if (testCase.inputValue == 0) { - maxDelta = 1e-12; - } assertEqualsNear( UnicodeString("testConverter inverse: ") + testCase.target + " back to " + testCase.source, - testCase.inputValue, converter.convertInverse(testCase.expectedValue), maxDelta); + testCase.inputValue, converter.convertInverse(testCase.expectedValue), inverseMaxDelta); - - // TODO: Test UnitsConverter created using CLDR separately. // Test UnitsConverter created by CLDR unit identifiers UnitsConverter converter2(testCase.source, testCase.target, status); if (status.errIfFailureAndReset("UnitsConverter(<%s>, <%s>, ...)", testCase.source, testCase.target)) { continue; } - - maxDelta = 1e-6 * uprv_fabs(testCase.expectedValue); - if (testCase.expectedValue == 0) { - maxDelta = 1e-12; - } assertEqualsNear(UnicodeString("testConverter2: ") + testCase.source + " to " + testCase.target, testCase.expectedValue, converter2.convert(testCase.inputValue), maxDelta); - - maxDelta = 1e-6 * uprv_fabs(testCase.inputValue); - if (testCase.inputValue == 0) { - maxDelta = 1e-12; - } assertEqualsNear( UnicodeString("testConverter2 inverse: ") + testCase.target + " back to " + testCase.source, - testCase.inputValue, converter2.convertInverse(testCase.expectedValue), maxDelta); + testCase.inputValue, converter2.convertInverse(testCase.expectedValue), inverseMaxDelta); } } @@ -647,6 +641,16 @@ void UnitsTest::testComplexUnitsConverter() { Measure(2.1, MeasureUnit::createMeter(status), status)}, 2, 0.001}, + + // Negative numbers + {"Negative number conversion", + "yard", + "mile-and-yard", + -1800, + {Measure(-1, MeasureUnit::createMile(status), status), + Measure(-40, MeasureUnit::createYard(status), status)}, + 2, + 1e-10}, }; status.assertSuccess(); @@ -694,11 +698,7 @@ void UnitsTest::testComplexUnitsConverter() { ComplexUnitsConverter converter2( testCase.input, testCase.output, status); testATestCase(converter2, "ComplexUnitsConverter #1 " , testCase); } - - status.assertSuccess(); - - // TODO(icu-units#63): test negative numbers! } void UnitsTest::testComplexUnitsConverterSorting() { diff --git a/Build/source/libs/icu/icu-src/source/test/intltest/ustrtest.cpp b/Build/source/libs/icu/icu-src/source/test/intltest/ustrtest.cpp index cd9751d761b..309a29713d7 100644 --- a/Build/source/libs/icu/icu-src/source/test/intltest/ustrtest.cpp +++ b/Build/source/libs/icu/icu-src/source/test/intltest/ustrtest.cpp @@ -1653,6 +1653,16 @@ UnicodeStringTest::TestBogus() { if(test1>=test2 || !(test2>test1) || test1.compare(test2)>=0 || !(test2.compare(test1)>0)) { errln("bogus<empty failed"); } + + // test that copy constructor of bogus is bogus & clone of bogus is nullptr + { + test3.setToBogus(); + UnicodeString test3Copy(test3); + UnicodeString *test3Clone = test3.clone(); + assertTrue(WHERE, test3.isBogus()); + assertTrue(WHERE, test3Copy.isBogus()); + assertTrue(WHERE, test3Clone == nullptr); + } } // StringEnumeration ------------------------------------------------------- *** @@ -2354,7 +2364,7 @@ void UnicodeStringTest::TestLargeAppend() { } else if (total <= INT32_MAX) { // Check that a string of exactly the maximum size works UnicodeString str2; - int32_t remain = INT32_MAX - total; + int32_t remain = static_cast<int32_t>(INT32_MAX - total); char16_t *buf2 = str2.getBuffer(remain); if (buf2 == nullptr) { // if somehow memory allocation fail, return the test diff --git a/Build/source/libs/icu/icu-src/source/test/iotest/strtst.c b/Build/source/libs/icu/icu-src/source/test/iotest/strtst.c index ee67b4c3ab1..3ffec2b25dc 100644 --- a/Build/source/libs/icu/icu-src/source/test/iotest/strtst.c +++ b/Build/source/libs/icu/icu-src/source/test/iotest/strtst.c @@ -315,9 +315,10 @@ static void TestLocalizedString(void) { #if !UCONFIG_NO_FORMATTING #define Test_u_snprintf(limit, format, value, expectedSize, expectedStr) UPRV_BLOCK_MACRO_BEGIN { \ u_uastrncpy(testStr, "xxxxxxxxxxxxxx", UPRV_LENGTHOF(testStr));\ - size = u_snprintf(testStr, limit, format, value);\ + size = u_snprintf(0, 0, format, value);\ + written = u_snprintf(testStr, limit, format, value);\ u_austrncpy(cTestResult, testStr, UPRV_LENGTHOF(cTestResult));\ - if (size != expectedSize || strcmp(cTestResult, expectedStr) != 0) {\ + if (size != written || size != expectedSize || strcmp(cTestResult, expectedStr) != 0) {\ log_err("Unexpected formatting. size=%d expectedSize=%d cTestResult=%s expectedStr=%s\n",\ size, expectedSize, cTestResult, expectedStr);\ }\ @@ -332,7 +333,7 @@ static void TestSnprintf(void) { #if !UCONFIG_NO_FORMATTING UChar testStr[256]; char cTestResult[256]; - int32_t size; + int32_t size, written; Test_u_snprintf(0, "%d", 123, 3, "xxxxxxxxxxxxxx"); Test_u_snprintf(2, "%d", 123, 3, "12xxxxxxxxxxxx"); diff --git a/Build/source/libs/icu/icu-src/source/test/perf/Makefile.in b/Build/source/libs/icu/icu-src/source/test/perf/Makefile.in index cb7c2f15943..85469cf092f 100644 --- a/Build/source/libs/icu/icu-src/source/test/perf/Makefile.in +++ b/Build/source/libs/icu/icu-src/source/test/perf/Makefile.in @@ -22,7 +22,7 @@ subdir = test/perf ## Files to remove for 'make clean' CLEANFILES = *~ -SUBDIRS = collationperf collperf collperf2 charperf dicttrieperf localecanperf normperf ubrkperf unisetperf usetperf ustrperf utfperf utrie2perf DateFmtPerf howExpensiveIs +SUBDIRS = collationperf collperf collperf2 charperf dicttrieperf localecanperf normperf strsrchperf ubrkperf unisetperf usetperf ustrperf utfperf utrie2perf DateFmtPerf howExpensiveIs # Subdirs that support 'xperf' XSUBDIRS = DateFmtPerf @@ -38,10 +38,7 @@ check check-recursive check-local xperf xperf-recursive ## List of standard targets everything: all-recursive all-local -all: -ifneq ($(RECURSIVE),YES) - @echo simply use \`make\' \(or \`make everything\'\) to do all -endif +all: everything install: install-recursive install-local clean: clean-recursive clean-local diff --git a/Build/source/libs/icu/icu-src/source/test/perf/charperf/charperf.cpp b/Build/source/libs/icu/icu-src/source/test/perf/charperf/charperf.cpp index 6fc576cd235..651434b6a49 100644 --- a/Build/source/libs/icu/icu-src/source/test/perf/charperf/charperf.cpp +++ b/Build/source/libs/icu/icu-src/source/test/perf/charperf/charperf.cpp @@ -81,7 +81,6 @@ CharPerformanceTest::CharPerformanceTest(int32_t argc, const char *argv[], else { MAX_ = 0xffff; } - printf("MAX_ size will be 0x%x\n", MAX_); if (options[MIN_OPTION_].doesOccur) { MIN_ = atoi(options[MIN_OPTION_].value); } diff --git a/Build/source/libs/icu/icu-src/source/test/perf/ustrperf/Makefile.in b/Build/source/libs/icu/icu-src/source/test/perf/ustrperf/Makefile.in index 4d601137ac0..8ef95af01d2 100644 --- a/Build/source/libs/icu/icu-src/source/test/perf/ustrperf/Makefile.in +++ b/Build/source/libs/icu/icu-src/source/test/perf/ustrperf/Makefile.in @@ -20,7 +20,7 @@ subdir = test/perf/ustrperf CLEANFILES = *~ $(DEPS) ## Target information -TARGET = stringperf +TARGET = ustrperf CPPFLAGS += -I$(top_srcdir)/common -I$(top_srcdir)/tools/toolutil -I$(top_srcdir)/tools/ctestfw LIBS = $(LIBCTESTFW) $(LIBICUI18N) $(LIBICUUC) $(LIBICUTOOLUTIL) $(DEFAULT_LIBS) $(LIB_M) diff --git a/Build/source/libs/icu/icu-src/source/test/perf/ustrperf/stringperf.h b/Build/source/libs/icu/icu-src/source/test/perf/ustrperf/stringperf.h index 59b841865a3..39ca45987c9 100644 --- a/Build/source/libs/icu/icu-src/source/test/perf/ustrperf/stringperf.h +++ b/Build/source/libs/icu/icu-src/source/test/perf/ustrperf/stringperf.h @@ -444,7 +444,6 @@ inline void catenate(const UChar* src,int32_t srcLen, UnicodeString s0) utimer_getTime(&mystop); double mytime = utimer_getDeltaSeconds(&mystart,&mystop); - printf("\nmytime=%f \n", mytime); *catICU += uCatenate_STR; } @@ -533,7 +532,6 @@ inline void StdLibCatenate(const wchar_t* src,int32_t srcLen, stlstring s0) utimer_getTime(&mystop); double mytime = utimer_getDeltaSeconds(&mystart,&mystop); - printf("\nmytime=%f \n", mytime); } diff --git a/Build/source/libs/icu/icu-src/source/test/testdata/break_rules/line_loose_cj.txt b/Build/source/libs/icu/icu-src/source/test/testdata/break_rules/line_loose_cj.txt index d0693d567cd..9d7b2cc12c6 100644 --- a/Build/source/libs/icu/icu-src/source/test/testdata/break_rules/line_loose_cj.txt +++ b/Build/source/libs/icu/icu-src/source/test/testdata/break_rules/line_loose_cj.txt @@ -20,7 +20,8 @@ # line-break=loose (BCP47 -u-lb-loose) as defined for Chinese & Japanese. # It sets characters of class CJ to behave like ID. # In addition, it allows breaks: -# * before hyphens 2010 & 2013 (both BA) and 301C, 30A0 (both NS) +# * between ID and hyphens 2010 & 2013 (both BA) +# * before 301C, 30A0 (both NS) # * before iteration marks 3005, 303B, 309D, 309E, 30FD, 30FE (all NS) # * between characters of LineBreak class IN such as 2026 # * before some centered punct 203C, 2047, 2048, 2049, 30FB, FF1A, FF1B, @@ -200,8 +201,9 @@ LB20.09: ^(HY | HH) CM* AL; LB21a: HL CM* (HY | BA | BAX) CM* [^CM CB]?; -LB21.1: . CM* [BA HY NS]; -LB21.2: BB CM* [^CM CB]; +LB21.1: [^ID] CM* [BA BAX HY NS]; +LB21.2: ID CM* [BA HY NS]; +LB21.3: BB CM* [^CM CB]; LB21b: SY CM* HL; @@ -236,9 +238,9 @@ LB30.1: (AL | CM | HL | NU) CM* OP30; LB30.2: CP30 CM* (AL | HL | NU); # LB30a keep pairs of RI together. -LB30a.1: RI CM* RI ÷ [^BK CR LF NL SP ZW WJ CL CP EX IS SY GL QU BA HY NS IN CM]; -LB30a.2: RI CM* RI CM* CMS ÷ [^BK CR LF NL SP ZW WJ CL CP EX IS SY GL QU BA HY NS IN CM]; -LB30a.3: RI CM* RI CM* [BK CR LF NL SP ZW WJ GL CL CP EX IS SY QU BA HY NS IN ZWJ]?; +LB30a.1: RI CM* RI ÷ [^BK CR LF NL SP ZW WJ CL CP EX IS SY GL QU BA BAX HY NS IN CM]; +LB30a.2: RI CM* RI CM* CMS ÷ [^BK CR LF NL SP ZW WJ CL CP EX IS SY GL QU BA BAX HY NS IN CM]; +LB30a.3: RI CM* RI CM* [BK CR LF NL SP ZW WJ GL CL CP EX IS SY QU BA BAX HY NS IN ZWJ]?; # LB30b Do not break between Emoji Base (or potential emoji) and Emoji Modifier LB30b.1: EB CM* EM; diff --git a/Build/source/libs/icu/icu-src/source/test/testdata/break_rules/line_normal_cj.txt b/Build/source/libs/icu/icu-src/source/test/testdata/break_rules/line_normal_cj.txt index a2704821441..a4e1428c2b2 100644 --- a/Build/source/libs/icu/icu-src/source/test/testdata/break_rules/line_normal_cj.txt +++ b/Build/source/libs/icu/icu-src/source/test/testdata/break_rules/line_normal_cj.txt @@ -20,7 +20,7 @@ # line-break=normal (BCP47 -u-lb-normal) as defined for Chinese & Japanese. # It sets characters of class CJ to behave like ID. # In addition, it allows breaks: -# * before hyphens 2010 & 2013 (both BA) and 301C, 30A0 (both NS) +# * before 301C, 30A0 (both NS) # It allows breaking before 201C and after 201D, for zh_Hans, zh_Hant, and ja. type = line; @@ -28,8 +28,7 @@ locale = ja@lb=normal; AI = [:LineBreak = Ambiguous:]; AL = [:LineBreak = Alphabetic:]; -BAX = [\u2010 \u2013]; -BA = [[:LineBreak = Break_After:] - BAX]; +BA = [:LineBreak = Break_After:]; HH = [\u2010]; # \u2010 is HYPHEN, default line break is BA. BB = [:LineBreak = Break_Before:]; BK = [:LineBreak = Mandatory_Break:]; @@ -154,7 +153,7 @@ LB11.3: WJ CM* [^CM]; LB12: GL CM* [^CM]; -LB12a: [^SP BA BAX HY] CM* GL; +LB12a: [^SP BA HY] CM* GL; # LB 13 Do not break before ‘]’ or ‘!’ or ‘/’, even after spaces. LB13.1: [^SP] CM* [CL CP EX SY]; @@ -182,12 +181,9 @@ LB20.09: ^(HY | HH) CM* AL; # Note: Rule 21a must come before 21 to prevent 21.1 from matching HL BA, then # not picking up the continuing match after the BA from 21a. -# TODO: For CJ tailorings (with BAX) does this rule want to include BAX? If so, -# should "HL BAX" not break when followed by a CB? Thats what the current -# rules do, which is why "[^CM CB]?" includes the ?. -LB21a: HL CM* (HY | BA | BAX) CM* [^CM CB]?; +LB21a: HL CM* (HY | BA) CM* [^CM CB]?; -# DO allow breaks here before $BAXcm and $NSXcm, so don't include them +# DO allow breaks here before $NSXcm, so don't include it LB21.1: . CM* [BA HY NS]; LB21.2: BB CM* [^CM CB]; diff --git a/Build/source/libs/icu/icu-src/source/test/testdata/rbbitst.txt b/Build/source/libs/icu/icu-src/source/test/testdata/rbbitst.txt index 7fb30c9e8e3..a8d1e8e7158 100644 --- a/Build/source/libs/icu/icu-src/source/test/testdata/rbbitst.txt +++ b/Build/source/libs/icu/icu-src/source/test/testdata/rbbitst.txt @@ -796,6 +796,9 @@ <word> <data>•ジョージア<400> •</data> +<word> +<data>•[<0>携帯<400>電話<400>]<0>お金<400>が<400>かかる<400>ん<400>です<400>。<0></data> + # Test for #11723 <word> <data>•アレルギー性<400>結膜炎<400></data> @@ -1445,6 +1448,9 @@ Bangkok)•</data> <data>•ກວາກຊວາກ•ກະເຈາະກະຈອກ•</data> <data>•ກະຊວງປ້ອງກັນຄວາມສະຫງົບ•</data> <data>•ໄຮ•ໄຮ່•ໄຮ້•</data> +# Checks for ICU-21409 (and ICU-21384) +<line> +<data>•ຣະຄັງ•ຣະມາ•ລູຊີເຟີ•</data> ########################################################################################## # @@ -1643,11 +1649,17 @@ Bangkok)•</data> # •brk OK before 3063 •brk OK before 301C •no brk btw 2026 •no brk before FF01• <data>•\u3084•\u3063•\u3071•\u308A\u0020•\u0031•\u301C\u0020•\u2026\u2026\u0020•\u30A2\uFF01\u0020•</data> +# •no brk before 2010 • +<data>•\u3042\u2010•\u0031\u0020•\u0061\u2010•\u0031\u0020•</data> + <locale ja@lb=loose> <line> # •brk OK before 3063 •brk OK before 301C •brk OK btw 2026 •brk OK before FF01• <data>•\u3084•\u3063•\u3071•\u308A\u0020•\u0031•\u301C\u0020•\u2026•\u2026\u0020•u30A2•\uFF01\u0020•</data> +# •no brk before 2010 except ok after ID • +<data>•\u3042•\u2010•\u0031\u0020•\u0061\u2010•\u0031\u0020•</data> + <locale en@lb=strict> <line> # •no brk before 3063 •no brk before 301C•no brk btw 2026 •no brk before FF01• @@ -1881,6 +1893,48 @@ Bangkok)•</data> # woman astronaut, woman astronaut / fitz4 <data>•\U0001F469\u200D\U0001F680•\U0001F469\U0001F3FD\u200D\U0001F680\u0020•</data> +<locale ja@lw=phrase> +<line> +#[京都観光]時雨殿に行った。-> [京都•観光]•時雨•殿に•行った。• +<data>•\uff3b\u4eac\u90fd•\u89b3\u5149\uff3d•\u6642\u96e8•\u6bbf\u306b•\u884c\u3063\u305f\u3002•</data> +#9月に東京から友達が遊びに来た -> 9月に•東京から•友達が•遊びに•来た• +<data>•\uff19\u6708\u306b•\u6771\u4eac\u304b\u3089•\u53cb\u9054\u304c•\u904a\u3073\u306b•\u6765\u305f•</data> +#る文字「そうだ、京都」-> る•文字•「そうだ、•京都」• +<data>•\u308b•\u6587\u5b57•\u300c\u305d\u3046\u3060\u3001•\u4eac\u90fd\u300d•</data> +#乗車率90%程度だろうか。 -> 乗車•率•90%•程度だろうか。• +<data>•\u4e57\u8eca•\u7387•\uff19\uff10\uff05•\u7a0b\u5ea6\u3060\u308d\u3046\u304b\u3002•</data> +#[携帯電話]正しい選択 -> [携帯•電話]•正しい•選択• +<data>•\uff3b\u643a\u5e2f•\u96fb\u8a71\uff3d•\u6b63\u3057\u3044•\u9078\u629e•</data> +#純金製百人一首にサッカーボール -> 純金•製•百人一首に•サッカーボール +<data>•\u7D14\u91D1•\u88FD•\u767E\u4EBA\u4E00\u9996\u306B•\u30B5\u30C3\u30AB\u30FC\u30DC\u30FC\u30EB•</data> +#Kana supplement: 𛁈(U+1B048) -> \uD82C\uDC48, 𛀸(U+1B038) -> \uD82C\uDC38, 𛀙(U+1B019)-> \uD82C\uDC19</data> +#𛁈る𛀸(しるこ)、あ𛀙よろし(あかよろし) -> 𛁈る𛀸•(しるこ)、•あ𛀙よろし•(あ•かよろし) +<data>•\uD82C\uDC48\u308B\uD82C\uDC38•\uFF08\u3057\u308B\u3053\uFF09\u3001•\u3042\uD82C\uDC19\u3088\u308D\u3057•\uFF08\u3042•\u304B\u3088\u308D\u3057\uFF09•</data> +#最初に目に入るのは、「許諾なき写真禁止」のサインである。 -> 最初に▁目に▁入るのは、▁「許諾なき▁写真▁禁止」▁の▁サインで▁ある。 +<data>•\u6700\u521D\u306B•\u76EE\u306B•\u5165\u308B\u306E\u306F\u3001•\u300C\u8A31\u8AFE\u306A\u304D•\u5199\u771F•\u7981\u6B62\u300D•\u306E•\u30B5\u30A4\u30F3\u3067•\u3042\u308B\u3002•</data> +#docomoのサイト情報によると、78000パケット以上▁使うならパケ放題がいいとか -> docomoの▁サイト▁情報によると、▁78000パケット▁以上▁使うなら▁パケ▁放題が▁いい▁とか +<data>•\uFF44\uFF4F\uFF43\uFF4F\uFF4D\uFF4F\u306E•\u30B5\u30A4\u30C8•\u60C5\u5831\u306B\u3088\u308B\u3068\u3001•\uFF17\uFF18\uFF10\uFF10\uFF10\u30D1\u30B1\u30C3\u30C8•\u4EE5\u4E0A•\u4F7F\u3046\u306A\u3089•\u30D1\u30B1•\u653E\u984C\u304C•\u3044\u3044•\u3068\u304B•</data> +#日本の携帯はCDMAの形だといわれています -> 日本の▁携帯は▁CDMAの▁形だと▁いわれ▁ています +<data>•\u65E5\u672C\u306E•\u643A\u5E2F\u306F•\uFF23\uFF24\uFF2D\uFF21\u306E•\u5F62\u3060\u3068•\u3044\u308F\u308C•\u3066\u3044\u307E\u3059•</data> +#中国の携帯は約500元から5000元です -> 中国の▁携帯は▁約▁500元から▁5000元です +<data>•\u4E2D\u56FD\u306E•\u643A\u5E2F\u306F•\u7D04•\uFF15\uFF10\uFF10\u5143\u304B\u3089•\uFF15\uFF10\uFF10\uFF10\u5143\u3067\u3059•</data> +#プリペイドカード携帯布教 -> プリペイドカード▁携帯▁布教 +<data>•\u30D7\u30EA\u30DA\u30A4\u30C9\u30AB\u30FC\u30C9•\u643A\u5E2F•\u5E03\u6559•</data> +#しかもロゴがUnicode!! -> しかも▁ロゴが▁Unicode!! +<data>•\u3057\u304B\u3082•\u30ED\u30B4\u304C•\uFF35\uFF4E\uFF49\uFF43\uFF4F\uFF44\uFF45\uFF01\uFF01•</data> +#しかし、これらのサービスは6年間使ってこなかった自分にとっては特に必要でないものであり、これからこの機能が加わったからといって特別ハッピーなわけでもない。 +#-> しかし、▁これらの▁サービスは▁6年間▁使ってこなかった▁自分にとっては▁特に▁必要でない▁もので▁あり、▁これから▁この▁機能が▁加わったから▁といって▁特別▁ハッピーな▁わけでもない。 +<data>•\u3057\u304B\u3057\u3001•\u3053\u308C\u3089\u306E•\u30B5\u30FC\u30D3\u30B9\u306F•\uFF16\u5E74\u9593•\u4F7F\u3063\u3066\u3053\u306A\u304B\u3063\u305F•\u81EA\u5206\u306B\u3068\u3063\u3066\u306F•\u7279\u306B•\u5FC5\u8981\u3067\u306A\u3044•\u3082\u306E\u3067•\u3042\u308A\u3001•\u3053\u308C\u304B\u3089•\u3053\u306E•\u6A5F\u80FD\u304C•\u52A0\u308F\u3063\u305F\u304B\u3089•\u3068\u3044\u3063\u3066•\u7279\u5225•\u30CF\u30C3\u30D4\u30FC\u306A•\u308F\u3051\u3067\u3082\u306A\u3044\u3002•</data> +#自由が丘での三ヶ月の生活を通して得られる経験 -> 自由が丘での▁三ヶ月の▁生活を通して▁得られる▁経験 +<data>•\u81EA\u7531\u304C\u4E18\u3067\u306E•\u4E09\u30F6\u6708\u306E•\u751F\u6D3B\u3092\u901A\u3057\u3066•\u5F97\u3089\u308C\u308B•\u7D4C\u9A13•</data> +#幕の内弁当がよく買われるらしいです。 -> 幕の内▁弁当が▁よく▁買われるらしいです。 +<data>•\u5E55\u306E\u5185•\u5F01\u5F53\u304C•\u3088\u304F•\u8CB7\u308F\u308C\u308B\u3089\u3057\u3044\u3067\u3059\u3002•</data> +#その名の通りに伝われと望まれています。 -> その▁名の通りに▁伝われと▁望まれ▁ています。 +<data>•\u305D\u306E•\u540D\u306E\u901A\u308A\u306B•\u4F1D\u308F\u308C\u3068•\u671B\u307E\u308C•\u3066\u3044\u307E\u3059\u3002•</data> +#下鴨神社の糺の森は、静かだし、ちょっとした空き時間の散歩にいいですよ♪ -> 下鴨▁神社の▁糺の森は、▁静か▁だし、▁ちょっとした▁空き▁時間の▁散歩に▁いいですよ♪ +<data>•\u4E0B\u9D28•\u795E\u793E\u306E•\u7CFA\u306E\u68EE\u306F\u3001•\u9759\u304B•\u3060\u3057\u3001•\u3061\u3087\u3063\u3068\u3057\u305F•\u7A7A\u304D•\u6642\u9593\u306E•\u6563\u6B69\u306B•\u3044\u3044\u3067\u3059\u3088\u266A•</data> +#この論理は、別の弱点から逃避するためによく使われるので注意が必要ですが。 -> この▁論理は、▁別の▁弱点から▁逃避▁する▁ために▁よく▁使われるので▁注意が▁必要▁ですが。 +<data>•\u3053\u306E•\u8AD6\u7406\u306F\u3001•\u5225\u306E•\u5F31\u70B9\u304B\u3089•\u9003\u907F•\u3059\u308B•\u305F\u3081\u306B•\u3088\u304F•\u4F7F\u308F\u308C\u308B\u306E\u3067•\u6CE8\u610F\u304C•\u5FC5\u8981•\u3067\u3059\u304C\u3002•</data> #################################################################################### # diff --git a/Build/source/libs/icu/icu-src/source/test/testdata/root.txt b/Build/source/libs/icu/icu-src/source/test/testdata/root.txt index 2d6fcb7f8f3..f3a9a151ee4 100644 --- a/Build/source/libs/icu/icu-src/source/test/testdata/root.txt +++ b/Build/source/libs/icu/icu-src/source/test/testdata/root.txt @@ -13,8 +13,8 @@ root { Version { 44.0 } - ExpectCLDRVersionAtLeast { 40.0 } // 'base' cldr version. Allow up to version =.=.* of this - CurrentCLDRVersion { 40.0 } // Current CLDR version as of the test update. Warn if not an exact match. + ExpectCLDRVersionAtLeast { 41.0 } // 'base' cldr version. Allow up to version =.=.* of this + CurrentCLDRVersion { 41.0 } // Current CLDR version as of the test update. Warn if not an exact match. ShortLanguage { xxx } diff --git a/Build/source/libs/icu/icu-src/source/tools/ctestfw/ctestfw.vcxproj b/Build/source/libs/icu/icu-src/source/tools/ctestfw/ctestfw.vcxproj index 1dd8e2602c5..a4bd954bf56 100644 --- a/Build/source/libs/icu/icu-src/source/tools/ctestfw/ctestfw.vcxproj +++ b/Build/source/libs/icu/icu-src/source/tools/ctestfw/ctestfw.vcxproj @@ -53,7 +53,7 @@ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> </ClCompile> <Link> - <OutputFile>..\..\..\$(IcuBinOutputDir)\icutest70d.exe</OutputFile> + <OutputFile>..\..\..\$(IcuBinOutputDir)\icutest71d.exe</OutputFile> <ProgramDatabaseFile>.\..\..\..\$(IcuLibOutputDir)\icutestd.pdb</ProgramDatabaseFile> <ImportLibrary>.\..\..\..\$(IcuLibOutputDir)\icutestd.lib</ImportLibrary> <AdditionalDependencies>icuucd.lib;icutud.lib;%(AdditionalDependencies)</AdditionalDependencies> @@ -66,7 +66,7 @@ <FunctionLevelLinking>true</FunctionLevelLinking> </ClCompile> <Link> - <OutputFile>..\..\..\$(IcuBinOutputDir)\icutest70.exe</OutputFile> + <OutputFile>..\..\..\$(IcuBinOutputDir)\icutest71.exe</OutputFile> <ProgramDatabaseFile>.\..\..\..\$(IcuLibOutputDir)\icutest.pdb</ProgramDatabaseFile> <ImportLibrary>.\..\..\..\$(IcuLibOutputDir)\icutest.lib</ImportLibrary> <AdditionalDependencies>icuuc.lib;icutu.lib;%(AdditionalDependencies)</AdditionalDependencies> diff --git a/Build/source/libs/icu/icu-src/source/tools/ctestfw/uperf.cpp b/Build/source/libs/icu/icu-src/source/tools/ctestfw/uperf.cpp index 5605f0d2e3d..67b9fe50aae 100644 --- a/Build/source/libs/icu/icu-src/source/tools/ctestfw/uperf.cpp +++ b/Build/source/libs/icu/icu-src/source/tools/ctestfw/uperf.cpp @@ -390,7 +390,7 @@ UBool UPerfTest::runTestLoop( char* testname, char* par ) loops = failsafe; failsafe *= 10; } else { - //System.out.println("# " + meth.getName() + " x " + loops + " = " + t); + //System.out.println("# " + meth.getName() + " x " + loops + " = " + t); loops = (int)((double)n / t * loops + 0.5); if (loops == 0) { fprintf(stderr,"Unable to converge on desired duration"); @@ -412,15 +412,13 @@ UBool UPerfTest::runTestLoop( char* testname, char* par ) long events = -1; for(int32_t ps =0; ps < passes; ps++){ - fprintf(stdout,"= %s begin " ,name); if(verbose==TRUE){ + fprintf(stdout,"= %s begin " ,name); if(iterations > 0) { fprintf(stdout, "%i\n", (int)loops); } else { fprintf(stdout, "%i\n", (int)n); } - } else { - fprintf(stdout, "\n"); } t = testFunction->time(loops, &status); if(U_FAILURE(status)){ @@ -439,12 +437,6 @@ UBool UPerfTest::runTestLoop( char* testname, char* par ) }else{ fprintf(stdout, "= %s end: %f loops: %i operations: %li events: %li\n", name, t, (int)loops, ops, events); } - }else{ - if(events == -1){ - fprintf(stdout,"= %s end %f %i %li\n", name, t, (int)loops, ops); - }else{ - fprintf(stdout,"= %s end %f %i %li %li\n", name, t, (int)loops, ops, events); - } } } if(verbose && U_SUCCESS(status)) { @@ -465,6 +457,12 @@ UBool UPerfTest::runTestLoop( char* testname, char* par ) name, min_t, (int)loops, (min_t*1E9)/(loops*ops), (min_t*1E9)/(loops*events)); } } + else if(U_SUCCESS(status)) { + // Print results in ndjson format for GHA Benchmark to process. + fprintf(stdout, + "{\"biggerIsBetter\":false,\"name\":\"%s\",\"unit\":\"ns/iter\",\"value\":%.4f}\n", + name, (min_t*1E9)/(loops*ops)); + } delete testFunction; } index++; diff --git a/Build/source/libs/icu/icu-src/source/tools/gennorm2/BUILD b/Build/source/libs/icu/icu-src/source/tools/gennorm2/BUILD.bazel index c602897bafc..c602897bafc 100644 --- a/Build/source/libs/icu/icu-src/source/tools/gennorm2/BUILD +++ b/Build/source/libs/icu/icu-src/source/tools/gennorm2/BUILD.bazel diff --git a/Build/source/libs/icu/icu-src/source/tools/icuexportdata/icuexportdata.cpp b/Build/source/libs/icu/icu-src/source/tools/icuexportdata/icuexportdata.cpp index ef933676115..7431ac74ab8 100644 --- a/Build/source/libs/icu/icu-src/source/tools/icuexportdata/icuexportdata.cpp +++ b/Build/source/libs/icu/icu-src/source/tools/icuexportdata/icuexportdata.cpp @@ -3,6 +3,7 @@ #include <iostream> #include <vector> +#include <algorithm> #include "toolutil.h" #include "uoptions.h" #include "cmemory.h" @@ -11,8 +12,10 @@ #include "unicode/uchar.h" #include "unicode/errorcode.h" #include "unicode/uniset.h" +#include "unicode/uscript.h" #include "unicode/putil.h" #include "unicode/umutablecptrie.h" +#include "ucase.h" #include "writesrc.h" U_NAMESPACE_USE @@ -27,6 +30,75 @@ UBool haveCopyright = TRUE; UCPTrieType trieType = UCPTRIE_TYPE_SMALL; const char* destdir = ""; +// Mask constants for modified values in the Script CodePointTrie, values are logically 12-bits. +int16_t DATAEXPORT_SCRIPT_X_WITH_COMMON = 0x0400; +int16_t DATAEXPORT_SCRIPT_X_WITH_INHERITED = 0x0800; +int16_t DATAEXPORT_SCRIPT_X_WITH_OTHER = 0x0c00; + +// TODO(ICU-21821): Replace this with a call to a library function +int32_t scxCodePoints[] = { + 7415, 7377, 7380, 7387, 7390, 7391, 7394, 7395, 7396, 7397, + 7398, 7399, 7400, 7403, 7404, 7406, 7407, 7408, 7409, 113824, + 113825, 113826, 113827, 834, 837, 7616, 7617, 12294, 12350, 12351, + 12688, 12689, 12690, 12691, 12692, 12693, 12694, 12695, 12696, 12697, + 12698, 12699, 12700, 12701, 12702, 12703, 12736, 12737, 12738, 12739, + 12740, 12741, 12742, 12743, 12744, 12745, 12746, 12747, 12748, 12749, + 12750, 12751, 12752, 12753, 12754, 12755, 12756, 12757, 12758, 12759, + 12760, 12761, 12762, 12763, 12764, 12765, 12766, 12767, 12768, 12769, + 12770, 12771, 12832, 12833, 12834, 12835, 12836, 12837, 12838, 12839, + 12840, 12841, 12842, 12843, 12844, 12845, 12846, 12847, 12848, 12849, + 12850, 12851, 12852, 12853, 12854, 12855, 12856, 12857, 12858, 12859, + 12860, 12861, 12862, 12863, 12864, 12865, 12866, 12867, 12868, 12869, + 12870, 12871, 12928, 12929, 12930, 12931, 12932, 12933, 12934, 12935, + 12936, 12937, 12938, 12939, 12940, 12941, 12942, 12943, 12944, 12945, + 12946, 12947, 12948, 12949, 12950, 12951, 12952, 12953, 12954, 12955, + 12956, 12957, 12958, 12959, 12960, 12961, 12962, 12963, 12964, 12965, + 12966, 12967, 12968, 12969, 12970, 12971, 12972, 12973, 12974, 12975, + 12976, 12992, 12993, 12994, 12995, 12996, 12997, 12998, 12999, 13000, + 13001, 13002, 13003, 13055, 13144, 13145, 13146, 13147, 13148, 13149, + 13150, 13151, 13152, 13153, 13154, 13155, 13156, 13157, 13158, 13159, + 13160, 13161, 13162, 13163, 13164, 13165, 13166, 13167, 13168, 13179, + 13180, 13181, 13182, 13183, 13280, 13281, 13282, 13283, 13284, 13285, + 13286, 13287, 13288, 13289, 13290, 13291, 13292, 13293, 13294, 13295, + 13296, 13297, 13298, 13299, 13300, 13301, 13302, 13303, 13304, 13305, + 13306, 13307, 13308, 13309, 13310, 119648, 119649, 119650, 119651, 119652, + 119653, 119654, 119655, 119656, 119657, 119658, 119659, 119660, 119661, 119662, + 119663, 119664, 119665, 127568, 127569, 867, 868, 869, 870, 871, + 872, 873, 874, 875, 876, 877, 878, 879, 7418, 7674, + 66272, 66273, 66274, 66275, 66276, 66277, 66278, 66279, 66280, 66281, + 66282, 66283, 66284, 66285, 66286, 66287, 66288, 66289, 66290, 66291, + 66292, 66293, 66294, 66295, 66296, 66297, 66298, 66299, 1748, 64830, + 64831, 1611, 1612, 1613, 1614, 1615, 1616, 1617, 1618, 1619, + 1620, 1621, 1648, 65010, 65021, 7381, 7382, 7384, 7393, 7402, + 7405, 7413, 7414, 43249, 12330, 12331, 12332, 12333, 43471, 65794, + 65847, 65848, 65849, 65850, 65851, 65852, 65853, 65854, 65855, 1156, + 1159, 11843, 42607, 1157, 1158, 1155, 7672, 7379, 7411, 7416, + 7417, 7401, 7383, 7385, 7388, 7389, 7392, 43251, 4347, 3046, + 3047, 3048, 3049, 3050, 3051, 3052, 3053, 3054, 3055, 3056, + 3057, 3058, 3059, 70401, 70403, 70459, 70460, 73680, 73681, 73683, + 2790, 2791, 2792, 2793, 2794, 2795, 2796, 2797, 2798, 2799, + 2662, 2663, 2664, 2665, 2666, 2667, 2668, 2669, 2670, 2671, + 42752, 42753, 42754, 42755, 42756, 42757, 42758, 42759, 12337, 12338, + 12339, 12340, 12341, 12441, 12442, 12443, 12444, 12448, 12540, 65392, + 65438, 65439, 3302, 3303, 3304, 3305, 3306, 3307, 3308, 3309, + 3310, 3311, 8239, 68338, 6146, 6147, 6149, 1564, 1632, 1633, + 1634, 1635, 1636, 1637, 1638, 1639, 1640, 1641, 2534, 2535, + 2536, 2537, 2538, 2539, 2540, 2541, 2542, 2543, 4160, 4161, + 4162, 4163, 4164, 4165, 4166, 4167, 4168, 4169, 65792, 65793, + 65799, 65800, 65801, 65802, 65803, 65804, 65805, 65806, 65807, 65808, + 65809, 65810, 65811, 65812, 65813, 65814, 65815, 65816, 65817, 65818, + 65819, 65820, 65821, 65822, 65823, 65824, 65825, 65826, 65827, 65828, + 65829, 65830, 65831, 65832, 65833, 65834, 65835, 65836, 65837, 65838, + 65839, 65840, 65841, 65842, 65843, 7412, 8432, 12348, 12349, 43310, + 7376, 7378, 5941, 5942, 2406, 2407, 2408, 2409, 2410, 2411, + 2412, 2413, 2414, 2415, 12291, 12307, 12316, 12317, 12318, 12319, + 12336, 12343, 65093, 65094, 1548, 1563, 12289, 12290, 12296, 12297, + 12298, 12299, 12300, 12301, 12302, 12303, 12304, 12305, 12308, 12309, + 12310, 12311, 12312, 12313, 12314, 12315, 12539, 65377, 65378, 65379, + 65380, 65381, 7386, 1567, 7410, 1600, 43062, 43063, 43064, 43065, + 2386, 2385, 43059, 43060, 43061, 43056, 43057, 43058, 2404, 2405 + }; + void handleError(ErrorCode& status, const char* context) { if (status.isFailure()) { std::cerr << "Error: " << context << ": " << status.errorName() << std::endl; @@ -96,6 +168,110 @@ void dumpEnumeratedProperty(UProperty uproperty, FILE* f) { usrc_writeUCPTrie(f, shortPropName, utrie.getAlias(), UPRV_TARGET_SYNTAX_TOML); } +void dumpScriptExtensions(FILE* f) { + IcuToolErrorCode status("icuexportdata: dumpScriptExtensions"); + + fputs("[[script_extensions]]\n", f); + const char* scxFullPropName = u_getPropertyName(UCHAR_SCRIPT_EXTENSIONS, U_LONG_PROPERTY_NAME); + const char* scxShortPropName = u_getPropertyName(UCHAR_SCRIPT_EXTENSIONS, U_SHORT_PROPERTY_NAME); + fprintf(f, "long_name = \"%s\"\n", scxFullPropName); + if (scxShortPropName) fprintf(f, "short_name = \"%s\"\n", scxShortPropName); + + // We want to use 16 bits for our exported trie of sc/scx data because we + // need 12 bits to match the 12 bits of data stored for sc/scx in the trie + // in the uprops.icu data file. + UCPTrieValueWidth scWidth = UCPTRIE_VALUE_BITS_16; + + // Create a mutable UCPTrie builder populated with Script property values data. + const UCPMap* scInvMap = u_getIntPropertyMap(UCHAR_SCRIPT, status); + handleError(status, scxFullPropName); + LocalUMutableCPTriePointer builder(umutablecptrie_fromUCPMap(scInvMap, status)); + handleError(status, scxFullPropName); + + // The values for the output scx companion array. + // Invariant is that all subvectors are distinct. + std::vector< std::vector<uint16_t> > outputDedupVec; + + // The sc/scx companion array is an array of arrays (of script codes) + fputs("script_code_array = [\n", f); + for(const UChar32 cp : scxCodePoints) { + // Get the Script value + uint32_t scVal = umutablecptrie_get(builder.getAlias(), cp); + // Get the Script_Extensions value (array of Script codes) + const int32_t SCX_ARRAY_CAPACITY = 32; + UScriptCode scxValArray[SCX_ARRAY_CAPACITY]; + int32_t numScripts = uscript_getScriptExtensions(cp, scxValArray, SCX_ARRAY_CAPACITY, status); + handleError(status, scxFullPropName); + + // Convert the scx array into a vector + std::vector<uint16_t> scxValVec; + for(int i = 0; i < numScripts; i++) { + scxValVec.push_back(scxValArray[i]); + } + // Ensure that it is sorted + std::sort(scxValVec.begin(), scxValVec.end()); + // Copy the Script value into the first position of the scx array only + // if we have the "other" case (Script value is not Common nor Inherited). + // This offers faster access when users want only the Script value. + if (scVal != USCRIPT_COMMON && scVal != USCRIPT_INHERITED) { + scxValVec.insert(scxValVec.begin(), scVal); + } + + // See if there is already an scx value array matching the newly built one. + // If there is, then use its index. + // If not, then append the new value array. + bool isScxValUnique = true; + size_t outputIndex = 0; + for (outputIndex = 0; outputIndex < outputDedupVec.size(); outputIndex++) { + if (outputDedupVec[outputIndex] == scxValVec) { + isScxValUnique = false; + break; + } + } + + if (isScxValUnique) { + outputDedupVec.push_back(scxValVec); + usrc_writeArray(f, " [", scxValVec.data(), 16, scxValVec.size(), " ", "],\n"); + } + + // We must update the value in the UCPTrie for the code point to contain: + // 9..0 the Script code in the lower 10 bits when 11..10 is 0, else it is + // the index into the companion array + // 11..10 the same higher-order 2 bits in the trie in uprops.icu indicating whether + // 3: other + // 2: Script=Inherited + // 1: Script=Common + // 0: Script=value in 9..0 (N/A because we are in this loop to create the companion array for non-0 cases) + uint16_t mask = 0; + if (scVal == USCRIPT_COMMON) { + mask = DATAEXPORT_SCRIPT_X_WITH_COMMON; + } else if (scVal == USCRIPT_INHERITED) { + mask = DATAEXPORT_SCRIPT_X_WITH_INHERITED; + } else { + mask = DATAEXPORT_SCRIPT_X_WITH_OTHER; + } + + // The new trie value is the index into the new array with the high order bits set + uint32_t newScVal = outputIndex | mask; + + // Update the code point in the mutable trie builder with the trie value + umutablecptrie_set(builder.getAlias(), cp, newScVal, status); + handleError(status, scxFullPropName); + } + fputs("]\n\n", f); // Print the TOML close delimiter for the outer array. + + // Convert from mutable trie builder to immutable trie. + LocalUCPTriePointer utrie(umutablecptrie_buildImmutable( + builder.getAlias(), + trieType, + scWidth, + status)); + handleError(status, scxFullPropName); + + fputs("[script_extensions.code_point_trie]\n", f); + usrc_writeUCPTrie(f, scxShortPropName, utrie.getAlias(), UPRV_TARGET_SYNTAX_TOML); +} + FILE* prepareOutputFile(const char* basename) { IcuToolErrorCode status("icuexportdata"); CharString outFileName; @@ -158,45 +334,42 @@ static UOption options[]={ UOPTION_QUIET, }; -int main(int argc, char* argv[]) { - U_MAIN_INIT_ARGS(argc, argv); - - /* preset then read command line options */ - options[OPT_DESTDIR].value=u_getDataDirectory(); - argc=u_parseArgs(argc, argv, UPRV_LENGTHOF(options), options); - - if(options[OPT_VERSION].doesOccur) { - printf("icuexportdata version %s, ICU tool to dump data files for external consumers\n", - U_ICU_DATA_VERSION); - printf("%s\n", U_COPYRIGHT_STRING); - exit(0); - } - - /* error handling, printing usage message */ - if(argc<0) { - fprintf(stderr, - "error in command line argument \"%s\"\n", - argv[-argc]); - } else if(argc<2) { - argc=-1; - } - - /* get the options values */ - haveCopyright = options[OPT_COPYRIGHT].doesOccur; - destdir = options[OPT_DESTDIR].value; - VERBOSE = options[OPT_VERBOSE].doesOccur; - QUIET = options[OPT_QUIET].doesOccur; +void printHelp(FILE* stdfile, const char* program) { + fprintf(stdfile, + "usage: %s -m mode [-options] [--all | properties...]\n" + "\tdump Unicode property data to .toml files\n" + "options:\n" + "\t-h or -? or --help this usage text\n" + "\t-V or --version show a version message\n" + "\t-m or --mode mode: currently only 'uprops' and 'ucase', but more may be added\n" + "\t --trie-type set the trie type (small or fast, default small)\n" + "\t-d or --destdir destination directory, followed by the path\n" + "\t --all write out all properties known to icuexportdata\n" + "\t --index write an _index.toml summarizing all data exported\n" + "\t-c or --copyright include a copyright notice\n" + "\t-v or --verbose Turn on verbose output\n" + "\t-q or --quiet do not display warnings and progress\n", + program); +} +int exportUprops(int argc, char* argv[]) { // Load list of Unicode properties std::vector<const char*> propNames; for (int i=1; i<argc; i++) { propNames.push_back(argv[i]); } if (options[OPT_ALL].doesOccur) { - for (int i=UCHAR_BINARY_START; i<UCHAR_INT_LIMIT; i++) { + int i = UCHAR_BINARY_START; + while (true) { if (i == UCHAR_BINARY_LIMIT) { i = UCHAR_INT_START; } + if (i == UCHAR_INT_LIMIT) { + i = UCHAR_SCRIPT_EXTENSIONS; + } + if (i == UCHAR_SCRIPT_EXTENSIONS + 1) { + break; + } UProperty uprop = static_cast<UProperty>(i); const char* propName = u_getPropertyName(uprop, U_SHORT_PROPERTY_NAME); if (propName == NULL) { @@ -207,47 +380,10 @@ int main(int argc, char* argv[]) { } if (propName != NULL) { propNames.push_back(propName); + } else { + std::cerr << "Warning: Could not find name for: " << uprop << std::endl; } - } - } - - if (propNames.empty() - || options[OPT_HELP_H].doesOccur - || options[OPT_HELP_QUESTION_MARK].doesOccur - || !options[OPT_MODE].doesOccur) { - FILE *stdfile=argc<0 ? stderr : stdout; - fprintf(stdfile, - "usage: %s -m uprops [-options] [--all | properties...]\n" - "\tdump Unicode property data to .toml files\n" - "options:\n" - "\t-h or -? or --help this usage text\n" - "\t-V or --version show a version message\n" - "\t-m or --mode mode: currently only 'uprops', but more may be added\n" - "\t --trie-type set the trie type (small or fast, default small)\n" - "\t-d or --destdir destination directory, followed by the path\n" - "\t --all write out all properties known to icuexportdata\n" - "\t --index write an _index.toml summarizing all data exported\n" - "\t-c or --copyright include a copyright notice\n" - "\t-v or --verbose Turn on verbose output\n" - "\t-q or --quiet do not display warnings and progress\n", - argv[0]); - return argc<0 ? U_ILLEGAL_ARGUMENT_ERROR : U_ZERO_ERROR; - } - - const char* mode = options[OPT_MODE].value; - if (uprv_strcmp(mode, "uprops") != 0) { - fprintf(stderr, "Invalid option for --mode (must be uprops)\n"); - return U_ILLEGAL_ARGUMENT_ERROR; - } - - if (options[OPT_TRIE_TYPE].doesOccur) { - if (uprv_strcmp(options[OPT_TRIE_TYPE].value, "fast") == 0) { - trieType = UCPTRIE_TYPE_FAST; - } else if (uprv_strcmp(options[OPT_TRIE_TYPE].value, "small") == 0) { - trieType = UCPTRIE_TYPE_SMALL; - } else { - fprintf(stderr, "Invalid option for --trie-type (must be small or fast)\n"); - return U_ILLEGAL_ARGUMENT_ERROR; + i++; } } @@ -272,6 +408,8 @@ int main(int argc, char* argv[]) { dumpBinaryProperty(propEnum, f); } else if (UCHAR_INT_START <= propEnum && propEnum <= UCHAR_INT_LIMIT) { dumpEnumeratedProperty(propEnum, f); + } else if (propEnum == UCHAR_SCRIPT_EXTENSIONS) { + dumpScriptExtensions(f); } else { std::cerr << "Don't know how to write property: " << propEnum << std::endl; return U_INTERNAL_PROGRAM_ERROR; @@ -293,3 +431,134 @@ int main(int argc, char* argv[]) { return 0; } + +struct AddRangeHelper { + UMutableCPTrie* ucptrie; +}; + +static UBool U_CALLCONV +addRangeToUCPTrie(const void* context, UChar32 start, UChar32 end, uint32_t value) { + IcuToolErrorCode status("addRangeToUCPTrie"); + UMutableCPTrie* ucptrie = ((const AddRangeHelper*) context)->ucptrie; + umutablecptrie_setRange(ucptrie, start, end, value, status); + handleError(status, "setRange"); + + return TRUE; +} + +int exportCase(int argc, char* argv[]) { + if (argc > 1) { + fprintf(stderr, "ucase mode does not expect additional arguments\n"); + return U_ILLEGAL_ARGUMENT_ERROR; + } + (void) argv; // Suppress unused variable warning + + IcuToolErrorCode status("icuexportdata"); + LocalUMutableCPTriePointer builder(umutablecptrie_open(0, 0, status)); + handleError(status, "exportCase"); + + int32_t exceptionsLength, unfoldLength; + const UCaseProps *caseProps = ucase_getSingleton(&exceptionsLength, &unfoldLength); + const UTrie2* caseTrie = &caseProps->trie; + + AddRangeHelper helper = { builder.getAlias() }; + utrie2_enum(caseTrie, NULL, addRangeToUCPTrie, &helper); + + UCPTrieValueWidth width = UCPTRIE_VALUE_BITS_16; + LocalUCPTriePointer utrie(umutablecptrie_buildImmutable( + builder.getAlias(), + trieType, + width, + status)); + handleError(status, "exportCase"); + + FILE* f = prepareOutputFile("ucase"); + + UVersionInfo versionInfo; + u_getUnicodeVersion(versionInfo); + char uvbuf[U_MAX_VERSION_STRING_LENGTH]; + u_versionToString(versionInfo, uvbuf); + fprintf(f, "icu_version = \"%s\"\nunicode_version = \"%s\"\n\n", + U_ICU_VERSION, + uvbuf); + + fputs("[ucase.code_point_trie]\n", f); + usrc_writeUCPTrie(f, "case_trie", utrie.getAlias(), UPRV_TARGET_SYNTAX_TOML); + fputs("\n", f); + + const char* indent = " "; + const char* suffix = "\n]\n"; + + fputs("[ucase.exceptions]\n", f); + const char* exceptionsPrefix = "exceptions = [\n "; + int32_t exceptionsWidth = 16; + usrc_writeArray(f, exceptionsPrefix, caseProps->exceptions, exceptionsWidth, + exceptionsLength, indent, suffix); + fputs("\n", f); + + fputs("[ucase.unfold]\n", f); + const char* unfoldPrefix = "unfold = [\n "; + int32_t unfoldWidth = 16; + usrc_writeArray(f, unfoldPrefix, caseProps->unfold, unfoldWidth, + unfoldLength, indent, suffix); + + return 0; +} + +int main(int argc, char* argv[]) { + U_MAIN_INIT_ARGS(argc, argv); + + /* preset then read command line options */ + options[OPT_DESTDIR].value=u_getDataDirectory(); + argc=u_parseArgs(argc, argv, UPRV_LENGTHOF(options), options); + + if(options[OPT_VERSION].doesOccur) { + printf("icuexportdata version %s, ICU tool to dump data files for external consumers\n", + U_ICU_DATA_VERSION); + printf("%s\n", U_COPYRIGHT_STRING); + exit(0); + } + + /* error handling, printing usage message */ + if(argc<0) { + fprintf(stderr, + "error in command line argument \"%s\"\n", + argv[-argc]); + } + + if (argc < 0 + || options[OPT_HELP_H].doesOccur + || options[OPT_HELP_QUESTION_MARK].doesOccur + || !options[OPT_MODE].doesOccur) { + FILE *stdfile=argc<0 ? stderr : stdout; + printHelp(stdfile, argv[0]); + return argc<0 ? U_ILLEGAL_ARGUMENT_ERROR : U_ZERO_ERROR; + } + + /* get the options values */ + haveCopyright = options[OPT_COPYRIGHT].doesOccur; + destdir = options[OPT_DESTDIR].value; + VERBOSE = options[OPT_VERBOSE].doesOccur; + QUIET = options[OPT_QUIET].doesOccur; + + if (options[OPT_TRIE_TYPE].doesOccur) { + if (uprv_strcmp(options[OPT_TRIE_TYPE].value, "fast") == 0) { + trieType = UCPTRIE_TYPE_FAST; + } else if (uprv_strcmp(options[OPT_TRIE_TYPE].value, "small") == 0) { + trieType = UCPTRIE_TYPE_SMALL; + } else { + fprintf(stderr, "Invalid option for --trie-type (must be small or fast)\n"); + return U_ILLEGAL_ARGUMENT_ERROR; + } + } + + const char* mode = options[OPT_MODE].value; + if (uprv_strcmp(mode, "uprops") == 0) { + return exportUprops(argc, argv); + } else if (uprv_strcmp(mode, "ucase") == 0) { + return exportCase(argc, argv); + } + + fprintf(stderr, "Invalid option for --mode (must be uprops or ucase)\n"); + return U_ILLEGAL_ARGUMENT_ERROR; +} diff --git a/Build/source/libs/icu/icu-src/source/tools/toolutil/BUILD b/Build/source/libs/icu/icu-src/source/tools/toolutil/BUILD.bazel index 276c857f124..276c857f124 100644 --- a/Build/source/libs/icu/icu-src/source/tools/toolutil/BUILD +++ b/Build/source/libs/icu/icu-src/source/tools/toolutil/BUILD.bazel diff --git a/Build/source/libs/icu/icu-src/source/tools/toolutil/toolutil.cpp b/Build/source/libs/icu/icu-src/source/tools/toolutil/toolutil.cpp index 1fc68aa69c8..a9dc37377a8 100644 --- a/Build/source/libs/icu/icu-src/source/tools/toolutil/toolutil.cpp +++ b/Build/source/libs/icu/icu-src/source/tools/toolutil/toolutil.cpp @@ -228,18 +228,19 @@ uprv_compareGoldenFiles( std::ifstream ifs(goldenFilePath, std::ifstream::in); int32_t pos = 0; char c; - while ((c = ifs.get()) != std::char_traits<char>::eof() && pos < bufferLen) { + while (ifs.get(c) && pos < bufferLen) { if (c != buffer[pos]) { // Files differ at this position - return pos; + break; } pos++; } - if (pos < bufferLen || c != std::char_traits<char>::eof()) { - // Files are different lengths - return pos; + if (pos == bufferLen && ifs.eof()) { + // Files are same lengths + pos = -1; } - return -1; + ifs.close(); + return pos; } /*U_CAPI UDate U_EXPORT2 diff --git a/Build/source/libs/icu/icu-src/source/tools/toolutil/toolutil.vcxproj b/Build/source/libs/icu/icu-src/source/tools/toolutil/toolutil.vcxproj index b74ac41cb0e..c7088baf676 100644 --- a/Build/source/libs/icu/icu-src/source/tools/toolutil/toolutil.vcxproj +++ b/Build/source/libs/icu/icu-src/source/tools/toolutil/toolutil.vcxproj @@ -74,7 +74,7 @@ <TypeLibraryName>.\..\..\..\lib\icutu.tlb</TypeLibraryName> </Midl> <Link> - <OutputFile>..\..\..\bin\icutu70.dll</OutputFile> + <OutputFile>..\..\..\bin\icutu71.dll</OutputFile> <ProgramDatabaseFile>.\..\..\..\lib\icutu.pdb</ProgramDatabaseFile> <DataExecutionPrevention> </DataExecutionPrevention> @@ -86,7 +86,7 @@ <TypeLibraryName>.\..\..\..\lib\icutud.tlb</TypeLibraryName> </Midl> <Link> - <OutputFile>..\..\..\bin\icutu70d.dll</OutputFile> + <OutputFile>..\..\..\bin\icutu71d.dll</OutputFile> <ProgramDatabaseFile>.\..\..\..\lib\icutud.pdb</ProgramDatabaseFile> <DataExecutionPrevention> </DataExecutionPrevention> @@ -113,7 +113,7 @@ <WholeProgramOptimization>true</WholeProgramOptimization> </ClCompile> <Link> - <OutputFile>..\..\..\bin64\icutu70.dll</OutputFile> + <OutputFile>..\..\..\bin64\icutu71.dll</OutputFile> <ProgramDatabaseFile>.\..\..\..\lib64\icutu.pdb</ProgramDatabaseFile> <ImportLibrary>..\..\..\lib64\icutu.lib</ImportLibrary> </Link> @@ -123,7 +123,7 @@ <TypeLibraryName>.\..\..\..\lib64\icutud.tlb</TypeLibraryName> </Midl> <Link> - <OutputFile>..\..\..\bin64\icutu70d.dll</OutputFile> + <OutputFile>..\..\..\bin64\icutu71d.dll</OutputFile> <ProgramDatabaseFile>.\..\..\..\lib64\icutud.pdb</ProgramDatabaseFile> <ImportLibrary>..\..\..\lib64\icutud.lib</ImportLibrary> </Link> @@ -144,7 +144,7 @@ <TypeLibraryName>..\..\..\libARM\icutu.tlb</TypeLibraryName> </Midl> <Link> - <OutputFile>..\..\..\binARM\icutu70.dll</OutputFile> + <OutputFile>..\..\..\binARM\icutu71.dll</OutputFile> <ProgramDatabaseFile>.\..\..\..\libARM\icutu.pdb</ProgramDatabaseFile> <ImportLibrary>..\..\..\libARM\icutu.lib</ImportLibrary> </Link> @@ -157,7 +157,7 @@ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> </ClCompile> <Link> - <OutputFile>..\..\..\binARM\icutu70d.dll</OutputFile> + <OutputFile>..\..\..\binARM\icutu71d.dll</OutputFile> <ProgramDatabaseFile>.\..\..\..\libARM\icutud.pdb</ProgramDatabaseFile> <ImportLibrary>..\..\..\libARM\icutud.lib</ImportLibrary> </Link> @@ -178,7 +178,7 @@ <TypeLibraryName>.\..\..\..\libARM64\icutu.tlb</TypeLibraryName> </Midl> <Link> - <OutputFile>..\..\..\binARM64\icutu70.dll</OutputFile> + <OutputFile>..\..\..\binARM64\icutu71.dll</OutputFile> <ProgramDatabaseFile>.\..\..\..\libARM64\icutu.pdb</ProgramDatabaseFile> <ImportLibrary>..\..\..\libARM64\icutu.lib</ImportLibrary> </Link> @@ -191,7 +191,7 @@ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> </ClCompile> <Link> - <OutputFile>..\..\..\binARM64\icutu70d.dll</OutputFile> + <OutputFile>..\..\..\binARM64\icutu71d.dll</OutputFile> <ProgramDatabaseFile>.\..\..\..\libARM64\icutud.pdb</ProgramDatabaseFile> <ImportLibrary>..\..\..\libARM64\icutud.lib</ImportLibrary> </Link> diff --git a/Build/source/libs/icu/icu-src/source/tools/tzcode/icuregions b/Build/source/libs/icu/icu-src/source/tools/tzcode/icuregions index 851f3242d19..c3c138a1228 100644 --- a/Build/source/libs/icu/icu-src/source/tools/tzcode/icuregions +++ b/Build/source/libs/icu/icu-src/source/tools/tzcode/icuregions @@ -12,6 +12,7 @@ Africa/Asmera ER America/Coral_Harbour CA America/Montreal CA +America/Virgin VI Europe/Simferopol UA Pacific/Johnston UM |