ICU-21389 Merge maint/maint-68 to master

This commit is contained in:
Shane F. Carr 2020-11-16 18:50:26 -06:00 committed by GitHub
commit a593239dba
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
58 changed files with 2012 additions and 1187 deletions

View file

@ -46,13 +46,21 @@
</tr>
</THEAD>
<tr class="row1">
<td class="file">measunit.h</td><td class="proto">LocalArray&lt;MeasureUnit&gt; icu::MeasureUnit::splitToSingleUnits(int32_t&amp;, UErrorCode&amp;) const</td><td class="">Internal<br>ICU 67</td><td>(missing)<br>
<td class="file">fmtable.h</td><td class="proto">const UFormattable* icu::Formattable::toUFormattable()</td><td class="stabchange">Stable<br>ICU 52</td><td>(missing)<br>
<span class=""><span></span></span></td>
</tr>
<tr class="row0">
<td class="file">measunit.h</td><td class="proto">LocalArray&lt;MeasureUnit&gt; icu::MeasureUnit::splitToSingleUnits(int32_t&amp;, UErrorCode&amp;) const</td><td class="">Internal<br>ICU 67</td><td>(missing)<br>
<span class=""><span></span></span></td>
</tr>
<tr class="row1">
<td class="file">measunit.h</td><td class="proto">int32_t icu::MeasureUnit::getIndex() const</td><td class="">Internal</td><td>(missing)<br>
<span class=""><span></span></span></td>
</tr>
<tr class="row0">
<td class="file">measunit.h</td><td class="proto"><tt>static</tt> MeasureUnit icu::MeasureUnit::resolveUnitPerUnit(const MeasureUnit&amp;, const MeasureUnit&amp;, bool*)</td><td class="">Internal</td><td>(missing)<br>
<span class=""><span></span></span></td>
</tr>
<tr class="row1">
<td class="file">measunit.h</td><td class="proto"><tt>static</tt> int32_t icu::MeasureUnit::getIndexCount()</td><td class="">Internal</td><td>(missing)<br>
<span class=""><span></span></span></td>
@ -93,6 +101,10 @@
<td class="file">nounit.h</td><td class="proto">void* icu::NoUnit::clone() const</td><td class="">Draft<br>ICU 60</td><td>(missing)<br>
<span class=""><span></span></span></td>
</tr>
<tr class="row1">
<td class="file">uniset.h</td><td class="proto">const USet* icu::UnicodeSet::toUSet()</td><td class="stabchange">Stable<br>ICU 4.2</td><td>(missing)<br>
<span class=""><span></span></span></td>
</tr>
</table>
<P></P>
<a href="#_top">(jump back to top)</a>
@ -140,232 +152,256 @@
<td class="file">bytestrie.h</td><td class="proto">uint64_t icu::BytesTrie::getState64() const</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 65</td>
</tr>
<tr class="row1">
<td class="file">listformatter.h</td><td class="proto"><tt>static</tt> ListFormatter* icu::ListFormatter::createInstance(const Locale&amp;, UListFormatterType, UListFormatterWidth, UErrorCode&amp;)</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 67</td>
</tr>
<tr class="row0">
<td class="file">localebuilder.h</td><td class="proto">UBool icu::LocaleBuilder::copyErrorTo(UErrorCode&amp;) const</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 65</td>
</tr>
<tr class="row0">
<tr class="row1">
<td class="file">localematcher.h</td><td class="proto">Builder&amp; icu::LocaleMatcher::Builder::addSupportedLocale(const Locale&amp;)</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 65</td>
</tr>
<tr class="row1">
<tr class="row0">
<td class="file">localematcher.h</td><td class="proto">Builder&amp; icu::LocaleMatcher::Builder::operator=(Builder&amp;&amp;)</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 65</td>
</tr>
<tr class="row0">
<tr class="row1">
<td class="file">localematcher.h</td><td class="proto">Builder&amp; icu::LocaleMatcher::Builder::setDefaultLocale(const Locale*)</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 65</td>
</tr>
<tr class="row1">
<tr class="row0">
<td class="file">localematcher.h</td><td class="proto">Builder&amp; icu::LocaleMatcher::Builder::setDemotionPerDesiredLocale(ULocMatchDemotion)</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 65</td>
</tr>
<tr class="row0">
<tr class="row1">
<td class="file">localematcher.h</td><td class="proto">Builder&amp; icu::LocaleMatcher::Builder::setFavorSubtag(ULocMatchFavorSubtag)</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 65</td>
</tr>
<tr class="row1">
<tr class="row0">
<td class="file">localematcher.h</td><td class="proto">Builder&amp; icu::LocaleMatcher::Builder::setSupportedLocales(Iter, Iter)</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 65</td>
</tr>
<tr class="row0">
<tr class="row1">
<td class="file">localematcher.h</td><td class="proto">Builder&amp; icu::LocaleMatcher::Builder::setSupportedLocales(Locale::Iterator&amp;)</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 65</td>
</tr>
<tr class="row1">
<tr class="row0">
<td class="file">localematcher.h</td><td class="proto">Builder&amp; icu::LocaleMatcher::Builder::setSupportedLocalesFromListString(StringPiece)</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 65</td>
</tr>
<tr class="row0">
<tr class="row1">
<td class="file">localematcher.h</td><td class="proto">Builder&amp; icu::LocaleMatcher::Builder::setSupportedLocalesViaConverter(Iter, Iter, Conv)</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 65</td>
</tr>
<tr class="row1">
<tr class="row0">
<td class="file">localematcher.h</td><td class="proto">Locale icu::LocaleMatcher::Result::makeResolvedLocale(UErrorCode&amp;) const</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 65</td>
</tr>
<tr class="row0">
<tr class="row1">
<td class="file">localematcher.h</td><td class="proto">LocaleMatcher icu::LocaleMatcher::Builder::build(UErrorCode&amp;) const</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 65</td>
</tr>
<tr class="row1">
<tr class="row0">
<td class="file">localematcher.h</td><td class="proto">LocaleMatcher&amp; icu::LocaleMatcher::operator=(LocaleMatcher&amp;&amp;)</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 65</td>
</tr>
<tr class="row0">
<tr class="row1">
<td class="file">localematcher.h</td><td class="proto">Result icu::LocaleMatcher::getBestMatchResult(Locale::Iterator&amp;, UErrorCode&amp;) const</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 65</td>
</tr>
<tr class="row1">
<tr class="row0">
<td class="file">localematcher.h</td><td class="proto">Result icu::LocaleMatcher::getBestMatchResult(const Locale&amp;, UErrorCode&amp;) const</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 65</td>
</tr>
<tr class="row0">
<tr class="row1">
<td class="file">localematcher.h</td><td class="proto">Result&amp; icu::LocaleMatcher::Result::operator=(Result&amp;&amp;)</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 65</td>
</tr>
<tr class="row1">
<tr class="row0">
<td class="file">localematcher.h</td><td class="proto">UBool icu::LocaleMatcher::Builder::copyErrorTo(UErrorCode&amp;) const</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 65</td>
</tr>
<tr class="row0">
<tr class="row1">
<td class="file">localematcher.h</td><td class="proto">const Locale* icu::LocaleMatcher::Result::getDesiredLocale() const</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 65</td>
</tr>
<tr class="row1">
<tr class="row0">
<td class="file">localematcher.h</td><td class="proto">const Locale* icu::LocaleMatcher::Result::getSupportedLocale() const</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 65</td>
</tr>
<tr class="row0">
<tr class="row1">
<td class="file">localematcher.h</td><td class="proto">const Locale* icu::LocaleMatcher::getBestMatch(Locale::Iterator&amp;, UErrorCode&amp;) const</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 65</td>
</tr>
<tr class="row1">
<tr class="row0">
<td class="file">localematcher.h</td><td class="proto">const Locale* icu::LocaleMatcher::getBestMatch(const Locale&amp;, UErrorCode&amp;) const</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 65</td>
</tr>
<tr class="row0">
<tr class="row1">
<td class="file">localematcher.h</td><td class="proto">const Locale* icu::LocaleMatcher::getBestMatchForListString(StringPiece, UErrorCode&amp;) const</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 65</td>
</tr>
<tr class="row1">
<tr class="row0">
<td class="file">localematcher.h</td><td class="proto"><tt>enum</tt> ULocMatchDemotion::ULOCMATCH_DEMOTION_NONE</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 65</td>
</tr>
<tr class="row0">
<tr class="row1">
<td class="file">localematcher.h</td><td class="proto"><tt>enum</tt> ULocMatchDemotion::ULOCMATCH_DEMOTION_REGION</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 65</td>
</tr>
<tr class="row1">
<tr class="row0">
<td class="file">localematcher.h</td><td class="proto"><tt>enum</tt> ULocMatchFavorSubtag::ULOCMATCH_FAVOR_LANGUAGE</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 65</td>
</tr>
<tr class="row0">
<tr class="row1">
<td class="file">localematcher.h</td><td class="proto"><tt>enum</tt> ULocMatchFavorSubtag::ULOCMATCH_FAVOR_SCRIPT</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 65</td>
</tr>
<tr class="row1">
<tr class="row0">
<td class="file">localematcher.h</td><td class="proto">icu::LocaleMatcher::Builder::Builder()</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 65</td>
</tr>
<tr class="row0">
<tr class="row1">
<td class="file">localematcher.h</td><td class="proto">icu::LocaleMatcher::Builder::Builder(Builder&amp;&amp;)</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 65</td>
</tr>
<tr class="row1">
<tr class="row0">
<td class="file">localematcher.h</td><td class="proto">icu::LocaleMatcher::Builder::~Builder()</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 65</td>
</tr>
<tr class="row0">
<tr class="row1">
<td class="file">localematcher.h</td><td class="proto">icu::LocaleMatcher::LocaleMatcher(LocaleMatcher&amp;&amp;)</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 65</td>
</tr>
<tr class="row1">
<tr class="row0">
<td class="file">localematcher.h</td><td class="proto">icu::LocaleMatcher::Result::Result(Result&amp;&amp;)</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 65</td>
</tr>
<tr class="row0">
<tr class="row1">
<td class="file">localematcher.h</td><td class="proto">icu::LocaleMatcher::Result::~Result()</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 65</td>
</tr>
<tr class="row1">
<tr class="row0">
<td class="file">localematcher.h</td><td class="proto">icu::LocaleMatcher::~LocaleMatcher()</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 65</td>
</tr>
<tr class="row0">
<tr class="row1">
<td class="file">localematcher.h</td><td class="proto">int32_t icu::LocaleMatcher::Result::getDesiredIndex() const</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 65</td>
</tr>
<tr class="row1">
<tr class="row0">
<td class="file">localematcher.h</td><td class="proto">int32_t icu::LocaleMatcher::Result::getSupportedIndex() const</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 65</td>
</tr>
<tr class="row0">
<tr class="row1">
<td class="file">locid.h</td><td class="proto">UBool icu::Locale::ConvertingIterator&lt; Iter, Conv &gt;::hasNext() const override</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 65</td>
</tr>
<tr class="row1">
<tr class="row0">
<td class="file">locid.h</td><td class="proto">UBool icu::Locale::Iterator::hasNext() const</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 65</td>
</tr>
<tr class="row0">
<tr class="row1">
<td class="file">locid.h</td><td class="proto">UBool icu::Locale::RangeIterator&lt; Iter &gt;::hasNext() const override</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 65</td>
</tr>
<tr class="row1">
<tr class="row0">
<td class="file">locid.h</td><td class="proto">const Locale&amp; icu::Locale::ConvertingIterator&lt; Iter, Conv &gt;::next() override</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 65</td>
</tr>
<tr class="row0">
<tr class="row1">
<td class="file">locid.h</td><td class="proto">const Locale&amp; icu::Locale::Iterator::next()</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 65</td>
</tr>
<tr class="row1">
<tr class="row0">
<td class="file">locid.h</td><td class="proto">const Locale&amp; icu::Locale::RangeIterator&lt; Iter &gt;::next() override</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 65</td>
</tr>
<tr class="row0">
<tr class="row1">
<td class="file">locid.h</td><td class="proto">icu::Locale::ConvertingIterator&lt; Iter, Conv &gt;::ConvertingIterator(Iter, Iter, Conv)</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 65</td>
</tr>
<tr class="row1">
<tr class="row0">
<td class="file">locid.h</td><td class="proto">icu::Locale::Iterator::~Iterator()</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 65</td>
</tr>
<tr class="row0">
<tr class="row1">
<td class="file">locid.h</td><td class="proto">icu::Locale::RangeIterator&lt; Iter &gt;::RangeIterator(Iter, Iter)</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 65</td>
</tr>
<tr class="row1">
<tr class="row0">
<td class="file">measunit.h</td><td class="proto"><tt>static</tt> MeasureUnit icu::MeasureUnit::getBar()</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 65</td>
</tr>
<tr class="row0">
<tr class="row1">
<td class="file">measunit.h</td><td class="proto"><tt>static</tt> MeasureUnit icu::MeasureUnit::getDecade()</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 65</td>
</tr>
<tr class="row1">
<tr class="row0">
<td class="file">measunit.h</td><td class="proto"><tt>static</tt> MeasureUnit icu::MeasureUnit::getDotPerCentimeter()</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 65</td>
</tr>
<tr class="row0">
<tr class="row1">
<td class="file">measunit.h</td><td class="proto"><tt>static</tt> MeasureUnit icu::MeasureUnit::getDotPerInch()</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 65</td>
</tr>
<tr class="row1">
<tr class="row0">
<td class="file">measunit.h</td><td class="proto"><tt>static</tt> MeasureUnit icu::MeasureUnit::getEm()</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 65</td>
</tr>
<tr class="row0">
<tr class="row1">
<td class="file">measunit.h</td><td class="proto"><tt>static</tt> MeasureUnit icu::MeasureUnit::getMegapixel()</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 65</td>
</tr>
<tr class="row1">
<tr class="row0">
<td class="file">measunit.h</td><td class="proto"><tt>static</tt> MeasureUnit icu::MeasureUnit::getPascal()</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 65</td>
</tr>
<tr class="row0">
<tr class="row1">
<td class="file">measunit.h</td><td class="proto"><tt>static</tt> MeasureUnit icu::MeasureUnit::getPixel()</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 65</td>
</tr>
<tr class="row1">
<tr class="row0">
<td class="file">measunit.h</td><td class="proto"><tt>static</tt> MeasureUnit icu::MeasureUnit::getPixelPerCentimeter()</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 65</td>
</tr>
<tr class="row0">
<tr class="row1">
<td class="file">measunit.h</td><td class="proto"><tt>static</tt> MeasureUnit icu::MeasureUnit::getPixelPerInch()</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 65</td>
</tr>
<tr class="row1">
<tr class="row0">
<td class="file">measunit.h</td><td class="proto"><tt>static</tt> MeasureUnit icu::MeasureUnit::getThermUs()</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 65</td>
</tr>
<tr class="row0">
<tr class="row1">
<td class="file">measunit.h</td><td class="proto"><tt>static</tt> MeasureUnit* icu::MeasureUnit::createBar(UErrorCode&amp;)</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 65</td>
</tr>
<tr class="row1">
<tr class="row0">
<td class="file">measunit.h</td><td class="proto"><tt>static</tt> MeasureUnit* icu::MeasureUnit::createDecade(UErrorCode&amp;)</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 65</td>
</tr>
<tr class="row0">
<tr class="row1">
<td class="file">measunit.h</td><td class="proto"><tt>static</tt> MeasureUnit* icu::MeasureUnit::createDotPerCentimeter(UErrorCode&amp;)</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 65</td>
</tr>
<tr class="row1">
<tr class="row0">
<td class="file">measunit.h</td><td class="proto"><tt>static</tt> MeasureUnit* icu::MeasureUnit::createDotPerInch(UErrorCode&amp;)</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 65</td>
</tr>
<tr class="row0">
<tr class="row1">
<td class="file">measunit.h</td><td class="proto"><tt>static</tt> MeasureUnit* icu::MeasureUnit::createEm(UErrorCode&amp;)</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 65</td>
</tr>
<tr class="row1">
<tr class="row0">
<td class="file">measunit.h</td><td class="proto"><tt>static</tt> MeasureUnit* icu::MeasureUnit::createMegapixel(UErrorCode&amp;)</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 65</td>
</tr>
<tr class="row0">
<tr class="row1">
<td class="file">measunit.h</td><td class="proto"><tt>static</tt> MeasureUnit* icu::MeasureUnit::createPascal(UErrorCode&amp;)</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 65</td>
</tr>
<tr class="row1">
<tr class="row0">
<td class="file">measunit.h</td><td class="proto"><tt>static</tt> MeasureUnit* icu::MeasureUnit::createPixel(UErrorCode&amp;)</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 65</td>
</tr>
<tr class="row0">
<tr class="row1">
<td class="file">measunit.h</td><td class="proto"><tt>static</tt> MeasureUnit* icu::MeasureUnit::createPixelPerCentimeter(UErrorCode&amp;)</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 65</td>
</tr>
<tr class="row1">
<tr class="row0">
<td class="file">measunit.h</td><td class="proto"><tt>static</tt> MeasureUnit* icu::MeasureUnit::createPixelPerInch(UErrorCode&amp;)</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 65</td>
</tr>
<tr class="row0">
<tr class="row1">
<td class="file">measunit.h</td><td class="proto"><tt>static</tt> MeasureUnit* icu::MeasureUnit::createThermUs(UErrorCode&amp;)</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 65</td>
</tr>
<tr class="row1">
<tr class="row0">
<td class="file">numberformatter.h</td><td class="proto">StringClass icu::number::FormattedNumber::toDecimalNumber(UErrorCode&amp;) const</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 65</td>
</tr>
<tr class="row0">
<tr class="row1">
<td class="file">numberrangeformatter.h</td><td class="proto">UnicodeString icu::number::FormattedNumberRange::getFirstDecimal(UErrorCode&amp;) const</td><td class="">Draft<br>ICU 63</td><td>Deprecated<br>
<span class="verchange"><span>ICU 68</span></span></td>
</tr>
<tr class="row1">
<tr class="row0">
<td class="file">numberrangeformatter.h</td><td class="proto">UnicodeString icu::number::FormattedNumberRange::getSecondDecimal(UErrorCode&amp;) const</td><td class="">Draft<br>ICU 63</td><td>Deprecated<br>
<span class="verchange"><span>ICU 68</span></span></td>
</tr>
<tr class="row0">
<tr class="row1">
<td class="file">reldatefmt.h</td><td class="proto"><tt>enum</tt> UDateAbsoluteUnit::UDAT_ABSOLUTE_HOUR</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 65</td>
</tr>
<tr class="row1">
<tr class="row0">
<td class="file">reldatefmt.h</td><td class="proto"><tt>enum</tt> UDateAbsoluteUnit::UDAT_ABSOLUTE_MINUTE</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 65</td>
</tr>
<tr class="row0">
<tr class="row1">
<td class="file">stringpiece.h</td><td class="proto">icu::StringPiece::StringPiece(T)</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 65</td>
</tr>
<tr class="row1">
<tr class="row0">
<td class="file">ucal.h</td><td class="proto">int32_t ucal_getHostTimeZone(UChar*, int32_t, UErrorCode*)</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 65</td>
</tr>
<tr class="row0">
<tr class="row1">
<td class="file">ucharstrie.h</td><td class="proto">UCharsTrie&amp; icu::UCharsTrie::resetToState64(uint64_t)</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 65</td>
</tr>
<tr class="row1">
<tr class="row0">
<td class="file">ucharstrie.h</td><td class="proto">uint64_t icu::UCharsTrie::getState64() const</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 65</td>
</tr>
<tr class="row1">
<td class="file">ulistformatter.h</td><td class="proto">UListFormatter* ulistfmt_openForType(const char*, UListFormatterType, UListFormatterWidth, UErrorCode*)</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 67</td>
</tr>
<tr class="row0">
<td class="file">ulistformatter.h</td><td class="proto"><tt>enum</tt> UListFormatterType::ULISTFMT_TYPE_AND</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 67</td>
</tr>
<tr class="row1">
<td class="file">ulistformatter.h</td><td class="proto"><tt>enum</tt> UListFormatterType::ULISTFMT_TYPE_OR</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 67</td>
</tr>
<tr class="row0">
<td class="file">ulistformatter.h</td><td class="proto"><tt>enum</tt> UListFormatterType::ULISTFMT_TYPE_UNITS</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 67</td>
</tr>
<tr class="row1">
<td class="file">ulistformatter.h</td><td class="proto"><tt>enum</tt> UListFormatterWidth::ULISTFMT_WIDTH_NARROW</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 67</td>
</tr>
<tr class="row0">
<td class="file">ulistformatter.h</td><td class="proto"><tt>enum</tt> UListFormatterWidth::ULISTFMT_WIDTH_SHORT</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 67</td>
</tr>
<tr class="row1">
<td class="file">ulistformatter.h</td><td class="proto"><tt>enum</tt> UListFormatterWidth::ULISTFMT_WIDTH_WIDE</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 67</td>
</tr>
<tr class="row0">
<td class="file">uloc.h</td><td class="proto">UEnumeration* uloc_openAvailableByType(ULocAvailableType, UErrorCode*)</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 65</td>
</tr>
@ -417,6 +453,13 @@
<td class="file">bytestrie.h</td><td class="proto">uint64_t icu::BytesTrie::getState64() const</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 65</td>
</tr>
<tr class="row1">
<td class="file">fmtable.h</td><td class="proto">UFormattable* icu::Formattable::toUFormattable()</td><td class="">(missing)</td><td>Stable<br>
<span class=""><span>ICU 52</span></span></td>
</tr>
<tr class="row0">
<td class="file">listformatter.h</td><td class="proto"><tt>static</tt> ListFormatter* icu::ListFormatter::createInstance(const Locale&amp;, UListFormatterType, UListFormatterWidth, UErrorCode&amp;)</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 67</td>
</tr>
<tr class="row1">
<td class="file">localebuilder.h</td><td class="proto">UBool icu::LocaleBuilder::copyErrorTo(UErrorCode&amp;) const</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 65</td>
</tr>
<tr class="row0">
@ -636,17 +679,42 @@
<td class="file">ucharstrie.h</td><td class="proto">uint64_t icu::UCharsTrie::getState64() const</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 65</td>
</tr>
<tr class="row0">
<td class="file">uloc.h</td><td class="proto">UEnumeration* uloc_openAvailableByType(ULocAvailableType, UErrorCode*)</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 65</td>
<td class="file">ulistformatter.h</td><td class="proto">UListFormatter* ulistfmt_openForType(const char*, UListFormatterType, UListFormatterWidth, UErrorCode*)</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 67</td>
</tr>
<tr class="row1">
<td class="file">uloc.h</td><td class="proto"><tt>enum</tt> ULocAvailableType::ULOC_AVAILABLE_DEFAULT</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 65</td>
<td class="file">ulistformatter.h</td><td class="proto"><tt>enum</tt> UListFormatterType::ULISTFMT_TYPE_AND</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 67</td>
</tr>
<tr class="row0">
<td class="file">uloc.h</td><td class="proto"><tt>enum</tt> ULocAvailableType::ULOC_AVAILABLE_ONLY_LEGACY_ALIASES</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 65</td>
<td class="file">ulistformatter.h</td><td class="proto"><tt>enum</tt> UListFormatterType::ULISTFMT_TYPE_OR</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 67</td>
</tr>
<tr class="row1">
<td class="file">ulistformatter.h</td><td class="proto"><tt>enum</tt> UListFormatterType::ULISTFMT_TYPE_UNITS</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 67</td>
</tr>
<tr class="row0">
<td class="file">ulistformatter.h</td><td class="proto"><tt>enum</tt> UListFormatterWidth::ULISTFMT_WIDTH_NARROW</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 67</td>
</tr>
<tr class="row1">
<td class="file">ulistformatter.h</td><td class="proto"><tt>enum</tt> UListFormatterWidth::ULISTFMT_WIDTH_SHORT</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 67</td>
</tr>
<tr class="row0">
<td class="file">ulistformatter.h</td><td class="proto"><tt>enum</tt> UListFormatterWidth::ULISTFMT_WIDTH_WIDE</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 67</td>
</tr>
<tr class="row1">
<td class="file">uloc.h</td><td class="proto">UEnumeration* uloc_openAvailableByType(ULocAvailableType, UErrorCode*)</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 65</td>
</tr>
<tr class="row0">
<td class="file">uloc.h</td><td class="proto"><tt>enum</tt> ULocAvailableType::ULOC_AVAILABLE_DEFAULT</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 65</td>
</tr>
<tr class="row1">
<td class="file">uloc.h</td><td class="proto"><tt>enum</tt> ULocAvailableType::ULOC_AVAILABLE_ONLY_LEGACY_ALIASES</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 65</td>
</tr>
<tr class="row0">
<td class="file">uloc.h</td><td class="proto"><tt>enum</tt> ULocAvailableType::ULOC_AVAILABLE_WITH_LEGACY_ALIASES</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 65</td>
</tr>
<tr class="row1">
<td class="file">uniset.h</td><td class="proto">USet* icu::UnicodeSet::toUSet()</td><td class="">(missing)</td><td>Stable<br>
<span class=""><span>ICU 4.2</span></span></td>
</tr>
<tr class="row0">
<td class="file">utrace.h</td><td class="proto"><tt>enum</tt> UTraceFunctionNumber::UTRACE_UDATA_BUNDLE</td><td class="" colspan="2" align="center">Draft&rarr;Stable<br>ICU 65</td>
</tr>
@ -684,177 +752,185 @@
<span class=""><span></span></span></td>
</tr>
<tr class="row0">
<td class="file">fmtable.h</td><td class="proto">UFormattable* icu::Formattable::toUFormattable()</td><td class="">(missing)</td><td>Stable<br>
<span class=""><span>ICU 52</span></span></td>
</tr>
<tr class="row1">
<td class="file">localematcher.h</td><td class="proto">Builder&amp; icu::LocaleMatcher::Builder::setMaxDistance(const Locale&amp;, const Locale&amp;)</td><td class="">(missing)</td><td>Draft<br>
<span class=""><span>ICU 68</span></span></td>
</tr>
<tr class="row1">
<tr class="row0">
<td class="file">localematcher.h</td><td class="proto">Builder&amp; icu::LocaleMatcher::Builder::setNoDefaultLocale()</td><td class="">(missing)</td><td>Draft<br>
<span class=""><span>ICU 68</span></span></td>
</tr>
<tr class="row0">
<tr class="row1">
<td class="file">localematcher.h</td><td class="proto">UBool icu::LocaleMatcher::isMatch(const Locale&amp;, const Locale&amp;, UErrorCode&amp;) const</td><td class="">(missing)</td><td>Draft<br>
<span class=""><span>ICU 68</span></span></td>
</tr>
<tr class="row1">
<tr class="row0">
<td class="file">measunit.h</td><td class="proto">int32_t icu::MeasureUnit::getOffset() const</td><td class="">(missing)</td><td>Internal<br>
<span class=""><span></span></span></td>
</tr>
<tr class="row0">
<tr class="row1">
<td class="file">measunit.h</td><td class="proto"><tt>static</tt> MeasureUnit icu::MeasureUnit::getCandela()</td><td class="">(missing)</td><td>Draft<br>
<span class=""><span>ICU 68</span></span></td>
</tr>
<tr class="row1">
<tr class="row0">
<td class="file">measunit.h</td><td class="proto"><tt>static</tt> MeasureUnit icu::MeasureUnit::getDessertSpoon()</td><td class="">(missing)</td><td>Draft<br>
<span class=""><span>ICU 68</span></span></td>
</tr>
<tr class="row0">
<tr class="row1">
<td class="file">measunit.h</td><td class="proto"><tt>static</tt> MeasureUnit icu::MeasureUnit::getDessertSpoonImperial()</td><td class="">(missing)</td><td>Draft<br>
<span class=""><span>ICU 68</span></span></td>
</tr>
<tr class="row1">
<tr class="row0">
<td class="file">measunit.h</td><td class="proto"><tt>static</tt> MeasureUnit icu::MeasureUnit::getDot()</td><td class="">(missing)</td><td>Draft<br>
<span class=""><span>ICU 68</span></span></td>
</tr>
<tr class="row0">
<tr class="row1">
<td class="file">measunit.h</td><td class="proto"><tt>static</tt> MeasureUnit icu::MeasureUnit::getDram()</td><td class="">(missing)</td><td>Draft<br>
<span class=""><span>ICU 68</span></span></td>
</tr>
<tr class="row1">
<tr class="row0">
<td class="file">measunit.h</td><td class="proto"><tt>static</tt> MeasureUnit icu::MeasureUnit::getDrop()</td><td class="">(missing)</td><td>Draft<br>
<span class=""><span>ICU 68</span></span></td>
</tr>
<tr class="row0">
<tr class="row1">
<td class="file">measunit.h</td><td class="proto"><tt>static</tt> MeasureUnit icu::MeasureUnit::getEarthRadius()</td><td class="">(missing)</td><td>Draft<br>
<span class=""><span>ICU 68</span></span></td>
</tr>
<tr class="row1">
<tr class="row0">
<td class="file">measunit.h</td><td class="proto"><tt>static</tt> MeasureUnit icu::MeasureUnit::getGrain()</td><td class="">(missing)</td><td>Draft<br>
<span class=""><span>ICU 68</span></span></td>
</tr>
<tr class="row0">
<tr class="row1">
<td class="file">measunit.h</td><td class="proto"><tt>static</tt> MeasureUnit icu::MeasureUnit::getJigger()</td><td class="">(missing)</td><td>Draft<br>
<span class=""><span>ICU 68</span></span></td>
</tr>
<tr class="row1">
<tr class="row0">
<td class="file">measunit.h</td><td class="proto"><tt>static</tt> MeasureUnit icu::MeasureUnit::getLumen()</td><td class="">(missing)</td><td>Draft<br>
<span class=""><span>ICU 68</span></span></td>
</tr>
<tr class="row0">
<tr class="row1">
<td class="file">measunit.h</td><td class="proto"><tt>static</tt> MeasureUnit icu::MeasureUnit::getPinch()</td><td class="">(missing)</td><td>Draft<br>
<span class=""><span>ICU 68</span></span></td>
</tr>
<tr class="row1">
<tr class="row0">
<td class="file">measunit.h</td><td class="proto"><tt>static</tt> MeasureUnit icu::MeasureUnit::getQuartImperial()</td><td class="">(missing)</td><td>Draft<br>
<span class=""><span>ICU 68</span></span></td>
</tr>
<tr class="row0">
<tr class="row1">
<td class="file">measunit.h</td><td class="proto"><tt>static</tt> MeasureUnit* icu::MeasureUnit::createCandela(UErrorCode&amp;)</td><td class="">(missing)</td><td>Draft<br>
<span class=""><span>ICU 68</span></span></td>
</tr>
<tr class="row1">
<tr class="row0">
<td class="file">measunit.h</td><td class="proto"><tt>static</tt> MeasureUnit* icu::MeasureUnit::createDessertSpoon(UErrorCode&amp;)</td><td class="">(missing)</td><td>Draft<br>
<span class=""><span>ICU 68</span></span></td>
</tr>
<tr class="row0">
<tr class="row1">
<td class="file">measunit.h</td><td class="proto"><tt>static</tt> MeasureUnit* icu::MeasureUnit::createDessertSpoonImperial(UErrorCode&amp;)</td><td class="">(missing)</td><td>Draft<br>
<span class=""><span>ICU 68</span></span></td>
</tr>
<tr class="row1">
<tr class="row0">
<td class="file">measunit.h</td><td class="proto"><tt>static</tt> MeasureUnit* icu::MeasureUnit::createDot(UErrorCode&amp;)</td><td class="">(missing)</td><td>Draft<br>
<span class=""><span>ICU 68</span></span></td>
</tr>
<tr class="row0">
<tr class="row1">
<td class="file">measunit.h</td><td class="proto"><tt>static</tt> MeasureUnit* icu::MeasureUnit::createDram(UErrorCode&amp;)</td><td class="">(missing)</td><td>Draft<br>
<span class=""><span>ICU 68</span></span></td>
</tr>
<tr class="row1">
<tr class="row0">
<td class="file">measunit.h</td><td class="proto"><tt>static</tt> MeasureUnit* icu::MeasureUnit::createDrop(UErrorCode&amp;)</td><td class="">(missing)</td><td>Draft<br>
<span class=""><span>ICU 68</span></span></td>
</tr>
<tr class="row0">
<tr class="row1">
<td class="file">measunit.h</td><td class="proto"><tt>static</tt> MeasureUnit* icu::MeasureUnit::createEarthRadius(UErrorCode&amp;)</td><td class="">(missing)</td><td>Draft<br>
<span class=""><span>ICU 68</span></span></td>
</tr>
<tr class="row1">
<tr class="row0">
<td class="file">measunit.h</td><td class="proto"><tt>static</tt> MeasureUnit* icu::MeasureUnit::createGrain(UErrorCode&amp;)</td><td class="">(missing)</td><td>Draft<br>
<span class=""><span>ICU 68</span></span></td>
</tr>
<tr class="row0">
<tr class="row1">
<td class="file">measunit.h</td><td class="proto"><tt>static</tt> MeasureUnit* icu::MeasureUnit::createJigger(UErrorCode&amp;)</td><td class="">(missing)</td><td>Draft<br>
<span class=""><span>ICU 68</span></span></td>
</tr>
<tr class="row1">
<tr class="row0">
<td class="file">measunit.h</td><td class="proto"><tt>static</tt> MeasureUnit* icu::MeasureUnit::createLumen(UErrorCode&amp;)</td><td class="">(missing)</td><td>Draft<br>
<span class=""><span>ICU 68</span></span></td>
</tr>
<tr class="row0">
<tr class="row1">
<td class="file">measunit.h</td><td class="proto"><tt>static</tt> MeasureUnit* icu::MeasureUnit::createPinch(UErrorCode&amp;)</td><td class="">(missing)</td><td>Draft<br>
<span class=""><span>ICU 68</span></span></td>
</tr>
<tr class="row1">
<tr class="row0">
<td class="file">measunit.h</td><td class="proto"><tt>static</tt> MeasureUnit* icu::MeasureUnit::createQuartImperial(UErrorCode&amp;)</td><td class="">(missing)</td><td>Draft<br>
<span class=""><span>ICU 68</span></span></td>
</tr>
<tr class="row0">
<tr class="row1">
<td class="file">measunit.h</td><td class="proto">std::pair&lt; LocalArray&lt; MeasureUnit &gt;, int32_t &gt; icu::MeasureUnit::splitToSingleUnits(UErrorCode&amp;) const</td><td class="">(missing)</td><td>Draft<br>
<span class=""><span>ICU 68</span></span></td>
</tr>
<tr class="row1">
<tr class="row0">
<td class="file">numberformatter.h</td><td class="proto">Derived icu::number::NumberFormatterSettings&lt; Derived &gt;::usage(StringPiece) const&amp;</td><td class="">(missing)</td><td>Draft<br>
<span class=""><span>ICU 68</span></span></td>
</tr>
<tr class="row0">
<tr class="row1">
<td class="file">numberformatter.h</td><td class="proto">Derived icu::number::NumberFormatterSettings&lt; Derived &gt;::usage(StringPiece)&amp;&amp;</td><td class="">(missing)</td><td>Draft<br>
<span class=""><span>ICU 68</span></span></td>
</tr>
<tr class="row1">
<tr class="row0">
<td class="file">numberformatter.h</td><td class="proto">MeasureUnit icu::number::FormattedNumber::getOutputUnit(UErrorCode&amp;) const</td><td class="">(missing)</td><td>Draft<br>
<span class=""><span>ICU 68</span></span></td>
</tr>
<tr class="row0">
<tr class="row1">
<td class="file">numberformatter.h</td><td class="proto">Usage&amp; icu::number::impl::Usage::operator=(Usage&amp;&amp;)</td><td class="">(missing)</td><td>Internal<br>
<span class=""><span></span></span></td>
</tr>
<tr class="row1">
<tr class="row0">
<td class="file">numberformatter.h</td><td class="proto">Usage&amp; icu::number::impl::Usage::operator=(const Usage&amp;)</td><td class="">(missing)</td><td>Internal<br>
<span class=""><span></span></span></td>
</tr>
<tr class="row0">
<tr class="row1">
<td class="file">numberformatter.h</td><td class="proto">bool icu::number::impl::Usage::isSet() const</td><td class="">(missing)</td><td>Internal<br>
<span class=""><span></span></span></td>
</tr>
<tr class="row1">
<tr class="row0">
<td class="file">numberformatter.h</td><td class="proto">icu::number::impl::Usage::Usage(Usage&amp;&amp;)</td><td class="">(missing)</td><td>Internal<br>
<span class=""><span></span></span></td>
</tr>
<tr class="row0">
<tr class="row1">
<td class="file">numberformatter.h</td><td class="proto">icu::number::impl::Usage::Usage(const Usage&amp;)</td><td class="">(missing)</td><td>Internal<br>
<span class=""><span></span></span></td>
</tr>
<tr class="row1">
<tr class="row0">
<td class="file">numberformatter.h</td><td class="proto">icu::number::impl::Usage::~Usage()</td><td class="">(missing)</td><td>Internal<br>
<span class=""><span></span></span></td>
</tr>
<tr class="row0">
<tr class="row1">
<td class="file">numberformatter.h</td><td class="proto">int16_t icu::number::impl::Usage::length() const</td><td class="">(missing)</td><td>Internal<br>
<span class=""><span></span></span></td>
</tr>
<tr class="row1">
<tr class="row0">
<td class="file">numberformatter.h</td><td class="proto">void icu::number::impl::Usage::set(StringPiece)</td><td class="">(missing)</td><td>Internal<br>
<span class=""><span></span></span></td>
</tr>
<tr class="row0">
<tr class="row1">
<td class="file">numberrangeformatter.h</td><td class="proto">std::pair&lt; StringClass, StringClass &gt; icu::number::FormattedNumberRange::getDecimalNumbers(UErrorCode&amp;) const</td><td class="">(missing)</td><td>Draft<br>
<span class=""><span>ICU 68</span></span></td>
</tr>
<tr class="row1">
<tr class="row0">
<td class="file">plurrule.h</td><td class="proto">UnicodeString icu::PluralRules::select(const number::FormattedNumberRange&amp;, UErrorCode&amp;) const</td><td class="">(missing)</td><td>Draft<br>
<span class=""><span>ICU 68</span></span></td>
</tr>
<tr class="row0">
<tr class="row1">
<td class="file">plurrule.h</td><td class="proto">UnicodeString icu::PluralRules::select(const number::impl::UFormattedNumberRangeData*, UErrorCode&amp;) const</td><td class="">(missing)</td><td>Internal<br>
<span class=""><span></span></span></td>
</tr>
<tr class="row0">
<td class="file">plurrule.h</td><td class="proto">int32_t icu::PluralRules::getSamples(const UnicodeString&amp;, FixedDecimal*, int32_t, UErrorCode&amp;)</td><td class="">(missing)</td><td>Internal<br>
<span class=""><span></span></span></td>
</tr>
<tr class="row1">
<td class="file">timezone.h</td><td class="proto"><tt>static</tt> TimeZone* icu::TimeZone::forLocaleOrDefault(const Locale&amp;)</td><td class="">(missing)</td><td>Internal<br>
<span class=""><span></span></span></td>
@ -880,66 +956,70 @@
<span class=""><span>ICU 68</span></span></td>
</tr>
<tr class="row1">
<td class="file">uniset.h</td><td class="proto">USet* icu::UnicodeSet::toUSet()</td><td class="">(missing)</td><td>Stable<br>
<span class=""><span>ICU 4.2</span></span></td>
</tr>
<tr class="row0">
<td class="file">unum.h</td><td class="proto"><tt>enum</tt> UNumberFormatMinimumGroupingDigits::UNUM_MINIMUM_GROUPING_DIGITS_AUTO</td><td class="">(missing)</td><td>Draft<br>
<span class=""><span>ICU 68</span></span></td>
</tr>
<tr class="row0">
<tr class="row1">
<td class="file">unum.h</td><td class="proto"><tt>enum</tt> UNumberFormatMinimumGroupingDigits::UNUM_MINIMUM_GROUPING_DIGITS_MIN2</td><td class="">(missing)</td><td>Draft<br>
<span class=""><span>ICU 68</span></span></td>
</tr>
<tr class="row1">
<tr class="row0">
<td class="file">unumberformatter.h</td><td class="proto"><tt>enum</tt> UNumberUnitWidth::UNUM_UNIT_WIDTH_FORMAL</td><td class="">(missing)</td><td>Draft<br>
<span class=""><span>ICU 68</span></span></td>
</tr>
<tr class="row0">
<tr class="row1">
<td class="file">unumberformatter.h</td><td class="proto"><tt>enum</tt> UNumberUnitWidth::UNUM_UNIT_WIDTH_VARIANT</td><td class="">(missing)</td><td>Draft<br>
<span class=""><span>ICU 68</span></span></td>
</tr>
<tr class="row1">
<tr class="row0">
<td class="file">unumberformatter.h</td><td class="proto">int32_t unumf_resultToDecimalNumber(const UFormattedNumber*, char*, int32_t, UErrorCode*)</td><td class="">(missing)</td><td>Draft<br>
<span class=""><span>ICU 68</span></span></td>
</tr>
<tr class="row0">
<tr class="row1">
<td class="file">unumberrangeformatter.h</td><td class="proto">UFormattedNumberRange* unumrf_openResult(UErrorCode*)</td><td class="">(missing)</td><td>Draft<br>
<span class=""><span>ICU 68</span></span></td>
</tr>
<tr class="row1">
<tr class="row0">
<td class="file">unumberrangeformatter.h</td><td class="proto">UNumberRangeFormatter* unumrf_openForSkeletonWithCollapseAndIdentityFallback(const UChar*, int32_t, UNumberRangeCollapse, UNumberRangeIdentityFallback, const char*, UParseError*, UErrorCode*)</td><td class="">(missing)</td><td>Draft<br>
<span class=""><span>ICU 68</span></span></td>
</tr>
<tr class="row0">
<tr class="row1">
<td class="file">unumberrangeformatter.h</td><td class="proto">UNumberRangeIdentityResult unumrf_resultGetIdentityResult(const UFormattedNumberRange*, UErrorCode*)</td><td class="">(missing)</td><td>Draft<br>
<span class=""><span>ICU 68</span></span></td>
</tr>
<tr class="row1">
<tr class="row0">
<td class="file">unumberrangeformatter.h</td><td class="proto">const UFormattedValue* unumrf_resultAsValue(const UFormattedNumberRange*, UErrorCode*)</td><td class="">(missing)</td><td>Draft<br>
<span class=""><span>ICU 68</span></span></td>
</tr>
<tr class="row0">
<tr class="row1">
<td class="file">unumberrangeformatter.h</td><td class="proto">int32_t unumrf_resultGetFirstDecimalNumber(const UFormattedNumberRange*, char*, int32_t, UErrorCode*)</td><td class="">(missing)</td><td>Draft<br>
<span class=""><span>ICU 68</span></span></td>
</tr>
<tr class="row1">
<tr class="row0">
<td class="file">unumberrangeformatter.h</td><td class="proto">int32_t unumrf_resultGetSecondDecimalNumber(const UFormattedNumberRange*, char*, int32_t, UErrorCode*)</td><td class="">(missing)</td><td>Draft<br>
<span class=""><span>ICU 68</span></span></td>
</tr>
<tr class="row0">
<tr class="row1">
<td class="file">unumberrangeformatter.h</td><td class="proto">void unumrf_close(UNumberRangeFormatter*)</td><td class="">(missing)</td><td>Draft<br>
<span class=""><span>ICU 68</span></span></td>
</tr>
<tr class="row1">
<tr class="row0">
<td class="file">unumberrangeformatter.h</td><td class="proto">void unumrf_closeResult(UFormattedNumberRange*)</td><td class="">(missing)</td><td>Draft<br>
<span class=""><span>ICU 68</span></span></td>
</tr>
<tr class="row0">
<tr class="row1">
<td class="file">unumberrangeformatter.h</td><td class="proto">void unumrf_formatDecimalRange(const UNumberRangeFormatter*, const char*, int32_t, const char*, int32_t, UFormattedNumberRange*, UErrorCode*)</td><td class="">(missing)</td><td>Draft<br>
<span class=""><span>ICU 68</span></span></td>
</tr>
<tr class="row1">
<tr class="row0">
<td class="file">unumberrangeformatter.h</td><td class="proto">void unumrf_formatDoubleRange(const UNumberRangeFormatter*, double, double, UFormattedNumberRange*, UErrorCode*)</td><td class="">(missing)</td><td>Draft<br>
<span class=""><span>ICU 68</span></span></td>
</tr>
<tr class="row0">
<tr class="row1">
<td class="file">upluralrules.h</td><td class="proto">int32_t uplrules_selectForRange(const UPluralRules*, const struct UFormattedNumberRange*, UChar*, int32_t, UErrorCode*)</td><td class="">(missing)</td><td>Draft<br>
<span class=""><span>ICU 68</span></span></td>
</tr>
@ -966,122 +1046,98 @@
<td class="file">dtptngen.h</td><td class="proto">UDateFormatHourCycle icu::DateTimePatternGenerator::getDefaultHourCycle(UErrorCode&amp;) const</td><td class="" colspan="2" align="center">Draft<br>ICU 67</td>
</tr>
<tr class="row0">
<td class="file">listformatter.h</td><td class="proto"><tt>static</tt> ListFormatter* icu::ListFormatter::createInstance(const Locale&amp;, UListFormatterType, UListFormatterWidth, UErrorCode&amp;)</td><td class="" colspan="2" align="center">Draft<br>ICU 67</td>
</tr>
<tr class="row1">
<td class="file">localematcher.h</td><td class="proto">Builder&amp; icu::LocaleMatcher::Builder::setDirection(ULocMatchDirection)</td><td class="" colspan="2" align="center">Draft<br>ICU 67</td>
</tr>
<tr class="row0">
<tr class="row1">
<td class="file">localematcher.h</td><td class="proto"><tt>enum</tt> ULocMatchDirection::ULOCMATCH_DIRECTION_ONLY_TWO_WAY</td><td class="" colspan="2" align="center">Draft<br>ICU 67</td>
</tr>
<tr class="row1">
<tr class="row0">
<td class="file">localematcher.h</td><td class="proto"><tt>enum</tt> ULocMatchDirection::ULOCMATCH_DIRECTION_WITH_ONE_WAY</td><td class="" colspan="2" align="center">Draft<br>ICU 67</td>
</tr>
<tr class="row0">
<tr class="row1">
<td class="file">locid.h</td><td class="proto">void icu::Locale::canonicalize(UErrorCode&amp;)</td><td class="" colspan="2" align="center">Draft<br>ICU 67</td>
</tr>
<tr class="row1">
<tr class="row0">
<td class="file">measfmt.h</td><td class="proto">void icu::MeasureFormat::parseObject(const UnicodeString&amp;, Formattable&amp;, ParsePosition&amp;) const</td><td class="" colspan="2" align="center">Draft<br>ICU 53</td>
</tr>
<tr class="row0">
<tr class="row1">
<td class="file">measunit.h</td><td class="proto">MeasureUnit icu::MeasureUnit::product(const MeasureUnit&amp;, UErrorCode&amp;) const</td><td class="" colspan="2" align="center">Draft<br>ICU 67</td>
</tr>
<tr class="row1">
<tr class="row0">
<td class="file">measunit.h</td><td class="proto">MeasureUnit icu::MeasureUnit::reciprocal(UErrorCode&amp;) const</td><td class="" colspan="2" align="center">Draft<br>ICU 67</td>
</tr>
<tr class="row0">
<tr class="row1">
<td class="file">measunit.h</td><td class="proto">MeasureUnit icu::MeasureUnit::withDimensionality(int32_t, UErrorCode&amp;) const</td><td class="" colspan="2" align="center">Draft<br>ICU 67</td>
</tr>
<tr class="row1">
<tr class="row0">
<td class="file">measunit.h</td><td class="proto">MeasureUnit icu::MeasureUnit::withSIPrefix(UMeasureSIPrefix, UErrorCode&amp;) const</td><td class="" colspan="2" align="center">Draft<br>ICU 67</td>
</tr>
<tr class="row0">
<tr class="row1">
<td class="file">measunit.h</td><td class="proto">MeasureUnit&amp; icu::MeasureUnit::operator=(MeasureUnit&amp;&amp;) noexcept</td><td class="" colspan="2" align="center">Draft<br>ICU 67</td>
</tr>
<tr class="row1">
<tr class="row0">
<td class="file">measunit.h</td><td class="proto">UMeasureSIPrefix icu::MeasureUnit::getSIPrefix(UErrorCode&amp;) const</td><td class="" colspan="2" align="center">Draft<br>ICU 67</td>
</tr>
<tr class="row0">
<tr class="row1">
<td class="file">measunit.h</td><td class="proto">UMeasureUnitComplexity icu::MeasureUnit::getComplexity(UErrorCode&amp;) const</td><td class="" colspan="2" align="center">Draft<br>ICU 67</td>
</tr>
<tr class="row1">
<tr class="row0">
<td class="file">measunit.h</td><td class="proto">const char* icu::MeasureUnit::getIdentifier() const</td><td class="" colspan="2" align="center">Draft<br>ICU 67</td>
</tr>
<tr class="row0">
<tr class="row1">
<td class="file">measunit.h</td><td class="proto">icu::MeasureUnit::MeasureUnit(MeasureUnit&amp;&amp;) noexcept</td><td class="" colspan="2" align="center">Draft<br>ICU 67</td>
</tr>
<tr class="row1">
<tr class="row0">
<td class="file">measunit.h</td><td class="proto">int32_t icu::MeasureUnit::getDimensionality(UErrorCode&amp;) const</td><td class="" colspan="2" align="center">Draft<br>ICU 67</td>
</tr>
<tr class="row0">
<tr class="row1">
<td class="file">measunit.h</td><td class="proto"><tt>static</tt> MeasureUnit icu::MeasureUnit::forIdentifier(StringPiece, UErrorCode&amp;)</td><td class="" colspan="2" align="center">Draft<br>ICU 67</td>
</tr>
<tr class="row1">
<tr class="row0">
<td class="file">stringpiece.h</td><td class="proto">icu::StringPiece::StringPiece(const char8_t*)</td><td class="" colspan="2" align="center">Draft<br>ICU 67</td>
</tr>
<tr class="row0">
<tr class="row1">
<td class="file">stringpiece.h</td><td class="proto">icu::StringPiece::StringPiece(const char8_t*, int32_t)</td><td class="" colspan="2" align="center">Draft<br>ICU 67</td>
</tr>
<tr class="row1">
<tr class="row0">
<td class="file">stringpiece.h</td><td class="proto">icu::StringPiece::StringPiece(const std::u8string&amp;)</td><td class="" colspan="2" align="center">Draft<br>ICU 67</td>
</tr>
<tr class="row0">
<tr class="row1">
<td class="file">stringpiece.h</td><td class="proto">icu::StringPiece::StringPiece(std::nullptr_t)</td><td class="" colspan="2" align="center">Draft<br>ICU 67</td>
</tr>
<tr class="row1">
<tr class="row0">
<td class="file">stringpiece.h</td><td class="proto">int32_t icu::StringPiece::compare(StringPiece)</td><td class="" colspan="2" align="center">Draft<br>ICU 67</td>
</tr>
<tr class="row0">
<tr class="row1">
<td class="file">stringpiece.h</td><td class="proto">int32_t icu::StringPiece::find(StringPiece, int32_t)</td><td class="" colspan="2" align="center">Draft<br>ICU 67</td>
</tr>
<tr class="row1">
<tr class="row0">
<td class="file">stringpiece.h</td><td class="proto">void icu::StringPiece::set(const char8_t*)</td><td class="" colspan="2" align="center">Draft<br>ICU 67</td>
</tr>
<tr class="row0">
<tr class="row1">
<td class="file">stringpiece.h</td><td class="proto">void icu::StringPiece::set(const char8_t*, int32_t)</td><td class="" colspan="2" align="center">Draft<br>ICU 67</td>
</tr>
<tr class="row1">
<tr class="row0">
<td class="file">udat.h</td><td class="proto"><tt>enum</tt> UDateFormatHourCycle::UDAT_HOUR_CYCLE_11</td><td class="" colspan="2" align="center">Draft<br>ICU 67</td>
</tr>
<tr class="row0">
<tr class="row1">
<td class="file">udat.h</td><td class="proto"><tt>enum</tt> UDateFormatHourCycle::UDAT_HOUR_CYCLE_12</td><td class="" colspan="2" align="center">Draft<br>ICU 67</td>
</tr>
<tr class="row1">
<tr class="row0">
<td class="file">udat.h</td><td class="proto"><tt>enum</tt> UDateFormatHourCycle::UDAT_HOUR_CYCLE_23</td><td class="" colspan="2" align="center">Draft<br>ICU 67</td>
</tr>
<tr class="row0">
<tr class="row1">
<td class="file">udat.h</td><td class="proto"><tt>enum</tt> UDateFormatHourCycle::UDAT_HOUR_CYCLE_24</td><td class="" colspan="2" align="center">Draft<br>ICU 67</td>
</tr>
<tr class="row1">
<tr class="row0">
<td class="file">udateintervalformat.h</td><td class="proto">void udtitvfmt_formatCalendarToResult(const UDateIntervalFormat*, UCalendar*, UCalendar*, UFormattedDateInterval*, UErrorCode*)</td><td class="" colspan="2" align="center">Draft<br>ICU 67</td>
</tr>
<tr class="row0">
<tr class="row1">
<td class="file">udateintervalformat.h</td><td class="proto">void udtitvfmt_formatToResult(const UDateIntervalFormat*, UDate, UDate, UFormattedDateInterval*, UErrorCode*)</td><td class="" colspan="2" align="center">Draft<br>ICU 67</td>
</tr>
<tr class="row1">
<tr class="row0">
<td class="file">udatpg.h</td><td class="proto">UDateFormatHourCycle udatpg_getDefaultHourCycle(const UDateTimePatternGenerator*, UErrorCode*)</td><td class="" colspan="2" align="center">Draft<br>ICU 67</td>
</tr>
<tr class="row0">
<td class="file">ulistformatter.h</td><td class="proto">UListFormatter* ulistfmt_openForType(const char*, UListFormatterType, UListFormatterWidth, UErrorCode*)</td><td class="" colspan="2" align="center">Draft<br>ICU 67</td>
</tr>
<tr class="row1">
<td class="file">ulistformatter.h</td><td class="proto"><tt>enum</tt> UListFormatterType::ULISTFMT_TYPE_AND</td><td class="" colspan="2" align="center">Draft<br>ICU 67</td>
</tr>
<tr class="row0">
<td class="file">ulistformatter.h</td><td class="proto"><tt>enum</tt> UListFormatterType::ULISTFMT_TYPE_OR</td><td class="" colspan="2" align="center">Draft<br>ICU 67</td>
</tr>
<tr class="row1">
<td class="file">ulistformatter.h</td><td class="proto"><tt>enum</tt> UListFormatterType::ULISTFMT_TYPE_UNITS</td><td class="" colspan="2" align="center">Draft<br>ICU 67</td>
</tr>
<tr class="row0">
<td class="file">ulistformatter.h</td><td class="proto"><tt>enum</tt> UListFormatterWidth::ULISTFMT_WIDTH_NARROW</td><td class="" colspan="2" align="center">Draft<br>ICU 67</td>
</tr>
<tr class="row1">
<td class="file">ulistformatter.h</td><td class="proto"><tt>enum</tt> UListFormatterWidth::ULISTFMT_WIDTH_SHORT</td><td class="" colspan="2" align="center">Draft<br>ICU 67</td>
</tr>
<tr class="row0">
<td class="file">ulistformatter.h</td><td class="proto"><tt>enum</tt> UListFormatterWidth::ULISTFMT_WIDTH_WIDE</td><td class="" colspan="2" align="center">Draft<br>ICU 67</td>
</tr>
<tr class="row1">
<td class="file">uregex.h</td><td class="proto"><tt>enum</tt> URegexpFlag::UREGEX_CANON_EQ</td><td class="" colspan="2" align="center">Draft<br>ICU 2.4</td>
</tr>
@ -1122,7 +1178,7 @@
<a href="#_top">(jump back to top)</a>
<hr>
<p>
<i><font size="-1">Contents generated by StableAPI tool on Wed Sep 30 17:55:30 PDT 2020<br>
<i><font size="-1">Contents generated by StableAPI tool on Fri Oct 23 11:35:16 PDT 2020<br>
Copyright &copy; 2017 and later: Unicode, Inc. and others.<br>
License &amp; terms of use: http://www.unicode.org/copyright.html
</font></i>

