ICU: Update to upstream release 68.2

This commit is contained in:
bruvzg 2020-12-18 23:02:48 +02:00
parent 7ad29ed64e
commit bf5ca85d61
No known key found for this signature in database
GPG Key ID: 009E1BFE42239B95
11 changed files with 275 additions and 51 deletions

View File

@ -206,7 +206,7 @@ Files extracted from upstream source:
## International Components for Unicode ## International Components for Unicode
- Upstream: https://github.com/unicode-org/icu - Upstream: https://github.com/unicode-org/icu
- Version: 68.1 - Version: 68.2
- License: Unicode - License: Unicode
Files extracted from upstream source: Files extracted from upstream source:

View File

@ -23,8 +23,10 @@ Removed from ICU 67
| File | API | ICU 67 | ICU 68 | | File | API | ICU 67 | ICU 68 |
|---|---|---|---| |---|---|---|---|
| fmtable.h | const UFormattable* icu::Formattable::toUFormattable() | StableICU 52 | (missing)
| measunit.h | LocalArray<MeasureUnit> icu::MeasureUnit::splitToSingleUnits(int32_t&, UErrorCode&) const | InternalICU 67 | (missing) | measunit.h | LocalArray<MeasureUnit> icu::MeasureUnit::splitToSingleUnits(int32_t&, UErrorCode&) const | InternalICU 67 | (missing)
| measunit.h | int32_t icu::MeasureUnit::getIndex() const | Internal | (missing) | measunit.h | int32_t icu::MeasureUnit::getIndex() const | Internal | (missing)
| measunit.h | <tt>static</tt> MeasureUnit icu::MeasureUnit::resolveUnitPerUnit(const MeasureUnit&amp;, const MeasureUnit&amp;, bool*) | Internal | (missing)
| measunit.h | <tt>static</tt> int32_t icu::MeasureUnit::getIndexCount() | Internal | (missing) | measunit.h | <tt>static</tt> int32_t icu::MeasureUnit::getIndexCount() | Internal | (missing)
| measunit.h | <tt>static</tt> int32_t icu::MeasureUnit::internalGetIndexForTypeAndSubtype(const char*, const char*) | Internal | (missing) | measunit.h | <tt>static</tt> int32_t icu::MeasureUnit::internalGetIndexForTypeAndSubtype(const char*, const char*) | Internal | (missing)
| nounit.h | UClassID icu::NoUnit::getDynamicClassID() const | DraftICU 60 | (missing) | nounit.h | UClassID icu::NoUnit::getDynamicClassID() const | DraftICU 60 | (missing)
@ -35,6 +37,7 @@ Removed from ICU 67
| nounit.h | <tt>static</tt> NoUnit icu::NoUnit::permille() | DraftICU 60 | (missing) | nounit.h | <tt>static</tt> NoUnit icu::NoUnit::permille() | DraftICU 60 | (missing)
| nounit.h | <tt>static</tt> UClassID icu::NoUnit::getStaticClassID() | DraftICU 60 | (missing) | nounit.h | <tt>static</tt> UClassID icu::NoUnit::getStaticClassID() | DraftICU 60 | (missing)
| nounit.h | void* icu::NoUnit::clone() const | DraftICU 60 | (missing) | nounit.h | void* icu::NoUnit::clone() const | DraftICU 60 | (missing)
| uniset.h | const USet* icu::UnicodeSet::toUSet() | StableICU 4.2 | (missing)
## Deprecated ## Deprecated
@ -57,6 +60,7 @@ Changed in ICU 68 (old, new)
|---|---|---|---| |---|---|---|---|
| bytestrie.h | BytesTrie&amp; icu::BytesTrie::resetToState64(uint64_t) | Draft→StableICU 65 | bytestrie.h | BytesTrie&amp; icu::BytesTrie::resetToState64(uint64_t) | Draft→StableICU 65
| bytestrie.h | uint64_t icu::BytesTrie::getState64() const | Draft→StableICU 65 | bytestrie.h | uint64_t icu::BytesTrie::getState64() const | Draft→StableICU 65
| listformatter.h | <tt>static</tt> ListFormatter* icu::ListFormatter::createInstance(const Locale&amp;, UListFormatterType, UListFormatterWidth, UErrorCode&amp;) | Draft→StableICU 67
| localebuilder.h | UBool icu::LocaleBuilder::copyErrorTo(UErrorCode&amp;) const | Draft→StableICU 65 | localebuilder.h | UBool icu::LocaleBuilder::copyErrorTo(UErrorCode&amp;) const | Draft→StableICU 65
| localematcher.h | Builder&amp; icu::LocaleMatcher::Builder::addSupportedLocale(const Locale&amp;) | Draft→StableICU 65 | localematcher.h | Builder&amp; icu::LocaleMatcher::Builder::addSupportedLocale(const Locale&amp;) | Draft→StableICU 65
| localematcher.h | Builder&amp; icu::LocaleMatcher::Builder::operator=(Builder&amp;&amp;) | Draft→StableICU 65 | localematcher.h | Builder&amp; icu::LocaleMatcher::Builder::operator=(Builder&amp;&amp;) | Draft→StableICU 65
@ -132,6 +136,13 @@ Changed in ICU 68 (old, new)
| ucal.h | int32_t ucal_getHostTimeZone(UChar*, int32_t, UErrorCode*) | Draft→StableICU 65 | ucal.h | int32_t ucal_getHostTimeZone(UChar*, int32_t, UErrorCode*) | Draft→StableICU 65
| ucharstrie.h | UCharsTrie&amp; icu::UCharsTrie::resetToState64(uint64_t) | Draft→StableICU 65 | ucharstrie.h | UCharsTrie&amp; icu::UCharsTrie::resetToState64(uint64_t) | Draft→StableICU 65
| ucharstrie.h | uint64_t icu::UCharsTrie::getState64() const | Draft→StableICU 65 | ucharstrie.h | uint64_t icu::UCharsTrie::getState64() const | Draft→StableICU 65
| ulistformatter.h | UListFormatter* ulistfmt_openForType(const char*, UListFormatterType, UListFormatterWidth, UErrorCode*) | Draft→StableICU 67
| ulistformatter.h | <tt>enum</tt> UListFormatterType::ULISTFMT_TYPE_AND | Draft→StableICU 67
| ulistformatter.h | <tt>enum</tt> UListFormatterType::ULISTFMT_TYPE_OR | Draft→StableICU 67
| ulistformatter.h | <tt>enum</tt> UListFormatterType::ULISTFMT_TYPE_UNITS | Draft→StableICU 67
| ulistformatter.h | <tt>enum</tt> UListFormatterWidth::ULISTFMT_WIDTH_NARROW | Draft→StableICU 67
| ulistformatter.h | <tt>enum</tt> UListFormatterWidth::ULISTFMT_WIDTH_SHORT | Draft→StableICU 67
| ulistformatter.h | <tt>enum</tt> UListFormatterWidth::ULISTFMT_WIDTH_WIDE | Draft→StableICU 67
| uloc.h | UEnumeration* uloc_openAvailableByType(ULocAvailableType, UErrorCode*) | Draft→StableICU 65 | uloc.h | UEnumeration* uloc_openAvailableByType(ULocAvailableType, UErrorCode*) | Draft→StableICU 65
| uloc.h | <tt>enum</tt> ULocAvailableType::ULOC_AVAILABLE_DEFAULT | Draft→StableICU 65 | uloc.h | <tt>enum</tt> ULocAvailableType::ULOC_AVAILABLE_DEFAULT | Draft→StableICU 65
| uloc.h | <tt>enum</tt> ULocAvailableType::ULOC_AVAILABLE_ONLY_LEGACY_ALIASES | Draft→StableICU 65 | uloc.h | <tt>enum</tt> ULocAvailableType::ULOC_AVAILABLE_ONLY_LEGACY_ALIASES | Draft→StableICU 65
@ -151,6 +162,8 @@ Promoted to stable in ICU 68
|---|---|---|---| |---|---|---|---|
| bytestrie.h | BytesTrie&amp; icu::BytesTrie::resetToState64(uint64_t) | Draft→StableICU 65 | bytestrie.h | BytesTrie&amp; icu::BytesTrie::resetToState64(uint64_t) | Draft→StableICU 65
| bytestrie.h | uint64_t icu::BytesTrie::getState64() const | Draft→StableICU 65 | bytestrie.h | uint64_t icu::BytesTrie::getState64() const | Draft→StableICU 65
| fmtable.h | UFormattable* icu::Formattable::toUFormattable() | (missing) | StableICU 52
| listformatter.h | <tt>static</tt> ListFormatter* icu::ListFormatter::createInstance(const Locale&amp;, UListFormatterType, UListFormatterWidth, UErrorCode&amp;) | Draft→StableICU 67
| localebuilder.h | UBool icu::LocaleBuilder::copyErrorTo(UErrorCode&amp;) const | Draft→StableICU 65 | localebuilder.h | UBool icu::LocaleBuilder::copyErrorTo(UErrorCode&amp;) const | Draft→StableICU 65
| localematcher.h | Builder&amp; icu::LocaleMatcher::Builder::addSupportedLocale(const Locale&amp;) | Draft→StableICU 65 | localematcher.h | Builder&amp; icu::LocaleMatcher::Builder::addSupportedLocale(const Locale&amp;) | Draft→StableICU 65
| localematcher.h | Builder&amp; icu::LocaleMatcher::Builder::operator=(Builder&amp;&amp;) | Draft→StableICU 65 | localematcher.h | Builder&amp; icu::LocaleMatcher::Builder::operator=(Builder&amp;&amp;) | Draft→StableICU 65
@ -224,10 +237,18 @@ Promoted to stable in ICU 68
| ucal.h | int32_t ucal_getHostTimeZone(UChar*, int32_t, UErrorCode*) | Draft→StableICU 65 | ucal.h | int32_t ucal_getHostTimeZone(UChar*, int32_t, UErrorCode*) | Draft→StableICU 65
| ucharstrie.h | UCharsTrie&amp; icu::UCharsTrie::resetToState64(uint64_t) | Draft→StableICU 65 | ucharstrie.h | UCharsTrie&amp; icu::UCharsTrie::resetToState64(uint64_t) | Draft→StableICU 65
| ucharstrie.h | uint64_t icu::UCharsTrie::getState64() const | Draft→StableICU 65 | ucharstrie.h | uint64_t icu::UCharsTrie::getState64() const | Draft→StableICU 65
| ulistformatter.h | UListFormatter* ulistfmt_openForType(const char*, UListFormatterType, UListFormatterWidth, UErrorCode*) | Draft→StableICU 67
| ulistformatter.h | <tt>enum</tt> UListFormatterType::ULISTFMT_TYPE_AND | Draft→StableICU 67
| ulistformatter.h | <tt>enum</tt> UListFormatterType::ULISTFMT_TYPE_OR | Draft→StableICU 67
| ulistformatter.h | <tt>enum</tt> UListFormatterType::ULISTFMT_TYPE_UNITS | Draft→StableICU 67
| ulistformatter.h | <tt>enum</tt> UListFormatterWidth::ULISTFMT_WIDTH_NARROW | Draft→StableICU 67
| ulistformatter.h | <tt>enum</tt> UListFormatterWidth::ULISTFMT_WIDTH_SHORT | Draft→StableICU 67
| ulistformatter.h | <tt>enum</tt> UListFormatterWidth::ULISTFMT_WIDTH_WIDE | Draft→StableICU 67
| uloc.h | UEnumeration* uloc_openAvailableByType(ULocAvailableType, UErrorCode*) | Draft→StableICU 65 | uloc.h | UEnumeration* uloc_openAvailableByType(ULocAvailableType, UErrorCode*) | Draft→StableICU 65
| uloc.h | <tt>enum</tt> ULocAvailableType::ULOC_AVAILABLE_DEFAULT | Draft→StableICU 65 | uloc.h | <tt>enum</tt> ULocAvailableType::ULOC_AVAILABLE_DEFAULT | Draft→StableICU 65
| uloc.h | <tt>enum</tt> ULocAvailableType::ULOC_AVAILABLE_ONLY_LEGACY_ALIASES | Draft→StableICU 65 | uloc.h | <tt>enum</tt> ULocAvailableType::ULOC_AVAILABLE_ONLY_LEGACY_ALIASES | Draft→StableICU 65
| uloc.h | <tt>enum</tt> ULocAvailableType::ULOC_AVAILABLE_WITH_LEGACY_ALIASES | Draft→StableICU 65 | uloc.h | <tt>enum</tt> ULocAvailableType::ULOC_AVAILABLE_WITH_LEGACY_ALIASES | Draft→StableICU 65
| uniset.h | USet* icu::UnicodeSet::toUSet() | (missing) | StableICU 4.2
| utrace.h | <tt>enum</tt> UTraceFunctionNumber::UTRACE_UDATA_BUNDLE | Draft→StableICU 65 | utrace.h | <tt>enum</tt> UTraceFunctionNumber::UTRACE_UDATA_BUNDLE | Draft→StableICU 65
| utrace.h | <tt>enum</tt> UTraceFunctionNumber::UTRACE_UDATA_DATA_FILE | Draft→StableICU 65 | utrace.h | <tt>enum</tt> UTraceFunctionNumber::UTRACE_UDATA_DATA_FILE | Draft→StableICU 65
| utrace.h | <tt>enum</tt> UTraceFunctionNumber::UTRACE_UDATA_RES_FILE | Draft→StableICU 65 | utrace.h | <tt>enum</tt> UTraceFunctionNumber::UTRACE_UDATA_RES_FILE | Draft→StableICU 65
@ -242,6 +263,7 @@ Added in ICU 68
| dtitvfmt.h | UDisplayContext icu::DateIntervalFormat::getContext(UDisplayContextType, UErrorCode&amp;) const | (missing) | DraftICU 68 | dtitvfmt.h | UDisplayContext icu::DateIntervalFormat::getContext(UDisplayContextType, UErrorCode&amp;) const | (missing) | DraftICU 68
| dtitvfmt.h | void icu::DateIntervalFormat::setContext(UDisplayContext, UErrorCode&amp;) | (missing) | DraftICU 68 | dtitvfmt.h | void icu::DateIntervalFormat::setContext(UDisplayContext, UErrorCode&amp;) | (missing) | DraftICU 68
| dtptngen.h | <tt>static</tt> DateTimePatternGenerator* icu::DateTimePatternGenerator::createInstanceNoStdPat(const Locale&amp;, UErrorCode&amp;) | (missing) | Internal | dtptngen.h | <tt>static</tt> DateTimePatternGenerator* icu::DateTimePatternGenerator::createInstanceNoStdPat(const Locale&amp;, UErrorCode&amp;) | (missing) | Internal
| fmtable.h | UFormattable* icu::Formattable::toUFormattable() | (missing) | StableICU 52
| localematcher.h | Builder&amp; icu::LocaleMatcher::Builder::setMaxDistance(const Locale&amp;, const Locale&amp;) | (missing) | DraftICU 68 | localematcher.h | Builder&amp; icu::LocaleMatcher::Builder::setMaxDistance(const Locale&amp;, const Locale&amp;) | (missing) | DraftICU 68
| localematcher.h | Builder&amp; icu::LocaleMatcher::Builder::setNoDefaultLocale() | (missing) | DraftICU 68 | localematcher.h | Builder&amp; icu::LocaleMatcher::Builder::setNoDefaultLocale() | (missing) | DraftICU 68
| localematcher.h | UBool icu::LocaleMatcher::isMatch(const Locale&amp;, const Locale&amp;, UErrorCode&amp;) const | (missing) | DraftICU 68 | localematcher.h | UBool icu::LocaleMatcher::isMatch(const Locale&amp;, const Locale&amp;, UErrorCode&amp;) const | (missing) | DraftICU 68
@ -285,12 +307,14 @@ Added in ICU 68
| numberrangeformatter.h | std::pair&lt; StringClass, StringClass &gt; icu::number::FormattedNumberRange::getDecimalNumbers(UErrorCode&amp;) const | (missing) | DraftICU 68 | numberrangeformatter.h | std::pair&lt; StringClass, StringClass &gt; icu::number::FormattedNumberRange::getDecimalNumbers(UErrorCode&amp;) const | (missing) | DraftICU 68
| plurrule.h | UnicodeString icu::PluralRules::select(const number::FormattedNumberRange&amp;, UErrorCode&amp;) const | (missing) | DraftICU 68 | plurrule.h | UnicodeString icu::PluralRules::select(const number::FormattedNumberRange&amp;, UErrorCode&amp;) const | (missing) | DraftICU 68
| plurrule.h | UnicodeString icu::PluralRules::select(const number::impl::UFormattedNumberRangeData*, UErrorCode&amp;) const | (missing) | Internal | plurrule.h | UnicodeString icu::PluralRules::select(const number::impl::UFormattedNumberRangeData*, UErrorCode&amp;) const | (missing) | Internal
| plurrule.h | int32_t icu::PluralRules::getSamples(const UnicodeString&amp;, FixedDecimal*, int32_t, UErrorCode&amp;) | (missing) | Internal
| timezone.h | <tt>static</tt> TimeZone* icu::TimeZone::forLocaleOrDefault(const Locale&amp;) | (missing) | Internal | timezone.h | <tt>static</tt> TimeZone* icu::TimeZone::forLocaleOrDefault(const Locale&amp;) | (missing) | Internal
| ucurr.h | <tt>enum</tt> UCurrNameStyle::UCURR_FORMAL_SYMBOL_NAME | (missing) | DraftICU 68 | ucurr.h | <tt>enum</tt> UCurrNameStyle::UCURR_FORMAL_SYMBOL_NAME | (missing) | DraftICU 68
| ucurr.h | <tt>enum</tt> UCurrNameStyle::UCURR_VARIANT_SYMBOL_NAME | (missing) | DraftICU 68 | ucurr.h | <tt>enum</tt> UCurrNameStyle::UCURR_VARIANT_SYMBOL_NAME | (missing) | DraftICU 68
| udateintervalformat.h | UDisplayContext udtitvfmt_getContext(const UDateIntervalFormat*, UDisplayContextType, UErrorCode*) | (missing) | DraftICU 68 | udateintervalformat.h | UDisplayContext udtitvfmt_getContext(const UDateIntervalFormat*, UDisplayContextType, UErrorCode*) | (missing) | DraftICU 68
| udateintervalformat.h | void udtitvfmt_setContext(UDateIntervalFormat*, UDisplayContext, UErrorCode*) | (missing) | DraftICU 68 | udateintervalformat.h | void udtitvfmt_setContext(UDateIntervalFormat*, UDisplayContext, UErrorCode*) | (missing) | DraftICU 68
| umachine.h | <tt>#define</tt> U_DEFINE_FALSE_AND_TRUE | (missing) | InternalICU 68 | umachine.h | <tt>#define</tt> U_DEFINE_FALSE_AND_TRUE | (missing) | InternalICU 68
| uniset.h | USet* icu::UnicodeSet::toUSet() | (missing) | StableICU 4.2
| unum.h | <tt>enum</tt> UNumberFormatMinimumGroupingDigits::UNUM_MINIMUM_GROUPING_DIGITS_AUTO | (missing) | DraftICU 68 | unum.h | <tt>enum</tt> UNumberFormatMinimumGroupingDigits::UNUM_MINIMUM_GROUPING_DIGITS_AUTO | (missing) | DraftICU 68
| unum.h | <tt>enum</tt> UNumberFormatMinimumGroupingDigits::UNUM_MINIMUM_GROUPING_DIGITS_MIN2 | (missing) | DraftICU 68 | unum.h | <tt>enum</tt> UNumberFormatMinimumGroupingDigits::UNUM_MINIMUM_GROUPING_DIGITS_MIN2 | (missing) | DraftICU 68
| unumberformatter.h | <tt>enum</tt> UNumberUnitWidth::UNUM_UNIT_WIDTH_FORMAL | (missing) | DraftICU 68 | unumberformatter.h | <tt>enum</tt> UNumberUnitWidth::UNUM_UNIT_WIDTH_FORMAL | (missing) | DraftICU 68
@ -317,7 +341,6 @@ Other existing drafts in ICU 68
| bytestream.h | void icu::ByteSink::AppendU8(const char*, int32_t) | DraftICU 67 | | bytestream.h | void icu::ByteSink::AppendU8(const char*, int32_t) | DraftICU 67 |
| bytestream.h | void icu::ByteSink::AppendU8(const char8_t*, int32_t) | DraftICU 67 | | bytestream.h | void icu::ByteSink::AppendU8(const char8_t*, int32_t) | DraftICU 67 |
| dtptngen.h | UDateFormatHourCycle icu::DateTimePatternGenerator::getDefaultHourCycle(UErrorCode&amp;) const | DraftICU 67 | | dtptngen.h | UDateFormatHourCycle icu::DateTimePatternGenerator::getDefaultHourCycle(UErrorCode&amp;) const | DraftICU 67 |
| listformatter.h | <tt>static</tt> ListFormatter* icu::ListFormatter::createInstance(const Locale&amp;, UListFormatterType, UListFormatterWidth, UErrorCode&amp;) | DraftICU 67 |
| localematcher.h | Builder&amp; icu::LocaleMatcher::Builder::setDirection(ULocMatchDirection) | DraftICU 67 | | localematcher.h | Builder&amp; icu::LocaleMatcher::Builder::setDirection(ULocMatchDirection) | DraftICU 67 |
| localematcher.h | <tt>enum</tt> ULocMatchDirection::ULOCMATCH_DIRECTION_ONLY_TWO_WAY | DraftICU 67 | | localematcher.h | <tt>enum</tt> ULocMatchDirection::ULOCMATCH_DIRECTION_ONLY_TWO_WAY | DraftICU 67 |
| localematcher.h | <tt>enum</tt> ULocMatchDirection::ULOCMATCH_DIRECTION_WITH_ONE_WAY | DraftICU 67 | | localematcher.h | <tt>enum</tt> ULocMatchDirection::ULOCMATCH_DIRECTION_WITH_ONE_WAY | DraftICU 67 |
@ -349,13 +372,6 @@ Other existing drafts in ICU 68
| udateintervalformat.h | void udtitvfmt_formatCalendarToResult(const UDateIntervalFormat*, UCalendar*, UCalendar*, UFormattedDateInterval*, UErrorCode*) | DraftICU 67 | | udateintervalformat.h | void udtitvfmt_formatCalendarToResult(const UDateIntervalFormat*, UCalendar*, UCalendar*, UFormattedDateInterval*, UErrorCode*) | DraftICU 67 |
| udateintervalformat.h | void udtitvfmt_formatToResult(const UDateIntervalFormat*, UDate, UDate, UFormattedDateInterval*, UErrorCode*) | DraftICU 67 | | udateintervalformat.h | void udtitvfmt_formatToResult(const UDateIntervalFormat*, UDate, UDate, UFormattedDateInterval*, UErrorCode*) | DraftICU 67 |
| udatpg.h | UDateFormatHourCycle udatpg_getDefaultHourCycle(const UDateTimePatternGenerator*, UErrorCode*) | DraftICU 67 | | udatpg.h | UDateFormatHourCycle udatpg_getDefaultHourCycle(const UDateTimePatternGenerator*, UErrorCode*) | DraftICU 67 |
| ulistformatter.h | UListFormatter* ulistfmt_openForType(const char*, UListFormatterType, UListFormatterWidth, UErrorCode*) | DraftICU 67 |
| ulistformatter.h | <tt>enum</tt> UListFormatterType::ULISTFMT_TYPE_AND | DraftICU 67 |
| ulistformatter.h | <tt>enum</tt> UListFormatterType::ULISTFMT_TYPE_OR | DraftICU 67 |
| ulistformatter.h | <tt>enum</tt> UListFormatterType::ULISTFMT_TYPE_UNITS | DraftICU 67 |
| ulistformatter.h | <tt>enum</tt> UListFormatterWidth::ULISTFMT_WIDTH_NARROW | DraftICU 67 |
| ulistformatter.h | <tt>enum</tt> UListFormatterWidth::ULISTFMT_WIDTH_SHORT | DraftICU 67 |
| ulistformatter.h | <tt>enum</tt> UListFormatterWidth::ULISTFMT_WIDTH_WIDE | DraftICU 67 |
| uregex.h | <tt>enum</tt> URegexpFlag::UREGEX_CANON_EQ | DraftICU 2.4 | | uregex.h | <tt>enum</tt> URegexpFlag::UREGEX_CANON_EQ | DraftICU 2.4 |
| utrace.h | <tt>enum</tt> UTraceFunctionNumber::UTRACE_UBRK_CREATE_BREAK_ENGINE | DraftICU 67 | | utrace.h | <tt>enum</tt> UTraceFunctionNumber::UTRACE_UBRK_CREATE_BREAK_ENGINE | DraftICU 67 |
| utrace.h | <tt>enum</tt> UTraceFunctionNumber::UTRACE_UBRK_CREATE_CHARACTER | DraftICU 67 | | utrace.h | <tt>enum</tt> UTraceFunctionNumber::UTRACE_UBRK_CREATE_CHARACTER | DraftICU 67 |
@ -373,7 +389,7 @@ This section shows cases where the signature was "simplified" for the sake of co
## Colophon ## Colophon
Contents generated by StableAPI tool on Wed Sep 30 17:44:26 PDT 2020 Contents generated by StableAPI tool on Fri Oct 23 11:32:42 PDT 2020
Copyright © 2019 and later: Unicode, Inc. and others. Copyright © 2019 and later: Unicode, Inc. and others.
License & terms of use: http://www.unicode.org/copyright.html License & terms of use: http://www.unicode.org/copyright.html