View file

@ -23,8 +23,10 @@ Removed from ICU 67
| File | API | ICU 67 | ICU 68 |
|---|---|---|---|
| fmtable.h | const UFormattable* icu::Formattable::toUFormattable() | StableICU 52 | (missing)
| measunit.h | LocalArray&lt;MeasureUnit&gt; icu::MeasureUnit::splitToSingleUnits(int32_t&amp;, UErrorCode&amp;) const | InternalICU 67 | (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::internalGetIndexForTypeAndSubtype(const char*, const char*) | Internal | (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> UClassID icu::NoUnit::getStaticClassID() | 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
@ -57,6 +60,7 @@ Changed in ICU 68 (old, new)
|---|---|---|---|
| bytestrie.h | BytesTrie&amp; icu::BytesTrie::resetToState64(uint64_t) | 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
| 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
@ -132,6 +136,13 @@ Changed in ICU 68 (old, new)
| 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 | 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 | <tt>enum</tt> ULocAvailableType::ULOC_AVAILABLE_DEFAULT | 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 | 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
| 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
@ -224,10 +237,18 @@ Promoted to stable in ICU 68
| 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 | 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 | <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_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_DATA_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 | 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
| 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::setNoDefaultLocale() | (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
| 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 | 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
| 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
| udateintervalformat.h | UDisplayContext udtitvfmt_getContext(const UDateIntervalFormat*, UDisplayContextType, 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
| 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_MIN2 | (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 char8_t*, int32_t) | 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 | <tt>enum</tt> ULocMatchDirection::ULOCMATCH_DIRECTION_ONLY_TWO_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_formatToResult(const UDateIntervalFormat*, UDate, UDate, UFormattedDateInterval*, 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 |
| 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 |
@ -373,7 +389,7 @@ This section shows cases where the signature was "simplified" for the sake of co
## 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.
License & terms of use: http://www.unicode.org/copyright.html

View file

@ -35,6 +35,7 @@
#include "unicode/bytestream.h"
#include "unicode/locid.h"
#include "unicode/localebuilder.h"
#include "unicode/strenum.h"
#include "unicode/stringpiece.h"
#include "unicode/uloc.h"
@ -1336,7 +1337,10 @@ AliasReplacer::replaceTerritory(UVector& toBeFreed, UErrorCode& status)
// Cannot use nullptr for language because that will construct
// the default locale, in that case, use "und" to get the correct
// locale.
Locale l(language == nullptr ? "und" : language, nullptr, script);
Locale l = LocaleBuilder()
.setLanguage(language == nullptr ? "und" : language)
.setScript(script)
.build(status);
l.addLikelySubtags(status);
const char* likelyRegion = l.getCountry();
CharString* item = nullptr;
@ -1453,7 +1457,7 @@ AliasReplacer::outputToString(
int32_t variantsStart = out.length();
for (int32_t i = 0; i < variants.size(); i++) {
out.append(SEP_CHAR, status)
.append((const char*)((UVector*)variants.elementAt(i)),
.append((const char*)(variants.elementAt(i)),
status);
}
T_CString_toUpperCase(out.data() + variantsStart);
@ -2453,9 +2457,13 @@ Locale::setKeywordValue(const char* keywordName, const char* keywordValue, UErro
if (U_FAILURE(status)) {
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 newLength = uloc_setKeywordValue(keywordName, keywordValue, fullName,
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 */
if (status == U_BUFFER_OVERFLOW_ERROR) {
U_ASSERT(newLength > bufferLength);
@ -2472,6 +2480,7 @@ Locale::setKeywordValue(const char* keywordName, const char* keywordValue, UErro
fullName = newFullName;
status = U_ZERO_ERROR;
uloc_setKeywordValue(keywordName, keywordValue, fullName, newLength, &status);
U_ASSERT(status != U_STRING_NOT_TERMINATED_WARNING);
} else {
U_ASSERT(newLength <= bufferLength);
}

View file

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

View file

@ -877,6 +877,9 @@ uloc_setKeywordValue(const char* keywordName,
if(U_FAILURE(*status)) {
return -1;
}
if (*status == U_STRING_NOT_TERMINATED_WARNING) {
*status = U_ZERO_ERROR;
}
if (keywordName == NULL || keywordName[0] == 0 || bufferCapacity <= 1) {
*status = U_ILLEGAL_ARGUMENT_ERROR;
return 0;
@ -914,6 +917,7 @@ uloc_setKeywordValue(const char* keywordName,
startSearchHere = (char*)locale_getKeywordsStart(buffer);
if(startSearchHere == NULL || (startSearchHere[1]==0)) {
if(keywordValueLen == 0) { /* no keywords = nothing to remove */
U_ASSERT(*status != U_STRING_NOT_TERMINATED_WARNING);
return bufLen;
}
@ -933,6 +937,7 @@ uloc_setKeywordValue(const char* keywordName,
startSearchHere += keywordNameLen;
*startSearchHere++ = '=';
uprv_strcpy(startSearchHere, keywordValueBuffer);
U_ASSERT(*status != U_STRING_NOT_TERMINATED_WARNING);
return needLen;
} /* end shortcut - no @ */
@ -1047,13 +1052,27 @@ uloc_setKeywordValue(const char* keywordName,
if (!handledInputKeyAndValue || U_FAILURE(*status)) {
/* if input key/value specified removal of a keyword not present in locale, or
* there was an error in CharString.append, leave original locale alone. */
U_ASSERT(*status != U_STRING_NOT_TERMINATED_WARNING);
return bufLen;
}
// needLen = length of the part before '@'
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);
U_ASSERT(*status != U_STRING_NOT_TERMINATED_WARNING);
return needLen;
}
/* ### ID parsing implementation **************************************************/

View file

@ -143,6 +143,11 @@
* <td>icu::MessageFormat</td>
* </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>unumberformatter.h, unum.h</td>
* <td>icu::number::NumberFormatter (ICU 60+) or icu::NumberFormat (older versions)</td>

View file

@ -36,17 +36,58 @@
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.
* Returns the Windows time zone converted to an ICU time zone as a heap-allocated buffer, or nullptr upon failure.
* This is main Windows time zone detection function.
*
* It 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.
* 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
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;
uprv_memset(&dynamicTZI, 0, sizeof(dynamicTZI));
SYSTEMTIME systemTimeAllZero;
@ -86,22 +127,138 @@ uprv_detectWindowsTimeZone()
// Note '-' before 'utcOffsetMin'. The timezone ID's sign convention
// is that a timezone ahead of UTC is Etc/GMT-<offset> and a timezone
// 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)) {
return uprv_strdup(gmtOffsetTz);
}
}
}
// If DST is NOT disabled, but we have an empty TimeZoneKeyName, then it is unclear
// what we should do as this should not happen.
// If DST is NOT disabled, but the TimeZoneKeyName field of the struct is NULL, then we may be dealing with a
// 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) {
// 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;
#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;
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).
StackUResourceBundle winTZBundle;
@ -123,18 +280,29 @@ uprv_detectWindowsTimeZone()
int regionCodeLen = GetGeoInfoW(geoId, GEO_ISO2, regionCodeW, UPRV_LENGTHOF(regionCodeW), 0);
const UChar *icuTZ16 = nullptr;
int32_t tzLen;
int32_t tzListLen = 0;
if (regionCodeLen != 0) {
for (int i = 0; i < UPRV_LENGTHOF(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)) {
// fallback to default "001" (world)
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

File diff suppressed because it is too large Load diff

View file

@ -1843,7 +1843,6 @@ likelySubtags:table(nofallback){
zh_Hant{"zh_Hant_TW"}
zh_ID{"zh_Hant_ID"}
zh_MO{"zh_Hant_MO"}
zh_MY{"zh_Hant_MY"}
zh_PA{"zh_Hant_PA"}
zh_PF{"zh_Hant_PF"}
zh_PH{"zh_Hant_PH"}

View file

@ -30290,7 +30290,7 @@ supplementalData:table(nofallback){
49931000,
57326521,
}
zh_Hant{
zh{
populationShareF:int{49170000}
}
zmi{

View file

@ -3,9 +3,9 @@
// License & terms of use: http://www.unicode.org/copyright.html
//---------------------------------------------------------
// Build tool: tz2icu
// Build date: Thu Oct 8 19:58:22 2020
// Build date: Wed Oct 21 21:13:50 2020
// tz database: ftp://ftp.iana.org/tz/
// tz version: 2020b
// tz version: 2020d
// ICU version: 68.1
//---------------------------------------------------------
// >> !!! >> THIS IS A MACHINE-GENERATED FILE << !!! <<
@ -13,7 +13,7 @@
//---------------------------------------------------------
zoneinfo64:table(nofallback) {
TZVersion { "2020b" }
TZVersion { "2020d" }
Zones:array {
/* ACT */ :int { 356 } //Z#0
/* AET */ :int { 368 } //Z#1
@ -1363,22 +1363,22 @@ zoneinfo64:table(nofallback) {
} //Z#268
/* Asia/Gaza */ :table {
transPre32:intvector { -1, 2109557424 }
trans:intvector { -933645600, -857358000, -844300800, -825822000, -812685600, -794199600, -779853600, -762656400, -748310400, -731127600, -399088800, -386650800, -368330400, -355114800, -336790800, -323654400, -305168400, -292032000, -273632400, -260496000, -242096400, -228960000, -210560400, -197424000, -178938000, -165801600, -147402000, -134265600, -115866000, -102643200, -84330000, -81313200, 142380000, 150843600, 167176800, 178664400, 334015200, 337644000, 452556000, 462232800, 482277600, 495579600, 516751200, 526424400, 545436000, 558478800, 576626400, 589323600, 609890400, 620773200, 638316000, 651618000, 669765600, 683672400, 701820000, 715726800, 733701600, 747176400, 765151200, 778021200, 796600800, 810075600, 828655200, 843170400, 860104800, 874620000, 891554400, 906069600, 924213600, 939934800, 956268000, 971989200, 987717600, 1003438800, 1019167200, 1034888400, 1050616800, 1066338000, 1082066400, 1096581600, 1113516000, 1128380400, 1143842400, 1158872400, 1175378400, 1189638000, 1206655200, 1219957200, 1238104800, 1252015200, 1269640860, 1281474000, 1301608860, 1312146000, 1333058400, 1348178400, 1364508000, 1380229200, 1395957600, 1414098000, 1427493600, 1445547600, 1458946800, 1477692000, 1490396400, 1509141600, 1521846000, 1540591200, 1553810400, 1572040800 }
trans:intvector { -933645600, -857358000, -844300800, -825822000, -812685600, -794199600, -779853600, -762656400, -748310400, -731127600, -399088800, -386650800, -368330400, -355114800, -336790800, -323654400, -305168400, -292032000, -273632400, -260496000, -242096400, -228960000, -210560400, -197424000, -178938000, -165801600, -147402000, -134265600, -115866000, -102643200, -84330000, -81313200, 142380000, 150843600, 167176800, 178664400, 334015200, 337644000, 452556000, 462232800, 482277600, 495579600, 516751200, 526424400, 545436000, 558478800, 576626400, 589323600, 609890400, 620773200, 638316000, 651618000, 669765600, 683672400, 701820000, 715726800, 733701600, 747176400, 765151200, 778021200, 796600800, 810075600, 828655200, 843170400, 860104800, 874620000, 891554400, 906069600, 924213600, 939934800, 956268000, 971989200, 987717600, 1003438800, 1019167200, 1034888400, 1050616800, 1066338000, 1082066400, 1096581600, 1113516000, 1128380400, 1143842400, 1158872400, 1175378400, 1189638000, 1206655200, 1219957200, 1238104800, 1252015200, 1269640860, 1281474000, 1301608860, 1312146000, 1333058400, 1348178400, 1364508000, 1380229200, 1395957600, 1414098000, 1427493600, 1445551200, 1458946800, 1477692000, 1490396400, 1509141600, 1521846000, 1540591200, 1553810400, 1572037200, 1585346400, 1603490400 }
typeOffsets:intvector { 8272, 0, 7200, 0, 7200, 3600 }
typeMap:bin { "010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201" }
typeMap:bin { "0102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201" }
finalRule { "Palestine" }
finalRaw:int { 7200 }
finalYear:int { 2020 }
finalYear:int { 2021 }
} //Z#269
/* Asia/Harbin */ :int { 315 } //Z#270
/* Asia/Hebron */ :table {
transPre32:intvector { -1, 2109557273 }
trans:intvector { -933645600, -857358000, -844300800, -825822000, -812685600, -794199600, -779853600, -762656400, -748310400, -731127600, -399088800, -386650800, -368330400, -355114800, -336790800, -323654400, -305168400, -292032000, -273632400, -260496000, -242096400, -228960000, -210560400, -197424000, -178938000, -165801600, -147402000, -134265600, -115866000, -102643200, -84330000, -81313200, 142380000, 150843600, 167176800, 178664400, 334015200, 337644000, 452556000, 462232800, 482277600, 495579600, 516751200, 526424400, 545436000, 558478800, 576626400, 589323600, 609890400, 620773200, 638316000, 651618000, 669765600, 683672400, 701820000, 715726800, 733701600, 747176400, 765151200, 778021200, 796600800, 810075600, 828655200, 843170400, 860104800, 874620000, 891554400, 906069600, 924213600, 939934800, 956268000, 971989200, 987717600, 1003438800, 1019167200, 1034888400, 1050616800, 1066338000, 1082066400, 1096581600, 1113516000, 1128380400, 1143842400, 1158872400, 1175378400, 1189638000, 1206655200, 1220216400, 1238104800, 1252015200, 1269554400, 1281474000, 1301608860, 1312146000, 1314655200, 1317330000, 1333058400, 1348178400, 1364508000, 1380229200, 1395957600, 1414098000, 1427493600, 1445547600, 1458946800, 1477692000, 1490396400, 1509141600, 1521846000, 1540591200, 1553810400, 1572040800 }
trans:intvector { -933645600, -857358000, -844300800, -825822000, -812685600, -794199600, -779853600, -762656400, -748310400, -731127600, -399088800, -386650800, -368330400, -355114800, -336790800, -323654400, -305168400, -292032000, -273632400, -260496000, -242096400, -228960000, -210560400, -197424000, -178938000, -165801600, -147402000, -134265600, -115866000, -102643200, -84330000, -81313200, 142380000, 150843600, 167176800, 178664400, 334015200, 337644000, 452556000, 462232800, 482277600, 495579600, 516751200, 526424400, 545436000, 558478800, 576626400, 589323600, 609890400, 620773200, 638316000, 651618000, 669765600, 683672400, 701820000, 715726800, 733701600, 747176400, 765151200, 778021200, 796600800, 810075600, 828655200, 843170400, 860104800, 874620000, 891554400, 906069600, 924213600, 939934800, 956268000, 971989200, 987717600, 1003438800, 1019167200, 1034888400, 1050616800, 1066338000, 1082066400, 1096581600, 1113516000, 1128380400, 1143842400, 1158872400, 1175378400, 1189638000, 1206655200, 1220216400, 1238104800, 1252015200, 1269554400, 1281474000, 1301608860, 1312146000, 1314655200, 1317330000, 1333058400, 1348178400, 1364508000, 1380229200, 1395957600, 1414098000, 1427493600, 1445551200, 1458946800, 1477692000, 1490396400, 1509141600, 1521846000, 1540591200, 1553810400, 1572037200, 1585346400, 1603490400 }
typeOffsets:intvector { 8423, 0, 7200, 0, 7200, 3600 }
typeMap:bin { "0102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201" }
typeMap:bin { "01020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201020102010201" }
finalRule { "Palestine" }
finalRaw:int { 7200 }
finalYear:int { 2020 }
finalYear:int { 2021 }
} //Z#271
/* Asia/Ho_Chi_Minh */ :table {
trans:intvector { -2004073600, -1851577590, -852105600, -782643600, -767869200, -718095600, -457776000, -315648000, 171820800 }
@ -2601,12 +2601,12 @@ zoneinfo64:table(nofallback) {
typeMap:bin { "0102" }
} //Z#560
/* Pacific/Fiji */ :table {
trans:intvector { -1709985344, 909842400, 920124000, 941896800, 951573600, 1259416800, 1269698400, 1287842400, 1299333600, 1319292000, 1327154400, 1350741600, 1358604000, 1382796000, 1390050000, 1414850400, 1421503200, 1446300000, 1452952800, 1478354400, 1484402400, 1509804000, 1515852000, 1541253600, 1547301600, 1573308000 }
trans:intvector { -1709985344, 909842400, 920124000, 941896800, 951573600, 1259416800, 1269698400, 1287842400, 1299333600, 1319292000, 1327154400, 1350741600, 1358604000, 1382796000, 1390050000, 1414850400, 1421503200, 1446300000, 1452952800, 1478354400, 1484402400, 1509804000, 1515852000, 1541253600, 1547301600, 1573308000, 1578751200, 1608386400, 1610805600, 1636812000 }
typeOffsets:intvector { 42944, 0, 43200, 0, 43200, 3600 }
typeMap:bin { "0102010201020102010201020102010201020102010201020102" }
typeMap:bin { "010201020102010201020102010201020102010201020102010201020102" }
finalRule { "Fiji" }
finalRaw:int { 43200 }
finalYear:int { 2020 }
finalYear:int { 2022 }
} //Z#561
/* Pacific/Funafuti */ :table {
transPre32:intvector { -1, 2117471484 }
@ -3127,7 +3127,7 @@ zoneinfo64:table(nofallback) {
8, -30, -1, 7200, 1, 3, 1, -1, 7200, 1, 3600
} //_#19
Palestine:intvector {
2, -31, -6, 0, 0, 9, -31, -7, 3600, 0, 3600
2, 24, -7, 0, 0, 9, 24, -7, 3600, 0, 3600
} //_#20
Para:intvector {
9, 1, -1, 0, 0, 2, 22, -1, 0, 0, 3600

View file

@ -461,11 +461,11 @@ uk{
other{"{0} електрон-вольта"}
}
foodcalorie{
dnam{"Калорії"}
few{"{0} Калорії"}
many{"{0} Калорій"}
one{"{0} Калорія"}
other{"{0} Калорії"}
dnam{"кілокалорії"}
few{"{0} кілокалорії"}
many{"{0} кілокалорій"}
one{"{0} кілокалорія"}
other{"{0} кілокалорії"}
}
joule{
dnam{"джоулі"}
@ -2371,11 +2371,11 @@ uk{
other{"{0} еВ"}
}
foodcalorie{
dnam{"Кал"}
few{"{0} Кал"}
many{"{0} Кал"}
one{"{0} Кал"}
other{"{0} Кал"}
dnam{"ккал"}
few{"{0} ккал"}
many{"{0} ккал"}
one{"{0} ккал"}
other{"{0} ккал"}
}
joule{
dnam{"джоулі"}
@ -2385,11 +2385,11 @@ uk{
other{"{0} Дж"}
}
kilocalorie{
dnam{"Ккал"}
few{"{0} Ккал"}
many{"{0} Ккал"}
one{"{0} Ккал"}
other{"{0} Ккал"}
dnam{"ккал"}
few{"{0} ккал"}
many{"{0} ккал"}
one{"{0} ккал"}
other{"{0} ккал"}
}
kilojoule{
dnam{"кілоджоуль"}

View file

@ -1604,7 +1604,7 @@ zh{
ls{"印度洋时间"}
}
"meta:Indochina"{
ls{"印度中国时间"}
ls{"印度支那时间"}
}
"meta:Indonesia_Central"{
ls{"印度尼西亚中部时间"}

View file

@ -1627,7 +1627,7 @@ zh_Hant{
ls{"印度洋時間"}
}
"meta:Indochina"{
ls{"印度中國時間"}
ls{"印度支那時間"}
}
"meta:Indonesia_Central"{
ls{"印尼中部時間"}

View file

@ -1422,7 +1422,11 @@ DateIntervalFormat::setIntervalPattern(UCalendarDateFields field,
if ( field == UCAL_AM_PM ) {
fInfo->getIntervalPattern(*bestSkeleton, UCAL_HOUR, pattern,status);
if ( !pattern.isEmpty() ) {
setIntervalPattern(field, pattern);
UBool suppressDayPeriodField = fSkeleton.indexOf(CAP_J) != -1;
UnicodeString adjustIntervalPattern;
adjustFieldWidth(*skeleton, *bestSkeleton, pattern, differenceInfo,
suppressDayPeriodField, adjustIntervalPattern);
setIntervalPattern(field, adjustIntervalPattern);
}
return false;
}
@ -1694,27 +1698,23 @@ DateIntervalFormat::adjustFieldWidth(const UnicodeString& inputSkeleton,
DateIntervalInfo::parseSkeleton(inputSkeleton, inputSkeletonFieldWidth);
DateIntervalInfo::parseSkeleton(bestMatchSkeleton, bestMatchSkeletonFieldWidth);
if (suppressDayPeriodField) {
adjustedPtn.findAndReplace(UnicodeString(LOW_A), UnicodeString());
adjustedPtn.findAndReplace(UnicodeString(" "), UnicodeString(" "));
findReplaceInPattern(adjustedPtn, UnicodeString(LOW_A), UnicodeString());
findReplaceInPattern(adjustedPtn, UnicodeString(" "), UnicodeString(" "));
adjustedPtn.trim();
}
if ( differenceInfo == 2 ) {
if (inputSkeleton.indexOf(LOW_Z) != -1) {
adjustedPtn.findAndReplace(UnicodeString(LOW_V),
UnicodeString(LOW_Z));
}
if (inputSkeleton.indexOf(CAP_K) != -1) {
adjustedPtn.findAndReplace(UnicodeString(LOW_H),
UnicodeString(CAP_K));
}
if (inputSkeleton.indexOf(LOW_K) != -1) {
adjustedPtn.findAndReplace(UnicodeString(CAP_H),
UnicodeString(LOW_K));
}
if (inputSkeleton.indexOf(LOW_B) != -1) {
adjustedPtn.findAndReplace(UnicodeString(LOW_A),
UnicodeString(LOW_B));
}
findReplaceInPattern(adjustedPtn, UnicodeString(LOW_V), UnicodeString(LOW_Z));
}
if (inputSkeleton.indexOf(CAP_K) != -1) {
findReplaceInPattern(adjustedPtn, UnicodeString(LOW_H), UnicodeString(CAP_K));
}
if (inputSkeleton.indexOf(LOW_K) != -1) {
findReplaceInPattern(adjustedPtn, UnicodeString(CAP_H), UnicodeString(LOW_K));
}
if (inputSkeleton.indexOf(LOW_B) != -1) {
findReplaceInPattern(adjustedPtn, UnicodeString(LOW_A), UnicodeString(LOW_B));
}
}
if (adjustedPtn.indexOf(LOW_A) != -1 && bestMatchSkeletonFieldWidth[LOW_A - PATTERN_CHAR_BASE] == 0) {
bestMatchSkeletonFieldWidth[LOW_A - PATTERN_CHAR_BASE] = 1;
@ -1792,6 +1792,39 @@ DateIntervalFormat::adjustFieldWidth(const UnicodeString& inputSkeleton,
}
}
void
DateIntervalFormat::findReplaceInPattern(UnicodeString& targetString,
const UnicodeString& strToReplace,
const UnicodeString& strToReplaceWith) {
int32_t firstQuoteIndex = targetString.indexOf(u'\'');
if (firstQuoteIndex == -1) {
targetString.findAndReplace(strToReplace, strToReplaceWith);
} else {
UnicodeString result;
UnicodeString source = targetString;
while (firstQuoteIndex >= 0) {
int32_t secondQuoteIndex = source.indexOf(u'\'', firstQuoteIndex + 1);
if (secondQuoteIndex == -1) {
secondQuoteIndex = source.length() - 1;
}
UnicodeString unquotedText(source, 0, firstQuoteIndex);
UnicodeString quotedText(source, firstQuoteIndex, secondQuoteIndex - firstQuoteIndex + 1);
unquotedText.findAndReplace(strToReplace, strToReplaceWith);
result += unquotedText;
result += quotedText;
source.remove(0, secondQuoteIndex + 1);
firstQuoteIndex = source.indexOf(u'\'');
}
source.findAndReplace(strToReplace, strToReplaceWith);
result += source;
targetString = result;
}
}
void

View file

@ -117,6 +117,12 @@ private:
};
// Internal struct that must be exported for MSVC
struct U_I18N_API SpanInfo {
int32_t spanValue;
int32_t length;
};
// Export an explicit template instantiation of the MaybeStackArray that
// is used as a data member of CEBuffer.
//
@ -126,7 +132,7 @@ private:
// See digitlst.h, pluralaffix.h, datefmt.h, and others for similar examples.
//
#if U_PF_WINDOWS <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN
template class U_I18N_API MaybeStackArray<int32_t, 8>;
template class U_I18N_API MaybeStackArray<SpanInfo, 8>;
#endif
/**
@ -162,13 +168,19 @@ public:
return fString;
}
void appendSpanIndex(int32_t index);
void prependSpanIndex(int32_t index);
/**
* Adds additional metadata used for span fields.
*
* spanValue: the index of the list item, for example.
* length: the length of the span, used to split adjacent fields.
*/
void appendSpanInfo(int32_t spanValue, int32_t length, UErrorCode& status);
void prependSpanInfo(int32_t spanValue, int32_t length, UErrorCode& status);
private:
FormattedStringBuilder fString;
FormattedStringBuilder::Field fNumericField;
MaybeStackArray<int32_t, 8> spanIndices;
MaybeStackArray<SpanInfo, 8> spanIndices;
bool nextPositionImpl(ConstrainedFieldPosition& cfpos, FormattedStringBuilder::Field numericField, UErrorCode& status) const;
static bool isIntOrGroup(FormattedStringBuilder::Field field);

View file

@ -46,19 +46,19 @@ Appendable& FormattedValueStringBuilderImpl::appendTo(Appendable& appendable, UE
UBool FormattedValueStringBuilderImpl::nextPosition(ConstrainedFieldPosition& cfpos, UErrorCode& status) const {
// NOTE: MSVC sometimes complains when implicitly converting between bool and UBool
return nextPositionImpl(cfpos, fNumericField, status) ? TRUE : FALSE;
return nextPositionImpl(cfpos, fNumericField, status) ? true : false;
}
UBool FormattedValueStringBuilderImpl::nextFieldPosition(FieldPosition& fp, UErrorCode& status) const {
int32_t rawField = fp.getField();
if (rawField == FieldPosition::DONT_CARE) {
return FALSE;
return false;
}
if (rawField < 0 || rawField >= UNUM_FIELD_COUNT) {
status = U_ILLEGAL_ARGUMENT_ERROR;
return FALSE;
return false;
}
ConstrainedFieldPosition cfpos;
@ -67,7 +67,7 @@ UBool FormattedValueStringBuilderImpl::nextFieldPosition(FieldPosition& fp, UErr
if (nextPositionImpl(cfpos, kUndefinedField, status)) {
fp.setBeginIndex(cfpos.getStart());
fp.setEndIndex(cfpos.getLimit());
return TRUE;
return true;
}
// Special case: fraction should start after integer if fraction is not present
@ -85,7 +85,7 @@ UBool FormattedValueStringBuilderImpl::nextFieldPosition(FieldPosition& fp, UErr
fp.setEndIndex(i - fString.fZero);
}
return FALSE;
return false;
}
void FormattedValueStringBuilderImpl::getAllFieldPositions(FieldPositionIteratorHandler& fpih,
@ -103,23 +103,12 @@ static constexpr Field kEndField = Field(0xf, 0xf);
bool FormattedValueStringBuilderImpl::nextPositionImpl(ConstrainedFieldPosition& cfpos, Field numericField, UErrorCode& /*status*/) const {
int32_t fieldStart = -1;
Field currField = kUndefinedField;
UFieldCategory spanCategory = UFIELD_CATEGORY_UNDEFINED;
int32_t spanValue;
for (int32_t i = fString.fZero + cfpos.getLimit(); i <= fString.fZero + fString.fLength; i++) {
Field _field = (i < fString.fZero + fString.fLength) ? fString.getFieldPtr()[i] : kEndField;
// Case 1: currently scanning a field.
if (currField != kUndefinedField) {
if (currField != _field) {
int32_t end = i - fString.fZero;
// Handle span fields; don't trim them
if (spanCategory != UFIELD_CATEGORY_UNDEFINED) {
cfpos.setState(
spanCategory,
spanValue,
fieldStart,
end);
return true;
}
// Grouping separators can be whitespace; don't throw them out!
if (isTrimmable(currField)) {
end = trimBack(i - fString.fZero);
@ -182,13 +171,11 @@ bool FormattedValueStringBuilderImpl::nextPositionImpl(ConstrainedFieldPosition&
if (elementField == Field(UFIELD_CATEGORY_LIST, ULISTFMT_ELEMENT_FIELD)
&& cfpos.matchesField(elementField.getCategory(), elementField.getField())
&& (cfpos.getLimit() < i - fString.fZero || cfpos.getCategory() != elementField.getCategory())) {
// Re-wind to the beginning of the field and then emit it
int32_t j = i - 1;
for (; j >= fString.fZero && fString.getFieldPtr()[j] == fString.getFieldPtr()[i-1]; j--) {}
int64_t si = cfpos.getInt64IterationContext() - 1;
cfpos.setState(
elementField.getCategory(),
elementField.getField(),
j - fString.fZero + 1,
i - fString.fZero - spanIndices[si].length,
i - fString.fZero);
return true;
}
@ -203,22 +190,28 @@ bool FormattedValueStringBuilderImpl::nextPositionImpl(ConstrainedFieldPosition&
}
// Case 3: check for field starting at this position
// Case 3a: Need to add a SpanField
if (_field == Field(UFIELD_CATEGORY_LIST, ULISTFMT_ELEMENT_FIELD)
// don't return the same field twice in a row:
&& (i == fString.fZero
|| fString.getFieldPtr()[i-1].getCategory() != UFIELD_CATEGORY_LIST
|| fString.getFieldPtr()[i-1].getField() != ULISTFMT_ELEMENT_FIELD)) {
if (_field == Field(UFIELD_CATEGORY_LIST, ULISTFMT_ELEMENT_FIELD)) {
int64_t si = cfpos.getInt64IterationContext();
spanValue = spanIndices[si];
int32_t spanValue = spanIndices[si].spanValue;
int32_t length = spanIndices[si].length;
cfpos.setInt64IterationContext(si + 1);
if (cfpos.matchesField(UFIELD_CATEGORY_LIST_SPAN, spanValue)) {
spanCategory = UFIELD_CATEGORY_LIST_SPAN;
UFieldCategory spanCategory = UFIELD_CATEGORY_LIST_SPAN;
fieldStart = i - fString.fZero;
currField = _field;
int32_t end = fieldStart + length;
cfpos.setState(
spanCategory,
spanValue,
fieldStart,
end);
return true;
} else {
// Failed to match; jump ahead
i += length - 1;
continue;
}
}
// Case 3b: No SpanField or SpanField did not match
// Case 3b: No SpanField
if (cfpos.matchesField(_field.getCategory(), _field.getField())) {
fieldStart = i - fString.fZero;
currField = _field;
@ -226,24 +219,40 @@ bool FormattedValueStringBuilderImpl::nextPositionImpl(ConstrainedFieldPosition&
}
U_ASSERT(currField == kUndefinedField);
// Always set the position to the end so that we don't revisit previous sections
cfpos.setState(
cfpos.getCategory(),
cfpos.getField(),
fString.fLength,
fString.fLength);
return false;
}
void FormattedValueStringBuilderImpl::appendSpanIndex(int32_t position) {
if (spanIndices.getCapacity() <= position) {
spanIndices.resize(position * 2);
void FormattedValueStringBuilderImpl::appendSpanInfo(int32_t spanValue, int32_t length, UErrorCode& status) {
if (U_FAILURE(status)) { return; }
U_ASSERT(spanIndices.getCapacity() >= spanValue);
if (spanIndices.getCapacity() == spanValue) {
if (!spanIndices.resize(spanValue * 2, spanValue)) {
status = U_MEMORY_ALLOCATION_ERROR;
return;
}
}
spanIndices[position] = position;
spanIndices[spanValue] = {spanValue, length};
}
void FormattedValueStringBuilderImpl::prependSpanIndex(int32_t position) {
if (spanIndices.getCapacity() <= position) {
spanIndices.resize(position * 2);
void FormattedValueStringBuilderImpl::prependSpanInfo(int32_t spanValue, int32_t length, UErrorCode& status) {
if (U_FAILURE(status)) { return; }
U_ASSERT(spanIndices.getCapacity() >= spanValue);
if (spanIndices.getCapacity() == spanValue) {
if (!spanIndices.resize(spanValue * 2, spanValue)) {
status = U_MEMORY_ALLOCATION_ERROR;
return;
}
}
for (int32_t i = 0; i < position; i++) {
for (int32_t i = spanValue - 1; i >= 0; i--) {
spanIndices[i+1] = spanIndices[i];
}
spanIndices[0] = position;
spanIndices[0] = {spanValue, length};
}
bool FormattedValueStringBuilderImpl::isIntOrGroup(Field field) {

View file

@ -16,6 +16,10 @@
* created by: Umesh P. Nair
*/
#include "unicode/utypes.h"
#if !UCONFIG_NO_FORMATTING
#include "cmemory.h"
#include "unicode/fpositer.h" // FieldPositionIterator
#include "unicode/listformatter.h"
@ -171,21 +175,21 @@ PatternHandler* createPatternHandler(
UErrorCode& status) {
if (uprv_strcmp(lang, "es") == 0) {
// Spanish
UnicodeString spanishYStr(TRUE, spanishY, -1);
UnicodeString spanishYStr(true, spanishY, -1);
bool twoIsY = two == spanishYStr;
bool endIsY = end == spanishYStr;
if (twoIsY || endIsY) {
UnicodeString replacement(TRUE, spanishE, -1);
UnicodeString replacement(true, spanishE, -1);
return new ContextualHandler(
shouldChangeToE,
twoIsY ? replacement : two, two,
endIsY ? replacement : end, end, status);
}
UnicodeString spanishOStr(TRUE, spanishO, -1);
UnicodeString spanishOStr(true, spanishO, -1);
bool twoIsO = two == spanishOStr;
bool endIsO = end == spanishOStr;
if (twoIsO || endIsO) {
UnicodeString replacement(TRUE, spanishU, -1);
UnicodeString replacement(true, spanishU, -1);
return new ContextualHandler(
shouldChangeToU,
twoIsO ? replacement : two, two,
@ -193,11 +197,11 @@ PatternHandler* createPatternHandler(
}
} else if (uprv_strcmp(lang, "he") == 0 || uprv_strcmp(lang, "iw") == 0) {
// Hebrew
UnicodeString hebrewVavStr(TRUE, hebrewVav, -1);
UnicodeString hebrewVavStr(true, hebrewVav, -1);
bool twoIsVav = two == hebrewVavStr;
bool endIsVav = end == hebrewVavStr;
if (twoIsVav || endIsVav) {
UnicodeString replacement(TRUE, hebrewVavDash, -1);
UnicodeString replacement(true, hebrewVavDash, -1);
return new ContextualHandler(
shouldChangeToVavDash,
twoIsVav ? replacement : two, two,
@ -238,7 +242,6 @@ ListFormatInternal(const ListFormatInternal &other) :
};
#if !UCONFIG_NO_FORMATTING
class FormattedListData : public FormattedValueStringBuilderImpl {
public:
FormattedListData(UErrorCode&) : FormattedValueStringBuilderImpl(kUndefinedField) {}
@ -248,7 +251,6 @@ public:
FormattedListData::~FormattedListData() = default;
UPRV_FORMATTED_VALUE_SUBCLASS_AUTO_IMPL(FormattedList)
#endif
static Hashtable* listPatternHash = nullptr;
@ -257,7 +259,7 @@ U_CDECL_BEGIN
static UBool U_CALLCONV uprv_listformatter_cleanup() {
delete listPatternHash;
listPatternHash = nullptr;
return TRUE;
return true;
}
static void U_CALLCONV
@ -350,7 +352,6 @@ const ListFormatInternal* ListFormatter::getListFormatInternal(
return result;
}
#if !UCONFIG_NO_FORMATTING
static const char* typeWidthToStyleString(UListFormatterType type, UListFormatterWidth width) {
switch (type) {
case ULISTFMT_TYPE_AND:
@ -394,7 +395,6 @@ static const char* typeWidthToStyleString(UListFormatterType type, UListFormatte
return nullptr;
}
#endif
static const UChar solidus = 0x2F;
static const UChar aliasPrefix[] = { 0x6C,0x69,0x73,0x74,0x50,0x61,0x74,0x74,0x65,0x72,0x6E,0x2F }; // "listPattern/"
@ -515,14 +515,9 @@ ListFormatter* ListFormatter::createInstance(UErrorCode& errorCode) {
}
ListFormatter* ListFormatter::createInstance(const Locale& locale, UErrorCode& errorCode) {
#if !UCONFIG_NO_FORMATTING
return createInstance(locale, ULISTFMT_TYPE_AND, ULISTFMT_WIDTH_WIDE, errorCode);
#else
return createInstance(locale, "standard", errorCode);
#endif
}
#if !UCONFIG_NO_FORMATTING
ListFormatter* ListFormatter::createInstance(
const Locale& locale, UListFormatterType type, UListFormatterWidth width, UErrorCode& errorCode) {
const char* style = typeWidthToStyleString(type, width);
@ -532,7 +527,6 @@ ListFormatter* ListFormatter::createInstance(
}
return createInstance(locale, style, errorCode);
}
#endif
ListFormatter* ListFormatter::createInstance(const Locale& locale, const char *style, UErrorCode& errorCode) {
const ListFormatInternal* listFormatInternal = getListFormatInternal(locale, style, errorCode);
@ -573,7 +567,7 @@ public:
start,
{UFIELD_CATEGORY_LIST, ULISTFMT_ELEMENT_FIELD},
status);
data->appendSpanIndex(0);
data->appendSpanInfo(0, start.length(), status);
}
}
@ -609,7 +603,7 @@ public:
next,
{UFIELD_CATEGORY_LIST, ULISTFMT_ELEMENT_FIELD},
status);
data->appendSpanIndex(position);
data->appendSpanInfo(position, next.length(), status);
data->getStringRef().append(
temp.tempSubString(offsets[1]),
{UFIELD_CATEGORY_LIST, ULISTFMT_LITERAL_FIELD},
@ -628,7 +622,7 @@ public:
next,
{UFIELD_CATEGORY_LIST, ULISTFMT_ELEMENT_FIELD},
status);
data->prependSpanIndex(position);
data->prependSpanInfo(position, next.length(), status);
data->getStringRef().insert(
0,
temp.tempSubStringBetween(0, offsets[1]),
@ -660,7 +654,6 @@ UnicodeString& ListFormatter::format(
int32_t index,
int32_t &offset,
UErrorCode& errorCode) const {
#if !UCONFIG_NO_FORMATTING
int32_t initialOffset = appendTo.length();
auto result = formatStringsToValue(items, nItems, errorCode);
UnicodeStringAppendable appendable(appendTo);
@ -671,11 +664,9 @@ UnicodeString& ListFormatter::format(
result.nextPosition(cfpos, errorCode);
offset = initialOffset + cfpos.getStart();
}
#endif
return appendTo;
}
#if !UCONFIG_NO_FORMATTING
FormattedList ListFormatter::formatStringsToValue(
const UnicodeString items[],
int32_t nItems,
@ -741,7 +732,8 @@ FormattedList ListFormatter::formatStringsToValue(
return FormattedList(result.data.orphan());
}
}
#endif
U_NAMESPACE_END
#endif /* #if !UCONFIG_NO_FORMATTING */

View file

@ -732,6 +732,7 @@ skeleton::parseStem(const StringSegment& segment, const UCharsTrie& stemTrie, Se
case STEM_CURRENCY:
CHECK_NULL(seen, unit, status);
CHECK_NULL(seen, perUnit, status);
return STATE_CURRENCY_UNIT;
case STEM_INTEGER_WIDTH:
@ -1475,32 +1476,33 @@ bool GeneratorHelpers::notation(const MacroProps& macros, UnicodeString& sb, UEr
}
bool GeneratorHelpers::unit(const MacroProps& macros, UnicodeString& sb, UErrorCode& status) {
if (utils::unitIsCurrency(macros.unit)) {
MeasureUnit unit = macros.unit;
if (!utils::unitIsBaseUnit(macros.perUnit)) {
if (utils::unitIsCurrency(macros.unit) || utils::unitIsCurrency(macros.perUnit)) {
status = U_UNSUPPORTED_ERROR;
return false;
}
unit = unit.product(macros.perUnit.reciprocal(status), status);
}
if (utils::unitIsCurrency(unit)) {
sb.append(u"currency/", -1);
CurrencyUnit currency(macros.unit, status);
CurrencyUnit currency(unit, status);
if (U_FAILURE(status)) {
return false;
}
blueprint_helpers::generateCurrencyOption(currency, sb, status);
return true;
} else if (utils::unitIsBaseUnit(macros.unit)) {
} else if (utils::unitIsBaseUnit(unit)) {
// Default value is not shown in normalized form
return false;
} else if (utils::unitIsPercent(macros.unit)) {
} else if (utils::unitIsPercent(unit)) {
sb.append(u"percent", -1);
return true;
} else if (utils::unitIsPermille(macros.unit)) {
} else if (utils::unitIsPermille(unit)) {
sb.append(u"permille", -1);
return true;
} else {
MeasureUnit unit = macros.unit;
if (utils::unitIsCurrency(macros.perUnit)) {
status = U_UNSUPPORTED_ERROR;
return false;
}
if (!utils::unitIsBaseUnit(macros.perUnit)) {
unit = unit.product(macros.perUnit.reciprocal(status), status);
}
sb.append(u"unit/", -1);
sb.append(unit.getIdentifier());
return true;

View file

@ -1037,6 +1037,17 @@ private:
UBool suppressDayPeriodField,
UnicodeString& adjustedIntervalPattern);
/**
* Does the same thing as UnicodeString::findAndReplace(), except that it won't perform
* the substitution inside quoted literal text.
* @param targetString The string to perform the find-replace operation on.
* @param strToReplace The string to search for and replace in the target string.
* @param strToReplaceWith The string to substitute in wherever `stringToReplace` was found.
*/
static void U_EXPORT2 findReplaceInPattern(UnicodeString& targetString,
const UnicodeString& strToReplace,
const UnicodeString& strToReplaceWith);
/**
* Concat a single date pattern with a time interval pattern,
* set it into the intervalPatterns, while field is time field.

View file

@ -23,6 +23,8 @@
#if U_SHOW_CPLUSPLUS_API
#if !UCONFIG_NO_FORMATTING
#include "unicode/unistr.h"
#include "unicode/locid.h"
#include "unicode/formattedvalue.h"
@ -65,7 +67,6 @@ struct ListFormatData : public UMemory {
*/
#if !UCONFIG_NO_FORMATTING
/**
* An immutable class containing the result of a list formatting operation.
*
@ -135,7 +136,6 @@ class U_I18N_API FormattedList : public UMemory, public FormattedValue {
: fData(nullptr), fErrorCode(errorCode) {}
friend class ListFormatter;
};
#endif // !UCONFIG_NO_FORMATTING
/**
@ -185,8 +185,6 @@ class U_I18N_API ListFormatter : public UObject{
*/
static ListFormatter* createInstance(const Locale& locale, UErrorCode& errorCode);
#ifndef U_HIDE_DRAFT_API
#if !UCONFIG_NO_FORMATTING
/**
* Creates a ListFormatter for the given locale, list type, and style.
*
@ -195,12 +193,10 @@ class U_I18N_API ListFormatter : public UObject{
* @param width The width of formatting to use.
* @param errorCode ICU error code, set if no data available for the given locale.
* @return A ListFormatter object created from internal data derived from CLDR data.
* @draft ICU 67
* @stable ICU 67
*/
static ListFormatter* createInstance(
const Locale& locale, UListFormatterType type, UListFormatterWidth width, UErrorCode& errorCode);
#endif /* !UCONFIG_NO_FORMATTING */
#endif /* U_HIDE_DRAFT_API */
#ifndef U_HIDE_INTERNAL_API
/**
@ -239,7 +235,6 @@ class U_I18N_API ListFormatter : public UObject{
UnicodeString& format(const UnicodeString items[], int32_t n_items,
UnicodeString& appendTo, UErrorCode& errorCode) const;
#if !UCONFIG_NO_FORMATTING
/**
* Formats a list of strings to a FormattedList, which exposes field
* position information. The FormattedList contains more information than
@ -255,7 +250,6 @@ class U_I18N_API ListFormatter : public UObject{
const UnicodeString items[],
int32_t n_items,
UErrorCode& errorCode) const;
#endif // !UCONFIG_NO_FORMATTING
#ifndef U_HIDE_INTERNAL_API
/**
@ -296,6 +290,8 @@ class U_I18N_API ListFormatter : public UObject{
U_NAMESPACE_END
#endif /* #if !UCONFIG_NO_FORMATTING */
#endif /* U_SHOW_CPLUSPLUS_API */
#endif // __LISTFORMATTER_H__

View file

@ -62,17 +62,16 @@ typedef enum UListFormatterField {
ULISTFMT_ELEMENT_FIELD
} UListFormatterField;
#ifndef U_HIDE_DRAFT_API
/**
* Type of meaning expressed by the list.
*
* @draft ICU 67
* @stable ICU 67
*/
typedef enum UListFormatterType {
/**
* Conjunction formatting, e.g. "Alice, Bob, Charlie, and Delta".
*
* @draft ICU 67
* @stable ICU 67
*/
ULISTFMT_TYPE_AND,
@ -80,14 +79,14 @@ typedef enum UListFormatterType {
* Disjunction (or alternative, or simply one of) formatting, e.g.
* "Alice, Bob, Charlie, or Delta".
*
* @draft ICU 67
* @stable ICU 67
*/
ULISTFMT_TYPE_OR,
/**
* Formatting of a list of values with units, e.g. "5 pounds, 12 ounces".
*
* @draft ICU 67
* @stable ICU 67
*/
ULISTFMT_TYPE_UNITS
} UListFormatterType;
@ -95,29 +94,28 @@ typedef enum UListFormatterType {
/**
* Verbosity level of the list patterns.
*
* @draft ICU 67
* @stable ICU 67
*/
typedef enum UListFormatterWidth {
/**
* Use list formatting with full words (no abbreviations) when possible.
*
* @draft ICU 67
* @stable ICU 67
*/
ULISTFMT_WIDTH_WIDE,
/**
* Use list formatting of typical length.
* @draft ICU 67
* @stable ICU 67
*/
ULISTFMT_WIDTH_SHORT,
/**
* Use list formatting of the shortest possible length.
* @draft ICU 67
* @stable ICU 67
*/
ULISTFMT_WIDTH_NARROW,
} UListFormatterWidth;
#endif /* U_HIDE_DRAFT_API */
/**
* Open a new UListFormatter object using the rules for a given locale.
@ -141,7 +139,6 @@ U_CAPI UListFormatter* U_EXPORT2
ulistfmt_open(const char* locale,
UErrorCode* status);
#ifndef U_HIDE_DRAFT_API
/**
* Open a new UListFormatter object appropriate for the given locale, list type,
* and style.
@ -162,12 +159,11 @@ ulistfmt_open(const char* locale,
* @return
* A pointer to a UListFormatter object for the specified locale,
* or NULL if an error occurred.
* @draft ICU 67
* @stable ICU 67
*/
U_CAPI UListFormatter* U_EXPORT2
ulistfmt_openForType(const char* locale, UListFormatterType type,
UListFormatterWidth width, UErrorCode* status);
#endif /* U_HIDE_DRAFT_API */
/**
* Close a UListFormatter object. Once closed it may no longer be used.

View file

@ -1243,6 +1243,7 @@ static void TestDisplayNameBrackets()
static void TestIllegalArgumentWhenNoDataWithNoSubstitute()
{
#if !UCONFIG_NO_FORMATTING
UErrorCode status = U_ZERO_ERROR;
UChar getName[kDisplayNameBracketsMax];
UDisplayContext contexts[] = {
@ -1299,6 +1300,7 @@ static void TestIllegalArgumentWhenNoDataWithNoSubstitute()
}
uldn_close(ldn);
#endif
}
/*------------------------------
@ -2243,12 +2245,7 @@ static void TestKeywordSetError(void)
strcpy(buffer,kwSetTestCases[i].l);
status = U_ZERO_ERROR;
res = uloc_setKeywordValue(kwSetTestCases[i].k, kwSetTestCases[i].v, buffer, blen, &status);
if(res == blen) {
if(status != U_STRING_NOT_TERMINATED_WARNING) {
log_err("expected not terminated warning on buffer %d got %s, len %d (%s + [%s=%s])\n", blen, u_errorName(status), res, kwSetTestCases[i].l, kwSetTestCases[i].k, kwSetTestCases[i].v);
return;
}
} else if(status != U_BUFFER_OVERFLOW_ERROR) {
if(status != U_BUFFER_OVERFLOW_ERROR) {
log_err("expected buffer overflow on buffer %d got %s, len %d (%s + [%s=%s])\n", blen, u_errorName(status), res, kwSetTestCases[i].l, kwSetTestCases[i].k, kwSetTestCases[i].v);
return;
}

View file

@ -184,7 +184,7 @@ library: common
uinit utypes errorcode
icuplug
platform
localebuilder localematcher
localematcher
group: pluralmap
# TODO: Move to i18n library, ticket #11926.
@ -634,6 +634,7 @@ group: resourcebundle
# Do we need class LocaleBased? https://unicode-org.atlassian.net/browse/ICU-8608
locbased.o
loclikely.o
localebuilder.o
deps
udata ucol_swp
sort stringenumeration uhash uvector
@ -641,15 +642,10 @@ group: resourcebundle
bytesinkutil
errorcode
group: localebuilder
localebuilder.o
deps
resourcebundle
group: localematcher
localematcher.o
deps
localebuilder localeprioritylist loclikelysubtags locdistance lsr
resourcebundle localeprioritylist loclikelysubtags locdistance lsr
group: localeprioritylist
localeprioritylist.o

View file

@ -1160,6 +1160,15 @@ void DateIntervalFormatTest::testHourMetacharacters() {
"hi_IN", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "hB", "\\u0930\\u093E\\u0924 12\\u20131",
"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-21343
"de", "CE 2010 09 27 01:00:00", "CE 2010 09 27 10:00:00", "KK", "1 \\u2013 10 Uhr AM",
};
expect(DATA, UPRV_LENGTHOF(DATA));
}

View file

@ -237,6 +237,8 @@ void IntlTestWithFieldPosition::checkMixedFormattedValue(
}
UBool afterLoopResult = fv.nextPosition(cfpos, status);
assertFalse(baseMessage + u"A after loop: " + CFPosToUnicodeString(cfpos), afterLoopResult);
afterLoopResult = fv.nextPosition(cfpos, status);
assertFalse(baseMessage + u"A after loop again: " + CFPosToUnicodeString(cfpos), afterLoopResult);
// Check nextPosition constrained over each category one at a time
for (int32_t category=0; category<UFIELD_CATEGORY_COUNT+1; category++) {
@ -266,6 +268,8 @@ void IntlTestWithFieldPosition::checkMixedFormattedValue(
}
UBool afterLoopResult = fv.nextPosition(cfpos, status);
assertFalse(baseMessage + u"B after loop @ " + CFPosToUnicodeString(cfpos), afterLoopResult);
afterLoopResult = fv.nextPosition(cfpos, status);
assertFalse(baseMessage + u"B after loop again @ " + CFPosToUnicodeString(cfpos), afterLoopResult);
}
// Check nextPosition constrained over each field one at a time
@ -300,6 +304,8 @@ void IntlTestWithFieldPosition::checkMixedFormattedValue(
}
UBool afterLoopResult = fv.nextPosition(cfpos, status);
assertFalse(baseMessage + u"C after loop: " + CFPosToUnicodeString(cfpos), afterLoopResult);
afterLoopResult = fv.nextPosition(cfpos, status);
assertFalse(baseMessage + u"C after loop again: " + CFPosToUnicodeString(cfpos), afterLoopResult);
}
}

View file

@ -48,6 +48,7 @@ void ListFormatterTest::runIndexedTest(int32_t index, UBool exec,
TESTCASE_AUTO(TestBadStylesFail);
TESTCASE_AUTO(TestCreateStyled);
TESTCASE_AUTO(TestContextual);
TESTCASE_AUTO(TestNextPosition);
TESTCASE_AUTO_END;
}
@ -494,10 +495,10 @@ void ListFormatterTest::TestOutOfOrderPatterns() {
void ListFormatterTest::TestFormattedValue() {
IcuTestErrorCode status(*this, "TestFormattedValue");
LocalPointer<ListFormatter> fmt(ListFormatter::createInstance("en", status));
if (status.errIfFailureAndReset()) { return; }
{
LocalPointer<ListFormatter> fmt(ListFormatter::createInstance("en", status));
if (status.errIfFailureAndReset()) { return; }
const char16_t* message = u"Field position test 1";
const char16_t* expectedString = u"hello, wonderful, and world";
const UnicodeString inputs[] = {
@ -523,6 +524,87 @@ void ListFormatterTest::TestFormattedValue() {
expectedFieldPositions,
UPRV_LENGTHOF(expectedFieldPositions));
}
{
LocalPointer<ListFormatter> fmt(ListFormatter::createInstance("zh", ULISTFMT_TYPE_UNITS, ULISTFMT_WIDTH_SHORT, status));
if (status.errIfFailureAndReset()) { return; }
const char16_t* message = u"Field position test 2 (ICU-21340)";
const char16_t* expectedString = u"aabbbbbbbccc";
const UnicodeString inputs[] = {
u"aa",
u"bbbbbbb",
u"ccc"
};
FormattedList result = fmt->formatStringsToValue(inputs, UPRV_LENGTHOF(inputs), status);
static const UFieldPositionWithCategory expectedFieldPositions[] = {
// field, begin index, end index
{UFIELD_CATEGORY_LIST_SPAN, 0, 0, 2},
{UFIELD_CATEGORY_LIST, ULISTFMT_ELEMENT_FIELD, 0, 2},
{UFIELD_CATEGORY_LIST_SPAN, 1, 2, 9},
{UFIELD_CATEGORY_LIST, ULISTFMT_ELEMENT_FIELD, 2, 9},
{UFIELD_CATEGORY_LIST_SPAN, 2, 9, 12},
{UFIELD_CATEGORY_LIST, ULISTFMT_ELEMENT_FIELD, 9, 12}};
checkMixedFormattedValue(
message,
result,
expectedString,
expectedFieldPositions,
UPRV_LENGTHOF(expectedFieldPositions));
}
{
LocalPointer<ListFormatter> fmt(ListFormatter::createInstance("en", ULISTFMT_TYPE_UNITS, ULISTFMT_WIDTH_SHORT, status));
if (status.errIfFailureAndReset()) { return; }
const char16_t* message = u"ICU-21383 Long list";
const char16_t* expectedString = u"a, b, c, d, e, f, g, h, i";
const UnicodeString inputs[] = {
u"a",
u"b",
u"c",
u"d",
u"e",
u"f",
u"g",
u"h",
u"i",
};
FormattedList result = fmt->formatStringsToValue(inputs, UPRV_LENGTHOF(inputs), status);
static const UFieldPositionWithCategory expectedFieldPositions[] = {
// field, begin index, end index
{UFIELD_CATEGORY_LIST_SPAN, 0, 0, 1},
{UFIELD_CATEGORY_LIST, ULISTFMT_ELEMENT_FIELD, 0, 1},
{UFIELD_CATEGORY_LIST, ULISTFMT_LITERAL_FIELD, 1, 3},
{UFIELD_CATEGORY_LIST_SPAN, 1, 3, 4},
{UFIELD_CATEGORY_LIST, ULISTFMT_ELEMENT_FIELD, 3, 4},
{UFIELD_CATEGORY_LIST, ULISTFMT_LITERAL_FIELD, 4, 6},
{UFIELD_CATEGORY_LIST_SPAN, 2, 6, 7},
{UFIELD_CATEGORY_LIST, ULISTFMT_ELEMENT_FIELD, 6, 7},
{UFIELD_CATEGORY_LIST, ULISTFMT_LITERAL_FIELD, 7, 9},
{UFIELD_CATEGORY_LIST_SPAN, 3, 9, 10},
{UFIELD_CATEGORY_LIST, ULISTFMT_ELEMENT_FIELD, 9, 10},
{UFIELD_CATEGORY_LIST, ULISTFMT_LITERAL_FIELD, 10, 12},
{UFIELD_CATEGORY_LIST_SPAN, 4, 12, 13},
{UFIELD_CATEGORY_LIST, ULISTFMT_ELEMENT_FIELD, 12, 13},
{UFIELD_CATEGORY_LIST, ULISTFMT_LITERAL_FIELD, 13, 15},
{UFIELD_CATEGORY_LIST_SPAN, 5, 15, 16},
{UFIELD_CATEGORY_LIST, ULISTFMT_ELEMENT_FIELD, 15, 16},
{UFIELD_CATEGORY_LIST, ULISTFMT_LITERAL_FIELD, 16, 18},
{UFIELD_CATEGORY_LIST_SPAN, 6, 18, 19},
{UFIELD_CATEGORY_LIST, ULISTFMT_ELEMENT_FIELD, 18, 19},
{UFIELD_CATEGORY_LIST, ULISTFMT_LITERAL_FIELD, 19, 21},
{UFIELD_CATEGORY_LIST_SPAN, 7, 21, 22},
{UFIELD_CATEGORY_LIST, ULISTFMT_ELEMENT_FIELD, 21, 22},
{UFIELD_CATEGORY_LIST, ULISTFMT_LITERAL_FIELD, 22, 24},
{UFIELD_CATEGORY_LIST_SPAN, 8, 24, 25},
{UFIELD_CATEGORY_LIST, ULISTFMT_ELEMENT_FIELD, 24, 25},
};
checkMixedFormattedValue(
message,
result,
expectedString,
expectedFieldPositions,
UPRV_LENGTHOF(expectedFieldPositions));
}
}
void ListFormatterTest::DoTheRealListStyleTesting(Locale locale,
@ -700,4 +782,50 @@ void ListFormatterTest::TestContextual() {
}
}
void ListFormatterTest::TestNextPosition() {
IcuTestErrorCode status(*this, "TestNextPosition");
std::vector<std::string> locales = { "en", "es", "zh", "ja" };
UListFormatterWidth widths [] = {
ULISTFMT_WIDTH_WIDE, ULISTFMT_WIDTH_SHORT, ULISTFMT_WIDTH_NARROW
};
const char* widthStr [] = {"wide", "short", "narrow"};
UListFormatterType types [] = {
ULISTFMT_TYPE_AND, ULISTFMT_TYPE_OR, ULISTFMT_TYPE_UNITS
};
const char* typeStr [] = {"and", "or", "units"};
const UnicodeString inputs[] = { u"A1", u"B2", u"C3", u"D4" };
for (auto width : widths) {
for (auto type : types) {
for (auto locale : locales) {
LocalPointer<ListFormatter> fmt(
ListFormatter::createInstance(locale.c_str(), type, width, status),
status);
if (status.errIfFailureAndReset()) {
continue;
}
for (int32_t n = 1; n <= UPRV_LENGTHOF(inputs); n++) {
FormattedList result = fmt->formatStringsToValue(
inputs, n, status);
int32_t elements = 0;
icu::ConstrainedFieldPosition cfpos;
cfpos.constrainCategory(UFIELD_CATEGORY_LIST);
while (result.nextPosition(cfpos, status) && U_SUCCESS(status)) {
if (cfpos.getField() == ULISTFMT_ELEMENT_FIELD) {
elements++;
}
}
std::string msg = locale;
// Test that if there are n elements (n=1..4) in the input, then the
// nextPosition() should iterate through exactly n times
// with field == ULISTFMT_ELEMENT_FIELD.
assertEquals((msg
.append(" w=").append(widthStr[width])
.append(" t=").append(typeStr[type])).c_str(),
n, elements);
}
}
}
}
}
#endif /* #if !UCONFIG_NO_FORMATTING */

View file

@ -55,6 +55,7 @@ class ListFormatterTest : public IntlTestWithFieldPosition {
void TestBadStylesFail();
void TestCreateStyled();
void TestContextual();
void TestNextPosition();
private:
void CheckFormatting(

View file

@ -4154,7 +4154,7 @@ LocaleTest::TestSetKeywordValue(void) {
{ "calendar", "buddhist" }
};
UErrorCode status = U_ZERO_ERROR;
IcuTestErrorCode status(*this, "TestSetKeywordValue()");
int32_t i = 0;
int32_t resultLen = 0;
@ -4176,6 +4176,24 @@ LocaleTest::TestSetKeywordValue(void) {
testCases[i].value, testCases[i].keyword, buffer);
}
}
// Test long locale
{
status.errIfFailureAndReset();
const char* input =
"de__POSIX@colnormalization=no;colstrength=primary;currency=eur;"
"em=default;kv=space;lb=strict;lw=normal;measure=metric;"
"numbers=latn;rg=atzzzz;sd=atat1";
const char* expected =
"de__POSIX@colnormalization=no;colstrength=primary;currency=eur;"
"em=default;kv=space;lb=strict;lw=normal;measure=metric;"
"numbers=latn;rg=atzzzz;sd=atat1;ss=none";
// Bug ICU-21385
Locale l2(input);
l2.setKeywordValue("ss", "none", status);
assertEquals("", expected, l2.getName());
status.errIfFailureAndReset();
}
}
void
@ -4894,6 +4912,9 @@ void LocaleTest::TestCanonicalize(void)
{ "ja-Latn-hepburn-heploc", "ja-Latn-alalc97"},
{ "aaa-Fooo-SU", "aaa-Fooo-RU"},
// ICU-21344
{ "ku-Arab-NT", "ku-Arab-IQ"},
};
int32_t i;
for (i=0; i < UPRV_LENGTHOF(testCases); i++) {

View file

@ -274,6 +274,7 @@ class NumberSkeletonTest : public IntlTest {
void flexibleSeparators();
void wildcardCharacters();
void perUnitInArabic();
void perUnitToSkeleton();
void runIndexedTest(int32_t index, UBool exec, const char *&name, char *par = 0);

View file

@ -798,6 +798,15 @@ void NumberFormatterApiTest::unitMeasure() {
Locale("de-DE"),
-1.24,
u"-1 Std., 14 Min. und 24 Sek.");
assertFormatSingle(
u"Zero out the unit field",
u"",
u"",
NumberFormatter::with().unit(KELVIN).unit(MeasureUnit()),
Locale("en"),
100,
u"100");
}
void NumberFormatterApiTest::unitCompoundMeasure() {
@ -973,6 +982,7 @@ void NumberFormatterApiTest::unitCompoundMeasure() {
u"2.4 m/s\u00B2");
}
// TODO: merge these tests into numbertest_skeletons.cpp instead of here:
void NumberFormatterApiTest::unitSkeletons() {
const struct TestCase {
const char *msg;
@ -1015,6 +1025,22 @@ void NumberFormatterApiTest::unitSkeletons() {
u"unit/meter-per-hectosecond", //
u"unit/meter-per-hectosecond"},
{"percent compound skeletons handled correctly", //
u"unit/percent-per-meter", //
u"unit/percent-per-meter"},
{"permille compound skeletons handled correctly", //
u"measure-unit/concentr-permille per-measure-unit/length-meter", //
u"unit/permille-per-meter"},
{"percent simple unit is not actually considered a unit", //
u"unit/percent", //
u"percent"},
{"permille simple unit is not actually considered a unit", //
u"measure-unit/concentr-permille", //
u"permille"},
// // TODO: binary prefixes not supported yet!
// {"Round-trip example from icu-units#35", //
// u"unit/kibijoule-per-furlong", //
@ -1048,20 +1074,33 @@ void NumberFormatterApiTest::unitSkeletons() {
u"measure-unit/meter per-measure-unit/hectosecond", //
U_NUMBER_SKELETON_SYNTAX_ERROR, //
U_ZERO_ERROR},
{"\"currency/EUR measure-unit/length-meter\" fails, conflicting skeleton.",
u"currency/EUR measure-unit/length-meter", //
U_NUMBER_SKELETON_SYNTAX_ERROR, //
U_ZERO_ERROR},
{"\"measure-unit/length-meter currency/EUR\" fails, conflicting skeleton.",
u"measure-unit/length-meter currency/EUR", //
U_NUMBER_SKELETON_SYNTAX_ERROR, //
U_ZERO_ERROR},
{"\"currency/EUR per-measure-unit/meter\" fails, conflicting skeleton.",
u"currency/EUR per-measure-unit/length-meter", //
U_NUMBER_SKELETON_SYNTAX_ERROR, //
U_ZERO_ERROR},
};
for (auto &cas : failCases) {
IcuTestErrorCode status(*this, cas.msg);
auto nf = NumberFormatter::forSkeleton(cas.inputSkeleton, status);
if (status.expectErrorAndReset(cas.expectedForSkelStatus, cas.msg)) {
continue;
continue;
}
nf.toSkeleton(status);
status.expectErrorAndReset(cas.expectedToSkelStatus, cas.msg);
}
IcuTestErrorCode status(*this, "unitSkeletons");
MeasureUnit METER_PER_SECOND = MeasureUnit::forIdentifier("meter-per-second", status);
assertEquals( //
".unit(METER_PER_SECOND) normalization", //
u"unit/meter-per-second", //
@ -1083,6 +1122,16 @@ void NumberFormatterApiTest::unitSkeletons() {
.unit(METER)
.perUnit(MeasureUnit::forIdentifier("hectosecond", status))
.toSkeleton(status));
status.assertSuccess();
assertEquals( //
".unit(CURRENCY) produces a currency/CURRENCY skeleton", //
u"currency/GBP", //
NumberFormatter::with().unit(GBP).toSkeleton(status));
status.assertSuccess();
// .unit(CURRENCY).perUnit(ANYTHING) is not supported.
NumberFormatter::with().unit(GBP).perUnit(METER).toSkeleton(status);
status.expectErrorAndReset(U_UNSUPPORTED_ERROR);
}
void NumberFormatterApiTest::unitUsage() {

View file

@ -31,6 +31,7 @@ void NumberSkeletonTest::runIndexedTest(int32_t index, UBool exec, const char*&
TESTCASE_AUTO(flexibleSeparators);
TESTCASE_AUTO(wildcardCharacters);
TESTCASE_AUTO(perUnitInArabic);
TESTCASE_AUTO(perUnitToSkeleton);
TESTCASE_AUTO_END;
}
@ -436,4 +437,59 @@ void NumberSkeletonTest::perUnitInArabic() {
}
}
void NumberSkeletonTest::perUnitToSkeleton() {
IcuTestErrorCode status(*this, "perUnitToSkeleton");
struct TestCase {
const char16_t* type;
const char16_t* subtype;
} cases[] = {
{u"area", u"acre"},
{u"concentr", u"percent"},
{u"concentr", u"permille"},
{u"concentr", u"permillion"},
{u"concentr", u"permyriad"},
{u"digital", u"bit"},
{u"length", u"yard"},
};
for (const auto& cas1 : cases) {
for (const auto& cas2 : cases) {
UnicodeString skeleton(u"measure-unit/");
skeleton += cas1.type;
skeleton += u"-";
skeleton += cas1.subtype;
skeleton += u" ";
skeleton += u"per-measure-unit/";
skeleton += cas2.type;
skeleton += u"-";
skeleton += cas2.subtype;
status.setScope(skeleton);
if (cas1.type != cas2.type && cas1.subtype != cas2.subtype) {
UnicodeString toSkeleton = NumberFormatter::forSkeleton(
skeleton, status).toSkeleton(status);
if (status.errIfFailureAndReset()) {
continue;
}
// Ensure both subtype are in the toSkeleton.
UnicodeString msg;
msg.append(toSkeleton)
.append(" should contain '")
.append(UnicodeString(cas1.subtype))
.append("' when constructed from ")
.append(skeleton);
assertTrue(msg, toSkeleton.indexOf(cas1.subtype) >= 0);
msg.remove();
msg.append(toSkeleton)
.append(" should contain '")
.append(UnicodeString(cas2.subtype))
.append("' when constructed from ")
.append(skeleton);
assertTrue(msg, toSkeleton.indexOf(cas2.subtype) >= 0);
}
}
}
}
#endif /* #if !UCONFIG_NO_FORMATTING */

View file

@ -362,6 +362,7 @@ U_CDECL_END
U_CDECL_BEGIN
static void U_CALLCONV ScanfMultipleIntegers(void)
{
#if !UCONFIG_NO_FORMATTING && !UCONFIG_NO_FILE_IO
UnicodeString input = UNICODE_STRING("[1.2.3]", 7);
UnicodeString fmt = UNICODE_STRING("[%d.%d.%d]", 10);
DataDrivenLogger logger;
@ -391,6 +392,7 @@ static void U_CALLCONV ScanfMultipleIntegers(void)
log_err("error in scanfmultipleintegers test 'result' Got: %d Exp: %d\n",
result, expectedResult);
}
#endif
}
U_CDECL_END
@ -732,8 +734,8 @@ static void addAllTests(TestNode** root) {
addTest(root, &DataDrivenPrintf, "datadriv/DataDrivenPrintf");
addTest(root, &DataDrivenPrintfPrecision, "datadriv/DataDrivenPrintfPrecision");
addTest(root, &DataDrivenScanf, "datadriv/DataDrivenScanf");
#endif
addTest(root, &ScanfMultipleIntegers, "ScanfMultipleIntegers");
#endif
addStreamTests(root);
}

View file

@ -110,31 +110,31 @@ char * opt_fName = 0;
const char * opt_locale = "en_US";
int opt_langid = 0; // Defaults to value corresponding to opt_locale.
char * opt_rules = 0;
UBool opt_help = FALSE;
UBool opt_help = false;
int opt_loopCount = 1;
int opt_iLoopCount = 1;
UBool opt_terse = FALSE;
UBool opt_qsort = FALSE;
UBool opt_binsearch = FALSE;
UBool opt_icu = TRUE;
UBool opt_win = FALSE; // Run with Windows native functions.
UBool opt_unix = FALSE; // Run with UNIX strcoll, strxfrm functions.
UBool opt_uselen = FALSE;
UBool opt_usekeys = FALSE;
UBool opt_strcmp = FALSE;
UBool opt_strcmpCPO = FALSE;
UBool opt_norm = FALSE;
UBool opt_keygen = FALSE;
UBool opt_french = FALSE;
UBool opt_frenchoff = FALSE;
UBool opt_shifted = FALSE;
UBool opt_lower = FALSE;
UBool opt_upper = FALSE;
UBool opt_case = FALSE;
UBool opt_terse = false;
UBool opt_qsort = false;
UBool opt_binsearch = false;
UBool opt_icu = true;
UBool opt_win = false; // Run with Windows native functions.
UBool opt_unix = false; // Run with UNIX strcoll, strxfrm functions.
UBool opt_uselen = false;
UBool opt_usekeys = false;
UBool opt_strcmp = false;
UBool opt_strcmpCPO = false;
UBool opt_norm = false;
UBool opt_keygen = false;
UBool opt_french = false;
UBool opt_frenchoff = false;
UBool opt_shifted = false;
UBool opt_lower = false;
UBool opt_upper = false;
UBool opt_case = false;
int opt_level = 0;
UBool opt_keyhist = FALSE;
UBool opt_itertest = FALSE;
UBool opt_dump = FALSE;
UBool opt_keyhist = false;
UBool opt_itertest = false;
UBool opt_dump = false;
@ -233,13 +233,13 @@ UBool ProcessOptions(int argc, const char **argv, OptSpec opts[])
if (strcmp(pOpt->name, pArgName) == 0) {
switch (pOpt->type) {
case OptSpec::FLAG:
*(UBool *)(pOpt->pVar) = TRUE;
*(UBool *)(pOpt->pVar) = true;
break;
case OptSpec::STRING:
argNum ++;
if (argNum >= argc) {
fprintf(stderr, "value expected for \"%s\" option.\n", pOpt->name);
return FALSE;
return false;
}
*(const char **)(pOpt->pVar) = argv[argNum];
break;
@ -247,13 +247,13 @@ UBool ProcessOptions(int argc, const char **argv, OptSpec opts[])
argNum ++;
if (argNum >= argc) {
fprintf(stderr, "value expected for \"%s\" option.\n", pOpt->name);
return FALSE;
return false;
}
char *endp;
i = strtol(argv[argNum], &endp, 0);
if (endp == argv[argNum]) {
fprintf(stderr, "integer value expected for \"%s\" option.\n", pOpt->name);
return FALSE;
return false;
}
*(int *)(pOpt->pVar) = i;
}
@ -263,10 +263,10 @@ UBool ProcessOptions(int argc, const char **argv, OptSpec opts[])
if (pOpt->name == 0)
{
fprintf(stderr, "Unrecognized option \"%s\"\n", pArgName);
return FALSE;
return false;
}
}
return TRUE;
return true;
}
//---------------------------------------------------------------------------------------
@ -425,7 +425,7 @@ void doKeyGen()
unsigned long elapsedTime = timeGetTime() - startTime;
int ns = (int)(float(1000000) * (float)elapsedTime / (float)(adj_loopCount*gNumFileLines));
if (opt_terse == FALSE) {
if (opt_terse == false) {
printf("Sort Key Generation: total # of keys = %d\n", loops*gNumFileLines);
printf("Sort Key Generation: time per key = %d ns\n", ns);
}
@ -448,7 +448,7 @@ void doKeyGen()
}
}
if (opt_terse == FALSE) {
if (opt_terse == false) {
printf("Key Length / character = %f\n", (float)totalKeyLen / (float)totalChars);
} else {
printf("%f, ", (float)totalKeyLen / (float)totalChars);
@ -610,7 +610,7 @@ void doBinarySearch()
r = CompareStringW(gWinLCID, 0, (gSortedLines[line])->name, lineLen, (gSortedLines[guess])->name, guessLen);
}
if (r == 0) {
if (opt_terse == FALSE) {
if (opt_terse == false) {
fprintf(stderr, "Error returned from Windows CompareStringW.\n");
}
exit(-1);
@ -679,7 +679,7 @@ void doBinarySearch()
}
int ns = (int)(float(1000000) * (float)elapsedTime / (float)gCount);
if (opt_terse == FALSE) {
if (opt_terse == false) {
printf("binary search: total # of string compares = %d\n", gCount);
printf("binary search: compares per loop = %d\n", gCount / loops);
printf("binary search: time per compare = %d ns\n", ns);
@ -763,7 +763,7 @@ void doQSort() {
unsigned long elapsedTime = timeGetTime() - startTime;
int ns = (int)(float(1000000) * (float)elapsedTime / (float)gCount);
if (opt_terse == FALSE) {
if (opt_terse == false) {
printf("qsort: total # of string compares = %d\n", gCount);
printf("qsort: time per compare = %d ns\n", ns);
} else {
@ -925,7 +925,7 @@ void doForwardIterTest(UBool haslen) {
int count5 = 5;
strindex = 0;
ucol_setOffset(iter, strindex, &error);
while (TRUE) {
while (true) {
if (ucol_next(iter, &error) == UCOL_NULLORDER) {
break;
}
@ -954,7 +954,7 @@ void doForwardIterTest(UBool haslen) {
int count5 = 5;
strindex = 0;
ucol_setOffset(iter, strindex, &error);
while (TRUE) {
while (true) {
tempgCount ++;
count5 --;
if (count5 == 0) {
@ -1088,7 +1088,7 @@ void doBackwardIterTest(UBool haslen) {
int count5 = 5;
strindex = 5;
ucol_setOffset(iter, strindex, &error);
while (TRUE) {
while (true) {
if (ucol_previous(iter, &error) == UCOL_NULLORDER) {
break;
}
@ -1117,7 +1117,7 @@ void doBackwardIterTest(UBool haslen) {
int count5 = 5;
strindex = 5;
ucol_setOffset(iter, strindex, &error);
while (TRUE) {
while (true) {
tempgCount ++;
count5 --;
if (count5 == 0) {
@ -1229,14 +1229,14 @@ private:
};
UCharFile::UCharFile(const char * fileName) {
fEof = FALSE;
fError = FALSE;
fEof = false;
fError = false;
fName = fileName;
fFile = fopen(fName, "rb");
fPending2ndSurrogate = 0;
if (fFile == NULL) {
fprintf(stderr, "Can not open file \"%s\"\n", opt_fName);
fError = TRUE;
fError = true;
return;
}
//
@ -1279,7 +1279,7 @@ UChar UCharFile::get() {
c = cL | (cH << 8);
if (cH == EOF) {
c = 0;
fEof = TRUE;
fEof = true;
}
break;
}
@ -1291,7 +1291,7 @@ UChar UCharFile::get() {
c = cL | (cH << 8);
if (cL == EOF) {
c = 0;
fEof = TRUE;
fEof = true;
}
break;
}
@ -1306,7 +1306,7 @@ UChar UCharFile::get() {
int ch = fgetc(fFile); // Note: c and ch are separate cause eof test doesn't work on UChar type.
if (ch == EOF) {
c = 0;
fEof = TRUE;
fEof = true;
break;
}
@ -1324,7 +1324,7 @@ UChar UCharFile::get() {
else if (ch >= 0xC0) {nBytes=2;}
else {
fprintf(stderr, "utf-8 encoded file contains corrupt data.\n");
fError = TRUE;
fError = true;
return 0;
}
@ -1335,7 +1335,7 @@ UChar UCharFile::get() {
bytes[i] = fgetc(fFile);
if (bytes[i] < 0x80 || bytes[i] >= 0xc0) {
fprintf(stderr, "utf-8 encoded file contains corrupt data.\n");
fError = TRUE;
fError = true;
return 0;
}
}
@ -1426,14 +1426,14 @@ UCollator *openRulesCollator() {
//
//----------------------------------------------------------------------------------------
int main(int argc, const char** argv) {
if (ProcessOptions(argc, argv, opts) != TRUE || opt_help || opt_fName == 0) {
if (ProcessOptions(argc, argv, opts) != true || opt_help || opt_fName == 0) {
printf(gUsageString);
exit (1);
}
// Make sure that we've only got one API selected.
if (opt_unix || opt_win) opt_icu = FALSE;
if (opt_unix) opt_win = FALSE;
if (opt_unix || opt_win) opt_icu = false;
if (opt_unix) opt_win = false;
//
// Set up an ICU collator
@ -1451,10 +1451,10 @@ int main(int argc, const char** argv) {
return -1;
}
}
if (status==U_USING_DEFAULT_WARNING && opt_terse==FALSE) {
if (status==U_USING_DEFAULT_WARNING && opt_terse==false) {
fprintf(stderr, "Warning, U_USING_DEFAULT_WARNING for %s\n", opt_locale);
}
if (status==U_USING_FALLBACK_WARNING && opt_terse==FALSE) {
if (status==U_USING_FALLBACK_WARNING && opt_terse==false) {
fprintf(stderr, "Warning, U_USING_FALLBACK_ERROR for %s\n", opt_locale);
}
@ -1589,16 +1589,16 @@ int main(int argc, const char** argv) {
buf[column++] = c;
if (column >= 1023)
{
static UBool warnFlag = TRUE;
static UBool warnFlag = true;
if (warnFlag) {
fprintf(stderr, "Warning - file line longer than 1023 chars truncated.\n");
warnFlag = FALSE;
warnFlag = false;
}
column--;
}
}
if (opt_terse == FALSE) {
if (opt_terse == false) {
printf("file \"%s\", %d lines.\n", opt_fName, gNumFileLines);
}

View file

@ -500,7 +500,7 @@ protected:
case kApplyPattern:
{
UNumberFormat *fmt = unum_open(UNUM_DECIMAL, NULL, -1, TEST_LOCALE, 0, &setupStatus);
unum_applyPattern(fmt, FALSE, fPat.getTerminatedBuffer(), -1, NULL, &setupStatus);
unum_applyPattern(fmt, false, fPat.getTerminatedBuffer(), -1, NULL, &setupStatus);
return fmt;
}
case kGroupOff:
@ -512,7 +512,7 @@ protected:
case kApplyGroupOff:
{
UNumberFormat *fmt = unum_open(UNUM_DECIMAL, NULL, -1, TEST_LOCALE, 0, &setupStatus);
unum_applyPattern(fmt, FALSE, fPat.getTerminatedBuffer(), -1, NULL, &setupStatus);
unum_applyPattern(fmt, false, fPat.getTerminatedBuffer(), -1, NULL, &setupStatus);
unum_setAttribute(fmt, UNUM_GROUPING_USED, UNUM_NO);
return fmt;
}

View file

@ -190,12 +190,12 @@ U_CAPI double uprv_getMeanTime(double *times, uint32_t *timeCount, double *margi
return meanTime;
}
UBool calcSieveTime = FALSE;
UBool calcSieveTime = false;
double meanSieveTime = 0.0;
double meanSieveME = 0.0;
U_CAPI double uprv_getSieveTime(double *marginOfError) {
if(calcSieveTime==FALSE) {
if(!calcSieveTime) {
#define SAMPLES 50
uint32_t samples = SAMPLES;
double times[SAMPLES];
@ -208,7 +208,7 @@ U_CAPI double uprv_getSieveTime(double *marginOfError) {
}
meanSieveTime = uprv_getMeanTime(times, &samples,&meanSieveME);
calcSieveTime=TRUE;
calcSieveTime=true;
}
if(marginOfError!=NULL) {
*marginOfError = meanSieveME;

View file

@ -47,7 +47,7 @@ private:
public:
virtual void call(UErrorCode* status){
if(line_mode==TRUE){
if(line_mode){
if(uselen){
for(int32_t i = 0; i< numLines; i++){
retVal = (*fn)(lines[i].name,lines[i].len,mode, options, status);
@ -68,7 +68,7 @@ public:
}
virtual long getOperationsPerIteration(){
if(line_mode==TRUE){
if(line_mode){
int32_t totalChars=0;
for(int32_t i =0; i< numLines; i++){
totalChars+= lines[i].len;
@ -86,7 +86,7 @@ public:
mode = _mode;
src = NULL;
srcLen = 0;
line_mode = TRUE;
line_mode = true;
}
QuickCheckPerfFunction(QuickCheckFn func, const UChar* source,int32_t sourceLen, UNormalizationMode _mode, int32_t opts, UBool _uselen) : options(opts) {
fn = func;
@ -96,7 +96,7 @@ public:
mode = _mode;
src = source;
srcLen = sourceLen;
line_mode = FALSE;
line_mode = false;
}
};
@ -118,7 +118,7 @@ private:
public:
virtual void call(UErrorCode* status){
if(line_mode==TRUE){
if(line_mode){
if(uselen){
for(int32_t i = 0; i< numLines; i++){
retVal = (*fn)(lines[i].name,lines[i].len,pDest,destLen, options, status);
@ -137,7 +137,7 @@ public:
}
}
virtual long getOperationsPerIteration(){
if(line_mode ==TRUE){
if(line_mode){
int32_t totalChars=0;
for(int32_t i =0; i< numLines; i++){
totalChars+= lines[i].len;
@ -156,7 +156,7 @@ public:
pDest = dest;
src = NULL;
srcLen = 0;
line_mode = TRUE;
line_mode = true;
}
NormPerfFunction(NormFn func, int32_t opts, const UChar* source,int32_t sourceLen,UBool _uselen) : options(opts) {
fn = func;
@ -167,7 +167,7 @@ public:
pDest = (UChar*) malloc(destLen * U_SIZEOF_UCHAR);
src = source;
srcLen = sourceLen;
line_mode = FALSE;
line_mode = false;
}
~NormPerfFunction(){
if(dest != pDest){

View file

@ -255,7 +255,7 @@ double NormalizeUTF16::call(int32_t iterations, int32_t pieceLength) {
UErrorCode errorCode = U_ZERO_ERROR;
utimer_getTime(&startTime);
for (int32_t i = 0; i < iterations; ++i) {
piece.setTo(FALSE, s + start, pieceLength);
piece.setTo(false, s + start, pieceLength);
norm2.normalize(piece, dest, errorCode);
start = (start + pieceLength) % limit;
}

View file

@ -35,7 +35,7 @@ UBool BitSet::get(int32_t bitIndex) const {
uint32_t longIndex = bitIndex >> 5;
int32_t bitInLong = bitIndex & 0x1F;
return (longIndex < len) ? (((data[longIndex] >> bitInLong) & 1) != 0)
: FALSE;
: false;
}
void BitSet::set(int32_t bitIndex) {

View file

@ -214,6 +214,6 @@ MeasureUnit.SIPrefix
</ul>
<hr/>
<p><i><font size="-1">Contents generated by ReportAPI tool on Thu Oct 01 10:15:24 PDT 2020<br/>© 2020 and later: Unicode, Inc. and others. License & terms of use: <a href="http://www.unicode.org/copyright.html">http://www.unicode.org/copyright.html</a></font></i></p>
<p><i><font size="-1">Contents generated by ReportAPI tool on Fri Oct 23 11:19:04 PDT 2020<br/>© 2020 and later: Unicode, Inc. and others. License & terms of use: <a href="http://www.unicode.org/copyright.html">http://www.unicode.org/copyright.html</a></font></i></p>
</body>
</html>

View file

@ -6,7 +6,7 @@
#*******************************************************************************
api.report.version = 68
api.report.prev.version = 67
release.file.ver = 68rc
api.doc.version = 68 Release Candidate
maven.pom.ver = 68.1-SNAPSHOT
release.file.ver = 68_1
api.doc.version = 68.1
maven.pom.ver = 68.1

View file

@ -226,6 +226,12 @@ public class FormattedValueStringBuilderImpl {
}
assert currField == null;
// Always set the position to the end so that we don't revisit previous sections
cfpos.setState(
cfpos.getField(),
cfpos.getFieldValue(),
self.length,
self.length);
return false;
}

View file

@ -98,7 +98,12 @@ public class CompactData implements MultiplierProducer {
.entrySet()) {
byte magnitude = (byte) (magnitudeEntry.getKey().length() - 1);
for (Map.Entry<String, String> pluralEntry : magnitudeEntry.getValue().entrySet()) {
StandardPlural plural = StandardPlural.fromString(pluralEntry.getKey().toString());
String pluralString = pluralEntry.getKey().toString();
if ("0".equals(pluralString) || "1".equals(pluralString)) {
// TODO(ICU-21258): Handle this case. For now, skip.
continue;
}
StandardPlural plural = StandardPlural.fromString(pluralString);
String patternString = pluralEntry.getValue().toString();
patterns[getIndex(magnitude, plural)] = patternString;
int numZeros = countZeros(patternString);

View file

@ -35,7 +35,7 @@ public class MeasureUnitImpl {
* <p>
* The "dimensionless" <code>MeasureUnitImpl</code> has an empty <code>singleUnits</code>.
*/
private ArrayList<SingleUnitImpl> singleUnits;
private final ArrayList<SingleUnitImpl> singleUnits;
public MeasureUnitImpl() {
singleUnits = new ArrayList<>();
@ -147,8 +147,7 @@ public class MeasureUnitImpl {
// Find a similar unit that already exists, to attempt to coalesce
SingleUnitImpl oldUnit = null;
for (int i = 0, n = this.singleUnits.size(); i < n; i++) {
SingleUnitImpl candidate = this.singleUnits.get(i);
for (SingleUnitImpl candidate : this.singleUnits) {
if (candidate.isCompatibleWith(singleUnit)) {
oldUnit = candidate;
break;
@ -372,34 +371,32 @@ public class MeasureUnitImpl {
public static class UnitsParser {
// This used only to not build the trie each time we use the parser
private volatile static CharsTrie savedTrie = null;
private final String[] simpleUnits;
// This trie used in the parsing operation.
private CharsTrie trie;
private final CharsTrie trie;
private final String fSource;
// Tracks parser progress: the offset into fSource.
private int fIndex = 0;
// 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).
private boolean fAfterPer = false;
private String fSource;
// If an "-and-" was parsed prior to finding the "single
// * unit", sawAnd is set to true. If not, it is left as is.
private boolean fSawAnd = false;
private UnitsParser(String identifier) {
this.simpleUnits = UnitsData.getSimpleUnits();
this.fSource = identifier;
if (UnitsParser.savedTrie != null) {
try {
this.trie = UnitsParser.savedTrie.clone();
} catch (CloneNotSupportedException e) {
throw new ICUCloneNotSupportedException();
}
return;
try {
this.trie = UnitsParser.savedTrie.clone();
} catch (CloneNotSupportedException e) {
throw new ICUCloneNotSupportedException();
}
}
// Building the trie.
static {
// Build Units trie.
CharsTrieBuilder trieBuilder;
trieBuilder = new CharsTrieBuilder();
@ -432,6 +429,7 @@ public class MeasureUnitImpl {
}
// Add simple units
String[] simpleUnits = UnitsData.getSimpleUnits();
for (int i = 0; i < simpleUnits.length; i++) {
trieBuilder.add(simpleUnits[i], i + UnitsData.Constants.kSimpleUnitOffset);
@ -439,15 +437,8 @@ public class MeasureUnitImpl {
// TODO: Use SLOW or FAST here?
UnitsParser.savedTrie = trieBuilder.build(StringTrieBuilder.Option.FAST);
try {
this.trie = UnitsParser.savedTrie.clone();
} catch (CloneNotSupportedException e) {
throw new ICUCloneNotSupportedException();
}
}
/**
* Construct a MeasureUnit from a CLDR Unit Identifier, defined in UTS 35.
* Validates and canonicalizes the identifier.
@ -607,7 +598,7 @@ public class MeasureUnitImpl {
break;
case TYPE_SIMPLE_UNIT:
result.setSimpleUnit(token.getSimpleUnitIndex(), simpleUnits);
result.setSimpleUnit(token.getSimpleUnitIndex(), UnitsData.getSimpleUnits());
return result;
default:
@ -746,7 +737,7 @@ public class MeasureUnitImpl {
}
static class MeasureUnitImplComparator implements Comparator<MeasureUnitImpl> {
private ConversionRates conversionRates;
private final ConversionRates conversionRates;
public MeasureUnitImplComparator(ConversionRates conversionRates) {
this.conversionRates = conversionRates;

View file

@ -613,91 +613,67 @@ public abstract class NumberFormatterSettings<T extends NumberFormatterSettings<
// of a MacroProps object at each step.
// TODO: Remove the reference to the parent after the macros are resolved?
MacroProps macros = new MacroProps();
// Bitmap: 1 if seen; 0 if unseen
long seen = 0;
NumberFormatterSettings<?> current = this;
while (current != null) {
long keyBitmask = (1L << current.key);
if (0 != (seen & keyBitmask)) {
current = current.parent;
continue;
}
seen |= keyBitmask;
switch (current.key) {
case KEY_MACROS:
macros.fallback((MacroProps) current.value);
break;
case KEY_LOCALE:
if (macros.loc == null) {
macros.loc = (ULocale) current.value;
}
macros.loc = (ULocale) current.value;
break;
case KEY_NOTATION:
if (macros.notation == null) {
macros.notation = (Notation) current.value;
}
macros.notation = (Notation) current.value;
break;
case KEY_UNIT:
if (macros.unit == null) {
macros.unit = (MeasureUnit) current.value;
}
macros.unit = (MeasureUnit) current.value;
break;
case KEY_PRECISION:
if (macros.precision == null) {
macros.precision = (Precision) current.value;
}
macros.precision = (Precision) current.value;
break;
case KEY_ROUNDING_MODE:
if (macros.roundingMode == null) {
macros.roundingMode = (RoundingMode) current.value;
}
macros.roundingMode = (RoundingMode) current.value;
break;
case KEY_GROUPING:
if (macros.grouping == null) {
macros.grouping = /* (Object) */ current.value;
}
macros.grouping = /* (Object) */ current.value;
break;
case KEY_PADDER:
if (macros.padder == null) {
macros.padder = (Padder) current.value;
}
macros.padder = (Padder) current.value;
break;
case KEY_INTEGER:
if (macros.integerWidth == null) {
macros.integerWidth = (IntegerWidth) current.value;
}
macros.integerWidth = (IntegerWidth) current.value;
break;
case KEY_SYMBOLS:
if (macros.symbols == null) {
macros.symbols = /* (Object) */ current.value;
}
macros.symbols = /* (Object) */ current.value;
break;
case KEY_UNIT_WIDTH:
if (macros.unitWidth == null) {
macros.unitWidth = (UnitWidth) current.value;
}
macros.unitWidth = (UnitWidth) current.value;
break;
case KEY_SIGN:
if (macros.sign == null) {
macros.sign = (SignDisplay) current.value;
}
macros.sign = (SignDisplay) current.value;
break;
case KEY_DECIMAL:
if (macros.decimal == null) {
macros.decimal = (DecimalSeparatorDisplay) current.value;
}
macros.decimal = (DecimalSeparatorDisplay) current.value;
break;
case KEY_SCALE:
if (macros.scale == null) {
macros.scale = (Scale) current.value;
}
macros.scale = (Scale) current.value;
break;
case KEY_THRESHOLD:
if (macros.threshold == null) {
macros.threshold = (Long) current.value;
}
macros.threshold = (Long) current.value;
break;
case KEY_PER_UNIT:
if (macros.perUnit == null) {
macros.perUnit = (MeasureUnit) current.value;
}
macros.perUnit = (MeasureUnit) current.value;
break;
case KEY_USAGE:
if(macros.usage == null) {
macros.usage = (String) current.value;
}
macros.usage = (String) current.value;
break;
default:
throw new AssertionError("Unknown key: " + current.key);

View file

@ -618,6 +618,7 @@ class NumberSkeletonImpl {
case STATE_INCREMENT_PRECISION:
case STATE_MEASURE_UNIT:
case STATE_PER_MEASURE_UNIT:
case STATE_IDENTIFIER_UNIT:
case STATE_UNIT_USAGE:
case STATE_CURRENCY_UNIT:
case STATE_INTEGER_WIDTH:
@ -659,7 +660,7 @@ class NumberSkeletonImpl {
BlueprintHelpers.parseScientificStem(segment, macros);
return ParseState.STATE_NULL;
case '0':
checkNull(macros.notation, segment);
checkNull(macros.integerWidth, segment);
BlueprintHelpers.parseIntegerStem(segment, macros);
return ParseState.STATE_NULL;
}
@ -784,6 +785,11 @@ class NumberSkeletonImpl {
return ParseState.STATE_MEASURE_UNIT;
case STEM_PER_MEASURE_UNIT:
// In C++, STEM_CURRENCY's checks mark perUnit as "seen". Here we do
// the inverse: checking that macros.unit is not set to a currency.
if (macros.unit instanceof Currency) {
throw new SkeletonSyntaxException("Duplicated setting", segment);
}
checkNull(macros.perUnit, segment);
return ParseState.STATE_PER_MEASURE_UNIT;
@ -798,6 +804,7 @@ class NumberSkeletonImpl {
case STEM_CURRENCY:
checkNull(macros.unit, segment);
checkNull(macros.perUnit, segment);
return ParseState.STATE_CURRENCY_UNIT;
case STEM_INTEGER_WIDTH:
@ -1448,25 +1455,25 @@ class NumberSkeletonImpl {
}
private static boolean unit(MacroProps macros, StringBuilder sb) {
if (macros.unit instanceof Currency) {
MeasureUnit unit = macros.unit;
if (macros.perUnit != null) {
if (macros.unit instanceof Currency || macros.perUnit instanceof Currency) {
throw new UnsupportedOperationException(
"Cannot generate number skeleton with currency unit and per-unit");
}
unit = unit.product(macros.perUnit.reciprocal());
}
if (unit instanceof Currency) {
sb.append("currency/");
BlueprintHelpers.generateCurrencyOption((Currency) macros.unit, sb);
BlueprintHelpers.generateCurrencyOption((Currency)unit, sb);
return true;
} else if (macros.unit == MeasureUnit.PERCENT) {
} else if (unit.equals(MeasureUnit.PERCENT)) {
sb.append("percent");
return true;
} else if (macros.unit == MeasureUnit.PERMILLE) {
} else if (unit.equals(MeasureUnit.PERMILLE)) {
sb.append("permille");
return true;
} else {
MeasureUnit unit = macros.unit;
if (macros.perUnit != null) {
if (macros.perUnit instanceof Currency) {
throw new UnsupportedOperationException(
"Cannot generate number skeleton with per-unit that is not a standard measure unit");
}
unit = unit.product(macros.perUnit.reciprocal());
}
sb.append("unit/");
sb.append(unit.getIdentifier());
return true;

View file

@ -295,7 +295,9 @@ public class ConstrainedFieldPosition {
*/
public void setState(Field field, Object value, int start, int limit) {
// Check matchesField only as an assertion (debug build)
assert matchesField(field, value);
if (field != null) {
assert matchesField(field, value);
}
fField = field;
fValue = value;

View file

@ -1982,6 +1982,14 @@ public class DateIntervalFormat extends UFormat {
pattern = fInfo.getIntervalPattern(bestSkeleton,
Calendar.HOUR);
if ( pattern != null ) {
boolean suppressDayPeriodField = fSkeleton.indexOf('J') != -1;
String part1 = adjustFieldWidth(skeleton, bestSkeleton,
pattern.getFirstPart(), differenceInfo, suppressDayPeriodField);
String part2 = adjustFieldWidth(skeleton, bestSkeleton,
pattern.getSecondPart(), differenceInfo, suppressDayPeriodField);
pattern = new PatternInfo(part1, part2,
pattern.firstDateInPtnIsLaterDate());
// share
intervalPatterns.put(DateIntervalInfo.
CALENDAR_FIELD_TO_PATTERN_LETTER[field],
@ -2097,24 +2105,24 @@ public class DateIntervalFormat extends UFormat {
DateIntervalInfo.parseSkeleton(bestMatchSkeleton, bestMatchSkeletonFieldWidth);
if (suppressDayPeriodField) {
if (bestMatchIntervalPattern.indexOf(" a") != -1) {
bestMatchIntervalPattern = bestMatchIntervalPattern.replace(" a", "");
bestMatchIntervalPattern = findReplaceInPattern(bestMatchIntervalPattern, " a", "");
} else if (bestMatchIntervalPattern.indexOf("a ") != -1) {
bestMatchIntervalPattern = bestMatchIntervalPattern.replace("a ", "");
bestMatchIntervalPattern = findReplaceInPattern(bestMatchIntervalPattern, "a ", "");
}
bestMatchIntervalPattern = bestMatchIntervalPattern.replace("a", "");
bestMatchIntervalPattern = findReplaceInPattern(bestMatchIntervalPattern, "a", "");
}
if ( differenceInfo == 2 ) {
if (inputSkeleton.indexOf('z') != -1) {
bestMatchIntervalPattern = bestMatchIntervalPattern.replace('v', 'z');
bestMatchIntervalPattern = findReplaceInPattern(bestMatchIntervalPattern, "v", "z");
}
if (inputSkeleton.indexOf('K') != -1) {
bestMatchIntervalPattern = bestMatchIntervalPattern.replace('h', 'K');
bestMatchIntervalPattern = findReplaceInPattern(bestMatchIntervalPattern, "h", "K");
}
if (inputSkeleton.indexOf('k') != -1) {
bestMatchIntervalPattern = bestMatchIntervalPattern.replace('H', 'k');
bestMatchIntervalPattern = findReplaceInPattern(bestMatchIntervalPattern, "H", "k");
}
if (inputSkeleton.indexOf('b') != -1) {
bestMatchIntervalPattern = bestMatchIntervalPattern.replace('a', 'b');
bestMatchIntervalPattern = findReplaceInPattern(bestMatchIntervalPattern, "a", "b");
}
}
if (bestMatchIntervalPattern.indexOf('a') != -1 && bestMatchSkeletonFieldWidth['a' - PATTERN_CHAR_BASE] == 0) {
@ -2189,6 +2197,43 @@ public class DateIntervalFormat extends UFormat {
}
return adjustedPtn.toString();
}
/**
* Does the same thing as String.replace(), except that it won't perform the
* substitution inside quoted literal text.
* @param targetString The string to perform the find-replace operation on.
* @param strToReplace The string to search for and replace in the target string.
* @param strToReplaceWith The string to substitute in wherever `stringToReplace` was found.
*/
private static String findReplaceInPattern(String targetString,
String strToReplace,
String strToReplaceWith) {
int firstQuoteIndex = targetString.indexOf("\'");
if (firstQuoteIndex < 0) {
return targetString.replace(strToReplace, strToReplaceWith);
} else {
StringBuilder result = new StringBuilder();
String source = targetString;
while (firstQuoteIndex >= 0) {
int secondQuoteIndex = source.indexOf("\'", firstQuoteIndex + 1);
if (secondQuoteIndex < 0) {
secondQuoteIndex = source.length() - 1;
}
String unquotedText = source.substring(0, firstQuoteIndex);
String quotedText = source.substring(firstQuoteIndex, secondQuoteIndex + 1);
result.append(unquotedText.replace(strToReplace, strToReplaceWith));
result.append(quotedText);
source = source.substring(secondQuoteIndex + 1);
firstQuoteIndex = source.indexOf("\'");
}
result.append(source.replace(strToReplace, strToReplaceWith));
return result.toString();
}
}
/*

View file

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:d2f7f3bb8c5ba30b965dddbe2432c00b72087f9b72998b501a80108ad38d76e7
size 13270764
oid sha256:079654dc48a1f25b918e4408123703bf0182c3391002d0d618191f46f8b9ed78
size 13270502

View file

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:6ce58e5a64fd5059164b21402d00bc19d8842f429db7a518dd8933c9044ddb8e
size 94643
oid sha256:2307e62abb987090e8083a213b86733849261015c3ed3bc7308f8aef3ecaa1f3
size 94647

View file

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:b783eeb37f9f408a3698a2abd754175f0ed442bae781d01b662d61896691fd48
oid sha256:ba1096e3fc2313d44b1aa66469702f462d4ee5624303eb0fdc3fd5ca422518bb
size 723507

View file

@ -805,6 +805,15 @@ public class DateIntervalFormatTest extends TestFmwk {
"hi_IN", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "hB", "\\u0930\\u093E\\u0924 12\\u20131",
"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-21343
"de", "CE 2010 09 27 01:00:00", "CE 2010 09 27 10:00:00", "KK", "1 \\u2013 10 Uhr AM",
};
expect(DATA, DATA.length);
}

View file

@ -215,6 +215,8 @@ public class FormattedValueTest {
}
boolean afterLoopResult = fv.nextPosition(cfpos);
assertFalse(baseMessage + "after loop: " + cfpos, afterLoopResult);
afterLoopResult = fv.nextPosition(cfpos);
assertFalse(baseMessage + "after loop again: " + cfpos, afterLoopResult);
// Check nextPosition constrained over each class one at a time
for (Class<?> classConstraint : uniqueFieldClasses) {
@ -238,6 +240,8 @@ public class FormattedValueTest {
}
afterLoopResult = fv.nextPosition(cfpos);
assertFalse(baseMessage + "after loop: " + cfpos, afterLoopResult);
afterLoopResult = fv.nextPosition(cfpos);
assertFalse(baseMessage + "after loop again: " + cfpos, afterLoopResult);
}
// Check nextPosition constrained over an unrelated class
@ -267,6 +271,8 @@ public class FormattedValueTest {
}
afterLoopResult = fv.nextPosition(cfpos);
assertFalse(baseMessage + "after loop: " + cfpos, afterLoopResult);
afterLoopResult = fv.nextPosition(cfpos);
assertFalse(baseMessage + "after loop again: " + cfpos, afterLoopResult);
}
}

View file

@ -217,9 +217,8 @@ public class ListFormatterTest extends TestFmwk {
@Test
public void TestFormattedValue() {
ListFormatter fmt = ListFormatter.getInstance(ULocale.ENGLISH);
{
ListFormatter fmt = ListFormatter.getInstance(ULocale.ENGLISH);
String message = "Field position test 1";
String expectedString = "hello, wonderful, and world";
String[] inputs = {
@ -244,6 +243,85 @@ public class ListFormatterTest extends TestFmwk {
expectedString,
expectedFieldPositions);
}
{
ListFormatter fmt = ListFormatter.getInstance(ULocale.CHINESE, Type.UNITS, Width.SHORT);
String message = "Field position test 2 (ICU-21340)";
String expectedString = "aabbbbbbbccc";
String inputs[] = {
"aa",
"bbbbbbb",
"ccc"
};
FormattedList result = fmt.formatToValue(Arrays.asList(inputs));
Object[][] expectedFieldPositions = {
// field, begin index, end index
{ListFormatter.SpanField.LIST_SPAN, 0, 2, 0},
{ListFormatter.Field.ELEMENT, 0, 2},
{ListFormatter.SpanField.LIST_SPAN, 2, 9, 1},
{ListFormatter.Field.ELEMENT, 2, 9},
{ListFormatter.SpanField.LIST_SPAN, 9, 12, 2},
{ListFormatter.Field.ELEMENT, 9, 12}};
if (!logKnownIssue("21351", "Java still coalesces adjacent elements")) {
FormattedValueTest.checkFormattedValue(
message,
result,
expectedString,
expectedFieldPositions);
}
}
{
ListFormatter fmt = ListFormatter.getInstance(ULocale.ENGLISH, Type.UNITS, Width.SHORT);
String message = "ICU-21383 Long list";
String expectedString = "a, b, c, d, e, f, g, h, i";
String inputs[] = {
"a",
"b",
"c",
"d",
"e",
"f",
"g",
"h",
"i",
};
FormattedList result = fmt.formatToValue(Arrays.asList(inputs));
Object[][] expectedFieldPositions = {
// field, begin index, end index
{ListFormatter.SpanField.LIST_SPAN, 0, 1, 0},
{ListFormatter.Field.ELEMENT, 0, 1},
{ListFormatter.Field.LITERAL, 1, 3},
{ListFormatter.SpanField.LIST_SPAN, 3, 4, 1},
{ListFormatter.Field.ELEMENT, 3, 4},
{ListFormatter.Field.LITERAL, 4, 6},
{ListFormatter.SpanField.LIST_SPAN, 6, 7, 2},
{ListFormatter.Field.ELEMENT, 6, 7},
{ListFormatter.Field.LITERAL, 7, 9},
{ListFormatter.SpanField.LIST_SPAN, 9, 10, 3},
{ListFormatter.Field.ELEMENT, 9, 10},
{ListFormatter.Field.LITERAL, 10, 12},
{ListFormatter.SpanField.LIST_SPAN, 12, 13, 4},
{ListFormatter.Field.ELEMENT, 12, 13},
{ListFormatter.Field.LITERAL, 13, 15},
{ListFormatter.SpanField.LIST_SPAN, 15, 16, 5},
{ListFormatter.Field.ELEMENT, 15, 16},
{ListFormatter.Field.LITERAL, 16, 18},
{ListFormatter.SpanField.LIST_SPAN, 18, 19, 6},
{ListFormatter.Field.ELEMENT, 18, 19},
{ListFormatter.Field.LITERAL, 19, 21},
{ListFormatter.SpanField.LIST_SPAN, 21, 22, 7},
{ListFormatter.Field.ELEMENT, 21, 22},
{ListFormatter.Field.LITERAL, 22, 24},
{ListFormatter.SpanField.LIST_SPAN, 24, 25, 8},
{ListFormatter.Field.ELEMENT, 24, 25},
};
FormattedValueTest.checkFormattedValue(
message,
result,
expectedString,
expectedFieldPositions);
}
}
@Test

View file

@ -756,6 +756,15 @@ public class NumberFormatterApiTest extends TestFmwk {
new ULocale("de-DE"),
-1.24,
"-1 Std., 14 Min. und 24 Sek.");
assertFormatSingle(
"Zero out the unit field",
"",
"",
NumberFormatter.with().unit(MeasureUnit.KELVIN).unit(NoUnit.BASE),
new ULocale("en"),
100,
"100");
}
@Test
@ -935,6 +944,7 @@ public class NumberFormatterApiTest extends TestFmwk {
"2.4 m/s\u00B2");
}
// TODO: merge these tests into NumberSkeletonTest.java instead of here:
@Test
public void unitSkeletons() {
Object[][] cases = {
@ -959,11 +969,11 @@ public class NumberFormatterApiTest extends TestFmwk {
"unit/meter-per-second"},
{"short-form compound units stay as is", //
"unit/square-meter-per-square-meter", //
"unit/square-meter-per-square-meter", //
"unit/square-meter-per-square-meter"},
{"short-form compound units stay as is", //
"unit/joule-per-furlong", //
"unit/joule-per-furlong", //
"unit/joule-per-furlong"},
{"short-form that doesn't consist of built-in units", //
@ -974,6 +984,22 @@ public class NumberFormatterApiTest extends TestFmwk {
"unit/meter-per-hectosecond", //
"unit/meter-per-hectosecond"},
{"percent compound skeletons handled correctly", //
"unit/percent-per-meter", //
"unit/percent-per-meter"},
{"permille compound skeletons handled correctly", //
"measure-unit/concentr-permille per-measure-unit/length-meter", //
"unit/permille-per-meter"},
{"percent simple unit is not actually considered a unit", //
"unit/percent", //
"percent"},
{"permille simple unit is not actually considered a unit", //
"measure-unit/concentr-permille", //
"permille"},
// // TODO: binary prefixes not supported yet!
// {"Round-trip example from icu-units#35", //
// "unit/kibijoule-per-furlong", //
@ -997,6 +1023,21 @@ public class NumberFormatterApiTest extends TestFmwk {
"measure-unit/meter per-measure-unit/hectosecond", //
true, //
false},
{"\"currency/EUR measure-unit/length-meter\" fails, conflicting skeleton.",
"currency/EUR measure-unit/length-meter", //
true, //
false},
{"\"measure-unit/length-meter currency/EUR\" fails, conflicting skeleton.",
"measure-unit/length-meter currency/EUR", //
true, //
false},
{"\"currency/EUR per-measure-unit/meter\" fails, conflicting skeleton.",
"currency/EUR per-measure-unit/length-meter", //
true, //
false},
};
for (Object[] cas : failCases) {
String msg = (String)cas[0];
@ -1026,6 +1067,39 @@ public class NumberFormatterApiTest extends TestFmwk {
}
}
}
assertEquals( //
".unit(METER_PER_SECOND) normalization", //
"unit/meter-per-second", //
NumberFormatter.with().unit(MeasureUnit.METER_PER_SECOND).toSkeleton());
assertEquals( //
".unit(METER).perUnit(SECOND) normalization", //
"unit/meter-per-second",
NumberFormatter.with().unit(MeasureUnit.METER).perUnit(MeasureUnit.SECOND).toSkeleton());
assertEquals( //
".unit(MeasureUnit.forIdentifier(\"hectometer\")) normalization", //
"unit/hectometer",
NumberFormatter.with().unit(MeasureUnit.forIdentifier("hectometer")).toSkeleton());
assertEquals( //
".unit(MeasureUnit.forIdentifier(\"hectometer\")) normalization", //
"unit/meter-per-hectosecond",
NumberFormatter.with()
.unit(MeasureUnit.METER)
.perUnit(MeasureUnit.forIdentifier("hectosecond"))
.toSkeleton());
assertEquals( //
".unit(CURRENCY) produces a currency/CURRENCY skeleton", //
"currency/GBP", //
NumberFormatter.with().unit(GBP).toSkeleton());
// .unit(CURRENCY).perUnit(ANYTHING) is not supported.
try {
NumberFormatter.with().unit(GBP).perUnit(MeasureUnit.METER).toSkeleton();
fail("should give an error, unit(currency) with perUnit() is invalid.");
} catch (UnsupportedOperationException e) {
// Pass
}
}
@Test

View file

@ -411,4 +411,37 @@ public class NumberSkeletonTest {
}
}
}
@Test
public void perUnitToSkeleton() {
String[][] cases = {
{"area", "acre"},
{"concentr", "percent"},
{"concentr", "permille"},
{"concentr", "permillion"},
{"concentr", "permyriad"},
{"digital", "bit"},
{"length", "yard"},
};
for (String[] cas1 : cases) {
for (String[] cas2 : cases) {
String skeleton = "measure-unit/" + cas1[0] + "-" + cas1[1] + " per-measure-unit/" +
cas2[0] + "-" + cas2[1];
if (cas1[0] != cas2[0] && cas1[1] != cas2[1]) {
String toSkeleton = NumberFormatter.forSkeleton(skeleton).toSkeleton();
// Ensure both subtype are in the toSkeleton.
String msg;
msg = toSkeleton + " should contain '" + cas1[1] + "' when constructed from " +
skeleton;
assertTrue(msg, toSkeleton.indexOf(cas1[1]) >= 0);
msg = toSkeleton + " should contain '" + cas2[1] + "' when constructed from " +
skeleton;
assertTrue(msg, toSkeleton.indexOf(cas2[1]) >= 0);
}
}
}
}
}

View file

@ -5212,6 +5212,9 @@ public class ULocaleTest extends TestFmwk {
Assert.assertEquals("ja-Latn-alalc97", canonicalTag("ja-Latn-hepburn-heploc"));
Assert.assertEquals("aaa-Fooo-RU", canonicalTag("aaa-Fooo-SU"));
// ICU-21344
Assert.assertEquals("ku-Arab-IQ", canonicalTag("ku-Arab-NT"));
}
@Test

View file

@ -99,7 +99,7 @@
<dependency>
<groupId>org.apache.ant</groupId>
<artifactId>ant</artifactId>
<version>1.10.8</version>
<version>1.10.9</version>
</dependency>
<!-- Testing only dependencies. -->