View File

@ -725,9 +725,14 @@ public:
} }
MemoryPool& operator=(MemoryPool&& other) U_NOEXCEPT { MemoryPool& operator=(MemoryPool&& other) U_NOEXCEPT {
fCount = other.fCount; // Since `this` may contain instances that need to be deleted, we can't
fPool = std::move(other.fPool); // just throw them away and replace them with `other`. The normal way of
other.fCount = 0; // dealing with this in C++ is to swap `this` and `other`, rather than
// simply overwrite: the destruction of `other` can then take care of
// running MemoryPool::~MemoryPool() over the still-to-be-deallocated
// instances.
std::swap(fCount, other.fCount);
std::swap(fPool, other.fPool);
return *this; return *this;
} }
@ -796,9 +801,6 @@ protected:
template<typename T, int32_t stackCapacity = 8> template<typename T, int32_t stackCapacity = 8>
class MaybeStackVector : protected MemoryPool<T, stackCapacity> { class MaybeStackVector : protected MemoryPool<T, stackCapacity> {
public: public:
using MemoryPool<T, stackCapacity>::MemoryPool;
using MemoryPool<T, stackCapacity>::operator=;
template<typename... Args> template<typename... Args>
T* emplaceBack(Args&&... args) { T* emplaceBack(Args&&... args) {
return this->create(args...); return this->create(args...);

View File

@ -35,6 +35,7 @@
#include "unicode/bytestream.h" #include "unicode/bytestream.h"
#include "unicode/locid.h" #include "unicode/locid.h"
#include "unicode/localebuilder.h"
#include "unicode/strenum.h" #include "unicode/strenum.h"
#include "unicode/stringpiece.h" #include "unicode/stringpiece.h"
#include "unicode/uloc.h" #include "unicode/uloc.h"
@ -1028,7 +1029,7 @@ public:
// place the the replaced locale ID in out and return true. // place the the replaced locale ID in out and return true.
// Otherwise return false for no replacement or error. // Otherwise return false for no replacement or error.
bool replace( bool replace(
const Locale& locale, CharString& out, UErrorCode status); const Locale& locale, CharString& out, UErrorCode& status);
private: private:
const char* language; const char* language;
@ -1336,10 +1337,13 @@ AliasReplacer::replaceTerritory(UVector& toBeFreed, UErrorCode& status)
// Cannot use nullptr for language because that will construct // Cannot use nullptr for language because that will construct
// the default locale, in that case, use "und" to get the correct // the default locale, in that case, use "und" to get the correct
// locale. // locale.
Locale l(language == nullptr ? "und" : language, nullptr, script); Locale l = LocaleBuilder()
.setLanguage(language == nullptr ? "und" : language)
.setScript(script)
.build(status);
l.addLikelySubtags(status); l.addLikelySubtags(status);
const char* likelyRegion = l.getCountry(); const char* likelyRegion = l.getCountry();
CharString* item = nullptr; LocalPointer<CharString> item;
if (likelyRegion != nullptr && uprv_strlen(likelyRegion) > 0) { if (likelyRegion != nullptr && uprv_strlen(likelyRegion) > 0) {
size_t len = uprv_strlen(likelyRegion); size_t len = uprv_strlen(likelyRegion);
const char* foundInReplacement = uprv_strstr(replacement, const char* foundInReplacement = uprv_strstr(replacement,
@ -1351,20 +1355,22 @@ AliasReplacer::replaceTerritory(UVector& toBeFreed, UErrorCode& status)
*(foundInReplacement-1) == ' '); *(foundInReplacement-1) == ' ');
U_ASSERT(foundInReplacement[len] == ' ' || U_ASSERT(foundInReplacement[len] == ' ' ||
foundInReplacement[len] == '\0'); foundInReplacement[len] == '\0');
item = new CharString(foundInReplacement, (int32_t)len, status); item.adoptInsteadAndCheckErrorCode(
new CharString(foundInReplacement, (int32_t)len, status), status);
} }
} }
if (item == nullptr) { if (item.isNull() && U_SUCCESS(status)) {
item = new CharString(replacement, item.adoptInsteadAndCheckErrorCode(
(int32_t)(firstSpace - replacement), status); new CharString(replacement,
(int32_t)(firstSpace - replacement), status), status);
} }
if (U_FAILURE(status)) { return false; } if (U_FAILURE(status)) { return false; }
if (item == nullptr) { if (item.isNull()) {
status = U_MEMORY_ALLOCATION_ERROR; status = U_MEMORY_ALLOCATION_ERROR;
return false; return false;
} }
replacedRegion = item->data(); replacedRegion = item->data();
toBeFreed.addElement(item, status); toBeFreed.addElement(item.orphan(), status);
} }
U_ASSERT(!same(region, replacedRegion)); U_ASSERT(!same(region, replacedRegion));
region = replacedRegion; region = replacedRegion;
@ -1453,7 +1459,7 @@ AliasReplacer::outputToString(
int32_t variantsStart = out.length(); int32_t variantsStart = out.length();
for (int32_t i = 0; i < variants.size(); i++) { for (int32_t i = 0; i < variants.size(); i++) {
out.append(SEP_CHAR, status) out.append(SEP_CHAR, status)
.append((const char*)((UVector*)variants.elementAt(i)), .append((const char*)(variants.elementAt(i)),
status); status);
} }
T_CString_toUpperCase(out.data() + variantsStart); T_CString_toUpperCase(out.data() + variantsStart);
@ -1470,7 +1476,7 @@ AliasReplacer::outputToString(
} }
bool bool
AliasReplacer::replace(const Locale& locale, CharString& out, UErrorCode status) AliasReplacer::replace(const Locale& locale, CharString& out, UErrorCode& status)
{ {
data = AliasData::singleton(status); data = AliasData::singleton(status);
if (U_FAILURE(status)) { if (U_FAILURE(status)) {
@ -2453,9 +2459,13 @@ Locale::setKeywordValue(const char* keywordName, const char* keywordValue, UErro
if (U_FAILURE(status)) { if (U_FAILURE(status)) {
return; return;
} }
if (status == U_STRING_NOT_TERMINATED_WARNING) {
status = U_ZERO_ERROR;
}
int32_t bufferLength = uprv_max((int32_t)(uprv_strlen(fullName) + 1), ULOC_FULLNAME_CAPACITY); int32_t bufferLength = uprv_max((int32_t)(uprv_strlen(fullName) + 1), ULOC_FULLNAME_CAPACITY);
int32_t newLength = uloc_setKeywordValue(keywordName, keywordValue, fullName, int32_t newLength = uloc_setKeywordValue(keywordName, keywordValue, fullName,
bufferLength, &status) + 1; bufferLength, &status) + 1;
U_ASSERT(status != U_STRING_NOT_TERMINATED_WARNING);
/* Handle the case the current buffer is not enough to hold the new id */ /* Handle the case the current buffer is not enough to hold the new id */
if (status == U_BUFFER_OVERFLOW_ERROR) { if (status == U_BUFFER_OVERFLOW_ERROR) {
U_ASSERT(newLength > bufferLength); U_ASSERT(newLength > bufferLength);
@ -2472,6 +2482,7 @@ Locale::setKeywordValue(const char* keywordName, const char* keywordValue, UErro
fullName = newFullName; fullName = newFullName;
status = U_ZERO_ERROR; status = U_ZERO_ERROR;
uloc_setKeywordValue(keywordName, keywordValue, fullName, newLength, &status); uloc_setKeywordValue(keywordName, keywordValue, fullName, newLength, &status);
U_ASSERT(status != U_STRING_NOT_TERMINATED_WARNING);
} else { } else {
U_ASSERT(newLength <= bufferLength); U_ASSERT(newLength <= bufferLength);
} }

View File

@ -1402,12 +1402,13 @@ void RBBITableBuilder::exportTable(void *where) {
U_ASSERT (sd->fAccepting <= 255); U_ASSERT (sd->fAccepting <= 255);
U_ASSERT (sd->fLookAhead <= 255); U_ASSERT (sd->fLookAhead <= 255);
U_ASSERT (0 <= sd->fTagsIdx && sd->fTagsIdx <= 255); U_ASSERT (0 <= sd->fTagsIdx && sd->fTagsIdx <= 255);
row->r8.fAccepting = sd->fAccepting; RBBIStateTableRow8 *r8 = (RBBIStateTableRow8*)row;
row->r8.fLookAhead = sd->fLookAhead; r8->fAccepting = sd->fAccepting;
row->r8.fTagsIdx = sd->fTagsIdx; r8->fLookAhead = sd->fLookAhead;
r8->fTagsIdx = sd->fTagsIdx;
for (col=0; col<catCount; col++) { for (col=0; col<catCount; col++) {
U_ASSERT (sd->fDtran->elementAti(col) <= kMaxStateFor8BitsTable); U_ASSERT (sd->fDtran->elementAti(col) <= kMaxStateFor8BitsTable);
row->r8.fNextState[col] = sd->fDtran->elementAti(col); r8->fNextState[col] = sd->fDtran->elementAti(col);
} }
} else { } else {
U_ASSERT (sd->fAccepting <= 0xffff); U_ASSERT (sd->fAccepting <= 0xffff);
@ -1603,12 +1604,13 @@ void RBBITableBuilder::exportSafeTable(void *where) {
UnicodeString *rowString = (UnicodeString *)fSafeTable->elementAt(state); UnicodeString *rowString = (UnicodeString *)fSafeTable->elementAt(state);
RBBIStateTableRow *row = (RBBIStateTableRow *)(table->fTableData + state*table->fRowLen); RBBIStateTableRow *row = (RBBIStateTableRow *)(table->fTableData + state*table->fRowLen);
if (use8BitsForSafeTable()) { if (use8BitsForSafeTable()) {
row->r8.fAccepting = 0; RBBIStateTableRow8 *r8 = (RBBIStateTableRow8*)row;
row->r8.fLookAhead = 0; r8->fAccepting = 0;
row->r8.fTagsIdx = 0; r8->fLookAhead = 0;
r8->fTagsIdx = 0;
for (col=0; col<catCount; col++) { for (col=0; col<catCount; col++) {
U_ASSERT(rowString->charAt(col) <= kMaxStateFor8BitsTable); U_ASSERT(rowString->charAt(col) <= kMaxStateFor8BitsTable);
row->r8.fNextState[col] = static_cast<uint8_t>(rowString->charAt(col)); r8->fNextState[col] = static_cast<uint8_t>(rowString->charAt(col));
} }
} else { } else {
row->r16.fAccepting = 0; row->r16.fAccepting = 0;

View File

@ -877,6 +877,9 @@ uloc_setKeywordValue(const char* keywordName,
if(U_FAILURE(*status)) { if(U_FAILURE(*status)) {
return -1; return -1;
} }
if (*status == U_STRING_NOT_TERMINATED_WARNING) {
*status = U_ZERO_ERROR;
}
if (keywordName == NULL || keywordName[0] == 0 || bufferCapacity <= 1) { if (keywordName == NULL || keywordName[0] == 0 || bufferCapacity <= 1) {
*status = U_ILLEGAL_ARGUMENT_ERROR; *status = U_ILLEGAL_ARGUMENT_ERROR;
return 0; return 0;
@ -914,6 +917,7 @@ uloc_setKeywordValue(const char* keywordName,
startSearchHere = (char*)locale_getKeywordsStart(buffer); startSearchHere = (char*)locale_getKeywordsStart(buffer);
if(startSearchHere == NULL || (startSearchHere[1]==0)) { if(startSearchHere == NULL || (startSearchHere[1]==0)) {
if(keywordValueLen == 0) { /* no keywords = nothing to remove */ if(keywordValueLen == 0) { /* no keywords = nothing to remove */
U_ASSERT(*status != U_STRING_NOT_TERMINATED_WARNING);
return bufLen; return bufLen;
} }
@ -933,6 +937,7 @@ uloc_setKeywordValue(const char* keywordName,
startSearchHere += keywordNameLen; startSearchHere += keywordNameLen;
*startSearchHere++ = '='; *startSearchHere++ = '=';
uprv_strcpy(startSearchHere, keywordValueBuffer); uprv_strcpy(startSearchHere, keywordValueBuffer);
U_ASSERT(*status != U_STRING_NOT_TERMINATED_WARNING);
return needLen; return needLen;
} /* end shortcut - no @ */ } /* end shortcut - no @ */
@ -1047,13 +1052,27 @@ uloc_setKeywordValue(const char* keywordName,
if (!handledInputKeyAndValue || U_FAILURE(*status)) { if (!handledInputKeyAndValue || U_FAILURE(*status)) {
/* if input key/value specified removal of a keyword not present in locale, or /* if input key/value specified removal of a keyword not present in locale, or
* there was an error in CharString.append, leave original locale alone. */ * there was an error in CharString.append, leave original locale alone. */
U_ASSERT(*status != U_STRING_NOT_TERMINATED_WARNING);
return bufLen; return bufLen;
} }
// needLen = length of the part before '@' // needLen = length of the part before '@'
needLen = (int32_t)(startSearchHere - buffer); needLen = (int32_t)(startSearchHere - buffer);
return needLen + updatedKeysAndValues.extract( // Check to see can we fit the startSearchHere, if not, return
// U_BUFFER_OVERFLOW_ERROR without copy updatedKeysAndValues into it.
// We do this because this API function does not behave like most others:
// It promises never to set a U_STRING_NOT_TERMINATED_WARNING.
// When the contents fits but without the terminating NUL, in this case we need to not change
// the buffer contents and return with a buffer overflow error.
int32_t appendLength = updatedKeysAndValues.length();
if (appendLength >= bufferCapacity - needLen) {
*status = U_BUFFER_OVERFLOW_ERROR;
return needLen + appendLength;
}
needLen += updatedKeysAndValues.extract(
startSearchHere, bufferCapacity - needLen, *status); startSearchHere, bufferCapacity - needLen, *status);
U_ASSERT(*status != U_STRING_NOT_TERMINATED_WARNING);
return needLen;
} }
/* ### ID parsing implementation **************************************************/ /* ### ID parsing implementation **************************************************/

View File

@ -143,6 +143,11 @@
* <td>icu::MessageFormat</td> * <td>icu::MessageFormat</td>
* </tr> * </tr>
* <tr> * <tr>
* <td>List Formatting</td>
* <td>ulistformatter.h</td>
* <td>icu::ListFormatter</td>
* </tr>
* <tr>
* <td>Number Formatting<br/>(includes currency and unit formatting)</td> * <td>Number Formatting<br/>(includes currency and unit formatting)</td>
* <td>unumberformatter.h, unum.h</td> * <td>unumberformatter.h, unum.h</td>
* <td>icu::number::NumberFormatter (ICU 60+) or icu::NumberFormat (older versions)</td> * <td>icu::number::NumberFormatter (ICU 60+) or icu::NumberFormat (older versions)</td>

View File

@ -1137,6 +1137,7 @@
#define ulocimp_toLanguageTag U_ICU_ENTRY_POINT_RENAME(ulocimp_toLanguageTag) #define ulocimp_toLanguageTag U_ICU_ENTRY_POINT_RENAME(ulocimp_toLanguageTag)
#define ulocimp_toLegacyKey U_ICU_ENTRY_POINT_RENAME(ulocimp_toLegacyKey) #define ulocimp_toLegacyKey U_ICU_ENTRY_POINT_RENAME(ulocimp_toLegacyKey)
#define ulocimp_toLegacyType U_ICU_ENTRY_POINT_RENAME(ulocimp_toLegacyType) #define ulocimp_toLegacyType U_ICU_ENTRY_POINT_RENAME(ulocimp_toLegacyType)
#define ultag_getTKeyStart U_ICU_ENTRY_POINT_RENAME(ultag_getTKeyStart)
#define ultag_isExtensionSubtags U_ICU_ENTRY_POINT_RENAME(ultag_isExtensionSubtags) #define ultag_isExtensionSubtags U_ICU_ENTRY_POINT_RENAME(ultag_isExtensionSubtags)
#define ultag_isLanguageSubtag U_ICU_ENTRY_POINT_RENAME(ultag_isLanguageSubtag) #define ultag_isLanguageSubtag U_ICU_ENTRY_POINT_RENAME(ultag_isLanguageSubtag)
#define ultag_isPrivateuseValueSubtags U_ICU_ENTRY_POINT_RENAME(ultag_isPrivateuseValueSubtags) #define ultag_isPrivateuseValueSubtags U_ICU_ENTRY_POINT_RENAME(ultag_isPrivateuseValueSubtags)

View File

@ -66,7 +66,7 @@
* This value will change in the subsequent releases of ICU * This value will change in the subsequent releases of ICU
* @stable ICU 2.6 * @stable ICU 2.6
*/ */
#define U_ICU_VERSION_MINOR_NUM 1 #define U_ICU_VERSION_MINOR_NUM 2
/** The current ICU patchlevel version as an integer. /** The current ICU patchlevel version as an integer.
* This value will change in the subsequent releases of ICU * This value will change in the subsequent releases of ICU
@ -139,7 +139,7 @@
* This value will change in the subsequent releases of ICU * This value will change in the subsequent releases of ICU
* @stable ICU 2.4 * @stable ICU 2.4
*/ */
#define U_ICU_VERSION "68.1" #define U_ICU_VERSION "68.2"
/** /**
* The current ICU library major version number as a string, for library name suffixes. * The current ICU library major version number as a string, for library name suffixes.
@ -158,7 +158,7 @@
/** Data version in ICU4C. /** Data version in ICU4C.
* @internal ICU 4.4 Internal Use Only * @internal ICU 4.4 Internal Use Only
**/ **/
#define U_ICU_DATA_VERSION "68.1" #define U_ICU_DATA_VERSION "68.2"
#endif /* U_HIDE_INTERNAL_API */ #endif /* U_HIDE_INTERNAL_API */
/*=========================================================================== /*===========================================================================

View File

@ -36,17 +36,58 @@
U_NAMESPACE_BEGIN U_NAMESPACE_BEGIN
// Note these constants and the struct are only used when dealing with the fallback path for RDP sesssions.
// This is the location of the time zones in the registry on Vista+ systems.
// See: https://docs.microsoft.com/windows/win32/api/timezoneapi/ns-timezoneapi-dynamic_time_zone_information
#define WINDOWS_TIMEZONES_REG_KEY_PATH L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones"
// Max length for a registry key is 255. +1 for null.
// See: https://docs.microsoft.com/windows/win32/sysinfo/registry-element-size-limits
#define WINDOWS_MAX_REG_KEY_LENGTH 256
#if U_PLATFORM_HAS_WINUWP_API == 0
// This is the layout of the TZI binary value in the registry.
// See: https://docs.microsoft.com/windows/win32/api/timezoneapi/ns-timezoneapi-time_zone_information
typedef struct _REG_TZI_FORMAT {
LONG Bias;
LONG StandardBias;
LONG DaylightBias;
SYSTEMTIME StandardDate;
SYSTEMTIME DaylightDate;
} REG_TZI_FORMAT;
#endif // U_PLATFORM_HAS_WINUWP_API
/** /**
* Main Windows time zone detection function. * This is main Windows time zone detection function.
* Returns the Windows time zone converted to an ICU time zone as a heap-allocated buffer, or nullptr upon failure.
* *
* Note: We use the Win32 API GetDynamicTimeZoneInformation (available since Vista+) to get the current time zone info. * It returns the Windows time zone converted to an ICU time zone as a heap-allocated buffer, or nullptr upon failure.
* This API returns a non-localized time zone name, which is mapped to an ICU time zone ID (~ Olsen ID). *
* We use the Win32 API GetDynamicTimeZoneInformation (which is available since Vista) to get the current time zone info,
* as this API returns a non-localized time zone name which can be then mapped to an ICU time zone.
*
* However, in some RDP/terminal services situations, this struct isn't always fully complete, and the TimeZoneKeyName
* field of the struct might be NULL. This can happen with some 3rd party RDP clients, and also when using older versions
* of the RDP protocol, which don't send the newer TimeZoneKeyNamei information and only send the StandardName and DaylightName.
*
* Since these 3rd party clients and older RDP clients only send the pre-Vista time zone information to the server, this means that we
* need to fallback on using the pre-Vista methods to determine the time zone. This unfortunately requires examining the registry directly
* in order to try and determine the current time zone.
*
* Note that this can however still fail in some cases though if the client and server are using different languages, as the StandardName
* that is sent by client is localized in the client's language. However, we must compare this to the names that are on the server, which
* are localized in registry using the server's language. Despite that, this is the best we can do.
*
* Note: This fallback method won't work for the UWP version though, as we can't use the registry APIs in UWP.
*
* Once we have the current Windows time zone, then we can then map it to an ICU time zone ID (~ Olsen ID).
*/ */
U_CAPI const char* U_EXPORT2 U_CAPI const char* U_EXPORT2
uprv_detectWindowsTimeZone() uprv_detectWindowsTimeZone()
{ {
// Obtain the DYNAMIC_TIME_ZONE_INFORMATION info to get the non-localized time zone name. // We first try to obtain the time zone directly by using the TimeZoneKeyName field of the DYNAMIC_TIME_ZONE_INFORMATION struct.
DYNAMIC_TIME_ZONE_INFORMATION dynamicTZI; DYNAMIC_TIME_ZONE_INFORMATION dynamicTZI;
uprv_memset(&dynamicTZI, 0, sizeof(dynamicTZI)); uprv_memset(&dynamicTZI, 0, sizeof(dynamicTZI));
SYSTEMTIME systemTimeAllZero; SYSTEMTIME systemTimeAllZero;
@ -86,22 +127,138 @@ uprv_detectWindowsTimeZone()
// Note '-' before 'utcOffsetMin'. The timezone ID's sign convention // Note '-' before 'utcOffsetMin'. The timezone ID's sign convention
// is that a timezone ahead of UTC is Etc/GMT-<offset> and a timezone // is that a timezone ahead of UTC is Etc/GMT-<offset> and a timezone
// behind UTC is Etc/GMT+<offset>. // behind UTC is Etc/GMT+<offset>.
int ret = snprintf(gmtOffsetTz, UPRV_LENGTHOF(gmtOffsetTz), "Etc/GMT%+d", -utcOffsetMins / 60); int ret = snprintf(gmtOffsetTz, UPRV_LENGTHOF(gmtOffsetTz), "Etc/GMT%+ld", -utcOffsetMins / 60);
if (ret > 0 && ret < UPRV_LENGTHOF(gmtOffsetTz)) { if (ret > 0 && ret < UPRV_LENGTHOF(gmtOffsetTz)) {
return uprv_strdup(gmtOffsetTz); return uprv_strdup(gmtOffsetTz);
} }
} }
} }
// If DST is NOT disabled, but we have an empty TimeZoneKeyName, then it is unclear // If DST is NOT disabled, but the TimeZoneKeyName field of the struct is NULL, then we may be dealing with a
// what we should do as this should not happen. // RDP/terminal services session where the 'Time Zone Redirection' feature is enabled. However, either the RDP
// client sent the server incomplete info (some 3rd party RDP clients only send the StandardName and DaylightName,
// but do not send the important TimeZoneKeyName), or if the RDP server has not appropriately populated the struct correctly.
//
// In this case we unfortunately have no choice but to fallback to using the pre-Vista method of determining the
// time zone, which requires examining the registry directly.
//
// Note that this can however still fail though if the client and server are using different languages, as the StandardName
// that is sent by client is *localized* in the client's language. However, we must compare this to the names that are
// on the server, which are *localized* in registry using the server's language.
//
// One other note is that this fallback method doesn't work for the UWP version, as we can't use the registry APIs.
// windowsTimeZoneName will point at timezoneSubKeyName if we had to fallback to using the registry, and we found a match.
WCHAR timezoneSubKeyName[WINDOWS_MAX_REG_KEY_LENGTH];
WCHAR *windowsTimeZoneName = dynamicTZI.TimeZoneKeyName;
if (dynamicTZI.TimeZoneKeyName[0] == 0) { if (dynamicTZI.TimeZoneKeyName[0] == 0) {
// We can't use the registry APIs in the UWP version.
#if U_PLATFORM_HAS_WINUWP_API == 1
(void)timezoneSubKeyName; // suppress unused variable warnings.
return nullptr; return nullptr;
#else
// Open the path to the time zones in the Windows registry.
LONG ret;
HKEY hKeyAllTimeZones = nullptr;
ret = RegOpenKeyExW(HKEY_LOCAL_MACHINE, WINDOWS_TIMEZONES_REG_KEY_PATH, 0, KEY_READ,
reinterpret_cast<PHKEY>(&hKeyAllTimeZones));
if (ret != ERROR_SUCCESS) {
// If we can't open the key, then we can't do much, so fail.
return nullptr;
}
// Read the number of subkeys under the time zone registry path.
DWORD numTimeZoneSubKeys;
ret = RegQueryInfoKeyW(hKeyAllTimeZones, nullptr, nullptr, nullptr, &numTimeZoneSubKeys,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr);
if (ret != ERROR_SUCCESS) {
RegCloseKey(hKeyAllTimeZones);
return nullptr;
}
// Examine each of the subkeys to try and find a match for the localized standard name ("Std").
//
// Note: The name of the time zone subkey itself is not localized, but the "Std" name is localized. This means
// that we could fail to find a match if the RDP client and RDP server are using different languages, but unfortunately
// there isn't much we can do about it.
HKEY hKeyTimeZoneSubKey = nullptr;
ULONG registryValueType;
WCHAR registryStandardName[WINDOWS_MAX_REG_KEY_LENGTH];
for (DWORD i = 0; i < numTimeZoneSubKeys; i++) {
// Note: RegEnumKeyExW wants the size of the buffer in characters.
DWORD size = UPRV_LENGTHOF(timezoneSubKeyName);
ret = RegEnumKeyExW(hKeyAllTimeZones, i, timezoneSubKeyName, &size, nullptr, nullptr, nullptr, nullptr);
if (ret != ERROR_SUCCESS) {
RegCloseKey(hKeyAllTimeZones);
return nullptr;
}
ret = RegOpenKeyExW(hKeyAllTimeZones, timezoneSubKeyName, 0, KEY_READ,
reinterpret_cast<PHKEY>(&hKeyTimeZoneSubKey));
if (ret != ERROR_SUCCESS) {
RegCloseKey(hKeyAllTimeZones);
return nullptr;
}
// Note: RegQueryValueExW wants the size of the buffer in bytes.
size = sizeof(registryStandardName);
ret = RegQueryValueExW(hKeyTimeZoneSubKey, L"Std", nullptr, &registryValueType,
reinterpret_cast<LPBYTE>(registryStandardName), &size);
if (ret != ERROR_SUCCESS || registryValueType != REG_SZ) {
RegCloseKey(hKeyTimeZoneSubKey);
RegCloseKey(hKeyAllTimeZones);
return nullptr;
}
// Note: wcscmp does an ordinal (byte) comparison.
if (wcscmp(reinterpret_cast<WCHAR *>(registryStandardName), dynamicTZI.StandardName) == 0) {
// Since we are comparing the *localized* time zone name, it's possible that some languages might use
// the same string for more than one time zone. Thus we need to examine the TZI data in the registry to
// compare the GMT offset (the bias), and the DST transition dates, to ensure it's the same time zone
// as the currently reported one.
REG_TZI_FORMAT registryTziValue;
uprv_memset(&registryTziValue, 0, sizeof(registryTziValue));
// Note: RegQueryValueExW wants the size of the buffer in bytes.
DWORD timezoneTziValueSize = sizeof(registryTziValue);
ret = RegQueryValueExW(hKeyTimeZoneSubKey, L"TZI", nullptr, &registryValueType,
reinterpret_cast<LPBYTE>(&registryTziValue), &timezoneTziValueSize);
if (ret == ERROR_SUCCESS) {
if ((dynamicTZI.Bias == registryTziValue.Bias) &&
(memcmp((const void *)&dynamicTZI.StandardDate, (const void *)&registryTziValue.StandardDate, sizeof(SYSTEMTIME)) == 0) &&
(memcmp((const void *)&dynamicTZI.DaylightDate, (const void *)&registryTziValue.DaylightDate, sizeof(SYSTEMTIME)) == 0))
{
// We found a matching time zone.
windowsTimeZoneName = timezoneSubKeyName;
break;
}
}
}
RegCloseKey(hKeyTimeZoneSubKey);
hKeyTimeZoneSubKey = nullptr;
}
if (hKeyTimeZoneSubKey != nullptr) {
RegCloseKey(hKeyTimeZoneSubKey);
}
if (hKeyAllTimeZones != nullptr) {
RegCloseKey(hKeyAllTimeZones);
}
#endif // U_PLATFORM_HAS_WINUWP_API
} }
CharString winTZ; CharString winTZ;
UErrorCode status = U_ZERO_ERROR; UErrorCode status = U_ZERO_ERROR;
winTZ.appendInvariantChars(UnicodeString(TRUE, dynamicTZI.TimeZoneKeyName, -1), status); winTZ.appendInvariantChars(UnicodeString(TRUE, windowsTimeZoneName, -1), status);
// Map Windows Timezone name (non-localized) to ICU timezone ID (~ Olson timezone id). // Map Windows Timezone name (non-localized) to ICU timezone ID (~ Olson timezone id).
StackUResourceBundle winTZBundle; StackUResourceBundle winTZBundle;
@ -123,18 +280,29 @@ uprv_detectWindowsTimeZone()
int regionCodeLen = GetGeoInfoW(geoId, GEO_ISO2, regionCodeW, UPRV_LENGTHOF(regionCodeW), 0); int regionCodeLen = GetGeoInfoW(geoId, GEO_ISO2, regionCodeW, UPRV_LENGTHOF(regionCodeW), 0);
const UChar *icuTZ16 = nullptr; const UChar *icuTZ16 = nullptr;
int32_t tzLen; int32_t tzListLen = 0;
if (regionCodeLen != 0) { if (regionCodeLen != 0) {
for (int i = 0; i < UPRV_LENGTHOF(regionCodeW); i++) { for (int i = 0; i < UPRV_LENGTHOF(regionCodeW); i++) {
regionCode[i] = static_cast<char>(regionCodeW[i]); regionCode[i] = static_cast<char>(regionCodeW[i]);
} }
icuTZ16 = ures_getStringByKey(winTZBundle.getAlias(), regionCode, &tzLen, &status); icuTZ16 = ures_getStringByKey(winTZBundle.getAlias(), regionCode, &tzListLen, &status);
} }
if (regionCodeLen == 0 || U_FAILURE(status)) { if (regionCodeLen == 0 || U_FAILURE(status)) {
// fallback to default "001" (world) // fallback to default "001" (world)
status = U_ZERO_ERROR; status = U_ZERO_ERROR;
icuTZ16 = ures_getStringByKey(winTZBundle.getAlias(), "001", &tzLen, &status); icuTZ16 = ures_getStringByKey(winTZBundle.getAlias(), "001", &tzListLen, &status);
}
// Note: We want the first entry in the string returned by ures_getStringByKey.
// However this string can be a space delimited list of timezones:
// Ex: "America/New_York America/Detroit America/Indiana/Petersburg ..."
// We need to stop at the first space, so we pass tzLen (instead of tzListLen) to appendInvariantChars below.
int32_t tzLen = 0;
if (tzListLen > 0) {
while (!(icuTZ16[tzLen] == u'\0' || icuTZ16[tzLen] == u' ')) {
tzLen++;
}
} }
// Note: cloneData returns nullptr if the status is a failure, so this // Note: cloneData returns nullptr if the status is a failure, so this

Binary file not shown.