From e5b51cc496803cc0f53128fdcf88f0260849d8b1 Mon Sep 17 00:00:00 2001 From: "Steven R. Loomis" Date: Wed, 17 Oct 2018 09:43:52 -0700 Subject: [PATCH] deps: icu 63.1 bump (CLDR 34) - Full release notes: http://site.icu-project.org/download/63 Fixes: https://github.com/nodejs/node/issues/22344 PR-URL: https://github.com/nodejs/node/pull/23715 Reviewed-By: Refael Ackermann Reviewed-By: Richard Lau Reviewed-By: Gus Caplan Reviewed-By: Michael Dawson --- deps/icu-small/README-SMALL-ICU.txt | 4 +- deps/icu-small/source/common/bmpset.cpp | 4 +- deps/icu-small/source/common/bytesinkutil.cpp | 38 + deps/icu-small/source/common/bytesinkutil.h | 22 + .../source/common/bytestriebuilder.cpp | 3 +- .../source/common/characterproperties.cpp | 336 +++ deps/icu-small/source/common/charstr.cpp | 14 +- deps/icu-small/source/common/charstr.h | 1 + deps/icu-small/source/common/cmemory.h | 6 +- deps/icu-small/source/common/dictbe.cpp | 16 +- deps/icu-small/source/common/edits.cpp | 4 +- .../source/common/loadednormalizer2impl.cpp | 83 +- deps/icu-small/source/common/locdspnm.cpp | 22 +- deps/icu-small/source/common/locid.cpp | 553 ++++- deps/icu-small/source/common/mutex.h | 2 +- deps/icu-small/source/common/norm2_nfc_data.h | 1128 +++++---- deps/icu-small/source/common/normalizer2.cpp | 90 +- .../source/common/normalizer2impl.cpp | 434 ++-- .../icu-small/source/common/normalizer2impl.h | 44 +- deps/icu-small/source/common/propname_data.h | 2006 +++++++++-------- deps/icu-small/source/common/putil.cpp | 187 +- deps/icu-small/source/common/putilimp.h | 69 +- deps/icu-small/source/common/rbbi.cpp | 8 +- deps/icu-small/source/common/rbbi_cache.cpp | 4 +- deps/icu-small/source/common/rbbirb.cpp | 27 +- deps/icu-small/source/common/rbbiscan.cpp | 2 +- deps/icu-small/source/common/rbbitblb.cpp | 41 +- deps/icu-small/source/common/rbbitblb.h | 13 +- deps/icu-small/source/common/serv.cpp | 4 +- deps/icu-small/source/common/sharedobject.h | 2 +- .../source/common/static_unicode_sets.cpp | 1 + .../source/common/stringtriebuilder.cpp | 2 +- deps/icu-small/source/common/ubidi.cpp | 28 +- .../source/common/ubiditransform.cpp | 8 +- deps/icu-small/source/common/ucase.cpp | 7 +- deps/icu-small/source/common/ucln_cmn.h | 2 +- deps/icu-small/source/common/ucnv.cpp | 12 +- deps/icu-small/source/common/ucnv2022.cpp | 4 +- deps/icu-small/source/common/ucnv_ct.cpp | 2 +- deps/icu-small/source/common/ucnv_u16.cpp | 4 +- deps/icu-small/source/common/ucnv_u32.cpp | 12 +- deps/icu-small/source/common/ucnv_u8.cpp | 4 +- deps/icu-small/source/common/ucnvhz.cpp | 4 +- deps/icu-small/source/common/ucnvmbcs.cpp | 4 +- deps/icu-small/source/common/ucnvsel.cpp | 9 +- deps/icu-small/source/common/ucol_swp.cpp | 75 - deps/icu-small/source/common/ucptrie.cpp | 590 +++++ deps/icu-small/source/common/ucptrie_impl.h | 289 +++ deps/icu-small/source/common/ucurr.cpp | 11 +- deps/icu-small/source/common/udata.cpp | 53 +- deps/icu-small/source/common/udataswp.h | 37 + deps/icu-small/source/common/uhash.cpp | 6 +- deps/icu-small/source/common/uinvchar.h | 16 - .../source/common/ulayout_props_data.h | 722 ++++++ deps/icu-small/source/common/uloc.cpp | 8 +- deps/icu-small/source/common/uloc_keytype.cpp | 5 +- deps/icu-small/source/common/uloc_tag.cpp | 490 +++- deps/icu-small/source/common/ulocimp.h | 32 + deps/icu-small/source/common/umapfile.cpp | 78 +- deps/icu-small/source/common/umapfile.h | 2 +- .../source/common/umutablecptrie.cpp | 1678 ++++++++++++++ deps/icu-small/source/common/umutex.h | 15 +- deps/icu-small/source/common/unames.cpp | 2 +- .../source/common/unicode/bytestream.h | 4 +- .../icu-small/source/common/unicode/casemap.h | 10 +- .../source/common/unicode/char16ptr.h | 6 + .../icu-small/source/common/unicode/docmain.h | 11 +- deps/icu-small/source/common/unicode/edits.h | 52 +- .../icu-small/source/common/unicode/enumset.h | 3 + .../source/common/unicode/filteredbrk.h | 10 +- .../icu-small/source/common/unicode/icuplug.h | 2 +- deps/icu-small/source/common/unicode/locid.h | 370 ++- .../source/common/unicode/messagepattern.h | 4 +- .../source/common/unicode/normalizer2.h | 8 +- .../source/common/unicode/platform.h | 26 +- deps/icu-small/source/common/unicode/ptypes.h | 2 + deps/icu-small/source/common/unicode/rbbi.h | 8 +- .../source/common/unicode/stringoptions.h | 18 +- .../source/common/unicode/stringtriebuilder.h | 11 +- deps/icu-small/source/common/unicode/ubidi.h | 10 +- .../source/common/unicode/ubiditransform.h | 53 +- deps/icu-small/source/common/unicode/uchar.h | 255 ++- deps/icu-small/source/common/unicode/ucnv.h | 13 +- .../icu-small/source/common/unicode/uconfig.h | 13 +- deps/icu-small/source/common/unicode/ucpmap.h | 162 ++ .../icu-small/source/common/unicode/ucptrie.h | 646 ++++++ deps/icu-small/source/common/unicode/ucurr.h | 1 + deps/icu-small/source/common/unicode/uenum.h | 2 - .../source/common/unicode/umachine.h | 23 +- .../source/common/unicode/umutablecptrie.h | 241 ++ deps/icu-small/source/common/unicode/uniset.h | 20 +- deps/icu-small/source/common/unicode/unistr.h | 3 + .../icu-small/source/common/unicode/uobject.h | 3 - .../icu-small/source/common/unicode/urename.h | 42 +- deps/icu-small/source/common/unicode/uset.h | 10 +- .../icu-small/source/common/unicode/ustring.h | 39 +- deps/icu-small/source/common/unicode/utf16.h | 18 +- deps/icu-small/source/common/unicode/utypes.h | 5 + .../icu-small/source/common/unicode/uvernum.h | 12 +- deps/icu-small/source/common/unifiedcache.cpp | 2 +- deps/icu-small/source/common/uniset.cpp | 32 +- deps/icu-small/source/common/uniset_props.cpp | 251 +-- deps/icu-small/source/common/unistr.cpp | 59 +- deps/icu-small/source/common/uprops.cpp | 50 +- deps/icu-small/source/common/uprops.h | 14 + deps/icu-small/source/common/uresbund.cpp | 55 +- deps/icu-small/source/common/uresdata.h | 2 +- deps/icu-small/source/common/ushape.cpp | 2 +- deps/icu-small/source/common/usprep.cpp | 10 +- deps/icu-small/source/common/ustrcase.cpp | 12 +- deps/icu-small/source/common/utext.cpp | 66 +- deps/icu-small/source/common/utrie.h | 15 +- deps/icu-small/source/common/utrie2.cpp | 132 +- deps/icu-small/source/common/utrie2.h | 39 +- .../source/common/utrie2_builder.cpp | 106 +- deps/icu-small/source/common/utrie2_impl.h | 17 +- deps/icu-small/source/common/utrie_swap.cpp | 344 +++ deps/icu-small/source/common/uts46.cpp | 23 +- deps/icu-small/source/common/wintz.cpp | 388 +--- deps/icu-small/source/common/wintz.h | 6 +- .../data/in/{icudt62l.dat => icudt63l.dat} | Bin 2808160 -> 2824512 bytes deps/icu-small/source/i18n/alphaindex.cpp | 8 +- deps/icu-small/source/i18n/anytrans.cpp | 6 +- deps/icu-small/source/i18n/calendar.cpp | 2 +- deps/icu-small/source/i18n/coll.cpp | 11 +- deps/icu-small/source/i18n/collationkeys.cpp | 12 +- deps/icu-small/source/i18n/csrmbcs.cpp | 2 +- deps/icu-small/source/i18n/currpinf.cpp | 278 ++- deps/icu-small/source/i18n/currunit.cpp | 7 +- deps/icu-small/source/i18n/dcfmtsym.cpp | 2 +- deps/icu-small/source/i18n/decimfmt.cpp | 32 +- deps/icu-small/source/i18n/dtfmtsym.cpp | 6 +- deps/icu-small/source/i18n/dtitvfmt.cpp | 6 +- deps/icu-small/source/i18n/dtitvinf.cpp | 6 +- deps/icu-small/source/i18n/dtptngen.cpp | 690 +++--- deps/icu-small/source/i18n/dtptngen_impl.h | 46 +- deps/icu-small/source/i18n/erarules.cpp | 307 +++ deps/icu-small/source/i18n/erarules.h | 92 + deps/icu-small/source/i18n/fphdlimp.h | 3 +- deps/icu-small/source/i18n/gregocal.cpp | 6 +- deps/icu-small/source/i18n/gregoimp.h | 4 +- deps/icu-small/source/i18n/indiancal.cpp | 105 +- deps/icu-small/source/i18n/indiancal.h | 49 +- deps/icu-small/source/i18n/japancal.cpp | 466 +--- deps/icu-small/source/i18n/japancal.h | 14 +- .../source/{common => i18n}/listformatter.cpp | 154 +- deps/icu-small/source/i18n/measfmt.cpp | 35 +- deps/icu-small/source/i18n/measunit.cpp | 112 +- deps/icu-small/source/i18n/msgfmt.cpp | 2 +- deps/icu-small/source/i18n/nfrule.cpp | 104 +- deps/icu-small/source/i18n/nfrule.h | 2 +- deps/icu-small/source/i18n/number_compact.cpp | 4 +- .../source/i18n/number_decimalquantity.cpp | 27 +- .../source/i18n/number_decimfmtprops.cpp | 1 + deps/icu-small/source/i18n/number_fluent.cpp | 31 +- .../source/i18n/number_formatimpl.cpp | 128 +- .../icu-small/source/i18n/number_formatimpl.h | 52 +- .../icu-small/source/i18n/number_grouping.cpp | 2 +- .../source/i18n/number_longnames.cpp | 52 +- deps/icu-small/source/i18n/number_longnames.h | 17 +- deps/icu-small/source/i18n/number_mapper.cpp | 16 +- .../source/i18n/number_modifiers.cpp | 178 +- deps/icu-small/source/i18n/number_modifiers.h | 155 +- .../source/i18n/number_multiplier.cpp | 8 +- .../icu-small/source/i18n/number_multiplier.h | 4 +- deps/icu-small/source/i18n/number_padding.cpp | 2 +- .../source/i18n/number_patternmodifier.cpp | 111 +- .../source/i18n/number_patternmodifier.h | 38 +- .../source/i18n/number_scientific.cpp | 34 +- .../icu-small/source/i18n/number_scientific.h | 10 +- .../source/i18n/number_stringbuilder.cpp | 12 + .../source/i18n/number_stringbuilder.h | 2 + deps/icu-small/source/i18n/number_types.h | 58 +- deps/icu-small/source/i18n/numfmt.cpp | 50 +- .../source/i18n/numparse_currency.cpp | 4 +- deps/icu-small/source/i18n/numparse_impl.cpp | 4 +- .../source/i18n/numparse_scientific.cpp | 5 + .../icu-small/source/i18n/numrange_fluent.cpp | 472 ++++ deps/icu-small/source/i18n/numrange_impl.cpp | 486 ++++ deps/icu-small/source/i18n/numrange_impl.h | 114 + deps/icu-small/source/i18n/numsys.cpp | 144 +- deps/icu-small/source/i18n/numsys_impl.h | 2 +- deps/icu-small/source/i18n/olsontz.cpp | 6 +- deps/icu-small/source/i18n/plurrule.cpp | 456 ++-- deps/icu-small/source/i18n/plurrule_impl.h | 52 +- deps/icu-small/source/i18n/rbnf.cpp | 183 +- deps/icu-small/source/i18n/rbt.h | 258 +-- deps/icu-small/source/i18n/rbt_pars.cpp | 12 +- deps/icu-small/source/i18n/regexcmp.cpp | 361 +-- deps/icu-small/source/i18n/region.cpp | 56 +- deps/icu-small/source/i18n/reldatefmt.cpp | 247 +- deps/icu-small/source/i18n/reldtfmt.cpp | 6 +- deps/icu-small/source/i18n/reldtfmt.h | 1 - deps/icu-small/source/i18n/rematch.cpp | 74 +- .../source/i18n/rulebasedcollator.cpp | 10 +- deps/icu-small/source/i18n/scriptset.cpp | 2 +- .../source/i18n/shareddateformatsymbols.h | 5 + deps/icu-small/source/i18n/smpdtfmt.cpp | 66 +- deps/icu-small/source/i18n/timezone.cpp | 10 +- deps/icu-small/source/i18n/transreg.cpp | 6 +- deps/icu-small/source/i18n/tzfmt.cpp | 6 +- deps/icu-small/source/i18n/tzgnames.cpp | 2 +- deps/icu-small/source/i18n/tznames.cpp | 2 +- deps/icu-small/source/i18n/tznames_impl.cpp | 14 +- deps/icu-small/source/i18n/ucln_in.h | 2 + deps/icu-small/source/i18n/ucol_res.cpp | 14 +- deps/icu-small/source/i18n/udat.cpp | 2 +- .../{common => i18n}/ulistformatter.cpp | 0 deps/icu-small/source/i18n/ulocdata.cpp | 2 +- .../source/i18n/unicode/alphaindex.h | 11 +- deps/icu-small/source/i18n/unicode/calendar.h | 161 +- deps/icu-small/source/i18n/unicode/coll.h | 14 +- .../i18n/unicode/compactdecimalformat.h | 19 +- deps/icu-small/source/i18n/unicode/currpinf.h | 15 +- deps/icu-small/source/i18n/unicode/currunit.h | 6 +- deps/icu-small/source/i18n/unicode/datefmt.h | 10 +- deps/icu-small/source/i18n/unicode/dcfmtsym.h | 8 +- deps/icu-small/source/i18n/unicode/decimfmt.h | 69 +- deps/icu-small/source/i18n/unicode/dtptngen.h | 16 +- deps/icu-small/source/i18n/unicode/fmtable.h | 2 +- deps/icu-small/source/i18n/unicode/gender.h | 7 +- .../{common => i18n}/unicode/listformatter.h | 36 +- deps/icu-small/source/i18n/unicode/measfmt.h | 14 +- deps/icu-small/source/i18n/unicode/measunit.h | 40 + deps/icu-small/source/i18n/unicode/msgfmt.h | 11 +- .../source/i18n/unicode/numberformatter.h | 119 +- .../i18n/unicode/numberrangeformatter.h | 866 +++++++ deps/icu-small/source/i18n/unicode/numfmt.h | 23 +- deps/icu-small/source/i18n/unicode/plurfmt.h | 12 - deps/icu-small/source/i18n/unicode/plurrule.h | 8 +- deps/icu-small/source/i18n/unicode/rbnf.h | 9 +- deps/icu-small/source/i18n/unicode/region.h | 2 +- .../source/i18n/unicode/reldatefmt.h | 14 +- deps/icu-small/source/i18n/unicode/smpdtfmt.h | 4 +- deps/icu-small/source/i18n/unicode/translit.h | 291 ++- deps/icu-small/source/i18n/unicode/tzfmt.h | 6 +- deps/icu-small/source/i18n/unicode/ucal.h | 13 + deps/icu-small/source/i18n/unicode/ucol.h | 3 +- deps/icu-small/source/i18n/unicode/ugender.h | 4 +- .../{common => i18n}/unicode/ulistformatter.h | 20 + .../source/i18n/unicode/unumberformatter.h | 36 +- deps/icu-small/source/i18n/unicode/usearch.h | 7 +- deps/icu-small/source/i18n/unicode/uspoof.h | 23 +- deps/icu-small/source/i18n/uregex.cpp | 4 +- deps/icu-small/source/i18n/usearch.cpp | 2 +- deps/icu-small/source/i18n/uspoof_impl.h | 2 +- deps/icu-small/source/i18n/vtzone.cpp | 2 +- deps/icu-small/source/i18n/zonemeta.cpp | 16 +- deps/icu-small/source/tools/genrb/parse.cpp | 5 + deps/icu-small/source/tools/genrb/reslist.cpp | 2 +- .../source/tools/pkgdata/pkgdata.cpp | 9 +- .../source/tools/toolutil/filestrm.cpp | 4 +- .../source/tools/toolutil/filetools.cpp | 2 +- .../source/tools/toolutil/package.cpp | 4 +- .../source/tools/toolutil/swapimpl.cpp | 10 +- .../source/tools/toolutil/udbgutil.cpp | 6 +- .../source/tools/toolutil/unewdata.cpp | 6 +- .../source/tools/toolutil/writesrc.cpp | 109 +- .../source/tools/toolutil/writesrc.h | 30 +- tools/icu/current_ver.dep | 12 +- 260 files changed, 15760 insertions(+), 6131 deletions(-) create mode 100644 deps/icu-small/source/common/characterproperties.cpp create mode 100644 deps/icu-small/source/common/ucptrie.cpp create mode 100644 deps/icu-small/source/common/ucptrie_impl.h create mode 100644 deps/icu-small/source/common/ulayout_props_data.h create mode 100644 deps/icu-small/source/common/umutablecptrie.cpp create mode 100644 deps/icu-small/source/common/unicode/ucpmap.h create mode 100644 deps/icu-small/source/common/unicode/ucptrie.h create mode 100644 deps/icu-small/source/common/unicode/umutablecptrie.h create mode 100644 deps/icu-small/source/common/utrie_swap.cpp rename deps/icu-small/source/data/in/{icudt62l.dat => icudt63l.dat} (65%) create mode 100644 deps/icu-small/source/i18n/erarules.cpp create mode 100644 deps/icu-small/source/i18n/erarules.h rename deps/icu-small/source/{common => i18n}/listformatter.cpp (71%) create mode 100644 deps/icu-small/source/i18n/numrange_fluent.cpp create mode 100644 deps/icu-small/source/i18n/numrange_impl.cpp create mode 100644 deps/icu-small/source/i18n/numrange_impl.h rename deps/icu-small/source/{common => i18n}/ulistformatter.cpp (100%) rename deps/icu-small/source/{common => i18n}/unicode/listformatter.h (79%) create mode 100644 deps/icu-small/source/i18n/unicode/numberrangeformatter.h rename deps/icu-small/source/{common => i18n}/unicode/ulistformatter.h (90%) diff --git a/deps/icu-small/README-SMALL-ICU.txt b/deps/icu-small/README-SMALL-ICU.txt index b98a528485653b..2ff8a36061cfad 100644 --- a/deps/icu-small/README-SMALL-ICU.txt +++ b/deps/icu-small/README-SMALL-ICU.txt @@ -1,8 +1,8 @@ Small ICU sources - auto generated by shrink-icu-src.py This directory contains the ICU subset used by --with-intl=small-icu (the default) -It is a strict subset of ICU 62 source files with the following exception(s): -* deps/icu-small/source/data/in/icudt62l.dat : Reduced-size data file +It is a strict subset of ICU 63 source files with the following exception(s): +* deps/icu-small/source/data/in/icudt63l.dat : Reduced-size data file To rebuild this directory, see ../../tools/icu/README.md diff --git a/deps/icu-small/source/common/bmpset.cpp b/deps/icu-small/source/common/bmpset.cpp index 35bc80dce359eb..bc79f5e5a63be1 100644 --- a/deps/icu-small/source/common/bmpset.cpp +++ b/deps/icu-small/source/common/bmpset.cpp @@ -241,13 +241,13 @@ void BMPSet::overrideIllegal() { bmpBlockBits[i]|=bits; } - mask=~(0x10001<<0xd); // Lead byte 0xED. + mask= static_cast(~(0x10001<<0xd)); // Lead byte 0xED. bits=1<<0xd; for(i=32; i<64; ++i) { // Second half of 4k block. bmpBlockBits[i]=(bmpBlockBits[i]&mask)|bits; } } else { - mask=~(0x10001<<0xd); // Lead byte 0xED. + mask= static_cast(~(0x10001<<0xd)); // Lead byte 0xED. for(i=32; i<64; ++i) { // Second half of 4k block. bmpBlockBits[i]&=mask; } diff --git a/deps/icu-small/source/common/bytesinkutil.cpp b/deps/icu-small/source/common/bytesinkutil.cpp index 6af7ddfd597638..c64a845f87538e 100644 --- a/deps/icu-small/source/common/bytesinkutil.cpp +++ b/deps/icu-small/source/common/bytesinkutil.cpp @@ -11,6 +11,7 @@ #include "unicode/utf8.h" #include "unicode/utf16.h" #include "bytesinkutil.h" +#include "charstr.h" #include "cmemory.h" #include "uassert.h" @@ -120,4 +121,41 @@ ByteSinkUtil::appendUnchanged(const uint8_t *s, const uint8_t *limit, return TRUE; } +CharStringByteSink::CharStringByteSink(CharString* dest) : dest_(*dest) { +} + +CharStringByteSink::~CharStringByteSink() = default; + +void +CharStringByteSink::Append(const char* bytes, int32_t n) { + UErrorCode status = U_ZERO_ERROR; + dest_.append(bytes, n, status); + // Any errors are silently ignored. +} + +char* +CharStringByteSink::GetAppendBuffer(int32_t min_capacity, + int32_t desired_capacity_hint, + char* scratch, + int32_t scratch_capacity, + int32_t* result_capacity) { + if (min_capacity < 1 || scratch_capacity < min_capacity) { + *result_capacity = 0; + return nullptr; + } + + UErrorCode status = U_ZERO_ERROR; + char* result = dest_.getAppendBuffer( + min_capacity, + desired_capacity_hint, + *result_capacity, + status); + if (U_SUCCESS(status)) { + return result; + } + + *result_capacity = scratch_capacity; + return scratch; +} + U_NAMESPACE_END diff --git a/deps/icu-small/source/common/bytesinkutil.h b/deps/icu-small/source/common/bytesinkutil.h index 8287ffea4ca713..69e4cbcd263932 100644 --- a/deps/icu-small/source/common/bytesinkutil.h +++ b/deps/icu-small/source/common/bytesinkutil.h @@ -13,6 +13,7 @@ U_NAMESPACE_BEGIN class ByteSink; +class CharString; class Edits; class U_COMMON_API ByteSinkUtil { @@ -58,4 +59,25 @@ class U_COMMON_API ByteSinkUtil { ByteSink &sink, uint32_t options, Edits *edits); }; +class CharStringByteSink : public ByteSink { +public: + CharStringByteSink(CharString* dest); + ~CharStringByteSink() override; + + CharStringByteSink() = delete; + CharStringByteSink(const CharStringByteSink&) = delete; + CharStringByteSink& operator=(const CharStringByteSink&) = delete; + + void Append(const char* bytes, int32_t n) override; + + char* GetAppendBuffer(int32_t min_capacity, + int32_t desired_capacity_hint, + char* scratch, + int32_t scratch_capacity, + int32_t* result_capacity) override; + +private: + CharString& dest_; +}; + U_NAMESPACE_END diff --git a/deps/icu-small/source/common/bytestriebuilder.cpp b/deps/icu-small/source/common/bytestriebuilder.cpp index 581505e0092b15..ec1ab7d8f5080e 100644 --- a/deps/icu-small/source/common/bytestriebuilder.cpp +++ b/deps/icu-small/source/common/bytestriebuilder.cpp @@ -339,7 +339,8 @@ BytesTrieBuilder::indexOfElementWithNextUnit(int32_t i, int32_t byteIndex, UChar BytesTrieBuilder::BTLinearMatchNode::BTLinearMatchNode(const char *bytes, int32_t len, Node *nextNode) : LinearMatchNode(len, nextNode), s(bytes) { - hash=hash*37+ustr_hashCharsN(bytes, len); + hash=static_cast( + static_cast(hash)*37u + static_cast(ustr_hashCharsN(bytes, len))); } UBool diff --git a/deps/icu-small/source/common/characterproperties.cpp b/deps/icu-small/source/common/characterproperties.cpp new file mode 100644 index 00000000000000..3aff85b3f1193e --- /dev/null +++ b/deps/icu-small/source/common/characterproperties.cpp @@ -0,0 +1,336 @@ +// © 2018 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html + +// characterproperties.cpp +// created: 2018sep03 Markus W. Scherer + +#include "unicode/utypes.h" +#include "unicode/localpointer.h" +#include "unicode/uchar.h" +#include "unicode/ucpmap.h" +#include "unicode/ucptrie.h" +#include "unicode/umutablecptrie.h" +#include "unicode/uniset.h" +#include "unicode/uscript.h" +#include "unicode/uset.h" +#include "cmemory.h" +#include "mutex.h" +#include "normalizer2impl.h" +#include "uassert.h" +#include "ubidi_props.h" +#include "ucase.h" +#include "ucln_cmn.h" +#include "umutex.h" +#include "uprops.h" + +using icu::UInitOnce; +using icu::UnicodeSet; + +namespace { + +UBool U_CALLCONV characterproperties_cleanup(); + +struct Inclusion { + UnicodeSet *fSet; + UInitOnce fInitOnce; +}; +Inclusion gInclusions[UPROPS_SRC_COUNT]; // cached getInclusions() + +UnicodeSet *sets[UCHAR_BINARY_LIMIT] = {}; + +UCPMap *maps[UCHAR_INT_LIMIT - UCHAR_INT_START] = {}; + +UMutex cpMutex = U_MUTEX_INITIALIZER; + +//---------------------------------------------------------------- +// Inclusions list +//---------------------------------------------------------------- + +// USetAdder implementation +// Does not use uset.h to reduce code dependencies +void U_CALLCONV +_set_add(USet *set, UChar32 c) { + ((UnicodeSet *)set)->add(c); +} + +void U_CALLCONV +_set_addRange(USet *set, UChar32 start, UChar32 end) { + ((UnicodeSet *)set)->add(start, end); +} + +void U_CALLCONV +_set_addString(USet *set, const UChar *str, int32_t length) { + ((UnicodeSet *)set)->add(icu::UnicodeString((UBool)(length<0), str, length)); +} + +UBool U_CALLCONV characterproperties_cleanup() { + for (Inclusion &in: gInclusions) { + delete in.fSet; + in.fSet = nullptr; + in.fInitOnce.reset(); + } + for (int32_t i = 0; i < UPRV_LENGTHOF(sets); ++i) { + delete sets[i]; + sets[i] = nullptr; + } + for (int32_t i = 0; i < UPRV_LENGTHOF(maps); ++i) { + ucptrie_close(reinterpret_cast(maps[i])); + maps[i] = nullptr; + } + return TRUE; +} + +} // namespace + +U_NAMESPACE_BEGIN + +/* +Reduce excessive reallocation, and make it easier to detect initialization problems. +Usually you don't see smaller sets than this for Unicode 5.0. +*/ +constexpr int32_t DEFAULT_INCLUSION_CAPACITY = 3072; + +void U_CALLCONV CharacterProperties::initInclusion(UPropertySource src, UErrorCode &errorCode) { + // This function is invoked only via umtx_initOnce(). + // This function is a friend of class UnicodeSet. + + U_ASSERT(0 <= src && src < UPROPS_SRC_COUNT); + if (src == UPROPS_SRC_NONE) { + errorCode = U_INTERNAL_PROGRAM_ERROR; + return; + } + UnicodeSet * &incl = gInclusions[src].fSet; + U_ASSERT(incl == nullptr); + + incl = new UnicodeSet(); + if (incl == nullptr) { + errorCode = U_MEMORY_ALLOCATION_ERROR; + return; + } + USetAdder sa = { + (USet *)incl, + _set_add, + _set_addRange, + _set_addString, + nullptr, // don't need remove() + nullptr // don't need removeRange() + }; + + incl->ensureCapacity(DEFAULT_INCLUSION_CAPACITY, errorCode); + switch(src) { + case UPROPS_SRC_CHAR: + uchar_addPropertyStarts(&sa, &errorCode); + break; + case UPROPS_SRC_PROPSVEC: + upropsvec_addPropertyStarts(&sa, &errorCode); + break; + case UPROPS_SRC_CHAR_AND_PROPSVEC: + uchar_addPropertyStarts(&sa, &errorCode); + upropsvec_addPropertyStarts(&sa, &errorCode); + break; +#if !UCONFIG_NO_NORMALIZATION + case UPROPS_SRC_CASE_AND_NORM: { + const Normalizer2Impl *impl=Normalizer2Factory::getNFCImpl(errorCode); + if(U_SUCCESS(errorCode)) { + impl->addPropertyStarts(&sa, errorCode); + } + ucase_addPropertyStarts(&sa, &errorCode); + break; + } + case UPROPS_SRC_NFC: { + const Normalizer2Impl *impl=Normalizer2Factory::getNFCImpl(errorCode); + if(U_SUCCESS(errorCode)) { + impl->addPropertyStarts(&sa, errorCode); + } + break; + } + case UPROPS_SRC_NFKC: { + const Normalizer2Impl *impl=Normalizer2Factory::getNFKCImpl(errorCode); + if(U_SUCCESS(errorCode)) { + impl->addPropertyStarts(&sa, errorCode); + } + break; + } + case UPROPS_SRC_NFKC_CF: { + const Normalizer2Impl *impl=Normalizer2Factory::getNFKC_CFImpl(errorCode); + if(U_SUCCESS(errorCode)) { + impl->addPropertyStarts(&sa, errorCode); + } + break; + } + case UPROPS_SRC_NFC_CANON_ITER: { + const Normalizer2Impl *impl=Normalizer2Factory::getNFCImpl(errorCode); + if(U_SUCCESS(errorCode)) { + impl->addCanonIterPropertyStarts(&sa, errorCode); + } + break; + } +#endif + case UPROPS_SRC_CASE: + ucase_addPropertyStarts(&sa, &errorCode); + break; + case UPROPS_SRC_BIDI: + ubidi_addPropertyStarts(&sa, &errorCode); + break; + case UPROPS_SRC_INPC: + case UPROPS_SRC_INSC: + case UPROPS_SRC_VO: + uprops_addPropertyStarts((UPropertySource)src, &sa, &errorCode); + break; + default: + errorCode = U_INTERNAL_PROGRAM_ERROR; + break; + } + + if (U_FAILURE(errorCode)) { + delete incl; + incl = nullptr; + return; + } + // Compact for caching + incl->compact(); + ucln_common_registerCleanup(UCLN_COMMON_CHARACTERPROPERTIES, characterproperties_cleanup); +} + +const UnicodeSet *getInclusionsForSource(UPropertySource src, UErrorCode &errorCode) { + if (U_FAILURE(errorCode)) { return nullptr; } + if (src < 0 || UPROPS_SRC_COUNT <= src) { + errorCode = U_ILLEGAL_ARGUMENT_ERROR; + return nullptr; + } + Inclusion &i = gInclusions[src]; + umtx_initOnce(i.fInitOnce, &CharacterProperties::initInclusion, src, errorCode); + return i.fSet; +} + +const UnicodeSet *CharacterProperties::getInclusionsForProperty( + UProperty prop, UErrorCode &errorCode) { + if (U_FAILURE(errorCode)) { return nullptr; } + UPropertySource src = uprops_getSource(prop); + return getInclusionsForSource(src, errorCode); +} + +U_NAMESPACE_END + +namespace { + +UnicodeSet *makeSet(UProperty property, UErrorCode &errorCode) { + if (U_FAILURE(errorCode)) { return nullptr; } + icu::LocalPointer set(new UnicodeSet()); + if (set.isNull()) { + errorCode = U_MEMORY_ALLOCATION_ERROR; + return nullptr; + } + const UnicodeSet *inclusions = + icu::CharacterProperties::getInclusionsForProperty(property, errorCode); + if (U_FAILURE(errorCode)) { return nullptr; } + int32_t numRanges = inclusions->getRangeCount(); + UChar32 startHasProperty = -1; + + for (int32_t i = 0; i < numRanges; ++i) { + UChar32 rangeEnd = inclusions->getRangeEnd(i); + for (UChar32 c = inclusions->getRangeStart(i); c <= rangeEnd; ++c) { + // TODO: Get a UCharacterProperty.BinaryProperty to avoid the property dispatch. + if (u_hasBinaryProperty(c, property)) { + if (startHasProperty < 0) { + // Transition from false to true. + startHasProperty = c; + } + } else if (startHasProperty >= 0) { + // Transition from true to false. + set->add(startHasProperty, c - 1); + startHasProperty = -1; + } + } + } + if (startHasProperty >= 0) { + set->add(startHasProperty, 0x10FFFF); + } + set->freeze(); + return set.orphan(); +} + +UCPMap *makeMap(UProperty property, UErrorCode &errorCode) { + if (U_FAILURE(errorCode)) { return nullptr; } + uint32_t nullValue = property == UCHAR_SCRIPT ? USCRIPT_UNKNOWN : 0; + icu::LocalUMutableCPTriePointer mutableTrie( + umutablecptrie_open(nullValue, nullValue, &errorCode)); + const UnicodeSet *inclusions = + icu::CharacterProperties::getInclusionsForProperty(property, errorCode); + if (U_FAILURE(errorCode)) { return nullptr; } + int32_t numRanges = inclusions->getRangeCount(); + UChar32 start = 0; + uint32_t value = nullValue; + + for (int32_t i = 0; i < numRanges; ++i) { + UChar32 rangeEnd = inclusions->getRangeEnd(i); + for (UChar32 c = inclusions->getRangeStart(i); c <= rangeEnd; ++c) { + // TODO: Get a UCharacterProperty.IntProperty to avoid the property dispatch. + uint32_t nextValue = u_getIntPropertyValue(c, property); + if (value != nextValue) { + if (value != nullValue) { + umutablecptrie_setRange(mutableTrie.getAlias(), start, c - 1, value, &errorCode); + } + start = c; + value = nextValue; + } + } + } + if (value != 0) { + umutablecptrie_setRange(mutableTrie.getAlias(), start, 0x10FFFF, value, &errorCode); + } + + UCPTrieType type; + if (property == UCHAR_BIDI_CLASS || property == UCHAR_GENERAL_CATEGORY) { + type = UCPTRIE_TYPE_FAST; + } else { + type = UCPTRIE_TYPE_SMALL; + } + UCPTrieValueWidth valueWidth; + // TODO: UCharacterProperty.IntProperty + int32_t max = u_getIntPropertyMaxValue(property); + if (max <= 0xff) { + valueWidth = UCPTRIE_VALUE_BITS_8; + } else if (max <= 0xffff) { + valueWidth = UCPTRIE_VALUE_BITS_16; + } else { + valueWidth = UCPTRIE_VALUE_BITS_32; + } + return reinterpret_cast( + umutablecptrie_buildImmutable(mutableTrie.getAlias(), type, valueWidth, &errorCode)); +} + +} // namespace + +U_NAMESPACE_USE + +U_CAPI const USet * U_EXPORT2 +u_getBinaryPropertySet(UProperty property, UErrorCode *pErrorCode) { + if (U_FAILURE(*pErrorCode)) { return nullptr; } + if (property < 0 || UCHAR_BINARY_LIMIT <= property) { + *pErrorCode = U_ILLEGAL_ARGUMENT_ERROR; + return nullptr; + } + Mutex m(&cpMutex); + UnicodeSet *set = sets[property]; + if (set == nullptr) { + sets[property] = set = makeSet(property, *pErrorCode); + } + if (U_FAILURE(*pErrorCode)) { return nullptr; } + return set->toUSet(); +} + +U_CAPI const UCPMap * U_EXPORT2 +u_getIntPropertyMap(UProperty property, UErrorCode *pErrorCode) { + if (U_FAILURE(*pErrorCode)) { return nullptr; } + if (property < UCHAR_INT_START || UCHAR_INT_LIMIT <= property) { + *pErrorCode = U_ILLEGAL_ARGUMENT_ERROR; + return nullptr; + } + Mutex m(&cpMutex); + UCPMap *map = maps[property - UCHAR_INT_START]; + if (map == nullptr) { + maps[property - UCHAR_INT_START] = map = makeMap(property, *pErrorCode); + } + return map; +} diff --git a/deps/icu-small/source/common/charstr.cpp b/deps/icu-small/source/common/charstr.cpp index 353f1d52542fa2..852cc539457760 100644 --- a/deps/icu-small/source/common/charstr.cpp +++ b/deps/icu-small/source/common/charstr.cpp @@ -79,7 +79,7 @@ CharString &CharString::append(const char *s, int32_t sLength, UErrorCode &error return *this; } if(sLength<0) { - sLength=uprv_strlen(s); + sLength= static_cast(uprv_strlen(s)); } if(sLength>0) { if(s==(buffer.getAlias()+len)) { @@ -126,15 +126,21 @@ char *CharString::getAppendBuffer(int32_t minCapacity, } CharString &CharString::appendInvariantChars(const UnicodeString &s, UErrorCode &errorCode) { + return appendInvariantChars(s.getBuffer(), s.length(), errorCode); +} + +CharString &CharString::appendInvariantChars(const UChar* uchars, int32_t ucharsLen, UErrorCode &errorCode) { if(U_FAILURE(errorCode)) { return *this; } - if (!uprv_isInvariantUnicodeString(s)) { + if (!uprv_isInvariantUString(uchars, ucharsLen)) { errorCode = U_INVARIANT_CONVERSION_ERROR; return *this; } - if(ensureCapacity(len+s.length()+1, 0, errorCode)) { - len+=s.extract(0, 0x7fffffff, buffer.getAlias()+len, buffer.getCapacity()-len, US_INV); + if(ensureCapacity(len+ucharsLen+1, 0, errorCode)) { + u_UCharsToChars(uchars, buffer.getAlias()+len, ucharsLen); + len += ucharsLen; + buffer[len] = 0; } return *this; } diff --git a/deps/icu-small/source/common/charstr.h b/deps/icu-small/source/common/charstr.h index 86f69c383a0b37..1a97e01988f991 100644 --- a/deps/icu-small/source/common/charstr.h +++ b/deps/icu-small/source/common/charstr.h @@ -123,6 +123,7 @@ class U_COMMON_API CharString : public UMemory { UErrorCode &errorCode); CharString &appendInvariantChars(const UnicodeString &s, UErrorCode &errorCode); + CharString &appendInvariantChars(const UChar* uchars, int32_t ucharsLen, UErrorCode& errorCode); /** * Appends a filename/path part, e.g., a directory name. diff --git a/deps/icu-small/source/common/cmemory.h b/deps/icu-small/source/common/cmemory.h index f98e13efc0ffbe..a6dd209d80b2f3 100644 --- a/deps/icu-small/source/common/cmemory.h +++ b/deps/icu-small/source/common/cmemory.h @@ -172,7 +172,7 @@ class LocalMemory : public LocalPointerBase { * @return *this */ LocalMemory &moveFrom(LocalMemory &src) U_NOEXCEPT { - delete[] LocalPointerBase::ptr; + uprv_free(LocalPointerBase::ptr); LocalPointerBase::ptr=src.ptr; src.ptr=NULL; return *this; @@ -279,6 +279,10 @@ inline T *LocalMemory::allocateInsteadAndCopy(int32_t newCapacity, int32_t le * * Unlike LocalMemory and LocalArray, this class never adopts * (takes ownership of) another array. + * + * WARNING: MaybeStackArray only works with primitive (plain-old data) types. + * It does NOT know how to call a destructor! If you work with classes with + * destructors, consider LocalArray in localpointer.h. */ template class MaybeStackArray { diff --git a/deps/icu-small/source/common/dictbe.cpp b/deps/icu-small/source/common/dictbe.cpp index 419d062ef25d44..0e4d0850fac912 100644 --- a/deps/icu-small/source/common/dictbe.cpp +++ b/deps/icu-small/source/common/dictbe.cpp @@ -325,9 +325,9 @@ ThaiBreakEngine::divideUpDictionaryRange( UText *text, // two characters after uc were not 0x0E4C THANTHAKHAT before // checking the dictionary. That is just a performance filter, // but it's not clear it's faster than checking the trie. - int32_t candidates = words[(wordsFound + 1) % THAI_LOOKAHEAD].candidates(text, fDictionary, rangeEnd); + int32_t num_candidates = words[(wordsFound + 1) % THAI_LOOKAHEAD].candidates(text, fDictionary, rangeEnd); utext_setNativeIndex(text, current + cuWordLength + chars); - if (candidates > 0) { + if (num_candidates > 0) { break; } } @@ -555,9 +555,9 @@ LaoBreakEngine::divideUpDictionaryRange( UText *text, if (fEndWordSet.contains(pc) && fBeginWordSet.contains(uc)) { // Maybe. See if it's in the dictionary. // TODO: this looks iffy; compare with old code. - int32_t candidates = words[(wordsFound + 1) % LAO_LOOKAHEAD].candidates(text, fDictionary, rangeEnd); + int32_t num_candidates = words[(wordsFound + 1) % LAO_LOOKAHEAD].candidates(text, fDictionary, rangeEnd); utext_setNativeIndex(text, current + cuWordLength + chars); - if (candidates > 0) { + if (num_candidates > 0) { break; } } @@ -748,9 +748,9 @@ BurmeseBreakEngine::divideUpDictionaryRange( UText *text, if (fEndWordSet.contains(pc) && fBeginWordSet.contains(uc)) { // Maybe. See if it's in the dictionary. // TODO: this looks iffy; compare with old code. - int32_t candidates = words[(wordsFound + 1) % BURMESE_LOOKAHEAD].candidates(text, fDictionary, rangeEnd); + int32_t num_candidates = words[(wordsFound + 1) % BURMESE_LOOKAHEAD].candidates(text, fDictionary, rangeEnd); utext_setNativeIndex(text, current + cuWordLength + chars); - if (candidates > 0) { + if (num_candidates > 0) { break; } } @@ -953,9 +953,9 @@ KhmerBreakEngine::divideUpDictionaryRange( UText *text, uc = utext_current32(text); if (fEndWordSet.contains(pc) && fBeginWordSet.contains(uc)) { // Maybe. See if it's in the dictionary. - int32_t candidates = words[(wordsFound + 1) % KHMER_LOOKAHEAD].candidates(text, fDictionary, rangeEnd); + int32_t num_candidates = words[(wordsFound + 1) % KHMER_LOOKAHEAD].candidates(text, fDictionary, rangeEnd); utext_setNativeIndex(text, current+cuWordLength+chars); - if (candidates > 0) { + if (num_candidates > 0) { break; } } diff --git a/deps/icu-small/source/common/edits.cpp b/deps/icu-small/source/common/edits.cpp index 3b3611fcf80cfe..00a8d601a1cc80 100644 --- a/deps/icu-small/source/common/edits.cpp +++ b/deps/icu-small/source/common/edits.cpp @@ -276,7 +276,7 @@ Edits &Edits::mergeAndAppend(const Edits &ab, const Edits &bc, UErrorCode &error // ab deletions meet bc insertions at the same intermediate-string index. // Some users expect the bc insertions to come first, so we fetch from bc first. if (bc_bLength == 0) { - if (bcHasNext && (bcHasNext = bcIter.next(errorCode))) { + if (bcHasNext && (bcHasNext = bcIter.next(errorCode)) != 0) { bc_bLength = bcIter.oldLength(); cLength = bcIter.newLength(); if (bc_bLength == 0) { @@ -293,7 +293,7 @@ Edits &Edits::mergeAndAppend(const Edits &ab, const Edits &bc, UErrorCode &error // else see if the other iterator is done, too. } if (ab_bLength == 0) { - if (abHasNext && (abHasNext = abIter.next(errorCode))) { + if (abHasNext && (abHasNext = abIter.next(errorCode)) != 0) { aLength = abIter.oldLength(); ab_bLength = abIter.newLength(); if (ab_bLength == 0) { diff --git a/deps/icu-small/source/common/loadednormalizer2impl.cpp b/deps/icu-small/source/common/loadednormalizer2impl.cpp index 6fb9b816dc6591..82cb325b723311 100644 --- a/deps/icu-small/source/common/loadednormalizer2impl.cpp +++ b/deps/icu-small/source/common/loadednormalizer2impl.cpp @@ -18,6 +18,7 @@ #include "unicode/udata.h" #include "unicode/localpointer.h" #include "unicode/normalizer2.h" +#include "unicode/ucptrie.h" #include "unicode/unistr.h" #include "unicode/unorm.h" #include "cstring.h" @@ -42,12 +43,12 @@ class LoadedNormalizer2Impl : public Normalizer2Impl { isAcceptable(void *context, const char *type, const char *name, const UDataInfo *pInfo); UDataMemory *memory; - UTrie2 *ownedTrie; + UCPTrie *ownedTrie; }; LoadedNormalizer2Impl::~LoadedNormalizer2Impl() { udata_close(memory); - utrie2_close(ownedTrie); + ucptrie_close(ownedTrie); } UBool U_CALLCONV @@ -62,7 +63,7 @@ LoadedNormalizer2Impl::isAcceptable(void * /*context*/, pInfo->dataFormat[1]==0x72 && pInfo->dataFormat[2]==0x6d && pInfo->dataFormat[3]==0x32 && - pInfo->formatVersion[0]==3 + pInfo->formatVersion[0]==4 ) { // Normalizer2Impl *me=(Normalizer2Impl *)context; // uprv_memcpy(me->dataVersion, pInfo->dataVersion, 4); @@ -91,9 +92,9 @@ LoadedNormalizer2Impl::load(const char *packageName, const char *name, UErrorCod int32_t offset=inIndexes[IX_NORM_TRIE_OFFSET]; int32_t nextOffset=inIndexes[IX_EXTRA_DATA_OFFSET]; - ownedTrie=utrie2_openFromSerialized(UTRIE2_16_VALUE_BITS, - inBytes+offset, nextOffset-offset, NULL, - &errorCode); + ownedTrie=ucptrie_openFromBinary(UCPTRIE_TYPE_FAST, UCPTRIE_VALUE_BITS_16, + inBytes+offset, nextOffset-offset, NULL, + &errorCode); if(U_FAILURE(errorCode)) { return; } @@ -131,15 +132,26 @@ U_CDECL_BEGIN static UBool U_CALLCONV uprv_loaded_normalizer2_cleanup(); U_CDECL_END -static Norm2AllModes *nfkcSingleton; -static Norm2AllModes *nfkc_cfSingleton; -static UHashtable *cache=NULL; +#if !NORM2_HARDCODE_NFC_DATA +static Norm2AllModes *nfcSingleton; +static icu::UInitOnce nfcInitOnce = U_INITONCE_INITIALIZER; +#endif +static Norm2AllModes *nfkcSingleton; static icu::UInitOnce nfkcInitOnce = U_INITONCE_INITIALIZER; + +static Norm2AllModes *nfkc_cfSingleton; static icu::UInitOnce nfkc_cfInitOnce = U_INITONCE_INITIALIZER; +static UHashtable *cache=NULL; + // UInitOnce singleton initialization function static void U_CALLCONV initSingletons(const char *what, UErrorCode &errorCode) { +#if !NORM2_HARDCODE_NFC_DATA + if (uprv_strcmp(what, "nfc") == 0) { + nfcSingleton = Norm2AllModes::createInstance(NULL, "nfc", errorCode); + } else +#endif if (uprv_strcmp(what, "nfkc") == 0) { nfkcSingleton = Norm2AllModes::createInstance(NULL, "nfkc", errorCode); } else if (uprv_strcmp(what, "nfkc_cf") == 0) { @@ -157,19 +169,36 @@ static void U_CALLCONV deleteNorm2AllModes(void *allModes) { } static UBool U_CALLCONV uprv_loaded_normalizer2_cleanup() { +#if !NORM2_HARDCODE_NFC_DATA + delete nfcSingleton; + nfcSingleton = NULL; + nfcInitOnce.reset(); +#endif + delete nfkcSingleton; nfkcSingleton = NULL; + nfkcInitOnce.reset(); + delete nfkc_cfSingleton; nfkc_cfSingleton = NULL; + nfkc_cfInitOnce.reset(); + uhash_close(cache); cache=NULL; - nfkcInitOnce.reset(); - nfkc_cfInitOnce.reset(); return TRUE; } U_CDECL_END +#if !NORM2_HARDCODE_NFC_DATA +const Norm2AllModes * +Norm2AllModes::getNFCInstance(UErrorCode &errorCode) { + if(U_FAILURE(errorCode)) { return NULL; } + umtx_initOnce(nfcInitOnce, &initSingletons, "nfc", errorCode); + return nfcSingleton; +} +#endif + const Norm2AllModes * Norm2AllModes::getNFKCInstance(UErrorCode &errorCode) { if(U_FAILURE(errorCode)) { return NULL; } @@ -184,6 +213,36 @@ Norm2AllModes::getNFKC_CFInstance(UErrorCode &errorCode) { return nfkc_cfSingleton; } +#if !NORM2_HARDCODE_NFC_DATA +const Normalizer2 * +Normalizer2::getNFCInstance(UErrorCode &errorCode) { + const Norm2AllModes *allModes=Norm2AllModes::getNFCInstance(errorCode); + return allModes!=NULL ? &allModes->comp : NULL; +} + +const Normalizer2 * +Normalizer2::getNFDInstance(UErrorCode &errorCode) { + const Norm2AllModes *allModes=Norm2AllModes::getNFCInstance(errorCode); + return allModes!=NULL ? &allModes->decomp : NULL; +} + +const Normalizer2 *Normalizer2Factory::getFCDInstance(UErrorCode &errorCode) { + const Norm2AllModes *allModes=Norm2AllModes::getNFCInstance(errorCode); + return allModes!=NULL ? &allModes->fcd : NULL; +} + +const Normalizer2 *Normalizer2Factory::getFCCInstance(UErrorCode &errorCode) { + const Norm2AllModes *allModes=Norm2AllModes::getNFCInstance(errorCode); + return allModes!=NULL ? &allModes->fcc : NULL; +} + +const Normalizer2Impl * +Normalizer2Factory::getNFCImpl(UErrorCode &errorCode) { + const Norm2AllModes *allModes=Norm2AllModes::getNFCInstance(errorCode); + return allModes!=NULL ? allModes->impl : NULL; +} +#endif + const Normalizer2 * Normalizer2::getNFKCInstance(UErrorCode &errorCode) { const Norm2AllModes *allModes=Norm2AllModes::getNFKCInstance(errorCode); @@ -247,7 +306,7 @@ Normalizer2::getInstance(const char *packageName, } void *temp=uhash_get(cache, name); if(temp==NULL) { - int32_t keyLength=uprv_strlen(name)+1; + int32_t keyLength= static_cast(uprv_strlen(name)+1); char *nameCopy=(char *)uprv_malloc(keyLength); if(nameCopy==NULL) { errorCode=U_MEMORY_ALLOCATION_ERROR; diff --git a/deps/icu-small/source/common/locdspnm.cpp b/deps/icu-small/source/common/locdspnm.cpp index 6ceb6cfc8bc653..2d9389e910a2ab 100644 --- a/deps/icu-small/source/common/locdspnm.cpp +++ b/deps/icu-small/source/common/locdspnm.cpp @@ -45,9 +45,9 @@ static int32_t ncat(char *buffer, uint32_t buflen, ...) { } va_start(args, buflen); - while ((str = va_arg(args, char *))) { + while ((str = va_arg(args, char *)) != 0) { char c; - while (p != e && (c = *str++)) { + while (p != e && (c = *str++) != 0) { *p++ = c; } } @@ -98,7 +98,7 @@ ICUDataTable::ICUDataTable(const char* path, const Locale& locale) : path(NULL), locale(Locale::getRoot()) { if (path) { - int32_t len = uprv_strlen(path); + int32_t len = static_cast(uprv_strlen(path)); this->path = (const char*) uprv_malloc(len + 1); if (this->path) { uprv_strcpy((char *)this->path, path); @@ -560,21 +560,21 @@ LocaleDisplayNamesImpl::adjustForUsageAndContext(CapContextUsage usage, } UnicodeString& -LocaleDisplayNamesImpl::localeDisplayName(const Locale& locale, +LocaleDisplayNamesImpl::localeDisplayName(const Locale& loc, UnicodeString& result) const { - if (locale.isBogus()) { + if (loc.isBogus()) { result.setToBogus(); return result; } UnicodeString resultName; - const char* lang = locale.getLanguage(); + const char* lang = loc.getLanguage(); if (uprv_strlen(lang) == 0) { lang = "root"; } - const char* script = locale.getScript(); - const char* country = locale.getCountry(); - const char* variant = locale.getVariant(); + const char* script = loc.getScript(); + const char* country = loc.getCountry(); + const char* variant = loc.getVariant(); UBool hasScript = uprv_strlen(script) > 0; UBool hasCountry = uprv_strlen(country) > 0; @@ -630,14 +630,14 @@ LocaleDisplayNamesImpl::localeDisplayName(const Locale& locale, resultRemainder.findAndReplace(formatOpenParen, formatReplaceOpenParen); resultRemainder.findAndReplace(formatCloseParen, formatReplaceCloseParen); - LocalPointer e(locale.createKeywords(status)); + LocalPointer e(loc.createKeywords(status)); if (e.isValid() && U_SUCCESS(status)) { UnicodeString temp2; char value[ULOC_KEYWORD_AND_VALUES_CAPACITY]; // sigh, no ULOC_VALUE_CAPACITY const char* key; while ((key = e->next((int32_t *)0, status)) != NULL) { value[0] = 0; - locale.getKeywordValue(key, value, ULOC_KEYWORD_AND_VALUES_CAPACITY, status); + loc.getKeywordValue(key, value, ULOC_KEYWORD_AND_VALUES_CAPACITY, status); if (U_FAILURE(status) || status == U_STRING_NOT_TERMINATED_WARNING) { return result; } diff --git a/deps/icu-small/source/common/locid.cpp b/deps/icu-small/source/common/locid.cpp index 36508acaf5ca70..e0dcc8a88ec0ec 100644 --- a/deps/icu-small/source/common/locid.cpp +++ b/deps/icu-small/source/common/locid.cpp @@ -31,9 +31,12 @@ ****************************************************************************** */ +#include +#include "unicode/bytestream.h" #include "unicode/locid.h" #include "unicode/strenum.h" +#include "unicode/stringpiece.h" #include "unicode/uloc.h" #include "putilimp.h" #include "mutex.h" @@ -43,9 +46,11 @@ #include "cstring.h" #include "uassert.h" #include "uhash.h" +#include "ulocimp.h" #include "ucln_cmn.h" #include "ustr_imp.h" #include "charstr.h" +#include "bytesinkutil.h" U_CDECL_BEGIN static UBool U_CALLCONV locale_cleanup(void); @@ -424,49 +429,70 @@ Locale::Locale(const Locale &other) *this = other; } -Locale &Locale::operator=(const Locale &other) -{ +Locale::Locale(Locale&& other) U_NOEXCEPT + : UObject(other), fullName(fullNameBuffer), baseName(fullName) { + *this = std::move(other); +} + +Locale& Locale::operator=(const Locale& other) { if (this == &other) { return *this; } - /* Free our current storage */ - if (baseName != fullName) { - uprv_free(baseName); + setToBogus(); + + if (other.fullName == other.fullNameBuffer) { + uprv_strcpy(fullNameBuffer, other.fullNameBuffer); + } else if (other.fullName == nullptr) { + fullName = nullptr; + } else { + fullName = uprv_strdup(other.fullName); + if (fullName == nullptr) return *this; } - baseName = NULL; - if(fullName != fullNameBuffer) { - uprv_free(fullName); - fullName = fullNameBuffer; + + if (other.baseName == other.fullName) { + baseName = fullName; + } else if (other.baseName != nullptr) { + baseName = uprv_strdup(other.baseName); + if (baseName == nullptr) return *this; } - /* Allocate the full name if necessary */ - if(other.fullName != other.fullNameBuffer) { - fullName = (char *)uprv_malloc(sizeof(char)*(uprv_strlen(other.fullName)+1)); - if (fullName == NULL) { - return *this; - } + uprv_strcpy(language, other.language); + uprv_strcpy(script, other.script); + uprv_strcpy(country, other.country); + + variantBegin = other.variantBegin; + fIsBogus = other.fIsBogus; + + return *this; +} + +Locale& Locale::operator=(Locale&& other) U_NOEXCEPT { + if (baseName != fullName) uprv_free(baseName); + if (fullName != fullNameBuffer) uprv_free(fullName); + + if (other.fullName == other.fullNameBuffer) { + uprv_strcpy(fullNameBuffer, other.fullNameBuffer); + fullName = fullNameBuffer; + } else { + fullName = other.fullName; } - /* Copy the full name */ - uprv_strcpy(fullName, other.fullName); - /* Copy the baseName if it differs from fullName. */ if (other.baseName == other.fullName) { baseName = fullName; } else { - if (other.baseName) { - baseName = uprv_strdup(other.baseName); - } + baseName = other.baseName; } - /* Copy the language and country fields */ uprv_strcpy(language, other.language); uprv_strcpy(script, other.script); uprv_strcpy(country, other.country); - /* The variantBegin is an offset, just copy it */ variantBegin = other.variantBegin; fIsBogus = other.fIsBogus; + + other.baseName = other.fullName = other.fullNameBuffer; + return *this; } @@ -545,7 +571,7 @@ Locale& Locale::init(const char* localeID, UBool canonicalize) /* after uloc_getName/canonicalize() we know that only '_' are separators */ separator = field[0] = fullName; fieldIdx = 1; - while ((separator = uprv_strchr(field[fieldIdx-1], SEP_CHAR)) && fieldIdx < UPRV_LENGTHOF(field)-1) { + while ((separator = uprv_strchr(field[fieldIdx-1], SEP_CHAR)) != 0 && fieldIdx < UPRV_LENGTHOF(field)-1) { field[fieldIdx] = separator + 1; fieldLen[fieldIdx-1] = (int32_t)(separator - field[fieldIdx-1]); fieldIdx++; @@ -652,7 +678,7 @@ Locale::initBaseName(UErrorCode &status) { int32_t Locale::hashCode() const { - return ustr_hashCharsN(fullName, uprv_strlen(fullName)); + return ustr_hashCharsN(fullName, static_cast(uprv_strlen(fullName))); } void @@ -704,6 +730,276 @@ Locale::setDefault( const Locale& newLocale, locale_set_default_internal(localeID, status); } +void +Locale::addLikelySubtags(UErrorCode& status) { + if (U_FAILURE(status)) { + return; + } + + // The maximized locale ID string is often longer, but there is no good + // heuristic to estimate just how much longer. Leave that to CharString. + CharString maximizedLocaleID; + int32_t maximizedLocaleIDCapacity = static_cast(uprv_strlen(fullName)); + + char* buffer; + int32_t reslen; + + for (;;) { + buffer = maximizedLocaleID.getAppendBuffer( + /*minCapacity=*/maximizedLocaleIDCapacity, + /*desiredCapacityHint=*/maximizedLocaleIDCapacity, + maximizedLocaleIDCapacity, + status); + + if (U_FAILURE(status)) { + return; + } + + reslen = uloc_addLikelySubtags( + fullName, + buffer, + maximizedLocaleIDCapacity, + &status); + + if (status != U_BUFFER_OVERFLOW_ERROR) { + break; + } + + maximizedLocaleIDCapacity = reslen; + status = U_ZERO_ERROR; + } + + if (U_FAILURE(status)) { + return; + } + + maximizedLocaleID.append(buffer, reslen, status); + if (status == U_STRING_NOT_TERMINATED_WARNING) { + status = U_ZERO_ERROR; // Terminators provided by CharString. + } + + if (U_FAILURE(status)) { + return; + } + + init(maximizedLocaleID.data(), /*canonicalize=*/FALSE); + if (isBogus()) { + status = U_ILLEGAL_ARGUMENT_ERROR; + } +} + +void +Locale::minimizeSubtags(UErrorCode& status) { + if (U_FAILURE(status)) { + return; + } + + // Except for a few edge cases (like the empty string, that is minimized to + // "en__POSIX"), minimized locale ID strings will be either the same length + // or shorter than their input. + CharString minimizedLocaleID; + int32_t minimizedLocaleIDCapacity = static_cast(uprv_strlen(fullName)); + + char* buffer; + int32_t reslen; + + for (;;) { + buffer = minimizedLocaleID.getAppendBuffer( + /*minCapacity=*/minimizedLocaleIDCapacity, + /*desiredCapacityHint=*/minimizedLocaleIDCapacity, + minimizedLocaleIDCapacity, + status); + + if (U_FAILURE(status)) { + return; + } + + reslen = uloc_minimizeSubtags( + fullName, + buffer, + minimizedLocaleIDCapacity, + &status); + + if (status != U_BUFFER_OVERFLOW_ERROR) { + break; + } + + // Because of the internal minimal buffer size of CharString, I can't + // think of any input data for which this could possibly ever happen. + // Maybe it would be better replaced with an assertion instead? + minimizedLocaleIDCapacity = reslen; + status = U_ZERO_ERROR; + } + + if (U_FAILURE(status)) { + return; + } + + minimizedLocaleID.append(buffer, reslen, status); + if (status == U_STRING_NOT_TERMINATED_WARNING) { + status = U_ZERO_ERROR; // Terminators provided by CharString. + } + + if (U_FAILURE(status)) { + return; + } + + init(minimizedLocaleID.data(), /*canonicalize=*/FALSE); + if (isBogus()) { + status = U_ILLEGAL_ARGUMENT_ERROR; + } +} + +Locale U_EXPORT2 +Locale::forLanguageTag(StringPiece tag, UErrorCode& status) +{ + Locale result(Locale::eBOGUS); + + if (U_FAILURE(status)) { + return result; + } + + // If a BCP-47 language tag is passed as the language parameter to the + // normal Locale constructor, it will actually fall back to invoking + // uloc_forLanguageTag() to parse it if it somehow is able to detect that + // the string actually is BCP-47. This works well for things like strings + // using BCP-47 extensions, but it does not at all work for things like + // BCP-47 grandfathered tags (eg. "en-GB-oed") which are possible to also + // interpret as ICU locale IDs and because of that won't trigger the BCP-47 + // parsing. Therefore the code here explicitly calls uloc_forLanguageTag() + // and then Locale::init(), instead of just calling the normal constructor. + + // All simple language tags will have the exact same length as ICU locale + // ID strings as they have as BCP-47 strings (like "en_US" for "en-US"). + CharString localeID; + int32_t resultCapacity = tag.size(); + + char* buffer; + int32_t parsedLength, reslen; + + for (;;) { + buffer = localeID.getAppendBuffer( + /*minCapacity=*/resultCapacity, + /*desiredCapacityHint=*/resultCapacity, + resultCapacity, + status); + + if (U_FAILURE(status)) { + return result; + } + + reslen = ulocimp_forLanguageTag( + tag.data(), + tag.length(), + buffer, + resultCapacity, + &parsedLength, + &status); + + if (status != U_BUFFER_OVERFLOW_ERROR) { + break; + } + + // For all BCP-47 language tags that use extensions, the corresponding + // ICU locale ID will be longer but uloc_forLanguageTag() does compute + // the exact length needed so this memory reallocation will be done at + // most once. + resultCapacity = reslen; + status = U_ZERO_ERROR; + } + + if (U_FAILURE(status)) { + return result; + } + + if (parsedLength != tag.size()) { + status = U_ILLEGAL_ARGUMENT_ERROR; + return result; + } + + localeID.append(buffer, reslen, status); + if (status == U_STRING_NOT_TERMINATED_WARNING) { + status = U_ZERO_ERROR; // Terminators provided by CharString. + } + + if (U_FAILURE(status)) { + return result; + } + + result.init(localeID.data(), /*canonicalize=*/FALSE); + if (result.isBogus()) { + status = U_ILLEGAL_ARGUMENT_ERROR; + } + return result; +} + +void +Locale::toLanguageTag(ByteSink& sink, UErrorCode& status) const +{ + if (U_FAILURE(status)) { + return; + } + + if (fIsBogus) { + status = U_ILLEGAL_ARGUMENT_ERROR; + return; + } + + // All simple language tags will have the exact same length as BCP-47 + // strings as they have as ICU locale IDs (like "en-US" for "en_US"). + LocalMemory scratch; + int32_t scratch_capacity = static_cast(uprv_strlen(fullName)); + + if (scratch_capacity == 0) { + scratch_capacity = 3; // "und" + } + + char* buffer; + int32_t result_capacity, reslen; + + for (;;) { + if (scratch.allocateInsteadAndReset(scratch_capacity) == nullptr) { + status = U_MEMORY_ALLOCATION_ERROR; + return; + } + + buffer = sink.GetAppendBuffer( + /*min_capacity=*/scratch_capacity, + /*desired_capacity_hint=*/scratch_capacity, + scratch.getAlias(), + scratch_capacity, + &result_capacity); + + reslen = uloc_toLanguageTag( + fullName, + buffer, + result_capacity, + /*strict=*/FALSE, + &status); + + if (status != U_BUFFER_OVERFLOW_ERROR) { + break; + } + + // For some very few edge cases a language tag will be longer as a + // BCP-47 string than it is as an ICU locale ID. Most notoriously "C" + // expands to the BCP-47 tag "en-US-u-va-posix", 16 times longer, and + // it'll take several calls to uloc_toLanguageTag() to figure that out. + // https://unicode-org.atlassian.net/browse/ICU-20132 + scratch_capacity = reslen; + status = U_ZERO_ERROR; + } + + if (U_FAILURE(status)) { + return; + } + + sink.Append(buffer, reslen); + if (status == U_STRING_NOT_TERMINATED_WARNING) { + status = U_ZERO_ERROR; // Terminators not used. + } +} + Locale U_EXPORT2 Locale::createFromName (const char *name) { @@ -1010,20 +1306,84 @@ KeywordEnumeration::~KeywordEnumeration() { uprv_free(keywords); } +// A wrapper around KeywordEnumeration that calls uloc_toUnicodeLocaleKey() in +// the next() method for each keyword before returning it. +class UnicodeKeywordEnumeration : public KeywordEnumeration { +public: + using KeywordEnumeration::KeywordEnumeration; + virtual ~UnicodeKeywordEnumeration(); + + virtual const char* next(int32_t* resultLength, UErrorCode& status) { + const char* legacy_key = KeywordEnumeration::next(nullptr, status); + if (U_SUCCESS(status) && legacy_key != nullptr) { + const char* key = uloc_toUnicodeLocaleKey(legacy_key); + if (key == nullptr) { + status = U_ILLEGAL_ARGUMENT_ERROR; + } else { + if (resultLength != nullptr) { + *resultLength = static_cast(uprv_strlen(key)); + } + return key; + } + } + if (resultLength != nullptr) *resultLength = 0; + return nullptr; + } +}; + +// Out-of-line virtual destructor to serve as the "key function". +UnicodeKeywordEnumeration::~UnicodeKeywordEnumeration() = default; + StringEnumeration * Locale::createKeywords(UErrorCode &status) const { char keywords[256]; - int32_t keywordCapacity = 256; + int32_t keywordCapacity = sizeof keywords; StringEnumeration *result = NULL; + if (U_FAILURE(status)) { + return result; + } + const char* variantStart = uprv_strchr(fullName, '@'); const char* assignment = uprv_strchr(fullName, '='); if(variantStart) { if(assignment > variantStart) { int32_t keyLen = locale_getKeywords(variantStart+1, '@', keywords, keywordCapacity, NULL, 0, NULL, FALSE, &status); - if(keyLen) { + if(U_SUCCESS(status) && keyLen) { result = new KeywordEnumeration(keywords, keyLen, 0, status); + if (!result) { + status = U_MEMORY_ALLOCATION_ERROR; + } + } + } else { + status = U_INVALID_FORMAT_ERROR; + } + } + return result; +} + +StringEnumeration * +Locale::createUnicodeKeywords(UErrorCode &status) const +{ + char keywords[256]; + int32_t keywordCapacity = sizeof keywords; + StringEnumeration *result = NULL; + + if (U_FAILURE(status)) { + return result; + } + + const char* variantStart = uprv_strchr(fullName, '@'); + const char* assignment = uprv_strchr(fullName, '='); + if(variantStart) { + if(assignment > variantStart) { + int32_t keyLen = locale_getKeywords(variantStart+1, '@', keywords, keywordCapacity, NULL, 0, NULL, FALSE, &status); + if(U_SUCCESS(status) && keyLen) { + result = new UnicodeKeywordEnumeration(keywords, keyLen, 0, status); + if (!result) { + status = U_MEMORY_ALLOCATION_ERROR; + } } } else { status = U_INVALID_FORMAT_ERROR; @@ -1038,6 +1398,105 @@ Locale::getKeywordValue(const char* keywordName, char *buffer, int32_t bufLen, U return uloc_getKeywordValue(fullName, keywordName, buffer, bufLen, &status); } +void +Locale::getKeywordValue(StringPiece keywordName, ByteSink& sink, UErrorCode& status) const { + if (U_FAILURE(status)) { + return; + } + + if (fIsBogus) { + status = U_ILLEGAL_ARGUMENT_ERROR; + return; + } + + // TODO: Remove the need for a const char* to a NUL terminated buffer. + const CharString keywordName_nul(keywordName, status); + if (U_FAILURE(status)) { + return; + } + + LocalMemory scratch; + int32_t scratch_capacity = 16; // Arbitrarily chosen default size. + + char* buffer; + int32_t result_capacity, reslen; + + for (;;) { + if (scratch.allocateInsteadAndReset(scratch_capacity) == nullptr) { + status = U_MEMORY_ALLOCATION_ERROR; + return; + } + + buffer = sink.GetAppendBuffer( + /*min_capacity=*/scratch_capacity, + /*desired_capacity_hint=*/scratch_capacity, + scratch.getAlias(), + scratch_capacity, + &result_capacity); + + reslen = uloc_getKeywordValue( + fullName, + keywordName_nul.data(), + buffer, + result_capacity, + &status); + + if (status != U_BUFFER_OVERFLOW_ERROR) { + break; + } + + scratch_capacity = reslen; + status = U_ZERO_ERROR; + } + + if (U_FAILURE(status)) { + return; + } + + sink.Append(buffer, reslen); + if (status == U_STRING_NOT_TERMINATED_WARNING) { + status = U_ZERO_ERROR; // Terminators not used. + } +} + +void +Locale::getUnicodeKeywordValue(StringPiece keywordName, + ByteSink& sink, + UErrorCode& status) const { + // TODO: Remove the need for a const char* to a NUL terminated buffer. + const CharString keywordName_nul(keywordName, status); + if (U_FAILURE(status)) { + return; + } + + const char* legacy_key = uloc_toLegacyKey(keywordName_nul.data()); + + if (legacy_key == nullptr) { + status = U_ILLEGAL_ARGUMENT_ERROR; + return; + } + + CharString legacy_value; + { + CharStringByteSink sink(&legacy_value); + getKeywordValue(legacy_key, sink, status); + } + + if (U_FAILURE(status)) { + return; + } + + const char* unicode_value = uloc_toUnicodeLocaleType( + keywordName_nul.data(), legacy_value.data()); + + if (unicode_value == nullptr) { + status = U_ILLEGAL_ARGUMENT_ERROR; + return; + } + + sink.Append(unicode_value, static_cast(uprv_strlen(unicode_value))); +} + void Locale::setKeywordValue(const char* keywordName, const char* keywordValue, UErrorCode &status) { @@ -1048,6 +1507,46 @@ Locale::setKeywordValue(const char* keywordName, const char* keywordValue, UErro } } +void +Locale::setKeywordValue(StringPiece keywordName, + StringPiece keywordValue, + UErrorCode& status) { + // TODO: Remove the need for a const char* to a NUL terminated buffer. + const CharString keywordName_nul(keywordName, status); + const CharString keywordValue_nul(keywordValue, status); + setKeywordValue(keywordName_nul.data(), keywordValue_nul.data(), status); +} + +void +Locale::setUnicodeKeywordValue(StringPiece keywordName, + StringPiece keywordValue, + UErrorCode& status) { + // TODO: Remove the need for a const char* to a NUL terminated buffer. + const CharString keywordName_nul(keywordName, status); + const CharString keywordValue_nul(keywordValue, status); + + if (U_FAILURE(status)) { + return; + } + + const char* legacy_key = uloc_toLegacyKey(keywordName_nul.data()); + + if (legacy_key == nullptr) { + status = U_ILLEGAL_ARGUMENT_ERROR; + return; + } + + const char* legacy_value = + uloc_toLegacyType(keywordName_nul.data(), keywordValue_nul.data()); + + if (legacy_value == nullptr) { + status = U_ILLEGAL_ARGUMENT_ERROR; + return; + } + + setKeywordValue(legacy_key, legacy_value, status); +} + const char * Locale::getBaseName() const { return baseName; diff --git a/deps/icu-small/source/common/mutex.h b/deps/icu-small/source/common/mutex.h index 04c22b4a3767b1..5223397bbcc10a 100644 --- a/deps/icu-small/source/common/mutex.h +++ b/deps/icu-small/source/common/mutex.h @@ -35,7 +35,7 @@ U_NAMESPACE_BEGIN // For example: // -// UMutex myMutex; +// UMutex myMutex = U_MUTEX_INITIALIZER; // // void Function(int arg1, int arg2) // { diff --git a/deps/icu-small/source/common/norm2_nfc_data.h b/deps/icu-small/source/common/norm2_nfc_data.h index c8bf440ae10819..82a68097385285 100644 --- a/deps/icu-small/source/common/norm2_nfc_data.h +++ b/deps/icu-small/source/common/norm2_nfc_data.h @@ -11,258 +11,197 @@ #ifdef INCLUDED_FROM_NORMALIZER2_CPP -static const UVersionInfo norm2_nfc_data_formatVersion={3,0,0,0}; +static const UVersionInfo norm2_nfc_data_formatVersion={4,0,0,0}; static const UVersionInfo norm2_nfc_data_dataVersion={0xb,0,0,0}; static const int32_t norm2_nfc_data_indexes[Normalizer2Impl::IX_COUNT]={ -0x50,0x4e50,0x8aa8,0x8ba8,0x8ba8,0x8ba8,0x8ba8,0x8ba8,0xc0,0x300,0xadc,0x29d0,0x3c56,0xfc00,0x1282,0x3b8c, +0x50,0x4ab0,0x8708,0x8808,0x8808,0x8808,0x8808,0x8808,0xc0,0x300,0xadc,0x29d0,0x3c56,0xfc00,0x1282,0x3b8c, 0x3c24,0x3c56,0x300,0 }; -static const uint16_t norm2_nfc_data_trieIndex[9976]={ -0x2aa,0x2b2,0x2ba,0x2c2,0x2d0,0x2d8,0x2e0,0x2e8,0x2f0,0x2f8,0x300,0x308,0x310,0x318,0x31e,0x326, -0x32e,0x336,0x2c9,0x2d1,0x33b,0x343,0x2c9,0x2d1,0x34b,0x353,0x35b,0x363,0x36b,0x373,0x37b,0x383, -0x38b,0x393,0x39b,0x3a3,0x3ab,0x3b3,0x3bb,0x3c3,0x2c9,0x2d1,0x2c9,0x2d1,0x3ca,0x3d2,0x3da,0x3e2, -0x3e6,0x3ee,0x3f4,0x3fc,0x2c9,0x2d1,0x404,0x40c,0x410,0x418,0x420,0x428,0x2c9,0x2d1,0x426,0x42e, -0x436,0x43d,0x441,0x2c9,0x2c9,0x2c9,0x448,0x450,0x2c9,0x458,0x460,0x2c9,0x2c9,0x468,0x470,0x478, -0x2c9,0x480,0x488,0x2c9,0x2c9,0x490,0x498,0x2c9,0x2c9,0x468,0x49f,0x2c9,0x4a7,0x4ad,0x4b5,0x2c9, -0x2c9,0x2c9,0x4bc,0x2c9,0x2c9,0x4c2,0x4ca,0x2c9,0x2c9,0x4d0,0x4d8,0x2c9,0x2c9,0x2c9,0x4de,0x2c9, -0x2c9,0x4e6,0x4ed,0x2c9,0x2c9,0x4f0,0x4f7,0x2c9,0x4fa,0x501,0x509,0x511,0x519,0x521,0x528,0x2c9, -0x2c9,0x52f,0x2c9,0x2c9,0x536,0x2c9,0x2c9,0x2c9,0x96d,0x2c9,0x2c9,0x975,0x2c9,0x97b,0x983,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x53a,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x542,0x542,0x2c9,0x2c9,0x2c9,0x2c9,0x548,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x550,0x2c9,0x2c9,0x2c9,0x553,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x55a,0x2c9,0x2c9,0x562,0x2c9,0x56a,0x2c9,0x2c9,0x572,0x577,0x57f,0x585,0x2c9,0x58b,0x2c9,0x592, -0x2c9,0x597,0x2c9,0x2c9,0x2c9,0x2c9,0x59d,0x5a5,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x5ad,0x5b2, -0x5ba,0x5c2,0x5ca,0x5d2,0x5da,0x5e2,0x5ea,0x5f2,0x5fa,0x602,0x60a,0x612,0x61a,0x622,0x62a,0x632, -0x63a,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x63e,0x646,0x2c9,0x64d,0x2c9,0x2c9,0x651,0x658,0x65d,0x2c9, -0x665,0x66d,0x675,0x67d,0x685,0x68d,0x2c9,0x695,0x2c9,0x69b,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x69e,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x6a6,0x2c9,0x2c9,0x2c9,0x6ab,0x2c9,0x2c9,0x2c9,0x6b3, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x6bb,0x6c2,0x6ca,0x6d2,0x6da,0x6e2,0x6ea,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x6f2,0x6fa,0x2c9,0x2c9,0x702,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x709,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x710,0x718,0x2c9,0x71e,0x722,0x2c9,0x2c9,0x598,0x72a,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x72e,0x736,0x739,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x498, -0x98b,0x98c,0x98d,0x98e,0x98f,0x990,0x99f,0x98b,0x98c,0x98d,0x98e,0x98f,0x990,0x99f,0x98b,0x98c, -0x98d,0x98e,0x98f,0x990,0x99f,0x98b,0x98c,0x98d,0x98e,0x98f,0x990,0x99f,0x98b,0x98c,0x98d,0x98e, -0x98f,0x990,0x99f,0x98b,0x98c,0x98d,0x98e,0x98f,0x990,0x99f,0x98b,0x98c,0x98d,0x98e,0x98f,0x990, -0x99f,0x98b,0x98c,0x98d,0x98e,0x98f,0x990,0x99f,0x98b,0x98c,0x98d,0x98e,0x98f,0x990,0x99f,0x98b, -0x98c,0x98d,0x98e,0x98f,0x990,0x99f,0x98b,0x98c,0x98d,0x98e,0x98f,0x990,0x99f,0x98b,0x98c,0x98d, -0x98e,0x98f,0x990,0x99f,0x98b,0x98c,0x98d,0x98e,0x98f,0x990,0x99f,0x98b,0x98c,0x98d,0x98e,0x98f, -0x990,0x99f,0x98b,0x98c,0x98d,0x98e,0x98f,0x990,0x99f,0x98b,0x98c,0x98d,0x98e,0x98f,0x990,0x99f, -0x98b,0x98c,0x98d,0x98e,0x98f,0x990,0x99f,0x98b,0x98c,0x98d,0x98e,0x98f,0x990,0x99f,0x98b,0x98c, -0x98d,0x98e,0x98f,0x990,0x99f,0x98b,0x98c,0x98d,0x98e,0x98f,0x990,0x99f,0x98b,0x98c,0x98d,0x98e, -0x98f,0x990,0x99f,0x98b,0x98c,0x98d,0x98e,0x98f,0x990,0x99f,0x98b,0x98c,0x98d,0x98e,0x98f,0x990, -0x99f,0x98b,0x98c,0x98d,0x98e,0x98f,0x990,0x99f,0x98b,0x98c,0x98d,0x98e,0x98f,0x990,0x99f,0x98b, -0x98c,0x98d,0x98e,0x98f,0x990,0x99f,0x98b,0x98c,0x98d,0x98e,0x98f,0x990,0x99f,0x98b,0x98c,0x98d, -0x98e,0x98f,0x990,0x99f,0x98b,0x98c,0x98d,0x98e,0x98f,0x990,0x99f,0x98b,0x98c,0x98d,0x98e,0x98f, -0x990,0x99f,0x98b,0x98c,0x98d,0x98e,0x98f,0x990,0x99f,0x98b,0x98c,0x98d,0x98e,0x98f,0x990,0x99f, -0x98b,0x98c,0x98d,0x98e,0x98f,0x990,0x99f,0x98b,0x98c,0x98d,0x98e,0x98f,0x990,0x99f,0x98b,0x98c, -0x98d,0x98e,0x98f,0x990,0x99f,0x98b,0x98c,0x98d,0x98e,0x98f,0x990,0x99f,0x98b,0x98c,0x98d,0x98e, -0x98f,0x990,0x99f,0x98b,0x98c,0x98d,0x98e,0x98f,0x990,0x99f,0x98b,0x98c,0x98d,0x98e,0x98f,0x990, -0x99f,0x98b,0x98c,0x98d,0x98e,0x98f,0x990,0x99f,0x98b,0x98c,0x98d,0x98e,0x98f,0x990,0x99f,0x98b, -0x98c,0x98d,0x98e,0x98f,0x990,0x99f,0x98b,0x98c,0x98d,0x98e,0x98f,0x990,0x99f,0x98b,0x98c,0x98d, -0x98e,0x98f,0x990,0x99f,0x98b,0x98c,0x98d,0x98e,0x98f,0x990,0x99f,0x98b,0x98c,0x98d,0x98e,0x98f, -0x990,0x99f,0x98b,0x98c,0x98d,0x98e,0x98f,0x990,0x99f,0x98b,0x98c,0x98d,0x98e,0x98f,0x990,0x99f, -0x98b,0x98c,0x98d,0x98e,0x98f,0x990,0x99f,0x98b,0x98c,0x98d,0x98e,0x98f,0x990,0x997,0x2c9,0x2c9, -0x9a7,0x9ae,0x2aa,0x9b5,0x2aa,0x2aa,0x2aa,0x2aa,0x2aa,0x2aa,0x2aa,0x2aa,0x2aa,0x2aa,0x2aa,0x2aa, -0x2aa,0x2aa,0x2aa,0x2aa,0x2aa,0x2aa,0x2aa,0x2aa,0x2aa,0x2aa,0x2aa,0x2aa,0x2aa,0x2aa,0x2aa,0x2aa, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x741,0x749,0x751,0x759,0x761,0x769,0x771,0x779, -0x781,0x789,0x791,0x799,0x7a1,0x7a9,0x7b1,0x2c9,0x7b8,0x7c0,0x7c8,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x7d0,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0xb28,0xb28,0xb40,0xb80,0xbc0,0xc00,0xc40,0xc78,0xcb8,0xb24,0xcec,0xb24,0xd2c,0xd6c,0xdac,0xdec, -0xe2c,0xe6c,0xeac,0xeec,0xb24,0xb24,0xf28,0xf68,0xf98,0xfd0,0xb24,0x1010,0x1040,0x1080,0xb24,0x1098, -0x880,0x8b0,0x8ee,0x92d,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x95a,0x188,0x188, -0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x976,0x188,0x188,0x9ac,0x188,0x9ec,0xa26,0x188,0x188, -0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188, -0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0xa66, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x7d4, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x7dc,0x2c9,0x2c9,0x2c9,0x7df,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x7e6,0x7ea,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x7f2,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x7f9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x800,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x709,0x6ab,0x805,0x80d,0x2c9,0x2c9,0x815,0x81c,0x2c9,0x598,0x2c9,0x2c9,0x824,0x2c9,0x2c9,0x827, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x82d,0x2c9,0x830,0x838,0x83f,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x847,0x2c9,0x2c9,0x84f,0x857,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x85c,0x864,0x2c9,0x2c9,0x6ab, -0x2c9,0x2c9,0x2c9,0x867,0x2c9,0x2c9,0x2c9,0x86d,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x870,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x542,0x86e, -0x2c9,0x877,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x6ab,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x87f,0x2c9,0x882,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x888,0x2c9,0x88e,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x894,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x89c,0x8a4,0x8ac,0x8b2,0x8ba,0x2c9,0x2c9,0x2c9,0x8c2,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x8ca,0x8d2,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x8d6,0x2c9,0x2c9,0x2c9, -0x8dd,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x8e5,0x8ed,0x8f5,0x8fd,0x905,0x90d,0x915,0x91d,0x925,0x92d, -0x935,0x93d,0x945,0x94d,0x955,0x95d,0x965,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9, -0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2c9,0x2a9,0x2a9,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,4,8,0xc,1,1,0x10,0x50,0x5c,0x70,0x88,0xcc,0xd0, -0xec,0x108,0x144,0x148,0x15c,0x174,0x180,0x1a4,0x1e4,1,0x1ec,0x20c,0x228,0x244,0x290,0x298, -0x2b0,0x2b8,0x2dc,1,1,1,1,1,1,0x2f4,0x334,0x340,0x354,0x36c,0x3b0,0x3b4, -0x3d0,0x3f0,0x428,0x430,0x444,0x45c,0x468,0x48c,0x4cc,1,0x4d4,0x4f4,0x510,0x530,0x57c,0x584, -0x5a0,0x5a8,0x5d0,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,0x5e8,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -0x1284,0x128a,0xade,0x1290,0xaf4,0xafe,0x5f4,0xb08,0x1296,0x129c,0xb12,0x12a2,0x12a8,0x12ae,0x12b4,0xb28, -1,0x12ba,0x12c0,0x12c6,0xb32,0xb48,0xb5a,1,0x5fc,0x12cc,0x12d2,0x12d8,0xb64,0x12de,1,1, -0x12e4,0x12ea,0xb7a,0x12f0,0xb90,0xb9a,0x600,0xba4,0x12f6,0x12fc,0xbae,0x1302,0x1308,0x130e,0x1314,0xbc4, -1,0x131a,0x1320,0x1326,0xbce,0xbe4,0xbf6,1,0x608,0x132c,0x1332,0x1338,0xc00,0x133e,1,0x1344, -0x134a,0x1350,0xc16,0xc2c,0x1357,0x135d,0x1362,0x1368,0x136e,0x1374,0x137a,0x1380,0x1386,0x138c,0x1392,0x1398, -1,1,0xc42,0xc50,0x139e,0x13a4,0x13aa,0x13b0,0x13b7,0x13bd,0x13c2,0x13c8,0x13ce,0x13d4,0x13da,0x13e0, -0x13e6,0x13ec,0x13f3,0x13f9,0x13fe,0x1404,1,1,0x140a,0x1410,0x1416,0x141c,0x1422,0x1428,0x142f,0x1435, -0x143a,1,1,1,0x1441,0x1447,0x144d,0x1453,1,0x1458,0x145e,0x1465,0x146b,0x1470,0x1476,1, -1,1,1,0x147c,0x1482,0x1489,0x148f,0x1494,0x149a,1,1,1,0xc5e,0xc6c,0x14a0,0x14a6, -0x14ac,0x14b2,1,1,0x14b8,0x14be,0x14c5,0x14cb,0x14d0,0x14d6,0xc7a,0xc84,0x14dc,0x14e2,0x14e9,0x14ef, -0xc8e,0xc98,0x14f5,0x14fb,0x1500,0x1506,1,1,0xca2,0xcac,0xcb6,0xcc0,0x150c,0x1512,0x1518,0x151e, -0x1524,0x152a,0x1531,0x1537,0x153c,0x1542,0x1548,0x154e,0x1554,0x155a,0x1560,0x1566,0x156c,0x1572,0x1578,0x60c, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -0xcca,0xce4,1,1,1,1,1,1,1,1,1,1,1,1,1,0xcfe, -0xd18,1,1,1,1,1,1,0x610,1,1,1,1,1,1,1,1, -1,1,1,1,1,0x157e,0x1584,0x158a,0x1590,0x1596,0x159c,0x15a2,0x15a8,0x15b0,0x15ba,0x15c4, -0x15ce,0x15d8,0x15e2,0x15ec,0x15f6,1,0x1600,0x160a,0x1614,0x161e,0x1627,0x162d,1,1,0x1632,0x1638, -0x163e,0x1644,0xd32,0xd3c,0x164d,0x1657,0x165f,0x1665,0x166b,1,1,1,0x1670,0x1676,1,1, -0x167c,0x1682,0x168a,0x1694,0x169d,0x16a3,0x16a9,0x16af,0x16b4,0x16ba,0x16c0,0x16c6,0x16cc,0x16d2,0x16d8,0x16de, -0x16e4,0x16ea,0x16f0,0x16f6,0x16fc,0x1702,0x1708,0x170e,0x1714,0x171a,0x1720,0x1726,0x172c,0x1732,0x1738,0x173e, -0x1744,0x174a,0x1750,0x1756,1,1,0x175c,0x1762,1,1,1,1,1,1,0xd46,0xd50, -0xd5a,0xd64,0x176a,0x1774,0x177e,0x1788,0xd6e,0xd78,0x1792,0x179c,0x17a4,0x17aa,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,0x614,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,0xfdcc,0xfdcc,0xfdcc,0xfdcc, -0xfdcc,0xffcc,0xfdcc,0xfdcc,0xfdcc,0xfdcc,0xfdcc,0xfdcc,0xfdcc,0xffcc,0xffcc,0xfdcc,0xffcc,0xfdcc,0xffcc,0xfdcc, -0xfdcc,0xffd0,0xffb8,0xffb8,0xffb8,0xffb8,0xffd0,0xfdb0,0xffb8,0xffb8,0xffb8,0xffb8,0xffb8,0xff94,0xff94,0xfdb8, -0xfdb8,0xfdb8,0xfdb8,0xfd94,0xfd94,0xffb8,0xffb8,0xffb8,0xffb8,0xfdb8,0xfdb8,0xffb8,0xfdb8,0xfdb8,0xffb8,0xffb8, -0xfe02,0xfe02,0xfe02,0xfe02,0xfc02,0xffb8,0xffb8,0xffb8,0xffb8,0xffcc,0xffcc,0xffcc,0x3c26,0x3c2c,0xfdcc,0x3c32, -0x3c38,0xfde0,0xffcc,0xffb8,0xffb8,0xffb8,0xffcc,0xffcc,0xffcc,0xffb8,0xffb8,1,0xffcc,0xffcc,0xffcc,0xffb8, -0xffb8,0xffb8,0xffb8,0xffcc,0xffd0,0xffb8,0xffb8,0xffcc,0xffd2,0xffd4,0xffd4,0xffd2,0xffd4,0xffd4,0xffd2,0xffcc, -0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,1,1,1,1, -0x29d1,1,1,1,1,1,1,1,1,1,0x29d5,1,1,1,1,1, -1,0x17b1,0x17b7,0x29d9,0x17bd,0x17c3,0x17c9,1,0x17cf,1,0x17d5,0x17db,0x17e3,0x618,1,1, -1,0x634,1,0x644,1,0x658,1,1,1,1,1,0x674,1,0x684,1,1, -1,0x688,1,1,1,0x6a0,0x17eb,0x17f1,0xd82,0x17f7,0xd8c,0x17fd,0x1805,0x6b4,1,1, -1,0x6d4,1,0x6e4,1,0x6fc,1,1,1,1,1,0x71c,1,0x72c,1,1, -1,0x734,1,1,1,0x754,0xd96,0xda8,0x180d,0x1813,0xdba,1,1,1,0x76c,0x1819, -0x181f,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,0x1825,0x182b,1,0x1831, -1,1,0x774,0x1837,1,1,1,1,0x183d,0x1843,0x1849,1,0x778,1,1,0x780, -1,0x784,0x790,0x798,0x79c,0x184f,0x7ac,1,1,1,0x7b0,1,1,1,1,0x7b4, -1,1,1,0x7c4,1,1,1,0x7c8,1,0x7cc,1,1,0x7d0,1,1,0x7d8, -1,0x7dc,0x7e8,0x7f0,0x7f4,0x1855,0x804,1,1,1,0x808,1,1,1,1,0x80c, -1,1,1,0x81c,1,1,1,0x820,1,0x824,1,1,0x185b,0x1861,1,0x1867, -1,1,0x828,0x186d,1,1,1,1,0x1873,0x1879,0x187f,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -0x82c,0x830,0x1885,0x188b,1,1,1,1,1,1,1,1,1,1,1,0xffcc, -0xffcc,0xffcc,0xffcc,0xffcc,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,0x1891,0x1897,1, -1,1,1,1,1,1,1,1,1,1,1,1,0x189d,0x18a3,0x18a9,0x18af, -1,1,0x18b5,0x18bb,0x834,0x838,0x18c1,0x18c7,0x18cd,0x18d3,0x18d9,0x18df,1,1,0x18e5,0x18eb, -0x18f1,0x18f7,0x18fd,0x1903,0x83c,0x840,0x1909,0x190f,0x1915,0x191b,0x1921,0x1927,0x192d,0x1933,0x1939,0x193f, -0x1945,0x194b,1,1,0x1951,0x1957,1,1,1,1,1,1,1,1,1,1, +static const uint16_t norm2_nfc_data_trieIndex[1690]={ +0,0x40,0x7b,0xbb,0xfb,0x13a,0x17a,0x1b2,0x1f2,0x226,0x254,0x226,0x294,0x2d4,0x313,0x353, +0x393,0x3d2,0x40f,0x44e,0x226,0x226,0x488,0x4c8,0x4f8,0x530,0x226,0x570,0x59f,0x5de,0x226,0x5f3, +0x631,0x65f,0x226,0x68c,0x6cc,0x709,0x729,0x768,0x7a7,0x7e4,0x803,0x840,0x729,0x879,0x8a7,0x8e6, +0x226,0x920,0x937,0x977,0x98e,0x9cd,0x226,0xa03,0xa23,0xa5e,0xa6a,0xaa4,0xacc,0xb09,0xb49,0xb83, +0xb9e,0x226,0xbd9,0x226,0xc19,0xc38,0xc6e,0xcab,0x226,0x226,0x226,0x226,0x226,0xcce,0x226,0x226, +0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0xcfa,0x226,0x226,0xd2f, +0x226,0x226,0xd4d,0x226,0xd77,0x226,0x226,0x226,0xdb3,0xdd3,0xe13,0x226,0xe51,0xe91,0xec5,0xef1, +0x808,0x226,0x226,0xf25,0x226,0x226,0x226,0xf65,0xfa5,0xfe5,0x1025,0x1065,0x10a5,0x10e5,0x1125,0x1165, +0x11a5,0x226,0x226,0x11d5,0x1206,0x226,0x1236,0x1269,0x12a6,0x12e5,0x1325,0x135b,0x1389,0x226,0x226,0x226, +0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, +0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x13b4,0x226,0x226,0x226,0x226, +0x226,0x226,0x226,0xcbc,0x226,0x13d1,0x226,0x1411,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, +0x1451,0x148b,0x14c9,0x1509,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, +0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, +0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, +0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, +0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, +0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, +0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, +0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, +0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, +0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, +0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, +0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, +0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, +0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, +0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, +0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, +0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, +0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, +0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, +0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, +0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, +0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, +0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, +0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, +0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, +0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, +0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, +0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, +0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, +0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x1548,0x1586,0x15a6,0x226,0x226,0x226,0x226, +0x15e0,0x226,0x226,0x161c,0x164e,0x167c,0x80c,0x168f,0x226,0x226,0x169f,0x16df,0x226,0x226,0x226,0x13e3, +0x171f,0x1727,0x172f,0x1737,0x1723,0x172b,0x1733,0x171f,0x1727,0x172f,0x1737,0x1723,0x172b,0x1733,0x171f,0x1727, +0x172f,0x1737,0x1723,0x172b,0x1733,0x171f,0x1727,0x172f,0x1737,0x1723,0x172b,0x1733,0x171f,0x1727,0x172f,0x1737, +0x1723,0x172b,0x1733,0x171f,0x1727,0x172f,0x1737,0x1723,0x172b,0x1733,0x171f,0x1727,0x172f,0x1737,0x1723,0x172b, +0x1733,0x171f,0x1727,0x172f,0x1737,0x1723,0x172b,0x1733,0x171f,0x1727,0x172f,0x1737,0x1723,0x172b,0x1733,0x171f, +0x1727,0x172f,0x1737,0x1723,0x172b,0x1733,0x171f,0x1727,0x172f,0x1737,0x1723,0x172b,0x1733,0x171f,0x1727,0x172f, +0x1737,0x1723,0x172b,0x1733,0x171f,0x1727,0x172f,0x1737,0x1723,0x172b,0x1733,0x171f,0x1727,0x172f,0x1737,0x1723, +0x172b,0x1733,0x171f,0x1727,0x172f,0x1737,0x1723,0x172b,0x1733,0x171f,0x1727,0x172f,0x1737,0x1723,0x172b,0x1733, +0x171f,0x1727,0x172f,0x1737,0x1723,0x172b,0x1733,0x171f,0x1727,0x172f,0x1737,0x1723,0x172b,0x1733,0x171f,0x1727, +0x172f,0x1737,0x1723,0x172b,0x1733,0x171f,0x1727,0x172f,0x1737,0x1723,0x172b,0x1733,0x171f,0x1727,0x172f,0x1737, +0x1723,0x172b,0x1733,0x171f,0x1727,0x172f,0x1737,0x1723,0x172b,0x1733,0x171f,0x1727,0x172f,0x1737,0x1723,0x172b, +0x1733,0x171f,0x1727,0x172f,0x1737,0x1723,0x172b,0x1733,0x171f,0x1727,0x172f,0x1737,0x1723,0x172b,0x176b,0x226, +0x17ab,0x17e6,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, +0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, +0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, +0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, +0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, +0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, +0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, +0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, +0x226,0x226,0x226,0x226,0x1826,0x1866,0x18a6,0x18e6,0x1926,0x1966,0x19a6,0x19e6,0x1a09,0x1a49,0x226,0x226, +0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x1a69,0x226,0x226,0x226,0x226,0x226,0x226,0x226, +0x61f,0x62e,0x644,0x663,0x678,0x678,0x678,0x67c,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, +0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, +0x226,0x226,0x226,0x226,0x226,0x226,0x226,0xbd9,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, +0x226,0x226,0x226,0x226,0x226,0x226,0x54f,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x40c, +0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x1a9c,0x226,0x226,0x1aac,0x226,0x226,0x226,0x226, +0x226,0x226,0x226,0x226,0x226,0x226,0xdc5,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, +0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x1abc,0x226,0x226,0x226,0x226,0x226,0x226, +0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x1ac6,0x54f, +0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x7eb,0x226,0x226,0x9ba,0x226,0x1ad6, +0x1ae3,0x1aef,0x226,0x226,0x226,0x226,0x414,0x226,0x1afa,0x1b0a,0x226,0x226,0x226,0x7e0,0x226,0x226, +0x226,0x226,0x1b1a,0x226,0x226,0x226,0x1b25,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, +0x226,0x1b2c,0x226,0x226,0x226,0x226,0x1b37,0x1b46,0x8f6,0x1b54,0x412,0x226,0x226,0x226,0x226,0x226, +0x226,0x226,0x226,0x1b62,0x798,0x226,0x226,0x226,0x226,0x226,0x1b72,0x1b81,0x226,0x226,0x226,0x226, +0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x8d6,0x1b89,0x1b99,0x226,0x226,0x226,0x9ba, +0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x1ba3,0x226,0x226,0x226,0x226,0x226,0x226,0x7e6,0x226, +0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x1ba0,0x226,0x226,0x226, +0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, +0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x7ed,0x7ea,0x226,0x226,0x226,0x226,0x7e8, +0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, +0x226,0x226,0x226,0x226,0x226,0x226,0x9ba,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, +0x226,0x226,0x226,0x226,0x226,0x226,0x226,0xbd3,0x226,0x226,0x226,0x226,0x7ea,0x226,0x226,0x226, +0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x1bb3,0x226,0x226,0x226, +0xebe,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x1bb8,0x226,0x226, +0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, +0x226,0x226,0x226,0x226,0x1bc7,0x1bd7,0x1be5,0x1bf2,0x226,0x1bfe,0x1c0c,0x1c1c,0x226,0x226,0x226,0x226, +0xce9,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, +0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x1c2c,0x1c34,0x1c42,0x226, +0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, +0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x1c52,0x226,0x226,0x226, +0x226,0x226,0x226,0x1c5e,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x1c6e, +0x1c7e,0x1c8e,0x1c9e,0x1cae,0x1cbe,0x1cce,0x1cde,0x1cee,0x1cfe,0x1d0e,0x1d1e,0x1d2e,0x1d3e,0x1d4e,0x1d5e,0x1d6e, +0x1d7e,0x1d8e,0x1d9e,0x1dae,0x1dbe,0x1dce,0x1dde,0x1dee,0x1dfe,0x1e0e,0x1e1e,0x1e2e,0x1e3e,0x1e4e,0x1e5e,0x1e6e, +0x1e7e,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226, +0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x226,0x408, +0x428,0xc4,0xc4,0xc4,0x448,0x457,0x46a,0x486,0x4a3,0x4bf,0x4dc,0x4f9,0x516,0x533,0xc4,0xc4, +0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4, +0xc4,0xc4,0xc4,0x54d,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4, +0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4, +0xc4,0xc4,0x564,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0x56f,0x58c,0xc4,0xc4,0xc4, +0xc4,0xc4,0xc4,0x5ac,0xc4,0xc4,0xc4,0x5bf,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4, +0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4, +0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0xc4,0x5df,0x5ff +}; + +static const uint16_t norm2_nfc_data_trieData[7822]={ +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,4,8,0xc,1, +1,0x10,0x50,0x5c,0x70,0x88,0xcc,0xd0,0xec,0x108,0x144,0x148,0x15c,0x174,0x180,0x1a4, +0x1e4,1,0x1ec,0x20c,0x228,0x244,0x290,0x298,0x2b0,0x2b8,0x2dc,1,1,1,1,1, +1,0x2f4,0x334,0x340,0x354,0x36c,0x3b0,0x3b4,0x3d0,0x3f0,0x428,0x430,0x444,0x45c,0x468,0x48c, +0x4cc,1,0x4d4,0x4f4,0x510,0x530,0x57c,0x584,0x5a0,0x5a8,0x5d0,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,0x5e8,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,0x1284,0x128a,0xade,0x1290,0xaf4, +0xafe,0x5f4,0xb08,0x1296,0x129c,0xb12,0x12a2,0x12a8,0x12ae,0x12b4,0xb28,1,0x12ba,0x12c0,0x12c6,0xb32, +0xb48,0xb5a,1,0x5fc,0x12cc,0x12d2,0x12d8,0xb64,0x12de,1,1,0x12e4,0x12ea,0xb7a,0x12f0,0xb90, +0xb9a,0x600,0xba4,0x12f6,0x12fc,0xbae,0x1302,0x1308,0x130e,0x1314,0xbc4,1,0x131a,0x1320,0x1326,0xbce, +0xbe4,0xbf6,1,0x608,0x132c,0x1332,0x1338,0xc00,0x133e,1,0x1344,0x134a,0x1350,0xc16,0xc2c,0x1357, +0x135d,0x1362,0x1368,0x136e,0x1374,0x137a,0x1380,0x1386,0x138c,0x1392,0x1398,1,1,0xc42,0xc50,0x139e, +0x13a4,0x13aa,0x13b0,0x13b7,0x13bd,0x13c2,0x13c8,0x13ce,0x13d4,0x13da,0x13e0,0x13e6,0x13ec,0x13f3,0x13f9,0x13fe, +0x1404,1,1,0x140a,0x1410,0x1416,0x141c,0x1422,0x1428,0x142f,0x1435,0x143a,1,1,1,0x1441, +0x1447,0x144d,0x1453,1,0x1458,0x145e,0x1465,0x146b,0x1470,0x1476,1,1,1,0x147c,0x1482,0x1489, +0x148f,0x1494,0x149a,1,1,1,0xc5e,0xc6c,0x14a0,0x14a6,0x14ac,0x14b2,1,1,0x14b8,0x14be, +0x14c5,0x14cb,0x14d0,0x14d6,0xc7a,0xc84,0x14dc,0x14e2,0x14e9,0x14ef,0xc8e,0xc98,0x14f5,0x14fb,0x1500,0x1506, +1,1,0xca2,0xcac,0xcb6,0xcc0,0x150c,0x1512,0x1518,0x151e,0x1524,0x152a,0x1531,0x1537,0x153c,0x1542, +0x1548,0x154e,0x1554,0x155a,0x1560,0x1566,0x156c,0x1572,0x1578,0x60c,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,0xcca,0xce4,1,1,1,1, +1,1,1,1,1,1,1,1,1,0xcfe,0xd18,1,1,1,1,1, +1,0x610,1,1,1,1,1,1,1,1,1,1,1,1,1,0x157e, +0x1584,0x158a,0x1590,0x1596,0x159c,0x15a2,0x15a8,0x15b0,0x15ba,0x15c4,0x15ce,0x15d8,0x15e2,0x15ec,0x15f6,1, +0x1600,0x160a,0x1614,0x161e,0x1627,0x162d,1,1,0x1632,0x1638,0x163e,0x1644,0xd32,0xd3c,0x164d,0x1657, +0x165f,0x1665,0x166b,1,1,1,0x1670,0x1676,1,1,0x167c,0x1682,0x168a,0x1694,0x169d,0x16a3, +0x16a9,0x16af,0x16b4,0x16ba,0x16c0,0x16c6,0x16cc,0x16d2,0x16d8,0x16de,0x16e4,0x16ea,0x16f0,0x16f6,0x16fc,0x1702, +0x1708,0x170e,0x1714,0x171a,0x1720,0x1726,0x172c,0x1732,0x1738,0x173e,0x1744,0x174a,0x1750,0x1756,1,1, +0x175c,0x1762,1,1,1,1,1,1,0xd46,0xd50,0xd5a,0xd64,0x176a,0x1774,0x177e,0x1788, +0xd6e,0xd78,0x1792,0x179c,0x17a4,0x17aa,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,0x614,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,0xfdcc,0xfdcc,0xfdcc,0xfdcc,0xfdcc,0xffcc,0xfdcc,0xfdcc,0xfdcc,0xfdcc,0xfdcc,0xfdcc, +0xfdcc,0xffcc,0xffcc,0xfdcc,0xffcc,0xfdcc,0xffcc,0xfdcc,0xfdcc,0xffd0,0xffb8,0xffb8,0xffb8,0xffb8,0xffd0,0xfdb0, +0xffb8,0xffb8,0xffb8,0xffb8,0xffb8,0xff94,0xff94,0xfdb8,0xfdb8,0xfdb8,0xfdb8,0xfd94,0xfd94,0xffb8,0xffb8,0xffb8, +0xffb8,0xfdb8,0xfdb8,0xffb8,0xfdb8,0xfdb8,0xffb8,0xffb8,0xfe02,0xfe02,0xfe02,0xfe02,0xfc02,0xffb8,0xffb8,0xffb8, +0xffb8,0xffcc,0xffcc,0xffcc,0x3c26,0x3c2c,0xfdcc,0x3c32,0x3c38,0xfde0,0xffcc,0xffb8,0xffb8,0xffb8,0xffcc,0xffcc, +0xffcc,0xffb8,0xffb8,1,0xffcc,0xffcc,0xffcc,0xffb8,0xffb8,0xffb8,0xffb8,0xffcc,0xffd0,0xffb8,0xffb8,0xffcc, +0xffd2,0xffd4,0xffd4,0xffd2,0xffd4,0xffd4,0xffd2,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc, +0xffcc,0xffcc,0xffcc,0xffcc,1,1,1,1,0x29d1,1,1,1,1,1,1,1, +1,1,0x29d5,1,1,1,1,1,0x17b1,0x17b7,0x29d9,0x17bd,0x17c3,0x17c9,1,0x17cf, +1,0x17d5,0x17db,0x17e3,0x618,1,1,1,0x634,1,0x644,1,0x658,1,1,1, +1,1,0x674,1,0x684,1,1,1,0x688,1,1,1,0x6a0,0x17eb,0x17f1,0xd82, +0x17f7,0xd8c,0x17fd,0x1805,0x6b4,1,1,1,0x6d4,1,0x6e4,1,0x6fc,1,1,1, +1,1,0x71c,1,0x72c,1,1,1,0x734,1,1,1,0x754,0xd96,0xda8,0x180d, +0x1813,0xdba,1,1,1,0x76c,0x1819,0x181f,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,0x1825,0x182b,1,0x1831,1,1,0x774,0x1837,1,1,1,1,0x183d, +0x1843,0x1849,1,0x778,1,1,0x780,1,0x784,0x790,0x798,0x79c,0x184f,0x7ac,1,1, +1,0x7b0,1,1,1,1,0x7b4,1,1,1,0x7c4,1,1,1,0x7c8,1, +0x7cc,1,1,0x7d0,1,1,0x7d8,1,0x7dc,0x7e8,0x7f0,0x7f4,0x1855,0x804,1,1, +1,0x808,1,1,1,0x80c,1,1,1,0x81c,1,1,1,0x820,1,0x824, +1,1,0x185b,0x1861,1,0x1867,1,1,0x828,0x186d,1,1,1,1,0x1873,0x1879, +0x187f,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,0x82c,0x830,0x1885,0x188b,1,1,1,1,1,1, +1,1,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0x1891, +0x1897,1,1,1,1,1,1,1,1,1,1,1,1,1,0x189d,0x18a3, +0x18a9,0x18af,1,1,0x18b5,0x18bb,0x834,0x838,0x18c1,0x18c7,0x18cd,0x18d3,0x18d9,0x18df,1,1, +0x18e5,0x18eb,0x18f1,0x18f7,0x18fd,0x1903,0x83c,0x840,0x1909,0x190f,0x1915,0x191b,0x1921,0x1927,0x192d,0x1933, +0x1939,0x193f,0x1945,0x194b,1,1,0x1951,0x1957,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,0xffb8,0xffcc,0xffcc,0xffcc,0xffcc,0xffb8,0xffcc, 0xffcc,0xffcc,0xffbc,0xffb8,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffb8,0xffb8,0xffb8,0xffb8,0xffb8,0xffb8, 0xffcc,0xffcc,0xffb8,0xffcc,0xffcc,0xffbc,0xffc8,0xffcc,0xfe14,0xfe16,0xfe18,0xfe1a,0xfe1c,0xfe1e,0xfe20,0xfe22, @@ -281,369 +220,415 @@ static const uint16_t norm2_nfc_data_trieIndex[9976]={ 1,1,0x85c,0x1987,1,0x860,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,1,1,0xffcc, 0xffcc,0xffcc,0xffcc,0xffb8,0xffcc,1,1,0xffcc,0xffcc,1,0xffb8,0xffcc,0xffcc,0xffb8,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,0xfe48,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +0xfe48,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0xffcc, +0xffb8,0xffcc,0xffcc,0xffb8,0xffcc,0xffcc,0xffb8,0xffb8,0xffb8,0xffcc,0xffb8,0xffb8,0xffcc,0xffb8,0xffcc,0xffcc, +0xffb8,0xffcc,0xffb8,0xffcc,0xffb8,0xffcc,0xffb8,0xffcc,0xffcc,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -0xffcc,0xffb8,0xffcc,0xffcc,0xffb8,0xffcc,0xffcc,0xffb8,0xffb8,0xffb8,0xffcc,0xffb8,0xffb8,0xffcc,0xffb8,0xffcc, -0xffcc,0xffcc,0xffb8,0xffcc,0xffb8,0xffcc,0xffb8,0xffcc,0xffb8,0xffcc,0xffcc,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,0xffcc,0xffcc, +0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffb8,0xffcc,1,1,1,1,1,1,1,1,1, +0xffb8,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,0xffcc,0xffcc,0xffcc,0xffcc,1,0xffcc,0xffcc,0xffcc,0xffcc, +0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,1,0xffcc,0xffcc,0xffcc,1,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,0xffb8,0xffb8,0xffb8,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffb8,0xffcc,1,1,1,1, -1,1,1,1,1,0xffb8,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,0xffcc,0xffcc, -0xffcc,0xffcc,1,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,1,0xffcc,0xffcc,0xffcc,1,0xffcc,0xffcc,0xffcc, -0xffcc,0xffcc,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,0xffb8,0xffb8,0xffb8, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,0xffb8,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc, -0xffcc,0xffcc,1,0xffb8,0xffcc,0xffcc,0xffb8,0xffcc,0xffcc,0xffb8,0xffcc,0xffcc,0xffcc,0xffb8,0xffb8,0xffb8, -0xfe36,0xfe38,0xfe3a,0xffcc,0xffcc,0xffcc,0xffb8,0xffcc,0xffcc,0xffb8,0xffb8,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc, -1,1,1,1,1,1,1,1,0x864,0x198d,1,1,1,1,1,1, -0x868,0x1993,1,0x86c,0x1999,1,1,1,1,1,1,1,0xfc0e,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,0xfe12,1,1, -1,0xffcc,0xffb8,0xffcc,0xffcc,1,1,1,0x29dc,0x29e2,0x29e8,0x29ee,0x29f4,0x29fa,0x2a00,0x2a06, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0xffb8, +0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,1,0xffb8, +0xffcc,0xffcc,0xffb8,0xffcc,0xffcc,0xffb8,0xffcc,0xffcc,0xffcc,0xffb8,0xffb8,0xffb8,0xfe36,0xfe38,0xfe3a,0xffcc, +0xffcc,0xffcc,0xffb8,0xffcc,0xffcc,0xffb8,0xffb8,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,0xfe0e,1,0xfc00,1, -1,1,1,1,1,1,1,0x870,1,1,1,0x199f,0x19a5,0xfe12,1,1, -1,1,1,1,1,1,1,0xfc00,1,1,1,1,0x2a0c,0x2a12,1,0x2a18, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,0xffcc,1, +1,1,1,1,0x864,0x198d,1,1,1,1,1,1,0x868,0x1993,1,0x86c, +0x1999,1,1,1,1,1,1,1,0xfc0e,1,1,1,1,1,1,1, +1,1,1,1,1,1,0xfe12,1,1,1,0xffcc,0xffb8,0xffcc,0xffcc,1,1, +1,0x29dc,0x29e2,0x29e8,0x29ee,0x29f4,0x29fa,0x2a00,0x2a06,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,0x2a1e,1,1,0x2a24,1,1,1,1,1,0xfe0e,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,0xfe12,1,1, -1,1,1,1,1,1,1,1,1,0x2a2a,0x2a30,0x2a36,1,1,0x2a3c,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,0xfe0e,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,0xfe0e,1,0xfc00,1,1,1,1,1,1,1,0x870, +1,1,1,0x199f,0x19a5,0xfe12,1,1,1,1,1,1,1,1,1,0xfc00, +1,1,1,1,0x2a0c,0x2a12,1,0x2a18,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,0xffcc,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,0x2a1e,1,1,0x2a24,1,1, +1,1,1,0xfe0e,1,1,1,1,1,1,1,1,1,1,1,1, +1,0xfe12,1,1,1,1,1,1,1,1,1,1,1,0x2a2a,0x2a30,0x2a36, +1,1,0x2a3c,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0xfe0e, 1,1,1,1,1,1,1,1,1,1,1,1,1,0xfe12,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,0x878,0x19ab,1,1,0x19b1,0x19b7,0xfe12,1,1,1,1,1,1, -1,1,0xfc00,0xfc00,1,1,1,1,0x2a42,0x2a48,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,0x884,1, -0x19bd,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,0xfc00,1,1,1,1,1,1,1,0x888,0x890,1,1,0x19c3,0x19c9, -0x19cf,0xfe12,1,1,1,1,1,1,1,1,1,0xfc00,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +0x878,0x19ab,1,1,0x19b1,0x19b7,0xfe12,1,1,1,1,1,1,1,1,0xfc00, +0xfc00,1,1,1,1,0x2a42,0x2a48,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,0x884,1,0x19bd,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,0xfc00,1,1,1,1,1,1,0x888,0x890,1,1, +0x19c3,0x19c9,0x19cf,0xfe12,1,1,1,1,1,1,1,1,1,0xfc00,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,0x894,1,0x19d5,1,1,1,1,0xfe12,1,1, 1,1,1,1,1,0xfea8,0xfcb6,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,0xfe0e,1,1,0x898,0x19db,1,0xfc00,1,1,1,0x89c,0x19e1, -0x19e7,1,0xdc4,0x19ef,1,0xfe12,1,1,1,1,1,1,1,0xfc00,0xfc00,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,0xfe12,0xfe12,1,0xfc00,1, -1,1,1,1,1,1,0x8a8,0x8b0,1,1,0x19f7,0x19fd,0x1a03,0xfe12,1,1, -1,1,1,1,1,1,1,0xfc00,1,1,1,1,1,1,1,1, -1,1,0xfc12,1,1,1,1,0xfc00,1,1,1,1,1,1,1,1, -1,0x8b4,0x1a09,1,0xdce,0x1a11,0x1a19,0xfc00,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -0xfece,0xfece,0xfe12,1,1,1,1,1,1,1,1,1,0xfed6,0xfed6,0xfed6,0xfed6, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,0xfeec,0xfeec,1,1,1,1,1,1, -1,1,1,1,0xfef4,0xfef4,0xfef4,0xfef4,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -0xffb8,0xffb8,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,0xffb8,1,0xffb8,1,0xffb0,1,1, -1,1,1,1,1,1,1,0x2a4f,1,1,1,1,1,1,1,1, -1,0x2a55,1,1,1,1,0x2a5b,1,1,1,1,0x2a61,1,1,1,1, -0x2a67,1,1,1,1,1,1,1,1,1,1,1,1,0x2a6d,1,1, -1,1,1,1,1,0xff02,0xff04,0x3c40,0xff08,0x3c48,0x2a72,1,0x2a78,1,0xff04,0xff04, -0xff04,0xff04,1,1,0xff04,0x3c50,0xffcc,0xffcc,0xfe12,1,0xffcc,0xffcc,1,1,1,1, -1,1,1,1,1,1,1,0x2a7f,1,1,1,1,1,1,1,1, -1,0x2a85,1,1,1,1,0x2a8b,1,1,1,1,0x2a91,1,1,1,1, -0x2a97,1,1,1,1,1,1,1,1,1,1,1,1,0x2a9d,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,0xfe0e,1,1,0x898,0x19db,1,0xfc00,1,1,1,0x89c,0x19e1,0x19e7, +1,0xdc4,0x19ef,1,0xfe12,1,1,1,1,1,1,1,0xfc00,0xfc00,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,0xfe12,0xfe12,1,0xfc00,1,1,1, +1,1,1,0x8a8,0x8b0,1,1,0x19f7,0x19fd,0x1a03,0xfe12,1,1,1,1,1, +1,1,1,1,0xfc00,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,0xfc12,1,1, +1,1,0xfc00,1,1,1,1,1,1,1,1,1,0x8b4,0x1a09,1,0xdce, +0x1a11,0x1a19,0xfc00,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,0xfece,0xfece,0xfe12,1,1, +1,1,1,1,1,1,0xfed6,0xfed6,0xfed6,0xfed6,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,0xfeec,0xfeec,1,1,1,1,1,1,1,1,0xfef4,0xfef4,0xfef4,0xfef4, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,0xffb8,0xffb8,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,0xffb8,1,0xffb8,1,0xffb0,1,1,1,1,1,1,0x2a4f,1,1,1, +1,1,1,1,1,1,0x2a55,1,1,1,1,0x2a5b,1,1,1,1, +0x2a61,1,1,1,1,0x2a67,1,1,1,1,1,1,1,1,1,1, +1,1,0x2a6d,1,1,1,1,1,1,1,0xff02,0xff04,0x3c40,0xff08,0x3c48,0x2a72, +1,0x2a78,1,0xff04,0xff04,0xff04,0xff04,1,1,0xff04,0x3c50,0xffcc,0xffcc,0xfe12,1,0xffcc, +0xffcc,1,1,1,1,1,1,1,1,1,1,1,0x2a7f,1,1,1, +1,1,1,1,1,1,0x2a85,1,1,1,1,0x2a8b,1,1,1,1, +0x2a91,1,1,1,1,0x2a97,1,1,1,1,1,1,1,1,1,1, +1,1,0x2a9d,1,1,1,1,1,1,0xffb8,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,0x8c0,0x1a1f,1,1,1,1,1,1,1,0xfc00,1,1,1, +1,1,1,1,1,0xfe0e,1,0xfe12,0xfe12,1,1,1,1,1,1,1, 1,1,1,1,1,1,0xffb8,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,0x8c0,0x1a1f,1,1,1,1,1,1,1,0xfc00,1,1,1,1,1, -1,1,1,0xfe0e,1,0xfe12,0xfe12,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,0xffb8,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,0xffcc,0xffcc,0xffcc,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,0xfe12,1,1,1, +1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2, +2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,0xfe12,1,1,1,1,1,1,1,1,1,1,0xffcc,1,1, -1,1,1,1,1,1,1,1,1,0xffc8,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,0xffbc,0xffcc,0xffb8,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0xffcc, -0xffb8,1,1,1,1,1,1,1,0xfe12,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,0xffcc,0xffcc,0xffcc, -0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,1,1,0xffb8,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffb8,0xffb8,0xffb8, -0xffb8,0xffb8,0xffb8,0xffcc,0xffcc,0xffb8,1,1,1,1,1,1,1,0x8c4,0x1a25,0x8c8, -0x1a2b,0x8cc,0x1a31,0x8d0,0x1a37,0x8d4,0x1a3d,1,1,0x8d8,0x1a43,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -0xfe0e,0xfc00,1,1,1,1,0x8dc,0x1a49,0x8e0,0x1a4f,0x8e4,0x8e8,0x1a55,0x1a5b,0x8ec,0x1a61, -0xfe12,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0xffcc, -0xffb8,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,0xfe12,0xfe12,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,0xfe0e,1, -1,1,1,1,1,1,1,1,1,1,0xfe12,0xfe12,1,1,1,1, +1,1,1,1,1,1,1,1,1,0xfe00,0xfe00,0xfe00,0xfe00,0xfe00,0xfe00,0xfe00, +0xfe00,0xfe00,0xfe00,0xfe00,0xfe00,0xfe00,0xfe00,0xfe00,0xfe00,0xfe00,0xfe00,0xfe00,0xfe00,0xfe00,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,0xfe0e,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,0xffcc,0xffcc,0xffcc,1,0xfe02,0xffb8,0xffb8,0xffb8,0xffb8,0xffb8,0xffcc,0xffcc, -0xffb8,0xffb8,0xffb8,0xffb8,0xffcc,1,0xfe02,0xfe02,0xfe02,0xfe02,0xfe02,0xfe02,0xfe02,1,1,1, -1,0xffb8,1,1,1,1,1,1,0xffcc,1,1,1,0xffcc,0xffcc,1,1, -1,1,1,1,0xffcc,0xffcc,0xffb8,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffb8,0xffcc, -0xffcc,0xffd4,0xffac,0xffb8,0xff94,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc, -0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffd0,0xffc8, -0xffc8,0xffb8,1,0xffcc,0xffd2,0xffb8,0xffcc,0xffb8,0x1a66,0x1a6c,0x1a72,0x1a78,0x1a7f,0x1a85,0x1a8b,0x1a91, -0x1a99,0x1aa3,0x1aaa,0x1ab0,0x1ab6,0x1abc,0x1ac2,0x1ac8,0x1acf,0x1ad5,0x1ada,0x1ae0,0x1ae8,0x1af2,0x1afc,0x1b06, -0x1b0e,0x1b14,0x1b1a,0x1b20,0x1b29,0x1b33,0x1b3b,0x1b41,0x1b46,0x1b4c,0x1b52,0x1b58,0x1b5e,0x1b64,0x1b6a,0x1b70, -0x1b77,0x1b7d,0x1b82,0x1b88,0x1b8e,0x1b94,0x1b9c,0x1ba6,0x1bae,0x1bb4,0x1bba,0x1bc0,0x1bc6,0x1bcc,0xdd8,0xde2, -0x1bd4,0x1bde,0x1be6,0x1bec,0x1bf2,0x1bf8,0x1bfe,0x1c04,0x1c0a,0x1c10,0x1c17,0x1c1d,0x1c22,0x1c28,0x1c2e,0x1c34, -0x1c3a,0x1c40,0x1c46,0x1c4c,0x1c54,0x1c5e,0x1c68,0x1c72,0x1c7c,0x1c86,0x1c90,0x1c9a,0x1ca3,0x1ca9,0x1caf,0x1cb5, -0x1cba,0x1cc0,0xdec,0xdf6,0x1cc8,0x1cd2,0x1cda,0x1ce0,0x1ce6,0x1cec,0xe00,0xe0a,0x1cf4,0x1cfe,0x1d08,0x1d12, -0x1d1c,0x1d26,0x1d2e,0x1d34,0x1d3a,0x1d40,0x1d46,0x1d4c,0x1d52,0x1d58,0x1d5e,0x1d64,0x1d6a,0x1d70,0x1d76,0x1d7c, -0x1d84,0x1d8e,0x1d98,0x1da2,0x1daa,0x1db0,0x1db7,0x1dbd,0x1dc2,0x1dc8,0x1dce,0x1dd4,0x1dda,0x1de0,0x1de6,0x1dec, -0x1df3,0x1df9,0x1dff,0x1e05,0x1e0b,0x1e11,0x1e16,0x1e1c,0x1e22,0x1e28,0x1e2f,0x1e35,0x1e3b,0x1e41,0x1e46,0x1e4c, -0x1e52,0x1e58,1,0x1e5f,1,1,1,1,0xe14,0xe22,0x1e64,0x1e6a,0x1e72,0x1e7c,0x1e86,0x1e90, -0x1e9a,0x1ea4,0x1eae,0x1eb8,0x1ec2,0x1ecc,0x1ed6,0x1ee0,0x1eea,0x1ef4,0x1efe,0x1f08,0x1f12,0x1f1c,0x1f26,0x1f30, -0xe30,0xe3a,0x1f38,0x1f3e,0x1f44,0x1f4a,0x1f52,0x1f5c,0x1f66,0x1f70,0x1f7a,0x1f84,0x1f8e,0x1f98,0x1fa2,0x1fac, -0x1fb4,0x1fba,0x1fc0,0x1fc6,0xe44,0xe4e,0x1fcc,0x1fd2,0x1fda,0x1fe4,0x1fee,0x1ff8,0x2002,0x200c,0x2016,0x2020, -0x202a,0x2034,0x203e,0x2048,0x2052,0x205c,0x2066,0x2070,0x207a,0x2084,0x208e,0x2098,0x20a0,0x20a6,0x20ac,0x20b2, -0x20ba,0x20c4,0x20ce,0x20d8,0x20e2,0x20ec,0x20f6,0x2100,0x210a,0x2114,0x211c,0x2122,0x2129,0x212f,0x2134,0x213a, -0x2140,0x2146,1,1,1,1,1,1,0xe58,0xe6e,0xe86,0xe94,0xea2,0xeb0,0xebe,0xecc, -0xed8,0xeee,0xf06,0xf14,0xf22,0xf30,0xf3e,0xf4c,0xf58,0xf66,0x214f,0x2159,0x2163,0x216d,1,1, -0xf74,0xf82,0x2177,0x2181,0x218b,0x2195,1,1,0xf90,0xfa6,0xfbe,0xfcc,0xfda,0xfe8,0xff6,0x1004, -0x1010,0x1026,0x103e,0x104c,0x105a,0x1068,0x1076,0x1084,0x1090,0x10a2,0x219f,0x21a9,0x21b3,0x21bd,0x21c7,0x21d1, -0x10b4,0x10c6,0x21db,0x21e5,0x21ef,0x21f9,0x2203,0x220d,0x10d8,0x10e6,0x2217,0x2221,0x222b,0x2235,1,1, -0x10f4,0x1102,0x223f,0x2249,0x2253,0x225d,1,1,0x1110,0x1122,0x2267,0x2271,0x227b,0x2285,0x228f,0x2299, -1,0x1134,1,0x22a3,1,0x22ad,1,0x22b7,0x1146,0x115c,0x1174,0x1182,0x1190,0x119e,0x11ac,0x11ba, -0x11c6,0x11dc,0x11f4,0x1202,0x1210,0x121e,0x122c,0x123a,0x1246,0x3b8e,0x22bf,0x3b96,0x1250,0x3b9e,0x22c5,0x3ba6, -0x22cb,0x3bae,0x22d1,0x3bb6,0x125a,0x3bbe,1,1,0x22d8,0x22e2,0x22f1,0x2301,0x2311,0x2321,0x2331,0x2341, -0x234c,0x2356,0x2365,0x2375,0x2385,0x2395,0x23a5,0x23b5,0x23c0,0x23ca,0x23d9,0x23e9,0x23f9,0x2409,0x2419,0x2429, -0x2434,0x243e,0x244d,0x245d,0x246d,0x247d,0x248d,0x249d,0x24a8,0x24b2,0x24c1,0x24d1,0x24e1,0x24f1,0x2501,0x2511, -0x251c,0x2526,0x2535,0x2545,0x2555,0x2565,0x2575,0x2585,0x258f,0x2595,0x259d,0x25a4,0x25ad,1,0x1264,0x25b7, -0x25bf,0x25c5,0x25cb,0x3bc6,0x25d0,1,0x2aa2,0x8f0,1,0x25d7,0x25df,0x25e6,0x25ef,1,0x126e,0x25f9, -0x2601,0x3bce,0x2607,0x3bd6,0x260c,0x2613,0x2619,0x261f,0x2625,0x262b,0x2633,0x3be0,1,1,0x263b,0x2643, -0x264b,0x2651,0x2657,0x3bea,1,0x265d,0x2663,0x2669,0x266f,0x2675,0x267d,0x3bf4,0x2685,0x268b,0x2691,0x2699, -0x26a1,0x26a7,0x26ad,0x3bfe,0x26b3,0x26b9,0x3c06,0x2aa7,1,1,0x26c1,0x26c8,0x26d1,1,0x1278,0x26db, -0x26e3,0x3c0e,0x26e9,0x3c16,0x26ee,0x2aab,0x8fc,1,0xfa09,0xfa09,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,0xffcc,0xffcc,0xfe02,0xfe02,0xffcc,0xffcc,0xffcc,0xffcc, -0xfe02,0xfe02,0xfe02,0xffcc,0xffcc,1,1,1,1,0xffcc,1,1,1,0xfe02,0xfe02,0xffcc, -0xffb8,0xffcc,0xfe02,0xfe02,0xffb8,0xffb8,0xffb8,0xffb8,0xffcc,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,0x2aae,1,1,1,0x2ab2,0x3c1e, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,0x908,1,0x90c,1,0x910,1,1,1,1,1,0x26f5,0x26fb, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,0x2701,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,0x2707,0x270d,0x2713,0x914,1,0x918,1,0x91c,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,0x920,0x2719,1,1,1,0x924,0x271f,1,0x928, -0x2725,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,0x92c,0x272b,0x930,0x2731,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -0x934,1,1,1,1,0x2737,1,0x938,0x273d,0x93c,1,0x2743,0x940,0x2749,1,1, -1,0x944,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,0x274f,0x948,0x2755,1,0x94c,0x950,1,1,1,1,1,1, -1,0x275b,0x2761,0x2767,0x276d,0x2773,0x954,0x958,0x2779,0x277f,0x95c,0x960,0x2785,0x278b,0x964,0x968, -0x96c,0x970,1,1,0x2791,0x2797,0x974,0x978,0x279d,0x27a3,0x97c,0x980,0x27a9,0x27af,1,1, -1,1,1,1,1,0x984,0x988,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,0x98c,1,1,1,1,1,0x990,0x994,1,0x998, -0x27b5,0x27bb,0x27c1,0x27c7,1,1,0x99c,0x9a0,0x9a4,0x9a8,1,1,1,1,1,1, -1,1,1,1,0x27cd,0x27d3,0x27d9,0x27df,1,1,1,1,1,1,0x27e5,0x27eb, -0x27f1,0x27f7,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,0x2ab7,0x2abb,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,0x2abf,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,0xffcc,0xffcc,0xffcc,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,0xfe12,0xffcc,0xffcc,0xffcc,0xffcc, -0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc, -0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,1,1,1,1, -1,1,1,1,1,1,0xffb4,0xffc8,0xffd0,0xffbc,0xffc0,0xffc0,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,0x9ac,1, -1,1,1,0x9b0,0x27fd,0x9b4,0x2803,0x9b8,0x2809,0x9bc,0x280f,0x9c0,0x2815,0x9c4,0x281b,0x9c8, -0x2821,0x9cc,0x2827,0x9d0,0x282d,0x9d4,0x2833,0x9d8,0x2839,0x9dc,0x283f,1,0x9e0,0x2845,0x9e4,0x284b, -0x9e8,0x2851,1,1,1,1,1,0x9ec,0x2857,0x285d,0x9f4,0x2863,0x2869,0x9fc,0x286f,0x2875, -0xa04,0x287b,0x2881,0xa0c,0x2887,0x288d,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,0x2893,1,1,1, -1,0xfc10,0xfc10,1,1,0xa14,0x2899,1,1,1,1,1,1,1,0xa18,1, -1,1,1,0xa1c,0x289f,0xa20,0x28a5,0xa24,0x28ab,0xa28,0x28b1,0xa2c,0x28b7,0xa30,0x28bd,0xa34, -0x28c3,0xa38,0x28c9,0xa3c,0x28cf,0xa40,0x28d5,0xa44,0x28db,0xa48,0x28e1,1,0xa4c,0x28e7,0xa50,0x28ed, -0xa54,0x28f3,1,1,1,1,1,0xa58,0x28f9,0x28ff,0xa60,0x2905,0x290b,0xa68,0x2911,0x2917, -0xa70,0x291d,0x2923,0xa78,0x2929,0x292f,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,0xa80,0xa84,0xa88,0xa8c,1,0x2935,1,1,0x293b, -0x2941,0x2947,0x294d,1,1,0xa90,0x2953,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,0xffcc,1,1,1,1,0xffcc,0xffcc,0xffcc,0xffcc, -0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,0xffcc,0xffcc,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,0xffcc,0xffcc,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,0xfe12,1,1,1,1,1, +1,1,1,1,1,1,0xfe00,0xfe00,0xfe00,0xfe00,0xfe00,0xfe00,0xfe00,0xfe00,0xfe00,0xfe00, +0xfe00,0xfe00,0xfe00,0xfe00,0xfe00,0xfe00,0xfe00,0xfe00,0xfe00,0xfe00,0xfe00,0xfe00,0xfe00,0xfe00,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,0xfe12,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc, -0xffcc,0xffcc,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,0xffb8,0xffb8,0xffb8,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,0xfe12,1,1,1,1, -1,1,1,1,1,1,1,1,0xfe12,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,0xffcc,1,0xffcc,0xffcc,0xffb8,1,1,0xffcc, -0xffcc,1,1,1,1,1,0xffcc,0xffcc,1,0xffcc,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,0xffcc,0xffcc,0xffcc,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,0xfe12,1,1,1,1,1, -1,1,1,1,0x2ac5,0x2ac9,0x2acd,0x2ad1,0x2ad5,0x2ad9,0x2add,0x2ae1,0x2ae1,0x2ae5,0x2ae9,0x2aed, -0x2af1,0x2af5,0x2af9,0x2afd,0x2b01,0x2b05,0x2b09,0x2b0d,0x2b11,0x2b15,0x2b19,0x2b1d,0x2b21,0x2b25,0x2b29,0x2b2d, -0x2b31,0x2b35,0x2b39,0x2b3d,0x2b41,0x2b45,0x2b49,0x2b4d,0x2b51,0x2b55,0x2b59,0x2b5d,0x2b61,0x2b65,0x2b69,0x2b6d, -0x2b71,0x2b75,0x2b79,0x2b7d,0x2b81,0x2b85,0x2b89,0x2b8d,0x2b91,0x2b95,0x2b99,0x2b9d,0x2ba1,0x2ba5,0x2ba9,0x2bad, -0x2bb1,0x2bb5,0x2bb9,0x2bbd,0x2bc1,0x2bc5,0x2bc9,0x2bcd,0x2bd1,0x2bd5,0x2bd9,0x2bdd,0x2be1,0x2be5,0x2be9,0x2bed, -0x2bf1,0x2bf5,0x2bf9,0x2bfd,0x2c01,0x2c05,0x2c09,0x2c0d,0x2c11,0x2c15,0x2c19,0x2c1d,0x2c21,0x2c25,0x2c29,0x2c2d, -0x2b11,0x2c31,0x2c35,0x2c39,0x2c3d,0x2c41,0x2c45,0x2c49,0x2c4d,0x2c51,0x2c55,0x2c59,0x2c5d,0x2c61,0x2c65,0x2c69, -0x2c6d,0x2c71,0x2c75,0x2c79,0x2c7d,0x2c81,0x2c85,0x2c89,0x2c8d,0x2c91,0x2c95,0x2c99,0x2c9d,0x2ca1,0x2ca5,0x2ca9, -0x2cad,0x2cb1,0x2cb5,0x2cb9,0x2cbd,0x2cc1,0x2cc5,0x2cc9,0x2ccd,0x2cd1,0x2cd5,0x2cd9,0x2cdd,0x2ce1,0x2ce5,0x2ce9, -0x2ced,0x2cf1,0x2cf5,0x2cf9,0x2cfd,0x2d01,0x2d05,0x2d09,0x2d0d,0x2d11,0x2d15,0x2d19,0x2d1d,0x2d21,0x2d25,0x2d29, -0x2d2d,0x2d31,0x2d35,0x2d39,0x2d3d,0x2c79,0x2d41,0x2d45,0x2d49,0x2d4d,0x2d51,0x2d55,0x2d59,0x2d5d,0x2c39,0x2d61, -0x2d65,0x2d69,0x2d6d,0x2d71,0x2d75,0x2d79,0x2d7d,0x2d81,0x2d85,0x2d89,0x2d8d,0x2d91,0x2d95,0x2d99,0x2d9d,0x2da1, -0x2da5,0x2da9,0x2dad,0x2b11,0x2db1,0x2db5,0x2db9,0x2dbd,0x2dc1,0x2dc5,0x2dc9,0x2dcd,0x2dd1,0x2dd5,0x2dd9,0x2ddd, -0x2de1,0x2de5,0x2de9,0x2ded,0x2df1,0x2df5,0x2df9,0x2dfd,0x2e01,0x2e05,0x2e09,0x2e0d,0x2e11,0x2e15,0x2e19,0x2c41, -0x2e1d,0x2e21,0x2e25,0x2e29,0x2e2d,0x2e31,0x2e35,0x2e39,0x2e3d,0x2e41,0x2e45,0x2e49,0x2e4d,0x2e51,0x2e55,0x2e59, -0x2e5d,0x2e61,0x2e65,0x2e69,0x2e6d,0x2e71,0x2e75,0x2e79,0x2e7d,0x2e81,0x2e85,0x2e89,0x2e8d,0x2e91,0x2e95,0x2e99, -0x2e9d,0x2ea1,0x2ea5,0x2ea9,0x2ead,0x2eb1,0x2eb5,0x2eb9,0x2ebd,0x2ec1,0x2ec5,0x2ec9,0x2ecd,0x2ed1,0x2ed5,0x2ed9, -0x2edd,0x2ee1,1,1,0x2ee5,1,0x2ee9,1,1,0x2eed,0x2ef1,0x2ef5,0x2ef9,0x2efd,0x2f01,0x2f05, -0x2f09,0x2f0d,0x2f11,1,0x2f15,1,0x2f19,1,1,0x2f1d,0x2f21,1,1,1,0x2f25,0x2f29, -0x2f2d,0x2f31,0x2f35,0x2f39,0x2f3d,0x2f41,0x2f45,0x2f49,0x2f4d,0x2f51,0x2f55,0x2f59,0x2f5d,0x2f61,0x2f65,0x2f69, -0x2f6d,0x2f71,0x2f75,0x2f79,0x2f7d,0x2f81,0x2f85,0x2f89,0x2f8d,0x2f91,0x2f95,0x2f99,0x2f9d,0x2fa1,0x2fa5,0x2fa9, -0x2fad,0x2fb1,0x2fb5,0x2fb9,0x2fbd,0x2fc1,0x2fc5,0x2fc9,0x2fcd,0x2fd1,0x2fd5,0x2d15,0x2fd9,0x2fdd,0x2fe1,0x2fe5, -0x2fe9,0x2fed,0x2fed,0x2ff1,0x2ff5,0x2ff9,0x2ffd,0x3001,0x3005,0x3009,0x300d,0x2f1d,0x3011,0x3015,0x3019,0x301d, -0x3021,0x3027,1,1,0x302b,0x302f,0x3033,0x3037,0x303b,0x303f,0x3043,0x3047,0x2f55,0x304b,0x304f,0x3053, -0x2ee5,0x3057,0x305b,0x305f,0x3063,0x3067,0x306b,0x306f,0x3073,0x3077,0x307b,0x307f,0x3083,0x2f79,0x3087,0x2f7d, -0x308b,0x308f,0x3093,0x3097,0x309b,0x2ee9,0x2b65,0x309f,0x30a3,0x30a7,0x2c7d,0x2dd9,0x30ab,0x30af,0x2f99,0x30b3, -0x2f9d,0x30b7,0x30bb,0x30bf,0x2ef1,0x30c3,0x30c7,0x30cb,0x30cf,0x30d3,0x2ef5,0x30d7,0x30db,0x30df,0x30e3,0x30e7, -0x30eb,0x2fd5,0x30ef,0x30f3,0x2d15,0x30f7,0x2fe5,0x30fb,0x30ff,0x3103,0x3107,0x310b,0x2ff9,0x310f,0x2f19,0x3113, -0x2ffd,0x2c31,0x3117,0x3001,0x311b,0x3009,0x311f,0x3123,0x3127,0x312b,0x312f,0x3011,0x2f09,0x3133,0x3015,0x3137, -0x3019,0x313b,0x2ae1,0x313f,0x3145,0x314b,0x3151,0x3155,0x3159,0x315d,0x3163,0x3169,0x316f,0x3173,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,0x3176,0xfe34,0x317c, -1,1,1,1,1,1,1,1,1,1,0x3182,0x3188,0x3190,0x319a,0x31a2,0x31a8, -0x31ae,0x31b4,0x31ba,0x31c0,0x31c6,0x31cc,0x31d2,1,0x31d8,0x31de,0x31e4,0x31ea,0x31f0,1,0x31f6,1, -0x31fc,0x3202,1,0x3208,0x320e,1,0x3214,0x321a,0x3220,0x3226,0x322c,0x3232,0x3238,0x323e,0x3244,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffb8,0xffb8,0xffb8,0xffb8,0xffb8,0xffb8,0xffb8,0xffcc,0xffcc, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,0xffb8,1,1, -0xffb8,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,0xfe12,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,0xffb8,1,0xffcc,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,0xfe12,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -0xffcc,0xfe02,0xffb8,1,1,1,1,0xfe12,1,1,1,1,1,0xffcc,0xffb8,1, +1,0xfe12,1,1,1,1,1,1,1,1,1,1,0xffcc,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,0xffcc,0xffcc,0xffcc,0xffcc,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,0xffb8,0xffb8,0xffcc,0xffcc,0xffcc,0xffb8,0xffcc,0xffb8,0xffb8,0xffb8, -0xffb8,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,0xa94,0x2959,0xa9a, -0x2963,1,1,1,1,1,1,1,1,0xaa0,1,1,1,1,1,0x296d, -1,1,1,1,1,1,1,1,1,1,1,1,1,0xfe12,0xfc0e,1, -1,1,1,1,0xffcc,0xffcc,0xffcc,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,0xffc8,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,0xfc00,1,1,1,1,1,1,0x2977,0x2981, -1,0xaa6,0xaac,0xfe12,0xfe12,1,1,1,1,1,1,1,1,1,1,1, -0xfe12,1,1,1,1,1,1,1,1,1,0xfe0e,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,0xfe12,0xfe0e,1,1,1,1,1,1,1,1,1,1,0xfe0e,0xfe12,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,0xfe0e,0xfe0e,1,0xfc00,1, -1,1,1,1,1,1,1,0xab2,1,1,1,0x298b,0x2995,0xfe12,1,1, -1,1,1,1,1,1,1,0xfc00,1,1,1,1,1,1,1,1, -1,1,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,1,1,1,0xffcc,0xffcc,0xffcc,0xffcc, -0xffcc,1,1,1,1,1,1,1,1,1,1,1,1,1,0xfe12,1, -1,1,0xfe0e,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,0xffcc,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,0xfc00,1,1,1, -1,1,1,1,1,0xabe,0xfc00,0x299f,0x29a9,0xfc00,0x29b3,1,1,1,0xfe12,0xfe0e, +0xffbc,0xffcc,0xffb8,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,0xffcc,0xffb8,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0xfc00, -1,1,1,1,1,1,1,1,0xad0,0xad6,0x29bd,0x29c7,1,1,1,0xfe12, -0xfe0e,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,0xfe12,0xfe0e,1,1,1,1,1,1,1,1,1,1,1,0xfe12, +1,1,1,0xfe12,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc, +1,1,0xffb8,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,0xfe12,0xfe0e,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,0xfe12,1,1,1,1,1,1,1,1,0xfe0e,1, -0xfe12,0xfe12,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0xfe12, +1,1,1,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffb8,0xffb8,0xffb8,0xffb8,0xffb8,0xffb8,0xffcc,0xffcc, +0xffb8,1,1,1,1,1,0x8c4,0x1a25,0x8c8,0x1a2b,0x8cc,0x1a31,0x8d0,0x1a37,0x8d4,0x1a3d, +1,1,0x8d8,0x1a43,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,0xfe0e,0xfc00,1,1,1,1,0x8dc,0x1a49,0x8e0,0x1a4f,0x8e4, +0x8e8,0x1a55,0x1a5b,0x8ec,0x1a61,0xfe12,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -0xfe02,0xfe02,0xfe02,0xfe02,0xfe02,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,1, +1,1,1,1,1,1,1,1,1,1,1,1,0xffcc,0xffb8,0xffcc,0xffcc, +0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0xfe12, +0xfe12,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,0xfe02,1, +1,1,1,1,1,1,1,0xfe0e,1,1,1,1,1,1,1,1, +1,1,1,0xfe12,0xfe12,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,0xffcc,0xffcc,0xffcc,1,0xfe02,0xffb8,0xffb8,0xffb8,0xffb8,0xffb8,0xffcc, +0xffcc,0xffb8,0xffb8,0xffb8,0xffb8,0xffcc,1,0xfe02,0xfe02,0xfe02,0xfe02,0xfe02,0xfe02,0xfe02,1,1, +1,1,0xffb8,1,1,1,1,1,1,0xffcc,1,1,1,0xffcc,0xffcc,1, +1,1,1,1,1,0xffcc,0xffcc,0xffb8,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffb8, +0xffcc,0xffcc,0xffd4,0xffac,0xffb8,0xff94,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc, +0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc, +0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffd0,0xffc8,0xffc8,0xffb8,1, +0xffcc,0xffd2,0xffb8,0xffcc,0xffb8,0x1a66,0x1a6c,0x1a72,0x1a78,0x1a7f,0x1a85,0x1a8b,0x1a91,0x1a99,0x1aa3,0x1aaa, +0x1ab0,0x1ab6,0x1abc,0x1ac2,0x1ac8,0x1acf,0x1ad5,0x1ada,0x1ae0,0x1ae8,0x1af2,0x1afc,0x1b06,0x1b0e,0x1b14,0x1b1a, +0x1b20,0x1b29,0x1b33,0x1b3b,0x1b41,0x1b46,0x1b4c,0x1b52,0x1b58,0x1b5e,0x1b64,0x1b6a,0x1b70,0x1b77,0x1b7d,0x1b82, +0x1b88,0x1b8e,0x1b94,0x1b9c,0x1ba6,0x1bae,0x1bb4,0x1bba,0x1bc0,0x1bc6,0x1bcc,0xdd8,0xde2,0x1bd4,0x1bde,0x1be6, +0x1bec,0x1bf2,0x1bf8,0x1bfe,0x1c04,0x1c0a,0x1c10,0x1c17,0x1c1d,0x1c22,0x1c28,0x1c2e,0x1c34,0x1c3a,0x1c40,0x1c46, +0x1c4c,0x1c54,0x1c5e,0x1c68,0x1c72,0x1c7c,0x1c86,0x1c90,0x1c9a,0x1ca3,0x1ca9,0x1caf,0x1cb5,0x1cba,0x1cc0,0xdec, +0xdf6,0x1cc8,0x1cd2,0x1cda,0x1ce0,0x1ce6,0x1cec,0xe00,0xe0a,0x1cf4,0x1cfe,0x1d08,0x1d12,0x1d1c,0x1d26,0x1d2e, +0x1d34,0x1d3a,0x1d40,0x1d46,0x1d4c,0x1d52,0x1d58,0x1d5e,0x1d64,0x1d6a,0x1d70,0x1d76,0x1d7c,0x1d84,0x1d8e,0x1d98, +0x1da2,0x1daa,0x1db0,0x1db7,0x1dbd,0x1dc2,0x1dc8,0x1dce,0x1dd4,0x1dda,0x1de0,0x1de6,0x1dec,0x1df3,0x1df9,0x1dff, +0x1e05,0x1e0b,0x1e11,0x1e16,0x1e1c,0x1e22,0x1e28,0x1e2f,0x1e35,0x1e3b,0x1e41,0x1e46,0x1e4c,0x1e52,0x1e58,1, +0x1e5f,1,1,1,1,0xe14,0xe22,0x1e64,0x1e6a,0x1e72,0x1e7c,0x1e86,0x1e90,0x1e9a,0x1ea4,0x1eae, +0x1eb8,0x1ec2,0x1ecc,0x1ed6,0x1ee0,0x1eea,0x1ef4,0x1efe,0x1f08,0x1f12,0x1f1c,0x1f26,0x1f30,0xe30,0xe3a,0x1f38, +0x1f3e,0x1f44,0x1f4a,0x1f52,0x1f5c,0x1f66,0x1f70,0x1f7a,0x1f84,0x1f8e,0x1f98,0x1fa2,0x1fac,0x1fb4,0x1fba,0x1fc0, +0x1fc6,0xe44,0xe4e,0x1fcc,0x1fd2,0x1fda,0x1fe4,0x1fee,0x1ff8,0x2002,0x200c,0x2016,0x2020,0x202a,0x2034,0x203e, +0x2048,0x2052,0x205c,0x2066,0x2070,0x207a,0x2084,0x208e,0x2098,0x20a0,0x20a6,0x20ac,0x20b2,0x20ba,0x20c4,0x20ce, +0x20d8,0x20e2,0x20ec,0x20f6,0x2100,0x210a,0x2114,0x211c,0x2122,0x2129,0x212f,0x2134,0x213a,0x2140,0x2146,1, +1,1,1,1,1,0xe58,0xe6e,0xe86,0xe94,0xea2,0xeb0,0xebe,0xecc,0xed8,0xeee,0xf06, +0xf14,0xf22,0xf30,0xf3e,0xf4c,0xf58,0xf66,0x214f,0x2159,0x2163,0x216d,1,1,0xf74,0xf82,0x2177, +0x2181,0x218b,0x2195,1,1,0xf90,0xfa6,0xfbe,0xfcc,0xfda,0xfe8,0xff6,0x1004,0x1010,0x1026,0x103e, +0x104c,0x105a,0x1068,0x1076,0x1084,0x1090,0x10a2,0x219f,0x21a9,0x21b3,0x21bd,0x21c7,0x21d1,0x10b4,0x10c6,0x21db, +0x21e5,0x21ef,0x21f9,0x2203,0x220d,0x10d8,0x10e6,0x2217,0x2221,0x222b,0x2235,1,1,0x10f4,0x1102,0x223f, +0x2249,0x2253,0x225d,1,1,0x1110,0x1122,0x2267,0x2271,0x227b,0x2285,0x228f,0x2299,1,0x1134,1, +0x22a3,1,0x22ad,1,0x22b7,0x1146,0x115c,0x1174,0x1182,0x1190,0x119e,0x11ac,0x11ba,0x11c6,0x11dc,0x11f4, +0x1202,0x1210,0x121e,0x122c,0x123a,0x1246,0x3b8e,0x22bf,0x3b96,0x1250,0x3b9e,0x22c5,0x3ba6,0x22cb,0x3bae,0x22d1, +0x3bb6,0x125a,0x3bbe,1,1,0x22d8,0x22e2,0x22f1,0x2301,0x2311,0x2321,0x2331,0x2341,0x234c,0x2356,0x2365, +0x2375,0x2385,0x2395,0x23a5,0x23b5,0x23c0,0x23ca,0x23d9,0x23e9,0x23f9,0x2409,0x2419,0x2429,0x2434,0x243e,0x244d, +0x245d,0x246d,0x247d,0x248d,0x249d,0x24a8,0x24b2,0x24c1,0x24d1,0x24e1,0x24f1,0x2501,0x2511,0x251c,0x2526,0x2535, +0x2545,0x2555,0x2565,0x2575,0x2585,0x258f,0x2595,0x259d,0x25a4,0x25ad,1,0x1264,0x25b7,0x25bf,0x25c5,0x25cb, +0x3bc6,0x25d0,1,0x2aa2,0x8f0,1,0x25d7,0x25df,0x25e6,0x25ef,1,0x126e,0x25f9,0x2601,0x3bce,0x2607, +0x3bd6,0x260c,0x2613,0x2619,0x261f,0x2625,0x262b,0x2633,0x3be0,1,1,0x263b,0x2643,0x264b,0x2651,0x2657, +0x3bea,1,0x265d,0x2663,0x2669,0x266f,0x2675,0x267d,0x3bf4,0x2685,0x268b,0x2691,0x2699,0x26a1,0x26a7,0x26ad, +0x3bfe,0x26b3,0x26b9,0x3c06,0x2aa7,1,1,0x26c1,0x26c8,0x26d1,1,0x1278,0x26db,0x26e3,0x3c0e,0x26e9, +0x3c16,0x26ee,0x2aab,0x8fc,1,0xfa09,0xfa09,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,0xffcc,0xffcc,0xfe02,0xfe02,0xffcc,0xffcc,0xffcc,0xffcc,0xfe02,0xfe02,0xfe02, +0xffcc,0xffcc,1,1,1,1,0xffcc,1,1,1,0xfe02,0xfe02,0xffcc,0xffb8,0xffcc,0xfe02, +0xfe02,0xffb8,0xffb8,0xffb8,0xffb8,0xffcc,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,0x2aae,1,1,1, +0x2ab2,0x3c1e,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,0x908,1,0x90c,1,0x910,1,1,1,1,1, +0x26f5,0x26fb,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,0x2701,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,0x2707,0x270d,0x2713,0x914,1,0x918,1,0x91c,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,0x920,0x2719,1,1,1,0x924,0x271f, +1,0x928,0x2725,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,0x92c,0x272b,0x930,0x2731,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,0x934,1,1,1,0x2737,1,0x938,0x273d,0x93c,1,0x2743,0x940,0x2749,1, +1,1,0x944,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,0x274f,0x948,0x2755,1,0x94c,0x950,1,1,1,1,1, +1,1,0x275b,0x2761,0x2767,0x276d,0x2773,0x954,0x958,0x2779,0x277f,0x95c,0x960,0x2785,0x278b,0x964, +0x968,0x96c,0x970,1,1,0x2791,0x2797,0x974,0x978,0x279d,0x27a3,0x97c,0x980,0x27a9,0x27af,1, +1,1,1,1,1,1,0x984,0x988,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,0x98c,1,1,1,1,1,0x990,0x994,1, +0x998,0x27b5,0x27bb,0x27c1,0x27c7,1,1,0x99c,0x9a0,0x9a4,0x9a8,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,0x27cd,0x27d3,0x27d9,0x27df,1, +1,1,1,1,1,0x27e5,0x27eb,0x27f1,0x27f7,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,0x2ab7,0x2abb,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +0x2abf,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,0x324a,0x3254, -0x3268,0x3280,0x3298,0x32b0,0x32c8,0xffb0,0xffb0,0xfe02,0xfe02,0xfe02,1,1,1,0xffc4,0xffb0,0xffb0, -0xffb0,0xffb0,0xffb0,1,1,1,1,1,1,1,1,0xffb8,0xffb8,0xffb8,0xffb8,0xffb8, -0xffb8,0xffb8,0xffb8,1,1,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffb8,0xffb8,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,0xffcc,0xffcc,0xffcc,0xffcc,1,1,1,1,1,1,1,1,1,1, -1,1,1,0x32d6,0x32e0,0x32f4,0x330c,0x3324,0x333c,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,0xffcc,0xffcc,0xffcc,1,1,1, +0xfe12,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,1, +1,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc, 0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc, -0xffcc,1,1,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,1,0xffcc,0xffcc,1,0xffcc,0xffcc, -0xffcc,0xffcc,0xffcc,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,0xffb8,0xffb8,0xffb8,0xffb8,0xffb8,0xffb8,0xffb8,1, -1,1,1,1,1,1,1,1,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xfe0e,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,0x334b,0x334f,0x3353,0x3357,0x335d,0x2f3d,0x3361,0x3365,0x3369,0x336d,0x2f41,0x3371, -0x3375,0x3379,0x2f45,0x337f,0x3383,0x3387,0x338b,0x3391,0x3395,0x3399,0x339d,0x33a3,0x33a7,0x33ab,0x33af,0x302f, -0x33b3,0x33b9,0x33bd,0x33c1,0x33c5,0x33c9,0x33cd,0x33d1,0x33d5,0x3043,0x2f49,0x2f4d,0x3047,0x33d9,0x33dd,0x2c49, -0x33e1,0x2f51,0x33e5,0x33e9,0x33ed,0x33f1,0x33f1,0x33f1,0x33f5,0x33fb,0x33ff,0x3403,0x3407,0x340d,0x3411,0x3415, -0x3419,0x341d,0x3421,0x3425,0x3429,0x342d,0x3431,0x3435,0x3439,0x343d,0x343d,0x304f,0x3441,0x3445,0x3449,0x344d, -0x2f59,0x3451,0x3455,0x3459,0x2ead,0x345d,0x3461,0x3465,0x3469,0x346d,0x3471,0x3475,0x3479,0x347d,0x3483,0x3487, -0x348b,0x348f,0x3493,0x3497,0x349b,0x34a1,0x34a7,0x34ab,0x34af,0x34b3,0x34b7,0x34bb,0x34bf,0x34c3,0x34c7,0x34c7, -0x34cb,0x34d1,0x34d5,0x2c39,0x34d9,0x34dd,0x34e3,0x34e7,0x34eb,0x34ef,0x34f3,0x34f7,0x2f6d,0x34fb,0x34ff,0x3503, -0x3509,0x350d,0x3513,0x3517,0x351b,0x351f,0x3523,0x3527,0x352b,0x352f,0x3533,0x3537,0x353b,0x353f,0x3545,0x3549, -0x354d,0x3551,0x2b61,0x3555,0x355b,0x355f,0x355f,0x3565,0x3569,0x3569,0x356d,0x3571,0x3577,0x357d,0x3581,0x3585, -0x3589,0x358d,0x3591,0x3595,0x3599,0x359d,0x35a1,0x2f71,0x35a5,0x35ab,0x35af,0x35b3,0x307f,0x35b3,0x35b7,0x2f79, -0x35bb,0x35bf,0x35c3,0x35c7,0x2f7d,0x2af5,0x35cb,0x35cf,0x35d3,0x35d7,0x35db,0x35df,0x35e3,0x35e9,0x35ed,0x35f1, -0x35f5,0x35f9,0x35fd,0x3603,0x3607,0x360b,0x360f,0x3613,0x3617,0x361b,0x361f,0x3623,0x2f81,0x3627,0x362b,0x3631, -0x3635,0x3639,0x363d,0x2f89,0x3641,0x3645,0x3649,0x364d,0x3651,0x3655,0x3659,0x365d,0x2b65,0x309f,0x3661,0x3665, -0x3669,0x366d,0x3673,0x3677,0x367b,0x367f,0x2f8d,0x3683,0x3689,0x368d,0x3691,0x3151,0x3695,0x3699,0x369d,0x36a1, -0x36a5,0x36ab,0x36af,0x36b3,0x36b7,0x36bd,0x36c1,0x36c5,0x36c9,0x2c7d,0x36cd,0x36d1,0x36d7,0x36dd,0x36e3,0x36e7, -0x36ed,0x36f1,0x36f5,0x36f9,0x36fd,0x2f91,0x2dd9,0x3701,0x3705,0x3709,0x370d,0x3713,0x3717,0x371b,0x371f,0x30af, -0x3723,0x3727,0x372d,0x3731,0x3735,0x373b,0x3741,0x3745,0x30b3,0x3749,0x374d,0x3751,0x3755,0x3759,0x375d,0x3761, -0x3767,0x376b,0x3771,0x3775,0x377b,0x30bb,0x377f,0x3783,0x3789,0x378d,0x3791,0x3797,0x379d,0x37a1,0x37a5,0x37a9, -0x37ad,0x37ad,0x37b1,0x37b5,0x30c3,0x37b9,0x37bd,0x37c1,0x37c5,0x37c9,0x37cf,0x37d3,0x2c45,0x37d9,0x37df,0x37e3, -0x37e9,0x37ef,0x37f5,0x37f9,0x30db,0x37fd,0x3803,0x3809,0x380f,0x3815,0x3819,0x3819,0x30df,0x3159,0x381d,0x3821, -0x3825,0x3829,0x382f,0x2bad,0x30e7,0x3833,0x3837,0x2fbd,0x383d,0x3843,0x2f05,0x3849,0x384d,0x2fcd,0x3851,0x3855, -0x3859,0x385f,0x385f,0x3865,0x3869,0x386d,0x3873,0x3877,0x387b,0x387f,0x3885,0x3889,0x388d,0x3891,0x3895,0x3899, -0x389f,0x38a3,0x38a7,0x38ab,0x38af,0x38b3,0x38b7,0x38bd,0x38c3,0x38c7,0x38cd,0x38d1,0x38d7,0x38db,0x2fe5,0x38df, -0x38e5,0x38eb,0x38ef,0x38f5,0x38f9,0x38ff,0x3903,0x3907,0x390b,0x390f,0x3913,0x3917,0x391d,0x3923,0x3929,0x3565, -0x392f,0x3933,0x3937,0x393b,0x393f,0x3943,0x3947,0x394b,0x394f,0x3953,0x3957,0x395b,0x2c8d,0x3961,0x3965,0x3969, -0x396d,0x3971,0x3975,0x2ff1,0x3979,0x397d,0x3981,0x3985,0x3989,0x398f,0x3995,0x399b,0x399f,0x39a3,0x39a7,0x39ab, -0x39b1,0x39b5,0x39bb,0x39bf,0x39c3,0x39c9,0x39cf,0x39d3,0x2b99,0x39d7,0x39db,0x39df,0x39e3,0x39e7,0x39eb,0x3103, -0x39ef,0x39f3,0x39f7,0x39fb,0x39ff,0x3a03,0x3a07,0x3a0b,0x3a0f,0x3a13,0x3a19,0x3a1d,0x3a21,0x3a25,0x3a29,0x3a2d, -0x3a33,0x3a39,0x3a3d,0x3a41,0x3117,0x311b,0x3a45,0x3a49,0x3a4f,0x3a53,0x3a57,0x3a5b,0x3a5f,0x3a65,0x3a6b,0x3a6f, -0x3a73,0x3a77,0x3a7d,0x311f,0x3a81,0x3a87,0x3a8d,0x3a91,0x3a95,0x3a99,0x3a9f,0x3aa3,0x3aa7,0x3aab,0x3aaf,0x3ab3, -0x3ab7,0x3abb,0x3ac1,0x3ac5,0x3ac9,0x3acd,0x3ad3,0x3ad7,0x3adb,0x3adf,0x3ae3,0x3ae9,0x3aef,0x3af3,0x3af7,0x3afb, -0x3b01,0x3b05,0x3137,0x3137,0x3b0b,0x3b0f,0x3b15,0x3b19,0x3b1d,0x3b21,0x3b25,0x3b29,0x3b2d,0x3b31,0x313b,0x3b37, -0x3b3b,0x3b3f,0x3b43,0x3b47,0x3b4b,0x3b51,0x3b55,0x3b5b,0x3b61,0x3b67,0x3b6b,0x3b6f,0x3b73,0x3b77,0x3b7b,0x3b7f, -0x3b83,0x3b87,1,1,2,2,2,2,2,2,2,2,2,2,2,2, -2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,0xfe00,0xfe00,0xfe00,0xfe00,0xfe00,0xfe00,0xfe00,0xfe00,0xfe00,0xfe00,0xfe00, -0xfe00,0xfe00,0xfe00,0xfe00,0xfe00,0xfe00,0xfe00,0xfe00,0xfe00,0xfe00,1,1,1,1,1,1, -1,1,1,1,0xfe00,0xfe00,0xfe00,0xfe00,0xfe00,0xfe00,0xfe00,0xfe00,0xfe00,0xfe00,0xfe00,0xfe00, -0xfe00,0xfe00,0xfe00,0xfe00,0xfe00,0xfe00,0xfe00,0xfe00,0xfe00,0xfe00,0xfe00,0xfe00,0xfe00,0xfe00,0xfe00,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,0xadc,0x1283,0x1283,0x1283, -0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283, -0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0xadc,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283, -0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283, +0xffcc,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,0xffb4,0xffc8,0xffd0,0xffbc,0xffc0, +0xffc0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,0x9ac,1,1,1,1,0x9b0,0x27fd,0x9b4,0x2803,0x9b8,0x2809,0x9bc,0x280f,0x9c0,0x2815, +0x9c4,0x281b,0x9c8,0x2821,0x9cc,0x2827,0x9d0,0x282d,0x9d4,0x2833,0x9d8,0x2839,0x9dc,0x283f,1,0x9e0, +0x2845,0x9e4,0x284b,0x9e8,0x2851,1,1,1,1,1,0x9ec,0x2857,0x285d,0x9f4,0x2863,0x2869, +0x9fc,0x286f,0x2875,0xa04,0x287b,0x2881,0xa0c,0x2887,0x288d,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,0x2893,1,1, +1,1,0xfc10,0xfc10,1,1,0xa14,0x2899,1,1,1,1,1,1,1,0xa18, +1,1,1,1,0xa1c,0x289f,0xa20,0x28a5,0xa24,0x28ab,0xa28,0x28b1,0xa2c,0x28b7,0xa30,0x28bd, +0xa34,0x28c3,0xa38,0x28c9,0xa3c,0x28cf,0xa40,0x28d5,0xa44,0x28db,0xa48,0x28e1,1,0xa4c,0x28e7,0xa50, +0x28ed,0xa54,0x28f3,1,1,1,1,1,0xa58,0x28f9,0x28ff,0xa60,0x2905,0x290b,0xa68,0x2911, +0x2917,0xa70,0x291d,0x2923,0xa78,0x2929,0x292f,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,0xa80,0xa84,0xa88,0xa8c,1,0x2935,1,1, +0x293b,0x2941,0x2947,0x294d,1,1,0xa90,0x2953,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,0xffcc,1,1,1,1,0xffcc,0xffcc,0xffcc,0xffcc, +0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,0xffcc,0xffcc,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,0xffcc,0xffcc,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,0xfe12,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,0x1283,0x1283,0x1283,0x1283, -0xadc,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283, -0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x3c54,1,0x3c54,0x3c54, -0x3c54,0x3c54,0x3c54,0x3c54,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,0x3c54,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,0x3c54,1,1,1,1,0x3c54,1,1,1, -0x3c54,1,0x3c54,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,0x3b87,1,1,1,1,1 +0xfe12,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,0xffcc,0xffcc,0xffcc,0xffcc, +0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,0xffb8,0xffb8,0xffb8,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0xfe12, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0xffcc, +1,0xffcc,0xffcc,0xffb8,1,1,0xffcc,0xffcc,1,1,1,1,1,0xffcc,0xffcc,1, +0xffcc,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,0xfe12,1,1,1,1,1,1,1,1,1,0xadc, +0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283, +0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0xadc,0x1283,0x1283,0x1283,0x1283, +0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283, +0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0xadc,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283, +0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283, +0x1283,0x1283,0x1283,0xadc,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283, +0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,0x1283,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,0x3c56,1,0x3c56,0x3c56,0x3c56, +0x3c56,0x3c56,0x3c56,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,0x3c56,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,0x3c56,1,1,1,1,0x3c56, +1,1,1,0x3c56,1,0x3c56,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,0x3b87,1,0x2ac5,0x2ac9,0x2acd,0x2ad1,0x2ad5,0x2ad9,0x2add,0x2ae1,0x2ae1,0x2ae5, +0x2ae9,0x2aed,0x2af1,0x2af5,0x2af9,0x2afd,0x2b01,0x2b05,0x2b09,0x2b0d,0x2b11,0x2b15,0x2b19,0x2b1d,0x2b21,0x2b25, +0x2b29,0x2b2d,0x2b31,0x2b35,0x2b39,0x2b3d,0x2b41,0x2b45,0x2b49,0x2b4d,0x2b51,0x2b55,0x2b59,0x2b5d,0x2b61,0x2b65, +0x2b69,0x2b6d,0x2b71,0x2b75,0x2b79,0x2b7d,0x2b81,0x2b85,0x2b89,0x2b8d,0x2b91,0x2b95,0x2b99,0x2b9d,0x2ba1,0x2ba5, +0x2ba9,0x2bad,0x2bb1,0x2bb5,0x2bb9,0x2bbd,0x2bc1,0x2bc5,0x2bc9,0x2bcd,0x2bd1,0x2bd5,0x2bd9,0x2bdd,0x2be1,0x2be5, +0x2be9,0x2bed,0x2bf1,0x2bf5,0x2bf9,0x2bfd,0x2c01,0x2c05,0x2c09,0x2c0d,0x2c11,0x2c15,0x2c19,0x2c1d,0x2c21,0x2c25, +0x2c29,0x2c2d,0x2b11,0x2c31,0x2c35,0x2c39,0x2c3d,0x2c41,0x2c45,0x2c49,0x2c4d,0x2c51,0x2c55,0x2c59,0x2c5d,0x2c61, +0x2c65,0x2c69,0x2c6d,0x2c71,0x2c75,0x2c79,0x2c7d,0x2c81,0x2c85,0x2c89,0x2c8d,0x2c91,0x2c95,0x2c99,0x2c9d,0x2ca1, +0x2ca5,0x2ca9,0x2cad,0x2cb1,0x2cb5,0x2cb9,0x2cbd,0x2cc1,0x2cc5,0x2cc9,0x2ccd,0x2cd1,0x2cd5,0x2cd9,0x2cdd,0x2ce1, +0x2ce5,0x2ce9,0x2ced,0x2cf1,0x2cf5,0x2cf9,0x2cfd,0x2d01,0x2d05,0x2d09,0x2d0d,0x2d11,0x2d15,0x2d19,0x2d1d,0x2d21, +0x2d25,0x2d29,0x2d2d,0x2d31,0x2d35,0x2d39,0x2d3d,0x2c79,0x2d41,0x2d45,0x2d49,0x2d4d,0x2d51,0x2d55,0x2d59,0x2d5d, +0x2c39,0x2d61,0x2d65,0x2d69,0x2d6d,0x2d71,0x2d75,0x2d79,0x2d7d,0x2d81,0x2d85,0x2d89,0x2d8d,0x2d91,0x2d95,0x2d99, +0x2d9d,0x2da1,0x2da5,0x2da9,0x2dad,0x2b11,0x2db1,0x2db5,0x2db9,0x2dbd,0x2dc1,0x2dc5,0x2dc9,0x2dcd,0x2dd1,0x2dd5, +0x2dd9,0x2ddd,0x2de1,0x2de5,0x2de9,0x2ded,0x2df1,0x2df5,0x2df9,0x2dfd,0x2e01,0x2e05,0x2e09,0x2e0d,0x2e11,0x2e15, +0x2e19,0x2c41,0x2e1d,0x2e21,0x2e25,0x2e29,0x2e2d,0x2e31,0x2e35,0x2e39,0x2e3d,0x2e41,0x2e45,0x2e49,0x2e4d,0x2e51, +0x2e55,0x2e59,0x2e5d,0x2e61,0x2e65,0x2e69,0x2e6d,0x2e71,0x2e75,0x2e79,0x2e7d,0x2e81,0x2e85,0x2e89,0x2e8d,0x2e91, +0x2e95,0x2e99,0x2e9d,0x2ea1,0x2ea5,0x2ea9,0x2ead,0x2eb1,0x2eb5,0x2eb9,0x2ebd,0x2ec1,0x2ec5,0x2ec9,0x2ecd,0x2ed1, +0x2ed5,0x2ed9,0x2edd,0x2ee1,1,1,0x2ee5,1,0x2ee9,1,1,0x2eed,0x2ef1,0x2ef5,0x2ef9,0x2efd, +0x2f01,0x2f05,0x2f09,0x2f0d,0x2f11,1,0x2f15,1,0x2f19,1,1,0x2f1d,0x2f21,1,1,1, +0x2f25,0x2f29,0x2f2d,0x2f31,0x2f35,0x2f39,0x2f3d,0x2f41,0x2f45,0x2f49,0x2f4d,0x2f51,0x2f55,0x2f59,0x2f5d,0x2f61, +0x2f65,0x2f69,0x2f6d,0x2f71,0x2f75,0x2f79,0x2f7d,0x2f81,0x2f85,0x2f89,0x2f8d,0x2f91,0x2f95,0x2f99,0x2f9d,0x2fa1, +0x2fa5,0x2fa9,0x2fad,0x2fb1,0x2fb5,0x2fb9,0x2fbd,0x2fc1,0x2fc5,0x2fc9,0x2fcd,0x2fd1,0x2fd5,0x2d15,0x2fd9,0x2fdd, +0x2fe1,0x2fe5,0x2fe9,0x2fed,0x2fed,0x2ff1,0x2ff5,0x2ff9,0x2ffd,0x3001,0x3005,0x3009,0x300d,0x2f1d,0x3011,0x3015, +0x3019,0x301d,0x3021,0x3027,1,1,0x302b,0x302f,0x3033,0x3037,0x303b,0x303f,0x3043,0x3047,0x2f55,0x304b, +0x304f,0x3053,0x2ee5,0x3057,0x305b,0x305f,0x3063,0x3067,0x306b,0x306f,0x3073,0x3077,0x307b,0x307f,0x3083,0x2f79, +0x3087,0x2f7d,0x308b,0x308f,0x3093,0x3097,0x309b,0x2ee9,0x2b65,0x309f,0x30a3,0x30a7,0x2c7d,0x2dd9,0x30ab,0x30af, +0x2f99,0x30b3,0x2f9d,0x30b7,0x30bb,0x30bf,0x2ef1,0x30c3,0x30c7,0x30cb,0x30cf,0x30d3,0x2ef5,0x30d7,0x30db,0x30df, +0x30e3,0x30e7,0x30eb,0x2fd5,0x30ef,0x30f3,0x2d15,0x30f7,0x2fe5,0x30fb,0x30ff,0x3103,0x3107,0x310b,0x2ff9,0x310f, +0x2f19,0x3113,0x2ffd,0x2c31,0x3117,0x3001,0x311b,0x3009,0x311f,0x3123,0x3127,0x312b,0x312f,0x3011,0x2f09,0x3133, +0x3015,0x3137,0x3019,0x313b,0x2ae1,0x313f,0x3145,0x314b,0x3151,0x3155,0x3159,0x315d,0x3163,0x3169,0x316f,0x3173, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,0x3176,0xfe34,0x317c,1,1,1,1,1,1,1, +1,1,1,0x3182,0x3188,0x3190,0x319a,0x31a2,0x31a8,0x31ae,0x31b4,0x31ba,0x31c0,0x31c6,0x31cc,0x31d2, +1,0x31d8,0x31de,0x31e4,0x31ea,0x31f0,1,0x31f6,1,0x31fc,0x3202,1,0x3208,0x320e,1,0x3214, +0x321a,0x3220,0x3226,0x322c,0x3232,0x3238,0x323e,0x3244,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc, +0xffb8,0xffb8,0xffb8,0xffb8,0xffb8,0xffb8,0xffb8,0xffcc,0xffcc,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,0xffb8,1,0xffcc,1,1,1,1, +1,1,1,1,0xffcc,0xfe02,0xffb8,1,1,1,1,0xfe12,1,1,1,1, +0xffcc,0xffcc,0xffcc,0xffcc,1,1,1,1,1,1,1,1,0xffb8,0xffb8,0xffcc,0xffcc, +0xffcc,0xffb8,0xffcc,0xffb8,0xffb8,0xffb8,1,1,1,1,1,1,1,1,1,0xa94, +0x2959,0xa9a,0x2963,1,1,1,1,1,0xaa0,1,1,1,1,1,0x296d,1, +1,1,1,1,1,1,1,1,0xfe12,0xfc0e,1,1,1,1,1,1, +1,0xfc00,1,1,1,1,1,1,0x2977,0x2981,1,0xaa6,0xaac,0xfe12,0xfe12,1, +1,1,1,1,1,1,1,1,1,1,0xfe12,1,1,1,1,1, +1,1,1,1,0xfe0e,1,1,1,1,1,0xfe12,0xfe0e,1,1,1,1, +1,1,1,1,1,0xfe0e,0xfe12,1,1,1,1,1,1,1,1,1, +1,1,0xfe0e,0xfe0e,1,0xfc00,1,1,1,1,1,1,1,0xab2,1,1, +1,0x298b,0x2995,0xfe12,1,1,1,1,1,1,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc, +0xffcc,1,1,1,0xfe12,1,1,1,0xfe0e,1,1,1,1,1,1,1, +1,1,0xfc00,1,1,1,1,1,1,1,1,0xabe,0xfc00,0x299f,0x29a9,0xfc00, +0x29b3,1,1,0xfe12,0xfe0e,1,1,1,1,1,1,1,1,1,1,1, +1,0xad0,0xad6,0x29bd,0x29c7,1,1,1,0xfe12,0xfe0e,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,0xfe12,0xfe0e,1,1,1,1,1, +1,1,1,0xfe02,0xfe02,0xfe02,0xfe02,0xfe02,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,0xfe02,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,0x324a,0x3254,0x3268,0x3280,0x3298,0x32b0,0x32c8,0xffb0,0xffb0,0xfe02,0xfe02, +0xfe02,1,1,1,0xffc4,0xffb0,0xffb0,0xffb0,1,1,1,1,1,1,1,1, +0xffb8,0xffb8,0xffb8,0xffb8,0xffb8,1,1,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffb8,0xffb8,1,1, +1,1,1,1,1,1,1,1,0xffcc,0xffcc,0xffcc,0xffcc,1,1,1,1, +1,1,1,1,1,1,1,0x32d6,0x32e0,0x32f4,0x330c,0x3324,0x333c,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,0xffcc,0xffcc,0xffcc,0xffcc, +0xffcc,0xffcc,0xffcc,1,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,1,1,0xffcc, +0xffcc,0xffcc,0xffcc,0xffcc,1,0xffcc,0xffcc,1,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,1,1,1, +1,1,0xffb8,0xffb8,0xffb8,0xffb8,0xffb8,0xffb8,0xffb8,1,1,1,1,1,1,1, +1,1,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xfe0e,1,1,1,1,1,0x334b,0x334f, +0x3353,0x3357,0x335d,0x2f3d,0x3361,0x3365,0x3369,0x336d,0x2f41,0x3371,0x3375,0x3379,0x2f45,0x337f,0x3383,0x3387, +0x338b,0x3391,0x3395,0x3399,0x339d,0x33a3,0x33a7,0x33ab,0x33af,0x302f,0x33b3,0x33b9,0x33bd,0x33c1,0x33c5,0x33c9, +0x33cd,0x33d1,0x33d5,0x3043,0x2f49,0x2f4d,0x3047,0x33d9,0x33dd,0x2c49,0x33e1,0x2f51,0x33e5,0x33e9,0x33ed,0x33f1, +0x33f1,0x33f1,0x33f5,0x33fb,0x33ff,0x3403,0x3407,0x340d,0x3411,0x3415,0x3419,0x341d,0x3421,0x3425,0x3429,0x342d, +0x3431,0x3435,0x3439,0x343d,0x343d,0x304f,0x3441,0x3445,0x3449,0x344d,0x2f59,0x3451,0x3455,0x3459,0x2ead,0x345d, +0x3461,0x3465,0x3469,0x346d,0x3471,0x3475,0x3479,0x347d,0x3483,0x3487,0x348b,0x348f,0x3493,0x3497,0x349b,0x34a1, +0x34a7,0x34ab,0x34af,0x34b3,0x34b7,0x34bb,0x34bf,0x34c3,0x34c7,0x34c7,0x34cb,0x34d1,0x34d5,0x2c39,0x34d9,0x34dd, +0x34e3,0x34e7,0x34eb,0x34ef,0x34f3,0x34f7,0x2f6d,0x34fb,0x34ff,0x3503,0x3509,0x350d,0x3513,0x3517,0x351b,0x351f, +0x3523,0x3527,0x352b,0x352f,0x3533,0x3537,0x353b,0x353f,0x3545,0x3549,0x354d,0x3551,0x2b61,0x3555,0x355b,0x355f, +0x355f,0x3565,0x3569,0x3569,0x356d,0x3571,0x3577,0x357d,0x3581,0x3585,0x3589,0x358d,0x3591,0x3595,0x3599,0x359d, +0x35a1,0x2f71,0x35a5,0x35ab,0x35af,0x35b3,0x307f,0x35b3,0x35b7,0x2f79,0x35bb,0x35bf,0x35c3,0x35c7,0x2f7d,0x2af5, +0x35cb,0x35cf,0x35d3,0x35d7,0x35db,0x35df,0x35e3,0x35e9,0x35ed,0x35f1,0x35f5,0x35f9,0x35fd,0x3603,0x3607,0x360b, +0x360f,0x3613,0x3617,0x361b,0x361f,0x3623,0x2f81,0x3627,0x362b,0x3631,0x3635,0x3639,0x363d,0x2f89,0x3641,0x3645, +0x3649,0x364d,0x3651,0x3655,0x3659,0x365d,0x2b65,0x309f,0x3661,0x3665,0x3669,0x366d,0x3673,0x3677,0x367b,0x367f, +0x2f8d,0x3683,0x3689,0x368d,0x3691,0x3151,0x3695,0x3699,0x369d,0x36a1,0x36a5,0x36ab,0x36af,0x36b3,0x36b7,0x36bd, +0x36c1,0x36c5,0x36c9,0x2c7d,0x36cd,0x36d1,0x36d7,0x36dd,0x36e3,0x36e7,0x36ed,0x36f1,0x36f5,0x36f9,0x36fd,0x2f91, +0x2dd9,0x3701,0x3705,0x3709,0x370d,0x3713,0x3717,0x371b,0x371f,0x30af,0x3723,0x3727,0x372d,0x3731,0x3735,0x373b, +0x3741,0x3745,0x30b3,0x3749,0x374d,0x3751,0x3755,0x3759,0x375d,0x3761,0x3767,0x376b,0x3771,0x3775,0x377b,0x30bb, +0x377f,0x3783,0x3789,0x378d,0x3791,0x3797,0x379d,0x37a1,0x37a5,0x37a9,0x37ad,0x37ad,0x37b1,0x37b5,0x30c3,0x37b9, +0x37bd,0x37c1,0x37c5,0x37c9,0x37cf,0x37d3,0x2c45,0x37d9,0x37df,0x37e3,0x37e9,0x37ef,0x37f5,0x37f9,0x30db,0x37fd, +0x3803,0x3809,0x380f,0x3815,0x3819,0x3819,0x30df,0x3159,0x381d,0x3821,0x3825,0x3829,0x382f,0x2bad,0x30e7,0x3833, +0x3837,0x2fbd,0x383d,0x3843,0x2f05,0x3849,0x384d,0x2fcd,0x3851,0x3855,0x3859,0x385f,0x385f,0x3865,0x3869,0x386d, +0x3873,0x3877,0x387b,0x387f,0x3885,0x3889,0x388d,0x3891,0x3895,0x3899,0x389f,0x38a3,0x38a7,0x38ab,0x38af,0x38b3, +0x38b7,0x38bd,0x38c3,0x38c7,0x38cd,0x38d1,0x38d7,0x38db,0x2fe5,0x38df,0x38e5,0x38eb,0x38ef,0x38f5,0x38f9,0x38ff, +0x3903,0x3907,0x390b,0x390f,0x3913,0x3917,0x391d,0x3923,0x3929,0x3565,0x392f,0x3933,0x3937,0x393b,0x393f,0x3943, +0x3947,0x394b,0x394f,0x3953,0x3957,0x395b,0x2c8d,0x3961,0x3965,0x3969,0x396d,0x3971,0x3975,0x2ff1,0x3979,0x397d, +0x3981,0x3985,0x3989,0x398f,0x3995,0x399b,0x399f,0x39a3,0x39a7,0x39ab,0x39b1,0x39b5,0x39bb,0x39bf,0x39c3,0x39c9, +0x39cf,0x39d3,0x2b99,0x39d7,0x39db,0x39df,0x39e3,0x39e7,0x39eb,0x3103,0x39ef,0x39f3,0x39f7,0x39fb,0x39ff,0x3a03, +0x3a07,0x3a0b,0x3a0f,0x3a13,0x3a19,0x3a1d,0x3a21,0x3a25,0x3a29,0x3a2d,0x3a33,0x3a39,0x3a3d,0x3a41,0x3117,0x311b, +0x3a45,0x3a49,0x3a4f,0x3a53,0x3a57,0x3a5b,0x3a5f,0x3a65,0x3a6b,0x3a6f,0x3a73,0x3a77,0x3a7d,0x311f,0x3a81,0x3a87, +0x3a8d,0x3a91,0x3a95,0x3a99,0x3a9f,0x3aa3,0x3aa7,0x3aab,0x3aaf,0x3ab3,0x3ab7,0x3abb,0x3ac1,0x3ac5,0x3ac9,0x3acd, +0x3ad3,0x3ad7,0x3adb,0x3adf,0x3ae3,0x3ae9,0x3aef,0x3af3,0x3af7,0x3afb,0x3b01,0x3b05,0x3137,0x3137,0x3b0b,0x3b0f, +0x3b15,0x3b19,0x3b1d,0x3b21,0x3b25,0x3b29,0x3b2d,0x3b31,0x313b,0x3b37,0x3b3b,0x3b3f,0x3b43,0x3b47,0x3b4b,0x3b51, +0x3b55,0x3b5b,0x3b61,0x3b67,0x3b6b,0x3b6f,0x3b73,0x3b77,0x3b7b,0x3b7f,0x3b83,0x3b87,1,1 +}; + +static const UCPTrie norm2_nfc_data_trie={ + norm2_nfc_data_trieIndex, + { norm2_nfc_data_trieData }, + 1690, 7822, + 0x2fc00, 0x30, + 0, 0, + 0, 0, + 0xc4, 0x226, + 0x1, }; static const uint16_t norm2_nfc_data_extraData[7724]={ @@ -1151,19 +1136,4 @@ static const uint8_t norm2_nfc_data_smallFCD[256]={ 0,0,0,0,0,0,0,0,0,0,0,7,0,0,2,0 }; -static const UTrie2 norm2_nfc_data_trie={ - norm2_nfc_data_trieIndex, - norm2_nfc_data_trieIndex+2728, - NULL, - 2728, - 7248, - 0x188, - 0xb24, - 0x1, - 0x1, - 0x30000, - 0x26f4, - NULL, 0, FALSE, FALSE, 0, NULL -}; - #endif // INCLUDED_FROM_NORMALIZER2_CPP diff --git a/deps/icu-small/source/common/normalizer2.cpp b/deps/icu-small/source/common/normalizer2.cpp index 133770cbc4d9aa..ca5d3aba1a1874 100644 --- a/deps/icu-small/source/common/normalizer2.cpp +++ b/deps/icu-small/source/common/normalizer2.cpp @@ -34,9 +34,11 @@ using icu::Normalizer2Impl; +#if NORM2_HARDCODE_NFC_DATA // NFC/NFD data machine-generated by gennorm2 --csource #define INCLUDED_FROM_NORMALIZER2_CPP #include "norm2_nfc_data.h" +#endif U_NAMESPACE_BEGIN @@ -176,6 +178,36 @@ FCDNormalizer2::~FCDNormalizer2() {} // instance cache ---------------------------------------------------------- *** +U_CDECL_BEGIN +static UBool U_CALLCONV uprv_normalizer2_cleanup(); +U_CDECL_END + +static Normalizer2 *noopSingleton; +static icu::UInitOnce noopInitOnce = U_INITONCE_INITIALIZER; + +static void U_CALLCONV initNoopSingleton(UErrorCode &errorCode) { + if(U_FAILURE(errorCode)) { + return; + } + noopSingleton=new NoopNormalizer2; + if(noopSingleton==NULL) { + errorCode=U_MEMORY_ALLOCATION_ERROR; + return; + } + ucln_common_registerCleanup(UCLN_COMMON_NORMALIZER2, uprv_normalizer2_cleanup); +} + +const Normalizer2 *Normalizer2Factory::getNoopInstance(UErrorCode &errorCode) { + if(U_FAILURE(errorCode)) { return NULL; } + umtx_initOnce(noopInitOnce, &initNoopSingleton, errorCode); + return noopSingleton; +} + +const Normalizer2Impl * +Normalizer2Factory::getImpl(const Normalizer2 *norm2) { + return &((Normalizer2WithImpl *)norm2)->impl; +} + Norm2AllModes::~Norm2AllModes() { delete impl; } @@ -195,6 +227,7 @@ Norm2AllModes::createInstance(Normalizer2Impl *impl, UErrorCode &errorCode) { return allModes; } +#if NORM2_HARDCODE_NFC_DATA Norm2AllModes * Norm2AllModes::createNFCInstance(UErrorCode &errorCode) { if(U_FAILURE(errorCode)) { @@ -210,48 +243,15 @@ Norm2AllModes::createNFCInstance(UErrorCode &errorCode) { return createInstance(impl, errorCode); } -U_CDECL_BEGIN -static UBool U_CALLCONV uprv_normalizer2_cleanup(); -U_CDECL_END - static Norm2AllModes *nfcSingleton; -static Normalizer2 *noopSingleton; static icu::UInitOnce nfcInitOnce = U_INITONCE_INITIALIZER; -static icu::UInitOnce noopInitOnce = U_INITONCE_INITIALIZER; -// UInitOnce singleton initialization functions static void U_CALLCONV initNFCSingleton(UErrorCode &errorCode) { nfcSingleton=Norm2AllModes::createNFCInstance(errorCode); ucln_common_registerCleanup(UCLN_COMMON_NORMALIZER2, uprv_normalizer2_cleanup); } -static void U_CALLCONV initNoopSingleton(UErrorCode &errorCode) { - if(U_FAILURE(errorCode)) { - return; - } - noopSingleton=new NoopNormalizer2; - if(noopSingleton==NULL) { - errorCode=U_MEMORY_ALLOCATION_ERROR; - return; - } - ucln_common_registerCleanup(UCLN_COMMON_NORMALIZER2, uprv_normalizer2_cleanup); -} - -U_CDECL_BEGIN - -static UBool U_CALLCONV uprv_normalizer2_cleanup() { - delete nfcSingleton; - nfcSingleton = NULL; - delete noopSingleton; - noopSingleton = NULL; - nfcInitOnce.reset(); - noopInitOnce.reset(); - return TRUE; -} - -U_CDECL_END - const Norm2AllModes * Norm2AllModes::getNFCInstance(UErrorCode &errorCode) { if(U_FAILURE(errorCode)) { return NULL; } @@ -281,23 +281,29 @@ const Normalizer2 *Normalizer2Factory::getFCCInstance(UErrorCode &errorCode) { return allModes!=NULL ? &allModes->fcc : NULL; } -const Normalizer2 *Normalizer2Factory::getNoopInstance(UErrorCode &errorCode) { - if(U_FAILURE(errorCode)) { return NULL; } - umtx_initOnce(noopInitOnce, &initNoopSingleton, errorCode); - return noopSingleton; -} - const Normalizer2Impl * Normalizer2Factory::getNFCImpl(UErrorCode &errorCode) { const Norm2AllModes *allModes=Norm2AllModes::getNFCInstance(errorCode); return allModes!=NULL ? allModes->impl : NULL; } +#endif // NORM2_HARDCODE_NFC_DATA -const Normalizer2Impl * -Normalizer2Factory::getImpl(const Normalizer2 *norm2) { - return &((Normalizer2WithImpl *)norm2)->impl; +U_CDECL_BEGIN + +static UBool U_CALLCONV uprv_normalizer2_cleanup() { + delete noopSingleton; + noopSingleton = NULL; + noopInitOnce.reset(); +#if NORM2_HARDCODE_NFC_DATA + delete nfcSingleton; + nfcSingleton = NULL; + nfcInitOnce.reset(); +#endif + return TRUE; } +U_CDECL_END + U_NAMESPACE_END // C API ------------------------------------------------------------------- *** diff --git a/deps/icu-small/source/common/normalizer2impl.cpp b/deps/icu-small/source/common/normalizer2impl.cpp index 15b4a528934779..e7ae646c41ae6d 100644 --- a/deps/icu-small/source/common/normalizer2impl.cpp +++ b/deps/icu-small/source/common/normalizer2impl.cpp @@ -16,6 +16,8 @@ * created by: Markus W. Scherer */ +// #define UCPTRIE_DEBUG + #include "unicode/utypes.h" #if !UCONFIG_NO_NORMALIZATION @@ -24,7 +26,9 @@ #include "unicode/edits.h" #include "unicode/normalizer2.h" #include "unicode/stringoptions.h" +#include "unicode/ucptrie.h" #include "unicode/udata.h" +#include "unicode/umutablecptrie.h" #include "unicode/ustring.h" #include "unicode/utf16.h" #include "unicode/utf8.h" @@ -34,8 +38,8 @@ #include "normalizer2impl.h" #include "putilimp.h" #include "uassert.h" +#include "ucptrie_impl.h" #include "uset_imp.h" -#include "utrie2.h" #include "uvector.h" U_NAMESPACE_BEGIN @@ -62,7 +66,7 @@ inline uint8_t leadByteForCP(UChar32 c) { * Returns the code point from one single well-formed UTF-8 byte sequence * between cpStart and cpLimit. * - * UTrie2 UTF-8 macros do not assemble whole code points (for efficiency). + * Trie UTF-8 macros do not assemble whole code points (for efficiency). * When we do need the code point, we call this function. * We should not need it for normalization-inert data (norm16==0). * Illegal sequences yield the error value norm16==0 just like real normalization-inert code points. @@ -122,7 +126,7 @@ int32_t getJamoTMinusBase(const uint8_t *src, const uint8_t *limit) { } } else if (src[1] == 0x87) { uint8_t t = src[2]; - if ((int8_t)t <= (int8_t)0x82) { + if ((int8_t)t <= (int8_t)0x82u) { return t - (0xa7 - 0x40); } } @@ -253,7 +257,7 @@ UBool ReorderingBuffer::appendSupplementary(UChar32 c, uint8_t cc, UErrorCode &e return TRUE; } -UBool ReorderingBuffer::append(const UChar *s, int32_t length, +UBool ReorderingBuffer::append(const UChar *s, int32_t length, UBool isNFD, uint8_t leadCC, uint8_t trailCC, UErrorCode &errorCode) { if(length==0) { @@ -280,8 +284,11 @@ UBool ReorderingBuffer::append(const UChar *s, int32_t length, while(i>DELTA_SHIFT)-MAX_DELTA-1; + minDecompNoCP = static_cast(inIndexes[IX_MIN_DECOMP_NO_CP]); + minCompNoMaybeCP = static_cast(inIndexes[IX_MIN_COMP_NO_MAYBE_CP]); + minLcccCP = static_cast(inIndexes[IX_MIN_LCCC_CP]); + + minYesNo = static_cast(inIndexes[IX_MIN_YES_NO]); + minYesNoMappingsOnly = static_cast(inIndexes[IX_MIN_YES_NO_MAPPINGS_ONLY]); + minNoNo = static_cast(inIndexes[IX_MIN_NO_NO]); + minNoNoCompBoundaryBefore = static_cast(inIndexes[IX_MIN_NO_NO_COMP_BOUNDARY_BEFORE]); + minNoNoCompNoMaybeCC = static_cast(inIndexes[IX_MIN_NO_NO_COMP_NO_MAYBE_CC]); + minNoNoEmpty = static_cast(inIndexes[IX_MIN_NO_NO_EMPTY]); + limitNoNo = static_cast(inIndexes[IX_LIMIT_NO_NO]); + minMaybeYes = static_cast(inIndexes[IX_MIN_MAYBE_YES]); + U_ASSERT((minMaybeYes & 7) == 0); // 8-aligned for noNoDelta bit fields + centerNoNoDelta = (minMaybeYes >> DELTA_SHIFT) - MAX_DELTA - 1; normTrie=inTrie; @@ -445,75 +453,8 @@ Normalizer2Impl::init(const int32_t *inIndexes, const UTrie2 *inTrie, smallFCD=inSmallFCD; } -class LcccContext { -public: - LcccContext(const Normalizer2Impl &ni, UnicodeSet &s) : impl(ni), set(s) {} - - void handleRange(UChar32 start, UChar32 end, uint16_t norm16) { - if (norm16 > Normalizer2Impl::MIN_NORMAL_MAYBE_YES && - norm16 != Normalizer2Impl::JAMO_VT) { - set.add(start, end); - } else if (impl.minNoNoCompNoMaybeCC <= norm16 && norm16 < impl.limitNoNo) { - uint16_t fcd16=impl.getFCD16(start); - if(fcd16>0xff) { set.add(start, end); } - } - } - -private: - const Normalizer2Impl &impl; - UnicodeSet &set; -}; - -namespace { - -struct PropertyStartsContext { - PropertyStartsContext(const Normalizer2Impl &ni, const USetAdder *adder) - : impl(ni), sa(adder) {} - - const Normalizer2Impl &impl; - const USetAdder *sa; -}; - -} // namespace - U_CDECL_BEGIN -static UBool U_CALLCONV -enumLcccRange(const void *context, UChar32 start, UChar32 end, uint32_t value) { - ((LcccContext *)context)->handleRange(start, end, (uint16_t)value); - return TRUE; -} - -static UBool U_CALLCONV -enumNorm16PropertyStartsRange(const void *context, UChar32 start, UChar32 end, uint32_t value) { - /* add the start code point to the USet */ - const PropertyStartsContext *ctx=(const PropertyStartsContext *)context; - const USetAdder *sa=ctx->sa; - sa->add(sa->set, start); - if (start != end && ctx->impl.isAlgorithmicNoNo((uint16_t)value) && - (value & Normalizer2Impl::DELTA_TCCC_MASK) > Normalizer2Impl::DELTA_TCCC_1) { - // Range of code points with same-norm16-value algorithmic decompositions. - // They might have different non-zero FCD16 values. - uint16_t prevFCD16=ctx->impl.getFCD16(start); - while(++start<=end) { - uint16_t fcd16=ctx->impl.getFCD16(start); - if(fcd16!=prevFCD16) { - sa->add(sa->set, start); - prevFCD16=fcd16; - } - } - } - return TRUE; -} - -static UBool U_CALLCONV -enumPropertyStartsRange(const void *context, UChar32 start, UChar32 /*end*/, uint32_t /*value*/) { - /* add the start code point to the USet */ - const USetAdder *sa=(const USetAdder *)context; - sa->add(sa->set, start); - return TRUE; -} - static uint32_t U_CALLCONV segmentStarterMapper(const void * /*context*/, uint32_t value) { return value&CANON_NOT_SEGMENT_STARTER; @@ -523,15 +464,44 @@ U_CDECL_END void Normalizer2Impl::addLcccChars(UnicodeSet &set) const { - LcccContext context(*this, set); - utrie2_enum(normTrie, NULL, enumLcccRange, &context); + UChar32 start = 0, end; + uint32_t norm16; + while ((end = ucptrie_getRange(normTrie, start, UCPMAP_RANGE_FIXED_LEAD_SURROGATES, INERT, + nullptr, nullptr, &norm16)) >= 0) { + if (norm16 > Normalizer2Impl::MIN_NORMAL_MAYBE_YES && + norm16 != Normalizer2Impl::JAMO_VT) { + set.add(start, end); + } else if (minNoNoCompNoMaybeCC <= norm16 && norm16 < limitNoNo) { + uint16_t fcd16 = getFCD16(start); + if (fcd16 > 0xff) { set.add(start, end); } + } + start = end + 1; + } } void Normalizer2Impl::addPropertyStarts(const USetAdder *sa, UErrorCode & /*errorCode*/) const { - /* add the start code point of each same-value range of each trie */ - PropertyStartsContext context(*this, sa); - utrie2_enum(normTrie, NULL, enumNorm16PropertyStartsRange, &context); + // Add the start code point of each same-value range of the trie. + UChar32 start = 0, end; + uint32_t value; + while ((end = ucptrie_getRange(normTrie, start, UCPMAP_RANGE_FIXED_LEAD_SURROGATES, INERT, + nullptr, nullptr, &value)) >= 0) { + sa->add(sa->set, start); + if (start != end && isAlgorithmicNoNo((uint16_t)value) && + (value & Normalizer2Impl::DELTA_TCCC_MASK) > Normalizer2Impl::DELTA_TCCC_1) { + // Range of code points with same-norm16-value algorithmic decompositions. + // They might have different non-zero FCD16 values. + uint16_t prevFCD16 = getFCD16(start); + while (++start <= end) { + uint16_t fcd16 = getFCD16(start); + if (fcd16 != prevFCD16) { + sa->add(sa->set, start); + prevFCD16 = fcd16; + } + } + } + start = end + 1; + } /* add Hangul LV syllables and LV+1 because of skippables */ for(UChar c=Hangul::HANGUL_BASE; ctrie, segmentStarterMapper, enumPropertyStartsRange, sa); + // Add the start code point of each same-value range of the canonical iterator data trie. + if (!ensureCanonIterData(errorCode)) { return; } + // Currently only used for the SEGMENT_STARTER property. + UChar32 start = 0, end; + uint32_t value; + while ((end = ucptrie_getRange(fCanonIterData->trie, start, UCPMAP_RANGE_NORMAL, 0, + segmentStarterMapper, nullptr, &value)) >= 0) { + sa->add(sa->set, start); + start = end + 1; } } @@ -633,27 +608,23 @@ Normalizer2Impl::decompose(const UChar *src, const UChar *limit, // count code units below the minimum or with irrelevant data for the quick check for(prevSrc=src; src!=limit;) { if( (c=*src)= limitNoNo) { @@ -789,7 +760,7 @@ Normalizer2Impl::decomposeShort(const uint8_t *src, const uint8_t *limit, } c = codePointFromValidUTF8(prevSrc, src); c = mapAlgorithmic(c, norm16); - norm16 = getNorm16(c); + norm16 = getRawNorm16(c); } else if (stopAtCompBoundary && norm16 < minNoNoCompNoMaybeCC) { return prevSrc; } @@ -828,7 +799,7 @@ Normalizer2Impl::decomposeShort(const uint8_t *src, const uint8_t *limit, } else { leadCC = 0; } - if (!buffer.append((const char16_t *)mapping+1, length, leadCC, trailCC, errorCode)) { + if (!buffer.append((const char16_t *)mapping+1, length, TRUE, leadCC, trailCC, errorCode)) { return nullptr; } } @@ -854,7 +825,7 @@ Normalizer2Impl::getDecomposition(UChar32 c, UChar buffer[4], int32_t &length) c length=0; U16_APPEND_UNSAFE(buffer, length, c); // The mapping might decompose further. - norm16 = getNorm16(c); + norm16 = getRawNorm16(c); } if (norm16 < minYesNo) { return decomp; @@ -926,19 +897,30 @@ void Normalizer2Impl::decomposeAndAppend(const UChar *src, const UChar *limit, return; } // Just merge the strings at the boundary. - ForwardUTrie2StringIterator iter(normTrie, src, limit); - uint8_t firstCC, prevCC, cc; - firstCC=prevCC=cc=getCC(iter.next16()); - while(cc!=0) { - prevCC=cc; - cc=getCC(iter.next16()); - }; + bool isFirst = true; + uint8_t firstCC = 0, prevCC = 0, cc; + const UChar *p = src; + while (p != limit) { + const UChar *codePointStart = p; + UChar32 c; + uint16_t norm16; + UCPTRIE_FAST_U16_NEXT(normTrie, UCPTRIE_16, p, limit, c, norm16); + if ((cc = getCC(norm16)) == 0) { + p = codePointStart; + break; + } + if (isFirst) { + firstCC = cc; + isFirst = false; + } + prevCC = cc; + } if(limit==NULL) { // appendZeroCC() needs limit!=NULL - limit=u_strchr(iter.codePointStart, 0); + limit=u_strchr(p, 0); } - if (buffer.append(src, (int32_t)(iter.codePointStart-src), firstCC, prevCC, errorCode)) { - buffer.appendZeroCC(iter.codePointStart, limit, errorCode); + if (buffer.append(src, (int32_t)(p - src), FALSE, firstCC, prevCC, errorCode)) { + buffer.appendZeroCC(p, limit, errorCode); } } @@ -1085,7 +1067,7 @@ void Normalizer2Impl::addComposites(const uint16_t *list, UnicodeSet &set) const } UChar32 composite=compositeAndFwd>>1; if((compositeAndFwd&1)!=0) { - addComposites(getCompositionsListForComposite(getNorm16(composite)), set); + addComposites(getCompositionsListForComposite(getRawNorm16(composite)), set); } set.add(composite); } while((firstUnit&COMP_1_LAST_TUPLE)==0); @@ -1124,7 +1106,7 @@ void Normalizer2Impl::recompose(ReorderingBuffer &buffer, int32_t recomposeStart prevCC=0; for(;;) { - UTRIE2_U16_NEXT16(normTrie, p, limit, c, norm16); + UCPTRIE_FAST_U16_NEXT(normTrie, UCPTRIE_16, p, limit, c, norm16); cc=getCCFromYesOrMaybe(norm16); if( // this character combines backward and isMaybe(norm16) && @@ -1229,7 +1211,7 @@ void Normalizer2Impl::recompose(ReorderingBuffer &buffer, int32_t recomposeStart // Is the composite a starter that combines forward? if(compositeAndFwd&1) { compositionsList= - getCompositionsListForComposite(getNorm16(composite)); + getCompositionsListForComposite(getRawNorm16(composite)); } else { compositionsList=NULL; } @@ -1268,7 +1250,7 @@ void Normalizer2Impl::recompose(ReorderingBuffer &buffer, int32_t recomposeStart UChar32 Normalizer2Impl::composePair(UChar32 a, UChar32 b) const { - uint16_t norm16=getNorm16(a); // maps an out-of-range 'a' to inert norm16=0 + uint16_t norm16=getNorm16(a); // maps an out-of-range 'a' to inert norm16 const uint16_t *list; if(isInert(norm16)) { return U_SENTINEL; @@ -1359,29 +1341,23 @@ Normalizer2Impl::compose(const UChar *src, const UChar *limit, return TRUE; } if( (c=*src)= MIN_YES_YES_WITH_CC) { cc = getCCFromNormalYesOrMaybe(n16); if (prevCC > cc) { @@ -1559,7 +1535,7 @@ Normalizer2Impl::compose(const UChar *src, const UChar *limit, // decompose and recompose. if (prevBoundary != prevSrc && !norm16HasCompBoundaryBefore(norm16)) { const UChar *p = prevSrc; - UTRIE2_U16_PREV16(normTrie, prevBoundary, p, c, norm16); + UCPTRIE_FAST_U16_PREV(normTrie, UCPTRIE_16, prevBoundary, p, c, norm16); if (!norm16HasCompBoundaryAfter(norm16, onlyContiguous)) { prevSrc = p; } @@ -1626,29 +1602,23 @@ Normalizer2Impl::composeQuickCheck(const UChar *src, const UChar *limit, return src; } if( (c=*src)= MIN_YES_YES_WITH_CC) { cc = getCCFromNormalYesOrMaybe(n16); if (prevCC > cc) { @@ -1975,7 +1945,7 @@ Normalizer2Impl::composeUTF8(uint32_t options, UBool onlyContiguous, // decompose and recompose. if (prevBoundary != prevSrc && !norm16HasCompBoundaryBefore(norm16)) { const uint8_t *p = prevSrc; - UTRIE2_U8_PREV16(normTrie, prevBoundary, p, norm16); + UCPTRIE_FAST_U8_PREV(normTrie, UCPTRIE_16, prevBoundary, p, norm16); if (!norm16HasCompBoundaryAfter(norm16, onlyContiguous)) { prevSrc = p; } @@ -2023,7 +1993,7 @@ UBool Normalizer2Impl::hasCompBoundaryBefore(const UChar *src, const UChar *limi } UChar32 c; uint16_t norm16; - UTRIE2_U16_NEXT16(normTrie, src, limit, c, norm16); + UCPTRIE_FAST_U16_NEXT(normTrie, UCPTRIE_16, src, limit, c, norm16); return norm16HasCompBoundaryBefore(norm16); } @@ -2032,7 +2002,7 @@ UBool Normalizer2Impl::hasCompBoundaryBefore(const uint8_t *src, const uint8_t * return TRUE; } uint16_t norm16; - UTRIE2_U8_NEXT16(normTrie, src, limit, norm16); + UCPTRIE_FAST_U8_NEXT(normTrie, UCPTRIE_16, src, limit, norm16); return norm16HasCompBoundaryBefore(norm16); } @@ -2043,7 +2013,7 @@ UBool Normalizer2Impl::hasCompBoundaryAfter(const UChar *start, const UChar *p, } UChar32 c; uint16_t norm16; - UTRIE2_U16_PREV16(normTrie, start, p, c, norm16); + UCPTRIE_FAST_U16_PREV(normTrie, UCPTRIE_16, start, p, c, norm16); return norm16HasCompBoundaryAfter(norm16, onlyContiguous); } @@ -2053,36 +2023,42 @@ UBool Normalizer2Impl::hasCompBoundaryAfter(const uint8_t *start, const uint8_t return TRUE; } uint16_t norm16; - UTRIE2_U8_PREV16(normTrie, start, p, norm16); + UCPTRIE_FAST_U8_PREV(normTrie, UCPTRIE_16, start, p, norm16); return norm16HasCompBoundaryAfter(norm16, onlyContiguous); } const UChar *Normalizer2Impl::findPreviousCompBoundary(const UChar *start, const UChar *p, UBool onlyContiguous) const { - BackwardUTrie2StringIterator iter(normTrie, start, p); - for(;;) { - uint16_t norm16=iter.previous16(); + while (p != start) { + const UChar *codePointLimit = p; + UChar32 c; + uint16_t norm16; + UCPTRIE_FAST_U16_PREV(normTrie, UCPTRIE_16, start, p, c, norm16); if (norm16HasCompBoundaryAfter(norm16, onlyContiguous)) { - return iter.codePointLimit; + return codePointLimit; } - if (hasCompBoundaryBefore(iter.codePoint, norm16)) { - return iter.codePointStart; + if (hasCompBoundaryBefore(c, norm16)) { + return p; } } + return p; } const UChar *Normalizer2Impl::findNextCompBoundary(const UChar *p, const UChar *limit, UBool onlyContiguous) const { - ForwardUTrie2StringIterator iter(normTrie, p, limit); - for(;;) { - uint16_t norm16=iter.next16(); - if (hasCompBoundaryBefore(iter.codePoint, norm16)) { - return iter.codePointStart; + while (p != limit) { + const UChar *codePointStart = p; + UChar32 c; + uint16_t norm16; + UCPTRIE_FAST_U16_NEXT(normTrie, UCPTRIE_16, p, limit, c, norm16); + if (hasCompBoundaryBefore(c, norm16)) { + return codePointStart; } if (norm16HasCompBoundaryAfter(norm16, onlyContiguous)) { - return iter.codePointLimit; + return p; } } + return p; } uint8_t Normalizer2Impl::getPreviousTrailCC(const UChar *start, const UChar *p) const { @@ -2130,7 +2106,7 @@ uint16_t Normalizer2Impl::getFCD16FromNormData(UChar32 c) const { } // Maps to an isCompYesAndZeroCC. c=mapAlgorithmic(c, norm16); - norm16=getNorm16(c); + norm16=getRawNorm16(c); } } if(norm16<=minYesNo || isHangulLVT(norm16)) { @@ -2195,17 +2171,10 @@ Normalizer2Impl::makeFCD(const UChar *src, const UChar *limit, prevFCD16=0; ++src; } else { - if(U16_IS_SURROGATE(c)) { + if(U16_IS_LEAD(c)) { UChar c2; - if(U16_IS_SURROGATE_LEAD(c)) { - if((src+1)!=limit && U16_IS_TRAIL(c2=src[1])) { - c=U16_GET_SUPPLEMENTARY(c, c2); - } - } else /* trail surrogate */ { - if(prevSrcadd(firstOrigin); @@ -2406,7 +2376,6 @@ void CanonIterData::addToStartSet(UChar32 origin, UChar32 decompLead, UErrorCode class InitCanonIterData { public: static void doInit(Normalizer2Impl *impl, UErrorCode &errorCode); - static void handleRange(Normalizer2Impl *impl, UChar32 start, UChar32 end, uint16_t value, UErrorCode &errorCode); }; U_CDECL_BEGIN @@ -2417,18 +2386,6 @@ initCanonIterData(Normalizer2Impl *impl, UErrorCode &errorCode) { InitCanonIterData::doInit(impl, errorCode); } -// Call Normalizer2Impl::makeCanonIterDataFromNorm16() for a range of same-norm16 characters. -// context: the Normalizer2Impl -static UBool U_CALLCONV -enumCIDRangeHandler(const void *context, UChar32 start, UChar32 end, uint32_t value) { - UErrorCode errorCode = U_ZERO_ERROR; - if (value != Normalizer2Impl::INERT) { - Normalizer2Impl *impl = (Normalizer2Impl *)context; - InitCanonIterData::handleRange(impl, start, end, (uint16_t)value, errorCode); - } - return U_SUCCESS(errorCode); -} - U_CDECL_END void InitCanonIterData::doInit(Normalizer2Impl *impl, UErrorCode &errorCode) { @@ -2438,8 +2395,24 @@ void InitCanonIterData::doInit(Normalizer2Impl *impl, UErrorCode &errorCode) { errorCode=U_MEMORY_ALLOCATION_ERROR; } if (U_SUCCESS(errorCode)) { - utrie2_enum(impl->normTrie, NULL, enumCIDRangeHandler, impl); - utrie2_freeze(impl->fCanonIterData->trie, UTRIE2_32_VALUE_BITS, &errorCode); + UChar32 start = 0, end; + uint32_t value; + while ((end = ucptrie_getRange(impl->normTrie, start, + UCPMAP_RANGE_FIXED_LEAD_SURROGATES, Normalizer2Impl::INERT, + nullptr, nullptr, &value)) >= 0) { + // Call Normalizer2Impl::makeCanonIterDataFromNorm16() for a range of same-norm16 characters. + if (value != Normalizer2Impl::INERT) { + impl->makeCanonIterDataFromNorm16(start, end, value, *impl->fCanonIterData, errorCode); + } + start = end + 1; + } +#ifdef UCPTRIE_DEBUG + umutablecptrie_setName(impl->fCanonIterData->mutableTrie, "CanonIterData"); +#endif + impl->fCanonIterData->trie = umutablecptrie_buildImmutable( + impl->fCanonIterData->mutableTrie, UCPTRIE_TYPE_SMALL, UCPTRIE_VALUE_BITS_32, &errorCode); + umutablecptrie_close(impl->fCanonIterData->mutableTrie); + impl->fCanonIterData->mutableTrie = nullptr; } if (U_FAILURE(errorCode)) { delete impl->fCanonIterData; @@ -2447,11 +2420,6 @@ void InitCanonIterData::doInit(Normalizer2Impl *impl, UErrorCode &errorCode) { } } -void InitCanonIterData::handleRange( - Normalizer2Impl *impl, UChar32 start, UChar32 end, uint16_t value, UErrorCode &errorCode) { - impl->makeCanonIterDataFromNorm16(start, end, value, *impl->fCanonIterData, errorCode); -} - void Normalizer2Impl::makeCanonIterDataFromNorm16(UChar32 start, UChar32 end, const uint16_t norm16, CanonIterData &newData, UErrorCode &errorCode) const { @@ -2465,7 +2433,7 @@ void Normalizer2Impl::makeCanonIterDataFromNorm16(UChar32 start, UChar32 end, co return; } for(UChar32 c=start; c<=end; ++c) { - uint32_t oldValue=utrie2_get32(newData.trie, c); + uint32_t oldValue = umutablecptrie_get(newData.mutableTrie, c); uint32_t newValue=oldValue; if(isMaybeOrNonZeroCC(norm16)) { // not a segment starter if it occurs in a decomposition or has cc!=0 @@ -2483,7 +2451,7 @@ void Normalizer2Impl::makeCanonIterDataFromNorm16(UChar32 start, UChar32 end, co if (isDecompNoAlgorithmic(norm16_2)) { // Maps to an isCompYesAndZeroCC. c2 = mapAlgorithmic(c2, norm16_2); - norm16_2 = getNorm16(c2); + norm16_2 = getRawNorm16(c2); // No compatibility mappings for the CanonicalIterator. U_ASSERT(!(isHangulLV(norm16_2) || isHangulLVT(norm16_2))); } @@ -2510,10 +2478,10 @@ void Normalizer2Impl::makeCanonIterDataFromNorm16(UChar32 start, UChar32 end, co if(norm16_2>=minNoNo) { while(itrie, c); + return (int32_t)ucptrie_get(fCanonIterData->trie, c); } const UnicodeSet &Normalizer2Impl::getCanonStartSet(int32_t n) const { @@ -2561,7 +2529,7 @@ UBool Normalizer2Impl::getCanonStartSet(UChar32 c, UnicodeSet &set) const { set.add(value); } if((canonValue&CANON_HAS_COMPOSITIONS)!=0) { - uint16_t norm16=getNorm16(c); + uint16_t norm16=getRawNorm16(c); if(norm16==JAMO_L) { UChar32 syllable= (UChar32)(Hangul::HANGUL_BASE+(c-Hangul::JAMO_L_BASE)*Hangul::JAMO_VT_COUNT); @@ -2608,7 +2576,7 @@ unorm2_swap(const UDataSwapper *ds, pInfo->dataFormat[1]==0x72 && pInfo->dataFormat[2]==0x6d && pInfo->dataFormat[3]==0x32 && - (1<=formatVersion0 && formatVersion0<=3) + (1<=formatVersion0 && formatVersion0<=4) )) { udata_printError(ds, "unorm2_swap(): data format %02x.%02x.%02x.%02x (format version %02x) is not recognized as Normalizer2 data\n", pInfo->dataFormat[0], pInfo->dataFormat[1], @@ -2669,9 +2637,9 @@ unorm2_swap(const UDataSwapper *ds, ds->swapArray32(ds, inBytes, nextOffset-offset, outBytes, pErrorCode); offset=nextOffset; - /* swap the UTrie2 */ + /* swap the trie */ nextOffset=indexes[Normalizer2Impl::IX_EXTRA_DATA_OFFSET]; - utrie2_swap(ds, inBytes+offset, nextOffset-offset, outBytes+offset, pErrorCode); + utrie_swapAnyVersion(ds, inBytes+offset, nextOffset-offset, outBytes+offset, pErrorCode); offset=nextOffset; /* swap the uint16_t extraData[] */ diff --git a/deps/icu-small/source/common/normalizer2impl.h b/deps/icu-small/source/common/normalizer2impl.h index 9dd4d1e5ab188b..2e6aff308819c5 100644 --- a/deps/icu-small/source/common/normalizer2impl.h +++ b/deps/icu-small/source/common/normalizer2impl.h @@ -24,12 +24,20 @@ #if !UCONFIG_NO_NORMALIZATION #include "unicode/normalizer2.h" +#include "unicode/ucptrie.h" #include "unicode/unistr.h" #include "unicode/unorm.h" +#include "unicode/utf.h" #include "unicode/utf16.h" #include "mutex.h" +#include "udataswp.h" #include "uset_imp.h" -#include "utrie2.h" + +// When the nfc.nrm data is *not* hardcoded into the common library +// (with this constant set to 0), +// then it needs to be built into the data package: +// Add nfc.nrm to icu4c/source/data/Makefile.in DAT_FILES_SHORT +#define NORM2_HARDCODE_NFC_DATA 1 U_NAMESPACE_BEGIN @@ -118,7 +126,7 @@ class U_COMMON_API Hangul { buffer[0]=(UChar)(JAMO_L_BASE+c/JAMO_V_COUNT); buffer[1]=(UChar)(JAMO_V_BASE+c%JAMO_V_COUNT); } else { - buffer[0]=orig-c2; // LV syllable + buffer[0]=(UChar)(orig-c2); // LV syllable buffer[1]=(UChar)(JAMO_T_BASE+c2); } } @@ -158,8 +166,7 @@ class U_COMMON_API ReorderingBuffer : public UMemory { appendBMP((UChar)c, cc, errorCode) : appendSupplementary(c, cc, errorCode); } - // s must be in NFD, otherwise change the implementation. - UBool append(const UChar *s, int32_t length, + UBool append(const UChar *s, int32_t length, UBool isNFD, uint8_t leadCC, uint8_t trailCC, UErrorCode &errorCode); UBool appendBMP(UChar c, uint8_t cc, UErrorCode &errorCode) { @@ -243,7 +250,7 @@ class U_COMMON_API Normalizer2Impl : public UObject { } virtual ~Normalizer2Impl(); - void init(const int32_t *inIndexes, const UTrie2 *inTrie, + void init(const int32_t *inIndexes, const UCPTrie *inTrie, const uint16_t *inExtraData, const uint8_t *inSmallFCD); void addLcccChars(UnicodeSet &set) const; @@ -254,7 +261,12 @@ class U_COMMON_API Normalizer2Impl : public UObject { UBool ensureCanonIterData(UErrorCode &errorCode) const; - uint16_t getNorm16(UChar32 c) const { return UTRIE2_GET16(normTrie, c); } + // The trie stores values for lead surrogate code *units*. + // Surrogate code *points* are inert. + uint16_t getNorm16(UChar32 c) const { + return U_IS_LEAD(c) ? INERT : UCPTRIE_FAST_GET(normTrie, UCPTRIE_16, c); + } + uint16_t getRawNorm16(UChar32 c) const { return UCPTRIE_FAST_GET(normTrie, UCPTRIE_16, c); } UNormalizationCheckResult getCompQuickCheck(uint16_t norm16) const { if(norm16 # include "unicode/uloc.h" -#if U_PLATFORM_HAS_WINUWP_API == 0 # include "wintz.h" -#else // U_PLATFORM_HAS_WINUWP_API +#if U_PLATFORM_HAS_WINUWP_API typedef PVOID LPMSG; // TODO: figure out how to get rid of this typedef #include #include @@ -1062,53 +1061,13 @@ uprv_tzname_clear_cache() #endif } -// With the Universal Windows Platform we can just ask Windows for the name -#if U_PLATFORM_HAS_WINUWP_API -U_CAPI const char* U_EXPORT2 -uprv_getWindowsTimeZone() -{ - // Get default Windows timezone. - ComPtr calendar; - HRESULT hr = RoActivateInstance( - HStringReference(RuntimeClass_Windows_Globalization_Calendar).Get(), - &calendar); - if (SUCCEEDED(hr)) - { - ComPtr timezone; - hr = calendar.As(&timezone); - if (SUCCEEDED(hr)) - { - HString timezoneString; - hr = timezone->GetTimeZone(timezoneString.GetAddressOf()); - if (SUCCEEDED(hr)) - { - int32_t length = static_cast(wcslen(timezoneString.GetRawBuffer(NULL))); - char* asciiId = (char*)uprv_calloc(length + 1, sizeof(char)); - if (asciiId != nullptr) - { - u_UCharsToChars((UChar*)timezoneString.GetRawBuffer(NULL), asciiId, length); - return asciiId; - } - } - } - } - - // Failed - return nullptr; -} -#endif - U_CAPI const char* U_EXPORT2 uprv_tzname(int n) { (void)n; // Avoid unreferenced parameter warning. const char *tzid = NULL; #if U_PLATFORM_USES_ONLY_WIN32_API -#if U_PLATFORM_HAS_WINUWP_API > 0 - tzid = uprv_getWindowsTimeZone(); -#else tzid = uprv_detectWindowsTimeZone(); -#endif if (tzid != NULL) { return tzid; @@ -1366,6 +1325,43 @@ uprv_pathIsAbsolute(const char *path) # endif #endif +#if U_PLATFORM_HAS_WINUWP_API != 0 +// Helper function to get the ICU Data Directory under the Windows directory location. +static BOOL U_CALLCONV getIcuDataDirectoryUnderWindowsDirectory(char* directoryBuffer, UINT bufferLength) +{ +#if defined(ICU_DATA_DIR_WINDOWS) + wchar_t windowsPath[MAX_PATH]; + char windowsPathUtf8[MAX_PATH]; + + UINT length = GetSystemWindowsDirectoryW(windowsPath, UPRV_LENGTHOF(windowsPath)); + if ((length > 0) && (length < (UPRV_LENGTHOF(windowsPath) - 1))) { + // Convert UTF-16 to a UTF-8 string. + UErrorCode status = U_ZERO_ERROR; + int32_t windowsPathUtf8Len = 0; + u_strToUTF8(windowsPathUtf8, static_cast(UPRV_LENGTHOF(windowsPathUtf8)), + &windowsPathUtf8Len, reinterpret_cast(windowsPath), -1, &status); + + if (U_SUCCESS(status) && (status != U_STRING_NOT_TERMINATED_WARNING) && + (windowsPathUtf8Len < (UPRV_LENGTHOF(windowsPathUtf8) - 1))) { + // Ensure it always has a separator, so we can append the ICU data path. + if (windowsPathUtf8[windowsPathUtf8Len - 1] != U_FILE_SEP_CHAR) { + windowsPathUtf8[windowsPathUtf8Len++] = U_FILE_SEP_CHAR; + windowsPathUtf8[windowsPathUtf8Len] = '\0'; + } + // Check if the concatenated string will fit. + if ((windowsPathUtf8Len + UPRV_LENGTHOF(ICU_DATA_DIR_WINDOWS)) < bufferLength) { + uprv_strcpy(directoryBuffer, windowsPathUtf8); + uprv_strcat(directoryBuffer, ICU_DATA_DIR_WINDOWS); + return TRUE; + } + } + } +#endif + + return FALSE; +} +#endif + static void U_CALLCONV dataDirectoryInitFn() { /* If we already have the directory, then return immediately. Will happen if user called * u_setDataDirectory(). @@ -1425,24 +1421,10 @@ static void U_CALLCONV dataDirectoryInitFn() { } #endif -#if defined(ICU_DATA_DIR_WINDOWS) && U_PLATFORM_HAS_WINUWP_API != 0 - // Use data from the %windir%\globalization\icu directory - // This is only available if ICU is built as a system component +#if U_PLATFORM_HAS_WINUWP_API != 0 && defined(ICU_DATA_DIR_WINDOWS) char datadir_path_buffer[MAX_PATH]; - UINT length = GetWindowsDirectoryA(datadir_path_buffer, UPRV_LENGTHOF(datadir_path_buffer)); - if (length > 0 && length < (UPRV_LENGTHOF(datadir_path_buffer) - sizeof(ICU_DATA_DIR_WINDOWS) - 1)) - { - if (datadir_path_buffer[length - 1] != '\\') - { - datadir_path_buffer[length++] = '\\'; - datadir_path_buffer[length] = '\0'; - } - - if ((length + 1 + sizeof(ICU_DATA_DIR_WINDOWS)) < UPRV_LENGTHOF(datadir_path_buffer)) - { - uprv_strcat(datadir_path_buffer, ICU_DATA_DIR_WINDOWS); - path = datadir_path_buffer; - } + if (getIcuDataDirectoryUnderWindowsDirectory(datadir_path_buffer, UPRV_LENGTHOF(datadir_path_buffer))) { + path = datadir_path_buffer; } #endif @@ -1491,20 +1473,30 @@ static void U_CALLCONV TimeZoneDataDirInitFn(UErrorCode &status) { status = U_MEMORY_ALLOCATION_ERROR; return; } -#if U_PLATFORM_HAS_WINUWP_API == 0 - const char *dir = getenv("ICU_TIMEZONE_FILES_DIR"); -#else - // TODO: UWP does not support alternate timezone data directories at this time + const char *dir = ""; + +#if U_PLATFORM_HAS_WINUWP_API != 0 + // The UWP version does not support the environment variable setting, but can possibly pick them up from the Windows directory. + char datadir_path_buffer[MAX_PATH]; + if (getIcuDataDirectoryUnderWindowsDirectory(datadir_path_buffer, UPRV_LENGTHOF(datadir_path_buffer))) { + dir = datadir_path_buffer; + } +#else + dir = getenv("ICU_TIMEZONE_FILES_DIR"); #endif // U_PLATFORM_HAS_WINUWP_API + #if defined(U_TIMEZONE_FILES_DIR) if (dir == NULL) { + // Build time configuration setting. dir = TO_STRING(U_TIMEZONE_FILES_DIR); } #endif + if (dir == NULL) { dir = ""; } + setTimeZoneFilesDir(dir, status); } @@ -1676,7 +1668,8 @@ The leftmost codepage (.xxx) wins. /* Note that we scan the *uncorrected* ID. */ if ((p = uprv_strrchr(posixID, '@')) != NULL) { if (correctedPOSIXLocale == NULL) { - correctedPOSIXLocale = static_cast(uprv_malloc(uprv_strlen(posixID)+1)); + /* new locale can be 1 char longer than old one if @ -> __ */ + correctedPOSIXLocale = static_cast(uprv_malloc(uprv_strlen(posixID)+2)); /* Exit on memory allocation error. */ if (correctedPOSIXLocale == NULL) { return NULL; @@ -1693,7 +1686,7 @@ The leftmost codepage (.xxx) wins. } if (uprv_strchr(correctedPOSIXLocale,'_') == NULL) { - uprv_strcat(correctedPOSIXLocale, "__"); /* aa@b -> aa__b */ + uprv_strcat(correctedPOSIXLocale, "__"); /* aa@b -> aa__b (note this can make the new locale 1 char longer) */ } else { uprv_strcat(correctedPOSIXLocale, "_"); /* aa_CC@b -> aa_CC_b */ @@ -1747,70 +1740,22 @@ The leftmost codepage (.xxx) wins. #elif U_PLATFORM_USES_ONLY_WIN32_API #define POSIX_LOCALE_CAPACITY 64 UErrorCode status = U_ZERO_ERROR; - char *correctedPOSIXLocale = 0; + char *correctedPOSIXLocale = nullptr; // If we have already figured this out just use the cached value - if (gCorrectedPOSIXLocale != NULL) { + if (gCorrectedPOSIXLocale != nullptr) { return gCorrectedPOSIXLocale; } // No cached value, need to determine the current value - static WCHAR windowsLocale[LOCALE_NAME_MAX_LENGTH]; -#if U_PLATFORM_HAS_WINUWP_API == 0 - // If not a Universal Windows App, we'll need user default language. - // Vista and above should use Locale Names instead of LCIDs - int length = GetUserDefaultLocaleName(windowsLocale, UPRV_LENGTHOF(windowsLocale)); -#else - // In a UWP app, we want the top language that the application and user agreed upon - ComPtr> languageList; - - ComPtr applicationLanguagesStatics; - HRESULT hr = GetActivationFactory( - HStringReference(RuntimeClass_Windows_Globalization_ApplicationLanguages).Get(), - &applicationLanguagesStatics); - if (SUCCEEDED(hr)) - { - hr = applicationLanguagesStatics->get_Languages(&languageList); - } + static WCHAR windowsLocale[LOCALE_NAME_MAX_LENGTH] = {}; + int length = GetLocaleInfoEx(LOCALE_NAME_USER_DEFAULT, LOCALE_SNAME, windowsLocale, LOCALE_NAME_MAX_LENGTH); - if (FAILED(hr)) - { - // If there is no application context, then use the top language from the user language profile - ComPtr globalizationPreferencesStatics; - hr = GetActivationFactory( - HStringReference(RuntimeClass_Windows_System_UserProfile_GlobalizationPreferences).Get(), - &globalizationPreferencesStatics); - if (SUCCEEDED(hr)) - { - hr = globalizationPreferencesStatics->get_Languages(&languageList); - } - } - - // We have a list of languages, ICU knows one, so use the top one for our locale - HString topLanguage; - if (SUCCEEDED(hr)) - { - hr = languageList->GetAt(0, topLanguage.GetAddressOf()); - } - - if (FAILED(hr)) - { - // Unexpected, use en-US by default - if (gCorrectedPOSIXLocale == NULL) { - gCorrectedPOSIXLocale = "en_US"; - } - - return gCorrectedPOSIXLocale; - } - - // ResolveLocaleName will get a likely subtags form consistent with Windows behavior. - int length = ResolveLocaleName(topLanguage.GetRawBuffer(NULL), windowsLocale, UPRV_LENGTHOF(windowsLocale)); -#endif - // Now we should have a Windows locale name that needs converted to the POSIX style, - if (length > 0) + // Now we should have a Windows locale name that needs converted to the POSIX style. + if (length > 0) // If length is 0, then the GetLocaleInfoEx failed. { // First we need to go from UTF-16 to char (and also convert from _ to - while we're at it.) - char modifiedWindowsLocale[LOCALE_NAME_MAX_LENGTH]; + char modifiedWindowsLocale[LOCALE_NAME_MAX_LENGTH] = {}; int32_t i; for (i = 0; i < UPRV_LENGTHOF(modifiedWindowsLocale); i++) @@ -1858,7 +1803,7 @@ The leftmost codepage (.xxx) wins. } // If unable to find a locale we can agree upon, use en-US by default - if (gCorrectedPOSIXLocale == NULL) { + if (gCorrectedPOSIXLocale == nullptr) { gCorrectedPOSIXLocale = "en_US"; } return gCorrectedPOSIXLocale; diff --git a/deps/icu-small/source/common/putilimp.h b/deps/icu-small/source/common/putilimp.h index 023e06879a0655..f744746b1f0feb 100644 --- a/deps/icu-small/source/common/putilimp.h +++ b/deps/icu-small/source/common/putilimp.h @@ -94,7 +94,7 @@ typedef size_t uintptr_t; # define U_NL_LANGINFO_CODESET CODESET #endif -#ifdef U_TZSET +#if defined(U_TZSET) || defined(U_HAVE_TZSET) /* Use the predefined value. */ #elif U_PLATFORM_USES_ONLY_WIN32_API // UWP doesn't support tzset or environment variables for tz @@ -132,7 +132,7 @@ typedef size_t uintptr_t; # define U_TIMEZONE timezone #endif -#ifdef U_TZNAME +#if defined(U_TZNAME) || defined(U_HAVE_TZNAME) /* Use the predefined value. */ #elif U_PLATFORM_USES_ONLY_WIN32_API /* not usable on all windows platforms */ @@ -204,30 +204,18 @@ typedef size_t uintptr_t; /** * \def U_HAVE_STD_ATOMICS - * Defines whether the standard C++11 is available. - * ICU will use this when available, - * otherwise will fall back to compiler or platform specific alternatives. + * Defines whether to use the standard C++11 functions + * If false, ICU will fall back to compiler or platform specific alternatives. + * Note: support for these fall back options for atomics will be removed in a future version + * of ICU, and the use of C++ 11 atomics will be required. * @internal */ #ifdef U_HAVE_STD_ATOMICS /* Use the predefined value. */ -#elif U_CPLUSPLUS_VERSION < 11 - /* Not C++11, disable use of atomics */ -# define U_HAVE_STD_ATOMICS 0 -#elif __clang__ && __clang_major__==3 && __clang_minor__<=1 - /* Clang 3.1, has atomic variable initializer bug. */ -# define U_HAVE_STD_ATOMICS 0 #else - /* U_HAVE_ATOMIC is typically set by an autoconf test of #include */ - /* Can be set manually, or left undefined, on platforms without autoconf. */ -# if defined(U_HAVE_ATOMIC) && U_HAVE_ATOMIC -# define U_HAVE_STD_ATOMICS 1 -# else -# define U_HAVE_STD_ATOMICS 0 -# endif +# define U_HAVE_STD_ATOMICS 1 #endif - /** * \def U_HAVE_CLANG_ATOMICS * Defines whether Clang c11 style built-in atomics are available. @@ -586,6 +574,49 @@ U_INTERNAL void * U_EXPORT2 uprv_maximumPtr(void *base); # endif #endif + +#ifdef __cplusplus +/** + * Pin a buffer capacity such that doing pointer arithmetic + * on the destination pointer and capacity cannot overflow. + * + * The pinned capacity must fulfill the following conditions (for positive capacities): + * - dest + capacity is a valid pointer according to the machine arcitecture (AS/400, 64-bit, etc.) + * - (dest + capacity) >= dest + * - The size (in bytes) of T[capacity] does not exceed 0x7fffffff + * + * @param dest the destination buffer pointer. + * @param capacity the requested buffer capacity, in units of type T. + * @return the pinned capacity. + * @internal + */ +template +inline int32_t pinCapacity(T *dest, int32_t capacity) { + if (capacity <= 0) { return capacity; } + + uintptr_t destInt = (uintptr_t)dest; + uintptr_t maxInt; + +# if U_PLATFORM == U_PF_OS390 && !defined(_LP64) + // We have 31-bit pointers. + maxInt = 0x7fffffff; +# elif U_PLATFORM == U_PF_OS400 + maxInt = (uintptr_t)uprv_maximumPtr((void *)dest); +# else + maxInt = destInt + 0x7fffffffu; + if (maxInt < destInt) { + // Less than 2GB to the end of the address space. + // Pin to that to prevent address overflow. + maxInt = (uintptr_t)-1; + } +# endif + + uintptr_t maxBytes = maxInt - destInt; // max. 2GB + int32_t maxCapacity = (int32_t)(maxBytes / sizeof(T)); + return capacity <= maxCapacity ? capacity : maxCapacity; +} +#endif // __cplusplus + /* Dynamic Library Functions */ typedef void (UVoidFunction)(void); diff --git a/deps/icu-small/source/common/rbbi.cpp b/deps/icu-small/source/common/rbbi.cpp index c5ea2770ba9854..cb3766506f4082 100644 --- a/deps/icu-small/source/common/rbbi.cpp +++ b/deps/icu-small/source/common/rbbi.cpp @@ -18,6 +18,8 @@ #if !UCONFIG_NO_BREAK_ITERATION +#include + #include "unicode/rbbi.h" #include "unicode/schriter.h" #include "unicode/uchriter.h" @@ -628,7 +630,7 @@ int32_t RuleBasedBreakIterator::preceding(int32_t offset) { // or on a trail byte if the input is UTF-8. utext_setNativeIndex(&fText, offset); - int32_t adjustedOffset = utext_getNativeIndex(&fText); + int32_t adjustedOffset = static_cast(utext_getNativeIndex(&fText)); UErrorCode status = U_ZERO_ERROR; fBreakCache->preceding(adjustedOffset, status); @@ -655,7 +657,7 @@ UBool RuleBasedBreakIterator::isBoundary(int32_t offset) { // But we still need the side effect of leaving iteration at the following boundary. utext_setNativeIndex(&fText, offset); - int32_t adjustedOffset = utext_getNativeIndex(&fText); + int32_t adjustedOffset = static_cast(utext_getNativeIndex(&fText)); bool result = false; UErrorCode status = U_ZERO_ERROR; @@ -848,7 +850,7 @@ int32_t RuleBasedBreakIterator::handleNext() { #ifdef RBBI_DEBUG if (gTrace) { - RBBIDebugPrintf(" %4ld ", utext_getNativeIndex(&fText)); + RBBIDebugPrintf(" %4" PRId64 " ", utext_getNativeIndex(&fText)); if (0x20<=c && c<0x7f) { RBBIDebugPrintf("\"%c\" ", c); } else { diff --git a/deps/icu-small/source/common/rbbi_cache.cpp b/deps/icu-small/source/common/rbbi_cache.cpp index 60316ce6420dc5..519c61049894e6 100644 --- a/deps/icu-small/source/common/rbbi_cache.cpp +++ b/deps/icu-small/source/common/rbbi_cache.cpp @@ -603,7 +603,7 @@ void RuleBasedBreakIterator::BreakCache::addFollowing(int32_t position, int32_t fStartBufIdx = modChunkSize(fStartBufIdx + 6); // TODO: experiment. Probably revert to 1. } fBoundaries[nextIdx] = position; - fStatuses[nextIdx] = ruleStatusIdx; + fStatuses[nextIdx] = static_cast(ruleStatusIdx); fEndBufIdx = nextIdx; if (update == UpdateCachePosition) { // Set current position to the newly added boundary. @@ -631,7 +631,7 @@ bool RuleBasedBreakIterator::BreakCache::addPreceding(int32_t position, int32_t fEndBufIdx = modChunkSize(fEndBufIdx - 1); } fBoundaries[nextIdx] = position; - fStatuses[nextIdx] = ruleStatusIdx; + fStatuses[nextIdx] = static_cast(ruleStatusIdx); fStartBufIdx = nextIdx; if (update == UpdateCachePosition) { fBufIdx = nextIdx; diff --git a/deps/icu-small/source/common/rbbirb.cpp b/deps/icu-small/source/common/rbbirb.cpp index a46f483d23334a..5f5661af94776d 100644 --- a/deps/icu-small/source/common/rbbirb.cpp +++ b/deps/icu-small/source/common/rbbirb.cpp @@ -303,17 +303,24 @@ RBBIDataHeader *RBBIRuleBuilder::build(UErrorCode &status) { } void RBBIRuleBuilder::optimizeTables() { + bool didSomething; + do { + didSomething = false; + + // Begin looking for duplicates with char class 3. + // Classes 0, 1 and 2 are special; they are unused, {bof} and {eof} respectively, + // and should not have other categories merged into them. + IntPair duplPair = {3, 0}; + while (fForwardTable->findDuplCharClassFrom(&duplPair)) { + fSetBuilder->mergeCategories(duplPair); + fForwardTable->removeColumn(duplPair.second); + didSomething = true; + } - // Begin looking for duplicates with char class 3. - // Classes 0, 1 and 2 are special; they are unused, {bof} and {eof} respectively, - // and should not have other categories merged into them. - IntPair duplPair = {3, 0}; - - while (fForwardTable->findDuplCharClassFrom(&duplPair)) { - fSetBuilder->mergeCategories(duplPair); - fForwardTable->removeColumn(duplPair.second); - } - fForwardTable->removeDuplicateStates(); + while (fForwardTable->removeDuplicateStates() > 0) { + didSomething = true; + } + } while (didSomething); } U_NAMESPACE_END diff --git a/deps/icu-small/source/common/rbbiscan.cpp b/deps/icu-small/source/common/rbbiscan.cpp index ecc1663d8f84f7..170c212e13fd1f 100644 --- a/deps/icu-small/source/common/rbbiscan.cpp +++ b/deps/icu-small/source/common/rbbiscan.cpp @@ -380,7 +380,7 @@ UBool RBBIRuleScanner::doParseActions(int32_t action) // with the current rule expression (on the Node Stack) // with the resulting OR expression going to *destRules // - RBBINode *thisRule = fNodeStack[fNodeStackPtr]; + thisRule = fNodeStack[fNodeStackPtr]; RBBINode *prevRules = *destRules; RBBINode *orNode = pushNewNode(RBBINode::opOr); if (U_FAILURE(*fRB->fStatus)) { diff --git a/deps/icu-small/source/common/rbbitblb.cpp b/deps/icu-small/source/common/rbbitblb.cpp index 42116b0f95575f..e6ae2dc654a88c 100644 --- a/deps/icu-small/source/common/rbbitblb.cpp +++ b/deps/icu-small/source/common/rbbitblb.cpp @@ -428,8 +428,8 @@ void RBBITableBuilder::calcChainedFollowPos(RBBINode *tree) { addRuleRootNodes(&ruleRootNodes, tree); UVector matchStartNodes(*fStatus); - for (int i=0; i(ruleRootNodes.elementAt(i)); + for (int j=0; j(ruleRootNodes.elementAt(j)); if (node->fChainIn) { setAdd(&matchStartNodes, node->fFirstPosSet); } @@ -1082,21 +1082,22 @@ bool RBBITableBuilder::findDuplCharClassFrom(IntPair *categories) { int32_t numStates = fDStates->size(); int32_t numCols = fRB->fSetBuilder->getNumCharCategories(); - uint16_t table_base; - uint16_t table_dupl; for (; categories->first < numCols-1; categories->first++) { for (categories->second=categories->first+1; categories->second < numCols; categories->second++) { - for (int32_t state=0; stateelementAt(state); - table_base = (uint16_t)sd->fDtran->elementAti(categories->first); - table_dupl = (uint16_t)sd->fDtran->elementAti(categories->second); - if (table_base != table_dupl) { - break; - } - } - if (table_base == table_dupl) { - return true; - } + // Initialized to different values to prevent returning true if numStates = 0 (implies no duplicates). + uint16_t table_base = 0; + uint16_t table_dupl = 1; + for (int32_t state=0; stateelementAt(state); + table_base = (uint16_t)sd->fDtran->elementAti(categories->first); + table_dupl = (uint16_t)sd->fDtran->elementAti(categories->second); + if (table_base != table_dupl) { + break; + } + } + if (table_base == table_dupl) { + return true; + } } } return false; @@ -1236,7 +1237,7 @@ void RBBITableBuilder::removeSafeState(IntPair duplStates) { } else if (existingVal > duplState) { newVal = existingVal - 1; } - sd->setCharAt(col, newVal); + sd->setCharAt(col, static_cast(newVal)); } } } @@ -1245,12 +1246,16 @@ void RBBITableBuilder::removeSafeState(IntPair duplStates) { /* * RemoveDuplicateStates */ -void RBBITableBuilder::removeDuplicateStates() { +int32_t RBBITableBuilder::removeDuplicateStates() { IntPair dupls = {3, 0}; + int32_t numStatesRemoved = 0; + while (findDuplicateState(&dupls)) { // printf("Removing duplicate states (%d, %d)\n", dupls.first, dupls.second); removeState(dupls); + ++numStatesRemoved; } + return numStatesRemoved; } @@ -1411,7 +1416,7 @@ void RBBITableBuilder::buildSafeReverseTable(UErrorCode &status) { UnicodeString &startState = *static_cast(fSafeTable->elementAt(1)); for (int32_t charClass=0; charClass < numCharClasses; ++charClass) { // Note: +2 for the start & stop state. - startState.setCharAt(charClass, charClass+2); + startState.setCharAt(charClass, static_cast(charClass+2)); } // Initially make every other state table row look like the start state row, diff --git a/deps/icu-small/source/common/rbbitblb.h b/deps/icu-small/source/common/rbbitblb.h index eea243e4cdd6c3..bc6077bb4da3dc 100644 --- a/deps/icu-small/source/common/rbbitblb.h +++ b/deps/icu-small/source/common/rbbitblb.h @@ -15,6 +15,9 @@ #define RBBITBLB_H #include "unicode/utypes.h" + +#if !UCONFIG_NO_BREAK_ITERATION + #include "unicode/uobject.h" #include "unicode/rbbi.h" #include "rbbirb.h" @@ -66,8 +69,11 @@ class RBBITableBuilder : public UMemory { */ void removeColumn(int32_t column); - /** Check for, and remove dupicate states (table rows). */ - void removeDuplicateStates(); + /** + * Check for, and remove dupicate states (table rows). + * @return the number of states removed. + */ + int32_t removeDuplicateStates(); /** Build the safe reverse table from the already-constructed forward table. */ void buildSafeReverseTable(UErrorCode &status); @@ -204,4 +210,7 @@ class RBBIStateDescriptor : public UMemory { U_NAMESPACE_END + +#endif /* #if !UCONFIG_NO_BREAK_ITERATION */ + #endif diff --git a/deps/icu-small/source/common/serv.cpp b/deps/icu-small/source/common/serv.cpp index 35e362b71a8fc2..2fb35bd1a5994f 100644 --- a/deps/icu-small/source/common/serv.cpp +++ b/deps/icu-small/source/common/serv.cpp @@ -702,9 +702,9 @@ ICUService::getDisplayName(const UnicodeString& id, UnicodeString& result, const } // fallback - UErrorCode status = U_ZERO_ERROR; + status = U_ZERO_ERROR; ICUServiceKey* fallbackKey = createKey(&id, status); - while (fallbackKey->fallback()) { + while (fallbackKey != NULL && fallbackKey->fallback()) { UnicodeString us; fallbackKey->currentID(us); f = (ICUServiceFactory*)map->get(us); diff --git a/deps/icu-small/source/common/sharedobject.h b/deps/icu-small/source/common/sharedobject.h index 54655d0d716720..878594c7ffa772 100644 --- a/deps/icu-small/source/common/sharedobject.h +++ b/deps/icu-small/source/common/sharedobject.h @@ -104,7 +104,7 @@ class U_COMMON_API SharedObject : public UObject { /** * Deletes this object if it has no references. * Available for non-cached SharedObjects only. Ownership of cached objects - * is with the UnifiedCache, which is soley responsible for eviction and deletion. + * is with the UnifiedCache, which is solely responsible for eviction and deletion. */ void deleteIfZeroRefCount() const; diff --git a/deps/icu-small/source/common/static_unicode_sets.cpp b/deps/icu-small/source/common/static_unicode_sets.cpp index 9e731f5781e215..5d598a0e33b6d4 100644 --- a/deps/icu-small/source/common/static_unicode_sets.cpp +++ b/deps/icu-small/source/common/static_unicode_sets.cpp @@ -27,6 +27,7 @@ UnicodeSet* gUnicodeSets[COUNT] = {}; // Save the empty instance in static memory to have well-defined behavior if a // regular UnicodeSet cannot be allocated. +alignas(UnicodeSet) char gEmptyUnicodeSet[sizeof(UnicodeSet)]; // Whether the gEmptyUnicodeSet is initialized and ready to use. diff --git a/deps/icu-small/source/common/stringtriebuilder.cpp b/deps/icu-small/source/common/stringtriebuilder.cpp index cf5b7b73ae2c1f..6f9cc2e5c22b55 100644 --- a/deps/icu-small/source/common/stringtriebuilder.cpp +++ b/deps/icu-small/source/common/stringtriebuilder.cpp @@ -373,7 +373,7 @@ StringTrieBuilder::registerFinalValue(int32_t value, UErrorCode &errorCode) { return newNode; } -UBool +int32_t StringTrieBuilder::hashNode(const void *node) { return ((const Node *)node)->hashCode(); } diff --git a/deps/icu-small/source/common/ubidi.cpp b/deps/icu-small/source/common/ubidi.cpp index 531ed64cff6ec8..4b65d491859bfa 100644 --- a/deps/icu-small/source/common/ubidi.cpp +++ b/deps/icu-small/source/common/ubidi.cpp @@ -624,7 +624,7 @@ getDirProps(UBiDi *pBiDi) { pBiDi->paras[pBiDi->paraCount-1].level=1; } if(isDefaultLevel) { - pBiDi->paraLevel=pBiDi->paras[0].level; + pBiDi->paraLevel=static_cast(pBiDi->paras[0].level); } /* The following is needed to resolve the text direction for default level paragraphs containing no strong character */ @@ -825,28 +825,28 @@ bracketProcessClosing(BracketData *bd, int32_t openIdx, int32_t position) { N0c1. */ if((direction==0 && pOpening->flags&FOUND_L) || - (direction==1 && pOpening->flags&FOUND_R)) { /* N0b */ - newProp=direction; + (direction==1 && pOpening->flags&FOUND_R)) { /* N0b */ + newProp=static_cast(direction); } - else if(pOpening->flags&(FOUND_L|FOUND_R)) { /* N0c */ + else if(pOpening->flags&(FOUND_L|FOUND_R)) { /* N0c */ /* it is stable if there is no containing pair or in conditions too complicated and not worth checking */ stable=(openIdx==pLastIsoRun->start); if(direction!=pOpening->contextDir) - newProp=pOpening->contextDir; /* N0c1 */ + newProp= static_cast(pOpening->contextDir); /* N0c1 */ else - newProp=direction; /* N0c2 */ + newProp= static_cast(direction); /* N0c2 */ } else { /* forget this and any brackets nested within this pair */ - pLastIsoRun->limit=openIdx; - return ON; /* N0d */ + pLastIsoRun->limit= static_cast(openIdx); + return ON; /* N0d */ } bd->pBiDi->dirProps[pOpening->position]=newProp; bd->pBiDi->dirProps[position]=newProp; /* Update nested N0c pairs that may be affected */ fixN0c(bd, openIdx, pOpening->position, newProp); if(stable) { - pLastIsoRun->limit=openIdx; /* forget any brackets nested within this pair */ + pLastIsoRun->limit= static_cast(openIdx); /* forget any brackets nested within this pair */ /* remove lower located synonyms if any */ while(pLastIsoRun->limit>pLastIsoRun->start && bd->openings[pLastIsoRun->limit-1].position==pOpening->position) @@ -918,7 +918,7 @@ bracketProcessChar(BracketData *bd, int32_t position) { bracket or it is a case of N0d */ /* Now see if it is an opening bracket */ if(c) - match=u_getBidiPairedBracket(c); /* get the matching char */ + match= static_cast(u_getBidiPairedBracket(c)); /* get the matching char */ else match=0; if(match!=c && /* has a matching char */ @@ -948,7 +948,7 @@ bracketProcessChar(BracketData *bd, int32_t position) { pLastIsoRun->contextPos=position; } else if(dirProp<=R || dirProp==AL) { - newProp=DIR_FROM_STRONG(dirProp); + newProp= static_cast(DIR_FROM_STRONG(dirProp)); pLastIsoRun->lastBase=dirProp; pLastIsoRun->lastStrong=dirProp; pLastIsoRun->contextDir=(UBiDiDirection)newProp; @@ -1101,7 +1101,7 @@ resolveExplicitLevels(UBiDi *pBiDi, UErrorCode *pErrorCode) { else start=pBiDi->paras[paraIndex-1].limit; limit=pBiDi->paras[paraIndex].limit; - level=pBiDi->paras[paraIndex].level; + level= static_cast(pBiDi->paras[paraIndex].level); for(i=start; iparas[paraIndex-1].limit; limit=pBiDi->paras[paraIndex].limit; - level=pBiDi->paras[paraIndex].level; + level= static_cast(pBiDi->paras[paraIndex].level); for(i=start; iparaCount; i++) { last=(pBiDi->paras[i].limit)-1; - level=pBiDi->paras[i].level; + level= static_cast(pBiDi->paras[i].level); if(level==0) continue; /* LTR paragraph */ start= i==0 ? 0 : pBiDi->paras[i-1].limit; diff --git a/deps/icu-small/source/common/ubiditransform.cpp b/deps/icu-small/source/common/ubiditransform.cpp index 80261d391e753b..394df6092d21b1 100644 --- a/deps/icu-small/source/common/ubiditransform.cpp +++ b/deps/icu-small/source/common/ubiditransform.cpp @@ -146,7 +146,7 @@ static UBool action_reorder(UBiDiTransform *pTransform, UErrorCode *pErrorCode) { ubidi_writeReordered(pTransform->pBidi, pTransform->dest, pTransform->destSize, - pTransform->reorderingOptions, pErrorCode); + static_cast(pTransform->reorderingOptions), pErrorCode); *pTransform->pDestLength = pTransform->srcLength; pTransform->reorderingOptions = UBIDI_REORDER_DEFAULT; @@ -393,9 +393,9 @@ resolveBaseDirection(const UChar *text, uint32_t length, switch (*pInLevel) { case UBIDI_DEFAULT_LTR: case UBIDI_DEFAULT_RTL: { - UBiDiLevel level = ubidi_getBaseDirection(text, length); - *pInLevel = level != UBIDI_NEUTRAL ? level - : *pInLevel == UBIDI_DEFAULT_RTL ? RTL : LTR; + UBiDiLevel level = static_cast(ubidi_getBaseDirection(text, length)); + *pInLevel = static_cast(level != UBIDI_NEUTRAL) ? level + : *pInLevel == UBIDI_DEFAULT_RTL ? static_cast(RTL) : static_cast(LTR); break; } default: diff --git a/deps/icu-small/source/common/ucase.cpp b/deps/icu-small/source/common/ucase.cpp index 43c57f896e9348..50c8d20c1fce73 100644 --- a/deps/icu-small/source/common/ucase.cpp +++ b/deps/icu-small/source/common/ucase.cpp @@ -270,6 +270,7 @@ ucase_addCaseClosure(UChar32 c, const USetAdder *sa) { } } if(HAS_SLOT(excWord, UCASE_EXC_DELTA)) { + pe=pe0; int32_t delta; GET_SLOT_VALUE(excWord, UCASE_EXC_DELTA, pe, delta); sa->add(sa->set, (excWord&UCASE_EXC_DELTA_IS_NEGATIVE)==0 ? c+delta : c-delta); @@ -1167,7 +1168,7 @@ ucase_toFullLower(UChar32 c, if(HAS_SLOT(excWord, UCASE_EXC_DELTA) && UCASE_IS_UPPER_OR_TITLE(props)) { int32_t delta; - GET_SLOT_VALUE(excWord, UCASE_EXC_DELTA, pe, delta); + GET_SLOT_VALUE(excWord, UCASE_EXC_DELTA, pe2, delta); return (excWord&UCASE_EXC_DELTA_IS_NEGATIVE)==0 ? c+delta : c-delta; } if(HAS_SLOT(excWord, UCASE_EXC_LOWER)) { @@ -1261,7 +1262,7 @@ toUpperOrTitle(UChar32 c, if(HAS_SLOT(excWord, UCASE_EXC_DELTA) && UCASE_GET_TYPE(props)==UCASE_LOWER) { int32_t delta; - GET_SLOT_VALUE(excWord, UCASE_EXC_DELTA, pe, delta); + GET_SLOT_VALUE(excWord, UCASE_EXC_DELTA, pe2, delta); return (excWord&UCASE_EXC_DELTA_IS_NEGATIVE)==0 ? c+delta : c-delta; } if(!upperNotTitle && HAS_SLOT(excWord, UCASE_EXC_TITLE)) { @@ -1469,7 +1470,7 @@ ucase_toFullFolding(UChar32 c, } if(HAS_SLOT(excWord, UCASE_EXC_DELTA) && UCASE_IS_UPPER_OR_TITLE(props)) { int32_t delta; - GET_SLOT_VALUE(excWord, UCASE_EXC_DELTA, pe, delta); + GET_SLOT_VALUE(excWord, UCASE_EXC_DELTA, pe2, delta); return (excWord&UCASE_EXC_DELTA_IS_NEGATIVE)==0 ? c+delta : c-delta; } if(HAS_SLOT(excWord, UCASE_EXC_FOLD)) { diff --git a/deps/icu-small/source/common/ucln_cmn.h b/deps/icu-small/source/common/ucln_cmn.h index 9b6c2058135c52..0ca911b47d9875 100644 --- a/deps/icu-small/source/common/ucln_cmn.h +++ b/deps/icu-small/source/common/ucln_cmn.h @@ -45,6 +45,7 @@ typedef enum ECleanupCommonType { UCLN_COMMON_CURRENCY, UCLN_COMMON_LOADED_NORMALIZER2, UCLN_COMMON_NORMALIZER2, + UCLN_COMMON_CHARACTERPROPERTIES, UCLN_COMMON_USET, UCLN_COMMON_UNAMES, UCLN_COMMON_UPROPS, @@ -52,7 +53,6 @@ typedef enum ECleanupCommonType { UCLN_COMMON_UCNV_IO, UCLN_COMMON_UDATA, UCLN_COMMON_PUTIL, - UCLN_COMMON_LIST_FORMATTER, UCLN_COMMON_UINIT, /* diff --git a/deps/icu-small/source/common/ucnv.cpp b/deps/icu-small/source/common/ucnv.cpp index 39ea5dfa6636f5..abf302eaddb7a8 100644 --- a/deps/icu-small/source/common/ucnv.cpp +++ b/deps/icu-small/source/common/ucnv.cpp @@ -1743,13 +1743,9 @@ ucnv_fromUChars(UConverter *cnv, } if(srcLength>0) { srcLimit=src+srcLength; + destCapacity=pinCapacity(dest, destCapacity); destLimit=dest+destCapacity; - /* pin the destination limit to U_MAX_PTR; NULL check is for OS/400 */ - if(destLimit0) { srcLimit=src+srcLength; + destCapacity=pinCapacity(dest, destCapacity); destLimit=dest+destCapacity; - /* pin the destination limit to U_MAX_PTR; NULL check is for OS/400 */ - if(destLimit(0x10000 | (mySourceChar << 8) | trailByte); } } else { args->converter->toUBytes[0] = (uint8_t)mySourceChar; @@ -3304,7 +3304,7 @@ UConverter_toUnicode_ISO_2022_CN_OFFSETS_LOGIC(UConverterToUnicodeArgs *args, myData->isEmptySegment = FALSE; /* we are handling it, reset to avoid future spurious errors */ *err = U_ILLEGAL_ESCAPE_SEQUENCE; args->converter->toUCallbackReason = UCNV_IRREGULAR; - args->converter->toUBytes[0] = mySourceChar; + args->converter->toUBytes[0] = static_cast(mySourceChar); args->converter->toULength = 1; args->target = myTarget; args->source = mySource; diff --git a/deps/icu-small/source/common/ucnv_ct.cpp b/deps/icu-small/source/common/ucnv_ct.cpp index 51e31aa4116bd3..b40e1b2c970e51 100644 --- a/deps/icu-small/source/common/ucnv_ct.cpp +++ b/deps/icu-small/source/common/ucnv_ct.cpp @@ -180,7 +180,7 @@ _CompoundTextgetName(const UConverter* cnv); static int32_t findNextEsc(const char *source, const char *sourceLimit) { - int32_t length = sourceLimit - source; + int32_t length = static_cast(sourceLimit - source); int32_t i; for (i = 1; i < length; i++) { if (*(source + i) == 0x1B) { diff --git a/deps/icu-small/source/common/ucnv_u16.cpp b/deps/icu-small/source/common/ucnv_u16.cpp index a289fd4acfac1a..6c1b87d3c939c6 100644 --- a/deps/icu-small/source/common/ucnv_u16.cpp +++ b/deps/icu-small/source/common/ucnv_u16.cpp @@ -71,7 +71,7 @@ _UTF16BEFromUnicodeWithOffsets(UConverterFromUnicodeArgs *pArgs, /* write the BOM if necessary */ if(cnv->fromUnicodeStatus==UCNV_NEED_TO_WRITE_BOM) { - static const char bom[]={ (char)0xfe, (char)0xff }; + static const char bom[]={ (char)0xfeu, (char)0xffu }; ucnv_fromUWriteBytes(cnv, bom, 2, &pArgs->target, pArgs->targetLimit, @@ -672,7 +672,7 @@ _UTF16LEFromUnicodeWithOffsets(UConverterFromUnicodeArgs *pArgs, /* write the BOM if necessary */ if(cnv->fromUnicodeStatus==UCNV_NEED_TO_WRITE_BOM) { - static const char bom[]={ (char)0xff, (char)0xfe }; + static const char bom[]={ (char)0xffu, (char)0xfeu }; ucnv_fromUWriteBytes(cnv, bom, 2, &pArgs->target, pArgs->targetLimit, diff --git a/deps/icu-small/source/common/ucnv_u32.cpp b/deps/icu-small/source/common/ucnv_u32.cpp index ca8c6788d3dd97..13444a3afd97f1 100644 --- a/deps/icu-small/source/common/ucnv_u32.cpp +++ b/deps/icu-small/source/common/ucnv_u32.cpp @@ -228,7 +228,7 @@ T_UConverter_fromUnicode_UTF32_BE(UConverterFromUnicodeArgs * args, /* write the BOM if necessary */ if(args->converter->fromUnicodeStatus==UCNV_NEED_TO_WRITE_BOM) { - static const char bom[]={ 0, 0, (char)0xfe, (char)0xff }; + static const char bom[]={ 0, 0, (char)0xfeu, (char)0xffu }; ucnv_fromUWriteBytes(args->converter, bom, 4, &args->target, args->targetLimit, @@ -331,7 +331,7 @@ T_UConverter_fromUnicode_UTF32_BE_OFFSET_LOGIC(UConverterFromUnicodeArgs * args, /* write the BOM if necessary */ if(args->converter->fromUnicodeStatus==UCNV_NEED_TO_WRITE_BOM) { - static const char bom[]={ 0, 0, (char)0xfe, (char)0xff }; + static const char bom[]={ 0, 0, (char)0xfeu, (char)0xffu }; ucnv_fromUWriteBytes(args->converter, bom, 4, &args->target, args->targetLimit, @@ -706,7 +706,7 @@ T_UConverter_fromUnicode_UTF32_LE(UConverterFromUnicodeArgs * args, /* write the BOM if necessary */ if(args->converter->fromUnicodeStatus==UCNV_NEED_TO_WRITE_BOM) { - static const char bom[]={ (char)0xff, (char)0xfe, 0, 0 }; + static const char bom[]={ (char)0xffu, (char)0xfeu, 0, 0 }; ucnv_fromUWriteBytes(args->converter, bom, 4, &args->target, args->targetLimit, @@ -817,7 +817,7 @@ T_UConverter_fromUnicode_UTF32_LE_OFFSET_LOGIC(UConverterFromUnicodeArgs * args, /* write the BOM if necessary */ if(args->converter->fromUnicodeStatus==UCNV_NEED_TO_WRITE_BOM) { - static const char bom[]={ (char)0xff, (char)0xfe, 0, 0 }; + static const char bom[]={ (char)0xffu, (char)0xfeu, 0, 0 }; ucnv_fromUWriteBytes(args->converter, bom, 4, &args->target, args->targetLimit, @@ -1043,7 +1043,7 @@ _UTF32Open(UConverter *cnv, _UTF32Reset(cnv, UCNV_RESET_BOTH); } -static const char utf32BOM[8]={ 0, 0, (char)0xfe, (char)0xff, (char)0xff, (char)0xfe, 0, 0 }; +static const char utf32BOM[8]={ 0, 0, (char)0xfeu, (char)0xffu, (char)0xffu, (char)0xfeu, 0, 0 }; static void U_CALLCONV _UTF32ToUnicodeWithOffsets(UConverterToUnicodeArgs *pArgs, @@ -1071,7 +1071,7 @@ _UTF32ToUnicodeWithOffsets(UConverterToUnicodeArgs *pArgs, b=*source; if(b==0) { state=1; /* could be 00 00 FE FF */ - } else if(b==(char)0xff) { + } else if(b==(char)0xffu) { state=5; /* could be FF FE 00 00 */ } else { state=8; /* default to UTF-32BE */ diff --git a/deps/icu-small/source/common/ucnv_u8.cpp b/deps/icu-small/source/common/ucnv_u8.cpp index 5a07244b02bf9c..878d67304c7d89 100644 --- a/deps/icu-small/source/common/ucnv_u8.cpp +++ b/deps/icu-small/source/common/ucnv_u8.cpp @@ -108,7 +108,7 @@ static void U_CALLCONV ucnv_toUnicode_UTF8 (UConverterToUnicodeArgs * args, if (mySource < sourceLimit) { toUBytes[i] = (char) (ch2 = *mySource); - if (!icu::UTF8::isValidTrail(ch, ch2, i, inBytes) && + if (!icu::UTF8::isValidTrail(ch, static_cast(ch2), i, inBytes) && !(isCESU8 && i == 1 && ch == 0xed && U8_IS_TRAIL(ch2))) { break; /* i < inBytes */ @@ -225,7 +225,7 @@ static void U_CALLCONV ucnv_toUnicode_UTF8_OFFSETS_LOGIC (UConverterToUnicodeAr if (mySource < sourceLimit) { toUBytes[i] = (char) (ch2 = *mySource); - if (!icu::UTF8::isValidTrail(ch, ch2, i, inBytes) && + if (!icu::UTF8::isValidTrail(ch, static_cast(ch2), i, inBytes) && !(isCESU8 && i == 1 && ch == 0xed && U8_IS_TRAIL(ch2))) { break; /* i < inBytes */ diff --git a/deps/icu-small/source/common/ucnvhz.cpp b/deps/icu-small/source/common/ucnvhz.cpp index 5a24575f05c28a..31595374696d8c 100644 --- a/deps/icu-small/source/common/ucnvhz.cpp +++ b/deps/icu-small/source/common/ucnvhz.cpp @@ -199,7 +199,7 @@ UConverter_toUnicode_HZ_OFFSETS_LOGIC(UConverterToUnicodeArgs *args, *err = U_ILLEGAL_ESCAPE_SEQUENCE; args->converter->toUCallbackReason = UCNV_IRREGULAR; args->converter->toUBytes[0] = UCNV_TILDE; - args->converter->toUBytes[1] = mySourceChar; + args->converter->toUBytes[1] = static_cast(mySourceChar); args->converter->toULength = 2; args->target = myTarget; args->source = mySource; @@ -229,7 +229,7 @@ UConverter_toUnicode_HZ_OFFSETS_LOGIC(UConverterToUnicodeArgs *args, --mySource; } else { /* Include the current byte in the illegal sequence. */ - args->converter->toUBytes[1] = mySourceChar; + args->converter->toUBytes[1] = static_cast(mySourceChar); args->converter->toULength = 2; } args->target = myTarget; diff --git a/deps/icu-small/source/common/ucnvmbcs.cpp b/deps/icu-small/source/common/ucnvmbcs.cpp index 9052394b4ff8d1..e1248a7bd36035 100644 --- a/deps/icu-small/source/common/ucnvmbcs.cpp +++ b/deps/icu-small/source/common/ucnvmbcs.cpp @@ -4164,8 +4164,8 @@ ucnv_MBCSFromUnicodeWithOffsets(UConverterFromUnicodeArgs *pArgs, nextSourceIndex=0; /* Get the SI/SO character for the converter */ - siLength = getSISOBytes(SI, cnv->options, siBytes); - soLength = getSISOBytes(SO, cnv->options, soBytes); + siLength = static_cast(getSISOBytes(SI, cnv->options, siBytes)); + soLength = static_cast(getSISOBytes(SO, cnv->options, soBytes)); /* conversion loop */ /* diff --git a/deps/icu-small/source/common/ucnvsel.cpp b/deps/icu-small/source/common/ucnvsel.cpp index 90c7a18b93a514..6ccee1ae61fd70 100644 --- a/deps/icu-small/source/common/ucnvsel.cpp +++ b/deps/icu-small/source/common/ucnvsel.cpp @@ -41,6 +41,7 @@ #include "propsvec.h" #include "uassert.h" #include "ucmndata.h" +#include "udataswp.h" #include "uenumimp.h" #include "cmemory.h" #include "cstring.h" @@ -72,7 +73,7 @@ static void generateSelectorData(UConverterSelector* result, // set errorValue to all-ones for (int32_t col = 0; col < columns; col++) { upvec_setValue(upvec, UPVEC_ERROR_VALUE_CP, UPVEC_ERROR_VALUE_CP, - col, ~0, ~0, status); + col, static_cast(~0), static_cast(~0), status); } for (int32_t i = 0; i < result->encodingsCount; ++i) { @@ -109,7 +110,7 @@ static void generateSelectorData(UConverterSelector* result, // this will be reached for the converters that fill the set with // strings. Those should be ignored by our system } else { - upvec_setValue(upvec, start_char, end_char, column, ~0, mask, + upvec_setValue(upvec, start_char, end_char, column, static_cast(~0), mask, status); } } @@ -130,7 +131,7 @@ static void generateSelectorData(UConverterSelector* result, uset_getItem(excludedCodePoints, j, &start_char, &end_char, NULL, 0, status); for (int32_t col = 0; col < columns; col++) { - upvec_setValue(upvec, start_char, end_char, col, ~0, ~0, + upvec_setValue(upvec, start_char, end_char, col, static_cast(~0), static_cast(~0), status); } } @@ -684,7 +685,7 @@ static int16_t countOnes(uint32_t* mask, int32_t len) { ent &= ent - 1; // clear the least significant bit set } } - return totalOnes; + return static_cast(totalOnes); } diff --git a/deps/icu-small/source/common/ucol_swp.cpp b/deps/icu-small/source/common/ucol_swp.cpp index 3055abaca3ba09..97b5c4aff50c88 100644 --- a/deps/icu-small/source/common/ucol_swp.cpp +++ b/deps/icu-small/source/common/ucol_swp.cpp @@ -28,81 +28,6 @@ /* swapping ----------------------------------------------------------------- */ -/* - * This performs data swapping for a folded trie (see utrie.c for details). - */ - -U_CAPI int32_t U_EXPORT2 -utrie_swap(const UDataSwapper *ds, - const void *inData, int32_t length, void *outData, - UErrorCode *pErrorCode) { - const UTrieHeader *inTrie; - UTrieHeader trie; - int32_t size; - UBool dataIs32; - - if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) { - return 0; - } - if(ds==NULL || inData==NULL || (length>=0 && outData==NULL)) { - *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR; - return 0; - } - - /* setup and swapping */ - if(length>=0 && (uint32_t)lengthreadUInt32(inTrie->signature); - trie.options=ds->readUInt32(inTrie->options); - trie.indexLength=udata_readInt32(ds, inTrie->indexLength); - trie.dataLength=udata_readInt32(ds, inTrie->dataLength); - - if( trie.signature!=0x54726965 || - (trie.options&UTRIE_OPTIONS_SHIFT_MASK)!=UTRIE_SHIFT || - ((trie.options>>UTRIE_OPTIONS_INDEX_SHIFT)&UTRIE_OPTIONS_SHIFT_MASK)!=UTRIE_INDEX_SHIFT || - trie.indexLength=0) { - UTrieHeader *outTrie; - - if(lengthswapArray32(ds, inTrie, sizeof(UTrieHeader), outTrie, pErrorCode); - - /* swap the index and the data */ - if(dataIs32) { - ds->swapArray16(ds, inTrie+1, trie.indexLength*2, outTrie+1, pErrorCode); - ds->swapArray32(ds, (const uint16_t *)(inTrie+1)+trie.indexLength, trie.dataLength*4, - (uint16_t *)(outTrie+1)+trie.indexLength, pErrorCode); - } else { - ds->swapArray16(ds, inTrie+1, (trie.indexLength+trie.dataLength)*2, outTrie+1, pErrorCode); - } - } - - return size; -} - #if !UCONFIG_NO_COLLATION U_CAPI UBool U_EXPORT2 diff --git a/deps/icu-small/source/common/ucptrie.cpp b/deps/icu-small/source/common/ucptrie.cpp new file mode 100644 index 00000000000000..13496ad56c5e58 --- /dev/null +++ b/deps/icu-small/source/common/ucptrie.cpp @@ -0,0 +1,590 @@ +// © 2017 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html + +// ucptrie.cpp (modified from utrie2.cpp) +// created: 2017dec29 Markus W. Scherer + +// #define UCPTRIE_DEBUG +#ifdef UCPTRIE_DEBUG +# include +#endif + +#include "unicode/utypes.h" +#include "unicode/ucptrie.h" +#include "unicode/utf.h" +#include "unicode/utf8.h" +#include "unicode/utf16.h" +#include "cmemory.h" +#include "uassert.h" +#include "ucptrie_impl.h" + +U_CAPI UCPTrie * U_EXPORT2 +ucptrie_openFromBinary(UCPTrieType type, UCPTrieValueWidth valueWidth, + const void *data, int32_t length, int32_t *pActualLength, + UErrorCode *pErrorCode) { + if (U_FAILURE(*pErrorCode)) { + return nullptr; + } + + if (length <= 0 || (U_POINTER_MASK_LSB(data, 3) != 0) || + type < UCPTRIE_TYPE_ANY || UCPTRIE_TYPE_SMALL < type || + valueWidth < UCPTRIE_VALUE_BITS_ANY || UCPTRIE_VALUE_BITS_8 < valueWidth) { + *pErrorCode = U_ILLEGAL_ARGUMENT_ERROR; + return nullptr; + } + + // Enough data for a trie header? + if (length < (int32_t)sizeof(UCPTrieHeader)) { + *pErrorCode = U_INVALID_FORMAT_ERROR; + return nullptr; + } + + // Check the signature. + const UCPTrieHeader *header = (const UCPTrieHeader *)data; + if (header->signature != UCPTRIE_SIG) { + *pErrorCode = U_INVALID_FORMAT_ERROR; + return nullptr; + } + + int32_t options = header->options; + int32_t typeInt = (options >> 6) & 3; + int32_t valueWidthInt = options & UCPTRIE_OPTIONS_VALUE_BITS_MASK; + if (typeInt > UCPTRIE_TYPE_SMALL || valueWidthInt > UCPTRIE_VALUE_BITS_8 || + (options & UCPTRIE_OPTIONS_RESERVED_MASK) != 0) { + *pErrorCode = U_INVALID_FORMAT_ERROR; + return nullptr; + } + UCPTrieType actualType = (UCPTrieType)typeInt; + UCPTrieValueWidth actualValueWidth = (UCPTrieValueWidth)valueWidthInt; + if (type < 0) { + type = actualType; + } + if (valueWidth < 0) { + valueWidth = actualValueWidth; + } + if (type != actualType || valueWidth != actualValueWidth) { + *pErrorCode = U_INVALID_FORMAT_ERROR; + return nullptr; + } + + // Get the length values and offsets. + UCPTrie tempTrie; + uprv_memset(&tempTrie, 0, sizeof(tempTrie)); + tempTrie.indexLength = header->indexLength; + tempTrie.dataLength = + ((options & UCPTRIE_OPTIONS_DATA_LENGTH_MASK) << 4) | header->dataLength; + tempTrie.index3NullOffset = header->index3NullOffset; + tempTrie.dataNullOffset = + ((options & UCPTRIE_OPTIONS_DATA_NULL_OFFSET_MASK) << 8) | header->dataNullOffset; + + tempTrie.highStart = header->shiftedHighStart << UCPTRIE_SHIFT_2; + tempTrie.shifted12HighStart = (tempTrie.highStart + 0xfff) >> 12; + tempTrie.type = type; + tempTrie.valueWidth = valueWidth; + + // Calculate the actual length. + int32_t actualLength = (int32_t)sizeof(UCPTrieHeader) + tempTrie.indexLength * 2; + if (valueWidth == UCPTRIE_VALUE_BITS_16) { + actualLength += tempTrie.dataLength * 2; + } else if (valueWidth == UCPTRIE_VALUE_BITS_32) { + actualLength += tempTrie.dataLength * 4; + } else { + actualLength += tempTrie.dataLength; + } + if (length < actualLength) { + *pErrorCode = U_INVALID_FORMAT_ERROR; // Not enough bytes. + return nullptr; + } + + // Allocate the trie. + UCPTrie *trie = (UCPTrie *)uprv_malloc(sizeof(UCPTrie)); + if (trie == nullptr) { + *pErrorCode = U_MEMORY_ALLOCATION_ERROR; + return nullptr; + } + uprv_memcpy(trie, &tempTrie, sizeof(tempTrie)); +#ifdef UCPTRIE_DEBUG + trie->name = "fromSerialized"; +#endif + + // Set the pointers to its index and data arrays. + const uint16_t *p16 = (const uint16_t *)(header + 1); + trie->index = p16; + p16 += trie->indexLength; + + // Get the data. + int32_t nullValueOffset = trie->dataNullOffset; + if (nullValueOffset >= trie->dataLength) { + nullValueOffset = trie->dataLength - UCPTRIE_HIGH_VALUE_NEG_DATA_OFFSET; + } + switch (valueWidth) { + case UCPTRIE_VALUE_BITS_16: + trie->data.ptr16 = p16; + trie->nullValue = trie->data.ptr16[nullValueOffset]; + break; + case UCPTRIE_VALUE_BITS_32: + trie->data.ptr32 = (const uint32_t *)p16; + trie->nullValue = trie->data.ptr32[nullValueOffset]; + break; + case UCPTRIE_VALUE_BITS_8: + trie->data.ptr8 = (const uint8_t *)p16; + trie->nullValue = trie->data.ptr8[nullValueOffset]; + break; + default: + // Unreachable because valueWidth was checked above. + *pErrorCode = U_INVALID_FORMAT_ERROR; + return nullptr; + } + + if (pActualLength != nullptr) { + *pActualLength = actualLength; + } + return trie; +} + +U_CAPI void U_EXPORT2 +ucptrie_close(UCPTrie *trie) { + uprv_free(trie); +} + +U_CAPI UCPTrieType U_EXPORT2 +ucptrie_getType(const UCPTrie *trie) { + return (UCPTrieType)trie->type; +} + +U_CAPI UCPTrieValueWidth U_EXPORT2 +ucptrie_getValueWidth(const UCPTrie *trie) { + return (UCPTrieValueWidth)trie->valueWidth; +} + +U_CAPI int32_t U_EXPORT2 +ucptrie_internalSmallIndex(const UCPTrie *trie, UChar32 c) { + int32_t i1 = c >> UCPTRIE_SHIFT_1; + if (trie->type == UCPTRIE_TYPE_FAST) { + U_ASSERT(0xffff < c && c < trie->highStart); + i1 += UCPTRIE_BMP_INDEX_LENGTH - UCPTRIE_OMITTED_BMP_INDEX_1_LENGTH; + } else { + U_ASSERT((uint32_t)c < (uint32_t)trie->highStart && trie->highStart > UCPTRIE_SMALL_LIMIT); + i1 += UCPTRIE_SMALL_INDEX_LENGTH; + } + int32_t i3Block = trie->index[ + (int32_t)trie->index[i1] + ((c >> UCPTRIE_SHIFT_2) & UCPTRIE_INDEX_2_MASK)]; + int32_t i3 = (c >> UCPTRIE_SHIFT_3) & UCPTRIE_INDEX_3_MASK; + int32_t dataBlock; + if ((i3Block & 0x8000) == 0) { + // 16-bit indexes + dataBlock = trie->index[i3Block + i3]; + } else { + // 18-bit indexes stored in groups of 9 entries per 8 indexes. + i3Block = (i3Block & 0x7fff) + (i3 & ~7) + (i3 >> 3); + i3 &= 7; + dataBlock = ((int32_t)trie->index[i3Block++] << (2 + (2 * i3))) & 0x30000; + dataBlock |= trie->index[i3Block + i3]; + } + return dataBlock + (c & UCPTRIE_SMALL_DATA_MASK); +} + +U_CAPI int32_t U_EXPORT2 +ucptrie_internalSmallU8Index(const UCPTrie *trie, int32_t lt1, uint8_t t2, uint8_t t3) { + UChar32 c = (lt1 << 12) | (t2 << 6) | t3; + if (c >= trie->highStart) { + // Possible because the UTF-8 macro compares with shifted12HighStart which may be higher. + return trie->dataLength - UCPTRIE_HIGH_VALUE_NEG_DATA_OFFSET; + } + return ucptrie_internalSmallIndex(trie, c); +} + +U_CAPI int32_t U_EXPORT2 +ucptrie_internalU8PrevIndex(const UCPTrie *trie, UChar32 c, + const uint8_t *start, const uint8_t *src) { + int32_t i, length; + // Support 64-bit pointers by avoiding cast of arbitrary difference. + if ((src - start) <= 7) { + i = length = (int32_t)(src - start); + } else { + i = length = 7; + start = src - 7; + } + c = utf8_prevCharSafeBody(start, 0, &i, c, -1); + i = length - i; // Number of bytes read backward from src. + int32_t idx = _UCPTRIE_CP_INDEX(trie, 0xffff, c); + return (idx << 3) | i; +} + +namespace { + +inline uint32_t getValue(UCPTrieData data, UCPTrieValueWidth valueWidth, int32_t dataIndex) { + switch (valueWidth) { + case UCPTRIE_VALUE_BITS_16: + return data.ptr16[dataIndex]; + case UCPTRIE_VALUE_BITS_32: + return data.ptr32[dataIndex]; + case UCPTRIE_VALUE_BITS_8: + return data.ptr8[dataIndex]; + default: + // Unreachable if the trie is properly initialized. + return 0xffffffff; + } +} + +} // namespace + +U_CAPI uint32_t U_EXPORT2 +ucptrie_get(const UCPTrie *trie, UChar32 c) { + int32_t dataIndex; + if ((uint32_t)c <= 0x7f) { + // linear ASCII + dataIndex = c; + } else { + UChar32 fastMax = trie->type == UCPTRIE_TYPE_FAST ? 0xffff : UCPTRIE_SMALL_MAX; + dataIndex = _UCPTRIE_CP_INDEX(trie, fastMax, c); + } + return getValue(trie->data, (UCPTrieValueWidth)trie->valueWidth, dataIndex); +} + +namespace { + +constexpr int32_t MAX_UNICODE = 0x10ffff; + +inline uint32_t maybeFilterValue(uint32_t value, uint32_t trieNullValue, uint32_t nullValue, + UCPMapValueFilter *filter, const void *context) { + if (value == trieNullValue) { + value = nullValue; + } else if (filter != nullptr) { + value = filter(context, value); + } + return value; +} + +UChar32 getRange(const void *t, UChar32 start, + UCPMapValueFilter *filter, const void *context, uint32_t *pValue) { + if ((uint32_t)start > MAX_UNICODE) { + return U_SENTINEL; + } + const UCPTrie *trie = reinterpret_cast(t); + UCPTrieValueWidth valueWidth = (UCPTrieValueWidth)trie->valueWidth; + if (start >= trie->highStart) { + if (pValue != nullptr) { + int32_t di = trie->dataLength - UCPTRIE_HIGH_VALUE_NEG_DATA_OFFSET; + uint32_t value = getValue(trie->data, valueWidth, di); + if (filter != nullptr) { value = filter(context, value); } + *pValue = value; + } + return MAX_UNICODE; + } + + uint32_t nullValue = trie->nullValue; + if (filter != nullptr) { nullValue = filter(context, nullValue); } + const uint16_t *index = trie->index; + + int32_t prevI3Block = -1; + int32_t prevBlock = -1; + UChar32 c = start; + uint32_t value; + bool haveValue = false; + do { + int32_t i3Block; + int32_t i3; + int32_t i3BlockLength; + int32_t dataBlockLength; + if (c <= 0xffff && (trie->type == UCPTRIE_TYPE_FAST || c <= UCPTRIE_SMALL_MAX)) { + i3Block = 0; + i3 = c >> UCPTRIE_FAST_SHIFT; + i3BlockLength = trie->type == UCPTRIE_TYPE_FAST ? + UCPTRIE_BMP_INDEX_LENGTH : UCPTRIE_SMALL_INDEX_LENGTH; + dataBlockLength = UCPTRIE_FAST_DATA_BLOCK_LENGTH; + } else { + // Use the multi-stage index. + int32_t i1 = c >> UCPTRIE_SHIFT_1; + if (trie->type == UCPTRIE_TYPE_FAST) { + U_ASSERT(0xffff < c && c < trie->highStart); + i1 += UCPTRIE_BMP_INDEX_LENGTH - UCPTRIE_OMITTED_BMP_INDEX_1_LENGTH; + } else { + U_ASSERT(c < trie->highStart && trie->highStart > UCPTRIE_SMALL_LIMIT); + i1 += UCPTRIE_SMALL_INDEX_LENGTH; + } + i3Block = trie->index[ + (int32_t)trie->index[i1] + ((c >> UCPTRIE_SHIFT_2) & UCPTRIE_INDEX_2_MASK)]; + if (i3Block == prevI3Block && (c - start) >= UCPTRIE_CP_PER_INDEX_2_ENTRY) { + // The index-3 block is the same as the previous one, and filled with value. + U_ASSERT((c & (UCPTRIE_CP_PER_INDEX_2_ENTRY - 1)) == 0); + c += UCPTRIE_CP_PER_INDEX_2_ENTRY; + continue; + } + prevI3Block = i3Block; + if (i3Block == trie->index3NullOffset) { + // This is the index-3 null block. + if (haveValue) { + if (nullValue != value) { + return c - 1; + } + } else { + value = nullValue; + if (pValue != nullptr) { *pValue = nullValue; } + haveValue = true; + } + prevBlock = trie->dataNullOffset; + c = (c + UCPTRIE_CP_PER_INDEX_2_ENTRY) & ~(UCPTRIE_CP_PER_INDEX_2_ENTRY - 1); + continue; + } + i3 = (c >> UCPTRIE_SHIFT_3) & UCPTRIE_INDEX_3_MASK; + i3BlockLength = UCPTRIE_INDEX_3_BLOCK_LENGTH; + dataBlockLength = UCPTRIE_SMALL_DATA_BLOCK_LENGTH; + } + // Enumerate data blocks for one index-3 block. + do { + int32_t block; + if ((i3Block & 0x8000) == 0) { + block = index[i3Block + i3]; + } else { + // 18-bit indexes stored in groups of 9 entries per 8 indexes. + int32_t group = (i3Block & 0x7fff) + (i3 & ~7) + (i3 >> 3); + int32_t gi = i3 & 7; + block = ((int32_t)index[group++] << (2 + (2 * gi))) & 0x30000; + block |= index[group + gi]; + } + if (block == prevBlock && (c - start) >= dataBlockLength) { + // The block is the same as the previous one, and filled with value. + U_ASSERT((c & (dataBlockLength - 1)) == 0); + c += dataBlockLength; + } else { + int32_t dataMask = dataBlockLength - 1; + prevBlock = block; + if (block == trie->dataNullOffset) { + // This is the data null block. + if (haveValue) { + if (nullValue != value) { + return c - 1; + } + } else { + value = nullValue; + if (pValue != nullptr) { *pValue = nullValue; } + haveValue = true; + } + c = (c + dataBlockLength) & ~dataMask; + } else { + int32_t di = block + (c & dataMask); + uint32_t value2 = getValue(trie->data, valueWidth, di); + value2 = maybeFilterValue(value2, trie->nullValue, nullValue, + filter, context); + if (haveValue) { + if (value2 != value) { + return c - 1; + } + } else { + value = value2; + if (pValue != nullptr) { *pValue = value; } + haveValue = true; + } + while ((++c & dataMask) != 0) { + if (maybeFilterValue(getValue(trie->data, valueWidth, ++di), + trie->nullValue, nullValue, + filter, context) != value) { + return c - 1; + } + } + } + } + } while (++i3 < i3BlockLength); + } while (c < trie->highStart); + U_ASSERT(haveValue); + int32_t di = trie->dataLength - UCPTRIE_HIGH_VALUE_NEG_DATA_OFFSET; + uint32_t highValue = getValue(trie->data, valueWidth, di); + if (maybeFilterValue(highValue, trie->nullValue, nullValue, + filter, context) != value) { + return c - 1; + } else { + return MAX_UNICODE; + } +} + +} // namespace + +U_CFUNC UChar32 +ucptrie_internalGetRange(UCPTrieGetRange *getRange, + const void *trie, UChar32 start, + UCPMapRangeOption option, uint32_t surrogateValue, + UCPMapValueFilter *filter, const void *context, uint32_t *pValue) { + if (option == UCPMAP_RANGE_NORMAL) { + return getRange(trie, start, filter, context, pValue); + } + uint32_t value; + if (pValue == nullptr) { + // We need to examine the range value even if the caller does not want it. + pValue = &value; + } + UChar32 surrEnd = option == UCPMAP_RANGE_FIXED_ALL_SURROGATES ? 0xdfff : 0xdbff; + UChar32 end = getRange(trie, start, filter, context, pValue); + if (end < 0xd7ff || start > surrEnd) { + return end; + } + // The range overlaps with surrogates, or ends just before the first one. + if (*pValue == surrogateValue) { + if (end >= surrEnd) { + // Surrogates followed by a non-surrogateValue range, + // or surrogates are part of a larger surrogateValue range. + return end; + } + } else { + if (start <= 0xd7ff) { + return 0xd7ff; // Non-surrogateValue range ends before surrogateValue surrogates. + } + // Start is a surrogate with a non-surrogateValue code *unit* value. + // Return a surrogateValue code *point* range. + *pValue = surrogateValue; + if (end > surrEnd) { + return surrEnd; // Surrogate range ends before non-surrogateValue rest of range. + } + } + // See if the surrogateValue surrogate range can be merged with + // an immediately following range. + uint32_t value2; + UChar32 end2 = getRange(trie, surrEnd + 1, filter, context, &value2); + if (value2 == surrogateValue) { + return end2; + } + return surrEnd; +} + +U_CAPI UChar32 U_EXPORT2 +ucptrie_getRange(const UCPTrie *trie, UChar32 start, + UCPMapRangeOption option, uint32_t surrogateValue, + UCPMapValueFilter *filter, const void *context, uint32_t *pValue) { + return ucptrie_internalGetRange(getRange, trie, start, + option, surrogateValue, + filter, context, pValue); +} + +U_CAPI int32_t U_EXPORT2 +ucptrie_toBinary(const UCPTrie *trie, + void *data, int32_t capacity, + UErrorCode *pErrorCode) { + if (U_FAILURE(*pErrorCode)) { + return 0; + } + + UCPTrieType type = (UCPTrieType)trie->type; + UCPTrieValueWidth valueWidth = (UCPTrieValueWidth)trie->valueWidth; + if (type < UCPTRIE_TYPE_FAST || UCPTRIE_TYPE_SMALL < type || + valueWidth < UCPTRIE_VALUE_BITS_16 || UCPTRIE_VALUE_BITS_8 < valueWidth || + capacity < 0 || + (capacity > 0 && (data == nullptr || (U_POINTER_MASK_LSB(data, 3) != 0)))) { + *pErrorCode = U_ILLEGAL_ARGUMENT_ERROR; + return 0; + } + + int32_t length = (int32_t)sizeof(UCPTrieHeader) + trie->indexLength * 2; + switch (valueWidth) { + case UCPTRIE_VALUE_BITS_16: + length += trie->dataLength * 2; + break; + case UCPTRIE_VALUE_BITS_32: + length += trie->dataLength * 4; + break; + case UCPTRIE_VALUE_BITS_8: + length += trie->dataLength; + break; + default: + // unreachable + break; + } + if (capacity < length) { + *pErrorCode = U_BUFFER_OVERFLOW_ERROR; + return length; + } + + char *bytes = (char *)data; + UCPTrieHeader *header = (UCPTrieHeader *)bytes; + header->signature = UCPTRIE_SIG; // "Tri3" + header->options = (uint16_t)( + ((trie->dataLength & 0xf0000) >> 4) | + ((trie->dataNullOffset & 0xf0000) >> 8) | + (trie->type << 6) | + valueWidth); + header->indexLength = (uint16_t)trie->indexLength; + header->dataLength = (uint16_t)trie->dataLength; + header->index3NullOffset = trie->index3NullOffset; + header->dataNullOffset = (uint16_t)trie->dataNullOffset; + header->shiftedHighStart = trie->highStart >> UCPTRIE_SHIFT_2; + bytes += sizeof(UCPTrieHeader); + + uprv_memcpy(bytes, trie->index, trie->indexLength * 2); + bytes += trie->indexLength * 2; + + switch (valueWidth) { + case UCPTRIE_VALUE_BITS_16: + uprv_memcpy(bytes, trie->data.ptr16, trie->dataLength * 2); + break; + case UCPTRIE_VALUE_BITS_32: + uprv_memcpy(bytes, trie->data.ptr32, trie->dataLength * 4); + break; + case UCPTRIE_VALUE_BITS_8: + uprv_memcpy(bytes, trie->data.ptr8, trie->dataLength); + break; + default: + // unreachable + break; + } + return length; +} + +namespace { + +#ifdef UCPTRIE_DEBUG +long countNull(const UCPTrie *trie) { + uint32_t nullValue=trie->nullValue; + int32_t length=trie->dataLength; + long count=0; + switch (trie->valueWidth) { + case UCPTRIE_VALUE_BITS_16: + for(int32_t i=0; idata.ptr16[i]==nullValue) { ++count; } + } + break; + case UCPTRIE_VALUE_BITS_32: + for(int32_t i=0; idata.ptr32[i]==nullValue) { ++count; } + } + break; + case UCPTRIE_VALUE_BITS_8: + for(int32_t i=0; idata.ptr8[i]==nullValue) { ++count; } + } + break; + default: + // unreachable + break; + } + return count; +} + +U_CFUNC void +ucptrie_printLengths(const UCPTrie *trie, const char *which) { + long indexLength=trie->indexLength; + long dataLength=(long)trie->dataLength; + long totalLength=(long)sizeof(UCPTrieHeader)+indexLength*2+ + dataLength*(trie->valueWidth==UCPTRIE_VALUE_BITS_16 ? 2 : + trie->valueWidth==UCPTRIE_VALUE_BITS_32 ? 4 : 1); + printf("**UCPTrieLengths(%s %s)** index:%6ld data:%6ld countNull:%6ld serialized:%6ld\n", + which, trie->name, indexLength, dataLength, countNull(trie), totalLength); +} +#endif + +} // namespace + +// UCPMap ---- +// Initially, this is the same as UCPTrie. This may well change. + +U_CAPI uint32_t U_EXPORT2 +ucpmap_get(const UCPMap *map, UChar32 c) { + return ucptrie_get(reinterpret_cast(map), c); +} + +U_CAPI UChar32 U_EXPORT2 +ucpmap_getRange(const UCPMap *map, UChar32 start, + UCPMapRangeOption option, uint32_t surrogateValue, + UCPMapValueFilter *filter, const void *context, uint32_t *pValue) { + return ucptrie_getRange(reinterpret_cast(map), start, + option, surrogateValue, + filter, context, pValue); +} diff --git a/deps/icu-small/source/common/ucptrie_impl.h b/deps/icu-small/source/common/ucptrie_impl.h new file mode 100644 index 00000000000000..1fe6a18ac5319e --- /dev/null +++ b/deps/icu-small/source/common/ucptrie_impl.h @@ -0,0 +1,289 @@ +// © 2017 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html + +// ucptrie_impl.h (modified from utrie2_impl.h) +// created: 2017dec29 Markus W. Scherer + +#ifndef __UCPTRIE_IMPL_H__ +#define __UCPTRIE_IMPL_H__ + +#include "unicode/ucptrie.h" +#ifdef UCPTRIE_DEBUG +#include "unicode/umutablecptrie.h" +#endif + +// UCPTrie signature values, in platform endianness and opposite endianness. +// The UCPTrie signature ASCII byte values spell "Tri3". +#define UCPTRIE_SIG 0x54726933 +#define UCPTRIE_OE_SIG 0x33697254 + +/** + * Header data for the binary, memory-mappable representation of a UCPTrie/CodePointTrie. + * @internal + */ +struct UCPTrieHeader { + /** "Tri3" in big-endian US-ASCII (0x54726933) */ + uint32_t signature; + + /** + * Options bit field: + * Bits 15..12: Data length bits 19..16. + * Bits 11..8: Data null block offset bits 19..16. + * Bits 7..6: UCPTrieType + * Bits 5..3: Reserved (0). + * Bits 2..0: UCPTrieValueWidth + */ + uint16_t options; + + /** Total length of the index tables. */ + uint16_t indexLength; + + /** Data length bits 15..0. */ + uint16_t dataLength; + + /** Index-3 null block offset, 0x7fff or 0xffff if none. */ + uint16_t index3NullOffset; + + /** Data null block offset bits 15..0, 0xfffff if none. */ + uint16_t dataNullOffset; + + /** + * First code point of the single-value range ending with U+10ffff, + * rounded up and then shifted right by UCPTRIE_SHIFT_2. + */ + uint16_t shiftedHighStart; +}; + +/** + * Constants for use with UCPTrieHeader.options. + * @internal + */ +enum { + UCPTRIE_OPTIONS_DATA_LENGTH_MASK = 0xf000, + UCPTRIE_OPTIONS_DATA_NULL_OFFSET_MASK = 0xf00, + UCPTRIE_OPTIONS_RESERVED_MASK = 0x38, + UCPTRIE_OPTIONS_VALUE_BITS_MASK = 7, + /** + * Value for index3NullOffset which indicates that there is no index-3 null block. + * Bit 15 is unused for this value because this bit is used if the index-3 contains + * 18-bit indexes. + */ + UCPTRIE_NO_INDEX3_NULL_OFFSET = 0x7fff, + UCPTRIE_NO_DATA_NULL_OFFSET = 0xfffff +}; + +// Internal constants. +enum { + /** The length of the BMP index table. 1024=0x400 */ + UCPTRIE_BMP_INDEX_LENGTH = 0x10000 >> UCPTRIE_FAST_SHIFT, + + UCPTRIE_SMALL_LIMIT = 0x1000, + UCPTRIE_SMALL_INDEX_LENGTH = UCPTRIE_SMALL_LIMIT >> UCPTRIE_FAST_SHIFT, + + /** Shift size for getting the index-3 table offset. */ + UCPTRIE_SHIFT_3 = 4, + + /** Shift size for getting the index-2 table offset. */ + UCPTRIE_SHIFT_2 = 5 + UCPTRIE_SHIFT_3, + + /** Shift size for getting the index-1 table offset. */ + UCPTRIE_SHIFT_1 = 5 + UCPTRIE_SHIFT_2, + + /** + * Difference between two shift sizes, + * for getting an index-2 offset from an index-3 offset. 5=9-4 + */ + UCPTRIE_SHIFT_2_3 = UCPTRIE_SHIFT_2 - UCPTRIE_SHIFT_3, + + /** + * Difference between two shift sizes, + * for getting an index-1 offset from an index-2 offset. 5=14-9 + */ + UCPTRIE_SHIFT_1_2 = UCPTRIE_SHIFT_1 - UCPTRIE_SHIFT_2, + + /** + * Number of index-1 entries for the BMP. (4) + * This part of the index-1 table is omitted from the serialized form. + */ + UCPTRIE_OMITTED_BMP_INDEX_1_LENGTH = 0x10000 >> UCPTRIE_SHIFT_1, + + /** Number of entries in an index-2 block. 32=0x20 */ + UCPTRIE_INDEX_2_BLOCK_LENGTH = 1 << UCPTRIE_SHIFT_1_2, + + /** Mask for getting the lower bits for the in-index-2-block offset. */ + UCPTRIE_INDEX_2_MASK = UCPTRIE_INDEX_2_BLOCK_LENGTH - 1, + + /** Number of code points per index-2 table entry. 512=0x200 */ + UCPTRIE_CP_PER_INDEX_2_ENTRY = 1 << UCPTRIE_SHIFT_2, + + /** Number of entries in an index-3 block. 32=0x20 */ + UCPTRIE_INDEX_3_BLOCK_LENGTH = 1 << UCPTRIE_SHIFT_2_3, + + /** Mask for getting the lower bits for the in-index-3-block offset. */ + UCPTRIE_INDEX_3_MASK = UCPTRIE_INDEX_3_BLOCK_LENGTH - 1, + + /** Number of entries in a small data block. 16=0x10 */ + UCPTRIE_SMALL_DATA_BLOCK_LENGTH = 1 << UCPTRIE_SHIFT_3, + + /** Mask for getting the lower bits for the in-small-data-block offset. */ + UCPTRIE_SMALL_DATA_MASK = UCPTRIE_SMALL_DATA_BLOCK_LENGTH - 1 +}; + +typedef UChar32 +UCPTrieGetRange(const void *trie, UChar32 start, + UCPMapValueFilter *filter, const void *context, uint32_t *pValue); + +U_CFUNC UChar32 +ucptrie_internalGetRange(UCPTrieGetRange *getRange, + const void *trie, UChar32 start, + UCPMapRangeOption option, uint32_t surrogateValue, + UCPMapValueFilter *filter, const void *context, uint32_t *pValue); + +#ifdef UCPTRIE_DEBUG +U_CFUNC void +ucptrie_printLengths(const UCPTrie *trie, const char *which); + +U_CFUNC void umutablecptrie_setName(UMutableCPTrie *builder, const char *name); +#endif + +/* + * Format of the binary, memory-mappable representation of a UCPTrie/CodePointTrie. + * For overview information see http://site.icu-project.org/design/struct/utrie + * + * The binary trie data should be 32-bit-aligned. + * The overall layout is: + * + * UCPTrieHeader header; -- 16 bytes, see struct definition above + * uint16_t index[header.indexLength]; + * uintXY_t data[header.dataLength]; + * + * The trie data array is an array of uint16_t, uint32_t, or uint8_t, + * specified via the UCPTrieValueWidth when building the trie. + * The data array is 32-bit-aligned for uint32_t, otherwise 16-bit-aligned. + * The overall length of the trie data is a multiple of 4 bytes. + * (Padding is added at the end of the index array and/or near the end of the data array as needed.) + * + * The length of the data array (dataLength) is stored as an integer split across two fields + * of the header struct (high bits in header.options). + * + * The trie type can be "fast" or "small" which determines the index structure, + * specified via the UCPTrieType when building the trie. + * + * The type and valueWidth are stored in the header.options. + * There are reserved type and valueWidth values, and reserved header.options bits. + * They could be used in future format extensions. + * Code reading the trie structure must fail with an error when unknown values or options are set. + * + * Values for ASCII character (U+0000..U+007F) can always be found at the start of the data array. + * + * Values for code points below a type-specific fast-indexing limit are found via two-stage lookup. + * For a "fast" trie, the limit is the BMP/supplementary boundary at U+10000. + * For a "small" trie, the limit is UCPTRIE_SMALL_MAX+1=U+1000. + * + * All code points in the range highStart..U+10FFFF map to a single highValue + * which is stored at the second-to-last position of the data array. + * (See UCPTRIE_HIGH_VALUE_NEG_DATA_OFFSET.) + * The highStart value is header.shiftedHighStart<>UCPTRIE_SHIFT_1. + * (For 0x100000 supplementary code points U+10000..U+10ffff.) + * + * After this index-1 table follow the variable-length index-3 and index-2 tables. + * + * The supplementary index tables are omitted completely + * if there is only BMP data (highStart<=U+10000). + * + * For a "small" trie: + * + * The index array starts with a fast-index table for lookup of code points U+0000..U+0FFF. + * + * The "supplementary" index tables are always stored. + * The index-1 table starts from U+0000, its maximum length is 68=0x44=0x110000>>UCPTRIE_SHIFT_1. + * + * For both trie types: + * + * The last index-2 block may be a partial block, storing indexes only for code points + * below highStart. + * + * Lookup for ASCII code point c: + * + * Linear access from the start of the data array. + * + * value = data[c]; + * + * Lookup for fast-range code point c: + * + * Shift the code point right by UCPTRIE_FAST_SHIFT=6 bits, + * fetch the index array value at that offset, + * add the lower code point bits, index into the data array. + * + * value = data[index[c>>6] + (c&0x3f)]; + * + * (This works for ASCII as well.) + * + * Lookup for small-range code point c below highStart: + * + * Split the code point into four bit fields using several sets of shifts & masks + * to read consecutive values from the index-1, index-2, index-3 and data tables. + * + * If all of the data block offsets in an index-3 block fit within 16 bits (up to 0xffff), + * then the data block offsets are stored directly as uint16_t. + * + * Otherwise (this is very unusual but possible), the index-2 entry for the index-3 block + * has bit 15 (0x8000) set, and each set of 8 index-3 entries is preceded by + * an additional uint16_t word. Data block offsets are 18 bits wide, with the top 2 bits stored + * in the additional word. + * + * See ucptrie_internalSmallIndex() for details. + * + * (In a "small" trie, this works for ASCII and below-fast_limit code points as well.) + * + * Compaction: + * + * Multiple code point ranges ("blocks") that are aligned on certain boundaries + * (determined by the shifting/bit fields of code points) and + * map to the same data values normally share a single subsequence of the data array. + * Data blocks can also overlap partially. + * (Depending on the builder code finding duplicate and overlapping blocks.) + * + * Iteration over same-value ranges: + * + * Range iteration (ucptrie_getRange()) walks the structure from a start code point + * until some code point is found that maps to a different value; + * the end of the returned range is just before that. + * + * The header.dataNullOffset (split across two header fields, high bits in header.options) + * is the offset of a widely shared data block filled with one single value. + * It helps quickly skip over large ranges of data with that value. + * The builder must ensure that if the start of any data block (fast or small) + * matches the dataNullOffset, then the whole block must be filled with the null value. + * Special care must be taken if there is no fast null data block + * but a small one, which is shorter, and it matches the *start* of some fast data block. + * + * Similarly, the header.index3NullOffset is the index-array offset of an index-3 block + * where all index entries point to the dataNullOffset. + * If there is no such data or index-3 block, then these offsets are set to + * values that cannot be reached (data offset out of range/reserved index offset), + * normally UCPTRIE_NO_DATA_NULL_OFFSET or UCPTRIE_NO_INDEX3_NULL_OFFSET respectively. + */ + +#endif diff --git a/deps/icu-small/source/common/ucurr.cpp b/deps/icu-small/source/common/ucurr.cpp index bfde3a9df9c2d1..5c9bbef70097e7 100644 --- a/deps/icu-small/source/common/ucurr.cpp +++ b/deps/icu-small/source/common/ucurr.cpp @@ -1077,11 +1077,11 @@ collectCurrencyNames(const char* locale, } // currency plurals - UErrorCode ec3 = U_ZERO_ERROR; - UResourceBundle* curr_p = ures_getByKey(rb, CURRENCYPLURALS, NULL, &ec3); + UErrorCode ec5 = U_ZERO_ERROR; + UResourceBundle* curr_p = ures_getByKey(rb, CURRENCYPLURALS, NULL, &ec5); n = ures_getSize(curr_p); for (int32_t i=0; ilocale) == 0) { @@ -1469,7 +1469,6 @@ getCacheEntry(const char* locale, UErrorCode& ec) { } umtx_lock(&gCurrencyCacheMutex); // check again. - int8_t found = -1; for (int8_t i = 0; i < CURRENCY_NAME_CACHE_NUM; ++i) { if (currCache[i]!= NULL && uprv_strcmp(locale, currCache[i]->locale) == 0) { diff --git a/deps/icu-small/source/common/udata.cpp b/deps/icu-small/source/common/udata.cpp index c15cb78a74ad7a..99efbc97eed737 100644 --- a/deps/icu-small/source/common/udata.cpp +++ b/deps/icu-small/source/common/udata.cpp @@ -418,7 +418,8 @@ class UDataPathIterator const char *path; /* working path (u_icudata_Dir) */ const char *nextPath; /* path following this one */ const char *basename; /* item's basename (icudt22e_mt.res)*/ - const char *suffix; /* item suffix (can be null) */ + + StringPiece suffix; /* item suffix (can be null) */ uint32_t basenameLen; /* length of basename */ @@ -432,13 +433,15 @@ class UDataPathIterator }; /** - * @param iter The iterator to be initialized. Its current state does not matter. - * @param path The full pathname to be iterated over. If NULL, defaults to U_ICUDATA_NAME - * @param pkg Package which is being searched for, ex "icudt28l". Will ignore leave directories such as /icudt28l - * @param item Item to be searched for. Can include full path, such as /a/b/foo.dat - * @param suffix Optional item suffix, if not-null (ex. ".dat") then 'path' can contain 'item' explicitly. - * Ex: 'stuff.dat' would be found in '/a/foo:/tmp/stuff.dat:/bar/baz' as item #2. - * '/blarg/stuff.dat' would also be found. + * @param iter The iterator to be initialized. Its current state does not matter. + * @param inPath The full pathname to be iterated over. If NULL, defaults to U_ICUDATA_NAME + * @param pkg Package which is being searched for, ex "icudt28l". Will ignore leaf directories such as /icudt28l + * @param item Item to be searched for. Can include full path, such as /a/b/foo.dat + * @param inSuffix Optional item suffix, if not-null (ex. ".dat") then 'path' can contain 'item' explicitly. + * Ex: 'stuff.dat' would be found in '/a/foo:/tmp/stuff.dat:/bar/baz' as item #2. + * '/blarg/stuff.dat' would also be found. + * Note: inSuffix may also be the 'item' being searched for as well, (ex: "ibm-5348_P100-1997.cnv"), in which case + * the 'item' parameter is often the same as pkg. (Though sometimes might have a tree part as well, ex: "icudt62l-curr"). */ UDataPathIterator::UDataPathIterator(const char *inPath, const char *pkg, const char *item, const char *inSuffix, UBool doCheckLastFour, @@ -566,7 +569,7 @@ const char *UDataPathIterator::next(UErrorCode *pErrorCode) if(checkLastFour == TRUE && (pathLen>=4) && - uprv_strncmp(pathBuffer.data() +(pathLen-4), suffix, 4)==0 && /* suffix matches */ + uprv_strncmp(pathBuffer.data() +(pathLen-4), suffix.data(), 4)==0 && /* suffix matches */ uprv_strncmp(findBasename(pathBuffer.data()), basename, basenameLen)==0 && /* base matches */ uprv_strlen(pathBasename)==(basenameLen+4)) { /* base+suffix = full len */ @@ -602,8 +605,13 @@ const char *UDataPathIterator::next(UErrorCode *pErrorCode) /* + basename */ pathBuffer.append(packageStub.data()+1, packageStub.length()-1, *pErrorCode); - if(*suffix) /* tack on suffix */ + if (!suffix.empty()) /* tack on suffix */ { + if (suffix.length() > 4) { + // If the suffix is actually an item ("ibm-5348_P100-1997.cnv") and not an extension (".res") + // then we need to ensure that the path ends with a separator. + pathBuffer.ensureEndsWithFileSeparator(*pErrorCode); + } pathBuffer.append(suffix, *pErrorCode); } } @@ -751,16 +759,19 @@ openCommonData(const char *path, /* Path from OpenChoice? */ UDataPathIterator iter(u_getDataDirectory(), inBasename, path, ".dat", TRUE, pErrorCode); - while((UDataMemory_isLoaded(&tData)==FALSE) && (pathBuffer = iter.next(pErrorCode)) != NULL) + while ((UDataMemory_isLoaded(&tData)==FALSE) && (pathBuffer = iter.next(pErrorCode)) != NULL) { #ifdef UDATA_DEBUG fprintf(stderr, "ocd: trying path %s - ", pathBuffer); #endif - uprv_mapFile(&tData, pathBuffer); + uprv_mapFile(&tData, pathBuffer, pErrorCode); #ifdef UDATA_DEBUG fprintf(stderr, "%s\n", UDataMemory_isLoaded(&tData)?"LOADED":"not loaded"); #endif } + if (U_FAILURE(*pErrorCode)) { + return NULL; + } #if defined(OS390_STUBDATA) && defined(OS390BATCH) if (!UDataMemory_isLoaded(&tData)) { @@ -769,7 +780,7 @@ openCommonData(const char *path, /* Path from OpenChoice? */ uprv_strncpy(ourPathBuffer, path, 1019); ourPathBuffer[1019]=0; uprv_strcat(ourPathBuffer, ".dat"); - uprv_mapFile(&tData, ourPathBuffer); + uprv_mapFile(&tData, ourPathBuffer, pErrorCode); } #endif @@ -860,7 +871,7 @@ static UBool extendICUData(UErrorCode *pErr) umtx_unlock(&extendICUDataMutex); #endif return didUpdate; /* Return true if ICUData pointer was updated. */ - /* (Could potentialy have been done by another thread racing */ + /* (Could potentially have been done by another thread racing */ /* us through here, but that's fine, we still return true */ /* so that current thread will also examine extended data. */ } @@ -986,12 +997,12 @@ static UDataMemory *doLoadFromIndividualFiles(const char *pkgName, /* init path iterator for individual files */ UDataPathIterator iter(dataPath, pkgName, path, tocEntryPathSuffix, FALSE, pErrorCode); - while((pathBuffer = iter.next(pErrorCode)) != NULL) + while ((pathBuffer = iter.next(pErrorCode)) != NULL) { #ifdef UDATA_DEBUG fprintf(stderr, "UDATA: trying individual file %s\n", pathBuffer); #endif - if(uprv_mapFile(&dataMemory, pathBuffer)) + if (uprv_mapFile(&dataMemory, pathBuffer, pErrorCode)) { pEntryData = checkDataItem(dataMemory.pHeader, isAcceptable, context, type, name, subErrorCode, pErrorCode); if (pEntryData != NULL) { @@ -1007,7 +1018,7 @@ static UDataMemory *doLoadFromIndividualFiles(const char *pkgName, return pEntryData; } - /* the data is not acceptable, or some error occured. Either way, unmap the memory */ + /* the data is not acceptable, or some error occurred. Either way, unmap the memory */ udata_close(&dataMemory); /* If we had a nasty error, bail out completely. */ @@ -1076,6 +1087,11 @@ static UDataMemory *doLoadFromCommonData(UBool isICUData, const char * /*pkgName } } } + // If we failed due to being out-of-memory, then stop early and report the error. + if (*subErrorCode == U_MEMORY_ALLOCATION_ERROR) { + *pErrorCode = *subErrorCode; + return NULL; + } /* Data wasn't found. If we were looking for an ICUData item and there is * more data available, load it and try again, * otherwise break out of this loop. */ @@ -1252,7 +1268,8 @@ doOpenChoice(const char *path, const char *type, const char *name, tocEntryName.append(".", *pErrorCode).append(type, *pErrorCode); tocEntryPath.append(".", *pErrorCode).append(type, *pErrorCode); } - tocEntryPathSuffix = tocEntryPath.data()+tocEntrySuffixIndex; /* suffix starts here */ + // The +1 is for the U_FILE_SEP_CHAR that is always appended above. + tocEntryPathSuffix = tocEntryPath.data() + tocEntrySuffixIndex + 1; /* suffix starts here */ #ifdef UDATA_DEBUG fprintf(stderr, " tocEntryName = %s\n", tocEntryName.data()); diff --git a/deps/icu-small/source/common/udataswp.h b/deps/icu-small/source/common/udataswp.h index 5303870b1d3046..5e7b043c4c934c 100644 --- a/deps/icu-small/source/common/udataswp.h +++ b/deps/icu-small/source/common/udataswp.h @@ -333,6 +333,43 @@ uprv_compareInvEbcdic(const UDataSwapper *ds, # error Unknown charset family! #endif +// utrie_swap.cpp -----------------------------------------------------------*** + +/** + * Swaps a serialized UTrie. + * @internal + */ +U_CAPI int32_t U_EXPORT2 +utrie_swap(const UDataSwapper *ds, + const void *inData, int32_t length, void *outData, + UErrorCode *pErrorCode); + +/** + * Swaps a serialized UTrie2. + * @internal + */ +U_CAPI int32_t U_EXPORT2 +utrie2_swap(const UDataSwapper *ds, + const void *inData, int32_t length, void *outData, + UErrorCode *pErrorCode); + +/** + * Swaps a serialized UCPTrie. + * @internal + */ +U_CAPI int32_t U_EXPORT2 +ucptrie_swap(const UDataSwapper *ds, + const void *inData, int32_t length, void *outData, + UErrorCode *pErrorCode); + +/** + * Swaps a serialized UTrie, UTrie2, or UCPTrie. + * @internal + */ +U_CAPI int32_t U_EXPORT2 +utrie_swapAnyVersion(const UDataSwapper *ds, + const void *inData, int32_t length, void *outData, + UErrorCode *pErrorCode); /* material... -------------------------------------------------------------- */ diff --git a/deps/icu-small/source/common/uhash.cpp b/deps/icu-small/source/common/uhash.cpp index a80e7b8ff27b42..239997d05d7e38 100644 --- a/deps/icu-small/source/common/uhash.cpp +++ b/deps/icu-small/source/common/uhash.cpp @@ -218,7 +218,7 @@ _uhash_allocate(UHashtable *hash, U_ASSERT(primeIndex >= 0 && primeIndex < PRIMES_LENGTH); - hash->primeIndex = primeIndex; + hash->primeIndex = static_cast(primeIndex); hash->length = PRIMES[primeIndex]; p = hash->elements = (UHashElement*) @@ -860,13 +860,13 @@ uhash_hashUChars(const UHashTok key) { U_CAPI int32_t U_EXPORT2 uhash_hashChars(const UHashTok key) { const char *s = (const char *)key.pointer; - return s == NULL ? 0 : static_cast(ustr_hashCharsN(s, uprv_strlen(s))); + return s == NULL ? 0 : static_cast(ustr_hashCharsN(s, static_cast(uprv_strlen(s)))); } U_CAPI int32_t U_EXPORT2 uhash_hashIChars(const UHashTok key) { const char *s = (const char *)key.pointer; - return s == NULL ? 0 : ustr_hashICharsN(s, uprv_strlen(s)); + return s == NULL ? 0 : ustr_hashICharsN(s, static_cast(uprv_strlen(s))); } U_CAPI UBool U_EXPORT2 diff --git a/deps/icu-small/source/common/uinvchar.h b/deps/icu-small/source/common/uinvchar.h index c4f9f88b9ad32f..56dddfa8fde9bb 100644 --- a/deps/icu-small/source/common/uinvchar.h +++ b/deps/icu-small/source/common/uinvchar.h @@ -53,22 +53,6 @@ uprv_isInvariantString(const char *s, int32_t length); U_INTERNAL UBool U_EXPORT2 uprv_isInvariantUString(const UChar *s, int32_t length); -#ifdef __cplusplus - -/** - * Check if a UnicodeString only contains invariant characters. - * See utypes.h for details. - * - * @param s Input string. - * @return TRUE if s contains only invariant characters. - */ -U_INTERNAL inline UBool U_EXPORT2 -uprv_isInvariantUnicodeString(const icu::UnicodeString &s) { - return uprv_isInvariantUString(icu::toUCharPtr(s.getBuffer()), s.length()); -} - -#endif /* __cplusplus */ - /** * \def U_UPPER_ORDINAL * Get the ordinal number of an uppercase invariant character diff --git a/deps/icu-small/source/common/ulayout_props_data.h b/deps/icu-small/source/common/ulayout_props_data.h new file mode 100644 index 00000000000000..f42d15fc830afd --- /dev/null +++ b/deps/icu-small/source/common/ulayout_props_data.h @@ -0,0 +1,722 @@ +// © 2018 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html +// +// file name: ulayout_props_data.h +// +// machine-generated by: icu/tools/unicode/c/genprops/layoutpropsbuilder.cpp + + +#ifdef INCLUDED_FROM_UPROPS_CPP + +static const int32_t maxInPCValue = 14; + +static const uint16_t inpc_trieIndex[765]={ +0,0x40,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0x80,0xc0,0xff,0x13f,0x17e,0x1be,0x17e,0x1fe,0x23e,0x27e,0x2bc,0x2fc, +0x33c,0x37b,0x23e,0x3bb,0x3fb,0x439,0x477,0x4ad,0x4e1,0x521,0x531,0x571,0x599,0x5d9,0x619,0x656, +0x2b7,0x2c6,0x2d2,0x2c6,0x2ed,0,0x10,0x20,0x30,0x40,0x50,0x60,0x70,0,0x10,0x20, +0x30,0,0x10,0x20,0x30,0,0x10,0x20,0x30,0,0x10,0x20,0x30,0,0x10,0x20, +0x30,0,0x10,0x20,0x30,0,0x10,0x20,0x30,0,0x10,0x20,0x30,0x80,0x90,0xa0, +0xb0,0xc0,0xd0,0xe0,0xf0,0xff,0x10f,0x11f,0x12f,0x13f,0x14f,0x15f,0x16f,0x17e,0x18e,0x19e, +0x1ae,0x1be,0x1ce,0x1de,0x1ee,0x17e,0x18e,0x19e,0x1ae,0x1fe,0x20e,0x21e,0x22e,0x23e,0x24e,0x25e, +0x26e,0x27e,0x28e,0x29e,0x2ae,0x2bc,0x2cc,0x2dc,0x2ec,0x2fc,0x30c,0x31c,0x32c,0x33c,0x34c,0x35c, +0x36c,0x37b,0x38b,0x39b,0x3ab,0x23e,0x24e,0x25e,0x26e,0x3bb,0x3cb,0x3db,0x3eb,0x3fb,0x40b,0x41b, +0x42b,0x439,0x449,0x459,0x469,0x477,0x487,0x497,0x4a7,0x4ad,0x4bd,0x4cd,0x4dd,0x4e1,0x4f1,0x501, +0x511,0x521,0x531,0x541,0x551,0x531,0x541,0x551,0x561,0x571,0x581,0x591,0x5a1,0x599,0x5a9,0x5b9, +0x5c9,0x5d9,0x5e9,0x5f9,0x609,0x619,0x629,0x639,0x649,0x656,0x666,0x676,0x686,0,0,0x68b, +0x69a,0,0x6a9,0x6b8,0x6c7,0x6d5,0x6e5,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0x6f3,0,0x6f3, +0,0x701,0,0x701,0,0,0,0x70b,0x71b,0x729,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0x739,0x749,0,0, +0,0,0,0,0,0x759,0x768,0,0,0,0x772,0,0,0,0x77e,0x78d, +0x79b,0,0,0,0,0,0,0,0,0x7ab,0,0,0x7b7,0x7c7,0,0x7cc, +0x52c,0x81,0,0x7dc,0,0,0,0x7ea,0x3fb,0,0,0x7fa,0x807,0,0,0, +0,0,0,0,0,0,0x817,0x827,0x835,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0x2b3,0x83f,0,0x84c,0,0,0,0, +0,0x101,0,0,0x858,0x864,0,0x874,0x882,0,0,0x892,0,0x8a0,0x3fb,0, +0,0x80,0,0,0x8b0,0x8c0,0,0x2b9,0,0,0x8c7,0x8d6,0x8e3,0,0,0x8f1, +0,0,0,0x901,0x2bd,0,0x911,0x151,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0x921,0,0x930,0,0,0x940,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0x950,0,0,0x958,0x966,0,0,0, +0x81,0,0,0x976,0,0,0,0,0x52d,0,0x981,0x991,0x3cb,0,0,0x659, +0x81,0,0,0x99e,0x9ae,0,0,0,0x9bb,0x9cb,0,0,0,0,0,0, +0,0,0,0x71,0x9db,0,0xff,0,0,0x9e6,0x9f6,0x14f,0xa04,0x52b,0,0, +0,0,0,0,0,0,0x99c,0xa14,0x16f,0,0,0,0,0,0xa24,0xa33, +0,0,0,0,0,0,0,0,0,0,0,0,0,0x2eb,0xa43,0xe3, +0x214,0,0,0,0xa53,0x2be,0,0,0,0,0,0xa63,0xa73,0,0,0, +0,0,0xa7b,0xa8b,0,0,0,0,0,0,0,0,0,0,0,0, +0,0xa97,0xaa6,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xab5, +0,0,0xac2,0,0xad1,0,0,0xadd,0xae7,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0x2eb, +0xaf7,0,0,0,0,0,0xb07,0xb0f,0xb1e,0,0,0,0,0,0,0, +0xb2d,0xb3c,0,0,0,0xb44,0xb54,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0xb61,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0x45,0x4d,0x4d,0x4d,0x5d,0x7d,0x9d,0xbd,0xdd, +2,2,0xec,0x10a,0x129,0x149,2,2,2,2,2,2,2,2,2,2, +2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, +2,2,2,2,2,2,0x169,0x188,2,2,2,2,2,2,2,2, +2,2,0x1a8,2,2,0x1c8,0x1e6,0x203,0x221,0x23f,0x25f,0x27d,0x297 +}; + +static const uint8_t inpc_trieData[2930]={ +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +8,8,8,7,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,8,7,1,0,7,4, +7,1,1,1,1,8,8,8,8,7,7,7,7,1,4,7, +0,8,1,8,8,8,1,1,0,0,0,0,0,0,0,0, +0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +8,7,7,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,1,0,7,4,7, +1,1,1,1,0,0,4,4,0,0,5,5,1,0,0,0, +0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0, +0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,8, +8,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,1,0,7,4,7,1, +1,0,0,0,0,8,8,0,0,8,8,1,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,8, +0,0,0,1,0,0,0,0,0,0,0,0,0,0,7,1, +1,1,1,8,0,8,8,0xd,0,7,7,1,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,8,8,8,8,8,8,0,8, +7,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,1,0,7,8,7,1, +1,1,1,0,0,4,0xb,0,0,5,0xc,1,0,0,0,0, +0,0,0,0,8,0xd,0,0,0,0,0,0,0,0,0,0, +1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,7,7,8,7,7,0, +0,0,4,4,4,0,5,5,5,8,0,0,0,0,0,0, +0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,8,7,7,7, +8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,8,8,7,7,7,7, +0,8,8,9,0,8,8,8,8,0,0,0,0,0,0,0, +8,1,0,0,0,0,0,0,0,0,0,0,0,1,1,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0xd,7,7,7,7, +0,8,0xd,0xd,0,0xd,0xd,8,8,0,0,0,0,0,0,0, +7,7,0,0,0,0,0,0,0,0,0,0,0,1,1,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,8,8,7,7,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,8,8,0,7,7,7,1,1,0,4, +4,4,0,5,5,5,8,0,0,0,0,0,0,0,0,0, +7,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,7,7,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,8,0,0,0,0,7,7,7,8, +8,1,0,1,0,7,4,0xb,4,5,0xc,5,7,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7, +7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,7,8,7,7,8,8,8,8,1,1,1,0,0,0,0, +0,0xe,0xe,0xe,0xe,0xe,7,0,8,8,8,8,8,8,8,8, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,7,8,7,7,8,8,8,8,1,1,0,8,1,0,0, +0,0xe,0xe,0xe,0xe,0xe,0,0,0,8,8,8,8,8,8,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0, +1,0,8,0,0,0,0,7,4,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,1,8,9,1,1,9, +9,9,9,8,8,8,8,8,7,8,9,8,8,1,0,8, +8,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1, +1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,0,0,0,0,0,0,1,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,7,7,8,8,1,4,8,8,8,8, +8,1,7,0,8,7,0,1,1,0,0,0,0,0,0,7, +7,1,1,0,0,0,0,1,1,0,7,7,7,0,0,7, +7,7,7,7,7,7,0,0,8,8,8,8,0,0,0,0, +0,0,0,0,0,0,0,1,7,4,8,8,7,7,7,7, +7,7,1,0,7,0,0,0,0,0,0,0,0,0,0,7, +7,7,8,0,0,8,1,1,0,0,0,0,0,0,0,0, +0,0,0,8,1,0,0,0,0,0,0,0,0,0,0,0, +0,7,8,8,8,8,1,1,1,0xb,0xc,5,4,4,4,5, +5,8,7,7,8,8,8,8,8,8,8,0,8,0,0,0, +0,0,0,0,0,0,8,0,0,8,8,1,7,7,0xd,0xd, +8,8,7,7,7,0,0,0,0,7,7,1,7,7,7,7, +7,7,1,8,1,0,0,0,0,7,7,7,7,7,0xe,0xe, +0xe,7,7,0xe,7,7,7,7,7,0,0,0,0,0,0,0, +7,7,0,0,0,0,0,0,0,8,1,4,7,8,0,0, +0,0,0,4,1,7,8,8,8,1,1,1,1,0,7,8, +7,7,8,8,8,8,1,1,8,1,7,4,4,4,8,8, +8,8,8,8,8,8,8,8,0,0,1,8,8,8,8,7, +0,0,0,0,0,0,0,0,0,0,0,8,7,8,8,1, +1,1,3,9,0xa,4,4,5,5,8,0xd,7,0,0,0,0, +0,0,0,0,0,0,0,8,1,8,8,8,0,7,1,1, +8,1,4,7,8,8,7,0,1,1,0,0,0,0,0,0, +8,7,8,8,7,7,7,8,7,8,0,0,0,0,7,7, +7,4,4,0xb,7,7,1,8,8,8,8,4,4,8,1,0, +0,0,0,0,0,0,0,8,8,8,0,6,1,1,1,1, +1,8,8,1,1,1,1,8,7,6,6,6,6,6,6,6, +0,0,0,0,1,0,0,0,0,8,0,0,7,0,0,0, +0,0,0,0,0,8,0,0,0,0,8,0,0,0,0,7, +7,1,8,7,0,0,0,0,0,0,0,0,7,7,7,7, +7,7,7,7,7,7,7,7,1,8,0,0,0,0,0,0, +0,0,0,0,8,8,8,8,8,8,8,8,8,8,8,8, +8,8,8,8,0,0,0,0,0,0,0,0,0,0,0,0, +0,8,0,0,0,0,0,0,0,0,0,0,0,1,1,1, +0,0,0,0,0,0,0,1,1,1,8,1,1,1,1,8, +0,0,0,8,7,7,8,8,1,1,4,4,8,7,7,2, +3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +8,8,8,8,1,8,4,8,1,7,4,1,1,0,0,0, +0,0,0,0,0,0,8,0,0,0,0,0,0,0,0,8, +7,0,0,0,0,0,0,0,0,0,0,0,7,8,7,0, +0,8,7,8,8,1,0xe,0xe,8,8,0xe,7,0xe,0xe,7,8, +8,0,0,0,0,0,0,0,0,0,0,0,4,1,8,4, +7,0,0,0,7,7,8,7,7,1,7,7,0,7,1,0, +0,6,1,1,0,8,6,0,0,0,0,0,1,1,1,8, +0,0,0,0,0,0,0,0,8,1,1,0,0,0,0,0, +7,8,7,0,0,0,0,0,0,0,0,0,0,0,0,0, +8,8,8,8,1,1,1,1,8,8,8,8,8,0,0,0, +0,0,0,0,0,0,7,4,7,1,1,8,8,7,7,1, +1,0,0,0,0,0,0,0,8,8,8,1,1,4,8,9, +9,8,1,1,0,8,0,0,0,0,0,0,0,0,0,0, +0,7,4,7,1,1,1,1,1,1,8,8,8,0xd,7,0, +0,0,0,0,0,0,0,1,0,8,1,0,0,0,0,0, +0,0,0,0,0,0,0,7,7,7,1,8,8,0xd,0xd,8, +7,8,8,0,0,0,0,0,0,8,0,7,4,7,1,1, +8,8,8,8,1,1,0,0,0,0,0,0,0,0,0,0, +0,1,1,0,7,7,8,7,7,7,7,0,0,4,4,0, +0,5,5,7,0,0,7,7,0,0,8,8,8,8,8,8, +8,0,0,0,7,7,1,8,8,7,1,0,0,0,0,0, +0,0,0,0,7,4,7,1,1,1,1,1,1,4,8,0xb, +5,7,5,8,7,1,1,0,0,0,0,0,0,0,0,0, +0,0,0,4,7,1,1,1,1,0,0,4,0xb,5,0xc,8, +8,7,1,7,7,7,1,1,1,1,1,1,8,8,7,7, +8,7,1,0,0,0,0,0,0,0,0,0,0,0,8,7, +8,4,7,1,1,8,8,8,8,7,1,0,0,0,0,0, +0,0,0,0,0,0,0,0,1,0,8,7,7,8,8,1, +1,4,8,1,8,8,8,0,0,0,0,0,0,0,0,0, +0,0,0,7,4,7,1,1,1,8,8,8,8,8,7,1, +1,0,0,0,0,0,8,1,1,8,8,8,8,8,8,1, +0,0,0,0,0,1,1,8,8,8,8,7,0,1,1,1, +1,0,8,1,1,8,8,8,7,7,1,1,1,0,0,0, +0,0,0,0,0,0,0,1,1,1,1,1,1,8,7,8, +0,0,0,0,0,0,0,8,8,1,1,1,1,1,0,8, +8,8,8,8,8,7,1,0,0,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,0,7,1,1,1,1,1,1,4, +1,8,7,8,8,0,0,0,0,0,0,0,0,0,8,8, +8,8,8,1,0,0,0,8,0,8,8,0,8,8,1,8, +1,0,0,1,0,0,0,0,0,0,0,0,0,0,7,7, +7,7,7,0,8,8,0,7,7,8,7,0,0,0,0,0, +0,0,0,0,8,1,4,7,0,0,0,0,0,0,0,0, +0,0 +}; + +static const UCPTrie inpc_trie={ + inpc_trieIndex, + { inpc_trieData }, + 765, 2930, + 0x12000, 0x12, + 1, 2, + 0, 0, + 0x2, 0x0, + 0x0, +}; + +static const int32_t maxInSCValue = 35; + +static const uint16_t insc_trieIndex[834]={ +0,0x40,0x60,0x94,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40, +0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40, +0x40,0x40,0x40,0x40,0xd4,0x112,0x152,0x190,0x1cf,0x20d,0x24c,0x28a,0x2ca,0x308,0x346,0x384, +0x3c4,0x402,0x441,0x47f,0x4bf,0x4fd,0x53d,0x57d,0x5bc,0x5fc,0x63b,0x67b,0x69b,0x6db,0x71b,0x758, +0x2f8,0x30b,0x317,0x30b,0x332,0,0x10,0x20,0x30,0x40,0x50,0x60,0x70,0x60,0x70,0x80, +0x90,0x94,0xa4,0xb4,0xc4,0x40,0x50,0x60,0x70,0x40,0x50,0x60,0x70,0x40,0x50,0x60, +0x70,0x40,0x50,0x60,0x70,0x40,0x50,0x60,0x70,0x40,0x50,0x60,0x70,0x40,0x50,0x60, +0x70,0x40,0x50,0x60,0x70,0xd4,0xe4,0xf4,0x104,0x112,0x122,0x132,0x142,0x152,0x162,0x172, +0x182,0x190,0x1a0,0x1b0,0x1c0,0x1cf,0x1df,0x1ef,0x1ff,0x20d,0x21d,0x22d,0x23d,0x24c,0x25c,0x26c, +0x27c,0x28a,0x29a,0x2aa,0x2ba,0x2ca,0x2da,0x2ea,0x2fa,0x308,0x318,0x328,0x338,0x346,0x356,0x366, +0x376,0x384,0x394,0x3a4,0x3b4,0x3c4,0x3d4,0x3e4,0x3f4,0x402,0x412,0x422,0x432,0x441,0x451,0x461, +0x471,0x47f,0x48f,0x49f,0x4af,0x4bf,0x4cf,0x4df,0x4ef,0x4fd,0x50d,0x51d,0x52d,0x53d,0x54d,0x55d, +0x56d,0x57d,0x58d,0x59d,0x5ad,0x5bc,0x5cc,0x5dc,0x5ec,0x5fc,0x60c,0x61c,0x62c,0x63b,0x64b,0x65b, +0x66b,0x67b,0x68b,0x69b,0x6ab,0x69b,0x6ab,0x6bb,0x6cb,0x6db,0x6eb,0x6fb,0x70b,0x71b,0x72b,0x73b, +0x74b,0x758,0x768,0x778,0x788,0xe9,0xe9,0x798,0x7a3,0x7b3,0x7c3,0x7d2,0x7e1,0x7ef,0x7ff,0x40, +0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40, +0x40,0x40,0x40,0x40,0x40,0x80f,0x81d,0xe6,0x81d,0xe6,0x82d,0x80f,0x83d,0xe9,0xe9,0x84d, +0x859,0x863,0x872,0x30,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40, +0x40,0x40,0x40,0x40,0x882,0x16c,0x892,0x8a2,0x22d,0xe9,0x8b2,0x8c2,0xe9,0xe9,0x374,0x8d2, +0x8e1,0x30,0x40,0x40,0xe9,0x8f1,0xe9,0xe9,0x901,0x90e,0x91e,0x92a,0x30,0x30,0x40,0x40, +0x40,0x40,0x40,0x40,0x93a,0xe6,0xe9,0x94a,0x956,0x30,0x40,0x40,0x966,0xe9,0x975,0x985, +0xe9,0xe9,0x995,0x9a5,0xe9,0xe9,0x9b5,0x9c2,0x9d2,0x40,0x40,0x40,0x40,0x40,0x40,0x40, +0x40,0x9e2,0x9f0,0x9fe,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40, +0x40,0x40,0x40,0xa08,0xa14,0xa24,0x40,0x40,0x40,0x40,0x40,0x75a,0xa32,0x40,0x40,0x40, +0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40, +0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x74,0x40,0x40,0x40,0xa42,0xe9,0xa4f, +0x40,0xe9,0xa5f,0xa6d,0xa7c,0xd6,0xe7,0xe9,0xa8c,0xa98,0x30,0xaa8,0xab6,0xac6,0xe9,0xad4, +0xe9,0xae4,0xaf3,0x40,0x40,0xb03,0xe9,0xe9,0xb12,0x297,0x30,0xb22,0xb32,0xe3,0xe9,0x889, +0xb42,0xb52,0x30,0xe9,0xb61,0xe9,0xe9,0xe9,0xb71,0xb81,0x40,0xb91,0xba1,0x40,0x40,0x40, +0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0xbb1,0xbc1,0xbce,0x30,0xbde,0xbee,0xe9, +0xbf8,0x31,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40, +0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0xc08,0xe6,0xe9, +0x88a,0xc18,0xc26,0xc30,0xc40,0xc50,0xe9,0xe9,0xc60,0x40,0x40,0x40,0x40,0xc70,0xe9,0x88b, +0xc80,0xc90,0xca0,0xe9,0xcad,0xd5,0xe8,0xe9,0xcbd,0xccd,0x30,0x6ba,0x35,0xe1,0x3eb,0x886, +0xcdd,0x40,0x40,0x40,0x40,0xced,0x16d,0xcfc,0xdf,0xe9,0xd0c,0xd1c,0x30,0xd2c,0x162,0x172, +0xd3c,0x308,0xd4c,0xd5c,0x9ed,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0xdb,0xe9,0xe9, +0xd6c,0xd7a,0xd8a,0x40,0x40,0xd99,0xe9,0xe9,0x91f,0xda9,0x30,0x40,0x40,0x40,0x40,0x40, +0x40,0x40,0x40,0x40,0x40,0xdb,0xe9,0xff,0xdb9,0xdc9,0xdd1,0x40,0x40,0xdb,0xe9,0xe9, +0xde1,0xdf1,0x30,0x40,0x40,0xdf,0xe9,0xe01,0xe0e,0x30,0x40,0x40,0x40,0xe9,0xe1e,0xe2e, +0xe3e,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0xdf,0xe9,0x886, +0xe4e,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40, +0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0xe5e,0xe9,0xe9, +0xe6b,0xe7b,0xe8b,0xe9,0xe9,0xe97,0xea1,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40, +0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0xeb1,0xe9,0xff, +0xec1,0xed1,0x6bb,0xee1,0x555,0xe9,0xeef,0x72b,0xeff,0x40,0x40,0x40,0x40,0xf0f,0xe9,0xe9, +0xf1e,0xf2e,0x30,0xf3e,0xe9,0xf4a,0xf57,0x30,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40, +0x40,0x40,0x40,0x40,0x40,0x40,0xe9,0xf67,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40, +0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x45,0x55,0x55,0x55,0x65,0x85,0xa5,0xc5, +0xe5,4,4,0xf5,0x114,0x134,0x154,4,0x174,4,0x17d,4,4,4,4,4, +4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, +4,4,4,4,4,4,4,4,4,4,4,0x19d,0x1bd,4,4,4, +4,4,4,4,4,4,4,0x1dd,4,4,0x1fd,0x21d,0x23d,0x25d,0x27d,0x29d, +0x2bd,0x2d8 +}; + +static const uint8_t insc_trieData[3960]={ +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0xc,0,0, +0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0xc,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0x1c,0x1c,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0xc,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,2,2,2,0x20,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23, +0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,5,5,0x22,0x22, +0x17,1,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x1f, +0x22,0x22,0,4,4,0,0,0x22,0x22,0x22,5,5,5,5,5,5, +5,5,0x23,0x23,0x22,0x22,0,0,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +0x18,0x18,0,0,0x23,0x23,0x23,0x23,0x23,0x23,5,5,5,5,5,5, +5,5,0xc,2,2,0x20,0,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0, +0,0x23,0x23,0,0,0x23,0x23,5,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,0,5,5,5,5, +5,5,5,0,5,0,0,0,5,5,5,5,0,0,0x17,1, +0x22,0x22,0x22,0x22,0x22,0,0,0x22,0x22,0,0,0x22,0x22,0x1f,6,0, +0,0,0,0,0,0,0,0x22,0,0,0,0,5,5,0,5, +0x23,0x23,0x22,0x22,0,0,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +5,5,0,0,0,0,0,0,0,0,0,0,2,0,0x1c,0, +2,2,0x20,0,0x23,0x23,0x23,0x23,0x23,0x23,0,0,0,0,0x23,0x23, +0,0,0x23,0x23,5,5,5,5,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,0,5,5,5,5,5,5,5, +0,5,5,0,5,5,0,5,5,0,0,0x17,0,0x22,0x22,0x22, +0,0,0,0,0x22,0x22,0,0,0x22,0x22,0x1f,0,0,0,4,0, +0,0,0,0,0,0,5,5,5,5,0,5,0,0,0,0, +0,0,0,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,2,0x12,0xc, +0xc,0,0xb,0,0,0,0,0,0,0,0,0,0,2,2,0x20, +0,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0,0x23,0x23,0x23,0,0x23, +0x23,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, +5,5,5,5,5,0,5,5,5,5,5,5,5,0,5,5, +0,5,5,5,5,5,0,0,0x17,1,0x22,0x22,0x22,0x22,0x22,0x22, +0,0x22,0x22,0x22,0,0x22,0x22,0x1f,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0x23,0x23,0x22,0x22,0,0, +0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0,0,0,0,0,0, +0,0,0,5,4,4,4,0x17,0x17,0x17,0,2,2,0x20,0,0x23, +0x23,0x23,0x23,0x23,0x23,0x23,0x23,0,0,0x23,0x23,0,0,0x23,0x23,5, +5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, +5,5,5,0,5,5,5,5,5,5,5,0,5,5,0,5, +5,5,5,5,0,0,0x17,1,0x22,0x22,0x22,0x22,0x22,0,0,0x22, +0x22,0,0,0x22,0x22,0x1f,0,0,0,0,0,0,0,0,0x22,0x22, +0,0,0,0,5,5,0,5,0x23,0x23,0x22,0x22,0,0,0x18,0x18, +0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0,5,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,2,0x15,0,0x23,0x23,0x23,0x23,0x23, +0x23,0,0,0,0x23,0x23,0x23,0,0x23,0x23,0x23,5,0,0,0,5, +5,0,5,0,5,5,0,0,0,5,5,0,0,0,5,5, +5,0,0,0,5,5,5,5,5,5,5,5,5,5,5,5, +0,0,0,0,0x22,0x22,0x22,0,0,0,0x22,0x22,0x22,0,0x22,0x22, +0x22,0x1f,0,0,0,0,0,0,0,0,0,0x22,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0x18,0x18,0x18,0x18,0x18,0x18, +0x18,0x18,0x18,0x18,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,2,2,2,0x20,2,0x23,0x23,0x23,0x23,0x23,0x23,0x23, +0x23,0,0x23,0x23,0x23,0,0x23,0x23,0x23,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,5,0,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,5,5,0,0, +0,1,0x22,0x22,0x22,0x22,0x22,0,0x22,0x22,0x22,0,0x22,0x22,0x22,0x1f, +0,0,0,0,0,0,0,0x22,0x22,0,5,5,5,0,0,0, +0,0,0x23,0x23,0x22,0x22,0,0,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +0x18,0x18,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,2,2,0x20,0,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0,0x23, +0x23,0x23,0,0x23,0x23,0x23,5,5,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,0,5,5,5,5,5, +5,5,5,5,5,0,5,5,5,5,5,0,0,0x17,1,0x22, +0x22,0x22,0x22,0x22,0,0x22,0x22,0x22,0,0x22,0x22,0x22,0x1f,0,0,0, +0,0,0,0,0x22,0x22,0,0,0,0,0,0,0,5,0,0x23, +0x23,0x22,0x22,0,0,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0, +0x11,0x11,0,0,0,0,0,0,0,0,0,0,0,0,0,2, +2,2,0x20,0,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0,0x23,0x23,0x23, +0,0x23,0x23,0x23,5,5,5,5,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,0x1a,0x1a,1,0x22,0x22,0x22, +0x22,0x22,0,0x22,0x22,0x22,0,0x22,0x22,0x22,0x1f,0xd,0,0,0,0, +0,6,6,6,0x22,0,0,0,0,0,0,0,0x23,0x23,0x23,0x22, +0x22,0,0,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0,0,0, +0,0,0,0,0,0,0,6,6,6,6,6,6,0,0,2, +0x20,0,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23, +0x23,0x23,0x23,0x23,0,0,0,5,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,0, +5,5,5,5,5,5,5,5,5,0,5,0,0,5,5,5, +5,5,5,5,0,0,0,0x1f,0,0,0,0,0x22,0x22,0x22,0x22, +0x22,0x22,0,0x22,0,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0,0,0, +0,0,0,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0,0,0x22, +0x22,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,0,0x22,0x22,0x22,0x22, +0x22,0x22,0x22,0x22,0x22,0x22,0x1a,0,0,0,0,0,0x22,0x22,0x22,0x22, +0x22,0x22,0,0x22,0x1e,0x1e,0x1e,0x1e,0xa,2,0x1a,0,0x18,0x18,0x18,0x18, +0x18,0x18,0x18,0x18,0x18,0x18,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,5,5,0,5, +0,0,5,5,0,5,0,0,5,0,0,0,0,0,0,5, +5,5,5,0,5,5,5,5,5,5,5,0,5,5,5,0, +5,0,5,0,0,5,5,0,5,5,0,0x22,0x22,0x22,0x22,0x22, +0x22,0x22,0x22,0x22,0x22,0,0x22,0xb,0xb,0,0,0x22,0x22,0x22,0x22,0x22, +0,0,0,0x1e,0x1e,0x1e,0x1e,0,2,0,0,0x18,0x18,0x18,0x18,0x18, +0x18,0x18,0x18,0x18,0x18,0,0,5,5,5,5,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0x18,0x18,0x18,0x18,0x18, +0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0, +0x1c,0,0x1c,0,0x17,0,0,0,0,0,0,5,5,5,5,5, +5,5,5,0,5,5,5,5,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, +5,5,5,5,5,5,5,5,0,0,0,0,0x22,0x22,0x22,0x22, +0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,2,0x20,0x22,0x22,2,2,0x1a, +1,0,0,8,8,8,8,8,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf, +0xf,0xf,0xf,0,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf, +0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf, +0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0,0,0,0,0,0,0x1c,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,5,0x23,0x23,0x23,0x23,0x23,0x23,0x23, +0x23,0x23,0x23,0x22,0x22,0x22,0x22,0x22,0x22,2,0x1e,0x20,0x13,0x1a,0xb,0xb, +0xb,0xb,5,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0,0xc,0, +0,0xc,0,5,5,0x23,0x23,0x23,0x23,0x22,0x22,0x22,0x22,5,5,5, +5,0xb,0xb,5,0x22,0x1e,0x1e,5,5,0x22,0x22,0x1e,0x1e,0x1e,0x1e,0x1e, +5,5,0x22,0x22,0x22,0x22,5,5,5,5,5,5,5,5,5,5, +5,0xb,0x22,0x22,0x22,0x22,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,5,0x1e,0x18, +0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1e,0x1e,0x22,0x22,0,0,0x23, +0x23,0x23,5,5,5,5,5,5,5,5,5,5,0,5,5,0x22, +0x22,0x1a,0,0,0,0,0,0,0,0,0,0,0,5,5,0x22, +0x22,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0x22, +0x22,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5, +0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0,0,0x22, +0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,2,0x20,0x22,0x1b,0x1b,0x1c,0x10, +0xa,0x1c,0x1c,0x1a,0x13,0x1c,0,0,0,0,0,0,0,0,1,0x1c, +0,0,0xc,5,5,5,5,5,5,5,5,5,5,5,5,5, +5,5,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0xf,0xf,0xf,0,0, +0,0,7,7,2,7,7,7,7,7,7,7,0x22,0x1c,0,0, +0,0,5,5,5,0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x21, +0,0,0x1d,0x1d,0x1d,0x1d,0x1d,0,0,0,0,0,0,0,0,0, +0,0,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22, +0x22,0x22,7,7,7,7,7,7,7,0x1e,0x1e,0,0,0,0,0, +0,5,5,5,5,5,5,5,0x22,0x22,0x22,0x22,0x22,0,0,0, +0,5,5,5,5,5,5,5,5,5,5,5,5,5,0x23,0x23, +0x23,5,5,0xb,0xb,0xf,7,7,9,0xf,0xf,0xf,0xf,0,0x13,0x22, +0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,2,0x1e, +0x1e,0x1e,0x1e,0x1e,0x1a,0x1c,0x1c,0,0,0x1c,2,2,2,0x10,0x20,0x23, +0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,5,5,5,5,0x17,0x22, +0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x1f,5,5,5,5,5, +5,5,0,0,0,0,2,0x10,0x20,0x23,0x23,0x23,0x23,0x23,0x23,0x23, +5,5,5,5,5,5,0xf,0xf,0xf,0x22,0x22,0x22,0x22,0x22,0x22,0x1a, +0x13,0xf,0xf,5,5,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,1, +5,5,5,7,7,5,5,5,5,0x23,0x23,0x17,0x22,0x22,0x22,0x22, +0x22,0x22,0x22,0x22,0x22,7,7,0x1a,0x1a,0,0,0,0,0,0,0, +0,0,0,0,0,5,5,5,5,0xf,0xf,0x22,0x22,0x22,0x22,0x22, +0x22,0x22,7,7,7,7,2,2,0x1c,0x17,0,0,0,0,0,0, +0,0,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0,0,0,5, +5,5,4,4,4,0,4,4,4,4,4,4,4,4,4,4, +4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0x20,0x20,4,0x11,0x11,4,4,4,0,0,0,0,0,0,0,0, +0,0,0,0x1c,0,0,0,0,0,0,0,0,0,0,0,0, +0x16,0x14,0,0,0xc,0xc,0xc,0xc,0xc,0,0,0,0,0,0,0, +0,0,0,0,0x1c,0x1c,0x1c,0,0,0,0,0,0,0,0,0, +0,0,0x23,0x23,0,0x23,0x23,0x23,0x1a,5,5,5,5,2,5,5, +5,5,0x22,0x22,0x22,0x22,0x22,0,0,0,0,0,0,0,0,5, +5,5,5,5,5,5,5,5,5,5,5,5,5,0x21,0x21,5, +5,5,5,0x21,0xf,0xf,5,5,5,5,5,5,5,0xf,5,2, +0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5, +0xb,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x1f,2,0,0, +0,0,0,0,0,0,0,0,4,4,4,4,4,4,4,4, +4,4,4,4,4,4,4,4,2,2,0,0,0,0,0,0, +0,0,0,0,0x23,0x22,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +5,5,5,5,5,5,0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x1e, +0x1e,0x1e,0,0,5,5,5,5,5,5,5,0x22,0x22,0x22,0x22,0x22, +0x22,0x22,0x22,7,7,7,0x1a,0,0,0,0,0,0,0,0,0, +0,0,0,2,2,0x10,0x20,0x23,0x23,0x23,0x23,0x23,5,5,5,0x23, +0x23,0x23,5,5,5,0x17,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0xf, +0xb,0xb,5,5,5,5,5,0x22,0,5,5,5,5,5,5,5, +5,5,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,5,5,5,5, +5,0,0x22,0x22,0x22,0xb,0xb,0xb,0xb,0,0,0,0,0,0,0, +0,0,7,7,7,7,7,7,7,7,7,7,7,7,7,7, +0,0,5,5,5,0xc,0xc,0xc,0,0,0,5,0x1e,0x1e,0x1e,5, +5,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22, +0x1e,0x1d,0x1e,0x1d,0,0,0,0,0,0,0,0,0,0,0,0, +0,0x23,0x23,5,5,5,5,5,5,5,5,5,0x22,0x22,0x22,0x22, +0x22,0,0,0,0,0,0x20,0x13,0,0,0,0,0,0,0,0, +0,5,5,5,5,5,5,5,5,5,5,5,5,5,5,0x23, +0x23,5,0x23,5,5,5,5,5,5,5,5,5,7,7,7,7, +7,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0,0x1e,0x1a,0,0,5,0x22, +0x22,0x22,0,0x22,0x22,0,0,0,0,0,0x22,0x22,2,0x20,5,5, +5,5,0,5,5,5,0,5,5,5,5,5,5,5,0,0, +0x17,0x17,0x17,0,0,0,0,0x13,2,2,0x20,0x11,0x11,0x23,0x23,0x23, +0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x22,0x22,0x22,0x22,0x22,0x22,0x1f,0, +0,0,0,0,0,0,0,0,3,3,3,3,3,3,3,3, +3,3,3,3,3,3,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0x19, +2,2,0x20,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,5,5,5, +0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x1f,0x17,0,0,0,0,0, +2,2,0x20,0x23,0x23,0x23,0x23,5,5,5,5,5,5,5,5,5, +0x22,0x22,0x22,0x13,0x1a,0,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +0,0,0,0,5,0x22,0x22,0,0,0,0,0,0,0,0,0, +0x21,0x21,0x21,0x21,0x21,5,5,5,5,5,5,5,5,5,5,5, +0x17,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5, +0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x1f,1,0xe, +0xe,0,0,0,0,0,0x1c,0x17,0x22,0x22,0,0,0,0x22,0x22,0x22, +0x22,2,0x1f,0x17,0x12,0,0,0,0,0,0,4,0,0x23,0x23,0x23, +0x23,5,5,5,0,5,0,5,5,5,5,0,5,5,5,5, +5,5,5,5,5,0,0,0,0,0,0,0,5,5,5,5, +5,5,5,5,5,5,5,5,5,5,5,2,0x22,0x22,0x22,0x22, +0x22,0x22,0x22,0x22,0x22,0x17,0x1a,0,0,0,0,0,2,2,2,0x20, +0,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0,0,0x23,5,0,5,5, +0,5,5,5,5,5,0,0x17,0x17,1,0x22,0x22,0,0,0,0, +0,0,0,0x22,0,0,0,0,0,0,2,2,0x23,0x23,0x22,0x22, +0,0,4,4,4,4,4,4,4,0,0,0,5,5,5,5, +5,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x1f,2,2,0x20, +0x17,1,0,0,0,0,0,0,0,0,0x18,0x18,0x18,0x18,0x18,0x18, +0x18,0x18,0x18,0x18,0,0,0,0,0x1c,0,0x23,0x23,0x23,0x23,0x23,0x23, +0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,5,2,0x20,0x1f,0x17,1,0,0, +0,0,0,0,0,0,0,0,0,0x22,0x22,0x22,0x22,0x22,0x22,0, +0,0x22,0x22,0x22,0x22,2,2,0x20,0x1f,0x17,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0x23,0x23,0x23,0x23,0x22,0x22,0, +0,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,2,0x20, +0x1f,0x22,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,5,5,5,5,5,5,5,5,5,5,5,2,0x20,0x22,0x22, +0x22,0x22,0x22,0x22,0x1f,0x17,0,0,0,0,0,0,0,0,5,5, +5,5,5,5,5,5,5,5,5,0,0,0xb,0xb,0xb,0x22,0x22, +0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x1a,0,0,0,0,0x18,0x18, +0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0,0,0,0,0x22,0x22, +0x22,0x22,0x22,0x22,0x22,2,0x20,0x1f,0x17,0,0,0,0,0,0x23,0x22, +0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,5,5,5,5,5,0x1c,0x1a, +2,2,2,2,0x20,0xe,0xb,0xb,0xb,0xb,0xc,0,0,0,0,0, +0xc,0,0x13,0,0,0,0,0,0,0,0,0x23,0x22,0x22,0x22,0x22, +0x22,0x22,0x22,0x22,0x22,0x22,0x22,5,5,5,5,0,0,0xe,0xe,0xe, +0xe,7,7,7,7,7,7,2,0x20,0x12,0x13,0,0,0,1,0, +0,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0,0x23,0x23,0x23,0x23,5, +5,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0,0x22,0x22,0x22,0x22,2,2,0x20, +0x1f,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0,0, +0,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0x22, +0x22,0x22,0x22,0x22,2,2,0,0,0,0,0,0,0,0,0,0x23, +0x23,0x23,0x23,0x23,0x23,0x23,0,0x23,0x23,0,0x23,5,5,5,5,0x22, +0x22,0x22,0x22,0x22,0x22,0,0,0,0x22,0,0x22,0x22,0,0x22,2,0x20, +0x17,0x22,0x1a,0x13,0xd,0xb,0,0,0,0,0,0,0,0,0x23,0x23, +0x23,0x23,0x23,0x23,0,0x23,0x23,0,0x23,0x23,5,5,5,5,5,5, +5,5,5,5,0x22,0x22,0x22,0x22,0x22,0,0x22,0x22,2,0x20,0x13,0, +0,0,0,0,0,0,0,5,5,0xc,0x22,0x22,0x22,0x22,0,0, +0,0,0,0,0,0,0,0 +}; + +static const UCPTrie insc_trie={ + insc_trieIndex, + { insc_trieData }, + 834, 3960, + 0x12000, 0x12, + 1, 2, + 0, 0, + 0x4, 0x40, + 0x0, +}; + +static const int32_t maxVoValue = 3; + +static const uint16_t vo_trieIndex[1100]={ +0,0x40,0x59,0x98,0,0,0,0,0,0,0,0xd0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0x33b,0x355,0x363,0x379,0x399,0x3b7,0x3d2,0x3ec,0x355,0x355,0x355,0x40c,0x355,0x355,0x355,0x40c, +0x42c,0x42c,0x42c,0x42c,0x42c,0x42c,0x42c,0x42c,0x42c,0x42c,0x42c,0x42c,0x42c,0x42c,0x42c,0x42c, +0x42c,0x42c,0x42c,0x42c,0x42c,0x42c,0x42c,0x42c,0x42c,0x42c,0x42c,0x42c,0x42c,0x42c,0x42c,0x42c, +0x42c,0x42c,0x42c,0x42c,0x42c,0x42c,0x42c,0x42c,0x42c,0x42c,0x42c,0x42c,0x355,0x355,0x355,0x40c, +0x355,0x355,0x355,0x40c,0,0x10,0x20,0x30,0x40,0x50,0x60,0x70,0x59,0x69,0x79,0x89, +0x98,0xa8,0xb8,0xc8,0,0x10,0x20,0x30,0,0x10,0x20,0x30,0,0x10,0x20,0x30, +0,0x10,0x20,0x30,0xd0,0xe0,0xf0,0x100,0,0x10,0x20,0x30,0,0x10,0x20,0x30, +0,0x10,0x20,0x30,0,0x10,0x20,0x30,0,0x10,0x20,0x30,0,0x10,0x20,0x30, +0,0x10,0x20,0x30,0,0x10,0x20,0x30,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x110, +0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x10f,0x110,0x110,0x110,0x110,0x110,0x110,0x110, +0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x110, +0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x110,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0x110,0x110,0x110,0x110,0x110,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0xa9,0x96,0x11e,0x12c,0xae,0xaa,0,0,0,0,0, +0,0x103,0x13c,0,0x14c,0x158,0x166,0x10b,0x175,0x110,0x110,0x110,0x184,0,0,0, +0,0,0,0,0x72,0,0xf6,0,0,0,0,0,0,0,0,0, +0,0,0,0x190,0x110,0x198,0,0,0,0,0x103,0x110,0x115,0,0xec,0x1a8, +0x1b6,0x10e,0x110,0x110,0x1c6,0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x110, +0x110,0x110,0,0,0,0,0,0,0,0,0,0,0x110,0x110,0x110,0x110, +0x110,0x110,0x116,0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x110, +0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x118,0x10a,0x110,0x1d2,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0x10e,0x110,0,0, +0x116,0,0,0,0,0,0x108,0x110,0x1e2,0x114,0x110,0,0,0,0,0, +0,0,0,0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x110, +0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x1f1,0x1ff,0x110,0x20e,0x21d, +0x110,0x22a,0x110,0x237,0x246,0x256,0x110,0x22a,0x110,0x237,0x261,0x110,0x110,0x26e,0x110,0x110, +0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x27e,0x110,0x110,0x110,0x110,0x110, +0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x27e,0x27e,0x27e,0x27e,0x27e, +0x286,0x110,0x28e,0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x110, +0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x110, +0x110,0x110,0x110,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0x110,0x110,0,0,0,0,0, +0,0,0,0x110,0,0x110,0x117,0x29b,0x2aa,0,0,0,0,0,0,0, +0,0,0x2ba,0x2c9,0x110,0x2d9,0x110,0x2e9,0x2f8,0,0,0,0,0,0,0, +0x308,0x318,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0x110,0x110,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x110,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0x110,0x110,0x110,0x110,0x110,0x110, +0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x110,0,0,0, +0,0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x110,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x110, +0x110,0x110,0,0,0,0,0,0,0,0,0x328,0x110,0x110,0x110,0x110,0x110, +0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x110, +0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x110,0x112,0x84,0x98,0xa8,0xa8,0xa8, +0xa8,0xa8,0xa8,0xc8,0xc,0xe8,0x100,0x115,0xc,0xc,0xc,0x134,0x153,0x172,0x191,0xc, +0x1ab,0xc,0x1cb,0x1eb,0x20b,0x223,0x223,0x223,0x223,0x223,0x223,0x223,0x223,0x223,0x223,0x223, +0x223,0x223,0x223,0x223,0x223,0x223,0x223,0x223,0x223,0x223,0x223,0x223,0x223,0x223,0x223,0x223, +0x223,0x223,0x223,0x223,0x223,0xfb,0xc,0x243,0xc,0x223,0x223,0x223,0x223,0x223,0x223,0x223, +0x223,0x223,0x223,0x223,0x223,0xc,0xc,0xc,0xc,0x223,0x223,0x223,0x223,0x223,0x223,0x223, +0x223,0x223,0x223,0x223,0x223,0x223,0xf8,0xc,0x262,0xc,0xc,0xc,0xc,0x282,0xc,0xc, +0xc,0xc,0xc,0x29c,0xc,0xc,0xfd,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc, +0xc,0x223,0x223,0x2b9,0xc,0xc,0xc,0xc,0xc,0x223,0x100,0xc,0xc,0xc,0xc,0xc, +0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0x2bc,0x223, +0x223,0x223,0x223,0x223,0x223,0x223,0x223,0xf8,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc, +0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0x2da,0xf8,0xc,0xc,0xc,0xc, +0xc,0xc,0xc,0xc,0x223,0x2fa,0xc,0xc,0x223,0xfd,0xc,0xc,0xc,0xc,0xc,0xc, +0xc,0xc,0xc,0xc,0x223,0x31a,0x223,0x223,0xc8,0x2b5,0xc,0xc,0x223,0x223,0x223,0x223, +0x223,0x223,0x223,0x223,0x223,0x223,0x223,0x223,0x223,0x223,0x223,0x223,0x223,0x223,0x223,0x223, +0x223,0x223,0x223,0x223,0x223,0x223,0x223,0x223,0x223,0x223,0x223,0x31b,0xc,0xc,0xc,0xc, +0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc, +0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc +}; + +static const uint8_t vo_trieData[828]={ +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,0,3,0,0,0,0,3,0,0,3,0,0,0,0,0, +0,0,0,0,0,3,3,3,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,3,3,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, +0,0,0,0,0,0,0,0,0,3,3,0,0,0,3,0, +0,0,0,3,3,3,0,0,0,0,0,0,3,0,3,3, +3,0,0,0,0,0,0,0,0,0,0,0,3,3,0,3, +3,3,3,3,3,3,0,0,0,0,0,3,3,0,3,3, +0,0,0,0,0,0,3,3,3,3,0,3,0,3,0,3, +0,0,0,0,3,0,0,0,0,0,3,3,3,3,3,3, +0,3,3,0,3,3,3,3,3,3,3,3,3,3,0,0, +3,3,3,3,3,3,3,3,0,0,0,0,3,3,3,3, +3,1,1,3,0,0,0,0,3,3,3,3,3,3,3,3, +3,3,3,3,3,3,0,3,3,3,3,3,3,3,3,3, +3,3,0,0,0,0,3,3,3,0,3,3,3,3,3,3, +3,3,3,3,3,3,0,0,0,0,0,0,0,0,0,0, +0,0,3,3,0,3,3,3,3,3,3,3,3,3,3,3, +3,3,2,2,3,3,3,3,3,1,1,1,1,1,1,1, +1,3,3,1,1,1,1,1,1,1,1,1,1,1,1,3, +3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,3, +2,3,2,3,2,3,2,3,3,3,3,3,3,2,3,3, +3,3,3,3,3,3,3,3,3,3,2,3,2,3,2,3, +3,3,3,3,3,2,3,3,3,3,3,2,2,3,3,3, +3,2,2,3,3,3,1,2,3,2,3,2,3,2,3,2, +3,3,3,3,3,3,2,2,3,3,3,3,3,1,3,3, +3,3,3,3,3,2,3,3,3,3,3,3,3,3,2,2, +2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,3, +3,3,3,3,3,3,3,3,3,2,2,2,2,2,3,3, +3,3,3,0,1,1,1,1,1,1,3,3,3,0,0,0, +0,3,3,3,3,3,3,3,3,3,0,2,3,3,3,3, +3,3,1,1,3,3,2,0,2,3,3,3,3,3,3,3, +3,3,3,1,1,0,0,0,2,3,3,3,3,3,3,3, +3,3,3,3,1,3,1,3,1,3,3,3,3,3,3,3, +3,3,3,3,1,1,1,1,1,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,3,3,3,1,3,3,3,3, +0,0,0,0,0,0,0,0,3,3,3,3,3,3,3,3, +3,0,0,0,3,3,0,0,2,2,3,3,3,3,3,3, +3,3,3,3,3,3,3,3,0,0,0,0 +}; + +static const UCPTrie vo_trie={ + vo_trieIndex, + { vo_trieData }, + 1100, 828, + 0x110000, 0x110, + 1, 2, + 0, 0, + 0xc, 0x0, + 0x0, +}; + +#endif // INCLUDED_FROM_UPROPS_CPP diff --git a/deps/icu-small/source/common/uloc.cpp b/deps/icu-small/source/common/uloc.cpp index 7a1dc723cff619..81b6e0f68ab88b 100644 --- a/deps/icu-small/source/common/uloc.cpp +++ b/deps/icu-small/source/common/uloc.cpp @@ -798,7 +798,7 @@ _getKeywords(const char *localeID, } keywordsLen += keywordList[i].keywordLen + 1; if(valuesToo) { - if(keywordsLen + keywordList[i].valueLen < keywordCapacity) { + if(keywordsLen + keywordList[i].valueLen <= keywordCapacity) { uprv_strncpy(keywords+keywordsLen, keywordList[i].valueStart, keywordList[i].valueLen); } keywordsLen += keywordList[i].valueLen; @@ -1133,7 +1133,7 @@ uloc_setKeywordValue(const char* keywordName, keyValuePrefix = ';'; /* for any subsequent key-value pair */ updatedKeysAndValues.append(localeKeywordNameBuffer, keyValueLen, *status); updatedKeysAndValues.append('=', *status); - updatedKeysAndValues.append(nextEqualsign, keyValueTail-nextEqualsign, *status); + updatedKeysAndValues.append(nextEqualsign, static_cast(keyValueTail-nextEqualsign), *status); } if (!nextSeparator && keywordValueLen > 0 && !handledInputKeyAndValue) { /* append new entry at the end, it sorts later than existing entries */ @@ -1500,7 +1500,7 @@ _deleteVariant(char* variants, int32_t variantsLen, } if (uprv_strncmp(variants, toDelete, toDeleteLen) == 0 && (variantsLen == toDeleteLen || - (flag=(variants[toDeleteLen] == '_')))) + (flag=(variants[toDeleteLen] == '_')) != 0)) { int32_t d = toDeleteLen + (flag?1:0); variantsLen -= d; @@ -2412,7 +2412,7 @@ uloc_acceptLanguageFromHTTP(char *result, int32_t resultAvailable, UAcceptResult /* eat spaces prior to semi */ for(t=(paramEnd-1);(paramEnd>s)&&isspace(*t);t--) ; - int32_t slen = ((t+1)-s); + int32_t slen = static_cast(((t+1)-s)); if(slen > ULOC_FULLNAME_CAPACITY) { *status = U_BUFFER_OVERFLOW_ERROR; return -1; // too big diff --git a/deps/icu-small/source/common/uloc_keytype.cpp b/deps/icu-small/source/common/uloc_keytype.cpp index 04b566a5d68b40..17ad91da01586d 100644 --- a/deps/icu-small/source/common/uloc_keytype.cpp +++ b/deps/icu-small/source/common/uloc_keytype.cpp @@ -228,7 +228,7 @@ initFromResourceBundle(UErrorCode& sts) { // a timezone key uses a colon instead of a slash in the resource. // e.g. America:Los_Angeles if (uprv_strchr(legacyTypeId, ':') != NULL) { - int32_t legacyTypeIdLen = uprv_strlen(legacyTypeId); + int32_t legacyTypeIdLen = static_cast(uprv_strlen(legacyTypeId)); char* legacyTypeIdBuf = (char*)uprv_malloc(legacyTypeIdLen + 1); if (legacyTypeIdBuf == NULL) { sts = U_MEMORY_ALLOCATION_ERROR; @@ -320,7 +320,7 @@ initFromResourceBundle(UErrorCode& sts) { if (isTZ) { // replace colon with slash if necessary if (uprv_strchr(from, ':') != NULL) { - int32_t fromLen = uprv_strlen(from); + int32_t fromLen = static_cast(uprv_strlen(from)); char* fromBuf = (char*)uprv_malloc(fromLen + 1); if (fromBuf == NULL) { sts = U_MEMORY_ALLOCATION_ERROR; @@ -472,7 +472,6 @@ isSpecialTypeRgKeyValue(const char* val) { p++; } return (subtagLen == 6); - return TRUE; } U_CFUNC const char* diff --git a/deps/icu-small/source/common/uloc_tag.cpp b/deps/icu-small/source/common/uloc_tag.cpp index f8337ec02476c4..8120331c4b91ff 100644 --- a/deps/icu-small/source/common/uloc_tag.cpp +++ b/deps/icu-small/source/common/uloc_tag.cpp @@ -12,11 +12,13 @@ #include "unicode/putil.h" #include "unicode/uloc.h" #include "ustr_imp.h" +#include "charstr.h" #include "cmemory.h" #include "cstring.h" #include "putilimp.h" #include "uinvchar.h" #include "ulocimp.h" +#include "uvector.h" #include "uassert.h" @@ -77,19 +79,34 @@ static const char LOCALE_TYPE_YES[] = "yes"; #define LANG_UND_LEN 3 +/* + Updated on 2018-09-12 from + https://www.iana.org/assignments/language-subtag-registry/language-subtag-registry . + + This table has 2 parts. The parts for Grandfathered tags is generated by the + following scripts from the IANA language tag registry. + + curl https://www.iana.org/assignments/language-subtag-registry/language-subtag-registry |\ + egrep -A 7 'Type: grandfathered' | \ + egrep 'Tag|Prefe' | grep -B1 'Preferred' | grep -v '^--' | \ + awk -n '/Tag/ {printf(" \"%s\", ", $2);} /Preferred/ {printf("\"%s\",\n", $2);}' |\ + tr 'A-Z' 'a-z' + + + The 2nd part is made of five ICU-specific entries. They're kept for + the backward compatibility for now, even though there are no preferred + values. They may have to be removed for the strict BCP 47 compliance. + +*/ static const char* const GRANDFATHERED[] = { /* grandfathered preferred */ "art-lojban", "jbo", - "cel-gaulish", "xtg-x-cel-gaulish", - "en-GB-oed", "en-GB-x-oed", + "en-gb-oed", "en-gb-oxendict", "i-ami", "ami", "i-bnn", "bnn", - "i-default", "en-x-i-default", - "i-enochian", "und-x-i-enochian", "i-hak", "hak", "i-klingon", "tlh", "i-lux", "lb", - "i-mingo", "see-x-i-mingo", "i-navajo", "nv", "i-pwn", "pwn", "i-tao", "tao", @@ -102,17 +119,175 @@ static const char* const GRANDFATHERED[] = { "sgn-ch-de", "sgg", "zh-guoyu", "cmn", "zh-hakka", "hak", - "zh-min", "nan-x-zh-min", "zh-min-nan", "nan", "zh-xiang", "hsn", - NULL, NULL + + // Grandfathered tags with no preferred value in the IANA + // registry. Kept for now for the backward compatibility + // because ICU has mapped them this way. + "cel-gaulish", "xtg-x-cel-gaulish", + "i-default", "en-x-i-default", + "i-enochian", "und-x-i-enochian", + "i-mingo", "see-x-i-mingo", + "zh-min", "nan-x-zh-min", }; +/* + Updated on 2018-09-12 from + https://www.iana.org/assignments/language-subtag-registry/language-subtag-registry . + + The table lists redundant tags with preferred value in the IANA languate tag registry. + It's generated with the following command: + + curl https://www.iana.org/assignments/language-subtag-registry/language-subtag-registry |\ + grep 'Type: redundant' -A 5 | egrep '^(Tag:|Prefer)' | grep -B1 'Preferred' | \ + awk -n '/Tag/ {printf(" \"%s\", ", $2);} /Preferred/ {printf("\"%s\",\n", $2);}' | \ + tr 'A-Z' 'a-z' + + In addition, ja-latn-hepburn-heploc is mapped to ja-latn-alalc97 because + a variant tag 'hepburn-heploc' has the preferred subtag, 'alaic97'. +*/ + +static const char* const REDUNDANT[] = { +// redundant preferred + "sgn-br", "bzs", + "sgn-co", "csn", + "sgn-de", "gsg", + "sgn-dk", "dsl", + "sgn-es", "ssp", + "sgn-fr", "fsl", + "sgn-gb", "bfi", + "sgn-gr", "gss", + "sgn-ie", "isg", + "sgn-it", "ise", + "sgn-jp", "jsl", + "sgn-mx", "mfs", + "sgn-ni", "ncs", + "sgn-nl", "dse", + "sgn-no", "nsl", + "sgn-pt", "psr", + "sgn-se", "swl", + "sgn-us", "ase", + "sgn-za", "sfs", + "zh-cmn", "cmn", + "zh-cmn-hans", "cmn-hans", + "zh-cmn-hant", "cmn-hant", + "zh-gan", "gan", + "zh-wuu", "wuu", + "zh-yue", "yue", + + // variant tag with preferred value + "ja-latn-hepburn-heploc", "ja-latn-alalc97", +}; + +/* + Updated on 2018-09-12 from + https://www.iana.org/assignments/language-subtag-registry/language-subtag-registry . + + grep 'Type: language' -A 7 language-subtag-registry | egrep 'Subtag|Prefe' | \ + grep -B1 'Preferred' | grep -v '^--' | \ + awk -n '/Subtag/ {printf(" \"%s\", ", $2);} /Preferred/ {printf("\"%s\",\n", $2);}' + + Make sure that 2-letter language subtags come before 3-letter subtags. +*/ static const char DEPRECATEDLANGS[][4] = { /* deprecated new */ + "in", "id", "iw", "he", "ji", "yi", - "in", "id" + "jw", "jv", + "mo", "ro", + "aam", "aas", + "adp", "dz", + "aue", "ktz", + "ayx", "nun", + "bgm", "bcg", + "bjd", "drl", + "ccq", "rki", + "cjr", "mom", + "cka", "cmr", + "cmk", "xch", + "coy", "pij", + "cqu", "quh", + "drh", "khk", + "drw", "prs", + "gav", "dev", + "gfx", "vaj", + "ggn", "gvr", + "gti", "nyc", + "guv", "duz", + "hrr", "jal", + "ibi", "opa", + "ilw", "gal", + "jeg", "oyb", + "kgc", "tdf", + "kgh", "kml", + "koj", "kwv", + "krm", "bmf", + "ktr", "dtp", + "kvs", "gdj", + "kwq", "yam", + "kxe", "tvd", + "kzj", "dtp", + "kzt", "dtp", + "lii", "raq", + "lmm", "rmx", + "meg", "cir", + "mst", "mry", + "mwj", "vaj", + "myt", "mry", + "nad", "xny", + "ncp", "kdz", + "nnx", "ngv", + "nts", "pij", + "oun", "vaj", + "pcr", "adx", + "pmc", "huw", + "pmu", "phr", + "ppa", "bfy", + "ppr", "lcq", + "pry", "prt", + "puz", "pub", + "sca", "hle", + "skk", "oyb", + "tdu", "dtp", + "thc", "tpo", + "thx", "oyb", + "tie", "ras", + "tkk", "twm", + "tlw", "weo", + "tmp", "tyj", + "tne", "kak", + "tnf", "prs", + "tsf", "taj", + "uok", "ema", + "xba", "cax", + "xia", "acn", + "xkh", "waw", + "xsj", "suj", + "ybd", "rki", + "yma", "lrr", + "ymt", "mtm", + "yos", "zom", + "yuu", "yug", +}; + +/* + Updated on 2018-04-24 from + + curl https://www.iana.org/assignments/language-subtag-registry/language-subtag-registry | \ + grep 'Type: region' -A 7 | egrep 'Subtag|Prefe' | \ + grep -B1 'Preferred' | \ + awk -n '/Subtag/ {printf(" \"%s\", ", $2);} /Preferred/ {printf("\"%s\",\n", $2);}' +*/ +static const char DEPRECATEDREGIONS[][3] = { +/* deprecated new */ + "BU", "MM", + "DD", "DE", + "FX", "FR", + "TP", "TL", + "YD", "YE", + "ZR", "CD", }; /* @@ -172,6 +347,46 @@ static const char* ultag_getGrandfathered(const ULanguageTag* langtag); #endif +namespace { + +// Helper class to memory manage CharString objects. +// Only ever stack-allocated, does not need to inherit UMemory. +class CharStringPool { +public: + CharStringPool() : status(U_ZERO_ERROR), pool(&deleter, nullptr, status) {} + ~CharStringPool() = default; + + CharStringPool(const CharStringPool&) = delete; + CharStringPool& operator=(const CharStringPool&) = delete; + + icu::CharString* create() { + if (U_FAILURE(status)) { + return nullptr; + } + icu::CharString* const obj = new icu::CharString; + if (obj == nullptr) { + status = U_MEMORY_ALLOCATION_ERROR; + return nullptr; + } + pool.addElement(obj, status); + if (U_FAILURE(status)) { + delete obj; + return nullptr; + } + return obj; + } + +private: + static void U_CALLCONV deleter(void* obj) { + delete static_cast(obj); + } + + UErrorCode status; + icu::UVector pool; +}; + +} // namespace + /* * ------------------------------------------------- * @@ -675,6 +890,11 @@ _appendLanguageToLanguageTag(const char* localeID, char* appendAt, int32_t capac } else { /* resolve deprecated */ for (i = 0; i < UPRV_LENGTHOF(DEPRECATEDLANGS); i += 2) { + // 2-letter deprecated subtags are listede before 3-letter + // ones in DEPRECATEDLANGS[]. Get out of loop on coming + // across the 1st 3-letter subtag, if the input is a 2-letter code. + // to avoid continuing to try when there's no match. + if (uprv_strlen(buf) < uprv_strlen(DEPRECATEDLANGS[i])) break; if (uprv_compareInvCharsAsAscii(buf, DEPRECATEDLANGS[i]) == 0) { uprv_strcpy(buf, DEPRECATEDLANGS[i + 1]); len = (int32_t)uprv_strlen(buf); @@ -721,7 +941,6 @@ _appendScriptToLanguageTag(const char* localeID, char* appendAt, int32_t capacit *(appendAt + reslen) = SEP; } reslen++; - if (reslen < capacity) { uprv_memcpy(appendAt + reslen, buf, uprv_min(len, capacity - reslen)); } @@ -763,6 +982,14 @@ _appendRegionToLanguageTag(const char* localeID, char* appendAt, int32_t capacit *(appendAt + reslen) = SEP; } reslen++; + /* resolve deprecated */ + for (int i = 0; i < UPRV_LENGTHOF(DEPRECATEDREGIONS); i += 2) { + if (uprv_compareInvCharsAsAscii(buf, DEPRECATEDREGIONS[i]) == 0) { + uprv_strcpy(buf, DEPRECATEDREGIONS[i + 1]); + len = (int32_t)uprv_strlen(buf); + break; + } + } if (reslen < capacity) { uprv_memcpy(appendAt + reslen, buf, uprv_min(len, capacity - reslen)); @@ -900,7 +1127,6 @@ _appendVariantsToLanguageTag(const char* localeID, char* appendAt, int32_t capac static int32_t _appendKeywordsToLanguageTag(const char* localeID, char* appendAt, int32_t capacity, UBool strict, UBool hadPosix, UErrorCode* status) { - char buf[ULOC_KEYWORD_AND_VALUES_CAPACITY]; char attrBuf[ULOC_KEYWORD_AND_VALUES_CAPACITY] = { 0 }; int32_t attrBufLength = 0; UEnumeration *keywordEnum = NULL; @@ -920,22 +1146,48 @@ _appendKeywordsToLanguageTag(const char* localeID, char* appendAt, int32_t capac AttributeListEntry *firstAttr = NULL; AttributeListEntry *attr; char *attrValue; - char extBuf[ULOC_KEYWORD_AND_VALUES_CAPACITY]; - char *pExtBuf = extBuf; - int32_t extBufCapacity = sizeof(extBuf); + CharStringPool extBufPool; const char *bcpKey=nullptr, *bcpValue=nullptr; UErrorCode tmpStatus = U_ZERO_ERROR; int32_t keylen; UBool isBcpUExt; while (TRUE) { + icu::CharString buf; key = uenum_next(keywordEnum, NULL, status); if (key == NULL) { break; } - len = uloc_getKeywordValue(localeID, key, buf, sizeof(buf), &tmpStatus); - /* buf must be null-terminated */ - if (U_FAILURE(tmpStatus) || tmpStatus == U_STRING_NOT_TERMINATED_WARNING) { + char* buffer; + int32_t resultCapacity = ULOC_KEYWORD_AND_VALUES_CAPACITY; + + for (;;) { + buffer = buf.getAppendBuffer( + /*minCapacity=*/resultCapacity, + /*desiredCapacityHint=*/resultCapacity, + resultCapacity, + tmpStatus); + + if (U_FAILURE(tmpStatus)) { + break; + } + + len = uloc_getKeywordValue( + localeID, key, buffer, resultCapacity, &tmpStatus); + + if (tmpStatus != U_BUFFER_OVERFLOW_ERROR) { + break; + } + + resultCapacity = len; + tmpStatus = U_ZERO_ERROR; + } + + if (U_FAILURE(tmpStatus)) { + if (tmpStatus == U_MEMORY_ALLOCATION_ERROR) { + *status = U_MEMORY_ALLOCATION_ERROR; + break; + } if (strict) { *status = U_ILLEGAL_ARGUMENT_ERROR; break; @@ -945,6 +1197,11 @@ _appendKeywordsToLanguageTag(const char* localeID, char* appendAt, int32_t capac continue; } + buf.append(buffer, len, tmpStatus); + if (tmpStatus == U_STRING_NOT_TERMINATED_WARNING) { + tmpStatus = U_ZERO_ERROR; // Terminators provided by CharString. + } + keylen = (int32_t)uprv_strlen(key); isBcpUExt = (keylen > 1); @@ -1007,7 +1264,7 @@ _appendKeywordsToLanguageTag(const char* localeID, char* appendAt, int32_t capac } /* we've checked buf is null-terminated above */ - bcpValue = uloc_toUnicodeLocaleType(key, buf); + bcpValue = uloc_toUnicodeLocaleType(key, buf.data()); if (bcpValue == NULL) { if (strict) { *status = U_ILLEGAL_ARGUMENT_ERROR; @@ -1015,33 +1272,44 @@ _appendKeywordsToLanguageTag(const char* localeID, char* appendAt, int32_t capac } continue; } - if (bcpValue == buf) { + if (bcpValue == buf.data()) { /* When uloc_toUnicodeLocaleType(key, buf) returns the input value as is, the value is well-formed, but has no known mapping. This implementation normalizes the - the value to lower case + value to lower case */ + icu::CharString* extBuf = extBufPool.create(); + if (extBuf == nullptr) { + *status = U_MEMORY_ALLOCATION_ERROR; + break; + } int32_t bcpValueLen = static_cast(uprv_strlen(bcpValue)); - if (bcpValueLen < extBufCapacity) { - uprv_strcpy(pExtBuf, bcpValue); - T_CString_toLowerCase(pExtBuf); + int32_t resultCapacity; + char* pExtBuf = extBuf->getAppendBuffer( + /*minCapacity=*/bcpValueLen, + /*desiredCapacityHint=*/bcpValueLen, + resultCapacity, + tmpStatus); + if (U_FAILURE(tmpStatus)) { + *status = tmpStatus; + break; + } - bcpValue = pExtBuf; + uprv_strcpy(pExtBuf, bcpValue); + T_CString_toLowerCase(pExtBuf); - pExtBuf += (bcpValueLen + 1); - extBufCapacity -= (bcpValueLen + 1); - } else { - if (strict) { - *status = U_ILLEGAL_ARGUMENT_ERROR; - break; - } - continue; + extBuf->append(pExtBuf, bcpValueLen, tmpStatus); + if (U_FAILURE(tmpStatus)) { + *status = tmpStatus; + break; } + + bcpValue = extBuf->data(); } } else { if (*key == PRIVATEUSE) { - if (!_isPrivateuseValueSubtags(buf, len)) { + if (!_isPrivateuseValueSubtags(buf.data(), len)) { if (strict) { *status = U_ILLEGAL_ARGUMENT_ERROR; break; @@ -1049,7 +1317,7 @@ _appendKeywordsToLanguageTag(const char* localeID, char* appendAt, int32_t capac continue; } } else { - if (!_isExtensionSingleton(key, keylen) || !_isExtensionSubtags(buf, len)) { + if (!_isExtensionSingleton(key, keylen) || !_isExtensionSubtags(buf.data(), len)) { if (strict) { *status = U_ILLEGAL_ARGUMENT_ERROR; break; @@ -1058,20 +1326,17 @@ _appendKeywordsToLanguageTag(const char* localeID, char* appendAt, int32_t capac } } bcpKey = key; - if ((len + 1) < extBufCapacity) { - uprv_memcpy(pExtBuf, buf, len); - bcpValue = pExtBuf; - - pExtBuf += len; - - *pExtBuf = 0; - pExtBuf++; - - extBufCapacity -= (len + 1); - } else { - *status = U_ILLEGAL_ARGUMENT_ERROR; + icu::CharString* extBuf = extBufPool.create(); + if (extBuf == nullptr) { + *status = U_MEMORY_ALLOCATION_ERROR; break; } + extBuf->append(buf.data(), len, tmpStatus); + if (U_FAILURE(tmpStatus)) { + *status = tmpStatus; + break; + } + bcpValue = extBuf->data(); } /* create ExtensionListEntry */ @@ -1242,6 +1507,7 @@ _appendLDMLExtensionAsKeywords(const char* ldmlext, ExtensionListEntry** appendT attrBufIdx += (len + 1); } else { *status = U_ILLEGAL_ARGUMENT_ERROR; + uprv_free(attr); goto cleanup; } @@ -1460,9 +1726,9 @@ _appendLDMLExtensionAsKeywords(const char* ldmlext, ExtensionListEntry** appendT kwd->value = pType; if (!_addExtensionToList(&kwdFirst, kwd, FALSE)) { - *status = U_ILLEGAL_ARGUMENT_ERROR; + // duplicate keyword is allowed, Only the first + // is honored. uprv_free(kwd); - goto cleanup; } } @@ -1836,7 +2102,7 @@ ultag_parse(const char* tag, int32_t tagLen, int32_t* parsedLen, UErrorCode* sta } /* check if the tag is grandfathered */ - for (i = 0; GRANDFATHERED[i] != NULL; i += 2) { + for (i = 0; i < UPRV_LENGTHOF(GRANDFATHERED); i += 2) { if (uprv_stricmp(GRANDFATHERED[i], tagBuf) == 0) { int32_t newTagLength; @@ -1858,6 +2124,37 @@ ultag_parse(const char* tag, int32_t tagLen, int32_t* parsedLen, UErrorCode* sta } } + size_t parsedLenDelta = 0; + if (grandfatheredLen == 0) { + for (i = 0; i < UPRV_LENGTHOF(REDUNDANT); i += 2) { + const char* redundantTag = REDUNDANT[i]; + size_t redundantTagLen = uprv_strlen(redundantTag); + // The preferred tag for a redundant tag is always shorter than redundant + // tag. A redundant tag may or may not be followed by other subtags. + // (i.e. "zh-yue" or "zh-yue-u-co-pinyin"). + if (uprv_strnicmp(redundantTag, tagBuf, static_cast(redundantTagLen)) == 0) { + const char* redundantTagEnd = tagBuf + redundantTagLen; + if (*redundantTagEnd == '\0' || *redundantTagEnd == SEP) { + const char* preferredTag = REDUNDANT[i + 1]; + size_t preferredTagLen = uprv_strlen(preferredTag); + uprv_strncpy(t->buf, preferredTag, preferredTagLen); + if (*redundantTagEnd == SEP) { + uprv_memmove(tagBuf + preferredTagLen, + redundantTagEnd, + tagLen - redundantTagLen + 1); + } else { + tagBuf[preferredTagLen] = '\0'; + } + // parsedLen should be the length of the input + // before redundantTag is replaced by preferredTag. + // Save the delta to add it back later. + parsedLenDelta = redundantTagLen - preferredTagLen; + break; + } + } + } + } + /* * langtag = language * ["-" script] @@ -1898,10 +2195,13 @@ ultag_parse(const char* tag, int32_t tagLen, int32_t* parsedLen, UErrorCode* sta if (next & LANG) { if (_isLanguageSubtag(pSubtag, subtagLen)) { *pSep = 0; /* terminate */ + // TODO: move deprecated language code handling here. t->language = T_CString_toLowerCase(pSubtag); pLastGoodPosition = pSep; - next = EXTL | SCRT | REGN | VART | EXTS | PRIV; + next = SCRT | REGN | VART | EXTS | PRIV; + if (subtagLen <= 3) + next |= EXTL; continue; } } @@ -1942,6 +2242,7 @@ ultag_parse(const char* tag, int32_t tagLen, int32_t* parsedLen, UErrorCode* sta if (next & REGN) { if (_isRegionSubtag(pSubtag, subtagLen)) { *pSep = 0; + // TODO: move deprecated region code handling here. t->region = T_CString_toUpperCase(pSubtag); pLastGoodPosition = pSep; @@ -2035,7 +2336,7 @@ ultag_parse(const char* tag, int32_t tagLen, int32_t* parsedLen, UErrorCode* sta } } if (next & PRIV) { - if (uprv_tolower(*pSubtag) == PRIVATEUSE) { + if (uprv_tolower(*pSubtag) == PRIVATEUSE && subtagLen == 1) { char *pPrivuseVal; if (pExtension != NULL) { @@ -2138,7 +2439,8 @@ ultag_parse(const char* tag, int32_t tagLen, int32_t* parsedLen, UErrorCode* sta } if (parsedLen != NULL) { - *parsedLen = (grandfatheredLen > 0) ? grandfatheredLen : (int32_t)(pLastGoodPosition - t->buf); + *parsedLen = (grandfatheredLen > 0) ? grandfatheredLen : + (int32_t)(pLastGoodPosition - t->buf + parsedLenDelta); } return t; @@ -2335,31 +2637,66 @@ uloc_toLanguageTag(const char* localeID, int32_t langtagCapacity, UBool strict, UErrorCode* status) { - /* char canonical[ULOC_FULLNAME_CAPACITY]; */ /* See #6822 */ - char canonical[256]; - int32_t reslen = 0; + icu::CharString canonical; + int32_t reslen; UErrorCode tmpStatus = U_ZERO_ERROR; UBool hadPosix = FALSE; const char* pKeywordStart; /* Note: uloc_canonicalize returns "en_US_POSIX" for input locale ID "". See #6835 */ - canonical[0] = 0; - if (uprv_strlen(localeID) > 0) { - uloc_canonicalize(localeID, canonical, sizeof(canonical), &tmpStatus); - if (tmpStatus != U_ZERO_ERROR) { + int32_t resultCapacity = static_cast(uprv_strlen(localeID)); + if (resultCapacity > 0) { + char* buffer; + + for (;;) { + buffer = canonical.getAppendBuffer( + /*minCapacity=*/resultCapacity, + /*desiredCapacityHint=*/resultCapacity, + resultCapacity, + tmpStatus); + + if (U_FAILURE(tmpStatus)) { + *status = tmpStatus; + return 0; + } + + reslen = + uloc_canonicalize(localeID, buffer, resultCapacity, &tmpStatus); + + if (tmpStatus != U_BUFFER_OVERFLOW_ERROR) { + break; + } + + resultCapacity = reslen; + tmpStatus = U_ZERO_ERROR; + } + + if (U_FAILURE(tmpStatus)) { *status = U_ILLEGAL_ARGUMENT_ERROR; return 0; } + + canonical.append(buffer, reslen, tmpStatus); + if (tmpStatus == U_STRING_NOT_TERMINATED_WARNING) { + tmpStatus = U_ZERO_ERROR; // Terminators provided by CharString. + } + + if (U_FAILURE(tmpStatus)) { + *status = tmpStatus; + return 0; + } } + reslen = 0; + /* For handling special case - private use only tag */ - pKeywordStart = locale_getKeywordsStart(canonical); - if (pKeywordStart == canonical) { + pKeywordStart = locale_getKeywordsStart(canonical.data()); + if (pKeywordStart == canonical.data()) { UEnumeration *kwdEnum; int kwdCnt = 0; UBool done = FALSE; - kwdEnum = uloc_openKeywords((const char*)canonical, &tmpStatus); + kwdEnum = uloc_openKeywords(canonical.data(), &tmpStatus); if (kwdEnum != NULL) { kwdCnt = uenum_count(kwdEnum, &tmpStatus); if (kwdCnt == 1) { @@ -2397,12 +2734,12 @@ uloc_toLanguageTag(const char* localeID, } } - reslen += _appendLanguageToLanguageTag(canonical, langtag, langtagCapacity, strict, status); - reslen += _appendScriptToLanguageTag(canonical, langtag + reslen, langtagCapacity - reslen, strict, status); - reslen += _appendRegionToLanguageTag(canonical, langtag + reslen, langtagCapacity - reslen, strict, status); - reslen += _appendVariantsToLanguageTag(canonical, langtag + reslen, langtagCapacity - reslen, strict, &hadPosix, status); - reslen += _appendKeywordsToLanguageTag(canonical, langtag + reslen, langtagCapacity - reslen, strict, hadPosix, status); - reslen += _appendPrivateuseToLanguageTag(canonical, langtag + reslen, langtagCapacity - reslen, strict, hadPosix, status); + reslen += _appendLanguageToLanguageTag(canonical.data(), langtag, langtagCapacity, strict, status); + reslen += _appendScriptToLanguageTag(canonical.data(), langtag + reslen, langtagCapacity - reslen, strict, status); + reslen += _appendRegionToLanguageTag(canonical.data(), langtag + reslen, langtagCapacity - reslen, strict, status); + reslen += _appendVariantsToLanguageTag(canonical.data(), langtag + reslen, langtagCapacity - reslen, strict, &hadPosix, status); + reslen += _appendKeywordsToLanguageTag(canonical.data(), langtag + reslen, langtagCapacity - reslen, strict, hadPosix, status); + reslen += _appendPrivateuseToLanguageTag(canonical.data(), langtag + reslen, langtagCapacity - reslen, strict, hadPosix, status); return reslen; } @@ -2414,6 +2751,23 @@ uloc_forLanguageTag(const char* langtag, int32_t localeIDCapacity, int32_t* parsedLength, UErrorCode* status) { + return ulocimp_forLanguageTag( + langtag, + -1, + localeID, + localeIDCapacity, + parsedLength, + status); +} + + +U_CAPI int32_t U_EXPORT2 +ulocimp_forLanguageTag(const char* langtag, + int32_t tagLen, + char* localeID, + int32_t localeIDCapacity, + int32_t* parsedLength, + UErrorCode* status) { ULanguageTag *lt; int32_t reslen = 0; const char *subtag, *p; @@ -2421,7 +2775,7 @@ uloc_forLanguageTag(const char* langtag, int32_t i, n; UBool noRegion = TRUE; - lt = ultag_parse(langtag, -1, parsedLength, status); + lt = ultag_parse(langtag, tagLen, parsedLength, status); if (U_FAILURE(*status)) { return 0; } diff --git a/deps/icu-small/source/common/ulocimp.h b/deps/icu-small/source/common/ulocimp.h index 855f9235dc636f..6dd8e33e09c88c 100644 --- a/deps/icu-small/source/common/ulocimp.h +++ b/deps/icu-small/source/common/ulocimp.h @@ -61,6 +61,38 @@ ulocimp_getCountry(const char *localeID, char *country, int32_t countryCapacity, const char **pEnd); +/** + * Returns a locale ID for the specified BCP47 language tag string. + * If the specified language tag contains any ill-formed subtags, + * the first such subtag and all following subtags are ignored. + *

+ * This implements the 'Language-Tag' production of BCP47, and so + * supports grandfathered (regular and irregular) as well as private + * use language tags. Private use tags are represented as 'x-whatever', + * and grandfathered tags are converted to their canonical replacements + * where they exist. Note that a few grandfathered tags have no modern + * replacement, these will be converted using the fallback described in + * the first paragraph, so some information might be lost. + * @param langtag the input BCP47 language tag. + * @param tagLen the length of langtag, or -1 to call uprv_strlen(). + * @param localeID the output buffer receiving a locale ID for the + * specified BCP47 language tag. + * @param localeIDCapacity the size of the locale ID output buffer. + * @param parsedLength if not NULL, successfully parsed length + * for the input language tag is set. + * @param err error information if receiving the locald ID + * failed. + * @return the length of the locale ID. + * @internal ICU 63 + */ +U_CAPI int32_t U_EXPORT2 +ulocimp_forLanguageTag(const char* langtag, + int32_t tagLen, + char* localeID, + int32_t localeIDCapacity, + int32_t* parsedLength, + UErrorCode* err); + /** * Get the region to use for supplemental data lookup. Uses * (1) any region specified by locale tag "rg"; if none then diff --git a/deps/icu-small/source/common/umapfile.cpp b/deps/icu-small/source/common/umapfile.cpp index 5084913cbf742a..a32573bbf70c95 100644 --- a/deps/icu-small/source/common/umapfile.cpp +++ b/deps/icu-small/source/common/umapfile.cpp @@ -22,6 +22,7 @@ #include "uposixdefs.h" #include "unicode/putil.h" +#include "unicode/ustring.h" #include "udatamem.h" #include "umapfile.h" @@ -64,7 +65,7 @@ # include "unicode/udata.h" # define LIB_PREFIX "lib" # define LIB_SUFFIX ".dll" - /* This is inconvienient until we figure out what to do with U_ICUDATA_NAME in utypes.h */ + /* This is inconvenient until we figure out what to do with U_ICUDATA_NAME in utypes.h */ # define U_ICUDATA_ENTRY_NAME "icudt" U_ICU_VERSION_SHORT U_LIB_SUFFIX_C_NAME_STRING "_dat" # endif #elif MAP_IMPLEMENTATION==MAP_STDIO @@ -84,7 +85,10 @@ *----------------------------------------------------------------------------*/ #if MAP_IMPLEMENTATION==MAP_NONE U_CFUNC UBool - uprv_mapFile(UDataMemory *pData, const char *path) { + uprv_mapFile(UDataMemory *pData, const char *path, UErrorCode *status) { + if (U_FAILURE(*status)) { + return FALSE; + } UDataMemory_init(pData); /* Clear the output struct. */ return FALSE; /* no file access */ } @@ -97,12 +101,17 @@ uprv_mapFile( UDataMemory *pData, /* Fill in with info on the result doing the mapping. */ /* Output only; any original contents are cleared. */ - const char *path /* File path to be opened/mapped */ + const char *path, /* File path to be opened/mapped. */ + UErrorCode *status /* Error status, used to report out-of-memory errors. */ ) { HANDLE map; HANDLE file; + if (U_FAILURE(*status)) { + return FALSE; + } + UDataMemory_init(pData); /* Clear the output struct. */ /* open the input file */ @@ -111,28 +120,29 @@ OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL|FILE_FLAG_RANDOM_ACCESS, NULL); #else - // First we need to go from char to UTF-16 - // u_UCharsToChars could work but it requires length. - WCHAR utf16Path[MAX_PATH]; - int32_t i; - for (i = 0; i < UPRV_LENGTHOF(utf16Path); i++) - { - utf16Path[i] = path[i]; - if (path[i] == '\0') - { - break; - } + // Convert from UTF-8 string to UTF-16 string. + wchar_t utf16Path[MAX_PATH]; + int32_t pathUtf16Len = 0; + u_strFromUTF8(reinterpret_cast(utf16Path), static_cast(UPRV_LENGTHOF(utf16Path)), &pathUtf16Len, path, -1, status); + + if (U_FAILURE(*status)) { + return FALSE; } - if (i >= UPRV_LENGTHOF(utf16Path)) - { - // Ran out of room, unlikely but be safe - utf16Path[UPRV_LENGTHOF(utf16Path) - 1] = '\0'; + if (*status == U_STRING_NOT_TERMINATED_WARNING) { + // Report back an error instead of a warning. + *status = U_BUFFER_OVERFLOW_ERROR; + return FALSE; } // TODO: Is it worth setting extended parameters to specify random access? file = CreateFile2(utf16Path, GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING, NULL); #endif - if(file==INVALID_HANDLE_VALUE) { + if (file == INVALID_HANDLE_VALUE) { + // If we failed to open the file due to an out-of-memory error, then we want + // to report that error back to the caller. + if (HRESULT_FROM_WIN32(GetLastError()) == E_OUTOFMEMORY) { + *status = U_MEMORY_ALLOCATION_ERROR; + } return FALSE; } @@ -165,7 +175,12 @@ map = CreateFileMappingFromApp(file, NULL, PAGE_READONLY, 0, NULL); #endif CloseHandle(file); - if(map==NULL) { + if (map == NULL) { + // If we failed to create the mapping due to an out-of-memory error, then + // we want to report that error back to the caller. + if (HRESULT_FROM_WIN32(GetLastError()) == E_OUTOFMEMORY) { + *status = U_MEMORY_ALLOCATION_ERROR; + } return FALSE; } @@ -193,12 +208,16 @@ #elif MAP_IMPLEMENTATION==MAP_POSIX U_CFUNC UBool - uprv_mapFile(UDataMemory *pData, const char *path) { + uprv_mapFile(UDataMemory *pData, const char *path, UErrorCode *status) { int fd; int length; struct stat mystat; void *data; + if (U_FAILURE(*status)) { + return FALSE; + } + UDataMemory_init(pData); /* Clear the output struct. */ /* determine the length of the file */ @@ -221,6 +240,7 @@ #endif close(fd); /* no longer needed */ if(data==MAP_FAILED) { + // Possibly check the errno value for ENOMEM, and report U_MEMORY_ALLOCATION_ERROR? return FALSE; } @@ -263,11 +283,15 @@ } U_CFUNC UBool - uprv_mapFile(UDataMemory *pData, const char *path) { + uprv_mapFile(UDataMemory *pData, const char *path, UErrorCode *status) { FILE *file; int32_t fileLength; void *p; + if (U_FAILURE(*status)) { + return FALSE; + } + UDataMemory_init(pData); /* Clear the output struct. */ /* open the input file */ file=fopen(path, "rb"); @@ -286,6 +310,7 @@ p=uprv_malloc(fileLength); if(p==NULL) { fclose(file); + *status = U_MEMORY_ALLOCATION_ERROR; return FALSE; } @@ -351,7 +376,7 @@ * * TODO: This works the way ICU historically has, but the * whole data fallback search path is so complicated that - * proabably almost no one will ever really understand it, + * probably almost no one will ever really understand it, * the potential for confusion is large. (It's not just * this one function, but the whole scheme.) * @@ -391,7 +416,7 @@ # define DATA_TYPE "dat" - U_CFUNC UBool uprv_mapFile(UDataMemory *pData, const char *path) { + U_CFUNC UBool uprv_mapFile(UDataMemory *pData, const char *path, UErrorCode *status) { const char *inBasename; char *basename; char pathBuffer[1024]; @@ -399,6 +424,10 @@ dllhandle *handle; void *val=0; + if (U_FAILURE(*status)) { + return FALSE; + } + inBasename=uprv_strrchr(path, U_FILE_SEP_CHAR); if(inBasename==NULL) { inBasename = path; @@ -430,6 +459,7 @@ data=mmap(0, length, PROT_READ, MAP_PRIVATE, fd, 0); close(fd); /* no longer needed */ if(data==MAP_FAILED) { + // Possibly check the errorno value for ENOMEM, and report U_MEMORY_ALLOCATION_ERROR? return FALSE; } pData->map = (char *)data + length; diff --git a/deps/icu-small/source/common/umapfile.h b/deps/icu-small/source/common/umapfile.h index 24e476b11e93d0..92bd567a2a9895 100644 --- a/deps/icu-small/source/common/umapfile.h +++ b/deps/icu-small/source/common/umapfile.h @@ -29,7 +29,7 @@ #include "unicode/udata.h" #include "putilimp.h" -U_CFUNC UBool uprv_mapFile(UDataMemory *pdm, const char *path); +U_CFUNC UBool uprv_mapFile(UDataMemory *pdm, const char *path, UErrorCode *status); U_CFUNC void uprv_unmapFile(UDataMemory *pData); /* MAP_NONE: no memory mapping, no file access at all */ diff --git a/deps/icu-small/source/common/umutablecptrie.cpp b/deps/icu-small/source/common/umutablecptrie.cpp new file mode 100644 index 00000000000000..40af4b6c16a163 --- /dev/null +++ b/deps/icu-small/source/common/umutablecptrie.cpp @@ -0,0 +1,1678 @@ +// © 2017 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html + +// umutablecptrie.cpp (inspired by utrie2_builder.cpp) +// created: 2017dec29 Markus W. Scherer + +// #define UCPTRIE_DEBUG +#ifdef UCPTRIE_DEBUG +# include +#endif + +#include "unicode/utypes.h" +#include "unicode/ucptrie.h" +#include "unicode/umutablecptrie.h" +#include "unicode/uobject.h" +#include "unicode/utf16.h" +#include "cmemory.h" +#include "uassert.h" +#include "ucptrie_impl.h" + +U_NAMESPACE_BEGIN + +namespace { + +constexpr int32_t MAX_UNICODE = 0x10ffff; + +constexpr int32_t UNICODE_LIMIT = 0x110000; +constexpr int32_t BMP_LIMIT = 0x10000; +constexpr int32_t ASCII_LIMIT = 0x80; + +constexpr int32_t I_LIMIT = UNICODE_LIMIT >> UCPTRIE_SHIFT_3; +constexpr int32_t BMP_I_LIMIT = BMP_LIMIT >> UCPTRIE_SHIFT_3; +constexpr int32_t ASCII_I_LIMIT = ASCII_LIMIT >> UCPTRIE_SHIFT_3; + +constexpr int32_t SMALL_DATA_BLOCKS_PER_BMP_BLOCK = (1 << (UCPTRIE_FAST_SHIFT - UCPTRIE_SHIFT_3)); + +// Flag values for data blocks. +constexpr uint8_t ALL_SAME = 0; +constexpr uint8_t MIXED = 1; +constexpr uint8_t SAME_AS = 2; + +/** Start with allocation of 16k data entries. */ +constexpr int32_t INITIAL_DATA_LENGTH = ((int32_t)1 << 14); + +/** Grow about 8x each time. */ +constexpr int32_t MEDIUM_DATA_LENGTH = ((int32_t)1 << 17); + +/** + * Maximum length of the build-time data array. + * One entry per 0x110000 code points. + */ +constexpr int32_t MAX_DATA_LENGTH = UNICODE_LIMIT; + +// Flag values for index-3 blocks while compacting/building. +constexpr uint8_t I3_NULL = 0; +constexpr uint8_t I3_BMP = 1; +constexpr uint8_t I3_16 = 2; +constexpr uint8_t I3_18 = 3; + +constexpr int32_t INDEX_3_18BIT_BLOCK_LENGTH = UCPTRIE_INDEX_3_BLOCK_LENGTH + UCPTRIE_INDEX_3_BLOCK_LENGTH / 8; + +class AllSameBlocks; + +class MutableCodePointTrie : public UMemory { +public: + MutableCodePointTrie(uint32_t initialValue, uint32_t errorValue, UErrorCode &errorCode); + MutableCodePointTrie(const MutableCodePointTrie &other, UErrorCode &errorCode); + MutableCodePointTrie(const MutableCodePointTrie &other) = delete; + ~MutableCodePointTrie(); + + MutableCodePointTrie &operator=(const MutableCodePointTrie &other) = delete; + + static MutableCodePointTrie *fromUCPMap(const UCPMap *map, UErrorCode &errorCode); + static MutableCodePointTrie *fromUCPTrie(const UCPTrie *trie, UErrorCode &errorCode); + + uint32_t get(UChar32 c) const; + int32_t getRange(UChar32 start, UCPMapValueFilter *filter, const void *context, + uint32_t *pValue) const; + + void set(UChar32 c, uint32_t value, UErrorCode &errorCode); + void setRange(UChar32 start, UChar32 end, uint32_t value, UErrorCode &errorCode); + + UCPTrie *build(UCPTrieType type, UCPTrieValueWidth valueWidth, UErrorCode &errorCode); + +private: + void clear(); + + bool ensureHighStart(UChar32 c); + int32_t allocDataBlock(int32_t blockLength); + int32_t getDataBlock(int32_t i); + + void maskValues(uint32_t mask); + UChar32 findHighStart() const; + int32_t compactWholeDataBlocks(int32_t fastILimit, AllSameBlocks &allSameBlocks); + int32_t compactData(int32_t fastILimit, uint32_t *newData, int32_t dataNullIndex); + int32_t compactIndex(int32_t fastILimit, UErrorCode &errorCode); + int32_t compactTrie(int32_t fastILimit, UErrorCode &errorCode); + + uint32_t *index = nullptr; + int32_t indexCapacity = 0; + int32_t index3NullOffset = -1; + uint32_t *data = nullptr; + int32_t dataCapacity = 0; + int32_t dataLength = 0; + int32_t dataNullOffset = -1; + + uint32_t origInitialValue; + uint32_t initialValue; + uint32_t errorValue; + UChar32 highStart; + uint32_t highValue; +#ifdef UCPTRIE_DEBUG +public: + const char *name; +#endif +private: + /** Temporary array while building the final data. */ + uint16_t *index16 = nullptr; + uint8_t flags[UNICODE_LIMIT >> UCPTRIE_SHIFT_3]; +}; + +MutableCodePointTrie::MutableCodePointTrie(uint32_t iniValue, uint32_t errValue, UErrorCode &errorCode) : + origInitialValue(iniValue), initialValue(iniValue), errorValue(errValue), + highStart(0), highValue(initialValue) +#ifdef UCPTRIE_DEBUG + , name("open") +#endif + { + if (U_FAILURE(errorCode)) { return; } + index = (uint32_t *)uprv_malloc(BMP_I_LIMIT * 4); + data = (uint32_t *)uprv_malloc(INITIAL_DATA_LENGTH * 4); + if (index == nullptr || data == nullptr) { + errorCode = U_MEMORY_ALLOCATION_ERROR; + return; + } + indexCapacity = BMP_I_LIMIT; + dataCapacity = INITIAL_DATA_LENGTH; +} + +MutableCodePointTrie::MutableCodePointTrie(const MutableCodePointTrie &other, UErrorCode &errorCode) : + index3NullOffset(other.index3NullOffset), + dataNullOffset(other.dataNullOffset), + origInitialValue(other.origInitialValue), initialValue(other.initialValue), + errorValue(other.errorValue), + highStart(other.highStart), highValue(other.highValue) +#ifdef UCPTRIE_DEBUG + , name("mutable clone") +#endif + { + if (U_FAILURE(errorCode)) { return; } + int32_t iCapacity = highStart <= BMP_LIMIT ? BMP_I_LIMIT : I_LIMIT; + index = (uint32_t *)uprv_malloc(iCapacity * 4); + data = (uint32_t *)uprv_malloc(other.dataCapacity * 4); + if (index == nullptr || data == nullptr) { + errorCode = U_MEMORY_ALLOCATION_ERROR; + return; + } + indexCapacity = iCapacity; + dataCapacity = other.dataCapacity; + + int32_t iLimit = highStart >> UCPTRIE_SHIFT_3; + uprv_memcpy(flags, other.flags, iLimit); + uprv_memcpy(index, other.index, iLimit * 4); + uprv_memcpy(data, other.data, (size_t)other.dataLength * 4); + dataLength = other.dataLength; + U_ASSERT(other.index16 == nullptr); +} + +MutableCodePointTrie::~MutableCodePointTrie() { + uprv_free(index); + uprv_free(data); + uprv_free(index16); +} + +MutableCodePointTrie *MutableCodePointTrie::fromUCPMap(const UCPMap *map, UErrorCode &errorCode) { + // Use the highValue as the initialValue to reduce the highStart. + uint32_t errorValue = ucpmap_get(map, -1); + uint32_t initialValue = ucpmap_get(map, 0x10ffff); + LocalPointer mutableTrie( + new MutableCodePointTrie(initialValue, errorValue, errorCode), + errorCode); + if (U_FAILURE(errorCode)) { + return nullptr; + } + UChar32 start = 0, end; + uint32_t value; + while ((end = ucpmap_getRange(map, start, UCPMAP_RANGE_NORMAL, 0, + nullptr, nullptr, &value)) >= 0) { + if (value != initialValue) { + if (start == end) { + mutableTrie->set(start, value, errorCode); + } else { + mutableTrie->setRange(start, end, value, errorCode); + } + } + start = end + 1; + } + if (U_SUCCESS(errorCode)) { + return mutableTrie.orphan(); + } else { + return nullptr; + } +} + +MutableCodePointTrie *MutableCodePointTrie::fromUCPTrie(const UCPTrie *trie, UErrorCode &errorCode) { + // Use the highValue as the initialValue to reduce the highStart. + uint32_t errorValue; + uint32_t initialValue; + switch (trie->valueWidth) { + case UCPTRIE_VALUE_BITS_16: + errorValue = trie->data.ptr16[trie->dataLength - UCPTRIE_ERROR_VALUE_NEG_DATA_OFFSET]; + initialValue = trie->data.ptr16[trie->dataLength - UCPTRIE_HIGH_VALUE_NEG_DATA_OFFSET]; + break; + case UCPTRIE_VALUE_BITS_32: + errorValue = trie->data.ptr32[trie->dataLength - UCPTRIE_ERROR_VALUE_NEG_DATA_OFFSET]; + initialValue = trie->data.ptr32[trie->dataLength - UCPTRIE_HIGH_VALUE_NEG_DATA_OFFSET]; + break; + case UCPTRIE_VALUE_BITS_8: + errorValue = trie->data.ptr8[trie->dataLength - UCPTRIE_ERROR_VALUE_NEG_DATA_OFFSET]; + initialValue = trie->data.ptr8[trie->dataLength - UCPTRIE_HIGH_VALUE_NEG_DATA_OFFSET]; + break; + default: + // Unreachable if the trie is properly initialized. + errorCode = U_ILLEGAL_ARGUMENT_ERROR; + return nullptr; + } + LocalPointer mutableTrie( + new MutableCodePointTrie(initialValue, errorValue, errorCode), + errorCode); + if (U_FAILURE(errorCode)) { + return nullptr; + } + UChar32 start = 0, end; + uint32_t value; + while ((end = ucptrie_getRange(trie, start, UCPMAP_RANGE_NORMAL, 0, + nullptr, nullptr, &value)) >= 0) { + if (value != initialValue) { + if (start == end) { + mutableTrie->set(start, value, errorCode); + } else { + mutableTrie->setRange(start, end, value, errorCode); + } + } + start = end + 1; + } + if (U_SUCCESS(errorCode)) { + return mutableTrie.orphan(); + } else { + return nullptr; + } +} + +void MutableCodePointTrie::clear() { + index3NullOffset = dataNullOffset = -1; + dataLength = 0; + highValue = initialValue = origInitialValue; + highStart = 0; + uprv_free(index16); + index16 = nullptr; +} + +uint32_t MutableCodePointTrie::get(UChar32 c) const { + if ((uint32_t)c > MAX_UNICODE) { + return errorValue; + } + if (c >= highStart) { + return highValue; + } + int32_t i = c >> UCPTRIE_SHIFT_3; + if (flags[i] == ALL_SAME) { + return index[i]; + } else { + return data[index[i] + (c & UCPTRIE_SMALL_DATA_MASK)]; + } +} + +inline uint32_t maybeFilterValue(uint32_t value, uint32_t initialValue, uint32_t nullValue, + UCPMapValueFilter *filter, const void *context) { + if (value == initialValue) { + value = nullValue; + } else if (filter != nullptr) { + value = filter(context, value); + } + return value; +} + +UChar32 MutableCodePointTrie::getRange( + UChar32 start, UCPMapValueFilter *filter, const void *context, + uint32_t *pValue) const { + if ((uint32_t)start > MAX_UNICODE) { + return U_SENTINEL; + } + if (start >= highStart) { + if (pValue != nullptr) { + uint32_t value = highValue; + if (filter != nullptr) { value = filter(context, value); } + *pValue = value; + } + return MAX_UNICODE; + } + uint32_t nullValue = initialValue; + if (filter != nullptr) { nullValue = filter(context, nullValue); } + UChar32 c = start; + uint32_t value; + bool haveValue = false; + int32_t i = c >> UCPTRIE_SHIFT_3; + do { + if (flags[i] == ALL_SAME) { + uint32_t value2 = maybeFilterValue(index[i], initialValue, nullValue, + filter, context); + if (haveValue) { + if (value2 != value) { + return c - 1; + } + } else { + value = value2; + if (pValue != nullptr) { *pValue = value; } + haveValue = true; + } + c = (c + UCPTRIE_SMALL_DATA_BLOCK_LENGTH) & ~UCPTRIE_SMALL_DATA_MASK; + } else /* MIXED */ { + int32_t di = index[i] + (c & UCPTRIE_SMALL_DATA_MASK); + uint32_t value2 = maybeFilterValue(data[di], initialValue, nullValue, + filter, context); + if (haveValue) { + if (value2 != value) { + return c - 1; + } + } else { + value = value2; + if (pValue != nullptr) { *pValue = value; } + haveValue = true; + } + while ((++c & UCPTRIE_SMALL_DATA_MASK) != 0) { + if (maybeFilterValue(data[++di], initialValue, nullValue, + filter, context) != value) { + return c - 1; + } + } + } + ++i; + } while (c < highStart); + U_ASSERT(haveValue); + if (maybeFilterValue(highValue, initialValue, nullValue, + filter, context) != value) { + return c - 1; + } else { + return MAX_UNICODE; + } +} + +void +writeBlock(uint32_t *block, uint32_t value) { + uint32_t *limit = block + UCPTRIE_SMALL_DATA_BLOCK_LENGTH; + while (block < limit) { + *block++ = value; + } +} + +bool MutableCodePointTrie::ensureHighStart(UChar32 c) { + if (c >= highStart) { + // Round up to a UCPTRIE_CP_PER_INDEX_2_ENTRY boundary to simplify compaction. + c = (c + UCPTRIE_CP_PER_INDEX_2_ENTRY) & ~(UCPTRIE_CP_PER_INDEX_2_ENTRY - 1); + int32_t i = highStart >> UCPTRIE_SHIFT_3; + int32_t iLimit = c >> UCPTRIE_SHIFT_3; + if (iLimit > indexCapacity) { + uint32_t *newIndex = (uint32_t *)uprv_malloc(I_LIMIT * 4); + if (newIndex == nullptr) { return false; } + uprv_memcpy(newIndex, index, i * 4); + uprv_free(index); + index = newIndex; + indexCapacity = I_LIMIT; + } + do { + flags[i] = ALL_SAME; + index[i] = initialValue; + } while(++i < iLimit); + highStart = c; + } + return true; +} + +int32_t MutableCodePointTrie::allocDataBlock(int32_t blockLength) { + int32_t newBlock = dataLength; + int32_t newTop = newBlock + blockLength; + if (newTop > dataCapacity) { + int32_t capacity; + if (dataCapacity < MEDIUM_DATA_LENGTH) { + capacity = MEDIUM_DATA_LENGTH; + } else if (dataCapacity < MAX_DATA_LENGTH) { + capacity = MAX_DATA_LENGTH; + } else { + // Should never occur. + // Either MAX_DATA_LENGTH is incorrect, + // or the code writes more values than should be possible. + return -1; + } + uint32_t *newData = (uint32_t *)uprv_malloc(capacity * 4); + if (newData == nullptr) { + return -1; + } + uprv_memcpy(newData, data, (size_t)dataLength * 4); + uprv_free(data); + data = newData; + dataCapacity = capacity; + } + dataLength = newTop; + return newBlock; +} + +/** + * No error checking for illegal arguments. + * + * @return -1 if no new data block available (out of memory in data array) + * @internal + */ +int32_t MutableCodePointTrie::getDataBlock(int32_t i) { + if (flags[i] == MIXED) { + return index[i]; + } + if (i < BMP_I_LIMIT) { + int32_t newBlock = allocDataBlock(UCPTRIE_FAST_DATA_BLOCK_LENGTH); + if (newBlock < 0) { return newBlock; } + int32_t iStart = i & ~(SMALL_DATA_BLOCKS_PER_BMP_BLOCK -1); + int32_t iLimit = iStart + SMALL_DATA_BLOCKS_PER_BMP_BLOCK; + do { + U_ASSERT(flags[iStart] == ALL_SAME); + writeBlock(data + newBlock, index[iStart]); + flags[iStart] = MIXED; + index[iStart++] = newBlock; + newBlock += UCPTRIE_SMALL_DATA_BLOCK_LENGTH; + } while (iStart < iLimit); + return index[i]; + } else { + int32_t newBlock = allocDataBlock(UCPTRIE_SMALL_DATA_BLOCK_LENGTH); + if (newBlock < 0) { return newBlock; } + writeBlock(data + newBlock, index[i]); + flags[i] = MIXED; + index[i] = newBlock; + return newBlock; + } +} + +void MutableCodePointTrie::set(UChar32 c, uint32_t value, UErrorCode &errorCode) { + if (U_FAILURE(errorCode)) { + return; + } + if ((uint32_t)c > MAX_UNICODE) { + errorCode = U_ILLEGAL_ARGUMENT_ERROR; + return; + } + + int32_t block; + if (!ensureHighStart(c) || (block = getDataBlock(c >> UCPTRIE_SHIFT_3)) < 0) { + errorCode = U_MEMORY_ALLOCATION_ERROR; + return; + } + + data[block + (c & UCPTRIE_SMALL_DATA_MASK)] = value; +} + +void +fillBlock(uint32_t *block, UChar32 start, UChar32 limit, uint32_t value) { + uint32_t *pLimit = block + limit; + block += start; + while (block < pLimit) { + *block++ = value; + } +} + +void MutableCodePointTrie::setRange(UChar32 start, UChar32 end, uint32_t value, UErrorCode &errorCode) { + if (U_FAILURE(errorCode)) { + return; + } + if ((uint32_t)start > MAX_UNICODE || (uint32_t)end > MAX_UNICODE || start > end) { + errorCode = U_ILLEGAL_ARGUMENT_ERROR; + return; + } + if (!ensureHighStart(end)) { + errorCode = U_MEMORY_ALLOCATION_ERROR; + return; + } + + UChar32 limit = end + 1; + if (start & UCPTRIE_SMALL_DATA_MASK) { + // Set partial block at [start..following block boundary[. + int32_t block = getDataBlock(start >> UCPTRIE_SHIFT_3); + if (block < 0) { + errorCode = U_MEMORY_ALLOCATION_ERROR; + return; + } + + UChar32 nextStart = (start + UCPTRIE_SMALL_DATA_MASK) & ~UCPTRIE_SMALL_DATA_MASK; + if (nextStart <= limit) { + fillBlock(data + block, start & UCPTRIE_SMALL_DATA_MASK, UCPTRIE_SMALL_DATA_BLOCK_LENGTH, + value); + start = nextStart; + } else { + fillBlock(data + block, start & UCPTRIE_SMALL_DATA_MASK, limit & UCPTRIE_SMALL_DATA_MASK, + value); + return; + } + } + + // Number of positions in the last, partial block. + int32_t rest = limit & UCPTRIE_SMALL_DATA_MASK; + + // Round down limit to a block boundary. + limit &= ~UCPTRIE_SMALL_DATA_MASK; + + // Iterate over all-value blocks. + while (start < limit) { + int32_t i = start >> UCPTRIE_SHIFT_3; + if (flags[i] == ALL_SAME) { + index[i] = value; + } else /* MIXED */ { + fillBlock(data + index[i], 0, UCPTRIE_SMALL_DATA_BLOCK_LENGTH, value); + } + start += UCPTRIE_SMALL_DATA_BLOCK_LENGTH; + } + + if (rest > 0) { + // Set partial block at [last block boundary..limit[. + int32_t block = getDataBlock(start >> UCPTRIE_SHIFT_3); + if (block < 0) { + errorCode = U_MEMORY_ALLOCATION_ERROR; + return; + } + + fillBlock(data + block, 0, rest, value); + } +} + +/* compaction --------------------------------------------------------------- */ + +void MutableCodePointTrie::maskValues(uint32_t mask) { + initialValue &= mask; + errorValue &= mask; + highValue &= mask; + int32_t iLimit = highStart >> UCPTRIE_SHIFT_3; + for (int32_t i = 0; i < iLimit; ++i) { + if (flags[i] == ALL_SAME) { + index[i] &= mask; + } + } + for (int32_t i = 0; i < dataLength; ++i) { + data[i] &= mask; + } +} + +inline bool +equalBlocks(const uint32_t *s, const uint32_t *t, int32_t length) { + while (length > 0 && *s == *t) { + ++s; + ++t; + --length; + } + return length == 0; +} + +inline bool +equalBlocks(const uint16_t *s, const uint32_t *t, int32_t length) { + while (length > 0 && *s == *t) { + ++s; + ++t; + --length; + } + return length == 0; +} + +inline bool +equalBlocks(const uint16_t *s, const uint16_t *t, int32_t length) { + while (length > 0 && *s == *t) { + ++s; + ++t; + --length; + } + return length == 0; +} + +bool allValuesSameAs(const uint32_t *p, int32_t length, uint32_t value) { + const uint32_t *pLimit = p + length; + while (p < pLimit && *p == value) { ++p; } + return p == pLimit; +} + +/** Search for an identical block. */ +int32_t findSameBlock(const uint32_t *p, int32_t pStart, int32_t length, + const uint32_t *q, int32_t qStart, int32_t blockLength) { + // Ensure that we do not even partially get past length. + length -= blockLength; + + q += qStart; + while (pStart <= length) { + if (equalBlocks(p + pStart, q, blockLength)) { + return pStart; + } + ++pStart; + } + return -1; +} + +int32_t findSameBlock(const uint16_t *p, int32_t pStart, int32_t length, + const uint32_t *q, int32_t qStart, int32_t blockLength) { + // Ensure that we do not even partially get past length. + length -= blockLength; + + q += qStart; + while (pStart <= length) { + if (equalBlocks(p + pStart, q, blockLength)) { + return pStart; + } + ++pStart; + } + return -1; +} + +int32_t findSameBlock(const uint16_t *p, int32_t pStart, int32_t length, + const uint16_t *q, int32_t qStart, int32_t blockLength) { + // Ensure that we do not even partially get past length. + length -= blockLength; + + q += qStart; + while (pStart <= length) { + if (equalBlocks(p + pStart, q, blockLength)) { + return pStart; + } + ++pStart; + } + return -1; +} + +int32_t findAllSameBlock(const uint32_t *p, int32_t start, int32_t limit, + uint32_t value, int32_t blockLength) { + // Ensure that we do not even partially get past limit. + limit -= blockLength; + + for (int32_t block = start; block <= limit; ++block) { + if (p[block] == value) { + for (int32_t i = 1;; ++i) { + if (i == blockLength) { + return block; + } + if (p[block + i] != value) { + block += i; + break; + } + } + } + } + return -1; +} + +/** + * Look for maximum overlap of the beginning of the other block + * with the previous, adjacent block. + */ +int32_t getOverlap(const uint32_t *p, int32_t length, + const uint32_t *q, int32_t qStart, int32_t blockLength) { + int32_t overlap = blockLength - 1; + U_ASSERT(overlap <= length); + q += qStart; + while (overlap > 0 && !equalBlocks(p + (length - overlap), q, overlap)) { + --overlap; + } + return overlap; +} + +int32_t getOverlap(const uint16_t *p, int32_t length, + const uint32_t *q, int32_t qStart, int32_t blockLength) { + int32_t overlap = blockLength - 1; + U_ASSERT(overlap <= length); + q += qStart; + while (overlap > 0 && !equalBlocks(p + (length - overlap), q, overlap)) { + --overlap; + } + return overlap; +} + +int32_t getOverlap(const uint16_t *p, int32_t length, + const uint16_t *q, int32_t qStart, int32_t blockLength) { + int32_t overlap = blockLength - 1; + U_ASSERT(overlap <= length); + q += qStart; + while (overlap > 0 && !equalBlocks(p + (length - overlap), q, overlap)) { + --overlap; + } + return overlap; +} + +int32_t getAllSameOverlap(const uint32_t *p, int32_t length, uint32_t value, + int32_t blockLength) { + int32_t min = length - (blockLength - 1); + int32_t i = length; + while (min < i && p[i - 1] == value) { --i; } + return length - i; +} + +bool isStartOfSomeFastBlock(uint32_t dataOffset, const uint32_t index[], int32_t fastILimit) { + for (int32_t i = 0; i < fastILimit; i += SMALL_DATA_BLOCKS_PER_BMP_BLOCK) { + if (index[i] == dataOffset) { + return true; + } + } + return false; +} + +/** + * Finds the start of the last range in the trie by enumerating backward. + * Indexes for code points higher than this will be omitted. + */ +UChar32 MutableCodePointTrie::findHighStart() const { + int32_t i = highStart >> UCPTRIE_SHIFT_3; + while (i > 0) { + bool match; + if (flags[--i] == ALL_SAME) { + match = index[i] == highValue; + } else /* MIXED */ { + const uint32_t *p = data + index[i]; + for (int32_t j = 0;; ++j) { + if (j == UCPTRIE_SMALL_DATA_BLOCK_LENGTH) { + match = true; + break; + } + if (p[j] != highValue) { + match = false; + break; + } + } + } + if (!match) { + return (i + 1) << UCPTRIE_SHIFT_3; + } + } + return 0; +} + +class AllSameBlocks { +public: + static constexpr int32_t NEW_UNIQUE = -1; + static constexpr int32_t OVERFLOW = -2; + + AllSameBlocks() : length(0), mostRecent(-1) {} + + int32_t findOrAdd(int32_t index, int32_t count, uint32_t value) { + if (mostRecent >= 0 && values[mostRecent] == value) { + refCounts[mostRecent] += count; + return indexes[mostRecent]; + } + for (int32_t i = 0; i < length; ++i) { + if (values[i] == value) { + mostRecent = i; + refCounts[i] += count; + return indexes[i]; + } + } + if (length == CAPACITY) { + return OVERFLOW; + } + mostRecent = length; + indexes[length] = index; + values[length] = value; + refCounts[length++] = count; + return NEW_UNIQUE; + } + + /** Replaces the block which has the lowest reference count. */ + void add(int32_t index, int32_t count, uint32_t value) { + U_ASSERT(length == CAPACITY); + int32_t least = -1; + int32_t leastCount = I_LIMIT; + for (int32_t i = 0; i < length; ++i) { + U_ASSERT(values[i] != value); + if (refCounts[i] < leastCount) { + least = i; + leastCount = refCounts[i]; + } + } + U_ASSERT(least >= 0); + mostRecent = least; + indexes[least] = index; + values[least] = value; + refCounts[least] = count; + } + + int32_t findMostUsed() const { + if (length == 0) { return -1; } + int32_t max = -1; + int32_t maxCount = 0; + for (int32_t i = 0; i < length; ++i) { + if (refCounts[i] > maxCount) { + max = i; + maxCount = refCounts[i]; + } + } + return indexes[max]; + } + +private: + static constexpr int32_t CAPACITY = 32; + + int32_t length; + int32_t mostRecent; + + int32_t indexes[CAPACITY]; + uint32_t values[CAPACITY]; + int32_t refCounts[CAPACITY]; +}; + +int32_t MutableCodePointTrie::compactWholeDataBlocks(int32_t fastILimit, AllSameBlocks &allSameBlocks) { +#ifdef UCPTRIE_DEBUG + bool overflow = false; +#endif + + // ASCII data will be stored as a linear table, even if the following code + // does not yet count it that way. + int32_t newDataCapacity = ASCII_LIMIT; + // Add room for a small data null block in case it would match the start of + // a fast data block where dataNullOffset must not be set in that case. + newDataCapacity += UCPTRIE_SMALL_DATA_BLOCK_LENGTH; + // Add room for special values (errorValue, highValue) and padding. + newDataCapacity += 4; + int32_t iLimit = highStart >> UCPTRIE_SHIFT_3; + int32_t blockLength = UCPTRIE_FAST_DATA_BLOCK_LENGTH; + int32_t inc = SMALL_DATA_BLOCKS_PER_BMP_BLOCK; + for (int32_t i = 0; i < iLimit; i += inc) { + if (i == fastILimit) { + blockLength = UCPTRIE_SMALL_DATA_BLOCK_LENGTH; + inc = 1; + } + uint32_t value = index[i]; + if (flags[i] == MIXED) { + // Really mixed? + const uint32_t *p = data + value; + value = *p; + if (allValuesSameAs(p + 1, blockLength - 1, value)) { + flags[i] = ALL_SAME; + index[i] = value; + // Fall through to ALL_SAME handling. + } else { + newDataCapacity += blockLength; + continue; + } + } else { + U_ASSERT(flags[i] == ALL_SAME); + if (inc > 1) { + // Do all of the fast-range data block's ALL_SAME parts have the same value? + bool allSame = true; + int32_t next_i = i + inc; + for (int32_t j = i + 1; j < next_i; ++j) { + U_ASSERT(flags[j] == ALL_SAME); + if (index[j] != value) { + allSame = false; + break; + } + } + if (!allSame) { + // Turn it into a MIXED block. + if (getDataBlock(i) < 0) { + return -1; + } + newDataCapacity += blockLength; + continue; + } + } + } + // Is there another ALL_SAME block with the same value? + int32_t other = allSameBlocks.findOrAdd(i, inc, value); + if (other == AllSameBlocks::OVERFLOW) { + // The fixed-size array overflowed. Slow check for a duplicate block. +#ifdef UCPTRIE_DEBUG + if (!overflow) { + puts("UCPTrie AllSameBlocks overflow"); + overflow = true; + } +#endif + int32_t jInc = SMALL_DATA_BLOCKS_PER_BMP_BLOCK; + for (int32_t j = 0;; j += jInc) { + if (j == i) { + allSameBlocks.add(i, inc, value); + break; + } + if (j == fastILimit) { + jInc = 1; + } + if (flags[j] == ALL_SAME && index[j] == value) { + allSameBlocks.add(j, jInc + inc, value); + other = j; + break; + // We could keep counting blocks with the same value + // before we add the first one, which may improve compaction in rare cases, + // but it would make it slower. + } + } + } + if (other >= 0) { + flags[i] = SAME_AS; + index[i] = other; + } else { + // New unique same-value block. + newDataCapacity += blockLength; + } + } + return newDataCapacity; +} + +#ifdef UCPTRIE_DEBUG +# define DEBUG_DO(expr) expr +#else +# define DEBUG_DO(expr) +#endif + +#ifdef UCPTRIE_DEBUG +// Braille symbols: U+28xx = UTF-8 E2 A0 80..E2 A3 BF +int32_t appendValue(char s[], int32_t length, uint32_t value) { + value ^= value >> 16; + value ^= value >> 8; + s[length] = 0xE2; + s[length + 1] = (char)(0xA0 + ((value >> 6) & 3)); + s[length + 2] = (char)(0x80 + (value & 0x3F)); + return length + 3; +} + +void printBlock(const uint32_t *block, int32_t blockLength, uint32_t value, + UChar32 start, int32_t overlap, uint32_t initialValue) { + char s[UCPTRIE_FAST_DATA_BLOCK_LENGTH * 3 + 3]; + int32_t length = 0; + int32_t i; + for (i = 0; i < overlap; ++i) { + length = appendValue(s, length, 0); // Braille blank + } + s[length++] = '|'; + for (; i < blockLength; ++i) { + if (block != nullptr) { + value = block[i]; + } + if (value == initialValue) { + value = 0x40; // Braille lower left dot + } + length = appendValue(s, length, value); + } + s[length] = 0; + start += overlap; + if (start <= 0xffff) { + printf(" %04lX %s|\n", (long)start, s); + } else if (start <= 0xfffff) { + printf(" %5lX %s|\n", (long)start, s); + } else { + printf(" %6lX %s|\n", (long)start, s); + } +} +#endif + +/** + * Compacts a build-time trie. + * + * The compaction + * - removes blocks that are identical with earlier ones + * - overlaps each new non-duplicate block as much as possible with the previously-written one + * - works with fast-range data blocks whose length is a multiple of that of + * higher-code-point data blocks + * + * It does not try to find an optimal order of writing, deduplicating, and overlapping blocks. + */ +int32_t MutableCodePointTrie::compactData(int32_t fastILimit, + uint32_t *newData, int32_t dataNullIndex) { +#ifdef UCPTRIE_DEBUG + int32_t countSame=0, sumOverlaps=0; + bool printData = dataLength == 29088 /* line.brk */ || + // dataLength == 30048 /* CanonIterData */ || + dataLength == 50400 /* zh.txt~stroke */; +#endif + + // The linear ASCII data has been copied into newData already. + int32_t newDataLength = 0; + for (int32_t i = 0; newDataLength < ASCII_LIMIT; + newDataLength += UCPTRIE_FAST_DATA_BLOCK_LENGTH, i += SMALL_DATA_BLOCKS_PER_BMP_BLOCK) { + index[i] = newDataLength; +#ifdef UCPTRIE_DEBUG + if (printData) { + printBlock(newData + newDataLength, UCPTRIE_FAST_DATA_BLOCK_LENGTH, 0, newDataLength, 0, initialValue); + } +#endif + } + + int32_t iLimit = highStart >> UCPTRIE_SHIFT_3; + int32_t blockLength = UCPTRIE_FAST_DATA_BLOCK_LENGTH; + int32_t inc = SMALL_DATA_BLOCKS_PER_BMP_BLOCK; + int32_t fastLength = 0; + for (int32_t i = ASCII_I_LIMIT; i < iLimit; i += inc) { + if (i == fastILimit) { + blockLength = UCPTRIE_SMALL_DATA_BLOCK_LENGTH; + inc = 1; + fastLength = newDataLength; + } + if (flags[i] == ALL_SAME) { + uint32_t value = index[i]; + int32_t n; + // Find an earlier part of the data array of length blockLength + // that is filled with this value. + // If we find a match, and the current block is the data null block, + // and it is not a fast block but matches the start of a fast block, + // then we need to continue looking. + // This is because this small block is shorter than the fast block, + // and not all of the rest of the fast block is filled with this value. + // Otherwise trie.getRange() would detect that the fast block starts at + // dataNullOffset and assume incorrectly that it is filled with the null value. + for (int32_t start = 0; + (n = findAllSameBlock(newData, start, newDataLength, + value, blockLength)) >= 0 && + i == dataNullIndex && i >= fastILimit && n < fastLength && + isStartOfSomeFastBlock(n, index, fastILimit); + start = n + 1) {} + if (n >= 0) { + DEBUG_DO(++countSame); + index[i] = n; + } else { + n = getAllSameOverlap(newData, newDataLength, value, blockLength); + DEBUG_DO(sumOverlaps += n); +#ifdef UCPTRIE_DEBUG + if (printData) { + printBlock(nullptr, blockLength, value, i << UCPTRIE_SHIFT_3, n, initialValue); + } +#endif + index[i] = newDataLength - n; + while (n < blockLength) { + newData[newDataLength++] = value; + ++n; + } + } + } else if (flags[i] == MIXED) { + const uint32_t *block = data + index[i]; + int32_t n = findSameBlock(newData, 0, newDataLength, block, 0, blockLength); + if (n >= 0) { + DEBUG_DO(++countSame); + index[i] = n; + } else { + n = getOverlap(newData, newDataLength, block, 0, blockLength); + DEBUG_DO(sumOverlaps += n); +#ifdef UCPTRIE_DEBUG + if (printData) { + printBlock(block, blockLength, 0, i << UCPTRIE_SHIFT_3, n, initialValue); + } +#endif + index[i] = newDataLength - n; + while (n < blockLength) { + newData[newDataLength++] = block[n++]; + } + } + } else /* SAME_AS */ { + uint32_t j = index[i]; + index[i] = index[j]; + } + } + +#ifdef UCPTRIE_DEBUG + /* we saved some space */ + printf("compacting UCPTrie: count of 32-bit data words %lu->%lu countSame=%ld sumOverlaps=%ld\n", + (long)dataLength, (long)newDataLength, (long)countSame, (long)sumOverlaps); +#endif + return newDataLength; +} + +int32_t MutableCodePointTrie::compactIndex(int32_t fastILimit, UErrorCode &errorCode) { + int32_t fastIndexLength = fastILimit >> (UCPTRIE_FAST_SHIFT - UCPTRIE_SHIFT_3); + if ((highStart >> UCPTRIE_FAST_SHIFT) <= fastIndexLength) { + // Only the linear fast index, no multi-stage index tables. + index3NullOffset = UCPTRIE_NO_INDEX3_NULL_OFFSET; + return fastIndexLength; + } + + // Condense the fast index table. + // Also, does it contain an index-3 block with all dataNullOffset? + uint16_t fastIndex[UCPTRIE_BMP_INDEX_LENGTH]; // fastIndexLength + int32_t i3FirstNull = -1; + for (int32_t i = 0, j = 0; i < fastILimit; ++j) { + uint32_t i3 = index[i]; + fastIndex[j] = (uint16_t)i3; + if (i3 == (uint32_t)dataNullOffset) { + if (i3FirstNull < 0) { + i3FirstNull = j; + } else if (index3NullOffset < 0 && + (j - i3FirstNull + 1) == UCPTRIE_INDEX_3_BLOCK_LENGTH) { + index3NullOffset = i3FirstNull; + } + } else { + i3FirstNull = -1; + } + // Set the index entries that compactData() skipped. + // Needed when the multi-stage index covers the fast index range as well. + int32_t iNext = i + SMALL_DATA_BLOCKS_PER_BMP_BLOCK; + while (++i < iNext) { + i3 += UCPTRIE_SMALL_DATA_BLOCK_LENGTH; + index[i] = i3; + } + } + + // Examine index-3 blocks. For each determine one of: + // - same as the index-3 null block + // - same as a fast-index block + // - 16-bit indexes + // - 18-bit indexes + // We store this in the first flags entry for the index-3 block. + // + // Also determine an upper limit for the index-3 table length. + int32_t index3Capacity = 0; + i3FirstNull = index3NullOffset; + // If the fast index covers the whole BMP, then + // the multi-stage index is only for supplementary code points. + // Otherwise, the multi-stage index covers all of Unicode. + int32_t iStart = fastILimit < BMP_I_LIMIT ? 0 : BMP_I_LIMIT; + int32_t iLimit = highStart >> UCPTRIE_SHIFT_3; + for (int32_t i = iStart; i < iLimit;) { + int32_t j = i; + int32_t jLimit = i + UCPTRIE_INDEX_3_BLOCK_LENGTH; + uint32_t oredI3 = 0; + bool isNull = true; + do { + uint32_t i3 = index[j]; + oredI3 |= i3; + if (i3 != (uint32_t)dataNullOffset) { + isNull = false; + } + } while (++j < jLimit); + if (isNull) { + flags[i] = I3_NULL; + if (i3FirstNull < 0) { + if (oredI3 <= 0xffff) { + index3Capacity += UCPTRIE_INDEX_3_BLOCK_LENGTH; + } else { + index3Capacity += INDEX_3_18BIT_BLOCK_LENGTH; + } + i3FirstNull = 0; + } + } else { + if (oredI3 <= 0xffff) { + int32_t n = findSameBlock(fastIndex, 0, fastIndexLength, + index, i, UCPTRIE_INDEX_3_BLOCK_LENGTH); + if (n >= 0) { + flags[i] = I3_BMP; + index[i] = n; + } else { + flags[i] = I3_16; + index3Capacity += UCPTRIE_INDEX_3_BLOCK_LENGTH; + } + } else { + flags[i] = I3_18; + index3Capacity += INDEX_3_18BIT_BLOCK_LENGTH; + } + } + i = j; + } + + int32_t index2Capacity = (iLimit - iStart) >> UCPTRIE_SHIFT_2_3; + + // Length of the index-1 table, rounded up. + int32_t index1Length = (index2Capacity + UCPTRIE_INDEX_2_MASK) >> UCPTRIE_SHIFT_1_2; + + // Index table: Fast index, index-1, index-3, index-2. + // +1 for possible index table padding. + int32_t index16Capacity = fastIndexLength + index1Length + index3Capacity + index2Capacity + 1; + index16 = (uint16_t *)uprv_malloc(index16Capacity * 2); + if (index16 == nullptr) { + errorCode = U_MEMORY_ALLOCATION_ERROR; + return 0; + } + uprv_memcpy(index16, fastIndex, fastIndexLength * 2); + + // Compact the index-3 table and write an uncompacted version of the index-2 table. + uint16_t index2[UNICODE_LIMIT >> UCPTRIE_SHIFT_2]; // index2Capacity + int32_t i2Length = 0; + i3FirstNull = index3NullOffset; + int32_t index3Start = fastIndexLength + index1Length; + int32_t indexLength = index3Start; + for (int32_t i = iStart; i < iLimit; i += UCPTRIE_INDEX_3_BLOCK_LENGTH) { + int32_t i3; + uint8_t f = flags[i]; + if (f == I3_NULL && i3FirstNull < 0) { + // First index-3 null block. Write & overlap it like a normal block, then remember it. + f = dataNullOffset <= 0xffff ? I3_16 : I3_18; + i3FirstNull = 0; + } + if (f == I3_NULL) { + i3 = index3NullOffset; + } else if (f == I3_BMP) { + i3 = index[i]; + } else if (f == I3_16) { + int32_t n = findSameBlock(index16, index3Start, indexLength, + index, i, UCPTRIE_INDEX_3_BLOCK_LENGTH); + if (n >= 0) { + i3 = n; + } else { + if (indexLength == index3Start) { + // No overlap at the boundary between the index-1 and index-3 tables. + n = 0; + } else { + n = getOverlap(index16, indexLength, + index, i, UCPTRIE_INDEX_3_BLOCK_LENGTH); + } + i3 = indexLength - n; + while (n < UCPTRIE_INDEX_3_BLOCK_LENGTH) { + index16[indexLength++] = index[i + n++]; + } + } + } else { + U_ASSERT(f == I3_18); + // Encode an index-3 block that contains one or more data indexes exceeding 16 bits. + int32_t j = i; + int32_t jLimit = i + UCPTRIE_INDEX_3_BLOCK_LENGTH; + int32_t k = indexLength; + do { + ++k; + uint32_t v = index[j++]; + uint32_t upperBits = (v & 0x30000) >> 2; + index16[k++] = v; + v = index[j++]; + upperBits |= (v & 0x30000) >> 4; + index16[k++] = v; + v = index[j++]; + upperBits |= (v & 0x30000) >> 6; + index16[k++] = v; + v = index[j++]; + upperBits |= (v & 0x30000) >> 8; + index16[k++] = v; + v = index[j++]; + upperBits |= (v & 0x30000) >> 10; + index16[k++] = v; + v = index[j++]; + upperBits |= (v & 0x30000) >> 12; + index16[k++] = v; + v = index[j++]; + upperBits |= (v & 0x30000) >> 14; + index16[k++] = v; + v = index[j++]; + upperBits |= (v & 0x30000) >> 16; + index16[k++] = v; + index16[k - 9] = upperBits; + } while (j < jLimit); + int32_t n = findSameBlock(index16, index3Start, indexLength, + index16, indexLength, INDEX_3_18BIT_BLOCK_LENGTH); + if (n >= 0) { + i3 = n | 0x8000; + } else { + if (indexLength == index3Start) { + // No overlap at the boundary between the index-1 and index-3 tables. + n = 0; + } else { + n = getOverlap(index16, indexLength, + index16, indexLength, INDEX_3_18BIT_BLOCK_LENGTH); + } + i3 = (indexLength - n) | 0x8000; + if (n > 0) { + int32_t start = indexLength; + while (n < INDEX_3_18BIT_BLOCK_LENGTH) { + index16[indexLength++] = index16[start + n++]; + } + } else { + indexLength += INDEX_3_18BIT_BLOCK_LENGTH; + } + } + } + if (index3NullOffset < 0 && i3FirstNull >= 0) { + index3NullOffset = i3; + } + // Set the index-2 table entry. + index2[i2Length++] = i3; + } + U_ASSERT(i2Length == index2Capacity); + U_ASSERT(indexLength <= index3Start + index3Capacity); + + if (index3NullOffset < 0) { + index3NullOffset = UCPTRIE_NO_INDEX3_NULL_OFFSET; + } + if (indexLength >= (UCPTRIE_NO_INDEX3_NULL_OFFSET + UCPTRIE_INDEX_3_BLOCK_LENGTH)) { + // The index-3 offsets exceed 15 bits, or + // the last one cannot be distinguished from the no-null-block value. + errorCode = U_INDEX_OUTOFBOUNDS_ERROR; + return 0; + } + + // Compact the index-2 table and write the index-1 table. + int32_t blockLength = UCPTRIE_INDEX_2_BLOCK_LENGTH; + int32_t i1 = fastIndexLength; + for (int32_t i = 0; i < i2Length; i += blockLength) { + if ((i2Length - i) < blockLength) { + // highStart is inside the last index-2 block. Shorten it. + blockLength = i2Length - i; + } + int32_t i2; + int32_t n = findSameBlock(index16, index3Start, indexLength, + index2, i, blockLength); + if (n >= 0) { + i2 = n; + } else { + if (indexLength == index3Start) { + // No overlap at the boundary between the index-1 and index-3/2 tables. + n = 0; + } else { + n = getOverlap(index16, indexLength, index2, i, blockLength); + } + i2 = indexLength - n; + while (n < blockLength) { + index16[indexLength++] = index2[i + n++]; + } + } + // Set the index-1 table entry. + index16[i1++] = i2; + } + U_ASSERT(i1 == index3Start); + U_ASSERT(indexLength <= index16Capacity); + +#ifdef UCPTRIE_DEBUG + /* we saved some space */ + printf("compacting UCPTrie: count of 16-bit index words %lu->%lu\n", + (long)iLimit, (long)indexLength); +#endif + + return indexLength; +} + +int32_t MutableCodePointTrie::compactTrie(int32_t fastILimit, UErrorCode &errorCode) { + // Find the real highStart and round it up. + U_ASSERT((highStart & (UCPTRIE_CP_PER_INDEX_2_ENTRY - 1)) == 0); + highValue = get(MAX_UNICODE); + int32_t realHighStart = findHighStart(); + realHighStart = (realHighStart + (UCPTRIE_CP_PER_INDEX_2_ENTRY - 1)) & + ~(UCPTRIE_CP_PER_INDEX_2_ENTRY - 1); + if (realHighStart == UNICODE_LIMIT) { + highValue = initialValue; + } + +#ifdef UCPTRIE_DEBUG + printf("UCPTrie: highStart U+%06lx highValue 0x%lx initialValue 0x%lx\n", + (long)realHighStart, (long)highValue, (long)initialValue); +#endif + + // We always store indexes and data values for the fast range. + // Pin highStart to the top of that range while building. + UChar32 fastLimit = fastILimit << UCPTRIE_SHIFT_3; + if (realHighStart < fastLimit) { + for (int32_t i = (realHighStart >> UCPTRIE_SHIFT_3); i < fastILimit; ++i) { + flags[i] = ALL_SAME; + index[i] = highValue; + } + highStart = fastLimit; + } else { + highStart = realHighStart; + } + + uint32_t asciiData[ASCII_LIMIT]; + for (int32_t i = 0; i < ASCII_LIMIT; ++i) { + asciiData[i] = get(i); + } + + // First we look for which data blocks have the same value repeated over the whole block, + // deduplicate such blocks, find a good null data block (for faster enumeration), + // and get an upper bound for the necessary data array length. + AllSameBlocks allSameBlocks; + int32_t newDataCapacity = compactWholeDataBlocks(fastILimit, allSameBlocks); + if (newDataCapacity < 0) { + errorCode = U_MEMORY_ALLOCATION_ERROR; + return 0; + } + uint32_t *newData = (uint32_t *)uprv_malloc(newDataCapacity * 4); + if (newData == nullptr) { + errorCode = U_MEMORY_ALLOCATION_ERROR; + return 0; + } + uprv_memcpy(newData, asciiData, sizeof(asciiData)); + + int32_t dataNullIndex = allSameBlocks.findMostUsed(); + int32_t newDataLength = compactData(fastILimit, newData, dataNullIndex); + U_ASSERT(newDataLength <= newDataCapacity); + uprv_free(data); + data = newData; + dataCapacity = newDataCapacity; + dataLength = newDataLength; + if (dataLength > (0x3ffff + UCPTRIE_SMALL_DATA_BLOCK_LENGTH)) { + // The offset of the last data block is too high to be stored in the index table. + errorCode = U_INDEX_OUTOFBOUNDS_ERROR; + return 0; + } + + if (dataNullIndex >= 0) { + dataNullOffset = index[dataNullIndex]; +#ifdef UCPTRIE_DEBUG + if (data[dataNullOffset] != initialValue) { + printf("UCPTrie initialValue %lx -> more common nullValue %lx\n", + (long)initialValue, (long)data[dataNullOffset]); + } +#endif + initialValue = data[dataNullOffset]; + } else { + dataNullOffset = UCPTRIE_NO_DATA_NULL_OFFSET; + } + + int32_t indexLength = compactIndex(fastILimit, errorCode); + highStart = realHighStart; + return indexLength; +} + +UCPTrie *MutableCodePointTrie::build(UCPTrieType type, UCPTrieValueWidth valueWidth, UErrorCode &errorCode) { + if (U_FAILURE(errorCode)) { + return nullptr; + } + if (type < UCPTRIE_TYPE_FAST || UCPTRIE_TYPE_SMALL < type || + valueWidth < UCPTRIE_VALUE_BITS_16 || UCPTRIE_VALUE_BITS_8 < valueWidth) { + errorCode = U_ILLEGAL_ARGUMENT_ERROR; + return nullptr; + } + + // The mutable trie always stores 32-bit values. + // When we build a UCPTrie for a smaller value width, we first mask off unused bits + // before compacting the data. + switch (valueWidth) { + case UCPTRIE_VALUE_BITS_32: + break; + case UCPTRIE_VALUE_BITS_16: + maskValues(0xffff); + break; + case UCPTRIE_VALUE_BITS_8: + maskValues(0xff); + break; + default: + break; + } + + UChar32 fastLimit = type == UCPTRIE_TYPE_FAST ? BMP_LIMIT : UCPTRIE_SMALL_LIMIT; + int32_t indexLength = compactTrie(fastLimit >> UCPTRIE_SHIFT_3, errorCode); + if (U_FAILURE(errorCode)) { + clear(); + return nullptr; + } + + // Ensure data table alignment: The index length must be even for uint32_t data. + if (valueWidth == UCPTRIE_VALUE_BITS_32 && (indexLength & 1) != 0) { + index16[indexLength++] = 0xffee; // arbitrary value + } + + // Make the total trie structure length a multiple of 4 bytes by padding the data table, + // and store special values as the last two data values. + int32_t length = indexLength * 2; + if (valueWidth == UCPTRIE_VALUE_BITS_16) { + if (((indexLength ^ dataLength) & 1) != 0) { + // padding + data[dataLength++] = errorValue; + } + if (data[dataLength - 1] != errorValue || data[dataLength - 2] != highValue) { + data[dataLength++] = highValue; + data[dataLength++] = errorValue; + } + length += dataLength * 2; + } else if (valueWidth == UCPTRIE_VALUE_BITS_32) { + // 32-bit data words never need padding to a multiple of 4 bytes. + if (data[dataLength - 1] != errorValue || data[dataLength - 2] != highValue) { + if (data[dataLength - 1] != highValue) { + data[dataLength++] = highValue; + } + data[dataLength++] = errorValue; + } + length += dataLength * 4; + } else { + int32_t and3 = (length + dataLength) & 3; + if (and3 == 0 && data[dataLength - 1] == errorValue && data[dataLength - 2] == highValue) { + // all set + } else if(and3 == 3 && data[dataLength - 1] == highValue) { + data[dataLength++] = errorValue; + } else { + while (and3 != 2) { + data[dataLength++] = highValue; + and3 = (and3 + 1) & 3; + } + data[dataLength++] = highValue; + data[dataLength++] = errorValue; + } + length += dataLength; + } + + // Calculate the total length of the UCPTrie as a single memory block. + length += sizeof(UCPTrie); + U_ASSERT((length & 3) == 0); + + uint8_t *bytes = (uint8_t *)uprv_malloc(length); + if (bytes == nullptr) { + errorCode = U_MEMORY_ALLOCATION_ERROR; + clear(); + return nullptr; + } + UCPTrie *trie = reinterpret_cast(bytes); + uprv_memset(trie, 0, sizeof(UCPTrie)); + trie->indexLength = indexLength; + trie->dataLength = dataLength; + + trie->highStart = highStart; + // Round up shifted12HighStart to a multiple of 0x1000 for easy testing from UTF-8 lead bytes. + // Runtime code needs to then test for the real highStart as well. + trie->shifted12HighStart = (highStart + 0xfff) >> 12; + trie->type = type; + trie->valueWidth = valueWidth; + + trie->index3NullOffset = index3NullOffset; + trie->dataNullOffset = dataNullOffset; + trie->nullValue = initialValue; + + bytes += sizeof(UCPTrie); + + // Fill the index and data arrays. + uint16_t *dest16 = (uint16_t *)bytes; + trie->index = dest16; + + if (highStart <= fastLimit) { + // Condense only the fast index from the mutable-trie index. + for (int32_t i = 0, j = 0; j < indexLength; i += SMALL_DATA_BLOCKS_PER_BMP_BLOCK, ++j) { + *dest16++ = (uint16_t)index[i]; // dest16[j] + } + } else { + uprv_memcpy(dest16, index16, indexLength * 2); + dest16 += indexLength; + } + bytes += indexLength * 2; + + // Write the data array. + const uint32_t *p = data; + switch (valueWidth) { + case UCPTRIE_VALUE_BITS_16: + // Write 16-bit data values. + trie->data.ptr16 = dest16; + for (int32_t i = dataLength; i > 0; --i) { + *dest16++ = (uint16_t)*p++; + } + break; + case UCPTRIE_VALUE_BITS_32: + // Write 32-bit data values. + trie->data.ptr32 = (uint32_t *)bytes; + uprv_memcpy(bytes, p, (size_t)dataLength * 4); + break; + case UCPTRIE_VALUE_BITS_8: + // Write 8-bit data values. + trie->data.ptr8 = bytes; + for (int32_t i = dataLength; i > 0; --i) { + *bytes++ = (uint8_t)*p++; + } + break; + default: + // Will not occur, valueWidth checked at the beginning. + break; + } + +#ifdef UCPTRIE_DEBUG + trie->name = name; + + ucptrie_printLengths(trie, ""); +#endif + + clear(); + return trie; +} + +} // namespace + +U_NAMESPACE_END + +U_NAMESPACE_USE + +U_CAPI UMutableCPTrie * U_EXPORT2 +umutablecptrie_open(uint32_t initialValue, uint32_t errorValue, UErrorCode *pErrorCode) { + if (U_FAILURE(*pErrorCode)) { + return nullptr; + } + LocalPointer trie( + new MutableCodePointTrie(initialValue, errorValue, *pErrorCode), *pErrorCode); + if (U_FAILURE(*pErrorCode)) { + return nullptr; + } + return reinterpret_cast(trie.orphan()); +} + +U_CAPI UMutableCPTrie * U_EXPORT2 +umutablecptrie_clone(const UMutableCPTrie *other, UErrorCode *pErrorCode) { + if (U_FAILURE(*pErrorCode)) { + return nullptr; + } + if (other == nullptr) { + return nullptr; + } + LocalPointer clone( + new MutableCodePointTrie(*reinterpret_cast(other), *pErrorCode), *pErrorCode); + if (U_FAILURE(*pErrorCode)) { + return nullptr; + } + return reinterpret_cast(clone.orphan()); +} + +U_CAPI void U_EXPORT2 +umutablecptrie_close(UMutableCPTrie *trie) { + delete reinterpret_cast(trie); +} + +U_CAPI UMutableCPTrie * U_EXPORT2 +umutablecptrie_fromUCPMap(const UCPMap *map, UErrorCode *pErrorCode) { + if (U_FAILURE(*pErrorCode)) { + return nullptr; + } + if (map == nullptr) { + *pErrorCode = U_ILLEGAL_ARGUMENT_ERROR; + return nullptr; + } + return reinterpret_cast(MutableCodePointTrie::fromUCPMap(map, *pErrorCode)); +} + +U_CAPI UMutableCPTrie * U_EXPORT2 +umutablecptrie_fromUCPTrie(const UCPTrie *trie, UErrorCode *pErrorCode) { + if (U_FAILURE(*pErrorCode)) { + return nullptr; + } + if (trie == nullptr) { + *pErrorCode = U_ILLEGAL_ARGUMENT_ERROR; + return nullptr; + } + return reinterpret_cast(MutableCodePointTrie::fromUCPTrie(trie, *pErrorCode)); +} + +U_CAPI uint32_t U_EXPORT2 +umutablecptrie_get(const UMutableCPTrie *trie, UChar32 c) { + return reinterpret_cast(trie)->get(c); +} + +namespace { + +UChar32 getRange(const void *trie, UChar32 start, + UCPMapValueFilter *filter, const void *context, uint32_t *pValue) { + return reinterpret_cast(trie)-> + getRange(start, filter, context, pValue); +} + +} // namespace + +U_CAPI UChar32 U_EXPORT2 +umutablecptrie_getRange(const UMutableCPTrie *trie, UChar32 start, + UCPMapRangeOption option, uint32_t surrogateValue, + UCPMapValueFilter *filter, const void *context, uint32_t *pValue) { + return ucptrie_internalGetRange(getRange, trie, start, + option, surrogateValue, + filter, context, pValue); +} + +U_CAPI void U_EXPORT2 +umutablecptrie_set(UMutableCPTrie *trie, UChar32 c, uint32_t value, UErrorCode *pErrorCode) { + if (U_FAILURE(*pErrorCode)) { + return; + } + reinterpret_cast(trie)->set(c, value, *pErrorCode); +} + +U_CAPI void U_EXPORT2 +umutablecptrie_setRange(UMutableCPTrie *trie, UChar32 start, UChar32 end, + uint32_t value, UErrorCode *pErrorCode) { + if (U_FAILURE(*pErrorCode)) { + return; + } + reinterpret_cast(trie)->setRange(start, end, value, *pErrorCode); +} + +/* Compact and internally serialize the trie. */ +U_CAPI UCPTrie * U_EXPORT2 +umutablecptrie_buildImmutable(UMutableCPTrie *trie, UCPTrieType type, UCPTrieValueWidth valueWidth, + UErrorCode *pErrorCode) { + if (U_FAILURE(*pErrorCode)) { + return nullptr; + } + return reinterpret_cast(trie)->build(type, valueWidth, *pErrorCode); +} + +#ifdef UCPTRIE_DEBUG +U_CFUNC void umutablecptrie_setName(UMutableCPTrie *trie, const char *name) { + reinterpret_cast(trie)->name = name; +} +#endif diff --git a/deps/icu-small/source/common/umutex.h b/deps/icu-small/source/common/umutex.h index 8f2f6123541f79..37e49871049b93 100644 --- a/deps/icu-small/source/common/umutex.h +++ b/deps/icu-small/source/common/umutex.h @@ -56,6 +56,13 @@ U_NAMESPACE_END U_NAMESPACE_BEGIN +// Export an explicit template instantiation of std::atomic. +// When building DLLs for Windows this is required as it is used as a data member of the exported SharedObject class. +// See digitlst.h, pluralaffix.h, datefmt.h, and others for similar examples. +#if U_PF_WINDOWS <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN +template struct U_COMMON_API std::atomic; +#endif + typedef std::atomic u_atomic_int32_t; #define ATOMIC_INT32_T_INITIALIZER(val) ATOMIC_VAR_INIT(val) @@ -205,7 +212,7 @@ umtx_atomic_dec(u_atomic_int32_t *p); U_NAMESPACE_END -#endif /* Low Level Atomic Ops Platfrom Chain */ +#endif /* Low Level Atomic Ops Platform Chain */ @@ -319,7 +326,7 @@ U_NAMESPACE_END *************************************************************************************************/ #if defined(U_USER_MUTEX_H) -// #inlcude "U_USER_MUTEX_H" +// #include "U_USER_MUTEX_H" #include U_MUTEX_XSTR(U_USER_MUTEX_H) #elif U_PLATFORM_USES_ONLY_WIN32_API @@ -389,7 +396,7 @@ struct UConditionVar { #else /* - * Unknow platform type. + * Unknown platform type. * This is an error condition. ICU requires mutexes. */ @@ -401,7 +408,7 @@ struct UConditionVar { /************************************************************************************** * - * Mutex Implementation function declaratations. + * Mutex Implementation function declarations. * Declarations are platform neutral. * Implementations, in umutex.cpp, are platform specific. * diff --git a/deps/icu-small/source/common/unames.cpp b/deps/icu-small/source/common/unames.cpp index 13a4572e1c38a1..5f752b0d1725cb 100644 --- a/deps/icu-small/source/common/unames.cpp +++ b/deps/icu-small/source/common/unames.cpp @@ -466,7 +466,7 @@ static uint16_t getExtName(uint32_t code, char *buffer, uint16_t bufferLength) { buffer[--i] = (v < 10 ? '0' + v : 'A' + v - 10); } buffer += ndigits; - length += ndigits; + length += static_cast(ndigits); WRITE_CHAR(buffer, bufferLength, length, '>'); return length; diff --git a/deps/icu-small/source/common/unicode/bytestream.h b/deps/icu-small/source/common/unicode/bytestream.h index 9df23f79c54c0c..61d1e8aca651d7 100644 --- a/deps/icu-small/source/common/unicode/bytestream.h +++ b/deps/icu-small/source/common/unicode/bytestream.h @@ -237,13 +237,12 @@ class StringByteSink : public ByteSink { * @stable ICU 4.2 */ StringByteSink(StringClass* dest) : dest_(dest) { } -#ifndef U_HIDE_DRAFT_API /** * Constructs a ByteSink that reserves append capacity and will append bytes to the dest string. * * @param dest pointer to string object to append to * @param initialAppendCapacity capacity beyond dest->length() to be reserve()d - * @draft ICU 60 + * @stable ICU 60 */ StringByteSink(StringClass* dest, int32_t initialAppendCapacity) : dest_(dest) { if (initialAppendCapacity > 0 && @@ -251,7 +250,6 @@ class StringByteSink : public ByteSink { dest->reserve(dest->length() + initialAppendCapacity); } } -#endif // U_HIDE_DRAFT_API /** * Append "bytes[0,n-1]" to this. * @param data the pointer to the bytes diff --git a/deps/icu-small/source/common/unicode/casemap.h b/deps/icu-small/source/common/unicode/casemap.h index 4b77256d742784..477eb484d136b6 100644 --- a/deps/icu-small/source/common/unicode/casemap.h +++ b/deps/icu-small/source/common/unicode/casemap.h @@ -194,7 +194,6 @@ class U_COMMON_API CaseMap U_FINAL : public UMemory { char16_t *dest, int32_t destCapacity, Edits *edits, UErrorCode &errorCode); -#ifndef U_HIDE_DRAFT_API /** * Lowercases a UTF-8 string and optionally records edits. * Casing is locale-dependent and context-sensitive. @@ -214,7 +213,7 @@ class U_COMMON_API CaseMap U_FINAL : public UMemory { * which must not indicate a failure before the function call. * * @see ucasemap_utf8ToLower - * @draft ICU 60 + * @stable ICU 60 */ static void utf8ToLower( const char *locale, uint32_t options, @@ -240,7 +239,7 @@ class U_COMMON_API CaseMap U_FINAL : public UMemory { * which must not indicate a failure before the function call. * * @see ucasemap_utf8ToUpper - * @draft ICU 60 + * @stable ICU 60 */ static void utf8ToUpper( const char *locale, uint32_t options, @@ -280,7 +279,7 @@ class U_COMMON_API CaseMap U_FINAL : public UMemory { * which must not indicate a failure before the function call. * * @see ucasemap_utf8ToTitle - * @draft ICU 60 + * @stable ICU 60 */ static void utf8ToTitle( const char *locale, uint32_t options, BreakIterator *iter, @@ -311,13 +310,12 @@ class U_COMMON_API CaseMap U_FINAL : public UMemory { * which must not indicate a failure before the function call. * * @see ucasemap_utf8FoldCase - * @draft ICU 60 + * @stable ICU 60 */ static void utf8Fold( uint32_t options, StringPiece src, ByteSink &sink, Edits *edits, UErrorCode &errorCode); -#endif // U_HIDE_DRAFT_API /** * Lowercases a UTF-8 string and optionally records edits. diff --git a/deps/icu-small/source/common/unicode/char16ptr.h b/deps/icu-small/source/common/unicode/char16ptr.h index 49d0e029a93b6e..a7c5f1a0c5ed56 100644 --- a/deps/icu-small/source/common/unicode/char16ptr.h +++ b/deps/icu-small/source/common/unicode/char16ptr.h @@ -28,6 +28,8 @@ U_NAMESPACE_BEGIN // Use the predefined value. #elif (defined(__clang__) || defined(__GNUC__)) && U_PLATFORM != U_PF_BROWSER_NATIVE_CLIENT # define U_ALIASING_BARRIER(ptr) asm volatile("" : : "rm"(ptr) : "memory") +#elif defined(U_IN_DOXYGEN) +# define U_ALIASING_BARRIER(ptr) #endif /** @@ -103,6 +105,7 @@ class U_COMMON_API Char16Ptr U_FINAL { #endif }; +/// \cond #ifdef U_ALIASING_BARRIER Char16Ptr::Char16Ptr(char16_t *p) : p_(p) {} @@ -134,6 +137,7 @@ Char16Ptr::~Char16Ptr() {} char16_t *Char16Ptr::get() const { return u_.cp; } #endif +/// \endcond /** * const char16_t * wrapper with implicit conversion from distinct but bit-compatible pointer types. @@ -209,6 +213,7 @@ class U_COMMON_API ConstChar16Ptr U_FINAL { #endif }; +/// \cond #ifdef U_ALIASING_BARRIER ConstChar16Ptr::ConstChar16Ptr(const char16_t *p) : p_(p) {} @@ -240,6 +245,7 @@ ConstChar16Ptr::~ConstChar16Ptr() {} const char16_t *ConstChar16Ptr::get() const { return u_.cp; } #endif +/// \endcond /** * Converts from const char16_t * to const UChar *. diff --git a/deps/icu-small/source/common/unicode/docmain.h b/deps/icu-small/source/common/unicode/docmain.h index 91e5ae3fa2e2e6..243fa17b87917a 100644 --- a/deps/icu-small/source/common/unicode/docmain.h +++ b/deps/icu-small/source/common/unicode/docmain.h @@ -88,6 +88,11 @@ * icu::UnicodeSet * * + * Maps from Unicode Code Points to Integer Values + * ucptrie.h, umutablecptrie.h + * C API + * + * * Maps from Strings to Integer Values * (no C API) * icu::BytesTrie, icu::UCharsTrie @@ -208,9 +213,9 @@ * C API * * - * Layout Engine/Complex Text Layout - * loengine.h - * icu::LayoutEngine,icu::ParagraphLayout + * Paragraph Layout / Complex Text Layout + * playout.h + * icu::ParagraphLayout * * * ICU I/O diff --git a/deps/icu-small/source/common/unicode/edits.h b/deps/icu-small/source/common/unicode/edits.h index f767a8d3b494c3..79e98b0cc27ac6 100644 --- a/deps/icu-small/source/common/unicode/edits.h +++ b/deps/icu-small/source/common/unicode/edits.h @@ -24,8 +24,8 @@ class UnicodeString; * in linear progression. Does not support moving/reordering of text. * * There are two types of edits: change edits and no-change edits. Add edits to - * instances of this class using {@link #addReplace(int, int)} (for change edits) and - * {@link #addUnchanged(int)} (for no-change edits). Change edits are retained with full granularity, + * instances of this class using {@link #addReplace(int32_t, int32_t)} (for change edits) and + * {@link #addUnchanged(int32_t)} (for no-change edits). Change edits are retained with full granularity, * whereas adjacent no-change edits are always merged together. In no-change edits, there is a one-to-one * mapping between code points in the source and destination strings. * @@ -62,11 +62,11 @@ class UnicodeString; * * * The "fine changes" and "coarse changes" iterators will step through only the change edits when their - * {@link Edits::Iterator#next()} methods are called. They are identical to the non-change iterators when - * their {@link Edits::Iterator#findSourceIndex(int)} or {@link Edits::Iterator#findDestinationIndex(int)} + * `Edits::Iterator::next()` methods are called. They are identical to the non-change iterators when + * their `Edits::Iterator::findSourceIndex()` or `Edits::Iterator::findDestinationIndex()` * methods are used to walk through the string. * - * For examples of how to use this class, see the test TestCaseMapEditsIteratorDocs in + * For examples of how to use this class, see the test `TestCaseMapEditsIteratorDocs` in * UCharacterCaseTest.java. * * An Edits object tracks a separate UErrorCode, but ICU string transformation functions @@ -86,7 +86,7 @@ class U_COMMON_API Edits U_FINAL : public UMemory { /** * Copy constructor. * @param other source edits - * @draft ICU 60 + * @stable ICU 60 */ Edits(const Edits &other) : array(stackArray), capacity(STACK_CAPACITY), length(other.length), @@ -98,7 +98,7 @@ class U_COMMON_API Edits U_FINAL : public UMemory { * Move constructor, might leave src empty. * This object will have the same contents that the source object had. * @param src source edits - * @draft ICU 60 + * @stable ICU 60 */ Edits(Edits &&src) U_NOEXCEPT : array(stackArray), capacity(STACK_CAPACITY), length(src.length), @@ -117,7 +117,7 @@ class U_COMMON_API Edits U_FINAL : public UMemory { * Assignment operator. * @param other source edits * @return *this - * @draft ICU 60 + * @stable ICU 60 */ Edits &operator=(const Edits &other); @@ -127,7 +127,7 @@ class U_COMMON_API Edits U_FINAL : public UMemory { * The behavior is undefined if *this and src are the same object. * @param src source edits * @return *this - * @draft ICU 60 + * @stable ICU 60 */ Edits &operator=(Edits &&src) U_NOEXCEPT; @@ -173,13 +173,11 @@ class U_COMMON_API Edits U_FINAL : public UMemory { */ UBool hasChanges() const { return numChanges != 0; } -#ifndef U_HIDE_DRAFT_API /** * @return the number of change edits - * @draft ICU 60 + * @stable ICU 60 */ int32_t numberOfChanges() const { return numChanges; } -#endif // U_HIDE_DRAFT_API /** * Access to the list of edits. @@ -189,9 +187,9 @@ class U_COMMON_API Edits U_FINAL : public UMemory { * starts at {@link #sourceIndex()} and runs for {@link #oldLength()} chars; the destination string * span starts at {@link #destinationIndex()} and runs for {@link #newLength()} chars. * - * The iterator can be moved between edits using the {@link #next()}, {@link #findSourceIndex(int)}, - * and {@link #findDestinationIndex(int)} methods. Calling any of these methods mutates the iterator - * to make it point to the corresponding edit. + * The iterator can be moved between edits using the `next()`, `findSourceIndex(int32_t, UErrorCode &)`, + * and `findDestinationIndex(int32_t, UErrorCode &)` methods. + * Calling any of these methods mutates the iterator to make it point to the corresponding edit. * * For more information, see the documentation for {@link Edits}. * @@ -202,7 +200,7 @@ class U_COMMON_API Edits U_FINAL : public UMemory { struct U_COMMON_API Iterator U_FINAL : public UMemory { /** * Default constructor, empty iterator. - * @draft ICU 60 + * @stable ICU 60 */ Iterator() : array(nullptr), index(0), length(0), @@ -253,7 +251,6 @@ class U_COMMON_API Edits U_FINAL : public UMemory { return findIndex(i, TRUE, errorCode) == 0; } -#ifndef U_HIDE_DRAFT_API /** * Moves the iterator to the edit that contains the destination index. * The destination index may be found in a no-change edit @@ -271,7 +268,7 @@ class U_COMMON_API Edits U_FINAL : public UMemory { * or else the function returns immediately. Check for U_FAILURE() * on output or use with function chaining. (See User Guide for details.) * @return TRUE if the edit for the destination index was found - * @draft ICU 60 + * @stable ICU 60 */ UBool findDestinationIndex(int32_t i, UErrorCode &errorCode) { return findIndex(i, FALSE, errorCode) == 0; @@ -297,7 +294,7 @@ class U_COMMON_API Edits U_FINAL : public UMemory { * or else the function returns immediately. Check for U_FAILURE() * on output or use with function chaining. (See User Guide for details.) * @return destination index; undefined if i is not 0..string length - * @draft ICU 60 + * @stable ICU 60 */ int32_t destinationIndexFromSourceIndex(int32_t i, UErrorCode &errorCode); @@ -321,10 +318,9 @@ class U_COMMON_API Edits U_FINAL : public UMemory { * or else the function returns immediately. Check for U_FAILURE() * on output or use with function chaining. (See User Guide for details.) * @return source index; undefined if i is not 0..string length - * @draft ICU 60 + * @stable ICU 60 */ int32_t sourceIndexFromDestinationIndex(int32_t i, UErrorCode &errorCode); -#endif // U_HIDE_DRAFT_API /** * Returns whether the edit currently represented by the iterator is a change edit. @@ -366,13 +362,13 @@ class U_COMMON_API Edits U_FINAL : public UMemory { /** * The start index of the current span in the replacement string; the span has length * {@link #newLength}. Well-defined only if the current edit is a change edit. - *

- * The replacement string is the concatenation of all substrings of the destination + * + * The *replacement string* is the concatenation of all substrings of the destination * string corresponding to change edits. - *

+ * * This method is intended to be used together with operations that write only replacement - * characters (e.g., {@link CaseMap#omitUnchangedText()}). The source string can then be modified - * in-place. + * characters (e.g. operations specifying the \ref U_OMIT_UNCHANGED_TEXT option). + * The source string can then be modified in-place. * * @return the current index into the replacement-characters-only string, * not counting unchanged spans @@ -475,7 +471,6 @@ class U_COMMON_API Edits U_FINAL : public UMemory { return Iterator(array, length, FALSE, FALSE); } -#ifndef U_HIDE_DRAFT_API /** * Merges the two input Edits and appends the result to this object. * @@ -501,10 +496,9 @@ class U_COMMON_API Edits U_FINAL : public UMemory { * or else the function returns immediately. Check for U_FAILURE() * on output or use with function chaining. (See User Guide for details.) * @return *this, with the merged edits appended - * @draft ICU 60 + * @stable ICU 60 */ Edits &mergeAndAppend(const Edits &ab, const Edits &bc, UErrorCode &errorCode); -#endif // U_HIDE_DRAFT_API private: void releaseArray() U_NOEXCEPT; diff --git a/deps/icu-small/source/common/unicode/enumset.h b/deps/icu-small/source/common/unicode/enumset.h index 82b2074ec35875..82d633ed016b5e 100644 --- a/deps/icu-small/source/common/unicode/enumset.h +++ b/deps/icu-small/source/common/unicode/enumset.h @@ -28,6 +28,7 @@ U_NAMESPACE_BEGIN * enum bitset for boolean fields. Similar to Java EnumSet<>. * Needs to range check. Used for private instance variables. * @internal + * \cond */ template class EnumSet { @@ -60,6 +61,8 @@ class EnumSet { uint32_t fBools; }; +/** \endcond */ + U_NAMESPACE_END #endif /* U_SHOW_CPLUSPLUS_API */ diff --git a/deps/icu-small/source/common/unicode/filteredbrk.h b/deps/icu-small/source/common/unicode/filteredbrk.h index 751d1faf40454f..2444114e9a14bf 100644 --- a/deps/icu-small/source/common/unicode/filteredbrk.h +++ b/deps/icu-small/source/common/unicode/filteredbrk.h @@ -67,16 +67,14 @@ class U_COMMON_API FilteredBreakIteratorBuilder : public UObject { static FilteredBreakIteratorBuilder *createInstance(UErrorCode &status); #endif /* U_HIDE_DEPRECATED_API */ -#ifndef U_HIDE_DRAFT_API /** * Construct an empty FilteredBreakIteratorBuilder. * In this state, it will not suppress any segment boundaries. * @param status The error code. * @return the new builder - * @draft ICU 60 + * @stable ICU 60 */ static FilteredBreakIteratorBuilder *createEmptyInstance(UErrorCode &status); -#endif /* U_HIDE_DRAFT_API */ /** * Suppress a certain string from being the end of a segment. @@ -95,7 +93,7 @@ class U_COMMON_API FilteredBreakIteratorBuilder : public UObject { * This function does not create any new segment boundaries, but only serves to un-do * the effect of earlier calls to suppressBreakAfter, or to un-do the effect of * locale data which may be suppressing certain strings. - * @param exception the exception to remove + * @param string the exception to remove * @param status error code * @return returns TRUE if the string was present and now removed, * FALSE if the call was a no-op because the string was not being suppressed. @@ -114,7 +112,6 @@ class U_COMMON_API FilteredBreakIteratorBuilder : public UObject { */ virtual BreakIterator *build(BreakIterator* adoptBreakIterator, UErrorCode& status) = 0; -#ifndef U_HIDE_DRAFT_API /** * Wrap (adopt) an existing break iterator in a new filtered instance. * The resulting BreakIterator is owned by the caller. @@ -126,12 +123,11 @@ class U_COMMON_API FilteredBreakIteratorBuilder : public UObject { * @param adoptBreakIterator the break iterator to adopt * @param status error code * @return the new BreakIterator, owned by the caller. - * @draft ICU 60 + * @stable ICU 60 */ inline BreakIterator *wrapIteratorWithFilter(BreakIterator* adoptBreakIterator, UErrorCode& status) { return build(adoptBreakIterator, status); } -#endif /* U_HIDE_DRAFT_API */ protected: /** diff --git a/deps/icu-small/source/common/unicode/icuplug.h b/deps/icu-small/source/common/unicode/icuplug.h index 2a11b96be69c53..827cbe94b61cf8 100644 --- a/deps/icu-small/source/common/unicode/icuplug.h +++ b/deps/icu-small/source/common/unicode/icuplug.h @@ -110,7 +110,7 @@ #include "unicode/utypes.h" -#if UCONFIG_ENABLE_PLUGINS +#if UCONFIG_ENABLE_PLUGINS || defined(U_IN_DOXYGEN) diff --git a/deps/icu-small/source/common/unicode/locid.h b/deps/icu-small/source/common/unicode/locid.h index c84774e07fd395..415bced82299e3 100644 --- a/deps/icu-small/source/common/unicode/locid.h +++ b/deps/icu-small/source/common/unicode/locid.h @@ -31,6 +31,10 @@ #ifndef LOCID_H #define LOCID_H +#include "unicode/bytestream.h" +#include "unicode/localpointer.h" +#include "unicode/strenum.h" +#include "unicode/stringpiece.h" #include "unicode/utypes.h" #include "unicode/uobject.h" #include "unicode/putil.h" @@ -280,6 +284,16 @@ class U_COMMON_API Locale : public UObject { */ Locale(const Locale& other); +#ifndef U_HIDE_DRAFT_API + /** + * Move constructor; might leave source in bogus state. + * This locale will have the same contents that the source locale had. + * + * @param other The Locale object being moved in. + * @draft ICU 63 + */ + Locale(Locale&& other) U_NOEXCEPT; +#endif // U_HIDE_DRAFT_API /** * Destructor @@ -296,6 +310,19 @@ class U_COMMON_API Locale : public UObject { */ Locale& operator=(const Locale& other); +#ifndef U_HIDE_DRAFT_API + /** + * Move assignment operator; might leave source in bogus state. + * This locale will have the same contents that the source locale had. + * The behavior is undefined if *this and the source are the same object. + * + * @param other The Locale object being moved in. + * @return *this + * @draft ICU 63 + */ + Locale& operator=(Locale&& other) U_NOEXCEPT; +#endif // U_HIDE_DRAFT_API + /** * Checks if two locale keys are the same. * @@ -362,6 +389,55 @@ class U_COMMON_API Locale : public UObject { UErrorCode& success); #endif /* U_HIDE_SYSTEM_API */ +#ifndef U_HIDE_DRAFT_API + /** + * Returns a Locale for the specified BCP47 language tag string. + * If the specified language tag contains any ill-formed subtags, + * the first such subtag and all following subtags are ignored. + *

+ * This implements the 'Language-Tag' production of BCP47, and so + * supports grandfathered (regular and irregular) as well as private + * use language tags. Private use tags are represented as 'x-whatever', + * and grandfathered tags are converted to their canonical replacements + * where they exist. Note that a few grandfathered tags have no modern + * replacement, these will be converted using the fallback described in + * the first paragraph, so some information might be lost. + * @param tag the input BCP47 language tag. + * @param status error information if creating the Locale failed. + * @return the Locale for the specified BCP47 language tag. + * @draft ICU 63 + */ + static Locale U_EXPORT2 forLanguageTag(StringPiece tag, UErrorCode& status); + + /** + * Returns a well-formed language tag for this Locale. + *

+ * Note: Any locale fields which do not satisfy the BCP47 syntax + * requirement will be silently omitted from the result. + * + * If this function fails, partial output may have been written to the sink. + * + * @param sink the output sink receiving the BCP47 language + * tag for this Locale. + * @param status error information if creating the language tag failed. + * @draft ICU 63 + */ + void toLanguageTag(ByteSink& sink, UErrorCode& status) const; + + /** + * Returns a well-formed language tag for this Locale. + *

+ * Note: Any locale fields which do not satisfy the BCP47 syntax + * requirement will be silently omitted from the result. + * + * @param status error information if creating the language tag failed. + * @return the BCP47 language tag for this Locale. + * @draft ICU 63 + */ + template + inline StringClass toLanguageTag(UErrorCode& status) const; +#endif // U_HIDE_DRAFT_API + /** * Creates a locale which has had minimal canonicalization * as per uloc_getName(). @@ -432,6 +508,69 @@ class U_COMMON_API Locale : public UObject { */ const char * getBaseName() const; +#ifndef U_HIDE_DRAFT_API + /** + * Add the likely subtags for this Locale, per the algorithm described + * in the following CLDR technical report: + * + * http://www.unicode.org/reports/tr35/#Likely_Subtags + * + * If this Locale is already in the maximal form, or not valid, or there is + * no data available for maximization, the Locale will be unchanged. + * + * For example, "und-Zzzz" cannot be maximized, since there is no + * reasonable maximization. + * + * Examples: + * + * "en" maximizes to "en_Latn_US" + * + * "de" maximizes to "de_Latn_US" + * + * "sr" maximizes to "sr_Cyrl_RS" + * + * "sh" maximizes to "sr_Latn_RS" (Note this will not reverse.) + * + * "zh_Hani" maximizes to "zh_Hans_CN" (Note this will not reverse.) + * + * @param status error information if maximizing this Locale failed. + * If this Locale is not well-formed, the error code is + * U_ILLEGAL_ARGUMENT_ERROR. + * @draft ICU 63 + */ + void addLikelySubtags(UErrorCode& status); + + /** + * Minimize the subtags for this Locale, per the algorithm described + * in the following CLDR technical report: + * + * http://www.unicode.org/reports/tr35/#Likely_Subtags + * + * If this Locale is already in the minimal form, or not valid, or there is + * no data available for minimization, the Locale will be unchanged. + * + * Since the minimization algorithm relies on proper maximization, see the + * comments for addLikelySubtags for reasons why there might not be any + * data. + * + * Examples: + * + * "en_Latn_US" minimizes to "en" + * + * "de_Latn_US" minimizes to "de" + * + * "sr_Cyrl_RS" minimizes to "sr" + * + * "zh_Hant_TW" minimizes to "zh_TW" (The region is preferred to the + * script, and minimizing to "zh" would imply "zh_Hans_CN".) + * + * @param status error information if maximizing this Locale failed. + * If this Locale is not well-formed, the error code is + * U_ILLEGAL_ARGUMENT_ERROR. + * @draft ICU 63 + */ + void minimizeSubtags(UErrorCode& status); +#endif // U_HIDE_DRAFT_API /** * Gets the list of keywords for the specified locale. @@ -439,13 +578,62 @@ class U_COMMON_API Locale : public UObject { * @param status the status code * @return pointer to StringEnumeration class, or NULL if there are no keywords. * Client must dispose of it by calling delete. + * @see getKeywords * @stable ICU 2.8 */ StringEnumeration * createKeywords(UErrorCode &status) const; +#ifndef U_HIDE_DRAFT_API + + /** + * Gets the list of Unicode keywords for the specified locale. + * + * @param status the status code + * @return pointer to StringEnumeration class, or NULL if there are no keywords. + * Client must dispose of it by calling delete. + * @see getUnicodeKeywords + * @draft ICU 63 + */ + StringEnumeration * createUnicodeKeywords(UErrorCode &status) const; + + /** + * Gets the set of keywords for this Locale. + * + * A wrapper to call createKeywords() and write the resulting + * keywords as standard strings (or compatible objects) into any kind of + * container that can be written to by an STL style output iterator. + * + * @param iterator an STL style output iterator to write the keywords to. + * @param status error information if creating set of keywords failed. + * @draft ICU 63 + */ + template + inline void getKeywords(OutputIterator iterator, UErrorCode& status) const; + + /** + * Gets the set of Unicode keywords for this Locale. + * + * A wrapper to call createUnicodeKeywords() and write the resulting + * keywords as standard strings (or compatible objects) into any kind of + * container that can be written to by an STL style output iterator. + * + * @param iterator an STL style output iterator to write the keywords to. + * @param status error information if creating set of keywords failed. + * @draft ICU 63 + */ + template + inline void getUnicodeKeywords(OutputIterator iterator, UErrorCode& status) const; + +#endif // U_HIDE_DRAFT_API + /** * Gets the value for a keyword. * + * This uses legacy keyword=value pairs, like "collation=phonebook". + * + * ICU4C doesn't do automatic conversion between legacy and Unicode + * keywords and values in getters and setters (as opposed to ICU4J). + * * @param keywordName name of the keyword for which we want the value. Case insensitive. * @param buffer The buffer to receive the keyword value. * @param bufferCapacity The capacity of receiving buffer @@ -456,12 +644,81 @@ class U_COMMON_API Locale : public UObject { */ int32_t getKeywordValue(const char* keywordName, char *buffer, int32_t bufferCapacity, UErrorCode &status) const; +#ifndef U_HIDE_DRAFT_API + /** + * Gets the value for a keyword. + * + * This uses legacy keyword=value pairs, like "collation=phonebook". + * + * ICU4C doesn't do automatic conversion between legacy and Unicode + * keywords and values in getters and setters (as opposed to ICU4J). + * + * @param keywordName name of the keyword for which we want the value. + * @param sink the sink to receive the keyword value. + * @param status error information if getting the value failed. + * @draft ICU 63 + */ + void getKeywordValue(StringPiece keywordName, ByteSink& sink, UErrorCode& status) const; + + /** + * Gets the value for a keyword. + * + * This uses legacy keyword=value pairs, like "collation=phonebook". + * + * ICU4C doesn't do automatic conversion between legacy and Unicode + * keywords and values in getters and setters (as opposed to ICU4J). + * + * @param keywordName name of the keyword for which we want the value. + * @param status error information if getting the value failed. + * @return the keyword value. + * @draft ICU 63 + */ + template + inline StringClass getKeywordValue(StringPiece keywordName, UErrorCode& status) const; + + /** + * Gets the Unicode value for a Unicode keyword. + * + * This uses Unicode key-value pairs, like "co-phonebk". + * + * ICU4C doesn't do automatic conversion between legacy and Unicode + * keywords and values in getters and setters (as opposed to ICU4J). + * + * @param keywordName name of the keyword for which we want the value. + * @param sink the sink to receive the keyword value. + * @param status error information if getting the value failed. + * @draft ICU 63 + */ + void getUnicodeKeywordValue(StringPiece keywordName, ByteSink& sink, UErrorCode& status) const; + + /** + * Gets the Unicode value for a Unicode keyword. + * + * This uses Unicode key-value pairs, like "co-phonebk". + * + * ICU4C doesn't do automatic conversion between legacy and Unicode + * keywords and values in getters and setters (as opposed to ICU4J). + * + * @param keywordName name of the keyword for which we want the value. + * @param status error information if getting the value failed. + * @return the keyword value. + * @draft ICU 63 + */ + template + inline StringClass getUnicodeKeywordValue(StringPiece keywordName, UErrorCode& status) const; +#endif // U_HIDE_DRAFT_API + /** * Sets or removes the value for a keyword. * * For removing all keywords, use getBaseName(), * and construct a new Locale if it differs from getName(). * + * This uses legacy keyword=value pairs, like "collation=phonebook". + * + * ICU4C doesn't do automatic conversion between legacy and Unicode + * keywords and values in getters and setters (as opposed to ICU4J). + * * @param keywordName name of the keyword to be set. Case insensitive. * @param keywordValue value of the keyword to be set. If 0-length or * NULL, will result in the keyword being removed. No error is given if @@ -472,6 +729,48 @@ class U_COMMON_API Locale : public UObject { */ void setKeywordValue(const char* keywordName, const char* keywordValue, UErrorCode &status); +#ifndef U_HIDE_DRAFT_API + /** + * Sets or removes the value for a keyword. + * + * For removing all keywords, use getBaseName(), + * and construct a new Locale if it differs from getName(). + * + * This uses legacy keyword=value pairs, like "collation=phonebook". + * + * ICU4C doesn't do automatic conversion between legacy and Unicode + * keywords and values in getters and setters (as opposed to ICU4J). + * + * @param keywordName name of the keyword to be set. + * @param keywordValue value of the keyword to be set. If 0-length or + * NULL, will result in the keyword being removed. No error is given if + * that keyword does not exist. + * @param status Returns any error information while performing this operation. + * @draft ICU 63 + */ + void setKeywordValue(StringPiece keywordName, StringPiece keywordValue, UErrorCode& status); + + /** + * Sets or removes the Unicode value for a Unicode keyword. + * + * For removing all keywords, use getBaseName(), + * and construct a new Locale if it differs from getName(). + * + * This uses Unicode key-value pairs, like "co-phonebk". + * + * ICU4C doesn't do automatic conversion between legacy and Unicode + * keywords and values in getters and setters (as opposed to ICU4J). + * + * @param keywordName name of the keyword to be set. + * @param keywordValue value of the keyword to be set. If 0-length or + * NULL, will result in the keyword being removed. No error is given if + * that keyword does not exist. + * @param status Returns any error information while performing this operation. + * @draft ICU 63 + */ + void setUnicodeKeywordValue(StringPiece keywordName, StringPiece keywordValue, UErrorCode& status); +#endif // U_HIDE_DRAFT_API + /** * returns the locale's three-letter language code, as specified * in ISO draft standard ISO-639-2. @@ -759,12 +1058,12 @@ class U_COMMON_API Locale : public UObject { /** * A friend to allow the default locale to be set by either the C or C++ API. - * @internal + * @internal (private) */ friend Locale *locale_set_default_internal(const char *, UErrorCode& status); /** - * @internal + * @internal (private) */ friend void U_CALLCONV locale_available_init(); }; @@ -775,6 +1074,17 @@ Locale::operator!=(const Locale& other) const return !operator==(other); } +#ifndef U_HIDE_DRAFT_API +template inline StringClass +Locale::toLanguageTag(UErrorCode& status) const +{ + StringClass result; + StringByteSink sink(&result); + toLanguageTag(sink, status); + return result; +} +#endif // U_HIDE_DRAFT_API + inline const char * Locale::getCountry() const { @@ -805,6 +1115,62 @@ Locale::getName() const return fullName; } +#ifndef U_HIDE_DRAFT_API + +template inline void +Locale::getKeywords(OutputIterator iterator, UErrorCode& status) const +{ + LocalPointer keys(createKeywords(status)); + if (U_FAILURE(status)) { + return; + } + for (;;) { + int32_t resultLength; + const char* buffer = keys->next(&resultLength, status); + if (U_FAILURE(status) || buffer == nullptr) { + return; + } + *iterator++ = StringClass(buffer, resultLength); + } +} + +template inline void +Locale::getUnicodeKeywords(OutputIterator iterator, UErrorCode& status) const +{ + LocalPointer keys(createUnicodeKeywords(status)); + if (U_FAILURE(status)) { + return; + } + for (;;) { + int32_t resultLength; + const char* buffer = keys->next(&resultLength, status); + if (U_FAILURE(status) || buffer == nullptr) { + return; + } + *iterator++ = StringClass(buffer, resultLength); + } +} + +template inline StringClass +Locale::getKeywordValue(StringPiece keywordName, UErrorCode& status) const +{ + StringClass result; + StringByteSink sink(&result); + getKeywordValue(keywordName, sink, status); + return result; +} + +template inline StringClass +Locale::getUnicodeKeywordValue(StringPiece keywordName, UErrorCode& status) const +{ + StringClass result; + StringByteSink sink(&result); + getUnicodeKeywordValue(keywordName, sink, status); + return result; +} + +#endif // U_HIDE_DRAFT_API + inline UBool Locale::isBogus(void) const { return fIsBogus; diff --git a/deps/icu-small/source/common/unicode/messagepattern.h b/deps/icu-small/source/common/unicode/messagepattern.h index f28adafee0d2ac..9f2a86551ca417 100644 --- a/deps/icu-small/source/common/unicode/messagepattern.h +++ b/deps/icu-small/source/common/unicode/messagepattern.h @@ -771,8 +771,8 @@ class U_COMMON_API MessagePattern : public UObject { * @stable ICU 4.8 */ UMessagePatternArgType getArgType() const { - UMessagePatternPartType type=getType(); - if(type==UMSGPAT_PART_TYPE_ARG_START || type==UMSGPAT_PART_TYPE_ARG_LIMIT) { + UMessagePatternPartType msgType=getType(); + if(msgType ==UMSGPAT_PART_TYPE_ARG_START || msgType ==UMSGPAT_PART_TYPE_ARG_LIMIT) { return (UMessagePatternArgType)value; } else { return UMSGPAT_ARG_TYPE_NONE; diff --git a/deps/icu-small/source/common/unicode/normalizer2.h b/deps/icu-small/source/common/unicode/normalizer2.h index 8a6d7138021b56..4caa0e31034b2d 100644 --- a/deps/icu-small/source/common/unicode/normalizer2.h +++ b/deps/icu-small/source/common/unicode/normalizer2.h @@ -241,7 +241,7 @@ class U_COMMON_API Normalizer2 : public UObject { * pass the U_SUCCESS() test, or else the function returns * immediately. Check for U_FAILURE() on output or use with * function chaining. (See User Guide for details.) - * @draft ICU 60 + * @stable ICU 60 */ virtual void normalizeUTF8(uint32_t options, StringPiece src, ByteSink &sink, @@ -391,7 +391,7 @@ class U_COMMON_API Normalizer2 : public UObject { * immediately. Check for U_FAILURE() on output or use with * function chaining. (See User Guide for details.) * @return TRUE if s is normalized - * @draft ICU 60 + * @stable ICU 60 */ virtual UBool isNormalizedUTF8(StringPiece s, UErrorCode &errorCode) const; @@ -559,7 +559,7 @@ class U_COMMON_API FilteredNormalizer2 : public Normalizer2 { * pass the U_SUCCESS() test, or else the function returns * immediately. Check for U_FAILURE() on output or use with * function chaining. (See User Guide for details.) - * @draft ICU 60 + * @stable ICU 60 */ virtual void normalizeUTF8(uint32_t options, StringPiece src, ByteSink &sink, @@ -686,7 +686,7 @@ class U_COMMON_API FilteredNormalizer2 : public Normalizer2 { * immediately. Check for U_FAILURE() on output or use with * function chaining. (See User Guide for details.) * @return TRUE if s is normalized - * @draft ICU 60 + * @stable ICU 60 */ virtual UBool isNormalizedUTF8(StringPiece s, UErrorCode &errorCode) const U_OVERRIDE; diff --git a/deps/icu-small/source/common/unicode/platform.h b/deps/icu-small/source/common/unicode/platform.h index d9636580c309b5..ee0d8b7a000303 100644 --- a/deps/icu-small/source/common/unicode/platform.h +++ b/deps/icu-small/source/common/unicode/platform.h @@ -38,7 +38,7 @@ * and/or from other macros that are predefined by the compiler * or defined in standard (POSIX or platform or compiler) headers. * - * As a temporary workaround, you can add an explicit #define for some macros + * As a temporary workaround, you can add an explicit \#define for some macros * before it is first tested, or add an equivalent -D macro definition * to the compiler's command line. * @@ -207,6 +207,9 @@ # define CYGWINMSVC #endif */ +#ifdef U_IN_DOXYGEN +# define CYGWINMSVC +#endif /** * \def U_PLATFORM_USES_ONLY_WIN32_API @@ -417,6 +420,9 @@ #ifndef __has_cpp_attribute # define __has_cpp_attribute(x) 0 #endif +#ifndef __has_declspec_attribute +# define __has_declspec_attribute(x) 0 +#endif #ifndef __has_builtin # define __has_builtin(x) 0 #endif @@ -493,13 +499,8 @@ namespace std { */ #ifdef U_NOEXCEPT /* Use the predefined value. */ -#elif defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS /* Visual Studio */ -# define U_NOEXCEPT -#elif U_CPLUSPLUS_VERSION >= 11 || __has_feature(cxx_noexcept) || __has_extension(cxx_noexcept) \ - || (defined(_MSC_VER) && _MSC_VER >= 1900) /* Visual Studio 2015 */ -# define U_NOEXCEPT noexcept #else -# define U_NOEXCEPT +# define U_NOEXCEPT noexcept #endif /** @@ -519,6 +520,8 @@ namespace std { (__has_feature(cxx_attributes) && __has_warning("-Wimplicit-fallthrough")) # define U_FALLTHROUGH [[clang::fallthrough]] # endif +#elif defined(__GNUC__) && (__GNUC__ >= 7) +# define U_FALLTHROUGH __attribute__((fallthrough)) #endif #ifndef U_FALLTHROUGH @@ -763,7 +766,8 @@ namespace std { #elif U_HAVE_CHAR16_T \ || (defined(__xlC__) && defined(__IBM_UTF_LITERAL) && U_SIZEOF_WCHAR_T != 2) \ || (defined(__HP_aCC) && __HP_aCC >= 035000) \ - || (defined(__HP_cc) && __HP_cc >= 111106) + || (defined(__HP_cc) && __HP_cc >= 111106) \ + || (defined(U_IN_DOXYGEN)) # define U_DECLARE_UTF16(string) u ## string #elif U_SIZEOF_WCHAR_T == 2 \ && (U_CHARSET_FAMILY == 0 || (U_PF_OS390 <= U_PLATFORM && U_PLATFORM <= U_PF_OS400 && defined(__UCS2__))) @@ -782,6 +786,8 @@ namespace std { /* Use the predefined value. */ #elif defined(U_STATIC_IMPLEMENTATION) # define U_EXPORT +#elif defined(_MSC_VER) || (__has_declspec_attribute(dllexport) && __has_declspec_attribute(dllimport)) +# define U_EXPORT __declspec(dllexport) #elif defined(__GNUC__) # define U_EXPORT __attribute__((visibility("default"))) #elif (defined(__SUNPRO_CC) && __SUNPRO_CC >= 0x550) \ @@ -789,8 +795,6 @@ namespace std { # define U_EXPORT __global /*#elif defined(__HP_aCC) || defined(__HP_cc) # define U_EXPORT __declspec(dllexport)*/ -#elif defined(_MSC_VER) -# define U_EXPORT __declspec(dllexport) #else # define U_EXPORT #endif @@ -806,7 +810,7 @@ namespace std { #ifdef U_IMPORT /* Use the predefined value. */ -#elif defined(_MSC_VER) +#elif defined(_MSC_VER) || (__has_declspec_attribute(dllexport) && __has_declspec_attribute(dllimport)) /* Windows needs to export/import data. */ # define U_IMPORT __declspec(dllimport) #else diff --git a/deps/icu-small/source/common/unicode/ptypes.h b/deps/icu-small/source/common/unicode/ptypes.h index 6eaf2dbf035725..70324ffee3b9c4 100644 --- a/deps/icu-small/source/common/unicode/ptypes.h +++ b/deps/icu-small/source/common/unicode/ptypes.h @@ -83,6 +83,7 @@ typedef unsigned char uint8_t; #else /* neither U_HAVE_STDINT_H nor U_HAVE_INTTYPES_H */ +/// \cond #if ! U_HAVE_INT8_T typedef signed char int8_t; #endif @@ -122,6 +123,7 @@ typedef unsigned int uint32_t; typedef unsigned long long uint64_t; #endif #endif +/// \endcond #endif /* U_HAVE_STDINT_H / U_HAVE_INTTYPES_H */ diff --git a/deps/icu-small/source/common/unicode/rbbi.h b/deps/icu-small/source/common/unicode/rbbi.h index e9b82cd520736b..47abd554eaf0f1 100644 --- a/deps/icu-small/source/common/unicode/rbbi.h +++ b/deps/icu-small/source/common/unicode/rbbi.h @@ -99,7 +99,7 @@ class U_COMMON_API RuleBasedBreakIterator /*U_FINAL*/ : public BreakIterator { * If present, UStack of LanguageBreakEngine objects that might handle * dictionary characters. Searched from top to bottom to find an object to * handle a given character. - * @internal + * @internal (private) */ UStack *fLanguageBreakEngines; @@ -108,14 +108,14 @@ class U_COMMON_API RuleBasedBreakIterator /*U_FINAL*/ : public BreakIterator { * If present, the special LanguageBreakEngine used for handling * characters that are in the dictionary set, but not handled by any * LangugageBreakEngine. - * @internal + * @internal (private) */ UnhandledEngine *fUnhandledBreakEngine; /** * Counter for the number of characters encountered with the "dictionary" * flag set. - * @internal + * @internal (private) */ uint32_t fDictionaryCharCount; @@ -150,7 +150,7 @@ class U_COMMON_API RuleBasedBreakIterator /*U_FINAL*/ : public BreakIterator { * * The break iterator adopts the memory, and will * free it when done. - * @internal + * @internal (private) */ RuleBasedBreakIterator(RBBIDataHeader* data, UErrorCode &status); diff --git a/deps/icu-small/source/common/unicode/stringoptions.h b/deps/icu-small/source/common/unicode/stringoptions.h index f2de96e9634a02..7b9f70944f62db 100644 --- a/deps/icu-small/source/common/unicode/stringoptions.h +++ b/deps/icu-small/source/common/unicode/stringoptions.h @@ -39,8 +39,6 @@ */ #define U_FOLD_CASE_EXCLUDE_SPECIAL_I 1 -#ifndef U_HIDE_DRAFT_API - /** * Titlecase the string as a whole rather than each word. * (Titlecase only the character at index 0, possibly adjusted.) @@ -50,7 +48,7 @@ * including both an options bit and an explicit BreakIterator. * * @see U_TITLECASE_ADJUST_TO_CASED - * @draft ICU 60 + * @stable ICU 60 */ #define U_TITLECASE_WHOLE_STRING 0x20 @@ -63,12 +61,10 @@ * including both an options bit and an explicit BreakIterator. * * @see U_TITLECASE_ADJUST_TO_CASED - * @draft ICU 60 + * @stable ICU 60 */ #define U_TITLECASE_SENTENCES 0x40 -#endif // U_HIDE_DRAFT_API - /** * Do not lowercase non-initial parts of words when titlecasing. * Option bit for titlecasing APIs that take an options bit set. @@ -112,8 +108,6 @@ */ #define U_TITLECASE_NO_BREAK_ADJUSTMENT 0x200 -#ifndef U_HIDE_DRAFT_API - /** * Adjust each titlecasing BreakIterator index to the next cased character. * (See the Unicode Standard, chapter 3, Default Case Conversion, R3 toTitlecase(X).) @@ -130,7 +124,7 @@ * It is an error to specify multiple titlecasing adjustment options together. * * @see U_TITLECASE_NO_BREAK_ADJUSTMENT - * @draft ICU 60 + * @stable ICU 60 */ #define U_TITLECASE_ADJUST_TO_CASED 0x400 @@ -141,7 +135,7 @@ * @see CaseMap * @see Edits * @see Normalizer2 - * @draft ICU 60 + * @stable ICU 60 */ #define U_EDITS_NO_RESET 0x2000 @@ -153,12 +147,10 @@ * @see CaseMap * @see Edits * @see Normalizer2 - * @draft ICU 60 + * @stable ICU 60 */ #define U_OMIT_UNCHANGED_TEXT 0x4000 -#endif // U_HIDE_DRAFT_API - /** * Option bit for u_strCaseCompare, u_strcasecmp, unorm_compare, etc: * Compare strings in code point order instead of code unit order. diff --git a/deps/icu-small/source/common/unicode/stringtriebuilder.h b/deps/icu-small/source/common/unicode/stringtriebuilder.h index 8d2b229413cd6d..c27fbd67960d70 100644 --- a/deps/icu-small/source/common/unicode/stringtriebuilder.h +++ b/deps/icu-small/source/common/unicode/stringtriebuilder.h @@ -26,8 +26,10 @@ */ // Forward declaration. +/// \cond struct UHashtable; typedef struct UHashtable UHashtable; +/// \endcond /** * Build options for BytesTrieBuilder and CharsTrieBuilder. @@ -64,7 +66,7 @@ class U_COMMON_API StringTrieBuilder : public UObject { public: #ifndef U_HIDE_INTERNAL_API /** @internal */ - static UBool hashNode(const void *node); + static int32_t hashNode(const void *node); /** @internal */ static UBool equalNodes(const void *left, const void *right); #endif /* U_HIDE_INTERNAL_API */ @@ -188,7 +190,10 @@ class U_COMMON_API StringTrieBuilder : public UObject { // Do not conditionalize the following with #ifndef U_HIDE_INTERNAL_API, // it is needed for layout of other objects. - /** @internal */ + /** + * @internal + * \cond + */ class Node : public UObject { public: Node(int32_t initialHash) : hash(initialHash), offset(0) {} @@ -391,7 +396,9 @@ class U_COMMON_API StringTrieBuilder : public UObject { int32_t length; Node *next; // A branch sub-node. }; + #endif /* U_HIDE_INTERNAL_API */ + /// \endcond /** @internal */ virtual Node *createLinearMatchNode(int32_t i, int32_t unitIndex, int32_t length, diff --git a/deps/icu-small/source/common/unicode/ubidi.h b/deps/icu-small/source/common/unicode/ubidi.h index 254a5bf9ef469f..f4875c8801efd6 100644 --- a/deps/icu-small/source/common/unicode/ubidi.h +++ b/deps/icu-small/source/common/unicode/ubidi.h @@ -323,6 +323,10 @@ * these special values are designed that way. Also, the implementation * assumes that UBIDI_MAX_EXPLICIT_LEVEL is odd. * + * Note: The numeric values of the related constants will not change: + * They are tied to the use of 7-bit byte values (plus the override bit) + * and of the UBiDiLevel=uint8_t data type in this API. + * * @see UBIDI_DEFAULT_LTR * @see UBIDI_DEFAULT_RTL * @see UBIDI_LEVEL_OVERRIDE @@ -386,6 +390,8 @@ typedef uint8_t UBiDiLevel; /** * Maximum explicit embedding level. + * Same as the max_depth value in the + * Unicode Bidirectional Algorithm. * (The maximum resolved level can be up to UBIDI_MAX_EXPLICIT_LEVEL+1). * @stable ICU 2.0 */ @@ -1996,7 +2002,7 @@ U_CDECL_BEGIN * * @return The directional property / Bidi class for the given code point * c if the default class has been overridden, or - * #U_BIDI_CLASS_DEFAULT=u_getIntPropertyMaxValue(UCHAR_BIDI_CLASS)+1 + * u_getIntPropertyMaxValue(UCHAR_BIDI_CLASS)+1 * if the standard Bidi class value for c is to be used. * @see ubidi_setClassCallback * @see ubidi_getClassCallback @@ -2010,7 +2016,7 @@ U_CDECL_END /** * Retrieve the Bidi class for a given code point. *

If a #UBiDiClassCallback callback is defined and returns a - * value other than #U_BIDI_CLASS_DEFAULT=u_getIntPropertyMaxValue(UCHAR_BIDI_CLASS)+1, + * value other than u_getIntPropertyMaxValue(UCHAR_BIDI_CLASS)+1, * that value is used; otherwise the default class determination mechanism is invoked.

* * @param pBiDi is the paragraph UBiDi object. diff --git a/deps/icu-small/source/common/unicode/ubiditransform.h b/deps/icu-small/source/common/unicode/ubiditransform.h index 627b005ed45f8d..5c08ed5df0fd90 100644 --- a/deps/icu-small/source/common/unicode/ubiditransform.h +++ b/deps/icu-small/source/common/unicode/ubiditransform.h @@ -26,33 +26,38 @@ /** * \file * \brief Bidi Transformations + */ + +/** + * `UBiDiOrder` indicates the order of text. * - * UBiDiOrder indicates the order of text.

* This bidi transformation engine supports all possible combinations (4 in * total) of input and output text order: - *

    - *
  • : unless the output direction is RTL, this - * corresponds to a normal operation of the Bidi algorithm as described in the - * Unicode Technical Report and implemented by UBiDi when the - * reordering mode is set to UBIDI_REORDER_DEFAULT. Visual RTL - * mode is not supported by UBiDi and is accomplished through - * reversing a visual LTR string,
  • - *
  • : unless the input direction is RTL, this - * corresponds to an "inverse bidi algorithm" in UBiDi with the - * reordering mode set to UBIDI_REORDER_INVERSE_LIKE_DIRECT. - * Visual RTL mode is not not supported by UBiDi and is - * accomplished through reversing a visual LTR string,
  • - *
  • : if the input and output base directions - * mismatch, this corresponds to the UBiDi implementation with the - * reordering mode set to UBIDI_REORDER_RUNS_ONLY; and if the - * input and output base directions are identical, the transformation engine - * will only handle character mirroring and Arabic shaping operations without - * reordering,
  • - *
  • : this reordering mode is not supported by - * the UBiDi engine; it implies character mirroring, Arabic - * shaping, and - if the input/output base directions mismatch - string - * reverse operations.
  • - *
+ * + * - : unless the output direction is RTL, this + * corresponds to a normal operation of the Bidi algorithm as described in the + * Unicode Technical Report and implemented by `UBiDi` when the + * reordering mode is set to `UBIDI_REORDER_DEFAULT`. Visual RTL + * mode is not supported by `UBiDi` and is accomplished through + * reversing a visual LTR string, + * + * - : unless the input direction is RTL, this + * corresponds to an "inverse bidi algorithm" in `UBiDi` with the + * reordering mode set to `UBIDI_REORDER_INVERSE_LIKE_DIRECT`. + * Visual RTL mode is not not supported by `UBiDi` and is + * accomplished through reversing a visual LTR string, + * + * - : if the input and output base directions + * mismatch, this corresponds to the `UBiDi` implementation with the + * reordering mode set to `UBIDI_REORDER_RUNS_ONLY`; and if the + * input and output base directions are identical, the transformation engine + * will only handle character mirroring and Arabic shaping operations without + * reordering, + * + * - : this reordering mode is not supported by + * the `UBiDi` engine; it implies character mirroring, Arabic + * shaping, and - if the input/output base directions mismatch - string + * reverse operations. * @see ubidi_setInverse * @see ubidi_setReorderingMode * @see UBIDI_REORDER_DEFAULT diff --git a/deps/icu-small/source/common/unicode/uchar.h b/deps/icu-small/source/common/unicode/uchar.h index 6d31083e66ee0d..9e180db53b665a 100644 --- a/deps/icu-small/source/common/unicode/uchar.h +++ b/deps/icu-small/source/common/unicode/uchar.h @@ -27,6 +27,24 @@ #include "unicode/utypes.h" #include "unicode/stringoptions.h" +#include "unicode/ucpmap.h" + +#if !defined(USET_DEFINED) && !defined(U_IN_DOXYGEN) + +#define USET_DEFINED + +/** + * USet is the C API type corresponding to C++ class UnicodeSet. + * It is forward-declared here to avoid including unicode/uset.h file if related + * APIs are not used. + * + * @see ucnv_getUnicodeSet + * @stable ICU 2.4 + */ +typedef struct USet USet; + +#endif + U_CDECL_BEGIN @@ -61,6 +79,18 @@ U_CDECL_BEGIN * "About the Unicode Character Database" (http://www.unicode.org/ucd/) * and the ICU User Guide chapter on Properties (http://icu-project.org/userguide/properties.html). * + * Many properties are accessible via generic functions that take a UProperty selector. + * - u_hasBinaryProperty() returns a binary value (TRUE/FALSE) per property and code point. + * - u_getIntPropertyValue() returns an integer value per property and code point. + * For each supported enumerated or catalog property, there is + * an enum type for all of the property's values, and + * u_getIntPropertyValue() returns the numeric values of those constants. + * - u_getBinaryPropertySet() returns a set for each ICU-supported binary property with + * all code points for which the property is true. + * - u_getIntPropertyMap() returns a map for each + * ICU-supported enumerated/catalog/int-valued property which + * maps all Unicode code points to their values for that property. + * * Many functions are designed to match java.lang.Character functions. * See the individual function documentation, * and see the JDK 1.4 java.lang.Character documentation @@ -546,12 +576,34 @@ typedef enum UProperty { (http://www.unicode.org/reports/tr9/) Returns UBidiPairedBracketType values. @stable ICU 52 */ UCHAR_BIDI_PAIRED_BRACKET_TYPE=0x1015, + /** + * Enumerated property Indic_Positional_Category. + * New in Unicode 6.0 as provisional property Indic_Matra_Category; + * renamed and changed to informative in Unicode 8.0. + * See http://www.unicode.org/reports/tr44/#IndicPositionalCategory.txt + * @stable ICU 63 + */ + UCHAR_INDIC_POSITIONAL_CATEGORY=0x1016, + /** + * Enumerated property Indic_Syllabic_Category. + * New in Unicode 6.0 as provisional; informative since Unicode 8.0. + * See http://www.unicode.org/reports/tr44/#IndicSyllabicCategory.txt + * @stable ICU 63 + */ + UCHAR_INDIC_SYLLABIC_CATEGORY=0x1017, + /** + * Enumerated property Vertical_Orientation. + * Used for UAX #50 Unicode Vertical Text Layout (https://www.unicode.org/reports/tr50/). + * New as a UCD property in Unicode 10.0. + * @stable ICU 63 + */ + UCHAR_VERTICAL_ORIENTATION=0x1018, #ifndef U_HIDE_DEPRECATED_API /** * One more than the last constant for enumerated/integer Unicode properties. * @deprecated ICU 58 The numeric value may change over time, see ICU ticket #12420. */ - UCHAR_INT_LIMIT=0x1016, + UCHAR_INT_LIMIT=0x1019, #endif // U_HIDE_DEPRECATED_API /** Bitmask property General_Category_Mask. @@ -2320,6 +2372,161 @@ typedef enum UHangulSyllableType { #endif // U_HIDE_DEPRECATED_API } UHangulSyllableType; +/** + * Indic Positional Category constants. + * + * @see UCHAR_INDIC_POSITIONAL_CATEGORY + * @stable ICU 63 + */ +typedef enum UIndicPositionalCategory { + /* + * Note: UIndicPositionalCategory constants are parsed by preparseucd.py. + * It matches lines like + * U_INPC_ + */ + + /** @stable ICU 63 */ + U_INPC_NA, + /** @stable ICU 63 */ + U_INPC_BOTTOM, + /** @stable ICU 63 */ + U_INPC_BOTTOM_AND_LEFT, + /** @stable ICU 63 */ + U_INPC_BOTTOM_AND_RIGHT, + /** @stable ICU 63 */ + U_INPC_LEFT, + /** @stable ICU 63 */ + U_INPC_LEFT_AND_RIGHT, + /** @stable ICU 63 */ + U_INPC_OVERSTRUCK, + /** @stable ICU 63 */ + U_INPC_RIGHT, + /** @stable ICU 63 */ + U_INPC_TOP, + /** @stable ICU 63 */ + U_INPC_TOP_AND_BOTTOM, + /** @stable ICU 63 */ + U_INPC_TOP_AND_BOTTOM_AND_RIGHT, + /** @stable ICU 63 */ + U_INPC_TOP_AND_LEFT, + /** @stable ICU 63 */ + U_INPC_TOP_AND_LEFT_AND_RIGHT, + /** @stable ICU 63 */ + U_INPC_TOP_AND_RIGHT, + /** @stable ICU 63 */ + U_INPC_VISUAL_ORDER_LEFT, +} UIndicPositionalCategory; + +/** + * Indic Syllabic Category constants. + * + * @see UCHAR_INDIC_SYLLABIC_CATEGORY + * @stable ICU 63 + */ +typedef enum UIndicSyllabicCategory { + /* + * Note: UIndicSyllabicCategory constants are parsed by preparseucd.py. + * It matches lines like + * U_INSC_ + */ + + /** @stable ICU 63 */ + U_INSC_OTHER, + /** @stable ICU 63 */ + U_INSC_AVAGRAHA, + /** @stable ICU 63 */ + U_INSC_BINDU, + /** @stable ICU 63 */ + U_INSC_BRAHMI_JOINING_NUMBER, + /** @stable ICU 63 */ + U_INSC_CANTILLATION_MARK, + /** @stable ICU 63 */ + U_INSC_CONSONANT, + /** @stable ICU 63 */ + U_INSC_CONSONANT_DEAD, + /** @stable ICU 63 */ + U_INSC_CONSONANT_FINAL, + /** @stable ICU 63 */ + U_INSC_CONSONANT_HEAD_LETTER, + /** @stable ICU 63 */ + U_INSC_CONSONANT_INITIAL_POSTFIXED, + /** @stable ICU 63 */ + U_INSC_CONSONANT_KILLER, + /** @stable ICU 63 */ + U_INSC_CONSONANT_MEDIAL, + /** @stable ICU 63 */ + U_INSC_CONSONANT_PLACEHOLDER, + /** @stable ICU 63 */ + U_INSC_CONSONANT_PRECEDING_REPHA, + /** @stable ICU 63 */ + U_INSC_CONSONANT_PREFIXED, + /** @stable ICU 63 */ + U_INSC_CONSONANT_SUBJOINED, + /** @stable ICU 63 */ + U_INSC_CONSONANT_SUCCEEDING_REPHA, + /** @stable ICU 63 */ + U_INSC_CONSONANT_WITH_STACKER, + /** @stable ICU 63 */ + U_INSC_GEMINATION_MARK, + /** @stable ICU 63 */ + U_INSC_INVISIBLE_STACKER, + /** @stable ICU 63 */ + U_INSC_JOINER, + /** @stable ICU 63 */ + U_INSC_MODIFYING_LETTER, + /** @stable ICU 63 */ + U_INSC_NON_JOINER, + /** @stable ICU 63 */ + U_INSC_NUKTA, + /** @stable ICU 63 */ + U_INSC_NUMBER, + /** @stable ICU 63 */ + U_INSC_NUMBER_JOINER, + /** @stable ICU 63 */ + U_INSC_PURE_KILLER, + /** @stable ICU 63 */ + U_INSC_REGISTER_SHIFTER, + /** @stable ICU 63 */ + U_INSC_SYLLABLE_MODIFIER, + /** @stable ICU 63 */ + U_INSC_TONE_LETTER, + /** @stable ICU 63 */ + U_INSC_TONE_MARK, + /** @stable ICU 63 */ + U_INSC_VIRAMA, + /** @stable ICU 63 */ + U_INSC_VISARGA, + /** @stable ICU 63 */ + U_INSC_VOWEL, + /** @stable ICU 63 */ + U_INSC_VOWEL_DEPENDENT, + /** @stable ICU 63 */ + U_INSC_VOWEL_INDEPENDENT, +} UIndicSyllabicCategory; + +/** + * Vertical Orientation constants. + * + * @see UCHAR_VERTICAL_ORIENTATION + * @stable ICU 63 + */ +typedef enum UVerticalOrientation { + /* + * Note: UVerticalOrientation constants are parsed by preparseucd.py. + * It matches lines like + * U_VO_ + */ + + /** @stable ICU 63 */ + U_VO_ROTATED, + /** @stable ICU 63 */ + U_VO_TRANSFORMED_ROTATED, + /** @stable ICU 63 */ + U_VO_TRANSFORMED_UPRIGHT, + /** @stable ICU 63 */ + U_VO_UPRIGHT, +} UVerticalOrientation; + /** * Check a binary Unicode property for a code point. * @@ -2342,6 +2549,7 @@ typedef enum UHangulSyllableType { * does not have data for the property at all, or not for this code point. * * @see UProperty + * @see u_getBinaryPropertySet * @see u_getIntPropertyValue * @see u_getUnicodeVersion * @stable ICU 2.1 @@ -2349,6 +2557,28 @@ typedef enum UHangulSyllableType { U_STABLE UBool U_EXPORT2 u_hasBinaryProperty(UChar32 c, UProperty which); +#ifndef U_HIDE_DRAFT_API + +/** + * Returns a frozen USet for a binary property. + * The library retains ownership over the returned object. + * Sets an error code if the property number is not one for a binary property. + * + * The returned set contains all code points for which the property is true. + * + * @param property UCHAR_BINARY_START..UCHAR_BINARY_LIMIT-1 + * @param pErrorCode an in/out ICU UErrorCode + * @return the property as a set + * @see UProperty + * @see u_hasBinaryProperty + * @see Unicode::fromUSet + * @draft ICU 63 + */ +U_CAPI const USet * U_EXPORT2 +u_getBinaryPropertySet(UProperty property, UErrorCode *pErrorCode); + +#endif // U_HIDE_DRAFT_API + /** * Check if a code point has the Alphabetic Unicode property. * Same as u_hasBinaryProperty(c, UCHAR_ALPHABETIC). @@ -2449,6 +2679,7 @@ u_isUWhiteSpace(UChar32 c); * @see u_hasBinaryProperty * @see u_getIntPropertyMinValue * @see u_getIntPropertyMaxValue + * @see u_getIntPropertyMap * @see u_getUnicodeVersion * @stable ICU 2.2 */ @@ -2505,6 +2736,28 @@ u_getIntPropertyMinValue(UProperty which); U_STABLE int32_t U_EXPORT2 u_getIntPropertyMaxValue(UProperty which); +#ifndef U_HIDE_DRAFT_API + +/** + * Returns an immutable UCPMap for an enumerated/catalog/int-valued property. + * The library retains ownership over the returned object. + * Sets an error code if the property number is not one for an "int property". + * + * The returned object maps all Unicode code points to their values for that property. + * For documentation of the integer values see u_getIntPropertyValue(). + * + * @param property UCHAR_INT_START..UCHAR_INT_LIMIT-1 + * @param pErrorCode an in/out ICU UErrorCode + * @return the property as a map + * @see UProperty + * @see u_getIntPropertyValue + * @draft ICU 63 + */ +U_CAPI const UCPMap * U_EXPORT2 +u_getIntPropertyMap(UProperty property, UErrorCode *pErrorCode); + +#endif // U_HIDE_DRAFT_API + /** * Get the numeric value for a Unicode code point as defined in the * Unicode Character Database. diff --git a/deps/icu-small/source/common/unicode/ucnv.h b/deps/icu-small/source/common/unicode/ucnv.h index 53b4c6f0733aca..ec7c5f350b4973 100644 --- a/deps/icu-small/source/common/unicode/ucnv.h +++ b/deps/icu-small/source/common/unicode/ucnv.h @@ -53,19 +53,18 @@ #include "unicode/uenum.h" #include "unicode/localpointer.h" -#ifndef __USET_H__ +#if !defined(USET_DEFINED) && !defined(U_IN_DOXYGEN) + +#define USET_DEFINED /** - * USet is the C API type for Unicode sets. - * It is forward-declared here to avoid including the header file if related + * USet is the C API type corresponding to C++ class UnicodeSet. + * It is forward-declared here to avoid including unicode/uset.h file if related * conversion APIs are not used. - * See unicode/uset.h * * @see ucnv_getUnicodeSet - * @stable ICU 2.6 + * @stable ICU 2.4 */ -struct USet; -/** @stable ICU 2.6 */ typedef struct USet USet; #endif diff --git a/deps/icu-small/source/common/unicode/uconfig.h b/deps/icu-small/source/common/unicode/uconfig.h index 5e28a146de3fff..3a7d2db9aa07c8 100644 --- a/deps/icu-small/source/common/unicode/uconfig.h +++ b/deps/icu-small/source/common/unicode/uconfig.h @@ -183,7 +183,7 @@ */ #ifdef U_HAVE_LIB_SUFFIX /* Use the predefined value. */ -#elif defined(U_LIB_SUFFIX_C_NAME) +#elif defined(U_LIB_SUFFIX_C_NAME) || defined(U_IN_DOXYGEN) # define U_HAVE_LIB_SUFFIX 1 #endif @@ -431,17 +431,6 @@ # define UCONFIG_HAVE_PARSEALLINPUT 1 #endif - -/** - * \def UCONFIG_FORMAT_FASTPATHS_49 - * This switch turns on other formatting fastpaths. Binary incompatible in object DecimalFormat and DecimalFormatSymbols - * - * @internal - */ -#ifndef UCONFIG_FORMAT_FASTPATHS_49 -# define UCONFIG_FORMAT_FASTPATHS_49 1 -#endif - /** * \def UCONFIG_NO_FILTERED_BREAK_ITERATION * This switch turns off filtered break iteration code. diff --git a/deps/icu-small/source/common/unicode/ucpmap.h b/deps/icu-small/source/common/unicode/ucpmap.h new file mode 100644 index 00000000000000..f2c42b6b7f4bee --- /dev/null +++ b/deps/icu-small/source/common/unicode/ucpmap.h @@ -0,0 +1,162 @@ +// © 2018 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html + +// ucpmap.h +// created: 2018sep03 Markus W. Scherer + +#ifndef __UCPMAP_H__ +#define __UCPMAP_H__ + +#include "unicode/utypes.h" + +#ifndef U_HIDE_DRAFT_API + +U_CDECL_BEGIN + +/** + * \file + * + * This file defines an abstract map from Unicode code points to integer values. + * + * @see UCPMap + * @see UCPTrie + * @see UMutableCPTrie + */ + +/** + * Abstract map from Unicode code points (U+0000..U+10FFFF) to integer values. + * + * @see UCPTrie + * @see UMutableCPTrie + * @draft ICU 63 + */ +typedef struct UCPMap UCPMap; + +/** + * Selectors for how ucpmap_getRange() etc. should report value ranges overlapping with surrogates. + * Most users should use UCPMAP_RANGE_NORMAL. + * + * @see ucpmap_getRange + * @see ucptrie_getRange + * @see umutablecptrie_getRange + * @draft ICU 63 + */ +enum UCPMapRangeOption { + /** + * ucpmap_getRange() enumerates all same-value ranges as stored in the map. + * Most users should use this option. + * @draft ICU 63 + */ + UCPMAP_RANGE_NORMAL, + /** + * ucpmap_getRange() enumerates all same-value ranges as stored in the map, + * except that lead surrogates (U+D800..U+DBFF) are treated as having the + * surrogateValue, which is passed to getRange() as a separate parameter. + * The surrogateValue is not transformed via filter(). + * See U_IS_LEAD(c). + * + * Most users should use UCPMAP_RANGE_NORMAL instead. + * + * This option is useful for maps that map surrogate code *units* to + * special values optimized for UTF-16 string processing + * or for special error behavior for unpaired surrogates, + * but those values are not to be associated with the lead surrogate code *points*. + * @draft ICU 63 + */ + UCPMAP_RANGE_FIXED_LEAD_SURROGATES, + /** + * ucpmap_getRange() enumerates all same-value ranges as stored in the map, + * except that all surrogates (U+D800..U+DFFF) are treated as having the + * surrogateValue, which is passed to getRange() as a separate parameter. + * The surrogateValue is not transformed via filter(). + * See U_IS_SURROGATE(c). + * + * Most users should use UCPMAP_RANGE_NORMAL instead. + * + * This option is useful for maps that map surrogate code *units* to + * special values optimized for UTF-16 string processing + * or for special error behavior for unpaired surrogates, + * but those values are not to be associated with the lead surrogate code *points*. + * @draft ICU 63 + */ + UCPMAP_RANGE_FIXED_ALL_SURROGATES +}; +#ifndef U_IN_DOXYGEN +typedef enum UCPMapRangeOption UCPMapRangeOption; +#endif + +/** + * Returns the value for a code point as stored in the map, with range checking. + * Returns an implementation-defined error value if c is not in the range 0..U+10FFFF. + * + * @param map the map + * @param c the code point + * @return the map value, + * or an implementation-defined error value if the code point is not in the range 0..U+10FFFF + * @draft ICU 63 + */ +U_CAPI uint32_t U_EXPORT2 +ucpmap_get(const UCPMap *map, UChar32 c); + +/** + * Callback function type: Modifies a map value. + * Optionally called by ucpmap_getRange()/ucptrie_getRange()/umutablecptrie_getRange(). + * The modified value will be returned by the getRange function. + * + * Can be used to ignore some of the value bits, + * make a filter for one of several values, + * return a value index computed from the map value, etc. + * + * @param context an opaque pointer, as passed into the getRange function + * @param value a value from the map + * @return the modified value + * @draft ICU 63 + */ +typedef uint32_t U_CALLCONV +UCPMapValueFilter(const void *context, uint32_t value); + +/** + * Returns the last code point such that all those from start to there have the same value. + * Can be used to efficiently iterate over all same-value ranges in a map. + * (This is normally faster than iterating over code points and get()ting each value, + * but much slower than a data structure that stores ranges directly.) + * + * If the UCPMapValueFilter function pointer is not NULL, then + * the value to be delivered is passed through that function, and the return value is the end + * of the range where all values are modified to the same actual value. + * The value is unchanged if that function pointer is NULL. + * + * Example: + * \code + * UChar32 start = 0, end; + * uint32_t value; + * while ((end = ucpmap_getRange(map, start, UCPMAP_RANGE_NORMAL, 0, + * NULL, NULL, &value)) >= 0) { + * // Work with the range start..end and its value. + * start = end + 1; + * } + * \endcode + * + * @param map the map + * @param start range start + * @param option defines whether surrogates are treated normally, + * or as having the surrogateValue; usually UCPMAP_RANGE_NORMAL + * @param surrogateValue value for surrogates; ignored if option==UCPMAP_RANGE_NORMAL + * @param filter a pointer to a function that may modify the map data value, + * or NULL if the values from the map are to be used unmodified + * @param context an opaque pointer that is passed on to the filter function + * @param pValue if not NULL, receives the value that every code point start..end has; + * may have been modified by filter(context, map value) + * if that function pointer is not NULL + * @return the range end code point, or -1 if start is not a valid code point + * @draft ICU 63 + */ +U_CAPI UChar32 U_EXPORT2 +ucpmap_getRange(const UCPMap *map, UChar32 start, + UCPMapRangeOption option, uint32_t surrogateValue, + UCPMapValueFilter *filter, const void *context, uint32_t *pValue); + +U_CDECL_END + +#endif // U_HIDE_DRAFT_API +#endif diff --git a/deps/icu-small/source/common/unicode/ucptrie.h b/deps/icu-small/source/common/unicode/ucptrie.h new file mode 100644 index 00000000000000..2718c984e43197 --- /dev/null +++ b/deps/icu-small/source/common/unicode/ucptrie.h @@ -0,0 +1,646 @@ +// © 2017 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html + +// ucptrie.h (modified from utrie2.h) +// created: 2017dec29 Markus W. Scherer + +#ifndef __UCPTRIE_H__ +#define __UCPTRIE_H__ + +#include "unicode/utypes.h" + +#ifndef U_HIDE_DRAFT_API + +#include "unicode/localpointer.h" +#include "unicode/ucpmap.h" +#include "unicode/utf8.h" + +U_CDECL_BEGIN + +/** + * \file + * + * This file defines an immutable Unicode code point trie. + * + * @see UCPTrie + * @see UMutableCPTrie + */ + +#ifndef U_IN_DOXYGEN +/** @internal */ +typedef union UCPTrieData { + /** @internal */ + const void *ptr0; + /** @internal */ + const uint16_t *ptr16; + /** @internal */ + const uint32_t *ptr32; + /** @internal */ + const uint8_t *ptr8; +} UCPTrieData; +#endif + +/** + * Immutable Unicode code point trie structure. + * Fast, reasonably compact, map from Unicode code points (U+0000..U+10FFFF) to integer values. + * For details see http://site.icu-project.org/design/struct/utrie + * + * Do not access UCPTrie fields directly; use public functions and macros. + * Functions are easy to use: They support all trie types and value widths. + * + * When performance is really important, macros provide faster access. + * Most macros are specific to either "fast" or "small" tries, see UCPTrieType. + * There are "fast" macros for special optimized use cases. + * + * The macros will return bogus values, or may crash, if used on the wrong type or value width. + * + * @see UMutableCPTrie + * @draft ICU 63 + */ +struct UCPTrie { +#ifndef U_IN_DOXYGEN + /** @internal */ + const uint16_t *index; + /** @internal */ + UCPTrieData data; + + /** @internal */ + int32_t indexLength; + /** @internal */ + int32_t dataLength; + /** Start of the last range which ends at U+10FFFF. @internal */ + UChar32 highStart; + /** highStart>>12 @internal */ + uint16_t shifted12HighStart; + + /** @internal */ + int8_t type; // UCPTrieType + /** @internal */ + int8_t valueWidth; // UCPTrieValueWidth + + /** padding/reserved @internal */ + uint32_t reserved32; + /** padding/reserved @internal */ + uint16_t reserved16; + + /** + * Internal index-3 null block offset. + * Set to an impossibly high value (e.g., 0xffff) if there is no dedicated index-3 null block. + * @internal + */ + uint16_t index3NullOffset; + /** + * Internal data null block offset, not shifted. + * Set to an impossibly high value (e.g., 0xfffff) if there is no dedicated data null block. + * @internal + */ + int32_t dataNullOffset; + /** @internal */ + uint32_t nullValue; + +#ifdef UCPTRIE_DEBUG + /** @internal */ + const char *name; +#endif +#endif +}; +#ifndef U_IN_DOXYGEN +typedef struct UCPTrie UCPTrie; +#endif + +/** + * Selectors for the type of a UCPTrie. + * Different trade-offs for size vs. speed. + * + * @see umutablecptrie_buildImmutable + * @see ucptrie_openFromBinary + * @see ucptrie_getType + * @draft ICU 63 + */ +enum UCPTrieType { + /** + * For ucptrie_openFromBinary() to accept any type. + * ucptrie_getType() will return the actual type. + * @draft ICU 63 + */ + UCPTRIE_TYPE_ANY = -1, + /** + * Fast/simple/larger BMP data structure. Use functions and "fast" macros. + * @draft ICU 63 + */ + UCPTRIE_TYPE_FAST, + /** + * Small/slower BMP data structure. Use functions and "small" macros. + * @draft ICU 63 + */ + UCPTRIE_TYPE_SMALL +}; +#ifndef U_IN_DOXYGEN +typedef enum UCPTrieType UCPTrieType; +#endif + +/** + * Selectors for the number of bits in a UCPTrie data value. + * + * @see umutablecptrie_buildImmutable + * @see ucptrie_openFromBinary + * @see ucptrie_getValueWidth + * @draft ICU 63 + */ +enum UCPTrieValueWidth { + /** + * For ucptrie_openFromBinary() to accept any data value width. + * ucptrie_getValueWidth() will return the actual data value width. + * @draft ICU 63 + */ + UCPTRIE_VALUE_BITS_ANY = -1, + /** + * The trie stores 16 bits per data value. + * It returns them as unsigned values 0..0xffff=65535. + * @draft ICU 63 + */ + UCPTRIE_VALUE_BITS_16, + /** + * The trie stores 32 bits per data value. + * @draft ICU 63 + */ + UCPTRIE_VALUE_BITS_32, + /** + * The trie stores 8 bits per data value. + * It returns them as unsigned values 0..0xff=255. + * @draft ICU 63 + */ + UCPTRIE_VALUE_BITS_8 +}; +#ifndef U_IN_DOXYGEN +typedef enum UCPTrieValueWidth UCPTrieValueWidth; +#endif + +/** + * Opens a trie from its binary form, stored in 32-bit-aligned memory. + * Inverse of ucptrie_toBinary(). + * + * The memory must remain valid and unchanged as long as the trie is used. + * You must ucptrie_close() the trie once you are done using it. + * + * @param type selects the trie type; results in an + * U_INVALID_FORMAT_ERROR if it does not match the binary data; + * use UCPTRIE_TYPE_ANY to accept any type + * @param valueWidth selects the number of bits in a data value; results in an + * U_INVALID_FORMAT_ERROR if it does not match the binary data; + * use UCPTRIE_VALUE_BITS_ANY to accept any data value width + * @param data a pointer to 32-bit-aligned memory containing the binary data of a UCPTrie + * @param length the number of bytes available at data; + * can be more than necessary + * @param pActualLength receives the actual number of bytes at data taken up by the trie data; + * can be NULL + * @param pErrorCode an in/out ICU UErrorCode + * @return the trie + * + * @see umutablecptrie_open + * @see umutablecptrie_buildImmutable + * @see ucptrie_toBinary + * @draft ICU 63 + */ +U_CAPI UCPTrie * U_EXPORT2 +ucptrie_openFromBinary(UCPTrieType type, UCPTrieValueWidth valueWidth, + const void *data, int32_t length, int32_t *pActualLength, + UErrorCode *pErrorCode); + +/** + * Closes a trie and releases associated memory. + * + * @param trie the trie + * @draft ICU 63 + */ +U_CAPI void U_EXPORT2 +ucptrie_close(UCPTrie *trie); + +#if U_SHOW_CPLUSPLUS_API + +U_NAMESPACE_BEGIN + +/** + * \class LocalUCPTriePointer + * "Smart pointer" class, closes a UCPTrie via ucptrie_close(). + * For most methods see the LocalPointerBase base class. + * + * @see LocalPointerBase + * @see LocalPointer + * @draft ICU 63 + */ +U_DEFINE_LOCAL_OPEN_POINTER(LocalUCPTriePointer, UCPTrie, ucptrie_close); + +U_NAMESPACE_END + +#endif + +/** + * Returns the trie type. + * + * @param trie the trie + * @return the trie type + * @see ucptrie_openFromBinary + * @see UCPTRIE_TYPE_ANY + * @draft ICU 63 + */ +U_CAPI UCPTrieType U_EXPORT2 +ucptrie_getType(const UCPTrie *trie); + +/** + * Returns the number of bits in a trie data value. + * + * @param trie the trie + * @return the number of bits in a trie data value + * @see ucptrie_openFromBinary + * @see UCPTRIE_VALUE_BITS_ANY + * @draft ICU 63 + */ +U_CAPI UCPTrieValueWidth U_EXPORT2 +ucptrie_getValueWidth(const UCPTrie *trie); + +/** + * Returns the value for a code point as stored in the trie, with range checking. + * Returns the trie error value if c is not in the range 0..U+10FFFF. + * + * Easier to use than UCPTRIE_FAST_GET() and similar macros but slower. + * Easier to use because, unlike the macros, this function works on all UCPTrie + * objects, for all types and value widths. + * + * @param trie the trie + * @param c the code point + * @return the trie value, + * or the trie error value if the code point is not in the range 0..U+10FFFF + * @draft ICU 63 + */ +U_CAPI uint32_t U_EXPORT2 +ucptrie_get(const UCPTrie *trie, UChar32 c); + +/** + * Returns the last code point such that all those from start to there have the same value. + * Can be used to efficiently iterate over all same-value ranges in a trie. + * (This is normally faster than iterating over code points and get()ting each value, + * but much slower than a data structure that stores ranges directly.) + * + * If the UCPMapValueFilter function pointer is not NULL, then + * the value to be delivered is passed through that function, and the return value is the end + * of the range where all values are modified to the same actual value. + * The value is unchanged if that function pointer is NULL. + * + * Example: + * \code + * UChar32 start = 0, end; + * uint32_t value; + * while ((end = ucptrie_getRange(trie, start, UCPMAP_RANGE_NORMAL, 0, + * NULL, NULL, &value)) >= 0) { + * // Work with the range start..end and its value. + * start = end + 1; + * } + * \endcode + * + * @param trie the trie + * @param start range start + * @param option defines whether surrogates are treated normally, + * or as having the surrogateValue; usually UCPMAP_RANGE_NORMAL + * @param surrogateValue value for surrogates; ignored if option==UCPMAP_RANGE_NORMAL + * @param filter a pointer to a function that may modify the trie data value, + * or NULL if the values from the trie are to be used unmodified + * @param context an opaque pointer that is passed on to the filter function + * @param pValue if not NULL, receives the value that every code point start..end has; + * may have been modified by filter(context, trie value) + * if that function pointer is not NULL + * @return the range end code point, or -1 if start is not a valid code point + * @draft ICU 63 + */ +U_CAPI UChar32 U_EXPORT2 +ucptrie_getRange(const UCPTrie *trie, UChar32 start, + UCPMapRangeOption option, uint32_t surrogateValue, + UCPMapValueFilter *filter, const void *context, uint32_t *pValue); + +/** + * Writes a memory-mappable form of the trie into 32-bit aligned memory. + * Inverse of ucptrie_openFromBinary(). + * + * @param trie the trie + * @param data a pointer to 32-bit-aligned memory to be filled with the trie data; + * can be NULL if capacity==0 + * @param capacity the number of bytes available at data, or 0 for pure preflighting + * @param pErrorCode an in/out ICU UErrorCode; + * U_BUFFER_OVERFLOW_ERROR if the capacity is too small + * @return the number of bytes written or (if buffer overflow) needed for the trie + * + * @see ucptrie_openFromBinary() + * @draft ICU 63 + */ +U_CAPI int32_t U_EXPORT2 +ucptrie_toBinary(const UCPTrie *trie, void *data, int32_t capacity, UErrorCode *pErrorCode); + +/** + * Macro parameter value for a trie with 16-bit data values. + * Use the name of this macro as a "dataAccess" parameter in other macros. + * Do not use this macro in any other way. + * + * @see UCPTRIE_VALUE_BITS_16 + * @draft ICU 63 + */ +#define UCPTRIE_16(trie, i) ((trie)->data.ptr16[i]) + +/** + * Macro parameter value for a trie with 32-bit data values. + * Use the name of this macro as a "dataAccess" parameter in other macros. + * Do not use this macro in any other way. + * + * @see UCPTRIE_VALUE_BITS_32 + * @draft ICU 63 + */ +#define UCPTRIE_32(trie, i) ((trie)->data.ptr32[i]) + +/** + * Macro parameter value for a trie with 8-bit data values. + * Use the name of this macro as a "dataAccess" parameter in other macros. + * Do not use this macro in any other way. + * + * @see UCPTRIE_VALUE_BITS_8 + * @draft ICU 63 + */ +#define UCPTRIE_8(trie, i) ((trie)->data.ptr8[i]) + +/** + * Returns a trie value for a code point, with range checking. + * Returns the trie error value if c is not in the range 0..U+10FFFF. + * + * @param trie (const UCPTrie *, in) the trie; must have type UCPTRIE_TYPE_FAST + * @param dataAccess UCPTRIE_16, UCPTRIE_32, or UCPTRIE_8 according to the trie’s value width + * @param c (UChar32, in) the input code point + * @return The code point's trie value. + * @draft ICU 63 + */ +#define UCPTRIE_FAST_GET(trie, dataAccess, c) dataAccess(trie, _UCPTRIE_CP_INDEX(trie, 0xffff, c)) + +/** + * Returns a 16-bit trie value for a code point, with range checking. + * Returns the trie error value if c is not in the range U+0000..U+10FFFF. + * + * @param trie (const UCPTrie *, in) the trie; must have type UCPTRIE_TYPE_SMALL + * @param dataAccess UCPTRIE_16, UCPTRIE_32, or UCPTRIE_8 according to the trie’s value width + * @param c (UChar32, in) the input code point + * @return The code point's trie value. + * @draft ICU 63 + */ +#define UCPTRIE_SMALL_GET(trie, dataAccess, c) \ + dataAccess(trie, _UCPTRIE_CP_INDEX(trie, UCPTRIE_SMALL_MAX, c)) + +/** + * UTF-16: Reads the next code point (UChar32 c, out), post-increments src, + * and gets a value from the trie. + * Sets the trie error value if c is an unpaired surrogate. + * + * @param trie (const UCPTrie *, in) the trie; must have type UCPTRIE_TYPE_FAST + * @param dataAccess UCPTRIE_16, UCPTRIE_32, or UCPTRIE_8 according to the trie’s value width + * @param src (const UChar *, in/out) the source text pointer + * @param limit (const UChar *, in) the limit pointer for the text, or NULL if NUL-terminated + * @param c (UChar32, out) variable for the code point + * @param result (out) variable for the trie lookup result + * @draft ICU 63 + */ +#define UCPTRIE_FAST_U16_NEXT(trie, dataAccess, src, limit, c, result) { \ + (c) = *(src)++; \ + int32_t __index; \ + if (!U16_IS_SURROGATE(c)) { \ + __index = _UCPTRIE_FAST_INDEX(trie, c); \ + } else { \ + uint16_t __c2; \ + if (U16_IS_SURROGATE_LEAD(c) && (src) != (limit) && U16_IS_TRAIL(__c2 = *(src))) { \ + ++(src); \ + (c) = U16_GET_SUPPLEMENTARY((c), __c2); \ + __index = _UCPTRIE_SMALL_INDEX(trie, c); \ + } else { \ + __index = (trie)->dataLength - UCPTRIE_ERROR_VALUE_NEG_DATA_OFFSET; \ + } \ + } \ + (result) = dataAccess(trie, __index); \ +} + +/** + * UTF-16: Reads the previous code point (UChar32 c, out), pre-decrements src, + * and gets a value from the trie. + * Sets the trie error value if c is an unpaired surrogate. + * + * @param trie (const UCPTrie *, in) the trie; must have type UCPTRIE_TYPE_FAST + * @param dataAccess UCPTRIE_16, UCPTRIE_32, or UCPTRIE_8 according to the trie’s value width + * @param start (const UChar *, in) the start pointer for the text + * @param src (const UChar *, in/out) the source text pointer + * @param c (UChar32, out) variable for the code point + * @param result (out) variable for the trie lookup result + * @draft ICU 63 + */ +#define UCPTRIE_FAST_U16_PREV(trie, dataAccess, start, src, c, result) { \ + (c) = *--(src); \ + int32_t __index; \ + if (!U16_IS_SURROGATE(c)) { \ + __index = _UCPTRIE_FAST_INDEX(trie, c); \ + } else { \ + uint16_t __c2; \ + if (U16_IS_SURROGATE_TRAIL(c) && (src) != (start) && U16_IS_LEAD(__c2 = *((src) - 1))) { \ + --(src); \ + (c) = U16_GET_SUPPLEMENTARY(__c2, (c)); \ + __index = _UCPTRIE_SMALL_INDEX(trie, c); \ + } else { \ + __index = (trie)->dataLength - UCPTRIE_ERROR_VALUE_NEG_DATA_OFFSET; \ + } \ + } \ + (result) = dataAccess(trie, __index); \ +} + +/** + * UTF-8: Post-increments src and gets a value from the trie. + * Sets the trie error value for an ill-formed byte sequence. + * + * Unlike UCPTRIE_FAST_U16_NEXT() this UTF-8 macro does not provide the code point + * because it would be more work to do so and is often not needed. + * If the trie value differs from the error value, then the byte sequence is well-formed, + * and the code point can be assembled without revalidation. + * + * @param trie (const UCPTrie *, in) the trie; must have type UCPTRIE_TYPE_FAST + * @param dataAccess UCPTRIE_16, UCPTRIE_32, or UCPTRIE_8 according to the trie’s value width + * @param src (const char *, in/out) the source text pointer + * @param limit (const char *, in) the limit pointer for the text (must not be NULL) + * @param result (out) variable for the trie lookup result + * @draft ICU 63 + */ +#define UCPTRIE_FAST_U8_NEXT(trie, dataAccess, src, limit, result) { \ + int32_t __lead = (uint8_t)*(src)++; \ + if (!U8_IS_SINGLE(__lead)) { \ + uint8_t __t1, __t2, __t3; \ + if ((src) != (limit) && \ + (__lead >= 0xe0 ? \ + __lead < 0xf0 ? /* U+0800..U+FFFF except surrogates */ \ + U8_LEAD3_T1_BITS[__lead &= 0xf] & (1 << ((__t1 = *(src)) >> 5)) && \ + ++(src) != (limit) && (__t2 = *(src) - 0x80) <= 0x3f && \ + (__lead = ((int32_t)(trie)->index[(__lead << 6) + (__t1 & 0x3f)]) + __t2, 1) \ + : /* U+10000..U+10FFFF */ \ + (__lead -= 0xf0) <= 4 && \ + U8_LEAD4_T1_BITS[(__t1 = *(src)) >> 4] & (1 << __lead) && \ + (__lead = (__lead << 6) | (__t1 & 0x3f), ++(src) != (limit)) && \ + (__t2 = *(src) - 0x80) <= 0x3f && \ + ++(src) != (limit) && (__t3 = *(src) - 0x80) <= 0x3f && \ + (__lead = __lead >= (trie)->shifted12HighStart ? \ + (trie)->dataLength - UCPTRIE_HIGH_VALUE_NEG_DATA_OFFSET : \ + ucptrie_internalSmallU8Index((trie), __lead, __t2, __t3), 1) \ + : /* U+0080..U+07FF */ \ + __lead >= 0xc2 && (__t1 = *(src) - 0x80) <= 0x3f && \ + (__lead = (int32_t)(trie)->index[__lead & 0x1f] + __t1, 1))) { \ + ++(src); \ + } else { \ + __lead = (trie)->dataLength - UCPTRIE_ERROR_VALUE_NEG_DATA_OFFSET; /* ill-formed*/ \ + } \ + } \ + (result) = dataAccess(trie, __lead); \ +} + +/** + * UTF-8: Pre-decrements src and gets a value from the trie. + * Sets the trie error value for an ill-formed byte sequence. + * + * Unlike UCPTRIE_FAST_U16_PREV() this UTF-8 macro does not provide the code point + * because it would be more work to do so and is often not needed. + * If the trie value differs from the error value, then the byte sequence is well-formed, + * and the code point can be assembled without revalidation. + * + * @param trie (const UCPTrie *, in) the trie; must have type UCPTRIE_TYPE_FAST + * @param dataAccess UCPTRIE_16, UCPTRIE_32, or UCPTRIE_8 according to the trie’s value width + * @param start (const char *, in) the start pointer for the text + * @param src (const char *, in/out) the source text pointer + * @param result (out) variable for the trie lookup result + * @draft ICU 63 + */ +#define UCPTRIE_FAST_U8_PREV(trie, dataAccess, start, src, result) { \ + int32_t __index = (uint8_t)*--(src); \ + if (!U8_IS_SINGLE(__index)) { \ + __index = ucptrie_internalU8PrevIndex((trie), __index, (const uint8_t *)(start), \ + (const uint8_t *)(src)); \ + (src) -= __index & 7; \ + __index >>= 3; \ + } \ + (result) = dataAccess(trie, __index); \ +} + +/** + * Returns a trie value for an ASCII code point, without range checking. + * + * @param trie (const UCPTrie *, in) the trie (of either fast or small type) + * @param dataAccess UCPTRIE_16, UCPTRIE_32, or UCPTRIE_8 according to the trie’s value width + * @param c (UChar32, in) the input code point; must be U+0000..U+007F + * @return The ASCII code point's trie value. + * @draft ICU 63 + */ +#define UCPTRIE_ASCII_GET(trie, dataAccess, c) dataAccess(trie, c) + +/** + * Returns a trie value for a BMP code point (U+0000..U+FFFF), without range checking. + * Can be used to look up a value for a UTF-16 code unit if other parts of + * the string processing check for surrogates. + * + * @param trie (const UCPTrie *, in) the trie; must have type UCPTRIE_TYPE_FAST + * @param dataAccess UCPTRIE_16, UCPTRIE_32, or UCPTRIE_8 according to the trie’s value width + * @param c (UChar32, in) the input code point, must be U+0000..U+FFFF + * @return The BMP code point's trie value. + * @draft ICU 63 + */ +#define UCPTRIE_FAST_BMP_GET(trie, dataAccess, c) dataAccess(trie, _UCPTRIE_FAST_INDEX(trie, c)) + +/** + * Returns a trie value for a supplementary code point (U+10000..U+10FFFF), + * without range checking. + * + * @param trie (const UCPTrie *, in) the trie; must have type UCPTRIE_TYPE_FAST + * @param dataAccess UCPTRIE_16, UCPTRIE_32, or UCPTRIE_8 according to the trie’s value width + * @param c (UChar32, in) the input code point, must be U+10000..U+10FFFF + * @return The supplementary code point's trie value. + * @draft ICU 63 + */ +#define UCPTRIE_FAST_SUPP_GET(trie, dataAccess, c) dataAccess(trie, _UCPTRIE_SMALL_INDEX(trie, c)) + +/* Internal definitions ----------------------------------------------------- */ + +#ifndef U_IN_DOXYGEN + +/** + * Internal implementation constants. + * These are needed for the API macros, but users should not use these directly. + * @internal + */ +enum { + /** @internal */ + UCPTRIE_FAST_SHIFT = 6, + + /** Number of entries in a data block for code points below the fast limit. 64=0x40 @internal */ + UCPTRIE_FAST_DATA_BLOCK_LENGTH = 1 << UCPTRIE_FAST_SHIFT, + + /** Mask for getting the lower bits for the in-fast-data-block offset. @internal */ + UCPTRIE_FAST_DATA_MASK = UCPTRIE_FAST_DATA_BLOCK_LENGTH - 1, + + /** @internal */ + UCPTRIE_SMALL_MAX = 0xfff, + + /** + * Offset from dataLength (to be subtracted) for fetching the + * value returned for out-of-range code points and ill-formed UTF-8/16. + * @internal + */ + UCPTRIE_ERROR_VALUE_NEG_DATA_OFFSET = 1, + /** + * Offset from dataLength (to be subtracted) for fetching the + * value returned for code points highStart..U+10FFFF. + * @internal + */ + UCPTRIE_HIGH_VALUE_NEG_DATA_OFFSET = 2 +}; + +/* Internal functions and macros -------------------------------------------- */ +// Do not conditionalize with #ifndef U_HIDE_INTERNAL_API, needed for public API + +/** @internal */ +U_INTERNAL int32_t U_EXPORT2 +ucptrie_internalSmallIndex(const UCPTrie *trie, UChar32 c); + +/** @internal */ +U_INTERNAL int32_t U_EXPORT2 +ucptrie_internalSmallU8Index(const UCPTrie *trie, int32_t lt1, uint8_t t2, uint8_t t3); + +/** + * Internal function for part of the UCPTRIE_FAST_U8_PREVxx() macro implementations. + * Do not call directly. + * @internal + */ +U_INTERNAL int32_t U_EXPORT2 +ucptrie_internalU8PrevIndex(const UCPTrie *trie, UChar32 c, + const uint8_t *start, const uint8_t *src); + +/** Internal trie getter for a code point below the fast limit. Returns the data index. @internal */ +#define _UCPTRIE_FAST_INDEX(trie, c) \ + ((int32_t)(trie)->index[(c) >> UCPTRIE_FAST_SHIFT] + ((c) & UCPTRIE_FAST_DATA_MASK)) + +/** Internal trie getter for a code point at or above the fast limit. Returns the data index. @internal */ +#define _UCPTRIE_SMALL_INDEX(trie, c) \ + ((c) >= (trie)->highStart ? \ + (trie)->dataLength - UCPTRIE_HIGH_VALUE_NEG_DATA_OFFSET : \ + ucptrie_internalSmallIndex(trie, c)) + +/** + * Internal trie getter for a code point, with checking that c is in U+0000..10FFFF. + * Returns the data index. + * @internal + */ +#define _UCPTRIE_CP_INDEX(trie, fastMax, c) \ + ((uint32_t)(c) <= (uint32_t)(fastMax) ? \ + _UCPTRIE_FAST_INDEX(trie, c) : \ + (uint32_t)(c) <= 0x10ffff ? \ + _UCPTRIE_SMALL_INDEX(trie, c) : \ + (trie)->dataLength - UCPTRIE_ERROR_VALUE_NEG_DATA_OFFSET) + +U_CDECL_END + +#endif // U_IN_DOXYGEN +#endif // U_HIDE_DRAFT_API +#endif diff --git a/deps/icu-small/source/common/unicode/ucurr.h b/deps/icu-small/source/common/unicode/ucurr.h index adfaf0023bb7cf..1021adc83e7ee2 100644 --- a/deps/icu-small/source/common/unicode/ucurr.h +++ b/deps/icu-small/source/common/unicode/ucurr.h @@ -60,6 +60,7 @@ enum UCurrencyUsage { UCURR_USAGE_COUNT=2 #endif // U_HIDE_DEPRECATED_API }; +/** Currency Usage used for Decimal Format */ typedef enum UCurrencyUsage UCurrencyUsage; /** diff --git a/deps/icu-small/source/common/unicode/uenum.h b/deps/icu-small/source/common/unicode/uenum.h index 56faae895279b6..eb8ecdf88b6ec5 100644 --- a/deps/icu-small/source/common/unicode/uenum.h +++ b/deps/icu-small/source/common/unicode/uenum.h @@ -190,8 +190,6 @@ U_STABLE UEnumeration* U_EXPORT2 uenum_openUCharStringsEnumeration(const UChar* const strings[], int32_t count, UErrorCode* ec); -/* Note: next function is not hidden as draft, as it is used internally (it was formerly an internal function). */ - /** * Given an array of const char* strings (invariant chars only), return a UEnumeration. String pointers from 0..count-1 must not be null. * Do not free or modify either the string array or the characters it points to until this object has been destroyed with uenum_close. diff --git a/deps/icu-small/source/common/unicode/umachine.h b/deps/icu-small/source/common/unicode/umachine.h index a9dc1631b00e70..6d932cfcfb2ae4 100644 --- a/deps/icu-small/source/common/unicode/umachine.h +++ b/deps/icu-small/source/common/unicode/umachine.h @@ -125,6 +125,9 @@ * May result in an error if it applied to something not an override. * @internal */ +#ifndef U_OVERRIDE +#define U_OVERRIDE override +#endif /** * \def U_FINAL @@ -133,24 +136,10 @@ * May result in an error if subclasses attempt to override. * @internal */ - -#if U_CPLUSPLUS_VERSION >= 11 -/* C++11 */ -#ifndef U_OVERRIDE -#define U_OVERRIDE override -#endif -#ifndef U_FINAL +#if !defined(U_FINAL) || defined(U_IN_DOXYGEN) #define U_FINAL final #endif -#else -/* not C++11 - define to nothing */ -#ifndef U_OVERRIDE -#define U_OVERRIDE -#endif -#ifndef U_FINAL -#define U_FINAL -#endif -#endif + /*==========================================================================*/ /* limits for int32_t etc., like in POSIX inttypes.h */ @@ -318,7 +307,7 @@ typedef int8_t UBool; * UChar is configurable by defining the macro UCHAR_TYPE * on the preprocessor or compiler command line: * -DUCHAR_TYPE=uint16_t or -DUCHAR_TYPE=wchar_t (if U_SIZEOF_WCHAR_T==2) etc. - * (The UCHAR_TYPE can also be #defined earlier in this file, for outside the ICU library code.) + * (The UCHAR_TYPE can also be \#defined earlier in this file, for outside the ICU library code.) * This is for transitional use from application code that uses uint16_t or wchar_t for UTF-16. * * The default is UChar=char16_t. diff --git a/deps/icu-small/source/common/unicode/umutablecptrie.h b/deps/icu-small/source/common/unicode/umutablecptrie.h new file mode 100644 index 00000000000000..e75191a4495209 --- /dev/null +++ b/deps/icu-small/source/common/unicode/umutablecptrie.h @@ -0,0 +1,241 @@ +// © 2017 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html + +// umutablecptrie.h (split out of ucptrie.h) +// created: 2018jan24 Markus W. Scherer + +#ifndef __UMUTABLECPTRIE_H__ +#define __UMUTABLECPTRIE_H__ + +#include "unicode/utypes.h" + +#ifndef U_HIDE_DRAFT_API + +#include "unicode/localpointer.h" +#include "unicode/ucpmap.h" +#include "unicode/ucptrie.h" +#include "unicode/utf8.h" + +U_CDECL_BEGIN + +/** + * \file + * + * This file defines a mutable Unicode code point trie. + * + * @see UCPTrie + * @see UMutableCPTrie + */ + +/** + * Mutable Unicode code point trie. + * Fast map from Unicode code points (U+0000..U+10FFFF) to 32-bit integer values. + * For details see http://site.icu-project.org/design/struct/utrie + * + * Setting values (especially ranges) and lookup is fast. + * The mutable trie is only somewhat space-efficient. + * It builds a compacted, immutable UCPTrie. + * + * This trie can be modified while iterating over its contents. + * For example, it is possible to merge its values with those from another + * set of ranges (e.g., another mutable or immutable trie): + * Iterate over those source ranges; for each of them iterate over this trie; + * add the source value into the value of each trie range. + * + * @see UCPTrie + * @see umutablecptrie_buildImmutable + * @draft ICU 63 + */ +typedef struct UMutableCPTrie UMutableCPTrie; + +/** + * Creates a mutable trie that initially maps each Unicode code point to the same value. + * It uses 32-bit data values until umutablecptrie_buildImmutable() is called. + * umutablecptrie_buildImmutable() takes a valueWidth parameter which + * determines the number of bits in the data value in the resulting UCPTrie. + * You must umutablecptrie_close() the trie once you are done using it. + * + * @param initialValue the initial value that is set for all code points + * @param errorValue the value for out-of-range code points and ill-formed UTF-8/16 + * @param pErrorCode an in/out ICU UErrorCode + * @return the trie + * @draft ICU 63 + */ +U_CAPI UMutableCPTrie * U_EXPORT2 +umutablecptrie_open(uint32_t initialValue, uint32_t errorValue, UErrorCode *pErrorCode); + +/** + * Clones a mutable trie. + * You must umutablecptrie_close() the clone once you are done using it. + * + * @param other the trie to clone + * @param pErrorCode an in/out ICU UErrorCode + * @return the trie clone + * @draft ICU 63 + */ +U_CAPI UMutableCPTrie * U_EXPORT2 +umutablecptrie_clone(const UMutableCPTrie *other, UErrorCode *pErrorCode); + +/** + * Closes a mutable trie and releases associated memory. + * + * @param trie the trie + * @draft ICU 63 + */ +U_CAPI void U_EXPORT2 +umutablecptrie_close(UMutableCPTrie *trie); + +#if U_SHOW_CPLUSPLUS_API + +U_NAMESPACE_BEGIN + +/** + * \class LocalUMutableCPTriePointer + * "Smart pointer" class, closes a UMutableCPTrie via umutablecptrie_close(). + * For most methods see the LocalPointerBase base class. + * + * @see LocalPointerBase + * @see LocalPointer + * @draft ICU 63 + */ +U_DEFINE_LOCAL_OPEN_POINTER(LocalUMutableCPTriePointer, UMutableCPTrie, umutablecptrie_close); + +U_NAMESPACE_END + +#endif + +/** + * Creates a mutable trie with the same contents as the UCPMap. + * You must umutablecptrie_close() the mutable trie once you are done using it. + * + * @param map the source map + * @param pErrorCode an in/out ICU UErrorCode + * @return the mutable trie + * @draft ICU 63 + */ +U_CAPI UMutableCPTrie * U_EXPORT2 +umutablecptrie_fromUCPMap(const UCPMap *map, UErrorCode *pErrorCode); + +/** + * Creates a mutable trie with the same contents as the immutable one. + * You must umutablecptrie_close() the mutable trie once you are done using it. + * + * @param trie the immutable trie + * @param pErrorCode an in/out ICU UErrorCode + * @return the mutable trie + * @draft ICU 63 + */ +U_CAPI UMutableCPTrie * U_EXPORT2 +umutablecptrie_fromUCPTrie(const UCPTrie *trie, UErrorCode *pErrorCode); + +/** + * Returns the value for a code point as stored in the trie. + * + * @param trie the trie + * @param c the code point + * @return the value + * @draft ICU 63 + */ +U_CAPI uint32_t U_EXPORT2 +umutablecptrie_get(const UMutableCPTrie *trie, UChar32 c); + +/** + * Returns the last code point such that all those from start to there have the same value. + * Can be used to efficiently iterate over all same-value ranges in a trie. + * (This is normally faster than iterating over code points and get()ting each value, + * but much slower than a data structure that stores ranges directly.) + * + * The trie can be modified between calls to this function. + * + * If the UCPMapValueFilter function pointer is not NULL, then + * the value to be delivered is passed through that function, and the return value is the end + * of the range where all values are modified to the same actual value. + * The value is unchanged if that function pointer is NULL. + * + * See the same-signature ucptrie_getRange() for a code sample. + * + * @param trie the trie + * @param start range start + * @param option defines whether surrogates are treated normally, + * or as having the surrogateValue; usually UCPMAP_RANGE_NORMAL + * @param surrogateValue value for surrogates; ignored if option==UCPMAP_RANGE_NORMAL + * @param filter a pointer to a function that may modify the trie data value, + * or NULL if the values from the trie are to be used unmodified + * @param context an opaque pointer that is passed on to the filter function + * @param pValue if not NULL, receives the value that every code point start..end has; + * may have been modified by filter(context, trie value) + * if that function pointer is not NULL + * @return the range end code point, or -1 if start is not a valid code point + * @draft ICU 63 + */ +U_CAPI UChar32 U_EXPORT2 +umutablecptrie_getRange(const UMutableCPTrie *trie, UChar32 start, + UCPMapRangeOption option, uint32_t surrogateValue, + UCPMapValueFilter *filter, const void *context, uint32_t *pValue); + +/** + * Sets a value for a code point. + * + * @param trie the trie + * @param c the code point + * @param value the value + * @param pErrorCode an in/out ICU UErrorCode + * @draft ICU 63 + */ +U_CAPI void U_EXPORT2 +umutablecptrie_set(UMutableCPTrie *trie, UChar32 c, uint32_t value, UErrorCode *pErrorCode); + +/** + * Sets a value for each code point [start..end]. + * Faster and more space-efficient than setting the value for each code point separately. + * + * @param trie the trie + * @param start the first code point to get the value + * @param end the last code point to get the value (inclusive) + * @param value the value + * @param pErrorCode an in/out ICU UErrorCode + * @draft ICU 63 + */ +U_CAPI void U_EXPORT2 +umutablecptrie_setRange(UMutableCPTrie *trie, + UChar32 start, UChar32 end, + uint32_t value, UErrorCode *pErrorCode); + +/** + * Compacts the data and builds an immutable UCPTrie according to the parameters. + * After this, the mutable trie will be empty. + * + * The mutable trie stores 32-bit values until buildImmutable() is called. + * If values shorter than 32 bits are to be stored in the immutable trie, + * then the upper bits are discarded. + * For example, when the mutable trie contains values 0x81, -0x7f, and 0xa581, + * and the value width is 8 bits, then each of these is stored as 0x81 + * and the immutable trie will return that as an unsigned value. + * (Some implementations may want to make productive temporary use of the upper bits + * until buildImmutable() discards them.) + * + * Not every possible set of mappings can be built into a UCPTrie, + * because of limitations resulting from speed and space optimizations. + * Every Unicode assigned character can be mapped to a unique value. + * Typical data yields data structures far smaller than the limitations. + * + * It is possible to construct extremely unusual mappings that exceed the data structure limits. + * In such a case this function will fail with a U_INDEX_OUTOFBOUNDS_ERROR. + * + * @param trie the trie trie + * @param type selects the trie type + * @param valueWidth selects the number of bits in a trie data value; if smaller than 32 bits, + * then the values stored in the trie will be truncated first + * @param pErrorCode an in/out ICU UErrorCode + * + * @see umutablecptrie_fromUCPTrie + * @draft ICU 63 + */ +U_CAPI UCPTrie * U_EXPORT2 +umutablecptrie_buildImmutable(UMutableCPTrie *trie, UCPTrieType type, UCPTrieValueWidth valueWidth, + UErrorCode *pErrorCode); + +U_CDECL_END + +#endif // U_HIDE_DRAFT_API +#endif diff --git a/deps/icu-small/source/common/unicode/uniset.h b/deps/icu-small/source/common/unicode/uniset.h index c2e0ad48bd7b2c..2ab2695a8780d7 100644 --- a/deps/icu-small/source/common/unicode/uniset.h +++ b/deps/icu-small/source/common/unicode/uniset.h @@ -13,6 +13,7 @@ #ifndef UNICODESET_H #define UNICODESET_H +#include "unicode/ucpmap.h" #include "unicode/unifilt.h" #include "unicode/unistr.h" #include "unicode/uset.h" @@ -25,9 +26,8 @@ U_NAMESPACE_BEGIN // Forward Declarations. -void U_CALLCONV UnicodeSet_initInclusion(int32_t src, UErrorCode &status); /**< @internal */ - class BMPSet; +class CharacterProperties; class ParsePosition; class RBBIRuleScanner; class SymbolTable; @@ -584,9 +584,8 @@ class U_COMMON_API UnicodeSet U_FINAL : public UnicodeFilter { //---------------------------------------------------------------- /** - * Make this object represent the range start - end. - * If end > start then this object is set to an - * an empty range. + * Make this object represent the range `start - end`. + * If `end > start` then this object is set to an empty range. * A frozen set will not be modified. * * @param start first character in the set, inclusive @@ -1506,6 +1505,7 @@ class U_COMMON_API UnicodeSet U_FINAL : public UnicodeFilter { //---------------------------------------------------------------- UnicodeSet(const UnicodeSet& o, UBool /* asThawed */); + UnicodeSet& copyFrom(const UnicodeSet& o, UBool asThawed); //---------------------------------------------------------------- // Implementation: Pattern parsing @@ -1614,7 +1614,7 @@ class U_COMMON_API UnicodeSet U_FINAL : public UnicodeFilter { UnicodeString& rebuiltPat, UErrorCode& ec); - friend void U_CALLCONV UnicodeSet_initInclusion(int32_t src, UErrorCode &status); + friend class CharacterProperties; static const UnicodeSet* getInclusions(int32_t src, UErrorCode &status); /** @@ -1634,9 +1634,15 @@ class U_COMMON_API UnicodeSet U_FINAL : public UnicodeFilter { */ void applyFilter(Filter filter, void* context, - int32_t src, + const UnicodeSet* inclusions, UErrorCode &status); +#ifndef U_HIDE_DRAFT_API // Skipped: ucpmap.h is draft only. + void applyIntPropertyValue(const UCPMap *map, + UCPMapValueFilter *filter, const void *context, + UErrorCode &errorCode); +#endif /* U_HIDE_DRAFT_API */ + /** * Set the new pattern to cache. */ diff --git a/deps/icu-small/source/common/unicode/unistr.h b/deps/icu-small/source/common/unicode/unistr.h index b84f40bd449ced..bf954b5f1d8232 100644 --- a/deps/icu-small/source/common/unicode/unistr.h +++ b/deps/icu-small/source/common/unicode/unistr.h @@ -243,6 +243,9 @@ class UnicodeStringAppendable; // unicode/appendable.h * than other ICU APIs. In particular: * - If indexes are out of bounds for a UnicodeString object * (<0 or >length()) then they are "pinned" to the nearest boundary. + * - If the buffer passed to an insert/append/replace operation is owned by the + * target object, e.g., calling str.append(str), an extra copy may take place + * to ensure safety. * - If primitive string pointer values (e.g., const char16_t * or char *) * for input strings are NULL, then those input string parameters are treated * as if they pointed to an empty string. diff --git a/deps/icu-small/source/common/unicode/uobject.h b/deps/icu-small/source/common/unicode/uobject.h index 080600e52650d5..f7a7b6eddbc96b 100644 --- a/deps/icu-small/source/common/unicode/uobject.h +++ b/deps/icu-small/source/common/unicode/uobject.h @@ -27,7 +27,6 @@ */ /** - * @{ * \def U_NO_THROW * Define this to define the throw() specification so * certain functions do not throw any exceptions @@ -44,8 +43,6 @@ #define U_NO_THROW throw() #endif -/** @} */ - /*===========================================================================*/ /* UClassID-based RTTI */ /*===========================================================================*/ diff --git a/deps/icu-small/source/common/unicode/urename.h b/deps/icu-small/source/common/unicode/urename.h index 4175e527f404a7..5812173e39cfd2 100644 --- a/deps/icu-small/source/common/unicode/urename.h +++ b/deps/icu-small/source/common/unicode/urename.h @@ -33,6 +33,9 @@ #if !U_DISABLE_RENAMING +// Disable Renaming for Visual Studio's IntelliSense feature, so that 'Go-to-Definition' (F12) will work. +#if !(defined(_MSC_VER) && defined(__INTELLISENSE__)) + /* We need the U_ICU_ENTRY_POINT_RENAME definition. There's a default one in unicode/uvernum.h we can use, but we will give the platform a chance to define it first. Normally (if utypes.h or umachine.h was included first) this will not be necessary as it will already be defined. @@ -107,6 +110,7 @@ #define _UTF7Data U_ICU_ENTRY_POINT_RENAME(_UTF7Data) #define _UTF8Data U_ICU_ENTRY_POINT_RENAME(_UTF8Data) #define allowedHourFormatsCleanup U_ICU_ENTRY_POINT_RENAME(allowedHourFormatsCleanup) +#define checkImpl U_ICU_ENTRY_POINT_RENAME(checkImpl) #define cmemory_cleanup U_ICU_ENTRY_POINT_RENAME(cmemory_cleanup) #define dayPeriodRulesCleanup U_ICU_ENTRY_POINT_RENAME(dayPeriodRulesCleanup) #define deleteAllowedHourFormats U_ICU_ENTRY_POINT_RENAME(deleteAllowedHourFormats) @@ -253,12 +257,14 @@ #define u_fstropen U_ICU_ENTRY_POINT_RENAME(u_fstropen) #define u_fungetc U_ICU_ENTRY_POINT_RENAME(u_fungetc) #define u_getBidiPairedBracket U_ICU_ENTRY_POINT_RENAME(u_getBidiPairedBracket) +#define u_getBinaryPropertySet U_ICU_ENTRY_POINT_RENAME(u_getBinaryPropertySet) #define u_getCombiningClass U_ICU_ENTRY_POINT_RENAME(u_getCombiningClass) #define u_getDataDirectory U_ICU_ENTRY_POINT_RENAME(u_getDataDirectory) #define u_getDataVersion U_ICU_ENTRY_POINT_RENAME(u_getDataVersion) #define u_getDefaultConverter U_ICU_ENTRY_POINT_RENAME(u_getDefaultConverter) #define u_getFC_NFKC_Closure U_ICU_ENTRY_POINT_RENAME(u_getFC_NFKC_Closure) #define u_getISOComment U_ICU_ENTRY_POINT_RENAME(u_getISOComment) +#define u_getIntPropertyMap U_ICU_ENTRY_POINT_RENAME(u_getIntPropertyMap) #define u_getIntPropertyMaxValue U_ICU_ENTRY_POINT_RENAME(u_getIntPropertyMaxValue) #define u_getIntPropertyMinValue U_ICU_ENTRY_POINT_RENAME(u_getIntPropertyMinValue) #define u_getIntPropertyValue U_ICU_ENTRY_POINT_RENAME(u_getIntPropertyValue) @@ -763,6 +769,20 @@ #define ucol_swap U_ICU_ENTRY_POINT_RENAME(ucol_swap) #define ucol_swapInverseUCA U_ICU_ENTRY_POINT_RENAME(ucol_swapInverseUCA) #define ucol_tertiaryOrder U_ICU_ENTRY_POINT_RENAME(ucol_tertiaryOrder) +#define ucpmap_get U_ICU_ENTRY_POINT_RENAME(ucpmap_get) +#define ucpmap_getRange U_ICU_ENTRY_POINT_RENAME(ucpmap_getRange) +#define ucptrie_close U_ICU_ENTRY_POINT_RENAME(ucptrie_close) +#define ucptrie_get U_ICU_ENTRY_POINT_RENAME(ucptrie_get) +#define ucptrie_getRange U_ICU_ENTRY_POINT_RENAME(ucptrie_getRange) +#define ucptrie_getType U_ICU_ENTRY_POINT_RENAME(ucptrie_getType) +#define ucptrie_getValueWidth U_ICU_ENTRY_POINT_RENAME(ucptrie_getValueWidth) +#define ucptrie_internalGetRange U_ICU_ENTRY_POINT_RENAME(ucptrie_internalGetRange) +#define ucptrie_internalSmallIndex U_ICU_ENTRY_POINT_RENAME(ucptrie_internalSmallIndex) +#define ucptrie_internalSmallU8Index U_ICU_ENTRY_POINT_RENAME(ucptrie_internalSmallU8Index) +#define ucptrie_internalU8PrevIndex U_ICU_ENTRY_POINT_RENAME(ucptrie_internalU8PrevIndex) +#define ucptrie_openFromBinary U_ICU_ENTRY_POINT_RENAME(ucptrie_openFromBinary) +#define ucptrie_swap U_ICU_ENTRY_POINT_RENAME(ucptrie_swap) +#define ucptrie_toBinary U_ICU_ENTRY_POINT_RENAME(ucptrie_toBinary) #define ucsdet_close U_ICU_ENTRY_POINT_RENAME(ucsdet_close) #define ucsdet_detect U_ICU_ENTRY_POINT_RENAME(ucsdet_detect) #define ucsdet_detectAll U_ICU_ENTRY_POINT_RENAME(ucsdet_detectAll) @@ -1079,6 +1099,7 @@ #define ulocdata_getPaperSize U_ICU_ENTRY_POINT_RENAME(ulocdata_getPaperSize) #define ulocdata_open U_ICU_ENTRY_POINT_RENAME(ulocdata_open) #define ulocdata_setNoSubstitute U_ICU_ENTRY_POINT_RENAME(ulocdata_setNoSubstitute) +#define ulocimp_forLanguageTag U_ICU_ENTRY_POINT_RENAME(ulocimp_forLanguageTag) #define ulocimp_getCountry U_ICU_ENTRY_POINT_RENAME(ulocimp_getCountry) #define ulocimp_getLanguage U_ICU_ENTRY_POINT_RENAME(ulocimp_getLanguage) #define ulocimp_getRegionForSupplementalData U_ICU_ENTRY_POINT_RENAME(ulocimp_getRegionForSupplementalData) @@ -1106,6 +1127,16 @@ #define umtx_condWait U_ICU_ENTRY_POINT_RENAME(umtx_condWait) #define umtx_lock U_ICU_ENTRY_POINT_RENAME(umtx_lock) #define umtx_unlock U_ICU_ENTRY_POINT_RENAME(umtx_unlock) +#define umutablecptrie_buildImmutable U_ICU_ENTRY_POINT_RENAME(umutablecptrie_buildImmutable) +#define umutablecptrie_clone U_ICU_ENTRY_POINT_RENAME(umutablecptrie_clone) +#define umutablecptrie_close U_ICU_ENTRY_POINT_RENAME(umutablecptrie_close) +#define umutablecptrie_fromUCPMap U_ICU_ENTRY_POINT_RENAME(umutablecptrie_fromUCPMap) +#define umutablecptrie_fromUCPTrie U_ICU_ENTRY_POINT_RENAME(umutablecptrie_fromUCPTrie) +#define umutablecptrie_get U_ICU_ENTRY_POINT_RENAME(umutablecptrie_get) +#define umutablecptrie_getRange U_ICU_ENTRY_POINT_RENAME(umutablecptrie_getRange) +#define umutablecptrie_open U_ICU_ENTRY_POINT_RENAME(umutablecptrie_open) +#define umutablecptrie_set U_ICU_ENTRY_POINT_RENAME(umutablecptrie_set) +#define umutablecptrie_setRange U_ICU_ENTRY_POINT_RENAME(umutablecptrie_setRange) #define uniset_getUnicode32Instance U_ICU_ENTRY_POINT_RENAME(uniset_getUnicode32Instance) #define unorm2_append U_ICU_ENTRY_POINT_RENAME(unorm2_append) #define unorm2_close U_ICU_ENTRY_POINT_RENAME(unorm2_close) @@ -1218,6 +1249,7 @@ #define uplug_setPlugLevel U_ICU_ENTRY_POINT_RENAME(uplug_setPlugLevel) #define uplug_setPlugName U_ICU_ENTRY_POINT_RENAME(uplug_setPlugName) #define uplug_setPlugNoUnload U_ICU_ENTRY_POINT_RENAME(uplug_setPlugNoUnload) +#define uprops_addPropertyStarts U_ICU_ENTRY_POINT_RENAME(uprops_addPropertyStarts) #define uprops_getSource U_ICU_ENTRY_POINT_RENAME(uprops_getSource) #define upropsvec_addPropertyStarts U_ICU_ENTRY_POINT_RENAME(upropsvec_addPropertyStarts) #define uprv_add32_overflow U_ICU_ENTRY_POINT_RENAME(uprv_add32_overflow) @@ -1236,6 +1268,7 @@ #define uprv_convertToPosix U_ICU_ENTRY_POINT_RENAME(uprv_convertToPosix) #define uprv_copyAscii U_ICU_ENTRY_POINT_RENAME(uprv_copyAscii) #define uprv_copyEbcdic U_ICU_ENTRY_POINT_RENAME(uprv_copyEbcdic) +#define uprv_currencyLeads U_ICU_ENTRY_POINT_RENAME(uprv_currencyLeads) #define uprv_decContextClearStatus U_ICU_ENTRY_POINT_RENAME(uprv_decContextClearStatus) #define uprv_decContextDefault U_ICU_ENTRY_POINT_RENAME(uprv_decContextDefault) #define uprv_decContextGetRounding U_ICU_ENTRY_POINT_RENAME(uprv_decContextGetRounding) @@ -1329,7 +1362,6 @@ #define uprv_fmod U_ICU_ENTRY_POINT_RENAME(uprv_fmod) #define uprv_free U_ICU_ENTRY_POINT_RENAME(uprv_free) #define uprv_getCharNameCharacters U_ICU_ENTRY_POINT_RENAME(uprv_getCharNameCharacters) -#define uprv_getDefaultCodepage U_ICU_ENTRY_POINT_RENAME(uprv_getDefaultCodepage) #define uprv_getDefaultLocaleID U_ICU_ENTRY_POINT_RENAME(uprv_getDefaultLocaleID) #define uprv_getInfinity U_ICU_ENTRY_POINT_RENAME(uprv_getInfinity) #define uprv_getMaxCharNameLength U_ICU_ENTRY_POINT_RENAME(uprv_getMaxCharNameLength) @@ -1754,7 +1786,6 @@ #define utrie2_fromUTrie U_ICU_ENTRY_POINT_RENAME(utrie2_fromUTrie) #define utrie2_get32 U_ICU_ENTRY_POINT_RENAME(utrie2_get32) #define utrie2_get32FromLeadSurrogateCodeUnit U_ICU_ENTRY_POINT_RENAME(utrie2_get32FromLeadSurrogateCodeUnit) -#define utrie2_getVersion U_ICU_ENTRY_POINT_RENAME(utrie2_getVersion) #define utrie2_internalU8NextIndex U_ICU_ENTRY_POINT_RENAME(utrie2_internalU8NextIndex) #define utrie2_internalU8PrevIndex U_ICU_ENTRY_POINT_RENAME(utrie2_internalU8PrevIndex) #define utrie2_isFrozen U_ICU_ENTRY_POINT_RENAME(utrie2_isFrozen) @@ -1766,7 +1797,6 @@ #define utrie2_set32ForLeadSurrogateCodeUnit U_ICU_ENTRY_POINT_RENAME(utrie2_set32ForLeadSurrogateCodeUnit) #define utrie2_setRange32 U_ICU_ENTRY_POINT_RENAME(utrie2_setRange32) #define utrie2_swap U_ICU_ENTRY_POINT_RENAME(utrie2_swap) -#define utrie2_swapAnyVersion U_ICU_ENTRY_POINT_RENAME(utrie2_swapAnyVersion) #define utrie_clone U_ICU_ENTRY_POINT_RENAME(utrie_clone) #define utrie_close U_ICU_ENTRY_POINT_RENAME(utrie_close) #define utrie_defaultGetFoldingOffset U_ICU_ENTRY_POINT_RENAME(utrie_defaultGetFoldingOffset) @@ -1778,6 +1808,7 @@ #define utrie_set32 U_ICU_ENTRY_POINT_RENAME(utrie_set32) #define utrie_setRange32 U_ICU_ENTRY_POINT_RENAME(utrie_setRange32) #define utrie_swap U_ICU_ENTRY_POINT_RENAME(utrie_swap) +#define utrie_swapAnyVersion U_ICU_ENTRY_POINT_RENAME(utrie_swapAnyVersion) #define utrie_unserialize U_ICU_ENTRY_POINT_RENAME(utrie_unserialize) #define utrie_unserializeDummy U_ICU_ENTRY_POINT_RENAME(utrie_unserializeDummy) #define vzone_clone U_ICU_ENTRY_POINT_RENAME(vzone_clone) @@ -1827,6 +1858,7 @@ #define ztrans_setTime U_ICU_ENTRY_POINT_RENAME(ztrans_setTime) #define ztrans_setTo U_ICU_ENTRY_POINT_RENAME(ztrans_setTo) -#endif +#endif /* !(defined(_MSC_VER) && defined(__INTELLISENSE__)) */ +#endif /* U_DISABLE_RENAMING */ +#endif /* URENAME_H */ -#endif diff --git a/deps/icu-small/source/common/unicode/uset.h b/deps/icu-small/source/common/unicode/uset.h index 5b7c5db9ec03e5..ef6bbb5c38f3fb 100644 --- a/deps/icu-small/source/common/unicode/uset.h +++ b/deps/icu-small/source/common/unicode/uset.h @@ -33,10 +33,14 @@ #include "unicode/uchar.h" #include "unicode/localpointer.h" -#ifndef UCNV_H -struct USet; +#ifndef USET_DEFINED + +#ifndef U_IN_DOXYGEN +#define USET_DEFINED +#endif /** - * A UnicodeSet. Use the uset_* API to manipulate. Create with + * USet is the C API type corresponding to C++ class UnicodeSet. + * Use the uset_* API to manipulate. Create with * uset_open*, and destroy with uset_close. * @stable ICU 2.4 */ diff --git a/deps/icu-small/source/common/unicode/ustring.h b/deps/icu-small/source/common/unicode/ustring.h index cf6ec0b6b4c9d2..0d2274a0cabb51 100644 --- a/deps/icu-small/source/common/unicode/ustring.h +++ b/deps/icu-small/source/common/unicode/ustring.h @@ -895,34 +895,31 @@ u_memrchr32(const UChar *s, UChar32 c, int32_t count); * parameters. * The string parameter must be a C string literal. * The length of the string, not including the terminating - * NUL, must be specified as a constant. + * `NUL`, must be specified as a constant. * The U_STRING_DECL macro should be invoked exactly once for one * such string variable before it is used. * * Usage: - *
- *    U_STRING_DECL(ustringVar1, "Quick-Fox 2", 11);
- *    U_STRING_DECL(ustringVar2, "jumps 5%", 8);
- *    static UBool didInit=FALSE;
- *
- *    int32_t function() {
- *        if(!didInit) {
- *            U_STRING_INIT(ustringVar1, "Quick-Fox 2", 11);
- *            U_STRING_INIT(ustringVar2, "jumps 5%", 8);
- *            didInit=TRUE;
- *        }
- *        return u_strcmp(ustringVar1, ustringVar2);
- *    }
- * 
- * - * Note that the macros will NOT consistently work if their argument is another #define. - * The following will not work on all platforms, don't use it. - * - *
+ *
+ *     U_STRING_DECL(ustringVar1, "Quick-Fox 2", 11);
+ *     U_STRING_DECL(ustringVar2, "jumps 5%", 8);
+ *     static UBool didInit=FALSE;
+ *
+ *     int32_t function() {
+ *         if(!didInit) {
+ *             U_STRING_INIT(ustringVar1, "Quick-Fox 2", 11);
+ *             U_STRING_INIT(ustringVar2, "jumps 5%", 8);
+ *             didInit=TRUE;
+ *         }
+ *         return u_strcmp(ustringVar1, ustringVar2);
+ *     }
+ *
+ * Note that the macros will NOT consistently work if their argument is another #`define`.
+ * The following will not work on all platforms, don't use it.
+ *
  *     #define GLUCK "Mr. Gluck"
  *     U_STRING_DECL(var, GLUCK, 9)
  *     U_STRING_INIT(var, GLUCK, 9)
- * 
* * Instead, use the string literal "Mr. Gluck" as the argument to both macro * calls. diff --git a/deps/icu-small/source/common/unicode/utf16.h b/deps/icu-small/source/common/unicode/utf16.h index b9b9c59d3cb21f..0908b4f00e9bf1 100644 --- a/deps/icu-small/source/common/unicode/utf16.h +++ b/deps/icu-small/source/common/unicode/utf16.h @@ -213,8 +213,6 @@ } \ } -#ifndef U_HIDE_DRAFT_API - /** * Get a code point from a string at a random-access offset, * without changing the offset. @@ -236,7 +234,7 @@ * @param length string length * @param c output UChar32 variable * @see U16_GET_UNSAFE - * @draft ICU 60 + * @stable ICU 60 */ #define U16_GET_OR_FFFD(s, start, i, length, c) { \ (c)=(s)[i]; \ @@ -258,8 +256,6 @@ } \ } -#endif // U_HIDE_DRAFT_API - /* definitions with forward iteration --------------------------------------- */ /** @@ -320,8 +316,6 @@ } \ } -#ifndef U_HIDE_DRAFT_API - /** * Get a code point from a string at a code point boundary offset, * and advance the offset to the next code point boundary. @@ -341,7 +335,7 @@ * @param length string length * @param c output UChar32 variable * @see U16_NEXT_UNSAFE - * @draft ICU 60 + * @stable ICU 60 */ #define U16_NEXT_OR_FFFD(s, i, length, c) { \ (c)=(s)[(i)++]; \ @@ -356,8 +350,6 @@ } \ } -#endif // U_HIDE_DRAFT_API - /** * Append a code point to a string, overwriting 1 or 2 code units. * The offset points to the current end of the string contents @@ -585,8 +577,6 @@ } \ } -#ifndef U_HIDE_DRAFT_API - /** * Move the string offset from one code point boundary to the previous one * and get the code point between them. @@ -605,7 +595,7 @@ * @param i string offset, must be startvalue.pointer; - U_ASSERT(sharedObject->cachePtr = this); + U_ASSERT(sharedObject->cachePtr == this); uhash_removeElement(fHashtable, element); removeSoftRef(sharedObject); // Deletes the sharedObject when softRefCount goes to zero. result = TRUE; diff --git a/deps/icu-small/source/common/uniset.cpp b/deps/icu-small/source/common/uniset.cpp index d828660796f743..7d2e3cd619fc1d 100644 --- a/deps/icu-small/source/common/uniset.cpp +++ b/deps/icu-small/source/common/uniset.cpp @@ -152,6 +152,7 @@ UnicodeSet::UnicodeSet() : UErrorCode status = U_ZERO_ERROR; allocateStrings(status); if (U_FAILURE(status)) { + setToBogus(); // If memory allocation failed, set to bogus state. return; } list = (UChar32*) uprv_malloc(sizeof(UChar32) * capacity); @@ -179,6 +180,7 @@ UnicodeSet::UnicodeSet(UChar32 start, UChar32 end) : UErrorCode status = U_ZERO_ERROR; allocateStrings(status); if (U_FAILURE(status)) { + setToBogus(); // If memory allocation failed, set to bogus state. return; } list = (UChar32*) uprv_malloc(sizeof(UChar32) * capacity); @@ -206,6 +208,7 @@ UnicodeSet::UnicodeSet(const UnicodeSet& o) : UErrorCode status = U_ZERO_ERROR; allocateStrings(status); if (U_FAILURE(status)) { + setToBogus(); // If memory allocation failed, set to bogus state. return; } list = (UChar32*) uprv_malloc(sizeof(UChar32) * capacity); @@ -230,6 +233,7 @@ UnicodeSet::UnicodeSet(const UnicodeSet& o, UBool /* asThawed */) : UErrorCode status = U_ZERO_ERROR; allocateStrings(status); if (U_FAILURE(status)) { + setToBogus(); // If memory allocation failed, set to bogus state. return; } list = (UChar32*) uprv_malloc(sizeof(UChar32) * capacity); @@ -272,6 +276,10 @@ UnicodeSet::~UnicodeSet() { * Assigns this object to be a copy of another. */ UnicodeSet& UnicodeSet::operator=(const UnicodeSet& o) { + return copyFrom(o, FALSE); +} + +UnicodeSet& UnicodeSet::copyFrom(const UnicodeSet& o, UBool asThawed) { if (this == &o) { return *this; } @@ -285,11 +293,12 @@ UnicodeSet& UnicodeSet::operator=(const UnicodeSet& o) { UErrorCode ec = U_ZERO_ERROR; ensureCapacity(o.len, ec); if (U_FAILURE(ec)) { - return *this; // There is no way to report this error :-( + // ensureCapacity will mark the UnicodeSet as Bogus if OOM failure happens. + return *this; } len = o.len; uprv_memcpy(list, o.list, (size_t)len*sizeof(UChar32)); - if (o.bmpSet == NULL) { + if (o.bmpSet == NULL || asThawed) { bmpSet = NULL; } else { bmpSet = new BMPSet(*o.bmpSet, list, len); @@ -304,7 +313,7 @@ UnicodeSet& UnicodeSet::operator=(const UnicodeSet& o) { setToBogus(); return *this; } - if (o.stringSpan == NULL) { + if (o.stringSpan == NULL || asThawed) { stringSpan = NULL; } else { stringSpan = new UnicodeSetStringSpan(*o.stringSpan, *strings); @@ -359,12 +368,12 @@ UBool UnicodeSet::operator==(const UnicodeSet& o) const { * @see Object#hashCode() */ int32_t UnicodeSet::hashCode(void) const { - int32_t result = len; + uint32_t result = static_cast(len); for (int32_t i = 0; i < len; ++i) { - result *= 1000003; + result *= 1000003u; result += list[i]; } - return result; + return static_cast(result); } //---------------------------------------------------------------- @@ -912,7 +921,8 @@ UnicodeSet& UnicodeSet::add(UChar32 c) { UErrorCode status = U_ZERO_ERROR; ensureCapacity(len+1, status); if (U_FAILURE(status)) { - return *this; // There is no way to report this error :-( + // ensureCapacity will mark the object as Bogus if OOM failure happens. + return *this; } list[len++] = UNICODESET_HIGH; } @@ -957,7 +967,8 @@ UnicodeSet& UnicodeSet::add(UChar32 c) { UErrorCode status = U_ZERO_ERROR; ensureCapacity(len+2, status); if (U_FAILURE(status)) { - return *this; // There is no way to report this error :-( + // ensureCapacity will mark the object as Bogus if OOM failure happens. + return *this; } //for (int32_t k=len-1; k>=i; --k) { @@ -1654,12 +1665,13 @@ UBool UnicodeSet::allocateStrings(UErrorCode &status) { } void UnicodeSet::ensureCapacity(int32_t newLen, UErrorCode& ec) { - if (newLen <= capacity) + if (newLen <= capacity) { return; + } UChar32* temp = (UChar32*) uprv_realloc(list, sizeof(UChar32) * (newLen + GROW_EXTRA)); if (temp == NULL) { ec = U_MEMORY_ALLOCATION_ERROR; - setToBogus(); + setToBogus(); // set the object to bogus state if an OOM failure occurred. return; } list = temp; diff --git a/deps/icu-small/source/common/uniset_props.cpp b/deps/icu-small/source/common/uniset_props.cpp index ef5d6a32b2d10b..1312de209802b5 100644 --- a/deps/icu-small/source/common/uniset_props.cpp +++ b/deps/icu-small/source/common/uniset_props.cpp @@ -36,8 +36,6 @@ #include "uprops.h" #include "propname.h" #include "normalizer2impl.h" -#include "ucase.h" -#include "ubidi_props.h" #include "uinvchar.h" #include "uprops.h" #include "charstr.h" @@ -98,47 +96,13 @@ static const char ASSIGNED[] = "Assigned"; // [:^Cn:] U_CDECL_BEGIN static UBool U_CALLCONV uset_cleanup(); -struct Inclusion { - UnicodeSet *fSet; - UInitOnce fInitOnce; -}; -static Inclusion gInclusions[UPROPS_SRC_COUNT]; // cached getInclusions() - static UnicodeSet *uni32Singleton; static icu::UInitOnce uni32InitOnce = U_INITONCE_INITIALIZER; -//---------------------------------------------------------------- -// Inclusions list -//---------------------------------------------------------------- - -// USetAdder implementation -// Does not use uset.h to reduce code dependencies -static void U_CALLCONV -_set_add(USet *set, UChar32 c) { - ((UnicodeSet *)set)->add(c); -} - -static void U_CALLCONV -_set_addRange(USet *set, UChar32 start, UChar32 end) { - ((UnicodeSet *)set)->add(start, end); -} - -static void U_CALLCONV -_set_addString(USet *set, const UChar *str, int32_t length) { - ((UnicodeSet *)set)->add(UnicodeString((UBool)(length<0), str, length)); -} - /** * Cleanup function for UnicodeSet */ static UBool U_CALLCONV uset_cleanup(void) { - for(int32_t i = UPROPS_SRC_NONE; i < UPROPS_SRC_COUNT; ++i) { - Inclusion &in = gInclusions[i]; - delete in.fSet; - in.fSet = NULL; - in.fInitOnce.reset(); - } - delete uni32Singleton; uni32Singleton = NULL; uni32InitOnce.reset(); @@ -149,114 +113,6 @@ U_CDECL_END U_NAMESPACE_BEGIN -/* -Reduce excessive reallocation, and make it easier to detect initialization problems. -Usually you don't see smaller sets than this for Unicode 5.0. -*/ -#define DEFAULT_INCLUSION_CAPACITY 3072 - -void U_CALLCONV UnicodeSet_initInclusion(int32_t src, UErrorCode &status) { - // This function is invoked only via umtx_initOnce(). - // This function is a friend of class UnicodeSet. - - U_ASSERT(src >=0 && srcensureCapacity(DEFAULT_INCLUSION_CAPACITY, status); - switch(src) { - case UPROPS_SRC_CHAR: - uchar_addPropertyStarts(&sa, &status); - break; - case UPROPS_SRC_PROPSVEC: - upropsvec_addPropertyStarts(&sa, &status); - break; - case UPROPS_SRC_CHAR_AND_PROPSVEC: - uchar_addPropertyStarts(&sa, &status); - upropsvec_addPropertyStarts(&sa, &status); - break; -#if !UCONFIG_NO_NORMALIZATION - case UPROPS_SRC_CASE_AND_NORM: { - const Normalizer2Impl *impl=Normalizer2Factory::getNFCImpl(status); - if(U_SUCCESS(status)) { - impl->addPropertyStarts(&sa, status); - } - ucase_addPropertyStarts(&sa, &status); - break; - } - case UPROPS_SRC_NFC: { - const Normalizer2Impl *impl=Normalizer2Factory::getNFCImpl(status); - if(U_SUCCESS(status)) { - impl->addPropertyStarts(&sa, status); - } - break; - } - case UPROPS_SRC_NFKC: { - const Normalizer2Impl *impl=Normalizer2Factory::getNFKCImpl(status); - if(U_SUCCESS(status)) { - impl->addPropertyStarts(&sa, status); - } - break; - } - case UPROPS_SRC_NFKC_CF: { - const Normalizer2Impl *impl=Normalizer2Factory::getNFKC_CFImpl(status); - if(U_SUCCESS(status)) { - impl->addPropertyStarts(&sa, status); - } - break; - } - case UPROPS_SRC_NFC_CANON_ITER: { - const Normalizer2Impl *impl=Normalizer2Factory::getNFCImpl(status); - if(U_SUCCESS(status)) { - impl->addCanonIterPropertyStarts(&sa, status); - } - break; - } -#endif - case UPROPS_SRC_CASE: - ucase_addPropertyStarts(&sa, &status); - break; - case UPROPS_SRC_BIDI: - ubidi_addPropertyStarts(&sa, &status); - break; - default: - status = U_INTERNAL_PROGRAM_ERROR; - break; - } - - if (U_FAILURE(status)) { - delete incl; - incl = NULL; - return; - } - // Compact for caching - incl->compact(); - ucln_common_registerCleanup(UCLN_COMMON_USET, uset_cleanup); -} - - - -const UnicodeSet* UnicodeSet::getInclusions(int32_t src, UErrorCode &status) { - U_ASSERT(src >=0 && src 0 && uprv_memcmp(&v, version, sizeof(v)) <= 0; } -typedef struct { - UProperty prop; - int32_t value; -} IntPropertyContext; - -static UBool intPropertyFilter(UChar32 ch, void* context) { - IntPropertyContext* c = (IntPropertyContext*)context; - return u_getIntPropertyValue((UChar32) ch, c->prop) == c->value; -} - static UBool scriptExtensionsFilter(UChar32 ch, void* context) { return uscript_hasScript(ch, *(UScriptCode*)context); } @@ -891,7 +732,7 @@ static UBool scriptExtensionsFilter(UChar32 ch, void* context) { */ void UnicodeSet::applyFilter(UnicodeSet::Filter filter, void* context, - int32_t src, + const UnicodeSet* inclusions, UErrorCode &status) { if (U_FAILURE(status)) return; @@ -902,12 +743,8 @@ void UnicodeSet::applyFilter(UnicodeSet::Filter filter, // To improve performance, use an inclusions set which // encodes information about character ranges that are known // to have identical properties. - // getInclusions(src) contains exactly the first characters of - // same-value ranges for the given properties "source". - const UnicodeSet* inclusions = getInclusions(src, status); - if (U_FAILURE(status)) { - return; - } + // inclusions contains the first characters of + // same-value ranges for the given property. clear(); @@ -944,6 +781,43 @@ void UnicodeSet::applyFilter(UnicodeSet::Filter filter, namespace { +/** Maps map values to 1 if the mask contains their value'th bit, all others to 0. */ +uint32_t U_CALLCONV generalCategoryMaskFilter(const void *context, uint32_t value) { + uint32_t mask = *(const uint32_t *)context; + value = U_MASK(value) & mask; + if (value != 0) { value = 1; } + return value; +} + +/** Maps one map value to 1, all others to 0. */ +uint32_t U_CALLCONV intValueFilter(const void *context, uint32_t value) { + uint32_t v = *(const uint32_t *)context; + return value == v ? 1 : 0; +} + +} // namespace + +void UnicodeSet::applyIntPropertyValue(const UCPMap *map, + UCPMapValueFilter *filter, const void *context, + UErrorCode &errorCode) { + if (U_FAILURE(errorCode)) { return; } + clear(); + UChar32 start = 0, end; + uint32_t value; + while ((end = ucpmap_getRange(map, start, UCPMAP_RANGE_NORMAL, 0, + filter, context, &value)) >= 0) { + if (value != 0) { + add(start, end); + } + start = end + 1; + } + if (isBogus()) { + errorCode = U_MEMORY_ALLOCATION_ERROR; + } +} + +namespace { + static UBool mungeCharName(char* dst, const char* src, int32_t dstCapacity) { /* Note: we use ' ' in compiler code page */ int32_t j = 0; @@ -971,16 +845,35 @@ static UBool mungeCharName(char* dst, const char* src, int32_t dstCapacity) { UnicodeSet& UnicodeSet::applyIntPropertyValue(UProperty prop, int32_t value, UErrorCode& ec) { - if (U_FAILURE(ec) || isFrozen()) return *this; - + if (U_FAILURE(ec)) { return *this; } + // All of the following check isFrozen() before modifying this set. if (prop == UCHAR_GENERAL_CATEGORY_MASK) { - applyFilter(generalCategoryMaskFilter, &value, UPROPS_SRC_CHAR, ec); + const UCPMap *map = u_getIntPropertyMap(UCHAR_GENERAL_CATEGORY, &ec); + applyIntPropertyValue(map, generalCategoryMaskFilter, &value, ec); } else if (prop == UCHAR_SCRIPT_EXTENSIONS) { + const UnicodeSet* inclusions = CharacterProperties::getInclusionsForProperty(prop, ec); UScriptCode script = (UScriptCode)value; - applyFilter(scriptExtensionsFilter, &script, UPROPS_SRC_PROPSVEC, ec); + applyFilter(scriptExtensionsFilter, &script, inclusions, ec); + } else if (0 <= prop && prop < UCHAR_BINARY_LIMIT) { + if (value == 0 || value == 1) { + const USet *set = u_getBinaryPropertySet(prop, &ec); + if (U_FAILURE(ec)) { return *this; } + copyFrom(*UnicodeSet::fromUSet(set), TRUE); + if (value == 0) { + complement(); + } + } else { + clear(); + } + } else if (UCHAR_INT_START <= prop && prop < UCHAR_INT_LIMIT) { + const UCPMap *map = u_getIntPropertyMap(prop, &ec); + applyIntPropertyValue(map, intValueFilter, &value, ec); } else { - IntPropertyContext c = {prop, value}; - applyFilter(intPropertyFilter, &c, uprops_getSource(prop), ec); + // This code used to always call getInclusions(property source) + // which sets an error for an unsupported property. + ec = U_ILLEGAL_ARGUMENT_ERROR; + // Otherwise we would just clear() this set because + // getIntPropertyValue(c, prop) returns 0 for all code points. } return *this; } @@ -1030,13 +923,13 @@ UnicodeSet::applyPropertyAlias(const UnicodeString& prop, p == UCHAR_TRAIL_CANONICAL_COMBINING_CLASS || p == UCHAR_LEAD_CANONICAL_COMBINING_CLASS) { char* end; - double value = uprv_strtod(vname.data(), &end); + double val = uprv_strtod(vname.data(), &end); // Anything between 0 and 255 is valid even if unused. // Cast double->int only after range check. // We catch NaN here because comparing it with both 0 and 255 will be false // (as are all comparisons with NaN). - if (*end != 0 || !(0 <= value && value <= 255) || - (v = (int32_t)value) != value) { + if (*end != 0 || !(0 <= val && val <= 255) || + (v = (int32_t)val) != val) { // non-integral value or outside 0..255, or trailing junk FAIL(ec); } @@ -1052,11 +945,12 @@ UnicodeSet::applyPropertyAlias(const UnicodeString& prop, case UCHAR_NUMERIC_VALUE: { char* end; - double value = uprv_strtod(vname.data(), &end); + double val = uprv_strtod(vname.data(), &end); if (*end != 0) { FAIL(ec); } - applyFilter(numericValueFilter, &value, UPROPS_SRC_CHAR, ec); + applyFilter(numericValueFilter, &val, + CharacterProperties::getInclusionsForProperty(p, ec), ec); return *this; } case UCHAR_NAME: @@ -1085,7 +979,8 @@ UnicodeSet::applyPropertyAlias(const UnicodeString& prop, if (!mungeCharName(buf, vname.data(), sizeof(buf))) FAIL(ec); UVersionInfo version; u_versionFromString(version, buf); - applyFilter(versionFilter, &version, UPROPS_SRC_PROPSVEC, ec); + applyFilter(versionFilter, &version, + CharacterProperties::getInclusionsForProperty(p, ec), ec); return *this; } case UCHAR_SCRIPT_EXTENSIONS: diff --git a/deps/icu-small/source/common/unistr.cpp b/deps/icu-small/source/common/unistr.cpp index 48ad929e85a729..ff85734d615efa 100644 --- a/deps/icu-small/source/common/unistr.cpp +++ b/deps/icu-small/source/common/unistr.cpp @@ -1447,10 +1447,15 @@ UnicodeString::doReplace(int32_t start, } if(srcChars == 0) { - srcStart = srcLength = 0; - } else if(srcLength < 0) { - // get the srcLength if necessary - srcLength = u_strlen(srcChars + srcStart); + srcLength = 0; + } else { + // Perform all remaining operations relative to srcChars + srcStart. + // From this point forward, do not use srcStart. + srcChars += srcStart; + if (srcLength < 0) { + // get the srcLength if necessary + srcLength = u_strlen(srcChars); + } } // pin the indices to legal values @@ -1465,17 +1470,28 @@ UnicodeString::doReplace(int32_t start, } newLength += srcLength; + // Check for insertion into ourself + const UChar *oldArray = getArrayStart(); + if (isBufferWritable() && + oldArray < srcChars + srcLength && + srcChars < oldArray + oldLength) { + // Copy into a new UnicodeString and start over + UnicodeString copy(srcChars, srcLength); + if (copy.isBogus()) { + setToBogus(); + return *this; + } + return doReplace(start, length, copy.getArrayStart(), 0, srcLength); + } + // cloneArrayIfNeeded(doCopyArray=FALSE) may change fArray but will not copy the current contents; // therefore we need to keep the current fArray UChar oldStackBuffer[US_STACKBUF_SIZE]; - UChar *oldArray; if((fUnion.fFields.fLengthAndFlags&kUsingStackBuffer) && (newLength > US_STACKBUF_SIZE)) { // copy the stack buffer contents because it will be overwritten with // fUnion.fFields values - u_memcpy(oldStackBuffer, fUnion.fStackFields.fBuffer, oldLength); + u_memcpy(oldStackBuffer, oldArray, oldLength); oldArray = oldStackBuffer; - } else { - oldArray = getArrayStart(); } // clone our array and allocate a bigger array if needed @@ -1503,7 +1519,7 @@ UnicodeString::doReplace(int32_t start, } // now fill in the hole with the new string - us_arrayCopy(srcChars, srcStart, newArray, start, srcLength); + us_arrayCopy(srcChars, 0, newArray, start, srcLength); setLength(newLength); @@ -1536,15 +1552,34 @@ UnicodeString::doAppend(const UChar *srcChars, int32_t srcStart, int32_t srcLeng return *this; } + // Perform all remaining operations relative to srcChars + srcStart. + // From this point forward, do not use srcStart. + srcChars += srcStart; + if(srcLength < 0) { // get the srcLength if necessary - if((srcLength = u_strlen(srcChars + srcStart)) == 0) { + if((srcLength = u_strlen(srcChars)) == 0) { return *this; } } int32_t oldLength = length(); int32_t newLength = oldLength + srcLength; + + // Check for append onto ourself + const UChar* oldArray = getArrayStart(); + if (isBufferWritable() && + oldArray < srcChars + srcLength && + srcChars < oldArray + oldLength) { + // Copy into a new UnicodeString and start over + UnicodeString copy(srcChars, srcLength); + if (copy.isBogus()) { + setToBogus(); + return *this; + } + return doAppend(copy.getArrayStart(), 0, srcLength); + } + // optimize append() onto a large-enough, owned string if((newLength <= getCapacity() && isBufferWritable()) || cloneArrayIfNeeded(newLength, getGrowCapacity(newLength))) { @@ -1556,8 +1591,8 @@ UnicodeString::doAppend(const UChar *srcChars, int32_t srcStart, int32_t srcLeng // or // str.appendString(buffer, length) // or similar. - if(srcChars + srcStart != newArray + oldLength) { - us_arrayCopy(srcChars, srcStart, newArray, oldLength, srcLength); + if(srcChars != newArray + oldLength) { + us_arrayCopy(srcChars, 0, newArray, oldLength, srcLength); } setLength(newLength); } diff --git a/deps/icu-small/source/common/uprops.cpp b/deps/icu-small/source/common/uprops.cpp index 21723b32aa7c8d..2421c15d2bd0b6 100644 --- a/deps/icu-small/source/common/uprops.cpp +++ b/deps/icu-small/source/common/uprops.cpp @@ -25,6 +25,7 @@ #include "unicode/utypes.h" #include "unicode/uchar.h" +#include "unicode/ucptrie.h" #include "unicode/unorm2.h" #include "unicode/uscript.h" #include "unicode/ustring.h" @@ -36,6 +37,10 @@ #include "ucase.h" #include "ustr_imp.h" +// ulayout_props_data.h is machine-generated by genprops +#define INCLUDED_FROM_UPROPS_CPP +#include "ulayout_props_data.h" + U_NAMESPACE_USE /* general properties API functions ----------------------------------------- */ @@ -56,7 +61,7 @@ static UBool defaultContains(const BinaryProperty &prop, UChar32 c, UProperty /* } static UBool caseBinaryPropertyContains(const BinaryProperty &/*prop*/, UChar32 c, UProperty which) { - return ucase_hasBinaryProperty(c, which); + return static_cast(ucase_hasBinaryProperty(c, which)); } static UBool isBidiControl(const BinaryProperty &/*prop*/, UChar32 c, UProperty /*which*/) { @@ -428,6 +433,18 @@ static int32_t getTrailCombiningClass(const IntProperty &/*prop*/, UChar32 c, UP } #endif +static int32_t getInPC(const IntProperty &, UChar32 c, UProperty) { + return ucptrie_get(&inpc_trie, c); +} + +static int32_t getInSC(const IntProperty &, UChar32 c, UProperty) { + return ucptrie_get(&insc_trie, c); +} + +static int32_t getVo(const IntProperty &, UChar32 c, UProperty) { + return ucptrie_get(&vo_trie, c); +} + static const IntProperty intProps[UCHAR_INT_LIMIT-UCHAR_INT_START]={ /* * column, mask and shift values for int-value properties from u_getUnicodeProperties(). @@ -463,6 +480,9 @@ static const IntProperty intProps[UCHAR_INT_LIMIT-UCHAR_INT_START]={ { 2, UPROPS_SB_MASK, UPROPS_SB_SHIFT, defaultGetValue, defaultGetMaxValue }, { 2, UPROPS_WB_MASK, UPROPS_WB_SHIFT, defaultGetValue, defaultGetMaxValue }, { UPROPS_SRC_BIDI, 0, 0, getBiDiPairedBracketType, biDiGetMaxValue }, + { UPROPS_SRC_INPC, 0, maxInPCValue, getInPC, getMaxValueFromShift }, + { UPROPS_SRC_INSC, 0, maxInSCValue, getInSC, getMaxValueFromShift }, + { UPROPS_SRC_VO, 0, maxVoValue, getVo, getMaxValueFromShift }, }; U_CAPI int32_t U_EXPORT2 @@ -564,6 +584,34 @@ uprops_getSource(UProperty which) { } } +U_CFUNC void U_EXPORT2 +uprops_addPropertyStarts(UPropertySource src, const USetAdder *sa, UErrorCode *pErrorCode) { + if (U_FAILURE(*pErrorCode)) { return; } + const UCPTrie *trie; + switch (src) { + case UPROPS_SRC_INPC: + trie = &inpc_trie; + break; + case UPROPS_SRC_INSC: + trie = &insc_trie; + break; + case UPROPS_SRC_VO: + trie = &vo_trie; + break; + default: + *pErrorCode = U_ILLEGAL_ARGUMENT_ERROR; + return; + } + + // Add the start code point of each same-value range of the trie. + UChar32 start = 0, end; + while ((end = ucptrie_getRange(trie, start, UCPMAP_RANGE_NORMAL, 0, + nullptr, nullptr, nullptr)) >= 0) { + sa->add(sa->set, start); + start = end + 1; + } +} + #if !UCONFIG_NO_NORMALIZATION U_CAPI int32_t U_EXPORT2 diff --git a/deps/icu-small/source/common/uprops.h b/deps/icu-small/source/common/uprops.h index 2078384c3e47dd..1a8e4e84f7445d 100644 --- a/deps/icu-small/source/common/uprops.h +++ b/deps/icu-small/source/common/uprops.h @@ -397,6 +397,10 @@ enum UPropertySource { UPROPS_SRC_NFKC_CF, /** From normalizer2impl.cpp/nfc.nrm canonical iterator data */ UPROPS_SRC_NFC_CANON_ITER, + // Text layout properties. + UPROPS_SRC_INPC, + UPROPS_SRC_INSC, + UPROPS_SRC_VO, /** One more than the highest UPropertySource (UPROPS_SRC_) constant. */ UPROPS_SRC_COUNT }; @@ -425,6 +429,9 @@ uchar_addPropertyStarts(const USetAdder *sa, UErrorCode *pErrorCode); U_CFUNC void U_EXPORT2 upropsvec_addPropertyStarts(const USetAdder *sa, UErrorCode *pErrorCode); +U_CFUNC void U_EXPORT2 +uprops_addPropertyStarts(UPropertySource src, const USetAdder *sa, UErrorCode *pErrorCode); + /** * Return a set of characters for property enumeration. * For each two consecutive characters (start, limit) in the set, @@ -452,6 +459,13 @@ U_NAMESPACE_BEGIN class UnicodeSet; +class CharacterProperties { +public: + CharacterProperties() = delete; + static void U_CALLCONV initInclusion(UPropertySource src, UErrorCode &errorCode); + static const UnicodeSet *getInclusionsForProperty(UProperty prop, UErrorCode &errorCode); +}; + // implemented in uniset_props.cpp U_CFUNC UnicodeSet * uniset_getUnicode32Instance(UErrorCode &errorCode); diff --git a/deps/icu-small/source/common/uresbund.cpp b/deps/icu-small/source/common/uresbund.cpp index c88d9014ec23b7..3da73421c0cfb7 100644 --- a/deps/icu-small/source/common/uresbund.cpp +++ b/deps/icu-small/source/common/uresbund.cpp @@ -368,6 +368,11 @@ static UResourceDataEntry *init_entry(const char *localeID, const char *path, UE res_load(&(r->fData), r->fPath, r->fName, status); if (U_FAILURE(*status)) { + /* if we failed to load due to an out-of-memory error, exit early. */ + if (*status == U_MEMORY_ALLOCATION_ERROR) { + uprv_free(r); + return NULL; + } /* we have no such entry in dll, so it will always use fallback */ *status = U_USING_FALLBACK_WARNING; r->fBogus = U_USING_FALLBACK_WARNING; @@ -537,6 +542,11 @@ loadParentsExceptRoot(UResourceDataEntry *&t1, UErrorCode usrStatus = U_ZERO_ERROR; if (usingUSRData) { // This code inserts user override data into the inheritance chain. u2 = init_entry(name, usrDataPath, &usrStatus); + // If we failed due to out-of-memory, report that to the caller and exit early. + if (usrStatus == U_MEMORY_ALLOCATION_ERROR) { + *status = usrStatus; + return FALSE; + } } if (usingUSRData && U_SUCCESS(usrStatus) && u2->fBogus == U_ZERO_ERROR) { @@ -642,21 +652,32 @@ static UResourceDataEntry *entryOpen(const char* path, const char* localeID, /* We're going to skip all the locales that do not have any data */ r = findFirstExisting(path, name, &isRoot, &hasChopped, &isDefault, &intStatus); + // If we failed due to out-of-memory, report the failure and exit early. + if (intStatus == U_MEMORY_ALLOCATION_ERROR) { + *status = intStatus; + goto finishUnlock; + } + if(r != NULL) { /* if there is one real locale, we can look for parents. */ t1 = r; hasRealData = TRUE; if ( usingUSRData ) { /* This code inserts user override data into the inheritance chain */ UErrorCode usrStatus = U_ZERO_ERROR; UResourceDataEntry *u1 = init_entry(t1->fName, usrDataPath, &usrStatus); - if ( u1 != NULL ) { - if(u1->fBogus == U_ZERO_ERROR) { - u1->fParent = t1; - r = u1; - } else { - /* the USR override data wasn't found, set it to be deleted */ - u1->fCountExisting = 0; - } - } + // If we failed due to out-of-memory, report the failure and exit early. + if (intStatus == U_MEMORY_ALLOCATION_ERROR) { + *status = intStatus; + goto finishUnlock; + } + if ( u1 != NULL ) { + if(u1->fBogus == U_ZERO_ERROR) { + u1->fParent = t1; + r = u1; + } else { + /* the USR override data wasn't found, set it to be deleted */ + u1->fCountExisting = 0; + } + } } if (hasChopped && !isRoot) { if (!loadParentsExceptRoot(t1, name, UPRV_LENGTHOF(name), usingUSRData, usrDataPath, status)) { @@ -671,6 +692,11 @@ static UResourceDataEntry *entryOpen(const char* path, const char* localeID, /* insert default locale */ uprv_strcpy(name, uloc_getDefault()); r = findFirstExisting(path, name, &isRoot, &hasChopped, &isDefault, &intStatus); + // If we failed due to out-of-memory, report the failure and exit early. + if (intStatus == U_MEMORY_ALLOCATION_ERROR) { + *status = intStatus; + goto finishUnlock; + } intStatus = U_USING_DEFAULT_WARNING; if(r != NULL) { /* the default locale exists */ t1 = r; @@ -690,6 +716,11 @@ static UResourceDataEntry *entryOpen(const char* path, const char* localeID, if(r == NULL) { uprv_strcpy(name, kRootLocaleName); r = findFirstExisting(path, name, &isRoot, &hasChopped, &isDefault, &intStatus); + // If we failed due to out-of-memory, report the failure and exit early. + if (intStatus == U_MEMORY_ALLOCATION_ERROR) { + *status = intStatus; + goto finishUnlock; + } if(r != NULL) { t1 = r; intStatus = U_USING_DEFAULT_WARNING; @@ -2421,7 +2452,7 @@ ures_loc_nextLocale(UEnumeration* en, UResourceBundle *k = NULL; const char *result = NULL; int32_t len = 0; - if(ures_hasNext(res) && (k = ures_getNextResource(res, &ctx->curr, status))) { + if(ures_hasNext(res) && (k = ures_getNextResource(res, &ctx->curr, status)) != 0) { result = ures_getKey(k); len = (int32_t)uprv_strlen(result); } @@ -2843,7 +2874,7 @@ ures_getKeywordValues(const char *path, const char *keyword, UErrorCode *status) valuesBuf[0]=0; valuesBuf[1]=0; - while((locale = uenum_next(locs, &locLen, status))) { + while((locale = uenum_next(locs, &locLen, status)) != 0) { UResourceBundle *bund = NULL; UResourceBundle *subPtr = NULL; UErrorCode subStatus = U_ZERO_ERROR; /* don't fail if a bundle is unopenable */ @@ -2868,7 +2899,7 @@ ures_getKeywordValues(const char *path, const char *keyword, UErrorCode *status) continue; } - while((subPtr = ures_getNextResource(&item,&subItem,&subStatus)) + while((subPtr = ures_getNextResource(&item,&subItem,&subStatus)) != 0 && U_SUCCESS(subStatus)) { const char *k; int32_t i; diff --git a/deps/icu-small/source/common/uresdata.h b/deps/icu-small/source/common/uresdata.h index 8d845e3dfcfc83..4e28ddccf63199 100644 --- a/deps/icu-small/source/common/uresdata.h +++ b/deps/icu-small/source/common/uresdata.h @@ -475,7 +475,7 @@ U_NAMESPACE_BEGIN class ResourceDataValue : public ResourceValue { public: - ResourceDataValue() : pResData(NULL), res(URES_NONE) {} + ResourceDataValue() : pResData(NULL), res(static_cast(URES_NONE)) {} virtual ~ResourceDataValue(); void setData(const ResourceData *data) { pResData = data; } diff --git a/deps/icu-small/source/common/ushape.cpp b/deps/icu-small/source/common/ushape.cpp index c3f3ef9e2078f0..792de50bbcc736 100644 --- a/deps/icu-small/source/common/ushape.cpp +++ b/deps/icu-small/source/common/ushape.cpp @@ -1323,7 +1323,7 @@ shapeUnicode(UChar *dest, int32_t sourceLength, /* to ensure the array index is within the range */ U_ASSERT(dest[i] >= 0x064Bu && dest[i]-0x064Bu < UPRV_LENGTHOF(IrrelevantPos)); - dest[i] = 0xFE70 + IrrelevantPos[(dest[i] - 0x064B)] + Shape; + dest[i] = 0xFE70 + IrrelevantPos[(dest[i] - 0x064B)] + static_cast(Shape); } }else if ((currLink & APRESENT) > 0) { dest[i] = (UChar)(0xFB50 + (currLink >> 8) + Shape); diff --git a/deps/icu-small/source/common/usprep.cpp b/deps/icu-small/source/common/usprep.cpp index 54a77172fe1b09..1e54e6cab59eb2 100644 --- a/deps/icu-small/source/common/usprep.cpp +++ b/deps/icu-small/source/common/usprep.cpp @@ -112,7 +112,9 @@ hashEntry(const UHashTok parm) { UHashTok namekey, pathkey; namekey.pointer = b->name; pathkey.pointer = b->path; - return uhash_hashChars(namekey)+37*uhash_hashChars(pathkey); + uint32_t unsignedHash = static_cast(uhash_hashChars(namekey)) + + 37u * static_cast(uhash_hashChars(pathkey)); + return static_cast(unsignedHash); } /* compares two entries */ @@ -351,9 +353,9 @@ usprep_getProfile(const char* path, LocalMemory keyName; LocalMemory keyPath; if( key.allocateInsteadAndReset() == NULL || - keyName.allocateInsteadAndCopy(uprv_strlen(name)+1) == NULL || + keyName.allocateInsteadAndCopy(static_cast(uprv_strlen(name)+1)) == NULL || (path != NULL && - keyPath.allocateInsteadAndCopy(uprv_strlen(path)+1) == NULL) + keyPath.allocateInsteadAndCopy(static_cast(uprv_strlen(path)+1)) == NULL) ) { *status = U_MEMORY_ALLOCATION_ERROR; usprep_unload(newProfile.getAlias()); @@ -726,7 +728,7 @@ usprep_prepare( const UStringPrepProfile* profile, ((result < _SPREP_TYPE_THRESHOLD) && (result & 0x01) /* first bit says it the code point is prohibited*/) ){ *status = U_STRINGPREP_PROHIBITED_ERROR; - uprv_syntaxError(b1, b2Index-U16_LENGTH(ch), b2Len, parseError); + uprv_syntaxError(b2, b2Index-U16_LENGTH(ch), b2Len, parseError); return 0; } diff --git a/deps/icu-small/source/common/ustrcase.cpp b/deps/icu-small/source/common/ustrcase.cpp index 978bd3b7b8618e..618e847c65d5a6 100644 --- a/deps/icu-small/source/common/ustrcase.cpp +++ b/deps/icu-small/source/common/ustrcase.cpp @@ -218,7 +218,7 @@ int32_t toLower(int32_t caseLocale, uint32_t options, int32_t srcIndex = srcStart; for (;;) { // fast path for simple cases - UChar lead; + UChar lead = 0; while (srcIndex < srcLimit) { lead = src[srcIndex]; int32_t delta; @@ -238,7 +238,7 @@ int32_t toLower(int32_t caseLocale, uint32_t options, continue; } } - lead += delta; + lead += static_cast(delta); destIndex = appendUnchanged(dest, destIndex, destCapacity, src + prev, srcIndex - 1 - prev, options, edits); if (destIndex >= 0) { @@ -313,7 +313,7 @@ int32_t toUpper(int32_t caseLocale, uint32_t options, int32_t srcIndex = 0; for (;;) { // fast path for simple cases - UChar lead; + UChar lead = 0; while (srcIndex < srcLength) { lead = src[srcIndex]; int32_t delta; @@ -333,7 +333,7 @@ int32_t toUpper(int32_t caseLocale, uint32_t options, continue; } } - lead += delta; + lead += static_cast(delta); destIndex = appendUnchanged(dest, destIndex, destCapacity, src + prev, srcIndex - 1 - prev, options, edits); if (destIndex >= 0) { @@ -1747,8 +1747,8 @@ static int32_t _cmpFold( } if(matchLen1) { - *matchLen1=m1-org1; - *matchLen2=m2-org2; + *matchLen1=static_cast(m1-org1); + *matchLen2=static_cast(m2-org2); } return cmpRes; } diff --git a/deps/icu-small/source/common/utext.cpp b/deps/icu-small/source/common/utext.cpp index 6f3806f27db3f0..5e3a005626e6b8 100644 --- a/deps/icu-small/source/common/utext.cpp +++ b/deps/icu-small/source/common/utext.cpp @@ -1196,9 +1196,9 @@ utf8TextAccess(UText *ut, int64_t index, UBool forward) { // Swap the UText buffers. // We want to fill what was previously the alternate buffer, // and make what was the current buffer be the new alternate. - UTF8Buf *u8b = (UTF8Buf *)ut->q; + UTF8Buf *u8b_swap = (UTF8Buf *)ut->q; ut->q = ut->p; - ut->p = u8b; + ut->p = u8b_swap; int32_t strLen = ut->b; UBool nulTerminated = FALSE; @@ -1207,9 +1207,9 @@ utf8TextAccess(UText *ut, int64_t index, UBool forward) { nulTerminated = TRUE; } - UChar *buf = u8b->buf; - uint8_t *mapToNative = u8b->mapToNative; - uint8_t *mapToUChars = u8b->mapToUChars; + UChar *buf = u8b_swap->buf; + uint8_t *mapToNative = u8b_swap->mapToNative; + uint8_t *mapToUChars = u8b_swap->mapToUChars; int32_t destIx = 0; int32_t srcIx = ix; UBool seenNonAscii = FALSE; @@ -1230,7 +1230,7 @@ utf8TextAccess(UText *ut, int64_t index, UBool forward) { // General case, handle everything. if (seenNonAscii == FALSE) { seenNonAscii = TRUE; - u8b->bufNILimit = destIx; + u8b_swap->bufNILimit = destIx; } int32_t cIx = srcIx; @@ -1263,22 +1263,22 @@ utf8TextAccess(UText *ut, int64_t index, UBool forward) { mapToUChars[srcIx - ix] = (uint8_t)destIx; // fill in Buffer descriptor - u8b->bufNativeStart = ix; - u8b->bufNativeLimit = srcIx; - u8b->bufStartIdx = 0; - u8b->bufLimitIdx = destIx; + u8b_swap->bufNativeStart = ix; + u8b_swap->bufNativeLimit = srcIx; + u8b_swap->bufStartIdx = 0; + u8b_swap->bufLimitIdx = destIx; if (seenNonAscii == FALSE) { - u8b->bufNILimit = destIx; + u8b_swap->bufNILimit = destIx; } - u8b->toUCharsMapStart = u8b->bufNativeStart; + u8b_swap->toUCharsMapStart = u8b_swap->bufNativeStart; // Set UText chunk to refer to this buffer. ut->chunkContents = buf; ut->chunkOffset = 0; - ut->chunkLength = u8b->bufLimitIdx; - ut->chunkNativeStart = u8b->bufNativeStart; - ut->chunkNativeLimit = u8b->bufNativeLimit; - ut->nativeIndexingLimit = u8b->bufNILimit; + ut->chunkLength = u8b_swap->bufLimitIdx; + ut->chunkNativeStart = u8b_swap->bufNativeStart; + ut->chunkNativeLimit = u8b_swap->bufNativeLimit; + ut->nativeIndexingLimit = u8b_swap->bufNILimit; // For zero terminated strings, keep track of the maximum point // scanned so far. @@ -1311,13 +1311,13 @@ utf8TextAccess(UText *ut, int64_t index, UBool forward) { // Swap the UText buffers. // We want to fill what was previously the alternate buffer, // and make what was the current buffer be the new alternate. - UTF8Buf *u8b = (UTF8Buf *)ut->q; + UTF8Buf *u8b_swap = (UTF8Buf *)ut->q; ut->q = ut->p; - ut->p = u8b; + ut->p = u8b_swap; - UChar *buf = u8b->buf; - uint8_t *mapToNative = u8b->mapToNative; - uint8_t *mapToUChars = u8b->mapToUChars; + UChar *buf = u8b_swap->buf; + uint8_t *mapToNative = u8b_swap->mapToNative; + uint8_t *mapToUChars = u8b_swap->mapToUChars; int32_t toUCharsMapStart = ix - sizeof(UTF8Buf::mapToUChars) + 1; // Note that toUCharsMapStart can be negative. Happens when the remaining // text from current position to the beginning is less than the buffer size. @@ -1387,19 +1387,19 @@ utf8TextAccess(UText *ut, int64_t index, UBool forward) { bufNILimit = destIx; } } - u8b->bufNativeStart = srcIx; - u8b->bufNativeLimit = ix; - u8b->bufStartIdx = destIx; - u8b->bufLimitIdx = UTF8_TEXT_CHUNK_SIZE+2; - u8b->bufNILimit = bufNILimit - u8b->bufStartIdx; - u8b->toUCharsMapStart = toUCharsMapStart; - - ut->chunkContents = &buf[u8b->bufStartIdx]; - ut->chunkLength = u8b->bufLimitIdx - u8b->bufStartIdx; + u8b_swap->bufNativeStart = srcIx; + u8b_swap->bufNativeLimit = ix; + u8b_swap->bufStartIdx = destIx; + u8b_swap->bufLimitIdx = UTF8_TEXT_CHUNK_SIZE+2; + u8b_swap->bufNILimit = bufNILimit - u8b_swap->bufStartIdx; + u8b_swap->toUCharsMapStart = toUCharsMapStart; + + ut->chunkContents = &buf[u8b_swap->bufStartIdx]; + ut->chunkLength = u8b_swap->bufLimitIdx - u8b_swap->bufStartIdx; ut->chunkOffset = ut->chunkLength; - ut->chunkNativeStart = u8b->bufNativeStart; - ut->chunkNativeLimit = u8b->bufNativeLimit; - ut->nativeIndexingLimit = u8b->bufNILimit; + ut->chunkNativeStart = u8b_swap->bufNativeStart; + ut->chunkNativeLimit = u8b_swap->bufNativeLimit; + ut->nativeIndexingLimit = u8b_swap->bufNILimit; return TRUE; } diff --git a/deps/icu-small/source/common/utrie.h b/deps/icu-small/source/common/utrie.h index 641027a1a3f448..3e2197eda6c261 100644 --- a/deps/icu-small/source/common/utrie.h +++ b/deps/icu-small/source/common/utrie.h @@ -21,7 +21,6 @@ #include "unicode/utypes.h" #include "unicode/utf16.h" -#include "udataswp.h" U_CDECL_BEGIN @@ -732,17 +731,13 @@ utrie_serialize(UNewTrie *trie, void *data, int32_t capacity, UBool reduceTo16Bits, UErrorCode *pErrorCode); -/** - * Swap a serialized UTrie. - * @internal - */ -U_CAPI int32_t U_EXPORT2 -utrie_swap(const UDataSwapper *ds, - const void *inData, int32_t length, void *outData, - UErrorCode *pErrorCode); - /* serialization ------------------------------------------------------------ */ +// UTrie signature values, in platform endianness and opposite endianness. +// The UTrie signature ASCII byte values spell "Trie". +#define UTRIE_SIG 0x54726965 +#define UTRIE_OE_SIG 0x65697254 + /** * Trie data structure in serialized form: * diff --git a/deps/icu-small/source/common/utrie2.cpp b/deps/icu-small/source/common/utrie2.cpp index 8f9183bafad71f..24ef5782c90565 100644 --- a/deps/icu-small/source/common/utrie2.cpp +++ b/deps/icu-small/source/common/utrie2.cpp @@ -24,11 +24,10 @@ * This file contains only the runtime and enumeration code, for read-only access. * See utrie2_builder.c for the builder code. */ -#ifdef UTRIE2_DEBUG -# include -#endif - #include "unicode/utypes.h" +#ifdef UCPTRIE_DEBUG +#include "unicode/umutablecptrie.h" +#endif #include "unicode/utf.h" #include "unicode/utf8.h" #include "unicode/utf16.h" @@ -202,6 +201,9 @@ utrie2_openFromSerialized(UTrie2ValueBits valueBits, trie->memory=(uint32_t *)data; trie->length=actualLength; trie->isMemoryOwned=FALSE; +#ifdef UTRIE2_DEBUG + trie->name="fromSerialized"; +#endif /* set the pointers to its index and data arrays */ p16=(const uint16_t *)(header+1); @@ -294,6 +296,9 @@ utrie2_openDummy(UTrie2ValueBits valueBits, trie->errorValue=errorValue; trie->highStart=0; trie->highValueIndex=dataMove+UTRIE2_DATA_START_OFFSET; +#ifdef UTRIE2_DEBUG + trie->name="dummy"; +#endif /* set the header fields */ header=(UTrie2Header *)trie->memory; @@ -373,34 +378,15 @@ utrie2_close(UTrie2 *trie) { } if(trie->newTrie!=NULL) { uprv_free(trie->newTrie->data); +#ifdef UCPTRIE_DEBUG + umutablecptrie_close(trie->newTrie->t3); +#endif uprv_free(trie->newTrie); } uprv_free(trie); } } -U_CAPI int32_t U_EXPORT2 -utrie2_getVersion(const void *data, int32_t length, UBool anyEndianOk) { - uint32_t signature; - if(length<16 || data==NULL || (U_POINTER_MASK_LSB(data, 3)!=0)) { - return 0; - } - signature=*(const uint32_t *)data; - if(signature==UTRIE2_SIG) { - return 2; - } - if(anyEndianOk && signature==UTRIE2_OE_SIG) { - return 2; - } - if(signature==UTRIE_SIG) { - return 1; - } - if(anyEndianOk && signature==UTRIE_OE_SIG) { - return 1; - } - return 0; -} - U_CAPI UBool U_EXPORT2 utrie2_isFrozen(const UTrie2 *trie) { return (UBool)(trie->newTrie==NULL); @@ -430,96 +416,6 @@ utrie2_serialize(const UTrie2 *trie, return trie->length; } -U_CAPI int32_t U_EXPORT2 -utrie2_swap(const UDataSwapper *ds, - const void *inData, int32_t length, void *outData, - UErrorCode *pErrorCode) { - const UTrie2Header *inTrie; - UTrie2Header trie; - int32_t dataLength, size; - UTrie2ValueBits valueBits; - - if(U_FAILURE(*pErrorCode)) { - return 0; - } - if(ds==NULL || inData==NULL || (length>=0 && outData==NULL)) { - *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR; - return 0; - } - - /* setup and swapping */ - if(length>=0 && length<(int32_t)sizeof(UTrie2Header)) { - *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR; - return 0; - } - - inTrie=(const UTrie2Header *)inData; - trie.signature=ds->readUInt32(inTrie->signature); - trie.options=ds->readUInt16(inTrie->options); - trie.indexLength=ds->readUInt16(inTrie->indexLength); - trie.shiftedDataLength=ds->readUInt16(inTrie->shiftedDataLength); - - valueBits=(UTrie2ValueBits)(trie.options&UTRIE2_OPTIONS_VALUE_BITS_MASK); - dataLength=(int32_t)trie.shiftedDataLength<=0) { - UTrie2Header *outTrie; - - if(lengthswapArray32(ds, &inTrie->signature, 4, &outTrie->signature, pErrorCode); - ds->swapArray16(ds, &inTrie->options, 12, &outTrie->options, pErrorCode); - - /* swap the index and the data */ - switch(valueBits) { - case UTRIE2_16_VALUE_BITS: - ds->swapArray16(ds, inTrie+1, (trie.indexLength+dataLength)*2, outTrie+1, pErrorCode); - break; - case UTRIE2_32_VALUE_BITS: - ds->swapArray16(ds, inTrie+1, trie.indexLength*2, outTrie+1, pErrorCode); - ds->swapArray32(ds, (const uint16_t *)(inTrie+1)+trie.indexLength, dataLength*4, - (uint16_t *)(outTrie+1)+trie.indexLength, pErrorCode); - break; - default: - *pErrorCode=U_INVALID_FORMAT_ERROR; - return 0; - } - } - - return size; -} - -// utrie2_swapAnyVersion() should be defined here but lives in utrie2_builder.c -// to avoid a dependency from utrie2.cpp on utrie.c. - /* enumeration -------------------------------------------------------------- */ #define MIN_VALUE(a, b) ((a)<(b) ? (a) : (b)) @@ -746,7 +642,7 @@ uint16_t BackwardUTrie2StringIterator::previous16() { codePointLimit=codePointStart; if(start>=codePointStart) { codePoint=U_SENTINEL; - return trie->errorValue; + return static_cast(trie->errorValue); } uint16_t result; UTRIE2_U16_PREV16(trie, start, codePointStart, codePoint, result); @@ -757,7 +653,7 @@ uint16_t ForwardUTrie2StringIterator::next16() { codePointStart=codePointLimit; if(codePointLimit==limit) { codePoint=U_SENTINEL; - return trie->errorValue; + return static_cast(trie->errorValue); } uint16_t result; UTRIE2_U16_NEXT16(trie, codePointLimit, limit, codePoint, result); diff --git a/deps/icu-small/source/common/utrie2.h b/deps/icu-small/source/common/utrie2.h index 8e1caa5e90bde2..75028ee23ac1e9 100644 --- a/deps/icu-small/source/common/utrie2.h +++ b/deps/icu-small/source/common/utrie2.h @@ -22,7 +22,6 @@ #include "unicode/utypes.h" #include "unicode/utf8.h" #include "putilimp.h" -#include "udataswp.h" U_CDECL_BEGIN @@ -330,40 +329,6 @@ utrie2_serialize(const UTrie2 *trie, /* Public UTrie2 API: miscellaneous functions ------------------------------- */ -/** - * Get the UTrie version from 32-bit-aligned memory containing the serialized form - * of either a UTrie (version 1) or a UTrie2 (version 2). - * - * @param data a pointer to 32-bit-aligned memory containing the serialized form - * of a UTrie, version 1 or 2 - * @param length the number of bytes available at data; - * can be more than necessary (see return value) - * @param anyEndianOk If FALSE, only platform-endian serialized forms are recognized. - * If TRUE, opposite-endian serialized forms are recognized as well. - * @return the UTrie version of the serialized form, or 0 if it is not - * recognized as a serialized UTrie - */ -U_CAPI int32_t U_EXPORT2 -utrie2_getVersion(const void *data, int32_t length, UBool anyEndianOk); - -/** - * Swap a serialized UTrie2. - * @internal - */ -U_CAPI int32_t U_EXPORT2 -utrie2_swap(const UDataSwapper *ds, - const void *inData, int32_t length, void *outData, - UErrorCode *pErrorCode); - -/** - * Swap a serialized UTrie or UTrie2. - * @internal - */ -U_CAPI int32_t U_EXPORT2 -utrie2_swapAnyVersion(const UDataSwapper *ds, - const void *inData, int32_t length, void *outData, - UErrorCode *pErrorCode); - /** * Build a UTrie2 (version 2) from a UTrie (version 1). * Enumerates all values in the UTrie and builds a UTrie2 with the same values. @@ -709,6 +674,10 @@ struct UTrie2 { UBool padding1; int16_t padding2; UNewTrie2 *newTrie; /* builder object; NULL when frozen */ + +#ifdef UTRIE2_DEBUG + const char *name; +#endif }; /** diff --git a/deps/icu-small/source/common/utrie2_builder.cpp b/deps/icu-small/source/common/utrie2_builder.cpp index d8a3a06757370d..80e09c9c26b3e1 100644 --- a/deps/icu-small/source/common/utrie2_builder.cpp +++ b/deps/icu-small/source/common/utrie2_builder.cpp @@ -24,16 +24,23 @@ * This file contains only the builder code. * See utrie2.c for the runtime and enumeration code. */ +// #define UTRIE2_DEBUG #ifdef UTRIE2_DEBUG # include #endif +// #define UCPTRIE_DEBUG #include "unicode/utypes.h" +#ifdef UCPTRIE_DEBUG +#include "unicode/ucptrie.h" +#include "unicode/umutablecptrie.h" +#include "ucptrie_impl.h" +#endif #include "cmemory.h" #include "utrie2.h" #include "utrie2_impl.h" -#include "utrie.h" /* for utrie2_fromUTrie() and utrie_swap() */ +#include "utrie.h" // for utrie2_fromUTrie() /* Implementation notes ----------------------------------------------------- */ @@ -132,8 +139,14 @@ utrie2_open(uint32_t initialValue, uint32_t errorValue, UErrorCode *pErrorCode) trie->errorValue=errorValue; trie->highStart=0x110000; trie->newTrie=newTrie; +#ifdef UTRIE2_DEBUG + trie->name="open"; +#endif newTrie->data=data; +#ifdef UCPTRIE_DEBUG + newTrie->t3=umutablecptrie_open(initialValue, errorValue, pErrorCode); +#endif newTrie->dataCapacity=UNEWTRIE2_INITIAL_DATA_LENGTH; newTrie->initialValue=initialValue; newTrie->errorValue=errorValue; @@ -246,6 +259,14 @@ cloneBuilder(const UNewTrie2 *other) { uprv_free(trie); return NULL; } +#ifdef UCPTRIE_DEBUG + if(other->t3==nullptr) { + trie->t3=nullptr; + } else { + UErrorCode errorCode=U_ZERO_ERROR; + trie->t3=umutablecptrie_clone(other->t3, &errorCode); + } +#endif trie->dataCapacity=other->dataCapacity; /* clone data */ @@ -343,6 +364,22 @@ copyEnumRange(const void *context, UChar32 start, UChar32 end, uint32_t value) { } #ifdef UTRIE2_DEBUG +static long countInitial(const UTrie2 *trie) { + uint32_t initialValue=trie->initialValue; + int32_t length=trie->dataLength; + long count=0; + if(trie->data16!=nullptr) { + for(int32_t i=0; idata16[i]==initialValue) { ++count; } + } + } else { + for(int32_t i=0; idata32[i]==initialValue) { ++count; } + } + } + return count; +} + static void utrie_printLengths(const UTrie *trie) { long indexLength=trie->indexLength; @@ -357,8 +394,8 @@ utrie2_printLengths(const UTrie2 *trie, const char *which) { long indexLength=trie->indexLength; long dataLength=(long)trie->dataLength; long totalLength=(long)sizeof(UTrie2Header)+indexLength*2+dataLength*(trie->data32!=NULL ? 4 : 2); - printf("**UTrie2Lengths(%s)** index:%6ld data:%6ld serialized:%6ld\n", - which, indexLength, dataLength, totalLength); + printf("**UTrie2Lengths(%s %s)** index:%6ld data:%6ld countInitial:%6ld serialized:%6ld\n", + which, trie->name, indexLength, dataLength, countInitial(trie), totalLength); } #endif @@ -622,6 +659,9 @@ set32(UNewTrie2 *trie, *pErrorCode=U_NO_WRITE_PERMISSION; return; } +#ifdef UCPTRIE_DEBUG + umutablecptrie_set(trie->t3, c, value, pErrorCode); +#endif block=getDataBlock(trie, c, forLSCP); if(block<0) { @@ -717,6 +757,9 @@ utrie2_setRange32(UTrie2 *trie, *pErrorCode=U_NO_WRITE_PERMISSION; return; } +#ifdef UCPTRIE_DEBUG + umutablecptrie_setRange(newTrie->t3, start, end, value, pErrorCode); +#endif if(!overwrite && value==newTrie->initialValue) { return; /* nothing to do */ } @@ -732,7 +775,7 @@ utrie2_setRange32(UTrie2 *trie, return; } - nextStart=(start+UTRIE2_DATA_BLOCK_LENGTH)&~UTRIE2_DATA_MASK; + nextStart=(start+UTRIE2_DATA_MASK)&~UTRIE2_DATA_MASK; if(nextStart<=limit) { fillBlock(newTrie->data+block, start&UTRIE2_DATA_MASK, UTRIE2_DATA_BLOCK_LENGTH, value, newTrie->initialValue, overwrite); @@ -983,6 +1026,10 @@ findHighStart(UNewTrie2 *trie, uint32_t highValue) { */ static void compactData(UNewTrie2 *trie) { +#ifdef UTRIE2_DEBUG + int32_t countSame=0, sumOverlaps=0; +#endif + int32_t start, newStart, movedStart; int32_t blockLength, overlap; int32_t i, mapIndex, blockCount; @@ -1023,6 +1070,9 @@ compactData(UNewTrie2 *trie) { if( (movedStart=findSameDataBlock(trie->data, newStart, start, blockLength)) >=0 ) { +#ifdef UTRIE2_DEBUG + ++countSame; +#endif /* found an identical block, set the other block's index value for the current block */ for(i=blockCount, mapIndex=start>>UTRIE2_SHIFT_2; i>0; --i) { trie->map[mapIndex++]=movedStart; @@ -1042,6 +1092,9 @@ compactData(UNewTrie2 *trie) { overlap>0 && !equal_uint32(trie->data+(newStart-overlap), trie->data+start, overlap); overlap-=UTRIE2_DATA_GRANULARITY) {} +#ifdef UTRIE2_DEBUG + sumOverlaps+=overlap; +#endif if(overlap>0 || newStart%lu\n", - (long)trie->dataLength, (long)newStart); + printf("compacting UTrie2: count of 32-bit data words %lu->%lu countSame=%ld sumOverlaps=%ld\n", + (long)trie->dataLength, (long)newStart, (long)countSame, (long)sumOverlaps); #endif trie->dataLength=newStart; @@ -1163,7 +1216,7 @@ compactIndex2(UNewTrie2 *trie) { #ifdef UTRIE2_DEBUG /* we saved some space */ - printf("compacting UTrie2: count of 16-bit index-2 words %lu->%lu\n", + printf("compacting UTrie2: count of 16-bit index words %lu->%lu\n", (long)trie->index2Length, (long)newStart); #endif @@ -1193,7 +1246,7 @@ compactTrie(UTrie2 *trie, UErrorCode *pErrorCode) { trie->highStart=newTrie->highStart=highStart; #ifdef UTRIE2_DEBUG - printf("UTrie2: highStart U+%04lx highValue 0x%lx initialValue 0x%lx\n", + printf("UTrie2: highStart U+%06lx highValue 0x%lx initialValue 0x%lx\n", (long)highStart, (long)highValue, (long)trie->initialValue); #endif @@ -1211,7 +1264,7 @@ compactTrie(UTrie2 *trie, UErrorCode *pErrorCode) { compactIndex2(newTrie); #ifdef UTRIE2_DEBUG } else { - printf("UTrie2: highStart U+%04lx count of 16-bit index-2 words %lu->%lu\n", + printf("UTrie2: highStart U+%04lx count of 16-bit index words %lu->%lu\n", (long)highStart, (long)trie->newTrie->index2Length, (long)UTRIE2_INDEX_1_OFFSET); #endif } @@ -1334,7 +1387,7 @@ utrie2_freeze(UTrie2 *trie, UTrie2ValueBits valueBits, UErrorCode *pErrorCode) { if(highStart<=0x10000) { trie->index2NullOffset=0xffff; } else { - trie->index2NullOffset=UTRIE2_INDEX_2_OFFSET+newTrie->index2NullOffset; + trie->index2NullOffset=static_cast(UTRIE2_INDEX_2_OFFSET+newTrie->index2NullOffset); } trie->dataNullOffset=(uint16_t)(dataMove+newTrie->dataNullOffset); trie->highValueIndex=dataMove+trie->dataLength-UTRIE2_DATA_GRANULARITY; @@ -1411,31 +1464,18 @@ utrie2_freeze(UTrie2 *trie, UTrie2ValueBits valueBits, UErrorCode *pErrorCode) { return; } +#ifdef UTRIE2_DEBUG + utrie2_printLengths(trie, ""); +#endif + +#ifdef UCPTRIE_DEBUG + umutablecptrie_setName(newTrie->t3, trie->name); + ucptrie_close( + umutablecptrie_buildImmutable( + newTrie->t3, UCPTRIE_TYPE_FAST, (UCPTrieValueWidth)valueBits, pErrorCode)); +#endif /* Delete the UNewTrie2. */ uprv_free(newTrie->data); uprv_free(newTrie); trie->newTrie=NULL; } - -/* - * This is here to avoid a dependency from utrie2.cpp on utrie.c. - * This file already depends on utrie.c. - * Otherwise, this should be in utrie2.cpp right after utrie2_swap(). - */ -U_CAPI int32_t U_EXPORT2 -utrie2_swapAnyVersion(const UDataSwapper *ds, - const void *inData, int32_t length, void *outData, - UErrorCode *pErrorCode) { - if(U_SUCCESS(*pErrorCode)) { - switch(utrie2_getVersion(inData, length, TRUE)) { - case 1: - return utrie_swap(ds, inData, length, outData, pErrorCode); - case 2: - return utrie2_swap(ds, inData, length, outData, pErrorCode); - default: - *pErrorCode=U_INVALID_FORMAT_ERROR; - return 0; - } - } - return 0; -} diff --git a/deps/icu-small/source/common/utrie2_impl.h b/deps/icu-small/source/common/utrie2_impl.h index b7dc9d3fb45fd4..2a14db3a6bdd1a 100644 --- a/deps/icu-small/source/common/utrie2_impl.h +++ b/deps/icu-small/source/common/utrie2_impl.h @@ -22,22 +22,20 @@ #ifndef __UTRIE2_IMPL_H__ #define __UTRIE2_IMPL_H__ +#ifdef UCPTRIE_DEBUG +#include "unicode/umutablecptrie.h" +#endif #include "utrie2.h" /* Public UTrie2 API implementation ----------------------------------------- */ /* - * These definitions are mostly needed by utrie2.c, + * These definitions are mostly needed by utrie2.cpp, * but also by utrie2_serialize() and utrie2_swap(). */ -/* - * UTrie and UTrie2 signature values, - * in platform endianness and opposite endianness. - */ -#define UTRIE_SIG 0x54726965 -#define UTRIE_OE_SIG 0x65697254 - +// UTrie2 signature values, in platform endianness and opposite endianness. +// The UTrie2 signature ASCII byte values spell "Tri2". #define UTRIE2_SIG 0x54726932 #define UTRIE2_OE_SIG 0x32697254 @@ -145,6 +143,9 @@ struct UNewTrie2 { int32_t index1[UNEWTRIE2_INDEX_1_LENGTH]; int32_t index2[UNEWTRIE2_MAX_INDEX_2_LENGTH]; uint32_t *data; +#ifdef UCPTRIE_DEBUG + UMutableCPTrie *t3; +#endif uint32_t initialValue, errorValue; int32_t index2Length, dataCapacity, dataLength; diff --git a/deps/icu-small/source/common/utrie_swap.cpp b/deps/icu-small/source/common/utrie_swap.cpp new file mode 100644 index 00000000000000..5abe7bd5d77e14 --- /dev/null +++ b/deps/icu-small/source/common/utrie_swap.cpp @@ -0,0 +1,344 @@ +// © 2018 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html + +// utrie_swap.cpp +// created: 2018aug08 Markus W. Scherer + +#include "unicode/utypes.h" +#include "cmemory.h" +#include "ucptrie_impl.h" +#include "udataswp.h" +#include "utrie.h" +#include "utrie2_impl.h" + +// These functions for swapping different generations of ICU code point tries are here +// so that their implementation files need not depend on swapper code, +// need not depend on each other, and so that other swapper code +// need not depend on other trie code. + +namespace { + +constexpr int32_t ASCII_LIMIT = 0x80; + +} // namespace + +U_CAPI int32_t U_EXPORT2 +utrie_swap(const UDataSwapper *ds, + const void *inData, int32_t length, void *outData, + UErrorCode *pErrorCode) { + const UTrieHeader *inTrie; + UTrieHeader trie; + int32_t size; + UBool dataIs32; + + if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) { + return 0; + } + if(ds==NULL || inData==NULL || (length>=0 && outData==NULL)) { + *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR; + return 0; + } + + /* setup and swapping */ + if(length>=0 && (uint32_t)lengthreadUInt32(inTrie->signature); + trie.options=ds->readUInt32(inTrie->options); + trie.indexLength=udata_readInt32(ds, inTrie->indexLength); + trie.dataLength=udata_readInt32(ds, inTrie->dataLength); + + if( trie.signature!=0x54726965 || + (trie.options&UTRIE_OPTIONS_SHIFT_MASK)!=UTRIE_SHIFT || + ((trie.options>>UTRIE_OPTIONS_INDEX_SHIFT)&UTRIE_OPTIONS_SHIFT_MASK)!=UTRIE_INDEX_SHIFT || + trie.indexLength=0) { + UTrieHeader *outTrie; + + if(lengthswapArray32(ds, inTrie, sizeof(UTrieHeader), outTrie, pErrorCode); + + /* swap the index and the data */ + if(dataIs32) { + ds->swapArray16(ds, inTrie+1, trie.indexLength*2, outTrie+1, pErrorCode); + ds->swapArray32(ds, (const uint16_t *)(inTrie+1)+trie.indexLength, trie.dataLength*4, + (uint16_t *)(outTrie+1)+trie.indexLength, pErrorCode); + } else { + ds->swapArray16(ds, inTrie+1, (trie.indexLength+trie.dataLength)*2, outTrie+1, pErrorCode); + } + } + + return size; +} + +U_CAPI int32_t U_EXPORT2 +utrie2_swap(const UDataSwapper *ds, + const void *inData, int32_t length, void *outData, + UErrorCode *pErrorCode) { + const UTrie2Header *inTrie; + UTrie2Header trie; + int32_t dataLength, size; + UTrie2ValueBits valueBits; + + if(U_FAILURE(*pErrorCode)) { + return 0; + } + if(ds==NULL || inData==NULL || (length>=0 && outData==NULL)) { + *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR; + return 0; + } + + /* setup and swapping */ + if(length>=0 && length<(int32_t)sizeof(UTrie2Header)) { + *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR; + return 0; + } + + inTrie=(const UTrie2Header *)inData; + trie.signature=ds->readUInt32(inTrie->signature); + trie.options=ds->readUInt16(inTrie->options); + trie.indexLength=ds->readUInt16(inTrie->indexLength); + trie.shiftedDataLength=ds->readUInt16(inTrie->shiftedDataLength); + + valueBits=(UTrie2ValueBits)(trie.options&UTRIE2_OPTIONS_VALUE_BITS_MASK); + dataLength=(int32_t)trie.shiftedDataLength<=0) { + UTrie2Header *outTrie; + + if(lengthswapArray32(ds, &inTrie->signature, 4, &outTrie->signature, pErrorCode); + ds->swapArray16(ds, &inTrie->options, 12, &outTrie->options, pErrorCode); + + /* swap the index and the data */ + switch(valueBits) { + case UTRIE2_16_VALUE_BITS: + ds->swapArray16(ds, inTrie+1, (trie.indexLength+dataLength)*2, outTrie+1, pErrorCode); + break; + case UTRIE2_32_VALUE_BITS: + ds->swapArray16(ds, inTrie+1, trie.indexLength*2, outTrie+1, pErrorCode); + ds->swapArray32(ds, (const uint16_t *)(inTrie+1)+trie.indexLength, dataLength*4, + (uint16_t *)(outTrie+1)+trie.indexLength, pErrorCode); + break; + default: + *pErrorCode=U_INVALID_FORMAT_ERROR; + return 0; + } + } + + return size; +} + +U_CAPI int32_t U_EXPORT2 +ucptrie_swap(const UDataSwapper *ds, + const void *inData, int32_t length, void *outData, + UErrorCode *pErrorCode) { + const UCPTrieHeader *inTrie; + UCPTrieHeader trie; + int32_t dataLength, size; + UCPTrieValueWidth valueWidth; + + if(U_FAILURE(*pErrorCode)) { + return 0; + } + if(ds==nullptr || inData==nullptr || (length>=0 && outData==nullptr)) { + *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR; + return 0; + } + + /* setup and swapping */ + if(length>=0 && length<(int32_t)sizeof(UCPTrieHeader)) { + *pErrorCode=U_INDEX_OUTOFBOUNDS_ERROR; + return 0; + } + + inTrie=(const UCPTrieHeader *)inData; + trie.signature=ds->readUInt32(inTrie->signature); + trie.options=ds->readUInt16(inTrie->options); + trie.indexLength=ds->readUInt16(inTrie->indexLength); + trie.dataLength = ds->readUInt16(inTrie->dataLength); + + UCPTrieType type = (UCPTrieType)((trie.options >> 6) & 3); + valueWidth = (UCPTrieValueWidth)(trie.options & UCPTRIE_OPTIONS_VALUE_BITS_MASK); + dataLength = ((int32_t)(trie.options & UCPTRIE_OPTIONS_DATA_LENGTH_MASK) << 4) | trie.dataLength; + + int32_t minIndexLength = type == UCPTRIE_TYPE_FAST ? + UCPTRIE_BMP_INDEX_LENGTH : UCPTRIE_SMALL_INDEX_LENGTH; + if( trie.signature!=UCPTRIE_SIG || + type > UCPTRIE_TYPE_SMALL || + (trie.options & UCPTRIE_OPTIONS_RESERVED_MASK) != 0 || + valueWidth > UCPTRIE_VALUE_BITS_8 || + trie.indexLength < minIndexLength || + dataLength < ASCII_LIMIT + ) { + *pErrorCode=U_INVALID_FORMAT_ERROR; /* not a UCPTrie */ + return 0; + } + + size=sizeof(UCPTrieHeader)+trie.indexLength*2; + switch(valueWidth) { + case UCPTRIE_VALUE_BITS_16: + size+=dataLength*2; + break; + case UCPTRIE_VALUE_BITS_32: + size+=dataLength*4; + break; + case UCPTRIE_VALUE_BITS_8: + size+=dataLength; + break; + default: + *pErrorCode=U_INVALID_FORMAT_ERROR; + return 0; + } + + if(length>=0) { + UCPTrieHeader *outTrie; + + if(lengthswapArray32(ds, &inTrie->signature, 4, &outTrie->signature, pErrorCode); + ds->swapArray16(ds, &inTrie->options, 12, &outTrie->options, pErrorCode); + + /* swap the index and the data */ + switch(valueWidth) { + case UCPTRIE_VALUE_BITS_16: + ds->swapArray16(ds, inTrie+1, (trie.indexLength+dataLength)*2, outTrie+1, pErrorCode); + break; + case UCPTRIE_VALUE_BITS_32: + ds->swapArray16(ds, inTrie+1, trie.indexLength*2, outTrie+1, pErrorCode); + ds->swapArray32(ds, (const uint16_t *)(inTrie+1)+trie.indexLength, dataLength*4, + (uint16_t *)(outTrie+1)+trie.indexLength, pErrorCode); + break; + case UCPTRIE_VALUE_BITS_8: + ds->swapArray16(ds, inTrie+1, trie.indexLength*2, outTrie+1, pErrorCode); + if(inTrie!=outTrie) { + uprv_memmove((outTrie+1)+trie.indexLength, (inTrie+1)+trie.indexLength, dataLength); + } + break; + default: + *pErrorCode=U_INVALID_FORMAT_ERROR; + return 0; + } + } + + return size; +} + +namespace { + +/** + * Gets the trie version from 32-bit-aligned memory containing the serialized form + * of a UTrie (version 1), a UTrie2 (version 2), or a UCPTrie (version 3). + * + * @param data a pointer to 32-bit-aligned memory containing the serialized form of a trie + * @param length the number of bytes available at data; + * can be more than necessary (see return value) + * @param anyEndianOk If FALSE, only platform-endian serialized forms are recognized. + * If TRUE, opposite-endian serialized forms are recognized as well. + * @return the trie version of the serialized form, or 0 if it is not + * recognized as a serialized trie + */ +int32_t +getVersion(const void *data, int32_t length, UBool anyEndianOk) { + uint32_t signature; + if(length<16 || data==nullptr || (U_POINTER_MASK_LSB(data, 3)!=0)) { + return 0; + } + signature=*(const uint32_t *)data; + if(signature==UCPTRIE_SIG) { + return 3; + } + if(anyEndianOk && signature==UCPTRIE_OE_SIG) { + return 3; + } + if(signature==UTRIE2_SIG) { + return 2; + } + if(anyEndianOk && signature==UTRIE2_OE_SIG) { + return 2; + } + if(signature==UTRIE_SIG) { + return 1; + } + if(anyEndianOk && signature==UTRIE_OE_SIG) { + return 1; + } + return 0; +} + +} // namespace + +U_CAPI int32_t U_EXPORT2 +utrie_swapAnyVersion(const UDataSwapper *ds, + const void *inData, int32_t length, void *outData, + UErrorCode *pErrorCode) { + if(U_FAILURE(*pErrorCode)) { return 0; } + switch(getVersion(inData, length, TRUE)) { + case 1: + return utrie_swap(ds, inData, length, outData, pErrorCode); + case 2: + return utrie2_swap(ds, inData, length, outData, pErrorCode); + case 3: + return ucptrie_swap(ds, inData, length, outData, pErrorCode); + default: + *pErrorCode=U_INVALID_FORMAT_ERROR; + return 0; + } +} diff --git a/deps/icu-small/source/common/uts46.cpp b/deps/icu-small/source/common/uts46.cpp index 5a23572eb64af2..b9e6cb023bb379 100644 --- a/deps/icu-small/source/common/uts46.cpp +++ b/deps/icu-small/source/common/uts46.cpp @@ -557,7 +557,10 @@ UTS46::processUnicode(const UnicodeString &src, destArray=dest.getBuffer(); destLength+=newLength-labelLength; labelLimit=labelStart+=newLength+1; - } else if(0xdf<=c && c<=0x200d && (c==0xdf || c==0x3c2 || c>=0x200c)) { + continue; + } else if(c<0xdf) { + // pass + } else if(c<=0x200d && (c==0xdf || c==0x3c2 || c>=0x200c)) { info.isTransDiff=TRUE; if(doMapDevChars) { destLength=mapDevChars(dest, labelStart, labelLimit, errorCode); @@ -565,15 +568,23 @@ UTS46::processUnicode(const UnicodeString &src, return dest; } destArray=dest.getBuffer(); - // Do not increment labelLimit in case c was removed. // All deviation characters have been mapped, no need to check for them again. doMapDevChars=FALSE; - } else { - ++labelLimit; + // Do not increment labelLimit in case c was removed. + continue; + } + } else if(U16_IS_SURROGATE(c)) { + if(U16_IS_SURROGATE_LEAD(c) ? + (labelLimit+1)==destLength || !U16_IS_TRAIL(destArray[labelLimit+1]) : + labelLimit==labelStart || !U16_IS_LEAD(destArray[labelLimit-1])) { + // Map an unpaired surrogate to U+FFFD before normalization so that when + // that removes characters we do not turn two unpaired ones into a pair. + info.labelErrors|=UIDNA_ERROR_DISALLOWED; + dest.setCharAt(labelLimit, 0xfffd); + destArray=dest.getBuffer(); } - } else { - ++labelLimit; } + ++labelLimit; } // Permit an empty label at the end (0 -#define MAX_LENGTH_ID 40 +U_NAMESPACE_BEGIN -/* The layout of the Tzi value in the registry */ -typedef struct -{ - int32_t bias; - int32_t standardBias; - int32_t daylightBias; - SYSTEMTIME standardDate; - SYSTEMTIME daylightDate; -} TZI; - -/** - * Various registry keys and key fragments. - */ -static const wchar_t CURRENT_ZONE_REGKEY[] = L"SYSTEM\\CurrentControlSet\\Control\\TimeZoneInformation\\"; -static const char STANDARD_TIME_REGKEY[] = " Standard Time"; -static const char TZI_REGKEY[] = "TZI"; -static const char STD_REGKEY[] = "Std"; +// The value of MAX_TIMEZONE_ID_LENGTH is 128, which is defined in DYNAMIC_TIME_ZONE_INFORMATION +#define MAX_TIMEZONE_ID_LENGTH 128 /** - * The time zone root keys (under HKLM) for Win7+ - */ -static const char TZ_REGKEY[] = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones\\"; - -static LONG openTZRegKey(HKEY *hkey, const char *winid) -{ - char subKeyName[110]; /* TODO: why 110?? */ - char *name; - LONG result; - - uprv_strcpy(subKeyName, TZ_REGKEY); - name = &subKeyName[strlen(subKeyName)]; - uprv_strcat(subKeyName, winid); - - result = RegOpenKeyExA(HKEY_LOCAL_MACHINE, - subKeyName, - 0, - KEY_QUERY_VALUE, - hkey); - return result; -} - -static LONG getTZI(const char *winid, TZI *tzi) -{ - DWORD cbData = sizeof(TZI); - LONG result; - HKEY hkey; - - result = openTZRegKey(&hkey, winid); - - if (result == ERROR_SUCCESS) - { - result = RegQueryValueExA(hkey, - TZI_REGKEY, - NULL, - NULL, - (LPBYTE)tzi, - &cbData); - RegCloseKey(hkey); - } - - return result; -} - -static LONG getSTDName(const char *winid, char *regStdName, int32_t length) -{ - DWORD cbData = length; - LONG result; - HKEY hkey; - - result = openTZRegKey(&hkey, winid); - - if (result == ERROR_SUCCESS) - { - result = RegQueryValueExA(hkey, - STD_REGKEY, - NULL, - NULL, - (LPBYTE)regStdName, - &cbData); - RegCloseKey(hkey); - } - - return result; -} - -static LONG getTZKeyName(char* tzKeyName, int32_t tzKeyNamelength) -{ - HKEY hkey; - LONG result = FALSE; - WCHAR timeZoneKeyNameData[128]; - DWORD timeZoneKeyNameLength = static_cast(sizeof(timeZoneKeyNameData)); - - if(ERROR_SUCCESS == RegOpenKeyExW( - HKEY_LOCAL_MACHINE, - CURRENT_ZONE_REGKEY, - 0, - KEY_QUERY_VALUE, - &hkey)) - { - if (ERROR_SUCCESS == RegQueryValueExW( - hkey, - L"TimeZoneKeyName", - NULL, - NULL, - (LPBYTE)timeZoneKeyNameData, - &timeZoneKeyNameLength)) - { - // Ensure null termination. - timeZoneKeyNameData[UPRV_LENGTHOF(timeZoneKeyNameData) - 1] = L'\0'; - - // Convert the UTF-16 string to UTF-8. - UErrorCode status = U_ZERO_ERROR; - u_strToUTF8(tzKeyName, tzKeyNamelength, NULL, reinterpret_cast(timeZoneKeyNameData), -1, &status); - if (U_ZERO_ERROR == status) - { - result = ERROR_SUCCESS; - } - } - RegCloseKey(hkey); - } - - return result; -} - -/* - This code attempts to detect the Windows time zone directly, - as set in the Windows Date and Time control panel. It attempts - to work on versions greater than Windows Vista and on localized - installs. It works by directly interrogating the registry and - comparing the data there with the data returned by the - GetTimeZoneInformation API, along with some other strategies. The - registry contains time zone data under this key: - - HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones\ - - Under this key are several subkeys, one for each time zone. For - example these subkeys are named "Pacific Standard Time" on Vista+. - There are some other wrinkles; see the code for - details. The subkey name is NOT LOCALIZED, allowing us to support - localized installs. - - Under the subkey are data values. We care about: - - Std Standard time display name, localized - TZI Binary block of data - - The TZI data is of particular interest. It contains the offset, two - more offsets for standard and daylight time, and the start and end - rules. This is the same data returned by the GetTimeZoneInformation - API. The API may modify the data on the way out, so we have to be - careful, but essentially we do a binary comparison against the TZI - blocks of various registry keys. When we find a match, we know what - time zone Windows is set to. Since the registry key is not - localized, we can then translate the key through a simple table - lookup into the corresponding ICU time zone. - - This strategy doesn't always work because there are zones which - share an offset and rules, so more than one TZI block will match. - For example, both Tokyo and Seoul are at GMT+9 with no DST rules; - their TZI blocks are identical. For these cases, we fall back to a - name lookup. We attempt to match the display name as stored in the - registry for the current zone to the display name stored in the - registry for various Windows zones. By comparing the registry data - directly we avoid conversion complications. - - Author: Alan Liu - Since: ICU 2.6 - Based on original code by Carl Brown +* Main Windows time zone detection function. +* Returns the Windows time zone converted to an ICU time zone as a heap-allocated buffer, or nullptr upon failure. +* Note: We use the Win32 API GetDynamicTimeZoneInformation to get the current time zone info. +* This API returns a non-localized time zone name, which we can then map to an ICU time zone name. */ - -/** - * Main Windows time zone detection function. Returns the Windows - * time zone, translated to an ICU time zone, or NULL upon failure. - */ U_CFUNC const char* U_EXPORT2 uprv_detectWindowsTimeZone() { UErrorCode status = U_ZERO_ERROR; - UResourceBundle* bundle = NULL; - char* icuid = NULL; - char apiStdName[MAX_LENGTH_ID]; - char regStdName[MAX_LENGTH_ID]; - char tmpid[MAX_LENGTH_ID]; + char* icuid = nullptr; + char dynamicTZKeyName[MAX_TIMEZONE_ID_LENGTH]; + char tmpid[MAX_TIMEZONE_ID_LENGTH]; int32_t len; - int id; + int id = GEOID_NOT_AVAILABLE; int errorCode; - wchar_t ISOcodeW[3]; /* 2 letter iso code in UTF-16*/ - char ISOcodeA[3]; /* 2 letter iso code in ansi */ + wchar_t ISOcodeW[3] = {}; /* 2 letter ISO code in UTF-16 */ + char ISOcode[3] = {}; /* 2 letter ISO code in UTF-8 */ - LONG result; - TZI tziKey; - TZI tziReg; - TIME_ZONE_INFORMATION apiTZI; + DYNAMIC_TIME_ZONE_INFORMATION dynamicTZI; + uprv_memset(&dynamicTZI, 0, sizeof(dynamicTZI)); + uprv_memset(dynamicTZKeyName, 0, sizeof(dynamicTZKeyName)); + uprv_memset(tmpid, 0, sizeof(tmpid)); - BOOL tryPreVistaFallback; - OSVERSIONINFO osVerInfo; + /* Obtain TIME_ZONE_INFORMATION from the API and get the non-localized time zone name. */ + if (TIME_ZONE_ID_INVALID == GetDynamicTimeZoneInformation(&dynamicTZI)) { + return nullptr; + } - /* Obtain TIME_ZONE_INFORMATION from the API, and then convert it - to TZI. We could also interrogate the registry directly; we do - this below if needed. */ - uprv_memset(&apiTZI, 0, sizeof(apiTZI)); - uprv_memset(&tziKey, 0, sizeof(tziKey)); - uprv_memset(&tziReg, 0, sizeof(tziReg)); - GetTimeZoneInformation(&apiTZI); - tziKey.bias = apiTZI.Bias; - uprv_memcpy((char *)&tziKey.standardDate, (char*)&apiTZI.StandardDate, - sizeof(apiTZI.StandardDate)); - uprv_memcpy((char *)&tziKey.daylightDate, (char*)&apiTZI.DaylightDate, - sizeof(apiTZI.DaylightDate)); + id = GetUserGeoID(GEOCLASS_NATION); + errorCode = GetGeoInfoW(id, GEO_ISO2, ISOcodeW, 3, 0); - /* Convert the wchar_t* standard name to char* */ - uprv_memset(apiStdName, 0, sizeof(apiStdName)); - wcstombs(apiStdName, apiTZI.StandardName, MAX_LENGTH_ID); + // convert from wchar_t* (UTF-16 on Windows) to char* (UTF-8). + u_strToUTF8(ISOcode, UPRV_LENGTHOF(ISOcode), nullptr, + reinterpret_cast(ISOcodeW), UPRV_LENGTHOF(ISOcodeW), &status); - tmpid[0] = 0; + LocalUResourceBundlePointer bundle(ures_openDirect(nullptr, "windowsZones", &status)); + ures_getByKey(bundle.getAlias(), "mapTimezones", bundle.getAlias(), &status); - id = GetUserGeoID(GEOCLASS_NATION); - errorCode = GetGeoInfoW(id, GEO_ISO2, ISOcodeW, 3, 0); - u_strToUTF8(ISOcodeA, 3, NULL, (const UChar *)ISOcodeW, 3, &status); + // convert from wchar_t* (UTF-16 on Windows) to char* (UTF-8). + u_strToUTF8(dynamicTZKeyName, UPRV_LENGTHOF(dynamicTZKeyName), nullptr, + reinterpret_cast(dynamicTZI.TimeZoneKeyName), UPRV_LENGTHOF(dynamicTZI.TimeZoneKeyName), &status); + + if (U_FAILURE(status)) { + return nullptr; + } - bundle = ures_openDirect(NULL, "windowsZones", &status); - ures_getByKey(bundle, "mapTimezones", bundle, &status); + if (dynamicTZI.TimeZoneKeyName[0] != 0) { + UResourceBundle winTZ; + ures_initStackObject(&winTZ); + ures_getByKey(bundle.getAlias(), dynamicTZKeyName, &winTZ, &status); - /* - Windows Vista+ provides us with a "TimeZoneKeyName" that is not localized - and can be used to directly map a name in our bundle. Try to use that first - if we're on Vista or higher - */ - uprv_memset(&osVerInfo, 0, sizeof(osVerInfo)); - osVerInfo.dwOSVersionInfoSize = sizeof(osVerInfo); - tryPreVistaFallback = TRUE; - result = getTZKeyName(regStdName, sizeof(regStdName)); - if(ERROR_SUCCESS == result) - { - UResourceBundle* winTZ = ures_getByKey(bundle, regStdName, NULL, &status); - if(U_SUCCESS(status)) - { - const UChar* icuTZ = NULL; - if (errorCode != 0) - { - icuTZ = ures_getStringByKey(winTZ, ISOcodeA, &len, &status); + if (U_SUCCESS(status)) { + const UChar* icuTZ = nullptr; + if (errorCode != 0) { + icuTZ = ures_getStringByKey(&winTZ, ISOcode, &len, &status); } - if (errorCode==0 || icuTZ==NULL) - { + if (errorCode == 0 || icuTZ == nullptr) { /* fallback to default "001" and reset status */ status = U_ZERO_ERROR; - icuTZ = ures_getStringByKey(winTZ, "001", &len, &status); + icuTZ = ures_getStringByKey(&winTZ, "001", &len, &status); } - if(U_SUCCESS(status)) - { - int index=0; - while (! (*icuTZ == '\0' || *icuTZ ==' ')) - { - tmpid[index++]=(char)(*icuTZ++); /* safe to assume 'char' is ASCII compatible on windows */ - } - tmpid[index]='\0'; - tryPreVistaFallback = FALSE; - } - } - ures_close(winTZ); - } + if (U_SUCCESS(status)) { + int index = 0; - if(tryPreVistaFallback) - { - /* Note: We get the winid not from static tables but from resource bundle. */ - while (U_SUCCESS(status) && ures_hasNext(bundle)) - { - UBool idFound = FALSE; - const char* winid; - UResourceBundle* winTZ = ures_getNextResource(bundle, NULL, &status); - if (U_FAILURE(status)) - { - break; - } - winid = ures_getKey(winTZ); - result = getTZI(winid, &tziReg); - - if (result == ERROR_SUCCESS) - { - /* Windows alters the DaylightBias in some situations. - Using the bias and the rules suffices, so overwrite - these unreliable fields. */ - tziKey.standardBias = tziReg.standardBias; - tziKey.daylightBias = tziReg.daylightBias; - - if (uprv_memcmp((char *)&tziKey, (char*)&tziReg, sizeof(tziKey)) == 0) - { - const UChar* icuTZ = NULL; - if (errorCode != 0) - { - icuTZ = ures_getStringByKey(winTZ, ISOcodeA, &len, &status); - } - if (errorCode==0 || icuTZ==NULL) - { - /* fallback to default "001" and reset status */ - status = U_ZERO_ERROR; - icuTZ = ures_getStringByKey(winTZ, "001", &len, &status); - } - - if (U_SUCCESS(status)) - { - /* Get the standard name from the registry key to compare with - the one from Windows API call. */ - uprv_memset(regStdName, 0, sizeof(regStdName)); - result = getSTDName(winid, regStdName, sizeof(regStdName)); - if (result == ERROR_SUCCESS) - { - if (uprv_strcmp(apiStdName, regStdName) == 0) - { - idFound = TRUE; - } - } - - /* tmpid buffer holds the ICU timezone ID corresponding to the timezone ID from Windows. - * If none is found, tmpid buffer will contain a fallback ID (i.e. the time zone ID matching - * the current time zone information) - */ - if (idFound || tmpid[0] == 0) - { - /* if icuTZ has more than one city, take only the first (i.e. terminate icuTZ at first space) */ - int index=0; - while (! (*icuTZ == '\0' || *icuTZ ==' ')) - { - tmpid[index++]=(char)(*icuTZ++); /* safe to assume 'char' is ASCII compatible on windows */ - } - tmpid[index]='\0'; - } - } + while (!(*icuTZ == '\0' || *icuTZ == ' ')) { + // time zone IDs only contain ASCII invariant characters. + tmpid[index++] = (char)(*icuTZ++); } - } - ures_close(winTZ); - if (idFound) - { - break; + tmpid[index] = '\0'; } } + ures_close(&winTZ); } - /* - * Copy the timezone ID to icuid to be returned. - */ - if (tmpid[0] != 0) - { - len = uprv_strlen(tmpid); - icuid = (char*)uprv_calloc(len + 1, sizeof(char)); - if (icuid != NULL) - { - uprv_strcpy(icuid, tmpid); - } + // Copy the timezone ID to icuid to be returned. + if (tmpid[0] != 0) { + icuid = uprv_strdup(tmpid); } - ures_close(bundle); - return icuid; } -#endif /* U_PLATFORM_USES_ONLY_WIN32_API && (U_PLATFORM_HAS_WINUWP_API == 0) */ +U_NAMESPACE_END +#endif /* U_PLATFORM_USES_ONLY_WIN32_API */ diff --git a/deps/icu-small/source/common/wintz.h b/deps/icu-small/source/common/wintz.h index 9e8cbbcfaba36f..0625bb204b197c 100644 --- a/deps/icu-small/source/common/wintz.h +++ b/deps/icu-small/source/common/wintz.h @@ -16,9 +16,7 @@ #include "unicode/utypes.h" -// This file contains only desktop windows behavior -// Windows UWP calls Windows::Globalization directly, so this isn't needed there. -#if U_PLATFORM_USES_ONLY_WIN32_API && (U_PLATFORM_HAS_WINUWP_API == 0) +#if U_PLATFORM_USES_ONLY_WIN32_API /** * \file @@ -33,6 +31,6 @@ U_CDECL_END U_CFUNC const char* U_EXPORT2 uprv_detectWindowsTimeZone(); -#endif /* U_PLATFORM_USES_ONLY_WIN32_API && (U_PLATFORM_HAS_WINUWP_API == 0) */ +#endif /* U_PLATFORM_USES_ONLY_WIN32_API */ #endif /* __WINTZ */ diff --git a/deps/icu-small/source/data/in/icudt62l.dat b/deps/icu-small/source/data/in/icudt63l.dat similarity index 65% rename from deps/icu-small/source/data/in/icudt62l.dat rename to deps/icu-small/source/data/in/icudt63l.dat index a6ac7ebb374980af350e400719adeeefdb78fa70..60f57612c0d0e32564ed40c84177cdddcea92062 100644 GIT binary patch delta 281512 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�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�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 U;njP2=wu71VIMj<;pZ3r4?8xXE&u=k delta 273341 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
Cy%~l9^bYWn$49{8phxSf;fv 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
UQ8h+0J_Ji^MWa1Bp*wn` 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∋wnO0zF}32<>bZF%JcRdoxg`>&V2)M(yu~!W#6FKu&anNwZ&eAFWI?}%58L#os;pVSWJz`6 zuv~+&bd%)Mq8)Zo9;&2G!HrUN+)=d`s|!)Mui~Ku`JJXl*tsd=CVNEr-x`Bx-7U6| zVs5fF%kNBqbG!=>-83w6PNs(qLg)X4DJHsp;QqoMD6iw+ZO<~l) zCbf63vq{tOTwgh9CLNe3g_12)8bjMIVFq0Yl|G=Ep;Bu)R$e+yAB0J#-S1V9<|y2w zDoWu>DlIQnp>36<-LyLrO%92a+SB4-%*32dl8Np`O5^E3lvE~9=ly|FIVy{m5~#Ti z3nR6%be!(-Q+jfg6i&SdOMxU+fhHPMM`&dfLc^-S02x&zlSr$gB|KNz3yE_iWQSCi zobH8^v`(a~>QYC~uz#p7O;xzdYDkd*?(|wxKDN*6u=L<)C@1D3MsqVs3Zt7-jUg0Y z8xl;f24`w*X&)U$Nh;+BDuJo~jP7jyD-OhT_sQ`H(bMHHY z*EDD-1-J*NNTS;PdP}LVf^OzZB1x?!1C=#~m_N6I_7hu6n6MKgFuijkn8|HvE1eO! z7@|A;IY|njlljov;xy>$RGO4W$FiWh!7o9ltvgHCXkfY&?|v^`S{O(>Zem4#&=*hP zor^^2yd<O?sibzFSu8EYid`W!q7BQXZzyLuLR>;>`-T+j4ti7C zf=zY~>g1Im(LW+uJW;CRzEUWO_(zvgDUN>LgffL=C4+m)N+}K&&cb9xyLh|gC2lqp zr#sW6M7r4x^D1(clusBQ{z+mi>IJTbJ-=Iwa+Z~tuyT#EZm1DETdG6HS4*4R$4aE# zm>pFiMBYYB9`)-|D6Ei;MbF=B9f4~pekIQD1|Gj5Ioud$cMZ+RH7})tEt1N$Ym$K7 zPI$?S1YZ<(O==F`^JrHWSaB%eZ$k2W58vgp=fSSpxKrTIe?|*agSor7DtD)8xZCbI z?*4?I_>LAfW^*_FdG1z|AN6W1hh4Gq6JMQjct#YS0g4s|%VC%7?wrI^%FAVjw&UR` z^|@O;k-N?1C&$jpDdn2;6wmWxVk8fbmdn(|FaAag!|{|rv~a@AU2_A4FhN;g7J9c) z?qHzY&^$90z9pS@`aVVPg|7hSpQPvF6ZLxKgp8)Z_hIItNwi|CRJT%ZldQh|_>_^e zS5{wd(|mlYDSx1OXREYNm=qD-&?4&{JO|24r{LK%Pv{5pkLCc>Vn7A!T{3*(~G78(*n~n?@(r0zw_39 z#rmzkd>_*jL0sF!N8Tc_qS@Ph4@J1rBT|SuT>WX}2Y5wI7h}9ikGC8}$z0QPZ_SNXr(E(2xvTx&)Y_I$yrH+P??XJ7$4dDo zZV}$_9(gV__l^M%Qpl-oyz#l#j&h?HWKkygRXWVH%X&;sJL_#;t1x>_C@S>c&|^V^ zsXam2$J^Qo^Ldvn-BsDm^%`QowZGg6e~N5^a*!Mz=B+Zqa#>CtWAUjr+w{b6QI>bT z-FLQJ^tQIs{3b%4NxVxI(c}Iomvng^()3vIGv!a->VLCNkh@KgNB>yv@~-T5vvQ%< z$PE>HyO?5`3{o7uJokIIgX- zS68-64Y`P0PO*DMI&7&Xr|$7K$(N>2^)H*AELpp)27aHMuZ7BHCf6t@yUk>`vA4CI z3jWkMFLhp7#zo`fuWSB7F4RhP>w61)ZoVWdyplKmmG!7sgiF@r-q82f&wL?EH@S8% z*?rDi=NC&qZ|HkvJ8!7W(pfHZUakrI&sN+(kWY|VrpmG&e)7gAn_S*8{oVRd*2)06 zs?wW!->UJ3hFahDuZ1Nh9^myZlRIuLyJ@ofhPPBtagle5RkLM!%h$AJc|)7c zFZhSnOcV-YV?`kYy=3^t`yLW|BEIXXw3k#u!F?Qf2`_g#D1oZ(P6uOt?Dl^EIMK7% diff --git a/deps/icu-small/source/i18n/alphaindex.cpp b/deps/icu-small/source/i18n/alphaindex.cpp index f4a082c5b20e5e..99f70114cbdb15 100644 --- a/deps/icu-small/source/i18n/alphaindex.cpp +++ b/deps/icu-small/source/i18n/alphaindex.cpp @@ -511,8 +511,8 @@ BucketList *AlphabeticIndex::createBucketList(UErrorCode &errorCode) const { ces, errorCode) && current.charAt(current.length() - 1) != 0xFFFF /* !current.endsWith("\uffff") */) { // "AE-ligature" or "Sch" etc. - for (int32_t i = bucketList->size() - 2;; --i) { - Bucket *singleBucket = getBucket(*bucketList, i); + for (int32_t j = bucketList->size() - 2;; --j) { + Bucket *singleBucket = getBucket(*bucketList, j); if (singleBucket->labelType_ != U_ALPHAINDEX_NORMAL) { // There is no single-character bucket since the last // underflow or inflow label. @@ -608,8 +608,8 @@ BucketList *AlphabeticIndex::createBucketList(UErrorCode &errorCode) const { } // Do not call publicBucketList->setDeleter(): // This vector shares its objects with the bucketList. - for (int32_t i = 0; i < bucketList->size(); ++i) { - bucket = getBucket(*bucketList, i); + for (int32_t j = 0; j < bucketList->size(); ++j) { + bucket = getBucket(*bucketList, j); if (bucket->displayBucket_ == NULL) { publicBucketList->addElement(bucket, errorCode); } diff --git a/deps/icu-small/source/i18n/anytrans.cpp b/deps/icu-small/source/i18n/anytrans.cpp index d06469e2ae2746..6e382b824b95b7 100644 --- a/deps/icu-small/source/i18n/anytrans.cpp +++ b/deps/icu-small/source/i18n/anytrans.cpp @@ -391,12 +391,12 @@ void AnyTransliterator::registerIDs() { UnicodeString id; TransliteratorIDParser::STVtoID(UnicodeString(TRUE, ANY, 3), target, variant, id); ec = U_ZERO_ERROR; - AnyTransliterator* t = new AnyTransliterator(id, target, variant, + AnyTransliterator* tl = new AnyTransliterator(id, target, variant, targetScript, ec); if (U_FAILURE(ec)) { - delete t; + delete tl; } else { - Transliterator::_registerInstance(t); + Transliterator::_registerInstance(tl); Transliterator::_registerSpecialInverse(target, UnicodeString(TRUE, NULL_ID, 4), FALSE); } } diff --git a/deps/icu-small/source/i18n/calendar.cpp b/deps/icu-small/source/i18n/calendar.cpp index 61757cb250f77d..24c2fb964e91a1 100644 --- a/deps/icu-small/source/i18n/calendar.cpp +++ b/deps/icu-small/source/i18n/calendar.cpp @@ -3797,7 +3797,7 @@ Calendar::setWeekData(const Locale& desiredLocale, const char *type, UErrorCode& Locale max = Locale::createFromName(maxLocaleID); useLocale = Locale(max.getLanguage(),max.getCountry()); } else { - useLocale = Locale(desiredLocale); + useLocale = desiredLocale; } /* The code here is somewhat of a hack, since week data and weekend data aren't really tied to diff --git a/deps/icu-small/source/i18n/coll.cpp b/deps/icu-small/source/i18n/coll.cpp index b7348a1d16f1e1..2a614fac5dcfbc 100644 --- a/deps/icu-small/source/i18n/coll.cpp +++ b/deps/icu-small/source/i18n/coll.cpp @@ -448,6 +448,13 @@ Collator* U_EXPORT2 Collator::createInstance(const Locale& desiredLocale, #endif { coll = makeInstance(desiredLocale, status); + // Either returns NULL with U_FAILURE(status), or non-NULL with U_SUCCESS(status) + } + // The use of *coll in setAttributesFromKeywords can cause the NULL check to be + // optimized out of the delete even though setAttributesFromKeywords returns + // immediately if U_FAILURE(status), so we add a check here. + if (U_FAILURE(status)) { + return NULL; } setAttributesFromKeywords(desiredLocale, *coll, status); if (U_FAILURE(status)) { @@ -986,8 +993,8 @@ Collator::internalCompareUTF8(const char *left, int32_t leftLength, return UCOL_EQUAL; } return compareUTF8( - StringPiece(left, (leftLength < 0) ? uprv_strlen(left) : leftLength), - StringPiece(right, (rightLength < 0) ? uprv_strlen(right) : rightLength), + StringPiece(left, (leftLength < 0) ? static_cast(uprv_strlen(left)) : leftLength), + StringPiece(right, (rightLength < 0) ? static_cast(uprv_strlen(right)) : rightLength), errorCode); } diff --git a/deps/icu-small/source/i18n/collationkeys.cpp b/deps/icu-small/source/i18n/collationkeys.cpp index 4b9e6b59075e1d..b5c322fb44679b 100644 --- a/deps/icu-small/source/i18n/collationkeys.cpp +++ b/deps/icu-small/source/i18n/collationkeys.cpp @@ -403,13 +403,13 @@ CollationKeys::writeSortKeyUpToQuaternary(CollationIterator &iter, uint8_t *secs = secondaries.data(); int32_t last = secondaries.length() - 1; if(secSegmentStart < last) { - uint8_t *p = secs + secSegmentStart; - uint8_t *q = secs + last; + uint8_t *q = secs + secSegmentStart; + uint8_t *r = secs + last; do { - uint8_t b = *p; - *p++ = *q; - *q-- = b; - } while(p < q); + uint8_t b = *q; + *q++ = *r; + *r-- = b; + } while(q < r); } secondaries.appendByte(p == Collation::NO_CE_PRIMARY ? Collation::LEVEL_SEPARATOR_BYTE : Collation::MERGE_SEPARATOR_BYTE); diff --git a/deps/icu-small/source/i18n/csrmbcs.cpp b/deps/icu-small/source/i18n/csrmbcs.cpp index 0c2df594d56a75..46d626bb3f4ffe 100644 --- a/deps/icu-small/source/i18n/csrmbcs.cpp +++ b/deps/icu-small/source/i18n/csrmbcs.cpp @@ -166,7 +166,7 @@ int32_t CharsetRecog_mbcs::match_mbcs(InputText *det, const uint16_t commonChars doubleByteCharCount++; if (commonChars != 0) { - if (binarySearch(commonChars, commonCharsLen, iter.charValue) >= 0){ + if (binarySearch(commonChars, commonCharsLen, static_cast(iter.charValue)) >= 0){ commonCharCount += 1; } } diff --git a/deps/icu-small/source/i18n/currpinf.cpp b/deps/icu-small/source/i18n/currpinf.cpp index 6b1efd5f4da721..f5d27e28d8ebfa 100644 --- a/deps/icu-small/source/i18n/currpinf.cpp +++ b/deps/icu-small/source/i18n/currpinf.cpp @@ -17,7 +17,6 @@ #include #endif - #include "unicode/locid.h" #include "unicode/plurrule.h" #include "unicode/strenum.h" @@ -30,7 +29,6 @@ U_NAMESPACE_BEGIN - static const UChar gNumberPatternSeparator = 0x3B; // ; U_CDECL_BEGIN @@ -65,66 +63,86 @@ static const char gDecimalFormatTag[]="decimalFormat"; static const char gCurrUnitPtnTag[]="CurrencyUnitPatterns"; CurrencyPluralInfo::CurrencyPluralInfo(UErrorCode& status) -: fPluralCountToCurrencyUnitPattern(NULL), - fPluralRules(NULL), - fLocale(NULL) { +: fPluralCountToCurrencyUnitPattern(nullptr), + fPluralRules(nullptr), + fLocale(nullptr), + fInternalStatus(U_ZERO_ERROR) { initialize(Locale::getDefault(), status); } CurrencyPluralInfo::CurrencyPluralInfo(const Locale& locale, UErrorCode& status) -: fPluralCountToCurrencyUnitPattern(NULL), - fPluralRules(NULL), - fLocale(NULL) { +: fPluralCountToCurrencyUnitPattern(nullptr), + fPluralRules(nullptr), + fLocale(nullptr), + fInternalStatus(U_ZERO_ERROR) { initialize(locale, status); } CurrencyPluralInfo::CurrencyPluralInfo(const CurrencyPluralInfo& info) : UObject(info), - fPluralCountToCurrencyUnitPattern(NULL), - fPluralRules(NULL), - fLocale(NULL) { + fPluralCountToCurrencyUnitPattern(nullptr), + fPluralRules(nullptr), + fLocale(nullptr), + fInternalStatus(U_ZERO_ERROR) { *this = info; } - CurrencyPluralInfo& CurrencyPluralInfo::operator=(const CurrencyPluralInfo& info) { if (this == &info) { return *this; } + fInternalStatus = info.fInternalStatus; + if (U_FAILURE(fInternalStatus)) { + // bail out early if the object we were copying from was already 'invalid'. + return *this; + } + deleteHash(fPluralCountToCurrencyUnitPattern); - UErrorCode status = U_ZERO_ERROR; - fPluralCountToCurrencyUnitPattern = initHash(status); + fPluralCountToCurrencyUnitPattern = initHash(fInternalStatus); copyHash(info.fPluralCountToCurrencyUnitPattern, - fPluralCountToCurrencyUnitPattern, status); - if ( U_FAILURE(status) ) { + fPluralCountToCurrencyUnitPattern, fInternalStatus); + if ( U_FAILURE(fInternalStatus) ) { return *this; } delete fPluralRules; + fPluralRules = nullptr; delete fLocale; - if (info.fPluralRules) { + fLocale = nullptr; + + if (info.fPluralRules != nullptr) { fPluralRules = info.fPluralRules->clone(); - } else { - fPluralRules = NULL; + if (fPluralRules == nullptr) { + fInternalStatus = U_MEMORY_ALLOCATION_ERROR; + return *this; + } } - if (info.fLocale) { + if (info.fLocale != nullptr) { fLocale = info.fLocale->clone(); - } else { - fLocale = NULL; + if (fLocale == nullptr) { + // Note: If clone had an error parameter, then we could check/set that instead. + fInternalStatus = U_MEMORY_ALLOCATION_ERROR; + return *this; + } + // If the other locale wasn't bogus, but our clone'd locale is bogus, then OOM happened + // during the call to clone(). + if (!info.fLocale->isBogus() && fLocale->isBogus()) { + fInternalStatus = U_MEMORY_ALLOCATION_ERROR; + return *this; + } } return *this; } - CurrencyPluralInfo::~CurrencyPluralInfo() { deleteHash(fPluralCountToCurrencyUnitPattern); - fPluralCountToCurrencyUnitPattern = NULL; + fPluralCountToCurrencyUnitPattern = nullptr; delete fPluralRules; delete fLocale; - fPluralRules = NULL; - fLocale = NULL; + fPluralRules = nullptr; + fLocale = nullptr; } UBool @@ -148,7 +166,14 @@ CurrencyPluralInfo::operator==(const CurrencyPluralInfo& info) const { CurrencyPluralInfo* CurrencyPluralInfo::clone() const { - return new CurrencyPluralInfo(*this); + CurrencyPluralInfo* newObj = new CurrencyPluralInfo(*this); + // Since clone doesn't have a 'status' parameter, the best we can do is return nullptr + // if the new object was not full constructed properly (an error occurred). + if (newObj != nullptr && U_FAILURE(newObj->fInternalStatus)) { + delete newObj; + newObj = nullptr; + } + return newObj; } const PluralRules* @@ -161,15 +186,15 @@ CurrencyPluralInfo::getCurrencyPluralPattern(const UnicodeString& pluralCount, UnicodeString& result) const { const UnicodeString* currencyPluralPattern = (UnicodeString*)fPluralCountToCurrencyUnitPattern->get(pluralCount); - if (currencyPluralPattern == NULL) { + if (currencyPluralPattern == nullptr) { // fall back to "other" if (pluralCount.compare(gPluralCountOther, 5)) { currencyPluralPattern = (UnicodeString*)fPluralCountToCurrencyUnitPattern->get(UnicodeString(TRUE, gPluralCountOther, 5)); } - if (currencyPluralPattern == NULL) { + if (currencyPluralPattern == nullptr) { // no currencyUnitPatterns defined, - // fallback to predefined defult. + // fallback to predefined default. // This should never happen when ICU resource files are // available, since currencyUnitPattern of "other" is always // defined in root. @@ -190,14 +215,11 @@ void CurrencyPluralInfo::setPluralRules(const UnicodeString& ruleDescription, UErrorCode& status) { if (U_SUCCESS(status)) { - if (fPluralRules) { - delete fPluralRules; - } + delete fPluralRules; fPluralRules = PluralRules::createRules(ruleDescription, status); } } - void CurrencyPluralInfo::setCurrencyPluralPattern(const UnicodeString& pluralCount, const UnicodeString& pattern, @@ -206,63 +228,77 @@ CurrencyPluralInfo::setCurrencyPluralPattern(const UnicodeString& pluralCount, UnicodeString* oldValue = static_cast( fPluralCountToCurrencyUnitPattern->get(pluralCount)); delete oldValue; - fPluralCountToCurrencyUnitPattern->put(pluralCount, new UnicodeString(pattern), status); + LocalPointer p(new UnicodeString(pattern), status); + if (U_SUCCESS(status)) { + // the p object allocated above will be owned by fPluralCountToCurrencyUnitPattern + // after the call to put(), even if the method returns failure. + fPluralCountToCurrencyUnitPattern->put(pluralCount, p.orphan(), status); + } } } - void CurrencyPluralInfo::setLocale(const Locale& loc, UErrorCode& status) { initialize(loc, status); } - void CurrencyPluralInfo::initialize(const Locale& loc, UErrorCode& status) { if (U_FAILURE(status)) { return; } delete fLocale; + fLocale = nullptr; + delete fPluralRules; + fPluralRules = nullptr; + fLocale = loc.clone(); - if (fPluralRules) { - delete fPluralRules; + if (fLocale == nullptr) { + status = U_MEMORY_ALLOCATION_ERROR; + return; + } + // If the locale passed in wasn't bogus, but our clone'd locale is bogus, then OOM happened + // during the call to loc.clone(). + if (!loc.isBogus() && fLocale->isBogus()) { + status = U_MEMORY_ALLOCATION_ERROR; + return; } fPluralRules = PluralRules::forLocale(loc, status); setupCurrencyPluralPattern(loc, status); } - void CurrencyPluralInfo::setupCurrencyPluralPattern(const Locale& loc, UErrorCode& status) { if (U_FAILURE(status)) { return; } - if (fPluralCountToCurrencyUnitPattern) { - deleteHash(fPluralCountToCurrencyUnitPattern); - } + deleteHash(fPluralCountToCurrencyUnitPattern); fPluralCountToCurrencyUnitPattern = initHash(status); if (U_FAILURE(status)) { return; } - NumberingSystem *ns = NumberingSystem::createInstance(loc,status); + LocalPointer ns(NumberingSystem::createInstance(loc, status), status); + if (U_FAILURE(status)) { + return; + } UErrorCode ec = U_ZERO_ERROR; - UResourceBundle *rb = ures_open(NULL, loc.getName(), &ec); - UResourceBundle *numElements = ures_getByKeyWithFallback(rb, gNumberElementsTag, NULL, &ec); - rb = ures_getByKeyWithFallback(numElements, ns->getName(), rb, &ec); - rb = ures_getByKeyWithFallback(rb, gPatternsTag, rb, &ec); + LocalUResourceBundlePointer rb(ures_open(nullptr, loc.getName(), &ec)); + LocalUResourceBundlePointer numElements(ures_getByKeyWithFallback(rb.getAlias(), gNumberElementsTag, nullptr, &ec)); + ures_getByKeyWithFallback(numElements.getAlias(), ns->getName(), rb.getAlias(), &ec); + ures_getByKeyWithFallback(rb.getAlias(), gPatternsTag, rb.getAlias(), &ec); int32_t ptnLen; - const UChar* numberStylePattern = ures_getStringByKeyWithFallback(rb, gDecimalFormatTag, &ptnLen, &ec); + const UChar* numberStylePattern = ures_getStringByKeyWithFallback(rb.getAlias(), gDecimalFormatTag, &ptnLen, &ec); // Fall back to "latn" if num sys specific pattern isn't there. - if ( ec == U_MISSING_RESOURCE_ERROR && uprv_strcmp(ns->getName(),gLatnTag)) { + if ( ec == U_MISSING_RESOURCE_ERROR && (uprv_strcmp(ns->getName(), gLatnTag) != 0)) { ec = U_ZERO_ERROR; - rb = ures_getByKeyWithFallback(numElements, gLatnTag, rb, &ec); - rb = ures_getByKeyWithFallback(rb, gPatternsTag, rb, &ec); - numberStylePattern = ures_getStringByKeyWithFallback(rb, gDecimalFormatTag, &ptnLen, &ec); + ures_getByKeyWithFallback(numElements.getAlias(), gLatnTag, rb.getAlias(), &ec); + ures_getByKeyWithFallback(rb.getAlias(), gPatternsTag, rb.getAlias(), &ec); + numberStylePattern = ures_getStringByKeyWithFallback(rb.getAlias(), gDecimalFormatTag, &ptnLen, &ec); } int32_t numberStylePatternLen = ptnLen; - const UChar* negNumberStylePattern = NULL; + const UChar* negNumberStylePattern = nullptr; int32_t negNumberStylePatternLen = 0; // TODO: Java // parse to check whether there is ";" separator in the numberStylePattern @@ -279,127 +315,127 @@ CurrencyPluralInfo::setupCurrencyPluralPattern(const Locale& loc, UErrorCode& st } } - ures_close(numElements); - ures_close(rb); - delete ns; - if (U_FAILURE(ec)) { + // If OOM occurred during the above code, then we want to report that back to the caller. + if (ec == U_MEMORY_ALLOCATION_ERROR) { + status = ec; + } return; } - UResourceBundle *currRb = ures_open(U_ICUDATA_CURR, loc.getName(), &ec); - UResourceBundle *currencyRes = ures_getByKeyWithFallback(currRb, gCurrUnitPtnTag, NULL, &ec); + LocalUResourceBundlePointer currRb(ures_open(U_ICUDATA_CURR, loc.getName(), &ec)); + LocalUResourceBundlePointer currencyRes(ures_getByKeyWithFallback(currRb.getAlias(), gCurrUnitPtnTag, nullptr, &ec)); #ifdef CURRENCY_PLURAL_INFO_DEBUG std::cout << "in set up\n"; #endif - StringEnumeration* keywords = fPluralRules->getKeywords(ec); + LocalPointer keywords(fPluralRules->getKeywords(ec), ec); if (U_SUCCESS(ec)) { const char* pluralCount; - while ((pluralCount = keywords->next(NULL, ec)) != NULL) { - if ( U_SUCCESS(ec) ) { - int32_t ptnLen; - UErrorCode err = U_ZERO_ERROR; - const UChar* patternChars = ures_getStringByKeyWithFallback( - currencyRes, pluralCount, &ptnLen, &err); - if (U_SUCCESS(err) && ptnLen > 0) { - UnicodeString* pattern = new UnicodeString(patternChars, ptnLen); + while (((pluralCount = keywords->next(nullptr, ec)) != nullptr) && U_SUCCESS(ec)) { + int32_t ptnLength; + UErrorCode err = U_ZERO_ERROR; + const UChar* patternChars = ures_getStringByKeyWithFallback(currencyRes.getAlias(), pluralCount, &ptnLength, &err); + if (err == U_MEMORY_ALLOCATION_ERROR || patternChars == nullptr) { + ec = err; + break; + } + if (U_SUCCESS(err) && ptnLength > 0) { + UnicodeString* pattern = new UnicodeString(patternChars, ptnLength); + if (pattern == nullptr) { + ec = U_MEMORY_ALLOCATION_ERROR; + break; + } #ifdef CURRENCY_PLURAL_INFO_DEBUG - char result_1[1000]; - pattern->extract(0, pattern->length(), result_1, "UTF-8"); - std::cout << "pluralCount: " << pluralCount << "; pattern: " << result_1 << "\n"; + char result_1[1000]; + pattern->extract(0, pattern->length(), result_1, "UTF-8"); + std::cout << "pluralCount: " << pluralCount << "; pattern: " << result_1 << "\n"; #endif - pattern->findAndReplace(UnicodeString(TRUE, gPart0, 3), - UnicodeString(numberStylePattern, numberStylePatternLen)); - pattern->findAndReplace(UnicodeString(TRUE, gPart1, 3), UnicodeString(TRUE, gTripleCurrencySign, 3)); - - if (hasSeparator) { - UnicodeString negPattern(patternChars, ptnLen); - negPattern.findAndReplace(UnicodeString(TRUE, gPart0, 3), - UnicodeString(negNumberStylePattern, negNumberStylePatternLen)); - negPattern.findAndReplace(UnicodeString(TRUE, gPart1, 3), UnicodeString(TRUE, gTripleCurrencySign, 3)); - pattern->append(gNumberPatternSeparator); - pattern->append(negPattern); - } + pattern->findAndReplace(UnicodeString(TRUE, gPart0, 3), + UnicodeString(numberStylePattern, numberStylePatternLen)); + pattern->findAndReplace(UnicodeString(TRUE, gPart1, 3), UnicodeString(TRUE, gTripleCurrencySign, 3)); + + if (hasSeparator) { + UnicodeString negPattern(patternChars, ptnLength); + negPattern.findAndReplace(UnicodeString(TRUE, gPart0, 3), + UnicodeString(negNumberStylePattern, negNumberStylePatternLen)); + negPattern.findAndReplace(UnicodeString(TRUE, gPart1, 3), UnicodeString(TRUE, gTripleCurrencySign, 3)); + pattern->append(gNumberPatternSeparator); + pattern->append(negPattern); + } #ifdef CURRENCY_PLURAL_INFO_DEBUG - pattern->extract(0, pattern->length(), result_1, "UTF-8"); - std::cout << "pluralCount: " << pluralCount << "; pattern: " << result_1 << "\n"; + pattern->extract(0, pattern->length(), result_1, "UTF-8"); + std::cout << "pluralCount: " << pluralCount << "; pattern: " << result_1 << "\n"; #endif - - fPluralCountToCurrencyUnitPattern->put(UnicodeString(pluralCount, -1, US_INV), pattern, status); - } + // the 'pattern' object allocated above will be owned by the fPluralCountToCurrencyUnitPattern after the call to + // put(), even if the method returns failure. + fPluralCountToCurrencyUnitPattern->put(UnicodeString(pluralCount, -1, US_INV), pattern, status); } } } - delete keywords; - ures_close(currencyRes); - ures_close(currRb); + // If OOM occurred during the above code, then we want to report that back to the caller. + if (ec == U_MEMORY_ALLOCATION_ERROR) { + status = ec; + } } - - void -CurrencyPluralInfo::deleteHash(Hashtable* hTable) -{ - if ( hTable == NULL ) { +CurrencyPluralInfo::deleteHash(Hashtable* hTable) { + if ( hTable == nullptr ) { return; } int32_t pos = UHASH_FIRST; - const UHashElement* element = NULL; - while ( (element = hTable->nextElement(pos)) != NULL ) { + const UHashElement* element = nullptr; + while ( (element = hTable->nextElement(pos)) != nullptr ) { const UHashTok valueTok = element->value; const UnicodeString* value = (UnicodeString*)valueTok.pointer; delete value; } delete hTable; - hTable = NULL; + hTable = nullptr; } - Hashtable* CurrencyPluralInfo::initHash(UErrorCode& status) { - if ( U_FAILURE(status) ) { - return NULL; - } - Hashtable* hTable; - if ( (hTable = new Hashtable(TRUE, status)) == NULL ) { - status = U_MEMORY_ALLOCATION_ERROR; - return NULL; + if (U_FAILURE(status)) { + return nullptr; } - if ( U_FAILURE(status) ) { - delete hTable; - return NULL; + LocalPointer hTable(new Hashtable(TRUE, status), status); + if (U_FAILURE(status)) { + return nullptr; } hTable->setValueComparator(ValueComparator); - return hTable; + return hTable.orphan(); } - void CurrencyPluralInfo::copyHash(const Hashtable* source, Hashtable* target, UErrorCode& status) { - if ( U_FAILURE(status) ) { + if (U_FAILURE(status)) { return; } int32_t pos = UHASH_FIRST; - const UHashElement* element = NULL; - if ( source ) { - while ( (element = source->nextElement(pos)) != NULL ) { + const UHashElement* element = nullptr; + if (source) { + while ( (element = source->nextElement(pos)) != nullptr ) { const UHashTok keyTok = element->key; const UnicodeString* key = (UnicodeString*)keyTok.pointer; const UHashTok valueTok = element->value; const UnicodeString* value = (UnicodeString*)valueTok.pointer; - UnicodeString* copy = new UnicodeString(*value); - target->put(UnicodeString(*key), copy, status); - if ( U_FAILURE(status) ) { + LocalPointer copy(new UnicodeString(*value), status); + if (U_FAILURE(status)) { + return; + } + // The HashTable owns the 'copy' object after the call to put(). + target->put(UnicodeString(*key), copy.orphan(), status); + if (U_FAILURE(status)) { return; } } } } - U_NAMESPACE_END #endif diff --git a/deps/icu-small/source/i18n/currunit.cpp b/deps/icu-small/source/i18n/currunit.cpp index 6d8d1cd6c6f97f..2ece508751bcec 100644 --- a/deps/icu-small/source/i18n/currunit.cpp +++ b/deps/icu-small/source/i18n/currunit.cpp @@ -27,9 +27,14 @@ CurrencyUnit::CurrencyUnit(ConstChar16Ptr _isoCode, UErrorCode& ec) { // The constructor always leaves the CurrencyUnit in a valid state (with a 3-character currency code). // Note: in ICU4J Currency.getInstance(), we check string length for 3, but in ICU4C we allow a // non-NUL-terminated string to be passed as an argument, so it is not possible to check length. + // However, we allow a NUL-terminated empty string, which should have the same behavior as nullptr. + // Consider NUL-terminated strings of length 1 or 2 as invalid. const char16_t* isoCodeToUse; - if (U_FAILURE(ec) || _isoCode == nullptr) { + if (U_FAILURE(ec) || _isoCode == nullptr || _isoCode[0] == 0) { isoCodeToUse = kDefaultCurrency; + } else if (_isoCode[1] == 0 || _isoCode[2] == 0) { + isoCodeToUse = kDefaultCurrency; + ec = U_ILLEGAL_ARGUMENT_ERROR; } else if (!uprv_isInvariantUString(_isoCode, 3)) { // TODO: Perform a more strict ASCII check like in ICU4J isAlpha3Code? isoCodeToUse = kDefaultCurrency; diff --git a/deps/icu-small/source/i18n/dcfmtsym.cpp b/deps/icu-small/source/i18n/dcfmtsym.cpp index 5a432aec8e4df0..04113785f27308 100644 --- a/deps/icu-small/source/i18n/dcfmtsym.cpp +++ b/deps/icu-small/source/i18n/dcfmtsym.cpp @@ -436,7 +436,7 @@ DecimalFormatSymbols::initialize(const Locale& loc, UErrorCode& status, sink.resolveMissingMonetarySeparators(fSymbols); // Resolve codePointZero - UChar32 tempCodePointZero; + UChar32 tempCodePointZero = -1; for (int32_t i=0; i<=9; i++) { const UnicodeString& stringDigit = getConstDigitSymbol(i); if (stringDigit.countChar32() != 1) { diff --git a/deps/icu-small/source/i18n/decimfmt.cpp b/deps/icu-small/source/i18n/decimfmt.cpp index a2638bb74298e3..edd8910d9d4fd6 100644 --- a/deps/icu-small/source/i18n/decimfmt.cpp +++ b/deps/icu-small/source/i18n/decimfmt.cpp @@ -1057,12 +1057,19 @@ UBool DecimalFormat::areSignificantDigitsUsed() const { void DecimalFormat::setSignificantDigitsUsed(UBool useSignificantDigits) { // These are the default values from the old implementation. + if (useSignificantDigits) { + if (fields->properties->minimumSignificantDigits != -1 || + fields->properties->maximumSignificantDigits != -1) { + return; + } + } else { + if (fields->properties->minimumSignificantDigits == -1 && + fields->properties->maximumSignificantDigits == -1) { + return; + } + } int32_t minSig = useSignificantDigits ? 1 : -1; int32_t maxSig = useSignificantDigits ? 6 : -1; - if (fields->properties->minimumSignificantDigits == minSig && - fields->properties->maximumSignificantDigits == maxSig) { - return; - } fields->properties->minimumSignificantDigits = minSig; fields->properties->maximumSignificantDigits = maxSig; touchNoError(); @@ -1175,7 +1182,12 @@ void DecimalFormat::setPropertiesFromPattern(const UnicodeString& pattern, int32 } const numparse::impl::NumberParserImpl* DecimalFormat::getParser(UErrorCode& status) const { - if (U_FAILURE(status)) { return nullptr; } + // TODO: Move this into umutex.h? (similar logic also in numrange_fluent.cpp) + // See ICU-20146 + + if (U_FAILURE(status)) { + return nullptr; + } // First try to get the pre-computed parser auto* ptr = fields->atomicParser.load(); @@ -1185,13 +1197,17 @@ const numparse::impl::NumberParserImpl* DecimalFormat::getParser(UErrorCode& sta // Try computing the parser on our own auto* temp = NumberParserImpl::createParserFromProperties(*fields->properties, *fields->symbols, false, status); + if (U_FAILURE(status)) { + return nullptr; + } if (temp == nullptr) { status = U_MEMORY_ALLOCATION_ERROR; - // although we may still dereference, call sites should be guarded + return nullptr; } - // Note: ptr starts as nullptr; during compare_exchange, it is set to what is actually stored in the - // atomic if another thread beat us to computing the parser object. + // Note: ptr starts as nullptr; during compare_exchange, + // it is set to what is actually stored in the atomic + // if another thread beat us to computing the parser object. auto* nonConstThis = const_cast(this); if (!nonConstThis->fields->atomicParser.compare_exchange_strong(ptr, temp)) { // Another thread beat us to computing the parser diff --git a/deps/icu-small/source/i18n/dtfmtsym.cpp b/deps/icu-small/source/i18n/dtfmtsym.cpp index af421d41c72e61..c9dfa045831d60 100644 --- a/deps/icu-small/source/i18n/dtfmtsym.cpp +++ b/deps/icu-small/source/i18n/dtfmtsym.cpp @@ -1311,7 +1311,7 @@ DateFormatSymbols::initZoneStringsArray(void) { UDate now = Calendar::getNow(); UnicodeString tzDispName; - while ((tzid = tzids->snext(status))) { + while ((tzid = tzids->snext(status)) != 0) { if (U_FAILURE(status)) { break; } @@ -2224,8 +2224,8 @@ DateFormatSymbols::initializeData(const Locale& locale, const char *type, UError ++typeMapPtr; } if (typeMapPtr->usageTypeName != NULL && compResult == 0) { - fCapitalization[typeMapPtr->usageTypeEnumValue][0] = intVector[0]; - fCapitalization[typeMapPtr->usageTypeEnumValue][1] = intVector[1]; + fCapitalization[typeMapPtr->usageTypeEnumValue][0] = static_cast(intVector[0]); + fCapitalization[typeMapPtr->usageTypeEnumValue][1] = static_cast(intVector[1]); } } } diff --git a/deps/icu-small/source/i18n/dtitvfmt.cpp b/deps/icu-small/source/i18n/dtitvfmt.cpp index 743b534fc8f9cf..d952cbf509dc40 100644 --- a/deps/icu-small/source/i18n/dtitvfmt.cpp +++ b/deps/icu-small/source/i18n/dtitvfmt.cpp @@ -877,8 +877,7 @@ DateIntervalFormat::getDateTimeSkeleton(const UnicodeString& skeleton, if ( MCount < 3 ) { normalizedDateSkeleton.append(CAP_M); } else { - int32_t i; - for ( i = 0; i < MCount && i < MAX_M_COUNT; ++i ) { + for ( int32_t j = 0; j < MCount && j < MAX_M_COUNT; ++j) { normalizedDateSkeleton.append(CAP_M); } } @@ -887,8 +886,7 @@ DateIntervalFormat::getDateTimeSkeleton(const UnicodeString& skeleton, if ( ECount <= 3 ) { normalizedDateSkeleton.append(CAP_E); } else { - int32_t i; - for ( i = 0; i < ECount && i < MAX_E_COUNT; ++i ) { + for ( int32_t j = 0; j < ECount && j < MAX_E_COUNT; ++j ) { normalizedDateSkeleton.append(CAP_E); } } diff --git a/deps/icu-small/source/i18n/dtitvinf.cpp b/deps/icu-small/source/i18n/dtitvinf.cpp index c863a683a5c2f8..a289fc79c8da0e 100644 --- a/deps/icu-small/source/i18n/dtitvinf.cpp +++ b/deps/icu-small/source/i18n/dtitvinf.cpp @@ -594,7 +594,7 @@ DateIntervalInfo::getBestSkeleton(const UnicodeString& skeleton, const UHashElement* elem = NULL; while ( (elem = fIntervalPatterns->nextElement(pos)) != NULL ) { const UHashTok keyTok = elem->key; - UnicodeString* skeleton = (UnicodeString*)keyTok.pointer; + UnicodeString* newSkeleton = (UnicodeString*)keyTok.pointer; #ifdef DTITVINF_DEBUG skeleton->extract(0, skeleton->length(), result, "UTF-8"); sprintf(mesg, "available skeletons: skeleton: %s; \n", result); @@ -606,7 +606,7 @@ DateIntervalInfo::getBestSkeleton(const UnicodeString& skeleton, for ( i = 0; i < fieldLength; ++i ) { skeletonFieldWidth[i] = 0; } - parseSkeleton(*skeleton, skeletonFieldWidth); + parseSkeleton(*newSkeleton, skeletonFieldWidth); // calculate distance int32_t distance = 0; int8_t fieldDifference = 1; @@ -632,7 +632,7 @@ DateIntervalInfo::getBestSkeleton(const UnicodeString& skeleton, } } if ( distance < bestDistance ) { - bestSkeleton = skeleton; + bestSkeleton = newSkeleton; bestDistance = distance; bestMatchDistanceInfo = fieldDifference; } diff --git a/deps/icu-small/source/i18n/dtptngen.cpp b/deps/icu-small/source/i18n/dtptngen.cpp index aefd70464eb2d8..b44daf37bf5802 100644 --- a/deps/icu-small/source/i18n/dtptngen.cpp +++ b/deps/icu-small/source/i18n/dtptngen.cpp @@ -18,6 +18,7 @@ #include "unicode/decimfmt.h" #include "unicode/dtfmtsym.h" #include "unicode/dtptngen.h" +#include "unicode/localpointer.h" #include "unicode/simpleformatter.h" #include "unicode/smpdtfmt.h" #include "unicode/udat.h" @@ -88,17 +89,17 @@ static void ures_a_open(UResourceBundleAIterator *aiter, UResourceBundle *bund, aiter->num = ures_getSize(aiter->bund); aiter->cursor = 0; #if !defined(U_SORT_ASCII_BUNDLE_ITERATOR) - aiter->entries = NULL; + aiter->entries = nullptr; #else aiter->entries = (UResAEntry*)uprv_malloc(sizeof(UResAEntry)*aiter->num); for(int i=0;inum;i++) { - aiter->entries[i].item = ures_getByIndex(aiter->bund, i, NULL, status); + aiter->entries[i].item = ures_getByIndex(aiter->bund, i, nullptr, status); const char *akey = ures_getKey(aiter->entries[i].item); int32_t len = uprv_strlen(akey)+1; aiter->entries[i].key = (UChar*)uprv_malloc(len*sizeof(UChar)); u_charsToUChars(akey, aiter->entries[i].key, len); } - uprv_sortArray(aiter->entries, aiter->num, sizeof(UResAEntry), ures_a_codepointSort, NULL, TRUE, status); + uprv_sortArray(aiter->entries, aiter->num, sizeof(UResAEntry), ures_a_codepointSort, nullptr, TRUE, status); #endif } @@ -115,7 +116,7 @@ static const UChar *ures_a_getNextString(UResourceBundleAIterator *aiter, int32_ #if !defined(U_SORT_ASCII_BUNDLE_ITERATOR) return ures_getNextString(aiter->bund, len, key, err); #else - if(U_FAILURE(*err)) return NULL; + if(U_FAILURE(*err)) return nullptr; UResourceBundle *item = aiter->entries[aiter->cursor].item; const UChar* ret = ures_getString(item, len, err); *key = ures_getKey(item); @@ -302,49 +303,48 @@ DateTimePatternGenerator::createInstance(UErrorCode& status) { DateTimePatternGenerator* U_EXPORT2 DateTimePatternGenerator::createInstance(const Locale& locale, UErrorCode& status) { if (U_FAILURE(status)) { - return NULL; + return nullptr; } LocalPointer result( new DateTimePatternGenerator(locale, status), status); - return U_SUCCESS(status) ? result.orphan() : NULL; + return U_SUCCESS(status) ? result.orphan() : nullptr; } DateTimePatternGenerator* U_EXPORT2 DateTimePatternGenerator::createEmptyInstance(UErrorCode& status) { - DateTimePatternGenerator *result = new DateTimePatternGenerator(status); - if (result == NULL) { - status = U_MEMORY_ALLOCATION_ERROR; - } if (U_FAILURE(status)) { - delete result; - result = NULL; + return nullptr; } - return result; + LocalPointer result( + new DateTimePatternGenerator(status), status); + return U_SUCCESS(status) ? result.orphan() : nullptr; } DateTimePatternGenerator::DateTimePatternGenerator(UErrorCode &status) : - skipMatcher(NULL), - fAvailableFormatKeyHash(NULL) + skipMatcher(nullptr), + fAvailableFormatKeyHash(nullptr), + internalErrorCode(U_ZERO_ERROR) { fp = new FormatParser(); dtMatcher = new DateTimeMatcher(); distanceInfo = new DistanceInfo(); patternMap = new PatternMap(); - if (fp == NULL || dtMatcher == NULL || distanceInfo == NULL || patternMap == NULL) { - status = U_MEMORY_ALLOCATION_ERROR; + if (fp == nullptr || dtMatcher == nullptr || distanceInfo == nullptr || patternMap == nullptr) { + internalErrorCode = status = U_MEMORY_ALLOCATION_ERROR; } } DateTimePatternGenerator::DateTimePatternGenerator(const Locale& locale, UErrorCode &status) : - skipMatcher(NULL), - fAvailableFormatKeyHash(NULL) + skipMatcher(nullptr), + fAvailableFormatKeyHash(nullptr), + internalErrorCode(U_ZERO_ERROR) { fp = new FormatParser(); dtMatcher = new DateTimeMatcher(); distanceInfo = new DistanceInfo(); patternMap = new PatternMap(); - if (fp == NULL || dtMatcher == NULL || distanceInfo == NULL || patternMap == NULL) { - status = U_MEMORY_ALLOCATION_ERROR; + if (fp == nullptr || dtMatcher == nullptr || distanceInfo == nullptr || patternMap == nullptr) { + internalErrorCode = status = U_MEMORY_ALLOCATION_ERROR; } else { initData(locale, status); @@ -353,13 +353,17 @@ DateTimePatternGenerator::DateTimePatternGenerator(const Locale& locale, UErrorC DateTimePatternGenerator::DateTimePatternGenerator(const DateTimePatternGenerator& other) : UObject(), - skipMatcher(NULL), - fAvailableFormatKeyHash(NULL) + skipMatcher(nullptr), + fAvailableFormatKeyHash(nullptr), + internalErrorCode(U_ZERO_ERROR) { fp = new FormatParser(); dtMatcher = new DateTimeMatcher(); distanceInfo = new DistanceInfo(); patternMap = new PatternMap(); + if (fp == nullptr || dtMatcher == nullptr || distanceInfo == nullptr || patternMap == nullptr) { + internalErrorCode = U_MEMORY_ALLOCATION_ERROR; + } *this=other; } @@ -369,6 +373,7 @@ DateTimePatternGenerator::operator=(const DateTimePatternGenerator& other) { if (&other == this) { return *this; } + internalErrorCode = other.internalErrorCode; pLocale = other.pLocale; fDefaultHourFormatChar = other.fDefaultHourFormatChar; *fp = *(other.fp); @@ -380,11 +385,16 @@ DateTimePatternGenerator::operator=(const DateTimePatternGenerator& other) { dateTimeFormat.getTerminatedBuffer(); decimal.getTerminatedBuffer(); delete skipMatcher; - if ( other.skipMatcher == NULL ) { - skipMatcher = NULL; + if ( other.skipMatcher == nullptr ) { + skipMatcher = nullptr; } else { skipMatcher = new DateTimeMatcher(*other.skipMatcher); + if (skipMatcher == nullptr) + { + internalErrorCode = U_MEMORY_ALLOCATION_ERROR; + return *this; + } } for (int32_t i=0; i< UDATPG_FIELD_COUNT; ++i ) { appendItemFormats[i] = other.appendItemFormats[i]; @@ -394,9 +404,8 @@ DateTimePatternGenerator::operator=(const DateTimePatternGenerator& other) { fieldDisplayNames[i][j].getTerminatedBuffer(); // NUL-terminate for the C API. } } - UErrorCode status = U_ZERO_ERROR; - patternMap->copyFrom(*other.patternMap, status); - copyHashtable(other.fAvailableFormatKeyHash, status); + patternMap->copyFrom(*other.patternMap, internalErrorCode); + copyHashtable(other.fAvailableFormatKeyHash, internalErrorCode); return *this; } @@ -431,21 +440,21 @@ DateTimePatternGenerator::operator!=(const DateTimePatternGenerator& other) cons } DateTimePatternGenerator::~DateTimePatternGenerator() { - if (fAvailableFormatKeyHash!=NULL) { + if (fAvailableFormatKeyHash!=nullptr) { delete fAvailableFormatKeyHash; } - if (fp != NULL) delete fp; - if (dtMatcher != NULL) delete dtMatcher; - if (distanceInfo != NULL) delete distanceInfo; - if (patternMap != NULL) delete patternMap; - if (skipMatcher != NULL) delete skipMatcher; + if (fp != nullptr) delete fp; + if (dtMatcher != nullptr) delete dtMatcher; + if (distanceInfo != nullptr) delete distanceInfo; + if (patternMap != nullptr) delete patternMap; + if (skipMatcher != nullptr) delete skipMatcher; } namespace { UInitOnce initOnce = U_INITONCE_INITIALIZER; -UHashtable *localeToAllowedHourFormatsMap = NULL; +UHashtable *localeToAllowedHourFormatsMap = nullptr; // Value deleter for hashmap. U_CFUNC void U_CALLCONV deleteAllowedHourFormats(void *ptr) { @@ -474,8 +483,8 @@ void DateTimePatternGenerator::initData(const Locale& locale, UErrorCode &status) { //const char *baseLangName = locale.getBaseName(); // unused - skipMatcher = NULL; - fAvailableFormatKeyHash=NULL; + skipMatcher = nullptr; + fAvailableFormatKeyHash=nullptr; addCanonicalItems(status); addICUPatterns(locale, status); addCLDRData(locale, status); @@ -483,6 +492,8 @@ DateTimePatternGenerator::initData(const Locale& locale, UErrorCode &status) { setDecimalSymbols(locale, status); umtx_initOnce(initOnce, loadAllowedHourFormatsData, status); getAllowedHourFormats(locale, status); + // If any of the above methods failed then the object is in an invalid state. + internalErrorCode = status; } // DateTimePatternGenerator::initData namespace { @@ -505,7 +516,7 @@ struct AllowedHourFormatsSink : public ResourceSink { LocalMemory list; int32_t length; if (value.getType() == URES_STRING) { - if (list.allocateInsteadAndReset(2) == NULL) { + if (list.allocateInsteadAndReset(2) == nullptr) { errorCode = U_MEMORY_ALLOCATION_ERROR; return; } @@ -515,7 +526,7 @@ struct AllowedHourFormatsSink : public ResourceSink { else { ResourceArray allowedFormats = value.getArray(errorCode); length = allowedFormats.getSize(); - if (list.allocateInsteadAndReset(length + 1) == NULL) { + if (list.allocateInsteadAndReset(length + 1) == nullptr) { errorCode = U_MEMORY_ALLOCATION_ERROR; return; } @@ -555,9 +566,14 @@ AllowedHourFormatsSink::~AllowedHourFormatsSink() {} U_CFUNC void U_CALLCONV DateTimePatternGenerator::loadAllowedHourFormatsData(UErrorCode &status) { if (U_FAILURE(status)) { return; } localeToAllowedHourFormatsMap = uhash_open( - uhash_hashChars, uhash_compareChars, NULL, &status); + uhash_hashChars, uhash_compareChars, nullptr, &status); + if (U_FAILURE(status)) { return; } + uhash_setValueDeleter(localeToAllowedHourFormatsMap, deleteAllowedHourFormats); - LocalUResourceBundlePointer rb(ures_openDirect(NULL, "supplementalData", &status)); + ucln_i18n_registerCleanup(UCLN_I18N_ALLOWED_HOUR_FORMATS, allowedHourFormatsCleanup); + + LocalUResourceBundlePointer rb(ures_openDirect(nullptr, "supplementalData", &status)); + if (U_FAILURE(status)) { return; } AllowedHourFormatsSink sink; // TODO: Currently in the enumeration each table allocates a new array. @@ -567,8 +583,6 @@ U_CFUNC void U_CALLCONV DateTimePatternGenerator::loadAllowedHourFormatsData(UEr // vector (at index enum*2) for easy data sharing, copy sub-arrays into runtime // object. Remember to clean up the vector, too. ures_getAllItemsWithFallback(rb.getAlias(), "timeData", sink, status); - - ucln_i18n_registerCleanup(UCLN_I18N_ALLOWED_HOUR_FORMATS, allowedHourFormatsCleanup); } void DateTimePatternGenerator::getAllowedHourFormats(const Locale &locale, UErrorCode &status) { @@ -589,17 +603,17 @@ void DateTimePatternGenerator::getAllowedHourFormats(const Locale &locale, UErro const char *language = maxLocale.getLanguage(); CharString langCountry; - langCountry.append(language, uprv_strlen(language), status); + langCountry.append(language, static_cast(uprv_strlen(language)), status); langCountry.append('_', status); - langCountry.append(country, uprv_strlen(country), status); + langCountry.append(country, static_cast(uprv_strlen(country)), status); int32_t *allowedFormats; allowedFormats = (int32_t *)uhash_get(localeToAllowedHourFormatsMap, langCountry.data()); - if (allowedFormats == NULL) { + if (allowedFormats == nullptr) { allowedFormats = (int32_t *)uhash_get(localeToAllowedHourFormatsMap, const_cast(country)); } - if (allowedFormats != NULL) { // Lookup is successful + if (allowedFormats != nullptr) { // Lookup is successful for (int32_t i = 0; i < UPRV_LENGTHOF(fAllowedHourFormats); ++i) { fAllowedHourFormats[i] = allowedFormats[i]; if (allowedFormats[i] == ALLOWED_HOUR_FORMAT_UNKNOWN) { @@ -615,10 +629,10 @@ void DateTimePatternGenerator::getAllowedHourFormats(const Locale &locale, UErro UnicodeString DateTimePatternGenerator::getSkeleton(const UnicodeString& pattern, UErrorCode& /*status*/) { - FormatParser fp; + FormatParser fp2; DateTimeMatcher matcher; PtnSkeleton localSkeleton; - matcher.set(pattern, &fp, localSkeleton); + matcher.set(pattern, &fp2, localSkeleton); return localSkeleton.getSkeleton(); } @@ -634,10 +648,10 @@ DateTimePatternGenerator::staticGetSkeleton( UnicodeString DateTimePatternGenerator::getBaseSkeleton(const UnicodeString& pattern, UErrorCode& /*status*/) { - FormatParser fp; + FormatParser fp2; DateTimeMatcher matcher; PtnSkeleton localSkeleton; - matcher.set(pattern, &fp, localSkeleton); + matcher.set(pattern, &fp2, localSkeleton); return localSkeleton.getBaseSkeleton(); } @@ -663,7 +677,7 @@ DateTimePatternGenerator::addICUPatterns(const Locale& locale, UErrorCode& statu DateFormat::EStyle style = (DateFormat::EStyle)i; df = DateFormat::createDateInstance(style, locale); SimpleDateFormat* sdf; - if (df != NULL && (sdf = dynamic_cast(df)) != NULL) { + if (df != nullptr && (sdf = dynamic_cast(df)) != nullptr) { sdf->toPattern(dfPattern); addPattern(dfPattern, FALSE, conflictingString, status); } @@ -672,7 +686,7 @@ DateTimePatternGenerator::addICUPatterns(const Locale& locale, UErrorCode& statu if (U_FAILURE(status)) { return; } df = DateFormat::createTimeInstance(style, locale); - if (df != NULL && (sdf = dynamic_cast(df)) != NULL) { + if (df != nullptr && (sdf = dynamic_cast(df)) != nullptr) { sdf->toPattern(dfPattern); addPattern(dfPattern, FALSE, conflictingString, status); @@ -747,13 +761,14 @@ DateTimePatternGenerator::getCalendarTypeToUse(const Locale& locale, CharString& ures_getFunctionalEquivalent( localeWithCalendarKey, ULOC_LOCALE_IDENTIFIER_CAPACITY, - NULL, + nullptr, "calendar", "calendar", locale.getName(), - NULL, + nullptr, FALSE, &err); + if (U_FAILURE(err)) { return; } localeWithCalendarKey[ULOC_LOCALE_IDENTIFIER_CAPACITY-1] = 0; // ensure null termination // now get the calendar key value from that locale char calendarType[ULOC_KEYWORDS_CAPACITY]; @@ -763,7 +778,8 @@ DateTimePatternGenerator::getCalendarTypeToUse(const Locale& locale, CharString& calendarType, ULOC_KEYWORDS_CAPACITY, &err); - if (U_SUCCESS(err) && calendarTypeLen < ULOC_KEYWORDS_CAPACITY) { + if (U_FAILURE(err)) { return; } + if (calendarTypeLen < ULOC_KEYWORDS_CAPACITY) { destination.clear().append(calendarType, -1, err); if (U_FAILURE(err)) { return; } } @@ -774,7 +790,7 @@ DateTimePatternGenerator::getCalendarTypeToUse(const Locale& locale, CharString& void DateTimePatternGenerator::consumeShortTimePattern(const UnicodeString& shortTimePattern, UErrorCode& status) { - + if (U_FAILURE(status)) { return; } // set fDefaultHourFormatChar to the hour format character from this pattern int32_t tfIdx, tfLen = shortTimePattern.length(); UBool ignoreChars = FALSE; @@ -782,7 +798,7 @@ DateTimePatternGenerator::consumeShortTimePattern(const UnicodeString& shortTime UChar tfChar = shortTimePattern.charAt(tfIdx); if ( tfChar == SINGLE_QUOTE ) { ignoreChars = !ignoreChars; // toggle (handle quoted literals & '' for single quote) - } else if ( !ignoreChars && u_strchr(hourFormatChars, tfChar) != NULL ) { + } else if ( !ignoreChars && u_strchr(hourFormatChars, tfChar) != nullptr ) { fDefaultHourFormatChar = tfChar; break; } @@ -872,9 +888,9 @@ struct DateTimePatternGenerator::AppendItemNamesSink : public ResourceSink { valueStr.getTerminatedBuffer(); } for (int32_t j = 1; j < UDATPG_WIDTH_COUNT; j++) { - UnicodeString& valueStr = dtpg.getMutableFieldDisplayName((UDateTimePatternField)i, (UDateTimePGDisplayWidth)j); - if (valueStr.isEmpty()) { - valueStr = dtpg.getFieldDisplayName((UDateTimePatternField)i, (UDateTimePGDisplayWidth)(j-1)); + UnicodeString& valueStr2 = dtpg.getMutableFieldDisplayName((UDateTimePatternField)i, (UDateTimePGDisplayWidth)j); + if (valueStr2.isEmpty()) { + valueStr2 = dtpg.getFieldDisplayName((UDateTimePatternField)i, (UDateTimePGDisplayWidth)(j-1)); } } } @@ -921,7 +937,7 @@ DateTimePatternGenerator::addCLDRData(const Locale& locale, UErrorCode& errorCod UnicodeString rbPattern, value, field; CharString path; - LocalUResourceBundlePointer rb(ures_open(NULL, locale.getName(), &errorCode)); + LocalUResourceBundlePointer rb(ures_open(nullptr, locale.getName(), &errorCode)); if (U_FAILURE(errorCode)) { return; } CharString calendarTypeToUse; // to be filled in with the type to use, if all goes well @@ -966,12 +982,13 @@ DateTimePatternGenerator::addCLDRData(const Locale& locale, UErrorCode& errorCod void DateTimePatternGenerator::initHashtable(UErrorCode& err) { - if (fAvailableFormatKeyHash!=NULL) { + if (U_FAILURE(err)) { return; } + if (fAvailableFormatKeyHash!=nullptr) { return; } - if ((fAvailableFormatKeyHash = new Hashtable(FALSE, err))==NULL) { - err=U_MEMORY_ALLOCATION_ERROR; - return; + LocalPointer hash(new Hashtable(FALSE, err), err); + if (U_SUCCESS(err)) { + fAvailableFormatKeyHash = hash.orphan(); } } @@ -1028,7 +1045,14 @@ DateTimePatternGenerator::getBestPattern(const UnicodeString& patternForm, UErro UnicodeString DateTimePatternGenerator::getBestPattern(const UnicodeString& patternForm, UDateTimePatternMatchOptions options, UErrorCode& status) { - const UnicodeString *bestPattern=NULL; + if (U_FAILURE(status)) { + return UnicodeString(); + } + if (U_FAILURE(internalErrorCode)) { + status = internalErrorCode; + return UnicodeString(); + } + const UnicodeString *bestPattern = nullptr; UnicodeString dtFormat; UnicodeString resultPattern; int32_t flags = kDTPGNoFlags; @@ -1044,16 +1068,23 @@ DateTimePatternGenerator::getBestPattern(const UnicodeString& patternForm, UDate resultPattern.remove(); dtMatcher->set(patternFormMapped, fp); - const PtnSkeleton* specifiedSkeleton=NULL; - bestPattern=getBestRaw(*dtMatcher, -1, distanceInfo, &specifiedSkeleton); + const PtnSkeleton* specifiedSkeleton = nullptr; + bestPattern=getBestRaw(*dtMatcher, -1, distanceInfo, status, &specifiedSkeleton); + if (U_FAILURE(status)) { + return UnicodeString(); + } + if ( distanceInfo->missingFieldMask==0 && distanceInfo->extraFieldMask==0 ) { resultPattern = adjustFieldTypes(*bestPattern, specifiedSkeleton, flags, options); return resultPattern; } int32_t neededFields = dtMatcher->getFieldMask(); - UnicodeString datePattern=getBestAppending(neededFields & dateMask, flags, options); - UnicodeString timePattern=getBestAppending(neededFields & timeMask, flags, options); + UnicodeString datePattern=getBestAppending(neededFields & dateMask, flags, status, options); + UnicodeString timePattern=getBestAppending(neededFields & timeMask, flags, status, options); + if (U_FAILURE(status)) { + return UnicodeString(); + } if (datePattern.length()==0) { if (timePattern.length()==0) { resultPattern.remove(); @@ -1074,7 +1105,7 @@ DateTimePatternGenerator::getBestPattern(const UnicodeString& patternForm, UDate /* * Map a skeleton that may have metacharacters jJC to one without, by replacing - * the metacharacters with locale-appropriate fields of of h/H/k/K and of a/b/B + * the metacharacters with locale-appropriate fields of h/H/k/K and of a/b/B * (depends on fDefaultHourFormatChar and fAllowedHourFormats being set, which in * turn depends on initData having been run). This method also updates the flags * as necessary. Returns the updated skeleton. @@ -1159,9 +1190,16 @@ UnicodeString DateTimePatternGenerator::replaceFieldTypes(const UnicodeString& pattern, const UnicodeString& skeleton, UDateTimePatternMatchOptions options, - UErrorCode& /*status*/) { + UErrorCode& status) { + if (U_FAILURE(status)) { + return UnicodeString(); + } + if (U_FAILURE(internalErrorCode)) { + status = internalErrorCode; + return UnicodeString(); + } dtMatcher->set(skeleton, fp); - UnicodeString result = adjustFieldTypes(pattern, NULL, kDTPGNoFlags, options); + UnicodeString result = adjustFieldTypes(pattern, nullptr, kDTPGNoFlags, options); return result; } @@ -1204,20 +1242,24 @@ DateTimePatternGenerator::getDateTimeFormat() const { void DateTimePatternGenerator::setDateTimeFromCalendar(const Locale& locale, UErrorCode& status) { + if (U_FAILURE(status)) { return; } + const UChar *resStr; int32_t resStrLen = 0; - Calendar* fCalendar = Calendar::createInstance(locale, status); + LocalPointer fCalendar(Calendar::createInstance(locale, status), status); if (U_FAILURE(status)) { return; } - LocalUResourceBundlePointer calData(ures_open(NULL, locale.getBaseName(), &status)); + LocalUResourceBundlePointer calData(ures_open(nullptr, locale.getBaseName(), &status)); + if (U_FAILURE(status)) { return; } ures_getByKey(calData.getAlias(), DT_DateTimeCalendarTag, calData.getAlias(), &status); + if (U_FAILURE(status)) { return; } LocalUResourceBundlePointer dateTimePatterns; - if (fCalendar != NULL && fCalendar->getType() != NULL && *fCalendar->getType() != '\0' + if (fCalendar->getType() != nullptr && *fCalendar->getType() != '\0' && uprv_strcmp(fCalendar->getType(), DT_DateTimeGregorianTag) != 0) { dateTimePatterns.adoptInstead(ures_getByKeyWithFallback(calData.getAlias(), fCalendar->getType(), - NULL, &status)); + nullptr, &status)); ures_getByKeyWithFallback(dateTimePatterns.getAlias(), DT_DateTimePatternsTag, dateTimePatterns.getAlias(), &status); } @@ -1238,8 +1280,6 @@ DateTimePatternGenerator::setDateTimeFromCalendar(const Locale& locale, UErrorCo } resStr = ures_getStringByIndex(dateTimePatterns.getAlias(), (int32_t)DateFormat::kDateTime, &resStrLen, &status); setDateTimeFormat(UnicodeString(TRUE, resStr, resStrLen)); - - delete fCalendar; } void @@ -1259,7 +1299,12 @@ DateTimePatternGenerator::addPattern( UnicodeString &conflictingPattern, UErrorCode& status) { - return addPatternWithSkeleton(pattern, NULL, override, conflictingPattern, status); + if (U_FAILURE(internalErrorCode)) { + status = internalErrorCode; + return UDATPG_NO_CONFLICT; + } + + return addPatternWithSkeleton(pattern, nullptr, override, conflictingPattern, status); } // For DateTimePatternGenerator::addPatternWithSkeleton - @@ -1280,13 +1325,17 @@ DateTimePatternGenerator::addPatternWithSkeleton( UnicodeString& conflictingPattern, UErrorCode& status) { + if (U_FAILURE(internalErrorCode)) { + status = internalErrorCode; + return UDATPG_NO_CONFLICT; + } UnicodeString basePattern; PtnSkeleton skeleton; UDateTimePatternConflict conflictingStatus = UDATPG_NO_CONFLICT; DateTimeMatcher matcher; - if ( skeletonToUse == NULL ) { + if ( skeletonToUse == nullptr ) { matcher.set(pattern, fp, skeleton); matcher.getBasePattern(basePattern); } else { @@ -1302,7 +1351,7 @@ DateTimePatternGenerator::addPatternWithSkeleton( // availableFormats items from root, which should not override any previous entry with the same base. UBool entryHadSpecifiedSkeleton; const UnicodeString *duplicatePattern = patternMap->getPatternFromBasePattern(basePattern, entryHadSpecifiedSkeleton); - if (duplicatePattern != NULL && (!entryHadSpecifiedSkeleton || (skeletonToUse != NULL && !override))) { + if (duplicatePattern != nullptr && (!entryHadSpecifiedSkeleton || (skeletonToUse != nullptr && !override))) { conflictingStatus = UDATPG_BASE_CONFLICT; conflictingPattern = *duplicatePattern; if (!override) { @@ -1313,16 +1362,16 @@ DateTimePatternGenerator::addPatternWithSkeleton( // items from CLDR data. In that case, we don't want an item from a parent locale to replace an item with // same skeleton from the specified locale, so skip the current item if skeletonWasSpecified is true for // the previously-specified conflicting item. - const PtnSkeleton* entrySpecifiedSkeleton = NULL; + const PtnSkeleton* entrySpecifiedSkeleton = nullptr; duplicatePattern = patternMap->getPatternFromSkeleton(skeleton, &entrySpecifiedSkeleton); - if (duplicatePattern != NULL ) { + if (duplicatePattern != nullptr ) { conflictingStatus = UDATPG_CONFLICT; conflictingPattern = *duplicatePattern; - if (!override || (skeletonToUse != NULL && entrySpecifiedSkeleton != NULL)) { + if (!override || (skeletonToUse != nullptr && entrySpecifiedSkeleton != nullptr)) { return conflictingStatus; } } - patternMap->add(basePattern, skeleton, pattern, skeletonToUse != NULL, status); + patternMap->add(basePattern, skeleton, pattern, skeletonToUse != nullptr, status); if(U_FAILURE(status)) { return conflictingStatus; } @@ -1369,13 +1418,16 @@ const UnicodeString* DateTimePatternGenerator::getBestRaw(DateTimeMatcher& source, int32_t includeMask, DistanceInfo* missingFields, + UErrorCode &status, const PtnSkeleton** specifiedSkeletonPtr) { int32_t bestDistance = 0x7fffffff; DistanceInfo tempInfo; - const UnicodeString *bestPattern=NULL; - const PtnSkeleton* specifiedSkeleton=NULL; + const UnicodeString *bestPattern=nullptr; + const PtnSkeleton* specifiedSkeleton=nullptr; + + PatternMapIterator it(status); + if (U_FAILURE(status)) { return nullptr; } - PatternMapIterator it; for (it.set(*patternMap); it.hasNext(); ) { DateTimeMatcher trial = it.next(); if (trial.equals(skipMatcher)) { @@ -1485,8 +1537,8 @@ DateTimePatternGenerator::adjustFieldTypes(const UnicodeString& pattern, c = fDefaultHourFormatChar; } field.remove(); - for (int32_t i=adjFieldLen; i>0; --i) { - field+=c; + for (int32_t j=adjFieldLen; j>0; --j) { + field += c; } } newPattern+=field; @@ -1496,14 +1548,21 @@ DateTimePatternGenerator::adjustFieldTypes(const UnicodeString& pattern, } UnicodeString -DateTimePatternGenerator::getBestAppending(int32_t missingFields, int32_t flags, UDateTimePatternMatchOptions options) { +DateTimePatternGenerator::getBestAppending(int32_t missingFields, int32_t flags, UErrorCode &status, UDateTimePatternMatchOptions options) { + if (U_FAILURE(status)) { + return UnicodeString(); + } UnicodeString resultPattern, tempPattern; - UErrorCode err=U_ZERO_ERROR; + const UnicodeString* tempPatternPtr; int32_t lastMissingFieldMask=0; if (missingFields!=0) { resultPattern=UnicodeString(); - const PtnSkeleton* specifiedSkeleton=NULL; - tempPattern = *getBestRaw(*dtMatcher, missingFields, distanceInfo, &specifiedSkeleton); + const PtnSkeleton* specifiedSkeleton=nullptr; + tempPatternPtr = getBestRaw(*dtMatcher, missingFields, distanceInfo, status, &specifiedSkeleton); + if (U_FAILURE(status)) { + return UnicodeString(); + } + tempPattern = *tempPatternPtr; resultPattern = adjustFieldTypes(tempPattern, specifiedSkeleton, flags, options); if ( distanceInfo->missingFieldMask==0 ) { return resultPattern; @@ -1519,19 +1578,26 @@ DateTimePatternGenerator::getBestAppending(int32_t missingFields, int32_t flags, continue; } int32_t startingMask = distanceInfo->missingFieldMask; - tempPattern = *getBestRaw(*dtMatcher, distanceInfo->missingFieldMask, distanceInfo, &specifiedSkeleton); + tempPatternPtr = getBestRaw(*dtMatcher, distanceInfo->missingFieldMask, distanceInfo, status, &specifiedSkeleton); + if (U_FAILURE(status)) { + return UnicodeString(); + } + tempPattern = *tempPatternPtr; tempPattern = adjustFieldTypes(tempPattern, specifiedSkeleton, flags, options); int32_t foundMask=startingMask& ~distanceInfo->missingFieldMask; int32_t topField=getTopBitNumber(foundMask); - UnicodeString appendName; - getAppendName((UDateTimePatternField)topField, appendName); - const UnicodeString *values[3] = { - &resultPattern, - &tempPattern, - &appendName - }; - SimpleFormatter(appendItemFormats[topField], 2, 3, err). - formatAndReplace(values, 3, resultPattern, NULL, 0, err); + + if (appendItemFormats[topField].length() != 0) { + UnicodeString appendName; + getAppendName((UDateTimePatternField)topField, appendName); + const UnicodeString *values[3] = { + &resultPattern, + &tempPattern, + &appendName + }; + SimpleFormatter(appendItemFormats[topField], 2, 3, status). + formatAndReplace(values, 3, resultPattern, nullptr, 0, status); + } lastMissingFieldMask = distanceInfo->missingFieldMask; } } @@ -1539,7 +1605,7 @@ DateTimePatternGenerator::getBestAppending(int32_t missingFields, int32_t flags, } int32_t -DateTimePatternGenerator::getTopBitNumber(int32_t foundMask) { +DateTimePatternGenerator::getTopBitNumber(int32_t foundMask) const { if ( foundMask==0 ) { return 0; } @@ -1568,22 +1634,21 @@ DateTimePatternGenerator::isAvailableFormatSet(const UnicodeString &key) const { void DateTimePatternGenerator::copyHashtable(Hashtable *other, UErrorCode &status) { - - if (other == NULL) { + if (other == nullptr || U_FAILURE(status)) { return; } - if (fAvailableFormatKeyHash != NULL) { + if (fAvailableFormatKeyHash != nullptr) { delete fAvailableFormatKeyHash; - fAvailableFormatKeyHash = NULL; + fAvailableFormatKeyHash = nullptr; } initHashtable(status); if(U_FAILURE(status)){ return; } int32_t pos = UHASH_FIRST; - const UHashElement* elem = NULL; + const UHashElement* elem = nullptr; // walk through the hash table and create a deep clone - while((elem = other->nextElement(pos))!= NULL){ + while((elem = other->nextElement(pos))!= nullptr){ const UHashTok otherKeyTok = elem->key; UnicodeString* otherKey = (UnicodeString*)otherKeyTok.pointer; fAvailableFormatKeyHash->puti(*otherKey, 1, status); @@ -1595,8 +1660,17 @@ DateTimePatternGenerator::copyHashtable(Hashtable *other, UErrorCode &status) { StringEnumeration* DateTimePatternGenerator::getSkeletons(UErrorCode& status) const { - StringEnumeration* skeletonEnumerator = new DTSkeletonEnumeration(*patternMap, DT_SKELETON, status); - return skeletonEnumerator; + if (U_FAILURE(status)) { + return nullptr; + } + if (U_FAILURE(internalErrorCode)) { + status = internalErrorCode; + return nullptr; + } + LocalPointer skeletonEnumerator( + new DTSkeletonEnumeration(*patternMap, DT_SKELETON, status), status); + + return U_SUCCESS(status) ? skeletonEnumerator.orphan() : nullptr; } const UnicodeString& @@ -1607,47 +1681,70 @@ DateTimePatternGenerator::getPatternForSkeleton(const UnicodeString& skeleton) c return emptyString; } curElem = patternMap->getHeader(skeleton.charAt(0)); - while ( curElem != NULL ) { + while ( curElem != nullptr ) { if ( curElem->skeleton->getSkeleton()==skeleton ) { return curElem->pattern; } - curElem=curElem->next; + curElem = curElem->next.getAlias(); } return emptyString; } StringEnumeration* DateTimePatternGenerator::getBaseSkeletons(UErrorCode& status) const { - StringEnumeration* baseSkeletonEnumerator = new DTSkeletonEnumeration(*patternMap, DT_BASESKELETON, status); - return baseSkeletonEnumerator; + if (U_FAILURE(status)) { + return nullptr; + } + if (U_FAILURE(internalErrorCode)) { + status = internalErrorCode; + return nullptr; + } + LocalPointer baseSkeletonEnumerator( + new DTSkeletonEnumeration(*patternMap, DT_BASESKELETON, status), status); + + return U_SUCCESS(status) ? baseSkeletonEnumerator.orphan() : nullptr; } StringEnumeration* DateTimePatternGenerator::getRedundants(UErrorCode& status) { - StringEnumeration* output = new DTRedundantEnumeration(); + if (U_FAILURE(status)) { return nullptr; } + if (U_FAILURE(internalErrorCode)) { + status = internalErrorCode; + return nullptr; + } + LocalPointer output(new DTRedundantEnumeration(), status); + if (U_FAILURE(status)) { return nullptr; } const UnicodeString *pattern; - PatternMapIterator it; + PatternMapIterator it(status); + if (U_FAILURE(status)) { return nullptr; } + for (it.set(*patternMap); it.hasNext(); ) { DateTimeMatcher current = it.next(); pattern = patternMap->getPatternFromSkeleton(*(it.getSkeleton())); if ( isCanonicalItem(*pattern) ) { continue; } - if ( skipMatcher == NULL ) { + if ( skipMatcher == nullptr ) { skipMatcher = new DateTimeMatcher(current); + if (skipMatcher == nullptr) { + status = U_MEMORY_ALLOCATION_ERROR; + return nullptr; + } } else { *skipMatcher = current; } UnicodeString trial = getBestPattern(current.getPattern(), status); + if (U_FAILURE(status)) { return nullptr; } if (trial == *pattern) { - ((DTRedundantEnumeration *)output)->add(*pattern, status); + ((DTRedundantEnumeration *)output.getAlias())->add(*pattern, status); + if (U_FAILURE(status)) { return nullptr; } } if (current.equals(skipMatcher)) { continue; } } - return output; + return output.orphan(); } UBool @@ -1671,45 +1768,54 @@ DateTimePatternGenerator::clone() const { PatternMap::PatternMap() { for (int32_t i=0; i < MAX_PATTERN_ENTRIES; ++i ) { - boot[i]=NULL; + boot[i] = nullptr; } isDupAllowed = TRUE; } void PatternMap::copyFrom(const PatternMap& other, UErrorCode& status) { + if (U_FAILURE(status)) { + return; + } this->isDupAllowed = other.isDupAllowed; - for (int32_t bootIndex=0; bootIndexbasePattern, otherElem->pattern))==NULL) { - // out of memory - status = U_MEMORY_ALLOCATION_ERROR; - return; + while (otherElem != nullptr) { + LocalPointer newElem(new PtnElem(otherElem->basePattern, otherElem->pattern), status); + if (U_FAILURE(status)) { + return; // out of memory } - if ( this->boot[bootIndex]== NULL ) { - this->boot[bootIndex] = curElem; + newElem->skeleton.adoptInsteadAndCheckErrorCode(new PtnSkeleton(*(otherElem->skeleton)), status); + if (U_FAILURE(status)) { + return; // out of memory } - if ((curElem->skeleton=new PtnSkeleton(*(otherElem->skeleton))) == NULL ) { - // out of memory - status = U_MEMORY_ALLOCATION_ERROR; - return; - } - curElem->skeletonWasSpecified = otherElem->skeletonWasSpecified; - if (prevElem!=NULL) { - prevElem->next=curElem; + newElem->skeletonWasSpecified = otherElem->skeletonWasSpecified; + + // Release ownership from the LocalPointer of the PtnElem object. + // The PtnElem will now be owned by either the boot (for the first entry in the linked-list) + // or owned by the previous PtnElem object in the linked-list. + curElem = newElem.orphan(); + + if (this->boot[bootIndex] == nullptr) { + this->boot[bootIndex] = curElem; + } else { + if (prevElem != nullptr) { + prevElem->next.adoptInstead(curElem); + } else { + U_ASSERT(false); + } } - curElem->next=NULL; prevElem = curElem; - otherElem = otherElem->next; + otherElem = otherElem->next.getAlias(); } } } PtnElem* -PatternMap::getHeader(UChar baseChar) { +PatternMap::getHeader(UChar baseChar) const { PtnElem* curElem; if ( (baseChar >= CAP_A) && (baseChar <= CAP_Z) ) { @@ -1720,7 +1826,7 @@ PatternMap::getHeader(UChar baseChar) { curElem = boot[26+baseChar-LOW_A]; } else { - return NULL; + return nullptr; } } return curElem; @@ -1728,9 +1834,9 @@ PatternMap::getHeader(UChar baseChar) { PatternMap::~PatternMap() { for (int32_t i=0; i < MAX_PATTERN_ENTRIES; ++i ) { - if (boot[i]!=NULL ) { + if (boot[i] != nullptr ) { delete boot[i]; - boot[i]=NULL; + boot[i] = nullptr; } } } // PatternMap destructor @@ -1759,39 +1865,45 @@ PatternMap::add(const UnicodeString& basePattern, } } - if (baseElem == NULL) { - if ((curElem = new PtnElem(basePattern, value)) == NULL ) { - // out of memory - status = U_MEMORY_ALLOCATION_ERROR; - return; + if (baseElem == nullptr) { + LocalPointer newElem(new PtnElem(basePattern, value), status); + if (U_FAILURE(status)) { + return; // out of memory } + newElem->skeleton.adoptInsteadAndCheckErrorCode(new PtnSkeleton(skeleton), status); + if (U_FAILURE(status)) { + return; // out of memory + } + newElem->skeletonWasSpecified = skeletonWasSpecified; if (baseChar >= LOW_A) { - boot[26 + (baseChar-LOW_A)] = curElem; + boot[26 + (baseChar - LOW_A)] = newElem.orphan(); // the boot array now owns the PtnElem. } else { - boot[baseChar-CAP_A] = curElem; + boot[baseChar - CAP_A] = newElem.orphan(); // the boot array now owns the PtnElem. } - curElem->skeleton = new PtnSkeleton(skeleton); - curElem->skeletonWasSpecified = skeletonWasSpecified; } - if ( baseElem != NULL ) { + if ( baseElem != nullptr ) { curElem = getDuplicateElem(basePattern, skeleton, baseElem); - if (curElem == NULL) { + if (curElem == nullptr) { // add new element to the list. curElem = baseElem; - while( curElem -> next != NULL ) + while( curElem -> next != nullptr ) { - curElem = curElem->next; + curElem = curElem->next.getAlias(); } - if ((curElem->next = new PtnElem(basePattern, value)) == NULL ) { - // out of memory - status = U_MEMORY_ALLOCATION_ERROR; - return; + + LocalPointer newElem(new PtnElem(basePattern, value), status); + if (U_FAILURE(status)) { + return; // out of memory } - curElem=curElem->next; - curElem->skeleton = new PtnSkeleton(skeleton); - curElem->skeletonWasSpecified = skeletonWasSpecified; + newElem->skeleton.adoptInsteadAndCheckErrorCode(new PtnSkeleton(skeleton), status); + if (U_FAILURE(status)) { + return; // out of memory + } + newElem->skeletonWasSpecified = skeletonWasSpecified; + curElem->next.adoptInstead(newElem.orphan()); + curElem = curElem->next.getAlias(); } else { // Pattern exists in the list already. @@ -1809,11 +1921,11 @@ PatternMap::add(const UnicodeString& basePattern, // Find the pattern from the given basePattern string. const UnicodeString * -PatternMap::getPatternFromBasePattern(UnicodeString& basePattern, UBool& skeletonWasSpecified) { // key to search for +PatternMap::getPatternFromBasePattern(const UnicodeString& basePattern, UBool& skeletonWasSpecified) const { // key to search for PtnElem *curElem; - if ((curElem=getHeader(basePattern.charAt(0)))==NULL) { - return NULL; // no match + if ((curElem=getHeader(basePattern.charAt(0)))==nullptr) { + return nullptr; // no match } do { @@ -1821,10 +1933,10 @@ PatternMap::getPatternFromBasePattern(UnicodeString& basePattern, UBool& skeleto skeletonWasSpecified = curElem->skeletonWasSpecified; return &(curElem->pattern); } - curElem=curElem->next; - }while (curElem != NULL); + curElem = curElem->next.getAlias(); + } while (curElem != nullptr); - return NULL; + return nullptr; } // PatternMap::getFromBasePattern @@ -1835,69 +1947,69 @@ PatternMap::getPatternFromBasePattern(UnicodeString& basePattern, UBool& skeleto // optimum distance value in getBestRaw. When this is called from public getRedundants (specifiedSkeletonPtr is NULL), // for now it will continue to compare based on baseOriginal so as not to change the behavior unnecessarily. const UnicodeString * -PatternMap::getPatternFromSkeleton(PtnSkeleton& skeleton, const PtnSkeleton** specifiedSkeletonPtr) { // key to search for +PatternMap::getPatternFromSkeleton(const PtnSkeleton& skeleton, const PtnSkeleton** specifiedSkeletonPtr) const { // key to search for PtnElem *curElem; if (specifiedSkeletonPtr) { - *specifiedSkeletonPtr = NULL; + *specifiedSkeletonPtr = nullptr; } // find boot entry UChar baseChar = skeleton.getFirstChar(); - if ((curElem=getHeader(baseChar))==NULL) { - return NULL; // no match + if ((curElem=getHeader(baseChar))==nullptr) { + return nullptr; // no match } do { UBool equal; - if (specifiedSkeletonPtr != NULL) { // called from DateTimePatternGenerator::getBestRaw or addPattern, use original + if (specifiedSkeletonPtr != nullptr) { // called from DateTimePatternGenerator::getBestRaw or addPattern, use original equal = curElem->skeleton->original == skeleton.original; } else { // called from DateTimePatternGenerator::getRedundants, use baseOriginal equal = curElem->skeleton->baseOriginal == skeleton.baseOriginal; } if (equal) { if (specifiedSkeletonPtr && curElem->skeletonWasSpecified) { - *specifiedSkeletonPtr = curElem->skeleton; + *specifiedSkeletonPtr = curElem->skeleton.getAlias(); } return &(curElem->pattern); } - curElem=curElem->next; - }while (curElem != NULL); + curElem = curElem->next.getAlias(); + } while (curElem != nullptr); - return NULL; + return nullptr; } UBool -PatternMap::equals(const PatternMap& other) { +PatternMap::equals(const PatternMap& other) const { if ( this==&other ) { return TRUE; } - for (int32_t bootIndex=0; bootIndexbasePattern != otherElem->basePattern) || (myElem->pattern != otherElem->pattern) ) { return FALSE; } - if ((myElem->skeleton!=otherElem->skeleton)&& + if ((myElem->skeleton.getAlias() != otherElem->skeleton.getAlias()) && !myElem->skeleton->equals(*(otherElem->skeleton))) { return FALSE; } - myElem = myElem->next; - otherElem=otherElem->next; + myElem = myElem->next.getAlias(); + otherElem = otherElem->next.getAlias(); } } return TRUE; @@ -1909,21 +2021,21 @@ PtnElem* PatternMap::getDuplicateElem( const UnicodeString &basePattern, const PtnSkeleton &skeleton, - PtnElem *baseElem) { + PtnElem *baseElem) { PtnElem *curElem; - if ( baseElem == (PtnElem *)NULL ) { - return (PtnElem*)NULL; + if ( baseElem == nullptr ) { + return nullptr; } else { curElem = baseElem; } do { if ( basePattern.compare(curElem->basePattern)==0 ) { - UBool isEqual=TRUE; - for (int32_t i=0; iskeleton->type[i] != skeleton.type[i] ) { - isEqual=FALSE; + isEqual = FALSE; break; } } @@ -1931,11 +2043,11 @@ PatternMap::getDuplicateElem( return curElem; } } - curElem = curElem->next; - } while( curElem != (PtnElem *)NULL ); + curElem = curElem->next.getAlias(); + } while( curElem != nullptr ); // end of the list - return (PtnElem*)NULL; + return nullptr; } // PatternMap::getDuplicateElem @@ -1976,7 +2088,7 @@ DateTimeMatcher::set(const UnicodeString& pattern, FormatParser* fp, PtnSkeleton continue; } int32_t canonicalIndex = fp->getCanonicalIndex(value); - if (canonicalIndex < 0 ) { + if (canonicalIndex < 0) { continue; } const dtTypeElem *row = &dtTypes[canonicalIndex]; @@ -1986,8 +2098,9 @@ DateTimeMatcher::set(const UnicodeString& pattern, FormatParser* fp, PtnSkeleton int32_t repeatCount = row->minLen; skeletonResult.baseOriginal.populate(field, repeatChar, repeatCount); int16_t subField = row->type; - if ( row->type > 0) { - subField += value.length(); + if (row->type > 0) { + U_ASSERT(value.length() < INT16_MAX); + subField += static_cast(value.length()); } skeletonResult.type[field] = subField; } @@ -2031,8 +2144,8 @@ DateTimeMatcher::getPattern() { } int32_t -DateTimeMatcher::getDistance(const DateTimeMatcher& other, int32_t includeMask, DistanceInfo& distanceInfo) { - int32_t result=0; +DateTimeMatcher::getDistance(const DateTimeMatcher& other, int32_t includeMask, DistanceInfo& distanceInfo) const { + int32_t result = 0; distanceInfo.clear(); for (int32_t i=0; iskeleton.original; } int32_t -DateTimeMatcher::getFieldMask() { - int32_t result=0; +DateTimeMatcher::getFieldMask() const { + int32_t result = 0; for (int32_t i=0; i= pattern.length()) { return DONE; } @@ -2132,10 +2245,10 @@ FormatParser::setTokens(const UnicodeString& pattern, int32_t startPos, int32_t void FormatParser::set(const UnicodeString& pattern) { - int32_t startPos=0; - TokenStatus result=START; - int32_t len=0; - itemNumber =0; + int32_t startPos = 0; + TokenStatus result = START; + int32_t len = 0; + itemNumber = 0; do { result = setTokens( pattern, startPos, &len ); @@ -2186,14 +2299,14 @@ FormatParser::getCanonicalIndex(const UnicodeString& s, UBool strict) { UBool FormatParser::isQuoteLiteral(const UnicodeString& s) { - return (UBool)(s.charAt(0)==SINGLE_QUOTE); + return (UBool)(s.charAt(0) == SINGLE_QUOTE); } -// This function aussumes the current itemIndex points to the quote literal. +// This function assumes the current itemIndex points to the quote literal. // Please call isQuoteLiteral prior to this function. void FormatParser::getQuoteLiteral(UnicodeString& quote, int32_t *itemIndex) { - int32_t i=*itemIndex; + int32_t i = *itemIndex; quote.remove(); if (items[i].charAt(0)==SINGLE_QUOTE) { @@ -2222,7 +2335,7 @@ FormatParser::getQuoteLiteral(UnicodeString& quote, int32_t *itemIndex) { } UBool -FormatParser::isPatternSeparator(UnicodeString& field) { +FormatParser::isPatternSeparator(const UnicodeString& field) const { for (int32_t i=0; iskeleton; + return nodePtr->skeleton.getAlias(); } } UBool -PatternMapIterator::hasNext() { - int32_t headIndex=bootIndex; - PtnElem *curPtr=nodePtr; +PatternMapIterator::hasNext() const { + int32_t headIndex = bootIndex; + PtnElem *curPtr = nodePtr; - if (patternMap==NULL) { + if (patternMap==nullptr) { return FALSE; } while ( headIndex < MAX_PATTERN_ENTRIES ) { - if ( curPtr != NULL ) { - if ( curPtr->next != NULL ) { + if ( curPtr != nullptr ) { + if ( curPtr->next != nullptr ) { return TRUE; } else { headIndex++; - curPtr=NULL; + curPtr=nullptr; continue; } } else { - if ( patternMap->boot[headIndex] != NULL ) { + if ( patternMap->boot[headIndex] != nullptr ) { return TRUE; } else { @@ -2299,7 +2410,6 @@ PatternMapIterator::hasNext() { continue; } } - } return FALSE; } @@ -2307,19 +2417,19 @@ PatternMapIterator::hasNext() { DateTimeMatcher& PatternMapIterator::next() { while ( bootIndex < MAX_PATTERN_ENTRIES ) { - if ( nodePtr != NULL ) { - if ( nodePtr->next != NULL ) { - nodePtr = nodePtr->next; + if ( nodePtr != nullptr ) { + if ( nodePtr->next != nullptr ) { + nodePtr = nodePtr->next.getAlias(); break; } else { bootIndex++; - nodePtr=NULL; + nodePtr=nullptr; continue; } } else { - if ( patternMap->boot[bootIndex] != NULL ) { + if ( patternMap->boot[bootIndex] != nullptr ) { nodePtr = patternMap->boot[bootIndex]; break; } @@ -2329,7 +2439,7 @@ PatternMapIterator::next() { } } } - if (nodePtr!=NULL) { + if (nodePtr!=nullptr) { matcher->copyFrom(*nodePtr->skeleton); } else { @@ -2468,36 +2578,28 @@ PtnSkeleton::~PtnSkeleton() { } PtnElem::PtnElem(const UnicodeString &basePat, const UnicodeString &pat) : -basePattern(basePat), -skeleton(NULL), -pattern(pat), -next(NULL) + basePattern(basePat), skeleton(nullptr), pattern(pat), next(nullptr) { } PtnElem::~PtnElem() { - - if (next!=NULL) { - delete next; - } - delete skeleton; } -DTSkeletonEnumeration::DTSkeletonEnumeration(PatternMap &patternMap, dtStrEnum type, UErrorCode& status) { +DTSkeletonEnumeration::DTSkeletonEnumeration(PatternMap& patternMap, dtStrEnum type, UErrorCode& status) : fSkeletons(nullptr) { PtnElem *curElem; PtnSkeleton *curSkeleton; UnicodeString s; int32_t bootIndex; pos=0; - fSkeletons = new UVector(status); + fSkeletons.adoptInsteadAndCheckErrorCode(new UVector(status), status); if (U_FAILURE(status)) { - delete fSkeletons; return; } + for (bootIndex=0; bootIndexbasePattern; @@ -2506,32 +2608,36 @@ DTSkeletonEnumeration::DTSkeletonEnumeration(PatternMap &patternMap, dtStrEnum t s=curElem->pattern; break; case DT_SKELETON: - curSkeleton=curElem->skeleton; + curSkeleton=curElem->skeleton.getAlias(); s=curSkeleton->getSkeleton(); break; } if ( !isCanonicalItem(s) ) { - fSkeletons->addElement(new UnicodeString(s), status); + LocalPointer newElem(new UnicodeString(s), status); if (U_FAILURE(status)) { - delete fSkeletons; - fSkeletons = NULL; return; } + fSkeletons->addElement(newElem.getAlias(), status); + if (U_FAILURE(status)) { + fSkeletons.adoptInstead(nullptr); + return; + } + newElem.orphan(); // fSkeletons vector now owns the UnicodeString. } - curElem = curElem->next; + curElem = curElem->next.getAlias(); } } - if ((bootIndex==MAX_PATTERN_ENTRIES) && (curElem!=NULL) ) { + if ((bootIndex==MAX_PATTERN_ENTRIES) && (curElem!=nullptr) ) { status = U_BUFFER_OVERFLOW_ERROR; } } const UnicodeString* DTSkeletonEnumeration::snext(UErrorCode& status) { - if (U_SUCCESS(status) && pos < fSkeletons->size()) { + if (U_SUCCESS(status) && fSkeletons.isValid() && pos < fSkeletons->size()) { return (const UnicodeString*)fSkeletons->elementAt(pos++); } - return NULL; + return nullptr; } void @@ -2541,7 +2647,7 @@ DTSkeletonEnumeration::reset(UErrorCode& /*status*/) { int32_t DTSkeletonEnumeration::count(UErrorCode& /*status*/) const { - return (fSkeletons==NULL) ? 0 : fSkeletons->size(); + return (fSkeletons.isNull()) ? 0 : fSkeletons->size(); } UBool @@ -2559,44 +2665,45 @@ DTSkeletonEnumeration::isCanonicalItem(const UnicodeString& item) { DTSkeletonEnumeration::~DTSkeletonEnumeration() { UnicodeString *s; - for (int32_t i=0; isize(); ++i) { - if ((s=(UnicodeString *)fSkeletons->elementAt(i))!=NULL) { - delete s; + if (fSkeletons.isValid()) { + for (int32_t i = 0; i < fSkeletons->size(); ++i) { + if ((s = (UnicodeString *)fSkeletons->elementAt(i)) != nullptr) { + delete s; + } } } - delete fSkeletons; } -DTRedundantEnumeration::DTRedundantEnumeration() { - pos=0; - fPatterns = NULL; +DTRedundantEnumeration::DTRedundantEnumeration() : pos(0), fPatterns(nullptr) { } void DTRedundantEnumeration::add(const UnicodeString& pattern, UErrorCode& status) { - if (U_FAILURE(status)) return; - if (fPatterns == NULL) { - fPatterns = new UVector(status); + if (U_FAILURE(status)) { return; } + if (fPatterns.isNull()) { + fPatterns.adoptInsteadAndCheckErrorCode(new UVector(status), status); if (U_FAILURE(status)) { - delete fPatterns; - fPatterns = NULL; return; } } - fPatterns->addElement(new UnicodeString(pattern), status); + LocalPointer newElem(new UnicodeString(pattern), status); + if (U_FAILURE(status)) { + return; + } + fPatterns->addElement(newElem.getAlias(), status); if (U_FAILURE(status)) { - delete fPatterns; - fPatterns = NULL; + fPatterns.adoptInstead(nullptr); return; } + newElem.orphan(); // fPatterns now owns the string. } const UnicodeString* DTRedundantEnumeration::snext(UErrorCode& status) { - if (U_SUCCESS(status) && pos < fPatterns->size()) { + if (U_SUCCESS(status) && fPatterns.isValid() && pos < fPatterns->size()) { return (const UnicodeString*)fPatterns->elementAt(pos++); } - return NULL; + return nullptr; } void @@ -2606,11 +2713,11 @@ DTRedundantEnumeration::reset(UErrorCode& /*status*/) { int32_t DTRedundantEnumeration::count(UErrorCode& /*status*/) const { - return (fPatterns==NULL) ? 0 : fPatterns->size(); + return (fPatterns.isNull()) ? 0 : fPatterns->size(); } UBool -DTRedundantEnumeration::isCanonicalItem(const UnicodeString& item) { +DTRedundantEnumeration::isCanonicalItem(const UnicodeString& item) const { if ( item.length() != 1 ) { return FALSE; } @@ -2624,12 +2731,13 @@ DTRedundantEnumeration::isCanonicalItem(const UnicodeString& item) { DTRedundantEnumeration::~DTRedundantEnumeration() { UnicodeString *s; - for (int32_t i=0; isize(); ++i) { - if ((s=(UnicodeString *)fPatterns->elementAt(i))!=NULL) { - delete s; + if (fPatterns.isValid()) { + for (int32_t i = 0; i < fPatterns->size(); ++i) { + if ((s = (UnicodeString *)fPatterns->elementAt(i)) != nullptr) { + delete s; + } } } - delete fPatterns; } U_NAMESPACE_END diff --git a/deps/icu-small/source/i18n/dtptngen_impl.h b/deps/icu-small/source/i18n/dtptngen_impl.h index 2ea31a75c488fa..95219f0ba257f5 100644 --- a/deps/icu-small/source/i18n/dtptngen_impl.h +++ b/deps/icu-small/source/i18n/dtptngen_impl.h @@ -116,7 +116,7 @@ typedef struct dtTypeElem { int16_t type; int16_t minLen; int16_t weight; -}dtTypeElem; +} dtTypeElem; // A compact storage mechanism for skeleton field strings. Several dozen of these will be created // for a typical DateTimePatternGenerator instance. @@ -172,30 +172,28 @@ class PtnSkeleton : public UMemory { virtual ~PtnSkeleton(); }; - class PtnElem : public UMemory { public: UnicodeString basePattern; - PtnSkeleton *skeleton; + LocalPointer skeleton; UnicodeString pattern; UBool skeletonWasSpecified; // if specified in availableFormats, not derived - PtnElem *next; + LocalPointer next; PtnElem(const UnicodeString &basePattern, const UnicodeString &pattern); virtual ~PtnElem(); - }; class FormatParser : public UMemory { public: UnicodeString items[MAX_DT_TOKEN]; - int32_t itemNumber; + int32_t itemNumber; FormatParser(); virtual ~FormatParser(); void set(const UnicodeString& patternString); void getQuoteLiteral(UnicodeString& quote, int32_t *itemIndex); - UBool isPatternSeparator(UnicodeString& field); + UBool isPatternSeparator(const UnicodeString& field) const; static UBool isQuoteLiteral(const UnicodeString& s); static int32_t getCanonicalIndex(const UnicodeString& s) { return getCanonicalIndex(s, TRUE); } static int32_t getCanonicalIndex(const UnicodeString& s, UBool strict); @@ -206,7 +204,7 @@ class FormatParser : public UMemory { ADD_TOKEN, SYNTAX_ERROR, DONE - } ToeknStatus; + } TokenStatus; TokenStatus status; virtual TokenStatus setTokens(const UnicodeString& pattern, int32_t startPos, int32_t *len); @@ -220,7 +218,7 @@ class DistanceInfo : public UMemory { DistanceInfo() {} virtual ~DistanceInfo(); void clear() { missingFieldMask = extraFieldMask = 0; } - void setTo(DistanceInfo& other); + void setTo(const DistanceInfo& other); void addMissing(int32_t field) { missingFieldMask |= (1< matcher; PatternMap *patternMap; }; class DTSkeletonEnumeration : public StringEnumeration { public: - DTSkeletonEnumeration(PatternMap &patternMap, dtStrEnum type, UErrorCode& status); + DTSkeletonEnumeration(PatternMap& patternMap, dtStrEnum type, UErrorCode& status); virtual ~DTSkeletonEnumeration(); static UClassID U_EXPORT2 getStaticClassID(void); virtual UClassID getDynamicClassID(void) const; @@ -287,7 +285,7 @@ class DTSkeletonEnumeration : public StringEnumeration { private: int32_t pos; UBool isCanonicalItem(const UnicodeString& item); - UVector *fSkeletons; + LocalPointer fSkeletons; }; class DTRedundantEnumeration : public StringEnumeration { @@ -302,8 +300,8 @@ class DTRedundantEnumeration : public StringEnumeration { void add(const UnicodeString &pattern, UErrorCode& status); private: int32_t pos; - UBool isCanonicalItem(const UnicodeString& item); - UVector *fPatterns; + UBool isCanonicalItem(const UnicodeString& item) const; + LocalPointer fPatterns; }; U_NAMESPACE_END diff --git a/deps/icu-small/source/i18n/erarules.cpp b/deps/icu-small/source/i18n/erarules.cpp new file mode 100644 index 00000000000000..669f84423046fd --- /dev/null +++ b/deps/icu-small/source/i18n/erarules.cpp @@ -0,0 +1,307 @@ +// © 2018 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html + +#include "unicode/utypes.h" + +#if !UCONFIG_NO_FORMATTING + +#include +#include "unicode/ucal.h" +#include "unicode/ures.h" +#include "unicode/ustring.h" +#include "cmemory.h" +#include "cstring.h" +#include "erarules.h" +#include "gregoimp.h" +#include "uassert.h" + +U_NAMESPACE_BEGIN + +static const int32_t MAX_ENCODED_START_YEAR = 32767; +static const int32_t MIN_ENCODED_START_YEAR = -32768; +static const int32_t MIN_ENCODED_START = -2147483391; // encodeDate(MIN_ENCODED_START_YEAR, 1, 1, ...); + +static const int32_t YEAR_MASK = 0xFFFF0000; +static const int32_t MONTH_MASK = 0x0000FF00; +static const int32_t DAY_MASK = 0x000000FF; + +static const int32_t MAX_INT32 = 0x7FFFFFFF; +static const int32_t MIN_INT32 = 0xFFFFFFFF; + +static const UChar VAL_FALSE[] = {0x66, 0x61, 0x6c, 0x73, 0x65}; // "false" +static const UChar VAL_FALSE_LEN = 5; + +static UBool isSet(int startDate) { + return startDate != 0; +} + +static UBool isValidRuleStartDate(int32_t year, int32_t month, int32_t day) { + return year >= MIN_ENCODED_START_YEAR && year <= MAX_ENCODED_START_YEAR + && month >= 1 && month <= 12 && day >=1 && day <= 31; +} + +/** + * Encode year/month/date to a single integer. + * year is high 16 bits (-32768 to 32767), month is + * next 8 bits and day of month is last 8 bits. + * + * @param year year + * @param month month (1-base) + * @param day day of month + * @return an encoded date. + */ +static int32_t encodeDate(int32_t year, int32_t month, int32_t day) { + return year << 16 | month << 8 | day; +} + +static void decodeDate(int32_t encodedDate, int32_t (&fields)[3]) { + if (encodedDate == MIN_ENCODED_START) { + fields[0] = MIN_INT32; + fields[1] = 1; + fields[2] = 1; + } else { + fields[0] = (encodedDate & YEAR_MASK) >> 16; + fields[1] = (encodedDate & MONTH_MASK) >> 8; + fields[2] = encodedDate & DAY_MASK; + } +} + +/** + * Compare an encoded date with another date specified by year/month/day. + * @param encoded An encoded date + * @param year Year of another date + * @param month Month of another date + * @param day Day of another date + * @return -1 when encoded date is earlier, 0 when two dates are same, + * and 1 when encoded date is later. + */ +static int32_t compareEncodedDateWithYMD(int encoded, int year, int month, int day) { + if (year < MIN_ENCODED_START_YEAR) { + if (encoded == MIN_ENCODED_START) { + if (year > MIN_INT32 || month > 1 || day > 1) { + return -1; + } + return 0; + } else { + return 1; + } + } else if (year > MAX_ENCODED_START_YEAR) { + return -1; + } else { + int tmp = encodeDate(year, month, day); + if (encoded < tmp) { + return -1; + } else if (encoded == tmp) { + return 0; + } else { + return 1; + } + } +} + +EraRules::EraRules(LocalMemory& eraStartDates, int32_t numEras) + : numEras(numEras) { + startDates.moveFrom(eraStartDates); + initCurrentEra(); +} + +EraRules::~EraRules() { +} + +EraRules* EraRules::createInstance(const char *calType, UBool includeTentativeEra, UErrorCode& status) { + if(U_FAILURE(status)) { + return nullptr; + } + LocalUResourceBundlePointer rb(ures_openDirect(nullptr, "supplementalData", &status)); + ures_getByKey(rb.getAlias(), "calendarData", rb.getAlias(), &status); + ures_getByKey(rb.getAlias(), calType, rb.getAlias(), &status); + ures_getByKey(rb.getAlias(), "eras", rb.getAlias(), &status); + + if (U_FAILURE(status)) { + return nullptr; + } + + int32_t numEras = ures_getSize(rb.getAlias()); + int32_t firstTentativeIdx = MAX_INT32; + + LocalMemory startDates(static_cast(uprv_malloc(numEras * sizeof(int32_t)))); + if (startDates.isNull()) { + status = U_MEMORY_ALLOCATION_ERROR; + return nullptr; + } + uprv_memset(startDates.getAlias(), 0 , numEras * sizeof(int32_t)); + + while (ures_hasNext(rb.getAlias())) { + LocalUResourceBundlePointer eraRuleRes(ures_getNextResource(rb.getAlias(), nullptr, &status)); + if (U_FAILURE(status)) { + return nullptr; + } + const char *eraIdxStr = ures_getKey(eraRuleRes.getAlias()); + char *endp; + int32_t eraIdx = (int32_t)strtol(eraIdxStr, &endp, 10); + if ((size_t)(endp - eraIdxStr) != uprv_strlen(eraIdxStr)) { + status = U_INVALID_FORMAT_ERROR; + return nullptr; + } + if (eraIdx < 0 || eraIdx >= numEras) { + status = U_INVALID_FORMAT_ERROR; + return nullptr; + } + if (isSet(startDates[eraIdx])) { + // start date of the index was already set + status = U_INVALID_FORMAT_ERROR; + return nullptr; + } + + UBool hasName = TRUE; + UBool hasEnd = TRUE; + int32_t len; + while (ures_hasNext(eraRuleRes.getAlias())) { + LocalUResourceBundlePointer res(ures_getNextResource(eraRuleRes.getAlias(), nullptr, &status)); + if (U_FAILURE(status)) { + return nullptr; + } + const char *key = ures_getKey(res.getAlias()); + if (uprv_strcmp(key, "start") == 0) { + const int32_t *fields = ures_getIntVector(res.getAlias(), &len, &status); + if (U_FAILURE(status)) { + return nullptr; + } + if (len != 3 || !isValidRuleStartDate(fields[0], fields[1], fields[2])) { + status = U_INVALID_FORMAT_ERROR; + return nullptr; + } + startDates[eraIdx] = encodeDate(fields[0], fields[1], fields[2]); + } else if (uprv_strcmp(key, "named") == 0) { + const UChar *val = ures_getString(res.getAlias(), &len, &status); + if (u_strncmp(val, VAL_FALSE, VAL_FALSE_LEN) == 0) { + hasName = FALSE; + } + } else if (uprv_strcmp(key, "end") == 0) { + hasEnd = TRUE; + } + } + + if (isSet(startDates[eraIdx])) { + if (hasEnd) { + // This implementation assumes either start or end is available, not both. + // For now, just ignore the end rule. + } + } else { + if (hasEnd) { + if (eraIdx != 0) { + // This implementation does not support end only rule for eras other than + // the first one. + status = U_INVALID_FORMAT_ERROR; + return nullptr; + } + U_ASSERT(eraIdx == 0); + startDates[eraIdx] = MIN_ENCODED_START; + } else { + status = U_INVALID_FORMAT_ERROR; + return nullptr; + } + } + + if (hasName) { + if (eraIdx >= firstTentativeIdx) { + status = U_INVALID_FORMAT_ERROR; + return nullptr; + } + } else { + if (eraIdx < firstTentativeIdx) { + firstTentativeIdx = eraIdx; + } + } + } + + EraRules *result; + if (firstTentativeIdx < MAX_INT32 && !includeTentativeEra) { + result = new EraRules(startDates, firstTentativeIdx); + } else { + result = new EraRules(startDates, numEras); + } + + if (result == nullptr) { + status = U_MEMORY_ALLOCATION_ERROR; + } + return result; +} + +void EraRules::getStartDate(int32_t eraIdx, int32_t (&fields)[3], UErrorCode& status) const { + if(U_FAILURE(status)) { + return; + } + if (eraIdx < 0 || eraIdx >= numEras) { + status = U_ILLEGAL_ARGUMENT_ERROR; + return; + } + decodeDate(startDates[eraIdx], fields); +} + +int32_t EraRules::getStartYear(int32_t eraIdx, UErrorCode& status) const { + int year = MAX_INT32; // bogus value + if(U_FAILURE(status)) { + return year; + } + if (eraIdx < 0 || eraIdx >= numEras) { + status = U_ILLEGAL_ARGUMENT_ERROR; + return year; + } + int fields[3]; + decodeDate(startDates[eraIdx], fields); + year = fields[0]; + + return year; +} + +int32_t EraRules::getEraIndex(int32_t year, int32_t month, int32_t day, UErrorCode& status) const { + if(U_FAILURE(status)) { + return -1; + } + + if (month < 1 || month > 12 || day < 1 || day > 31) { + status = U_ILLEGAL_ARGUMENT_ERROR; + return -1; + } + int32_t high = numEras; // last index + 1 + int32_t low; + + // Short circuit for recent years. Most modern computations will + // occur in the last few eras. + if (compareEncodedDateWithYMD(startDates[getCurrentEraIndex()], year, month, day) <= 0) { + low = getCurrentEraIndex(); + } else { + low = 0; + } + + // Do binary search + while (low < high - 1) { + int i = (low + high) / 2; + if (compareEncodedDateWithYMD(startDates[i], year, month, day) <= 0) { + low = i; + } else { + high = i; + } + } + return low; +} + +void EraRules::initCurrentEra() { + UDate now = ucal_getNow(); + int year, month0, dom, dow, doy, mid; + Grego::timeToFields(now, year, month0, dom, dow, doy, mid); + int currentEncodedDate = encodeDate(year, month0 + 1 /* changes to 1-base */, dom); + int eraIdx = numEras - 1; + while (eraIdx > 0) { + if (currentEncodedDate >= startDates[eraIdx]) { + break; + } + eraIdx--; + } + // Note: current era could be before the first era. + // In this case, this implementation returns the first era index (0). + currentEra = eraIdx;} + +U_NAMESPACE_END +#endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/deps/icu-small/source/i18n/erarules.h b/deps/icu-small/source/i18n/erarules.h new file mode 100644 index 00000000000000..4ed86408325ed7 --- /dev/null +++ b/deps/icu-small/source/i18n/erarules.h @@ -0,0 +1,92 @@ +// © 2018 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html + +#ifndef ERARULES_H_ +#define ERARULES_H_ + +#include "unicode/utypes.h" + +#if !UCONFIG_NO_FORMATTING + +#include "unicode/localpointer.h" +#include "unicode/uobject.h" +#include "cmemory.h" + +U_NAMESPACE_BEGIN + +// Export an explicit template instantiation of LocalMemory used as a data member of EraRules. +// When building DLLs for Windows this is required even though no direct access leaks out of the i18n library. +// See digitlst.h, pluralaffix.h, datefmt.h, and others for similar examples. +#if U_PF_WINDOWS <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN +// Ignore warning 4661 as LocalPointerBase does not use operator== or operator!= +#pragma warning(suppress: 4661) +template class U_I18N_API LocalPointerBase; +template class U_I18N_API LocalMemory; +#endif + +class U_I18N_API EraRules : public UMemory { +public: + ~EraRules(); + + static EraRules* createInstance(const char *calType, UBool includeTentativeEra, UErrorCode& status); + + /** + * Gets number of effective eras + * @return number of effective eras + */ + inline int32_t getNumberOfEras() const { + return numEras; + } + + /** + * Gets start date of an era + * @param eraIdx Era index + * @param fields Receives date fields. The result includes values of year, month, + * day of month in this order. When an era has no start date, the result + * will be January 1st in year whose value is minimum integer. + * @param status Receives status. + */ + void getStartDate(int32_t eraIdx, int32_t (&fields)[3], UErrorCode& status) const; + + /** + * Gets start year of an era + * @param eraIdx Era index + * @param status Receives status. + * @return The first year of an era. When a era has no start date, minimum int32 + * value is returned. + */ + int32_t getStartYear(int32_t eraIdx, UErrorCode& status) const; + + /** + * Returns era index for the specified year/month/day. + * @param year Year + * @param month Month (1-base) + * @param day Day of month + * @param status Receives status + * @return era index (or 0, when the specified date is before the first era) + */ + int32_t getEraIndex(int32_t year, int32_t month, int32_t day, UErrorCode& status) const; + + /** + * Gets the current era index. This is calculated only once for an instance of + * EraRules. + * + * @return era index of current era (or 0, when current date is before the first era) + */ + inline int32_t getCurrentEraIndex() const { + return currentEra; + } + +private: + EraRules(LocalMemory& eraStartDates, int32_t numEra); + + void initCurrentEra(); + + LocalMemory startDates; + int32_t numEras; + int32_t currentEra; +}; + +U_NAMESPACE_END +#endif /* #if !UCONFIG_NO_FORMATTING */ +#endif /* ERARULES_H_ */ diff --git a/deps/icu-small/source/i18n/fphdlimp.h b/deps/icu-small/source/i18n/fphdlimp.h index 2e9d5622b1b5b0..a6827e01e98b4b 100644 --- a/deps/icu-small/source/i18n/fphdlimp.h +++ b/deps/icu-small/source/i18n/fphdlimp.h @@ -10,9 +10,10 @@ #ifndef FPHDLIMP_H #define FPHDLIMP_H +#include "unicode/utypes.h" + #if !UCONFIG_NO_FORMATTING -#include "unicode/utypes.h" #include "unicode/fieldpos.h" #include "unicode/fpositer.h" diff --git a/deps/icu-small/source/i18n/gregocal.cpp b/deps/icu-small/source/i18n/gregocal.cpp index 49c4226049d9c8..4db66758df1f1f 100644 --- a/deps/icu-small/source/i18n/gregocal.cpp +++ b/deps/icu-small/source/i18n/gregocal.cpp @@ -541,8 +541,8 @@ int32_t GregorianCalendar::handleComputeMonthStart(int32_t eyear, int32_t month, } UBool isLeap = eyear%4 == 0; - int32_t y = eyear-1; - int32_t julianDay = 365*y + ClockMath::floorDivide(y, 4) + (kJan1_1JulianDay - 3); + int64_t y = (int64_t)eyear-1; + int64_t julianDay = 365*y + ClockMath::floorDivide(y, (int64_t)4) + (kJan1_1JulianDay - 3); nonConstThis->fIsGregorian = (eyear >= fGregorianCutoverYear); #if defined (U_DEBUG_CAL) @@ -572,7 +572,7 @@ int32_t GregorianCalendar::handleComputeMonthStart(int32_t eyear, int32_t month, julianDay += isLeap?kLeapNumDays[month]:kNumDays[month]; } - return julianDay; + return static_cast(julianDay); } int32_t GregorianCalendar::handleGetMonthLength(int32_t extendedYear, int32_t month) const diff --git a/deps/icu-small/source/i18n/gregoimp.h b/deps/icu-small/source/i18n/gregoimp.h index 55922a6b40aa52..eb3844f8523eeb 100644 --- a/deps/icu-small/source/i18n/gregoimp.h +++ b/deps/icu-small/source/i18n/gregoimp.h @@ -299,8 +299,8 @@ inline int32_t Grego::millisToJulianDay(double millis) { } inline int32_t Grego::gregorianShift(int32_t eyear) { - int32_t y = eyear-1; - int32_t gregShift = ClockMath::floorDivide(y, 400) - ClockMath::floorDivide(y, 100) + 2; + int64_t y = (int64_t)eyear-1; + int32_t gregShift = static_cast(ClockMath::floorDivide(y, (int64_t)400) - ClockMath::floorDivide(y, (int64_t)100) + 2); return gregShift; } diff --git a/deps/icu-small/source/i18n/indiancal.cpp b/deps/icu-small/source/i18n/indiancal.cpp index a2a7f2dcdd3e9e..667b6f2d7a32c5 100644 --- a/deps/icu-small/source/i18n/indiancal.cpp +++ b/deps/icu-small/source/i18n/indiancal.cpp @@ -347,12 +347,15 @@ IndianCalendar::inDaylightTime(UErrorCode& status) const return (UBool)(U_SUCCESS(status) ? (internalGet(UCAL_DST_OFFSET) != 0) : FALSE); } -// default century -const UDate IndianCalendar::fgSystemDefaultCentury = DBL_MIN; -const int32_t IndianCalendar::fgSystemDefaultCenturyYear = -1; -UDate IndianCalendar::fgSystemDefaultCenturyStart = DBL_MIN; -int32_t IndianCalendar::fgSystemDefaultCenturyStartYear = -1; +/** + * The system maintains a static default century start date and Year. They are + * initialized the first time they are used. Once the system default century date + * and year are set, they do not change. + */ +static UDate gSystemDefaultCenturyStart = DBL_MIN; +static int32_t gSystemDefaultCenturyStartYear = -1; +static icu::UInitOnce gSystemDefaultCenturyInit = U_INITONCE_INITIALIZER; UBool IndianCalendar::haveDefaultCentury() const @@ -360,87 +363,45 @@ UBool IndianCalendar::haveDefaultCentury() const return TRUE; } -UDate IndianCalendar::defaultCenturyStart() const +static void U_CALLCONV +initializeSystemDefaultCentury() { - return internalGetDefaultCenturyStart(); -} + // initialize systemDefaultCentury and systemDefaultCenturyYear based + // on the current time. They'll be set to 80 years before + // the current time. + UErrorCode status = U_ZERO_ERROR; -int32_t IndianCalendar::defaultCenturyStartYear() const -{ - return internalGetDefaultCenturyStartYear(); -} + IndianCalendar calendar ( Locale ( "@calendar=Indian" ), status); + if ( U_SUCCESS ( status ) ) { + calendar.setTime ( Calendar::getNow(), status ); + calendar.add ( UCAL_YEAR, -80, status ); -UDate -IndianCalendar::internalGetDefaultCenturyStart() const -{ - // lazy-evaluate systemDefaultCenturyStart - UBool needsUpdate; - { - Mutex m; - needsUpdate = (fgSystemDefaultCenturyStart == fgSystemDefaultCentury); - } + UDate newStart = calendar.getTime ( status ); + int32_t newYear = calendar.get ( UCAL_YEAR, status ); - if (needsUpdate) { - initializeSystemDefaultCentury(); + gSystemDefaultCenturyStart = newStart; + gSystemDefaultCenturyStartYear = newYear; } + // We have no recourse upon failure. +} - // use defaultCenturyStart unless it's the flag value; - // then use systemDefaultCenturyStart - return fgSystemDefaultCenturyStart; +UDate +IndianCalendar::defaultCenturyStart() const +{ + // lazy-evaluate systemDefaultCenturyStart + umtx_initOnce(gSystemDefaultCenturyInit, &initializeSystemDefaultCentury); + return gSystemDefaultCenturyStart; } int32_t -IndianCalendar::internalGetDefaultCenturyStartYear() const +IndianCalendar::defaultCenturyStartYear() const { // lazy-evaluate systemDefaultCenturyStartYear - UBool needsUpdate; - { - Mutex m; - - needsUpdate = (fgSystemDefaultCenturyStart == fgSystemDefaultCentury); - } - - if (needsUpdate) { - initializeSystemDefaultCentury(); - } - - // use defaultCenturyStart unless it's the flag value; - // then use systemDefaultCenturyStartYear - - return fgSystemDefaultCenturyStartYear; + umtx_initOnce(gSystemDefaultCenturyInit, &initializeSystemDefaultCentury); + return gSystemDefaultCenturyStartYear; } -void -IndianCalendar::initializeSystemDefaultCentury() -{ - // initialize systemDefaultCentury and systemDefaultCenturyYear based - // on the current time. They'll be set to 80 years before - // the current time. - // No point in locking as it should be idempotent. - if (fgSystemDefaultCenturyStart == fgSystemDefaultCentury) { - UErrorCode status = U_ZERO_ERROR; - - IndianCalendar calendar(Locale("@calendar=Indian"),status); - if (U_SUCCESS(status)) { - calendar.setTime(Calendar::getNow(), status); - calendar.add(UCAL_YEAR, -80, status); - - UDate newStart = calendar.getTime(status); - int32_t newYear = calendar.get(UCAL_YEAR, status); - - { - Mutex m; - - fgSystemDefaultCenturyStart = newStart; - fgSystemDefaultCenturyStartYear = newYear; - } - } - - // We have no recourse upon failure unless we want to propagate the failure - // out. - } -} UOBJECT_DEFINE_RTTI_IMPLEMENTATION(IndianCalendar) diff --git a/deps/icu-small/source/i18n/indiancal.h b/deps/icu-small/source/i18n/indiancal.h index d40af5ad450c9e..ffd4ae8b8a40cd 100644 --- a/deps/icu-small/source/i18n/indiancal.h +++ b/deps/icu-small/source/i18n/indiancal.h @@ -68,7 +68,7 @@ U_NAMESPACE_BEGIN */ -class IndianCalendar : public Calendar { +class U_I18N_API IndianCalendar : public Calendar { public: /** * Useful constants for IndianCalendar. @@ -274,10 +274,10 @@ class IndianCalendar : public Calendar { * @return The class ID for all objects of this class. * @internal */ - U_I18N_API static UClassID U_EXPORT2 getStaticClassID(void); + static UClassID U_EXPORT2 getStaticClassID(void); /** - * return the calendar type, "buddhist". + * return the calendar type, "indian". * * @return calendar type * @internal @@ -320,49 +320,6 @@ class IndianCalendar : public Calendar { * @internal */ virtual int32_t defaultCenturyStartYear() const; - - private: // default century stuff. - /** - * The system maintains a static default century start date. This is initialized - * the first time it is used. Before then, it is set to SYSTEM_DEFAULT_CENTURY to - * indicate an uninitialized state. Once the system default century date and year - * are set, they do not change. - */ - static UDate fgSystemDefaultCenturyStart; - - /** - * See documentation for systemDefaultCenturyStart. - */ - static int32_t fgSystemDefaultCenturyStartYear; - - /** - * Default value that indicates the defaultCenturyStartYear is unitialized - */ - static const int32_t fgSystemDefaultCenturyYear; - - /** - * start of default century, as a date - */ - static const UDate fgSystemDefaultCentury; - - /** - * Returns the beginning date of the 100-year window that dates - * with 2-digit years are considered to fall within. - */ - UDate internalGetDefaultCenturyStart(void) const; - - /** - * Returns the first year of the 100-year window that dates with - * 2-digit years are considered to fall within. - */ - int32_t internalGetDefaultCenturyStartYear(void) const; - - /** - * Initializes the 100-year window that dates with 2-digit years - * are considered to fall within so that its start date is 80 years - * before the current time. - */ - static void initializeSystemDefaultCentury(void); }; U_NAMESPACE_END diff --git a/deps/icu-small/source/i18n/japancal.cpp b/deps/icu-small/source/i18n/japancal.cpp index a2738e86a91edb..056781617d6d9d 100644 --- a/deps/icu-small/source/i18n/japancal.cpp +++ b/deps/icu-small/source/i18n/japancal.cpp @@ -16,286 +16,88 @@ #include "unicode/utypes.h" #if !UCONFIG_NO_FORMATTING - +#if U_PLATFORM_HAS_WINUWP_API == 0 +#include // getenv() is not available in UWP env +#endif #include "cmemory.h" +#include "erarules.h" #include "japancal.h" #include "unicode/gregocal.h" #include "umutex.h" #include "uassert.h" - -//#define U_DEBUG_JCAL - -#ifdef U_DEBUG_JCAL -#include -#endif +#include "ucln_in.h" +#include "cstring.h" + +static icu::EraRules * gJapaneseEraRules = nullptr; +static icu::UInitOnce gJapaneseEraRulesInitOnce = U_INITONCE_INITIALIZER; +static int32_t gCurrentEra = 0; + +U_CDECL_BEGIN +static UBool japanese_calendar_cleanup(void) { + if (gJapaneseEraRules) { + delete gJapaneseEraRules; + gJapaneseEraRules = nullptr; + } + gCurrentEra = 0; + gJapaneseEraRulesInitOnce.reset(); + return TRUE; +} +U_CDECL_END U_NAMESPACE_BEGIN UOBJECT_DEFINE_RTTI_IMPLEMENTATION(JapaneseCalendar) -// Gregorian date of each emperor's ascension -// Years are AD, months are 1-based. -static const struct { - int16_t year; - int8_t month; - int8_t day; -} kEraInfo[] = { - // Year Month Day - { 645, 6, 19 }, // Taika 0 - { 650, 2, 15 }, // Hakuchi 1 - { 672, 1, 1 }, // Hakuho 2 - { 686, 7, 20 }, // Shucho 3 - { 701, 3, 21 }, // Taiho 4 - { 704, 5, 10 }, // Keiun 5 - { 708, 1, 11 }, // Wado 6 - { 715, 9, 2 }, // Reiki 7 - { 717, 11, 17 }, // Yoro 8 - { 724, 2, 4 }, // Jinki 9 - { 729, 8, 5 }, // Tempyo 10 - { 749, 4, 14 }, // Tempyo-kampo 11 - { 749, 7, 2 }, // Tempyo-shoho 12 - { 757, 8, 18 }, // Tempyo-hoji 13 - { 765, 1, 7 }, // Tempho-jingo 14 - { 767, 8, 16 }, // Jingo-keiun 15 - { 770, 10, 1 }, // Hoki 16 - { 781, 1, 1 }, // Ten-o 17 - { 782, 8, 19 }, // Enryaku 18 - { 806, 5, 18 }, // Daido 19 - { 810, 9, 19 }, // Konin 20 - { 824, 1, 5 }, // Tencho - { 834, 1, 3 }, // Showa - { 848, 6, 13 }, // Kajo - { 851, 4, 28 }, // Ninju - { 854, 11, 30 }, // Saiko - { 857, 2, 21 }, // Tennan - { 859, 4, 15 }, // Jogan - { 877, 4, 16 }, // Genkei - { 885, 2, 21 }, // Ninna - { 889, 4, 27 }, // Kampyo 30 - { 898, 4, 26 }, // Shotai - { 901, 7, 15 }, // Engi - { 923, 4, 11 }, // Encho - { 931, 4, 26 }, // Shohei - { 938, 5, 22 }, // Tengyo - { 947, 4, 22 }, // Tenryaku - { 957, 10, 27 }, // Tentoku - { 961, 2, 16 }, // Owa - { 964, 7, 10 }, // Koho - { 968, 8, 13 }, // Anna 40 - { 970, 3, 25 }, // Tenroku - { 973, 12, 20 }, // Ten-en - { 976, 7, 13 }, // Jogen - { 978, 11, 29 }, // Tengen - { 983, 4, 15 }, // Eikan - { 985, 4, 27 }, // Kanna - { 987, 4, 5 }, // Ei-en - { 989, 8, 8 }, // Eiso - { 990, 11, 7 }, // Shoryaku - { 995, 2, 22 }, // Chotoku 50 - { 999, 1, 13 }, // Choho - { 1004, 7, 20 }, // Kanko - { 1012, 12, 25 }, // Chowa - { 1017, 4, 23 }, // Kannin - { 1021, 2, 2 }, // Jian - { 1024, 7, 13 }, // Manju - { 1028, 7, 25 }, // Chogen - { 1037, 4, 21 }, // Choryaku - { 1040, 11, 10 }, // Chokyu - { 1044, 11, 24 }, // Kantoku 60 - { 1046, 4, 14 }, // Eisho - { 1053, 1, 11 }, // Tengi - { 1058, 8, 29 }, // Kohei - { 1065, 8, 2 }, // Jiryaku - { 1069, 4, 13 }, // Enkyu - { 1074, 8, 23 }, // Shoho - { 1077, 11, 17 }, // Shoryaku - { 1081, 2, 10 }, // Eiho - { 1084, 2, 7 }, // Otoku - { 1087, 4, 7 }, // Kanji 70 - { 1094, 12, 15 }, // Kaho - { 1096, 12, 17 }, // Eicho - { 1097, 11, 21 }, // Shotoku - { 1099, 8, 28 }, // Kowa - { 1104, 2, 10 }, // Choji - { 1106, 4, 9 }, // Kasho - { 1108, 8, 3 }, // Tennin - { 1110, 7, 13 }, // Ten-ei - { 1113, 7, 13 }, // Eikyu - { 1118, 4, 3 }, // Gen-ei 80 - { 1120, 4, 10 }, // Hoan - { 1124, 4, 3 }, // Tenji - { 1126, 1, 22 }, // Daiji - { 1131, 1, 29 }, // Tensho - { 1132, 8, 11 }, // Chosho - { 1135, 4, 27 }, // Hoen - { 1141, 7, 10 }, // Eiji - { 1142, 4, 28 }, // Koji - { 1144, 2, 23 }, // Tenyo - { 1145, 7, 22 }, // Kyuan 90 - { 1151, 1, 26 }, // Ninpei - { 1154, 10, 28 }, // Kyuju - { 1156, 4, 27 }, // Hogen - { 1159, 4, 20 }, // Heiji - { 1160, 1, 10 }, // Eiryaku - { 1161, 9, 4 }, // Oho - { 1163, 3, 29 }, // Chokan - { 1165, 6, 5 }, // Eiman - { 1166, 8, 27 }, // Nin-an - { 1169, 4, 8 }, // Kao 100 - { 1171, 4, 21 }, // Shoan - { 1175, 7, 28 }, // Angen - { 1177, 8, 4 }, // Jisho - { 1181, 7, 14 }, // Yowa - { 1182, 5, 27 }, // Juei - { 1184, 4, 16 }, // Genryuku - { 1185, 8, 14 }, // Bunji - { 1190, 4, 11 }, // Kenkyu - { 1199, 4, 27 }, // Shoji - { 1201, 2, 13 }, // Kennin 110 - { 1204, 2, 20 }, // Genkyu - { 1206, 4, 27 }, // Ken-ei - { 1207, 10, 25 }, // Shogen - { 1211, 3, 9 }, // Kenryaku - { 1213, 12, 6 }, // Kenpo - { 1219, 4, 12 }, // Shokyu - { 1222, 4, 13 }, // Joo - { 1224, 11, 20 }, // Gennin - { 1225, 4, 20 }, // Karoku - { 1227, 12, 10 }, // Antei 120 - { 1229, 3, 5 }, // Kanki - { 1232, 4, 2 }, // Joei - { 1233, 4, 15 }, // Tempuku - { 1234, 11, 5 }, // Bunryaku - { 1235, 9, 19 }, // Katei - { 1238, 11, 23 }, // Ryakunin - { 1239, 2, 7 }, // En-o - { 1240, 7, 16 }, // Ninji - { 1243, 2, 26 }, // Kangen - { 1247, 2, 28 }, // Hoji 130 - { 1249, 3, 18 }, // Kencho - { 1256, 10, 5 }, // Kogen - { 1257, 3, 14 }, // Shoka - { 1259, 3, 26 }, // Shogen - { 1260, 4, 13 }, // Bun-o - { 1261, 2, 20 }, // Kocho - { 1264, 2, 28 }, // Bun-ei - { 1275, 4, 25 }, // Kenji - { 1278, 2, 29 }, // Koan - { 1288, 4, 28 }, // Shoo 140 - { 1293, 8, 55 }, // Einin - { 1299, 4, 25 }, // Shoan - { 1302, 11, 21 }, // Kengen - { 1303, 8, 5 }, // Kagen - { 1306, 12, 14 }, // Tokuji - { 1308, 10, 9 }, // Enkei - { 1311, 4, 28 }, // Ocho - { 1312, 3, 20 }, // Showa - { 1317, 2, 3 }, // Bunpo - { 1319, 4, 28 }, // Geno 150 - { 1321, 2, 23 }, // Genkyo - { 1324, 12, 9 }, // Shochu - { 1326, 4, 26 }, // Kareki - { 1329, 8, 29 }, // Gentoku - { 1331, 8, 9 }, // Genko - { 1334, 1, 29 }, // Kemmu - { 1336, 2, 29 }, // Engen - { 1340, 4, 28 }, // Kokoku - { 1346, 12, 8 }, // Shohei - { 1370, 7, 24 }, // Kentoku 160 - { 1372, 4, 1 }, // Bunch\u0169 - { 1375, 5, 27 }, // Tenju - { 1379, 3, 22 }, // Koryaku - { 1381, 2, 10 }, // Kowa - { 1384, 4, 28 }, // Gench\u0169 - { 1384, 2, 27 }, // Meitoku - { 1387, 8, 23 }, // Kakei - { 1389, 2, 9 }, // Koo - { 1390, 3, 26 }, // Meitoku - { 1394, 7, 5 }, // Oei 170 - { 1428, 4, 27 }, // Shocho - { 1429, 9, 5 }, // Eikyo - { 1441, 2, 17 }, // Kakitsu - { 1444, 2, 5 }, // Bun-an - { 1449, 7, 28 }, // Hotoku - { 1452, 7, 25 }, // Kyotoku - { 1455, 7, 25 }, // Kosho - { 1457, 9, 28 }, // Choroku - { 1460, 12, 21 }, // Kansho - { 1466, 2, 28 }, // Bunsho 180 - { 1467, 3, 3 }, // Onin - { 1469, 4, 28 }, // Bunmei - { 1487, 7, 29 }, // Chokyo - { 1489, 8, 21 }, // Entoku - { 1492, 7, 19 }, // Meio - { 1501, 2, 29 }, // Bunki - { 1504, 2, 30 }, // Eisho - { 1521, 8, 23 }, // Taiei - { 1528, 8, 20 }, // Kyoroku - { 1532, 7, 29 }, // Tenmon 190 - { 1555, 10, 23 }, // Koji - { 1558, 2, 28 }, // Eiroku - { 1570, 4, 23 }, // Genki - { 1573, 7, 28 }, // Tensho - { 1592, 12, 8 }, // Bunroku - { 1596, 10, 27 }, // Keicho - { 1615, 7, 13 }, // Genwa - { 1624, 2, 30 }, // Kan-ei - { 1644, 12, 16 }, // Shoho - { 1648, 2, 15 }, // Keian 200 - { 1652, 9, 18 }, // Shoo - { 1655, 4, 13 }, // Meiryaku - { 1658, 7, 23 }, // Manji - { 1661, 4, 25 }, // Kanbun - { 1673, 9, 21 }, // Enpo - { 1681, 9, 29 }, // Tenwa - { 1684, 2, 21 }, // Jokyo - { 1688, 9, 30 }, // Genroku - { 1704, 3, 13 }, // Hoei - { 1711, 4, 25 }, // Shotoku 210 - { 1716, 6, 22 }, // Kyoho - { 1736, 4, 28 }, // Genbun - { 1741, 2, 27 }, // Kanpo - { 1744, 2, 21 }, // Enkyo - { 1748, 7, 12 }, // Kan-en - { 1751, 10, 27 }, // Horyaku - { 1764, 6, 2 }, // Meiwa - { 1772, 11, 16 }, // An-ei - { 1781, 4, 2 }, // Tenmei - { 1789, 1, 25 }, // Kansei 220 - { 1801, 2, 5 }, // Kyowa - { 1804, 2, 11 }, // Bunka - { 1818, 4, 22 }, // Bunsei - { 1830, 12, 10 }, // Tenpo - { 1844, 12, 2 }, // Koka - { 1848, 2, 28 }, // Kaei - { 1854, 11, 27 }, // Ansei - { 1860, 3, 18 }, // Man-en - { 1861, 2, 19 }, // Bunkyu - { 1864, 2, 20 }, // Genji 230 - { 1865, 4, 7 }, // Keio 231 - { 1868, 9, 8 }, // Meiji 232 - { 1912, 7, 30 }, // Taisho 233 - { 1926, 12, 25 }, // Showa 234 - { 1989, 1, 8 } // Heisei 235 -}; - -#define kEraCount UPRV_LENGTHOF(kEraInfo) - -/** - * The current era, for reference. - */ -static const int32_t kCurrentEra = (kEraCount-1); // int32_t to match the calendar field type - static const int32_t kGregorianEpoch = 1970; // used as the default value of EXTENDED_YEAR +static const char* TENTATIVE_ERA_VAR_NAME = "ICU_ENABLE_TENTATIVE_ERA"; + +// Initialize global Japanese era data +static void U_CALLCONV initializeEras(UErrorCode &status) { + // Although start date of next Japanese era is planned ahead, a name of + // new era might not be available. This implementation allows tester to + // check a new era without era names by settings below (in priority order). + // By default, such tentative era is disabled. + + // 1. Environment variable ICU_ENABLE_TENTATIVE_ERA=true or false + + UBool includeTentativeEra = FALSE; + +#if U_PLATFORM_HAS_WINUWP_API == 1 + // UWP doesn't allow access to getenv(), but we can call GetEnvironmentVariableW to do the same thing. + UChar varName[26] = {}; + u_charsToUChars(TENTATIVE_ERA_VAR_NAME, varName, static_cast(uprv_strlen(TENTATIVE_ERA_VAR_NAME))); + WCHAR varValue[5] = {}; + DWORD ret = GetEnvironmentVariableW(reinterpret_cast(varName), varValue, UPRV_LENGTHOF(varValue)); + if ((ret == 4) && (_wcsicmp(varValue, L"true") == 0)) { + includeTentativeEra = TRUE; + } +#else + char *envVarVal = getenv(TENTATIVE_ERA_VAR_NAME); + if (envVarVal != NULL && uprv_stricmp(envVarVal, "true") == 0) { + includeTentativeEra = TRUE; + } +#endif + gJapaneseEraRules = EraRules::createInstance("japanese", includeTentativeEra, status); + if (U_FAILURE(status)) { + return; + } + gCurrentEra = gJapaneseEraRules->getCurrentEraIndex(); +} + +static void init(UErrorCode &status) { + umtx_initOnce(gJapaneseEraRulesInitOnce, &initializeEras, status); + ucln_i18n_registerCleanup(UCLN_I18N_JAPANESE_CALENDAR, japanese_calendar_cleanup); +} /* Some platforms don't like to export constants, like old Palm OS and some z/OS configurations. */ uint32_t JapaneseCalendar::getCurrentEra() { - return kCurrentEra; + return gCurrentEra; } JapaneseCalendar::JapaneseCalendar(const Locale& aLocale, UErrorCode& success) : GregorianCalendar(aLocale, success) { + init(success); setTimeInMillis(getNow(), success); // Call this again now that the vtable is set up properly. } @@ -306,6 +108,9 @@ JapaneseCalendar::~JapaneseCalendar() JapaneseCalendar::JapaneseCalendar(const JapaneseCalendar& source) : GregorianCalendar(source) { + UErrorCode status = U_ZERO_ERROR; + init(status); + U_ASSERT(U_SUCCESS(status)); } JapaneseCalendar& JapaneseCalendar::operator= ( const JapaneseCalendar& right) @@ -332,10 +137,14 @@ int32_t JapaneseCalendar::getDefaultMonthInYear(int32_t eyear) int32_t month = 0; // Find out if we are at the edge of an era - - if(eyear == kEraInfo[era].year) { + int32_t eraStart[3] = { 0,0,0 }; + UErrorCode status = U_ZERO_ERROR; + gJapaneseEraRules->getStartDate(era, eraStart, status); + U_ASSERT(U_SUCCESS(status)); + if(eyear == eraStart[0]) { // Yes, we're in the first year of this era. - return kEraInfo[era].month-1; + return eraStart[1] // month + -1; // return 0-based month } return month; @@ -346,9 +155,13 @@ int32_t JapaneseCalendar::getDefaultDayInMonth(int32_t eyear, int32_t month) int32_t era = internalGetEra(); int32_t day = 1; - if(eyear == kEraInfo[era].year) { - if(month == (kEraInfo[era].month-1)) { - return kEraInfo[era].day; + int32_t eraStart[3] = { 0,0,0 }; + UErrorCode status = U_ZERO_ERROR; + gJapaneseEraRules->getStartDate(era, eraStart, status); + U_ASSERT(U_SUCCESS(status)); + if(eyear == eraStart[0]) { + if(month == eraStart[1] - 1) { + return eraStart[2]; } } @@ -358,7 +171,7 @@ int32_t JapaneseCalendar::getDefaultDayInMonth(int32_t eyear, int32_t month) int32_t JapaneseCalendar::internalGetEra() const { - return internalGet(UCAL_ERA, kCurrentEra); + return internalGet(UCAL_ERA, gCurrentEra); } int32_t JapaneseCalendar::handleGetExtendedYear() @@ -369,12 +182,18 @@ int32_t JapaneseCalendar::handleGetExtendedYear() if (newerField(UCAL_EXTENDED_YEAR, UCAL_YEAR) == UCAL_EXTENDED_YEAR && newerField(UCAL_EXTENDED_YEAR, UCAL_ERA) == UCAL_EXTENDED_YEAR) { - year = internalGet(UCAL_EXTENDED_YEAR, kGregorianEpoch); - } else { - // Subtract one because year starts at 1 - year = internalGet(UCAL_YEAR) + kEraInfo[internalGetEra()].year - 1; - } - return year; + year = internalGet(UCAL_EXTENDED_YEAR, kGregorianEpoch); + } else { + UErrorCode status = U_ZERO_ERROR; + int32_t eraStartYear = gJapaneseEraRules->getStartYear(internalGet(UCAL_ERA, gCurrentEra), status); + U_ASSERT(U_SUCCESS(status)); + + // extended year is a gregorian year, where 1 = 1AD, 0 = 1BC, -1 = 2BC, etc + year = internalGet(UCAL_YEAR, 1) // pin to minimum of year 1 (first year) + + eraStartYear // add gregorian starting year + - 1; // Subtract one because year starts at 1 + } + return year; } @@ -383,79 +202,10 @@ void JapaneseCalendar::handleComputeFields(int32_t julianDay, UErrorCode& status //Calendar::timeToFields(theTime, quick, status); GregorianCalendar::handleComputeFields(julianDay, status); int32_t year = internalGet(UCAL_EXTENDED_YEAR); // Gregorian year + int32_t eraIdx = gJapaneseEraRules->getEraIndex(year, internalGet(UCAL_MONTH) + 1, internalGet(UCAL_DAY_OF_MONTH), status); - int32_t low = 0; - - // Short circuit for recent years. Most modern computations will - // occur in the current era and won't require the binary search. - // Note that if the year is == the current era year, then we use - // the binary search to handle the month/dom comparison. -#ifdef U_DEBUG_JCAL - fprintf(stderr, "== %d \n", year); -#endif - - if (year > kEraInfo[kCurrentEra].year) { - low = kCurrentEra; -#ifdef U_DEBUG_JCAL - fprintf(stderr, " low=%d (special)\n", low); -#endif - } else { - // Binary search - int32_t high = kEraCount; - -#ifdef U_DEBUG_JCAL - fprintf(stderr, " high=%d\n", high); -#endif - while (low < high - 1) { - int32_t i = (low + high) / 2; - int32_t diff = year - kEraInfo[i].year; - -#ifdef U_DEBUG_JCAL - fprintf(stderr, " d=%d low=%d, high=%d. Considering %d:M%d D%d Y%d. { we are ?:M%d D%d Y%d }\n", - diff,low, high, i, kEraInfo[i].month-1, kEraInfo[i].day, kEraInfo[i].year, internalGet(UCAL_MONTH), internalGet(UCAL_DATE),year); -#endif - - // If years are the same, then compare the months, and if those - // are the same, compare days of month. In the ERAS array - // months are 1-based for easier maintenance. - if (diff == 0) { - diff = internalGet(UCAL_MONTH) - (kEraInfo[i].month - 1); -#ifdef U_DEBUG_JCAL - fprintf(stderr, "diff now %d (M) = %d - %d - 1\n", diff, internalGet(UCAL_MONTH), kEraInfo[i].month); -#endif - if (diff == 0) { - diff = internalGet(UCAL_DATE) - kEraInfo[i].day; -#ifdef U_DEBUG_JCAL - fprintf(stderr, "diff now %d (D)\n", diff); -#endif - } - } - if (diff >= 0) { - low = i; - } else { - high = i; - } -#ifdef U_DEBUG_JCAL - fprintf(stderr, ". low=%d, high=%d, i=%d, diff=%d.. %d\n", low, high, i, diff, year); -#endif - - } - } - -#ifdef U_DEBUG_JCAL - fprintf(stderr, " low[era]=%d,.. %d\n", low, year); -#endif - // Now we've found the last era that starts before this date, so - // adjust the year to count from the start of that era. Note that - // all dates before the first era will fall into the first era by - // the algorithm. - - internalSet(UCAL_ERA, low); - internalSet(UCAL_YEAR, year - kEraInfo[low].year + 1); -#ifdef U_DEBUG_JCAL - fprintf(stderr, " Set ERA=%d, year=%d\n", low, year-kEraInfo[low].year+1); -#endif - + internalSet(UCAL_ERA, eraIdx); + internalSet(UCAL_YEAR, year - gJapaneseEraRules->getStartYear(eraIdx, status) + 1); } /* @@ -483,7 +233,7 @@ int32_t JapaneseCalendar::handleGetLimit(UCalendarDateFields field, ELimitType l if (limitType == UCAL_LIMIT_MINIMUM || limitType == UCAL_LIMIT_GREATEST_MINIMUM) { return 0; } - return kCurrentEra; + return gCurrentEra; case UCAL_YEAR: { switch (limitType) { @@ -494,7 +244,12 @@ int32_t JapaneseCalendar::handleGetLimit(UCalendarDateFields field, ELimitType l return 1; case UCAL_LIMIT_COUNT: //added to avoid warning case UCAL_LIMIT_MAXIMUM: - return GregorianCalendar::handleGetLimit(UCAL_YEAR, UCAL_LIMIT_MAXIMUM) - kEraInfo[kCurrentEra].year; + { + UErrorCode status = U_ZERO_ERROR; + int32_t eraStartYear = gJapaneseEraRules->getStartYear(gCurrentEra, status); + U_ASSERT(U_SUCCESS(status)); + return GregorianCalendar::handleGetLimit(UCAL_YEAR, UCAL_LIMIT_MAXIMUM) - eraStartYear; + } default: return 1; // Error condition, invalid limitType } @@ -510,15 +265,18 @@ int32_t JapaneseCalendar::getActualMaximum(UCalendarDateFields field, UErrorCode if (U_FAILURE(status)) { return 0; // error case... any value } - if (era == kCurrentEra) { + if (era == gCurrentEra) { // TODO: Investigate what value should be used here - revisit after 4.0. return handleGetLimit(UCAL_YEAR, UCAL_LIMIT_MAXIMUM); } else { - int32_t nextEraYear = kEraInfo[era + 1].year; - int32_t nextEraMonth = kEraInfo[era + 1].month; - int32_t nextEraDate = kEraInfo[era + 1].day; - - int32_t maxYear = nextEraYear - kEraInfo[era].year + 1; // 1-base + int32_t nextEraStart[3] = { 0,0,0 }; + gJapaneseEraRules->getStartDate(era + 1, nextEraStart, status); + int32_t nextEraYear = nextEraStart[0]; + int32_t nextEraMonth = nextEraStart[1]; // 1-base + int32_t nextEraDate = nextEraStart[2]; + + int32_t eraStartYear = gJapaneseEraRules->getStartYear(era, status); + int32_t maxYear = nextEraYear - eraStartYear + 1; // 1-base if (nextEraMonth == 1 && nextEraDate == 1) { // Subtract 1, because the next era starts at Jan 1 maxYear--; diff --git a/deps/icu-small/source/i18n/japancal.h b/deps/icu-small/source/i18n/japancal.h index 356351d28dd28a..67d2d7031526a2 100644 --- a/deps/icu-small/source/i18n/japancal.h +++ b/deps/icu-small/source/i18n/japancal.h @@ -49,10 +49,18 @@ U_NAMESPACE_BEGIN * July 30, 1912 (Taisho), December 25, 1926 (Showa), and January 7, 1989 (Heisei). Constants * for these eras, suitable for use in the UCAL_ERA field, are provided * in this class. Note that the number used for each era is more or - * less arbitrary. Currently, the era starting in 1053 AD is era #0; however this - * may change in the future as we add more historical data. Use the predefined - * constants rather than using actual, absolute numbers. + * less arbitrary. Currently, the era starting in 645 AD is era #0; however this + * may change in the future. Use the predefined constants rather than using actual, + * absolute numbers. *

+ * Since ICU4C 63, start date of each era is imported from CLDR. CLDR era data + * may contain tentative era in near future with placeholder names. By default, + * such era data is not enabled. ICU4C users who want to test the behavior of + * the future era can enable this one of following settings (in the priority + * order): + *

    + *
  1. Environment variable ICU_ENABLE_TENTATIVE_ERA=true.
  2. + * * @internal */ class JapaneseCalendar : public GregorianCalendar { diff --git a/deps/icu-small/source/common/listformatter.cpp b/deps/icu-small/source/i18n/listformatter.cpp similarity index 71% rename from deps/icu-small/source/common/listformatter.cpp rename to deps/icu-small/source/i18n/listformatter.cpp index 33a8ac28671fc6..d9195348529c57 100644 --- a/deps/icu-small/source/common/listformatter.cpp +++ b/deps/icu-small/source/i18n/listformatter.cpp @@ -16,14 +16,19 @@ * created by: Umesh P. Nair */ +#include "cmemory.h" +#include "unicode/fpositer.h" // FieldPositionIterator #include "unicode/listformatter.h" #include "unicode/simpleformatter.h" +#include "unicode/ulistformatter.h" +#include "fphdlimp.h" #include "mutex.h" #include "hash.h" #include "cstring.h" +#include "uarrsort.h" #include "ulocimp.h" #include "charstr.h" -#include "ucln_cmn.h" +#include "ucln_in.h" #include "uresimp.h" #include "resource.h" @@ -61,14 +66,14 @@ ListFormatInternal(const ListFormatInternal &other) : -static Hashtable* listPatternHash = NULL; +static Hashtable* listPatternHash = nullptr; static UMutex listFormatterMutex = U_MUTEX_INITIALIZER; static const char STANDARD_STYLE[] = "standard"; U_CDECL_BEGIN static UBool U_CALLCONV uprv_listformatter_cleanup() { delete listPatternHash; - listPatternHash = NULL; + listPatternHash = nullptr; return TRUE; } @@ -81,7 +86,7 @@ U_CDECL_END ListFormatter::ListFormatter(const ListFormatter& other) : owned(other.owned), data(other.data) { - if (other.owned != NULL) { + if (other.owned != nullptr) { owned = new ListFormatInternal(*other.owned); data = owned; } @@ -96,7 +101,7 @@ ListFormatter& ListFormatter::operator=(const ListFormatter& other) { owned = new ListFormatInternal(*other.owned); data = owned; } else { - owned = NULL; + owned = nullptr; data = other.data; } return *this; @@ -108,53 +113,53 @@ void ListFormatter::initializeHash(UErrorCode& errorCode) { } listPatternHash = new Hashtable(); - if (listPatternHash == NULL) { + if (listPatternHash == nullptr) { errorCode = U_MEMORY_ALLOCATION_ERROR; return; } listPatternHash->setValueDeleter(uprv_deleteListFormatInternal); - ucln_common_registerCleanup(UCLN_COMMON_LIST_FORMATTER, uprv_listformatter_cleanup); + ucln_i18n_registerCleanup(UCLN_I18N_LIST_FORMATTER, uprv_listformatter_cleanup); } const ListFormatInternal* ListFormatter::getListFormatInternal( const Locale& locale, const char *style, UErrorCode& errorCode) { if (U_FAILURE(errorCode)) { - return NULL; + return nullptr; } CharString keyBuffer(locale.getName(), errorCode); keyBuffer.append(':', errorCode).append(style, errorCode); UnicodeString key(keyBuffer.data(), -1, US_INV); - ListFormatInternal* result = NULL; + ListFormatInternal* result = nullptr; { Mutex m(&listFormatterMutex); - if (listPatternHash == NULL) { + if (listPatternHash == nullptr) { initializeHash(errorCode); if (U_FAILURE(errorCode)) { - return NULL; + return nullptr; } } result = static_cast(listPatternHash->get(key)); } - if (result != NULL) { + if (result != nullptr) { return result; } result = loadListFormatInternal(locale, style, errorCode); if (U_FAILURE(errorCode)) { - return NULL; + return nullptr; } { Mutex m(&listFormatterMutex); ListFormatInternal* temp = static_cast(listPatternHash->get(key)); - if (temp != NULL) { + if (temp != nullptr) { delete result; result = temp; } else { listPatternHash->put(key, result, errorCode); if (U_FAILURE(errorCode)) { - return NULL; + return nullptr; } } } @@ -235,11 +240,11 @@ ListFormatter::ListPatternsSink::~ListPatternsSink() {} ListFormatInternal* ListFormatter::loadListFormatInternal( const Locale& locale, const char * style, UErrorCode& errorCode) { - UResourceBundle* rb = ures_open(NULL, locale.getName(), &errorCode); + UResourceBundle* rb = ures_open(nullptr, locale.getName(), &errorCode); rb = ures_getByKeyWithFallback(rb, "listPattern", rb, &errorCode); if (U_FAILURE(errorCode)) { ures_close(rb); - return NULL; + return nullptr; } ListFormatter::ListPatternsSink sink; char currentStyle[kStyleLenMax+1]; @@ -255,20 +260,20 @@ ListFormatInternal* ListFormatter::loadListFormatInternal( } ures_close(rb); if (U_FAILURE(errorCode)) { - return NULL; + return nullptr; } if (sink.two.isEmpty() || sink.start.isEmpty() || sink.middle.isEmpty() || sink.end.isEmpty()) { errorCode = U_MISSING_RESOURCE_ERROR; - return NULL; + return nullptr; } ListFormatInternal* result = new ListFormatInternal(sink.two, sink.start, sink.middle, sink.end, errorCode); - if (result == NULL) { + if (result == nullptr) { errorCode = U_MEMORY_ALLOCATION_ERROR; - return NULL; + return nullptr; } if (U_FAILURE(errorCode)) { delete result; - return NULL; + return nullptr; } return result; } @@ -283,15 +288,14 @@ ListFormatter* ListFormatter::createInstance(const Locale& locale, UErrorCode& e } ListFormatter* ListFormatter::createInstance(const Locale& locale, const char *style, UErrorCode& errorCode) { - Locale tempLocale = locale; - const ListFormatInternal* listFormatInternal = getListFormatInternal(tempLocale, style, errorCode); + const ListFormatInternal* listFormatInternal = getListFormatInternal(locale, style, errorCode); if (U_FAILURE(errorCode)) { - return NULL; + return nullptr; } ListFormatter* p = new ListFormatter(listFormatInternal); - if (p == NULL) { + if (p == nullptr) { errorCode = U_MEMORY_ALLOCATION_ERROR; - return NULL; + return nullptr; } return p; } @@ -301,7 +305,7 @@ ListFormatter::ListFormatter(const ListFormatData& listFormatData, UErrorCode &e data = owned; } -ListFormatter::ListFormatter(const ListFormatInternal* listFormatterInternal) : owned(NULL), data(listFormatterInternal) { +ListFormatter::ListFormatter(const ListFormatInternal* listFormatterInternal) : owned(nullptr), data(listFormatterInternal) { } ListFormatter::~ListFormatter() { @@ -323,6 +327,8 @@ static void joinStringsAndReplace( UnicodeString &result, UBool recordOffset, int32_t &offset, + int32_t *offsetFirst, + int32_t *offsetSecond, UErrorCode& errorCode) { if (U_FAILURE(errorCode)) { return; @@ -348,6 +354,8 @@ static void joinStringsAndReplace( } else if (offset >= 0) { offset += offsets[0]; } + if (offsetFirst != nullptr) *offsetFirst = offsets[0]; + if (offsetSecond != nullptr) *offsetSecond = offsets[1]; } UnicodeString& ListFormatter::format( @@ -359,6 +367,19 @@ UnicodeString& ListFormatter::format( return format(items, nItems, appendTo, -1, offset, errorCode); } +#if !UCONFIG_NO_FORMATTING +UnicodeString& ListFormatter::format( + const UnicodeString items[], + int32_t nItems, + UnicodeString & appendTo, + FieldPositionIterator* posIter, + UErrorCode& errorCode) const { + int32_t offset; + FieldPositionIteratorHandler handler(posIter, errorCode); + return format_(items, nItems, appendTo, -1, offset, &handler, errorCode); +}; +#endif + UnicodeString& ListFormatter::format( const UnicodeString items[], int32_t nItems, @@ -366,11 +387,23 @@ UnicodeString& ListFormatter::format( int32_t index, int32_t &offset, UErrorCode& errorCode) const { + return format_(items, nItems, appendTo, index, offset, nullptr, errorCode); +} + +UnicodeString& ListFormatter::format_( + const UnicodeString items[], + int32_t nItems, + UnicodeString& appendTo, + int32_t index, + int32_t &offset, + FieldPositionHandler* handler, + UErrorCode& errorCode) const { +#if !UCONFIG_NO_FORMATTING offset = -1; if (U_FAILURE(errorCode)) { return appendTo; } - if (data == NULL) { + if (data == nullptr) { errorCode = U_INVALID_STATE_ERROR; return appendTo; } @@ -382,6 +415,11 @@ UnicodeString& ListFormatter::format( if (index == 0) { offset = appendTo.length(); } + if (handler != nullptr) { + handler->addAttribute(ULISTFMT_ELEMENT_FIELD, + appendTo.length(), + appendTo.length() + items[0].length()); + } appendTo.append(items[0]); return appendTo; } @@ -389,6 +427,12 @@ UnicodeString& ListFormatter::format( if (index == 0) { offset = 0; } + int32_t offsetFirst; + int32_t offsetSecond; + int32_t prefixLength = 0; + // for n items, there are 2 * (n + 1) boundary including 0 and the upper + // edge. + MaybeStackArray offsets((handler != nullptr) ? 2 * (nItems + 1): 0); joinStringsAndReplace( nItems == 2 ? data->twoPattern : data->startPattern, result, @@ -396,7 +440,14 @@ UnicodeString& ListFormatter::format( result, index == 1, offset, + &offsetFirst, + &offsetSecond, errorCode); + if (handler != nullptr) { + offsets[0] = 0; + prefixLength += offsetFirst; + offsets[1] = offsetSecond - prefixLength; + } if (nItems > 2) { for (int32_t i = 2; i < nItems - 1; ++i) { joinStringsAndReplace( @@ -406,7 +457,13 @@ UnicodeString& ListFormatter::format( result, index == i, offset, + &offsetFirst, + &offsetSecond, errorCode); + if (handler != nullptr) { + prefixLength += offsetFirst; + offsets[i] = offsetSecond - prefixLength; + } } joinStringsAndReplace( data->endPattern, @@ -415,7 +472,45 @@ UnicodeString& ListFormatter::format( result, index == nItems - 1, offset, + &offsetFirst, + &offsetSecond, errorCode); + if (handler != nullptr) { + prefixLength += offsetFirst; + offsets[nItems - 1] = offsetSecond - prefixLength; + } + } + if (handler != nullptr) { + // If there are already some data in appendTo, we need to adjust the index + // by shifting that lenght while insert into handler. + int32_t shift = appendTo.length() + prefixLength; + // Output the ULISTFMT_ELEMENT_FIELD in the order of the input elements + for (int32_t i = 0; i < nItems; ++i) { + offsets[i + nItems] = offsets[i] + items[i].length() + shift; + offsets[i] += shift; + handler->addAttribute( + ULISTFMT_ELEMENT_FIELD, // id + offsets[i], // index + offsets[i + nItems]); // limit + } + // The locale pattern may reorder the items (such as in ur-IN locale), + // so we cannot assume the array is in accendning order. + // To handle the edging case, just insert the two ends into the array + // and sort. Then we output ULISTFMT_LITERAL_FIELD if the indecies + // between the even and odd position are not the same in the sorted array. + offsets[2 * nItems] = shift - prefixLength; + offsets[2 * nItems + 1] = result.length() + shift - prefixLength; + uprv_sortArray(offsets.getAlias(), 2 * (nItems + 1), sizeof(int32_t), + uprv_int32Comparator, nullptr, + false, &errorCode); + for (int32_t i = 0; i <= nItems; ++i) { + if (offsets[i * 2] != offsets[i * 2 + 1]) { + handler->addAttribute( + ULISTFMT_LITERAL_FIELD, // id + offsets[i * 2], // index + offsets[i * 2 + 1]); // limit + } + } } if (U_SUCCESS(errorCode)) { if (offset >= 0) { @@ -423,6 +518,7 @@ UnicodeString& ListFormatter::format( } appendTo += result; } +#endif return appendTo; } diff --git a/deps/icu-small/source/i18n/measfmt.cpp b/deps/icu-small/source/i18n/measfmt.cpp index 996a20c2e043e8..03974ff4b74048 100644 --- a/deps/icu-small/source/i18n/measfmt.cpp +++ b/deps/icu-small/source/i18n/measfmt.cpp @@ -47,7 +47,7 @@ U_NAMESPACE_BEGIN static constexpr int32_t PER_UNIT_INDEX = StandardPlural::COUNT; static constexpr int32_t PATTERN_COUNT = PER_UNIT_INDEX + 1; -static constexpr int32_t MEAS_UNIT_COUNT = 138; // see assertion in MeasureFormatCacheData constructor +static constexpr int32_t MEAS_UNIT_COUNT = 142; // see assertion in MeasureFormatCacheData constructor static constexpr int32_t WIDTH_INDEX_COUNT = UMEASFMT_WIDTH_NARROW + 1; UOBJECT_DEFINE_RTTI_IMPLEMENTATION(MeasureFormat) @@ -618,7 +618,7 @@ MeasureFormat::MeasureFormat( : cache(NULL), numberFormat(NULL), pluralRules(NULL), - width(w), + fWidth(w), listFormatter(NULL) { initMeasureFormat(locale, w, NULL, status); } @@ -631,7 +631,7 @@ MeasureFormat::MeasureFormat( : cache(NULL), numberFormat(NULL), pluralRules(NULL), - width(w), + fWidth(w), listFormatter(NULL) { initMeasureFormat(locale, w, nfToAdopt, status); } @@ -641,7 +641,7 @@ MeasureFormat::MeasureFormat(const MeasureFormat &other) : cache(other.cache), numberFormat(other.numberFormat), pluralRules(other.pluralRules), - width(other.width), + fWidth(other.fWidth), listFormatter(NULL) { cache->addRef(); numberFormat->addRef(); @@ -659,7 +659,7 @@ MeasureFormat &MeasureFormat::operator=(const MeasureFormat &other) { SharedObject::copyPtr(other.cache, cache); SharedObject::copyPtr(other.numberFormat, numberFormat); SharedObject::copyPtr(other.pluralRules, pluralRules); - width = other.width; + fWidth = other.fWidth; delete listFormatter; if (other.listFormatter != NULL) { listFormatter = new ListFormatter(*other.listFormatter); @@ -673,7 +673,7 @@ MeasureFormat::MeasureFormat() : cache(NULL), numberFormat(NULL), pluralRules(NULL), - width(UMEASFMT_WIDTH_SHORT), + fWidth(UMEASFMT_WIDTH_SHORT), listFormatter(NULL) { } @@ -703,7 +703,7 @@ UBool MeasureFormat::operator==(const Format &other) const { // don't have to check it here. // differing widths aren't equivalent - if (width != rhs.width) { + if (fWidth != rhs.fWidth) { return FALSE; } // Width the same check locales. @@ -805,7 +805,7 @@ UnicodeString &MeasureFormat::formatMeasures( if (measureCount == 1) { return formatMeasure(measures[0], **numberFormat, appendTo, pos, status); } - if (width == UMEASFMT_WIDTH_NUMERIC) { + if (fWidth == UMEASFMT_WIDTH_NUMERIC) { Formattable hms[3]; int32_t bitMap = toHMS(measures, measureCount, hms, status); if (bitMap > 0) { @@ -839,7 +839,7 @@ UnicodeString &MeasureFormat::formatMeasures( } UnicodeString MeasureFormat::getUnitDisplayName(const MeasureUnit& unit, UErrorCode& /*status*/) const { - UMeasureFormatWidth width = getRegularWidth(this->width); + UMeasureFormatWidth width = getRegularWidth(fWidth); const UChar* const* styleToDnam = cache->dnams[unit.getIndex()]; const UChar* dnam = styleToDnam[width]; if (dnam == NULL) { @@ -895,11 +895,11 @@ void MeasureFormat::initMeasureFormat( return; } } - width = w; + fWidth = w; delete listFormatter; listFormatter = ListFormatter::createInstance( locale, - listStyles[getRegularWidth(width)], + listStyles[getRegularWidth(fWidth)], status); } @@ -922,7 +922,7 @@ UBool MeasureFormat::setMeasureFormatLocale(const Locale &locale, UErrorCode &st if (U_FAILURE(status) || locale == getLocale(status)) { return FALSE; } - initMeasureFormat(locale, width, NULL, status); + initMeasureFormat(locale, fWidth, NULL, status); return U_SUCCESS(status); } @@ -956,7 +956,7 @@ UnicodeString &MeasureFormat::formatMeasure( if (isCurrency(amtUnit)) { UChar isoCode[4]; u_charsToUChars(amtUnit.getSubtype(), isoCode, 4); - return cache->getCurrencyFormat(width)->format( + return cache->getCurrencyFormat(fWidth)->format( new CurrencyAmount(amtNumber, isoCode, status), appendTo, pos, @@ -965,7 +965,7 @@ UnicodeString &MeasureFormat::formatMeasure( UnicodeString formattedNumber; StandardPlural::Form pluralForm = QuantityFormatter::selectPlural( amtNumber, nf, **pluralRules, formattedNumber, pos, status); - const SimpleFormatter *formatter = getPluralFormatter(amtUnit, width, pluralForm, status); + const SimpleFormatter *formatter = getPluralFormatter(amtUnit, fWidth, pluralForm, status); return QuantityFormatter::format(*formatter, formattedNumber, appendTo, pos, status); } @@ -1016,7 +1016,6 @@ UnicodeString &MeasureFormat::formatNumeric( return appendTo; break; } - return appendTo; } static void appendRange( @@ -1173,7 +1172,7 @@ int32_t MeasureFormat::withPerUnitAndAppend( if (U_FAILURE(status)) { return offset; } - const SimpleFormatter *perUnitFormatter = getFormatterOrNull(perUnit, width, PER_UNIT_INDEX); + const SimpleFormatter *perUnitFormatter = getFormatterOrNull(perUnit, fWidth, PER_UNIT_INDEX); if (perUnitFormatter != NULL) { const UnicodeString *params[] = {&formatted}; perUnitFormatter->formatAndAppend( @@ -1185,9 +1184,9 @@ int32_t MeasureFormat::withPerUnitAndAppend( status); return offset; } - const SimpleFormatter *perFormatter = getPerFormatter(width, status); + const SimpleFormatter *perFormatter = getPerFormatter(fWidth, status); const SimpleFormatter *pattern = - getPluralFormatter(perUnit, width, StandardPlural::ONE, status); + getPluralFormatter(perUnit, fWidth, StandardPlural::ONE, status); if (U_FAILURE(status)) { return offset; } diff --git a/deps/icu-small/source/i18n/measunit.cpp b/deps/icu-small/source/i18n/measunit.cpp index dc156aa720aae0..f6059f8c6dc808 100644 --- a/deps/icu-small/source/i18n/measunit.cpp +++ b/deps/icu-small/source/i18n/measunit.cpp @@ -39,23 +39,23 @@ static const int32_t gOffsets[] = { 2, 7, 16, - 20, - 24, - 321, - 331, - 342, - 346, - 352, - 356, - 376, - 377, - 388, - 391, - 397, + 22, + 26, + 325, + 336, + 347, + 351, + 357, + 361, + 381, + 382, + 393, + 396, 402, - 406, - 410, - 435 + 408, + 412, + 416, + 441 }; static const int32_t gIndexes[] = { @@ -63,23 +63,23 @@ static const int32_t gIndexes[] = { 2, 7, 16, - 20, - 24, - 24, - 34, - 45, - 49, - 55, - 59, - 79, - 80, - 91, + 22, + 26, + 26, + 37, + 48, + 52, + 58, + 62, + 82, + 83, 94, - 100, - 105, + 97, + 103, 109, 113, - 138 + 117, + 142 }; // Must be sorted alphabetically. @@ -128,6 +128,8 @@ static const char * const gSubTypes[] = { "milligram-per-deciliter", "millimole-per-liter", "part-per-million", + "percent", + "permille", "liter-per-100kilometers", "liter-per-kilometer", "mile-per-gallon", @@ -388,9 +390,11 @@ static const char * const gSubTypes[] = { "UYN", "UYP", "UYU", + "UYW", "UZS", "VEB", "VEF", + "VES", "VNC", "VND", "VUV", @@ -437,6 +441,7 @@ static const char * const gSubTypes[] = { "kilobyte", "megabit", "megabyte", + "petabyte", "terabit", "terabyte", "century", @@ -505,6 +510,7 @@ static const char * const gSubTypes[] = { "megawatt", "milliwatt", "watt", + "atmosphere", "hectopascal", "inch-hg", "millibar", @@ -547,14 +553,14 @@ static const char * const gSubTypes[] = { // Must be sorted by first value and then second value. static int32_t unitPerUnitToSingleUnit[][4] = { - {363, 333, 17, 0}, - {365, 339, 17, 2}, - {367, 333, 17, 3}, - {367, 424, 4, 2}, - {367, 425, 4, 3}, - {382, 422, 3, 1}, - {385, 11, 16, 4}, - {427, 363, 4, 1} + {368, 338, 17, 0}, + {370, 344, 17, 2}, + {372, 338, 17, 3}, + {372, 430, 4, 2}, + {372, 431, 4, 3}, + {387, 428, 3, 1}, + {390, 11, 16, 5}, + {433, 368, 4, 1} }; // Shortcuts to the base unit in order to make the default constructor fast @@ -641,6 +647,14 @@ MeasureUnit *MeasureUnit::createPartPerMillion(UErrorCode &status) { return MeasureUnit::create(3, 3, status); } +MeasureUnit *MeasureUnit::createPercent(UErrorCode &status) { + return MeasureUnit::create(3, 4, status); +} + +MeasureUnit *MeasureUnit::createPermille(UErrorCode &status) { + return MeasureUnit::create(3, 5, status); +} + MeasureUnit *MeasureUnit::createLiterPer100Kilometers(UErrorCode &status) { return MeasureUnit::create(4, 0, status); } @@ -689,14 +703,18 @@ MeasureUnit *MeasureUnit::createMegabyte(UErrorCode &status) { return MeasureUnit::create(6, 7, status); } -MeasureUnit *MeasureUnit::createTerabit(UErrorCode &status) { +MeasureUnit *MeasureUnit::createPetabyte(UErrorCode &status) { return MeasureUnit::create(6, 8, status); } -MeasureUnit *MeasureUnit::createTerabyte(UErrorCode &status) { +MeasureUnit *MeasureUnit::createTerabit(UErrorCode &status) { return MeasureUnit::create(6, 9, status); } +MeasureUnit *MeasureUnit::createTerabyte(UErrorCode &status) { + return MeasureUnit::create(6, 10, status); +} + MeasureUnit *MeasureUnit::createCentury(UErrorCode &status) { return MeasureUnit::create(7, 0, status); } @@ -949,26 +967,30 @@ MeasureUnit *MeasureUnit::createWatt(UErrorCode &status) { return MeasureUnit::create(15, 5, status); } -MeasureUnit *MeasureUnit::createHectopascal(UErrorCode &status) { +MeasureUnit *MeasureUnit::createAtmosphere(UErrorCode &status) { return MeasureUnit::create(16, 0, status); } -MeasureUnit *MeasureUnit::createInchHg(UErrorCode &status) { +MeasureUnit *MeasureUnit::createHectopascal(UErrorCode &status) { return MeasureUnit::create(16, 1, status); } -MeasureUnit *MeasureUnit::createMillibar(UErrorCode &status) { +MeasureUnit *MeasureUnit::createInchHg(UErrorCode &status) { return MeasureUnit::create(16, 2, status); } -MeasureUnit *MeasureUnit::createMillimeterOfMercury(UErrorCode &status) { +MeasureUnit *MeasureUnit::createMillibar(UErrorCode &status) { return MeasureUnit::create(16, 3, status); } -MeasureUnit *MeasureUnit::createPoundPerSquareInch(UErrorCode &status) { +MeasureUnit *MeasureUnit::createMillimeterOfMercury(UErrorCode &status) { return MeasureUnit::create(16, 4, status); } +MeasureUnit *MeasureUnit::createPoundPerSquareInch(UErrorCode &status) { + return MeasureUnit::create(16, 5, status); +} + MeasureUnit *MeasureUnit::createKilometerPerHour(UErrorCode &status) { return MeasureUnit::create(17, 0, status); } diff --git a/deps/icu-small/source/i18n/msgfmt.cpp b/deps/icu-small/source/i18n/msgfmt.cpp index 8b3807e67148a4..8ff86a2cacf018 100644 --- a/deps/icu-small/source/i18n/msgfmt.cpp +++ b/deps/icu-small/source/i18n/msgfmt.cpp @@ -1078,7 +1078,7 @@ void MessageFormat::format(int32_t msgStart, const void *plNumber, // that formats the number without subtracting the offset. appendTo.formatAndAppend(pluralNumber.formatter, *arg, success); } - } else if ((formatter = getCachedFormatter(i -2))) { + } else if ((formatter = getCachedFormatter(i -2)) != 0) { // Handles all ArgType.SIMPLE, and formatters from setFormat() and its siblings. if (dynamic_cast(formatter) || dynamic_cast(formatter) || diff --git a/deps/icu-small/source/i18n/nfrule.cpp b/deps/icu-small/source/i18n/nfrule.cpp index 9f5deb31683291..b5e7892d5e68cb 100644 --- a/deps/icu-small/source/i18n/nfrule.cpp +++ b/deps/icu-small/source/i18n/nfrule.cpp @@ -39,14 +39,14 @@ NFRule::NFRule(const RuleBasedNumberFormat* _rbnf, const UnicodeString &_ruleTex , radix(10) , exponent(0) , decimalPoint(0) - , ruleText(_ruleText) + , fRuleText(_ruleText) , sub1(NULL) , sub2(NULL) , formatter(_rbnf) , rulePatternFormat(NULL) { - if (!ruleText.isEmpty()) { - parseRuleDescriptor(ruleText, status); + if (!fRuleText.isEmpty()) { + parseRuleDescriptor(fRuleText, status); } } @@ -122,7 +122,7 @@ NFRule::makeRules(UnicodeString& description, status = U_MEMORY_ALLOCATION_ERROR; return; } - description = rule1->ruleText; + description = rule1->fRuleText; // check the description to see whether there's text enclosed // in brackets @@ -314,7 +314,7 @@ NFRule::parseRuleDescriptor(UnicodeString& description, UErrorCode& status) if (c == gSlash) { val = 0; ++p; - int64_t ll_10 = 10; + ll_10 = 10; while (p < descriptorLength) { c = descriptor.charAt(p); if (c >= gZero && c <= gNine) { @@ -418,7 +418,7 @@ NFRule::extractSubstitutions(const NFRuleSet* ruleSet, if (U_FAILURE(status)) { return; } - this->ruleText = ruleText; + fRuleText = ruleText; sub1 = extractSubstitution(ruleSet, predecessor, status); if (sub1 == NULL) { // Small optimization. There is no need to create a redundant NullSubstitution. @@ -427,15 +427,15 @@ NFRule::extractSubstitutions(const NFRuleSet* ruleSet, else { sub2 = extractSubstitution(ruleSet, predecessor, status); } - int32_t pluralRuleStart = this->ruleText.indexOf(gDollarOpenParenthesis, -1, 0); - int32_t pluralRuleEnd = (pluralRuleStart >= 0 ? this->ruleText.indexOf(gClosedParenthesisDollar, -1, pluralRuleStart) : -1); + int32_t pluralRuleStart = fRuleText.indexOf(gDollarOpenParenthesis, -1, 0); + int32_t pluralRuleEnd = (pluralRuleStart >= 0 ? fRuleText.indexOf(gClosedParenthesisDollar, -1, pluralRuleStart) : -1); if (pluralRuleEnd >= 0) { - int32_t endType = this->ruleText.indexOf(gComma, pluralRuleStart); + int32_t endType = fRuleText.indexOf(gComma, pluralRuleStart); if (endType < 0) { status = U_PARSE_ERROR; return; } - UnicodeString type(this->ruleText.tempSubString(pluralRuleStart + 2, endType - pluralRuleStart - 2)); + UnicodeString type(fRuleText.tempSubString(pluralRuleStart + 2, endType - pluralRuleStart - 2)); UPluralType pluralType; if (type.startsWith(UNICODE_STRING_SIMPLE("cardinal"))) { pluralType = UPLURAL_TYPE_CARDINAL; @@ -448,7 +448,7 @@ NFRule::extractSubstitutions(const NFRuleSet* ruleSet, return; } rulePatternFormat = formatter->createPluralFormat(pluralType, - this->ruleText.tempSubString(endType + 1, pluralRuleEnd - endType - 1), status); + fRuleText.tempSubString(endType + 1, pluralRuleEnd - endType - 1), status); } } @@ -484,16 +484,16 @@ NFRule::extractSubstitution(const NFRuleSet* ruleSet, // special-case the ">>>" token, since searching for the > at the // end will actually find the > in the middle - if (ruleText.indexOf(gGreaterGreaterGreater, 3, 0) == subStart) { + if (fRuleText.indexOf(gGreaterGreaterGreater, 3, 0) == subStart) { subEnd = subStart + 2; // otherwise the substitution token ends with the same character // it began with } else { - UChar c = ruleText.charAt(subStart); - subEnd = ruleText.indexOf(c, subStart + 1); + UChar c = fRuleText.charAt(subStart); + subEnd = fRuleText.indexOf(c, subStart + 1); // special case for '<%foo<<' - if (c == gLessThan && subEnd != -1 && subEnd < ruleText.length() - 1 && ruleText.charAt(subEnd+1) == c) { + if (c == gLessThan && subEnd != -1 && subEnd < fRuleText.length() - 1 && fRuleText.charAt(subEnd+1) == c) { // ordinals use "=#,##0==%abbrev=" as their rule. Notice that the '==' in the middle // occurs because of the juxtaposition of two different rules. The check for '<' is a hack // to get around this. Having the duplicate at the front would cause problems with @@ -513,12 +513,12 @@ NFRule::extractSubstitution(const NFRuleSet* ruleSet, // some text bounded by substitution token characters). Use // makeSubstitution() to create the right kind of substitution UnicodeString subToken; - subToken.setTo(ruleText, subStart, subEnd + 1 - subStart); + subToken.setTo(fRuleText, subStart, subEnd + 1 - subStart); result = NFSubstitution::makeSubstitution(subStart, this, predecessor, ruleSet, this->formatter, subToken, status); // remove the substitution from the rule text - ruleText.removeBetween(subStart, subEnd+1); + fRuleText.removeBetween(subStart, subEnd+1); return result; } @@ -601,7 +601,7 @@ NFRule::indexOfAnyRulePrefix() const { int result = -1; for (int i = 0; RULE_PREFIXES[i]; i++) { - int32_t pos = ruleText.indexOf(*RULE_PREFIXES[i]); + int32_t pos = fRuleText.indexOf(*RULE_PREFIXES[i]); if (pos != -1 && (result == -1 || pos < result)) { result = pos; } @@ -637,7 +637,7 @@ NFRule::operator==(const NFRule& rhs) const return baseValue == rhs.baseValue && radix == rhs.radix && exponent == rhs.exponent - && ruleText == rhs.ruleText + && fRuleText == rhs.fRuleText && util_equalSubstitutions(sub1, rhs.sub1) && util_equalSubstitutions(sub2, rhs.sub2); } @@ -690,14 +690,14 @@ NFRule::_appendRuleText(UnicodeString& result) const // if the rule text begins with a space, write an apostrophe // (whitespace after the rule descriptor is ignored; the // apostrophe is used to make the whitespace significant) - if (ruleText.charAt(0) == gSpace && (sub1 == NULL || sub1->getPos() != 0)) { + if (fRuleText.charAt(0) == gSpace && (sub1 == NULL || sub1->getPos() != 0)) { result.append(gTick); } // now, write the rule's rule text, inserting appropriate // substitution tokens in the appropriate places UnicodeString ruleTextCopy; - ruleTextCopy.setTo(ruleText); + ruleTextCopy.setTo(fRuleText); UnicodeString temp; if (sub2 != NULL) { @@ -743,24 +743,24 @@ NFRule::doFormat(int64_t number, UnicodeString& toInsertInto, int32_t pos, int32 // into the right places in toInsertInto (notice we do the // substitutions in reverse order so that the offsets don't get // messed up) - int32_t pluralRuleStart = ruleText.length(); + int32_t pluralRuleStart = fRuleText.length(); int32_t lengthOffset = 0; if (!rulePatternFormat) { - toInsertInto.insert(pos, ruleText); + toInsertInto.insert(pos, fRuleText); } else { - pluralRuleStart = ruleText.indexOf(gDollarOpenParenthesis, -1, 0); - int pluralRuleEnd = ruleText.indexOf(gClosedParenthesisDollar, -1, pluralRuleStart); + pluralRuleStart = fRuleText.indexOf(gDollarOpenParenthesis, -1, 0); + int pluralRuleEnd = fRuleText.indexOf(gClosedParenthesisDollar, -1, pluralRuleStart); int initialLength = toInsertInto.length(); - if (pluralRuleEnd < ruleText.length() - 1) { - toInsertInto.insert(pos, ruleText.tempSubString(pluralRuleEnd + 2)); + if (pluralRuleEnd < fRuleText.length() - 1) { + toInsertInto.insert(pos, fRuleText.tempSubString(pluralRuleEnd + 2)); } toInsertInto.insert(pos, rulePatternFormat->format((int32_t)(number/util64_pow(radix, exponent)), status)); if (pluralRuleStart > 0) { - toInsertInto.insert(pos, ruleText.tempSubString(0, pluralRuleStart)); + toInsertInto.insert(pos, fRuleText.tempSubString(0, pluralRuleStart)); } - lengthOffset = ruleText.length() - (toInsertInto.length() - initialLength); + lengthOffset = fRuleText.length() - (toInsertInto.length() - initialLength); } if (sub2 != NULL) { @@ -789,17 +789,17 @@ NFRule::doFormat(double number, UnicodeString& toInsertInto, int32_t pos, int32_ // [again, we have two copies of this routine that do the same thing // so that we don't sacrifice precision in a long by casting it // to a double] - int32_t pluralRuleStart = ruleText.length(); + int32_t pluralRuleStart = fRuleText.length(); int32_t lengthOffset = 0; if (!rulePatternFormat) { - toInsertInto.insert(pos, ruleText); + toInsertInto.insert(pos, fRuleText); } else { - pluralRuleStart = ruleText.indexOf(gDollarOpenParenthesis, -1, 0); - int pluralRuleEnd = ruleText.indexOf(gClosedParenthesisDollar, -1, pluralRuleStart); + pluralRuleStart = fRuleText.indexOf(gDollarOpenParenthesis, -1, 0); + int pluralRuleEnd = fRuleText.indexOf(gClosedParenthesisDollar, -1, pluralRuleStart); int initialLength = toInsertInto.length(); - if (pluralRuleEnd < ruleText.length() - 1) { - toInsertInto.insert(pos, ruleText.tempSubString(pluralRuleEnd + 2)); + if (pluralRuleEnd < fRuleText.length() - 1) { + toInsertInto.insert(pos, fRuleText.tempSubString(pluralRuleEnd + 2)); } double pluralVal = number; if (0 <= pluralVal && pluralVal < 1) { @@ -812,9 +812,9 @@ NFRule::doFormat(double number, UnicodeString& toInsertInto, int32_t pos, int32_ } toInsertInto.insert(pos, rulePatternFormat->format((int32_t)(pluralVal), status)); if (pluralRuleStart > 0) { - toInsertInto.insert(pos, ruleText.tempSubString(0, pluralRuleStart)); + toInsertInto.insert(pos, fRuleText.tempSubString(0, pluralRuleStart)); } - lengthOffset = ruleText.length() - (toInsertInto.length() - initialLength); + lengthOffset = fRuleText.length() - (toInsertInto.length() - initialLength); } if (sub2 != NULL) { @@ -908,15 +908,15 @@ NFRule::doParse(const UnicodeString& text, ParsePosition pp; UnicodeString workText(text); - int32_t sub1Pos = sub1 != NULL ? sub1->getPos() : ruleText.length(); - int32_t sub2Pos = sub2 != NULL ? sub2->getPos() : ruleText.length(); + int32_t sub1Pos = sub1 != NULL ? sub1->getPos() : fRuleText.length(); + int32_t sub2Pos = sub2 != NULL ? sub2->getPos() : fRuleText.length(); // check to see whether the text before the first substitution // matches the text at the beginning of the string being // parsed. If it does, strip that off the front of workText; // otherwise, dump out with a mismatch UnicodeString prefix; - prefix.setTo(ruleText, 0, sub1Pos); + prefix.setTo(fRuleText, 0, sub1Pos); #ifdef RBNF_DEBUG fprintf(stderr, "doParse %p ", this); @@ -1000,7 +1000,7 @@ NFRule::doParse(const UnicodeString& text, // the substitution, giving us a new partial parse result pp.setIndex(0); - temp.setTo(ruleText, sub1Pos, sub2Pos - sub1Pos); + temp.setTo(fRuleText, sub1Pos, sub2Pos - sub1Pos); double partialResult = matchToDelimiter(workText, start, tempBaseValue, temp, pp, sub1, nonNumericalExecutedRuleMask, @@ -1021,7 +1021,7 @@ NFRule::doParse(const UnicodeString& text, // partial result with whatever it gets back from its // substitution if there's a successful match, giving us // a real result - temp.setTo(ruleText, sub2Pos, ruleText.length() - sub2Pos); + temp.setTo(fRuleText, sub2Pos, fRuleText.length() - sub2Pos); partialResult = matchToDelimiter(workText2, 0, partialResult, temp, pp2, sub2, nonNumericalExecutedRuleMask, @@ -1039,18 +1039,18 @@ NFRule::doParse(const UnicodeString& text, else { // commented out because ParsePosition doesn't have error index in 1.1.x // restored for ICU4C port - int32_t temp = pp2.getErrorIndex() + sub1Pos + pp.getIndex(); - if (temp> parsePosition.getErrorIndex()) { - parsePosition.setErrorIndex(temp); + int32_t i_temp = pp2.getErrorIndex() + sub1Pos + pp.getIndex(); + if (i_temp> parsePosition.getErrorIndex()) { + parsePosition.setErrorIndex(i_temp); } } } else { // commented out because ParsePosition doesn't have error index in 1.1.x // restored for ICU4C port - int32_t temp = sub1Pos + pp.getErrorIndex(); - if (temp > parsePosition.getErrorIndex()) { - parsePosition.setErrorIndex(temp); + int32_t i_temp = sub1Pos + pp.getErrorIndex(); + if (i_temp > parsePosition.getErrorIndex()) { + parsePosition.setErrorIndex(i_temp); } } // keep trying to match things until the outer matchToDelimiter() @@ -1483,11 +1483,11 @@ NFRule::findText(const UnicodeString& str, rulePatternFormat->parseType(str, this, result, position); int start = position.getBeginIndex(); if (start >= 0) { - int32_t pluralRuleStart = ruleText.indexOf(gDollarOpenParenthesis, -1, 0); - int32_t pluralRuleSuffix = ruleText.indexOf(gClosedParenthesisDollar, -1, pluralRuleStart) + 2; + int32_t pluralRuleStart = fRuleText.indexOf(gDollarOpenParenthesis, -1, 0); + int32_t pluralRuleSuffix = fRuleText.indexOf(gClosedParenthesisDollar, -1, pluralRuleStart) + 2; int32_t matchLen = position.getEndIndex() - start; - UnicodeString prefix(ruleText.tempSubString(0, pluralRuleStart)); - UnicodeString suffix(ruleText.tempSubString(pluralRuleSuffix)); + UnicodeString prefix(fRuleText.tempSubString(0, pluralRuleStart)); + UnicodeString suffix(fRuleText.tempSubString(pluralRuleSuffix)); if (str.compare(start - prefix.length(), prefix.length(), prefix, 0, prefix.length()) == 0 && str.compare(start + matchLen, suffix.length(), suffix, 0, suffix.length()) == 0) { diff --git a/deps/icu-small/source/i18n/nfrule.h b/deps/icu-small/source/i18n/nfrule.h index 843a4a0762bb01..2b030390ea7dcb 100644 --- a/deps/icu-small/source/i18n/nfrule.h +++ b/deps/icu-small/source/i18n/nfrule.h @@ -109,7 +109,7 @@ class NFRule : public UMemory { int32_t radix; int16_t exponent; UChar decimalPoint; - UnicodeString ruleText; + UnicodeString fRuleText; NFSubstitution* sub1; NFSubstitution* sub2; const RuleBasedNumberFormat* formatter; diff --git a/deps/icu-small/source/i18n/number_compact.cpp b/deps/icu-small/source/i18n/number_compact.cpp index 40278e1a012e54..10942c35f535df 100644 --- a/deps/icu-small/source/i18n/number_compact.cpp +++ b/deps/icu-small/source/i18n/number_compact.cpp @@ -273,13 +273,13 @@ void CompactHandler::processQuantity(DecimalQuantity &quantity, MicroProps &micr if (U_FAILURE(status)) { return; } // Treat zero as if it had magnitude 0 - int magnitude; + int32_t magnitude; if (quantity.isZero()) { magnitude = 0; micros.rounder.apply(quantity, status); } else { // TODO: Revisit chooseMultiplierAndApply - int multiplier = micros.rounder.chooseMultiplierAndApply(quantity, data, status); + int32_t multiplier = micros.rounder.chooseMultiplierAndApply(quantity, data, status); magnitude = quantity.isZero() ? 0 : quantity.getMagnitude(); magnitude -= multiplier; } diff --git a/deps/icu-small/source/i18n/number_decimalquantity.cpp b/deps/icu-small/source/i18n/number_decimalquantity.cpp index 9d80e3349cb8aa..2c4182b1c6ecda 100644 --- a/deps/icu-small/source/i18n/number_decimalquantity.cpp +++ b/deps/icu-small/source/i18n/number_decimalquantity.cpp @@ -1154,8 +1154,31 @@ const char16_t* DecimalQuantity::checkHealth() const { } bool DecimalQuantity::operator==(const DecimalQuantity& other) const { - // FIXME: Make a faster implementation. - return toString() == other.toString(); + bool basicEquals = + scale == other.scale + && precision == other.precision + && flags == other.flags + && lOptPos == other.lOptPos + && lReqPos == other.lReqPos + && rReqPos == other.rReqPos + && rOptPos == other.rOptPos + && isApproximate == other.isApproximate; + if (!basicEquals) { + return false; + } + + if (precision == 0) { + return true; + } else if (isApproximate) { + return origDouble == other.origDouble && origDelta == other.origDelta; + } else { + for (int m = getUpperDisplayMagnitude(); m >= getLowerDisplayMagnitude(); m--) { + if (getDigit(m) != other.getDigit(m)) { + return false; + } + } + return true; + } } UnicodeString DecimalQuantity::toString() const { diff --git a/deps/icu-small/source/i18n/number_decimfmtprops.cpp b/deps/icu-small/source/i18n/number_decimfmtprops.cpp index 6754fe19eca56c..12fe7060e2d051 100644 --- a/deps/icu-small/source/i18n/number_decimfmtprops.cpp +++ b/deps/icu-small/source/i18n/number_decimfmtprops.cpp @@ -15,6 +15,7 @@ using namespace icu::number::impl; namespace { +alignas(DecimalFormatProperties) char kRawDefaultProperties[sizeof(DecimalFormatProperties)]; icu::UInitOnce gDefaultPropertiesInitOnce = U_INITONCE_INITIALIZER; diff --git a/deps/icu-small/source/i18n/number_fluent.cpp b/deps/icu-small/source/i18n/number_fluent.cpp index 687adb6b5babd2..a66e3bd0f23510 100644 --- a/deps/icu-small/source/i18n/number_fluent.cpp +++ b/deps/icu-small/source/i18n/number_fluent.cpp @@ -363,6 +363,7 @@ UnlocalizedNumberFormatter::UnlocalizedNumberFormatter(const NFS& other) // No additional fields to assign } +// Make default copy constructor call the NumberFormatterSettings copy constructor. UnlocalizedNumberFormatter::UnlocalizedNumberFormatter(UNF&& src) U_NOEXCEPT : UNF(static_cast&&>(src)) {} @@ -383,6 +384,7 @@ UnlocalizedNumberFormatter& UnlocalizedNumberFormatter::operator=(UNF&& src) U_N return *this; } +// Make default copy constructor call the NumberFormatterSettings copy constructor. LocalizedNumberFormatter::LocalizedNumberFormatter(const LNF& other) : LNF(static_cast&>(other)) {} @@ -405,7 +407,8 @@ LocalizedNumberFormatter::LocalizedNumberFormatter(NFS&& src) U_NOEXCEPT LocalizedNumberFormatter& LocalizedNumberFormatter::operator=(const LNF& other) { NFS::operator=(static_cast&>(other)); - // No additional fields to assign (let call count and compiled formatter reset to defaults) + // Reset to default values. + clear(); return *this; } @@ -417,20 +420,26 @@ LocalizedNumberFormatter& LocalizedNumberFormatter::operator=(LNF&& src) U_NOEXC // Formatter is compiled lnfMoveHelper(static_cast(src)); } else { - // Reset to default values. - auto* callCount = reinterpret_cast(fUnsafeCallCount); - umtx_storeRelease(*callCount, 0); - fCompiled = nullptr; + clear(); } return *this; } +void LocalizedNumberFormatter::clear() { + // Reset to default values. + auto* callCount = reinterpret_cast(fUnsafeCallCount); + umtx_storeRelease(*callCount, 0); + delete fCompiled; + fCompiled = nullptr; +} + void LocalizedNumberFormatter::lnfMoveHelper(LNF&& src) { // Copy over the compiled formatter and set call count to INT32_MIN as in computeCompiled(). // Don't copy the call count directly because doing so requires a loadAcquire/storeRelease. // The bits themselves appear to be platform-dependent, so copying them might not be safe. auto* callCount = reinterpret_cast(fUnsafeCallCount); umtx_storeRelease(*callCount, INT32_MIN); + delete fCompiled; fCompiled = src.fCompiled; // Reset the source object to leave it in a safe state. auto* srcCallCount = reinterpret_cast(src.fUnsafeCallCount); @@ -657,9 +666,9 @@ LocalizedNumberFormatter::formatDecimalQuantity(const DecimalQuantity& dq, UErro void LocalizedNumberFormatter::formatImpl(impl::UFormattedNumberData* results, UErrorCode& status) const { if (computeCompiled(status)) { - fCompiled->apply(results->quantity, results->string, status); + fCompiled->format(results->quantity, results->string, status); } else { - NumberFormatterImpl::applyStatic(fMacros, results->quantity, results->string, status); + NumberFormatterImpl::formatStatic(fMacros, results->quantity, results->string, status); } } @@ -706,7 +715,11 @@ bool LocalizedNumberFormatter::computeCompiled(UErrorCode& status) const { if (currentCount == fMacros.threshold && fMacros.threshold > 0) { // Build the data structure and then use it (slow to fast path). - const NumberFormatterImpl* compiled = NumberFormatterImpl::fromMacros(fMacros, status); + const NumberFormatterImpl* compiled = new NumberFormatterImpl(fMacros, status); + if (compiled == nullptr) { + status = U_MEMORY_ALLOCATION_ERROR; + return false; + } U_ASSERT(fCompiled == nullptr); const_cast(this)->fCompiled = compiled; umtx_storeRelease(*callCount, INT32_MIN); @@ -776,7 +789,7 @@ Appendable& FormattedNumber::appendTo(Appendable& appendable) { return appendTo(appendable, localStatus); } -Appendable& FormattedNumber::appendTo(Appendable& appendable, UErrorCode& status) { +Appendable& FormattedNumber::appendTo(Appendable& appendable, UErrorCode& status) const { if (U_FAILURE(status)) { return appendable; } diff --git a/deps/icu-small/source/i18n/number_formatimpl.cpp b/deps/icu-small/source/i18n/number_formatimpl.cpp index 3f887128bcc668..60c18ee284e238 100644 --- a/deps/icu-small/source/i18n/number_formatimpl.cpp +++ b/deps/icu-small/source/i18n/number_formatimpl.cpp @@ -67,14 +67,18 @@ getCurrencyFormatInfo(const Locale& locale, const char* isoCode, UErrorCode& sta MicroPropsGenerator::~MicroPropsGenerator() = default; -NumberFormatterImpl* NumberFormatterImpl::fromMacros(const MacroProps& macros, UErrorCode& status) { - return new NumberFormatterImpl(macros, true, status); +NumberFormatterImpl::NumberFormatterImpl(const MacroProps& macros, UErrorCode& status) + : NumberFormatterImpl(macros, true, status) { } -void NumberFormatterImpl::applyStatic(const MacroProps& macros, DecimalQuantity& inValue, - NumberStringBuilder& outString, UErrorCode& status) { +int32_t NumberFormatterImpl::formatStatic(const MacroProps& macros, DecimalQuantity& inValue, + NumberStringBuilder& outString, UErrorCode& status) { NumberFormatterImpl impl(macros, false, status); - impl.applyUnsafe(inValue, outString, status); + MicroProps& micros = impl.preProcessUnsafe(inValue, status); + if (U_FAILURE(status)) { return 0; } + int32_t length = writeNumber(micros, inValue, outString, 0, status); + length += writeAffixes(micros, outString, 0, length, status); + return length; } int32_t NumberFormatterImpl::getPrefixSuffixStatic(const MacroProps& macros, int8_t signum, @@ -89,22 +93,40 @@ int32_t NumberFormatterImpl::getPrefixSuffixStatic(const MacroProps& macros, int // The "unsafe" method simply re-uses fMicros, eliminating the extra copy operation. // See MicroProps::processQuantity() for details. -void NumberFormatterImpl::apply(DecimalQuantity& inValue, NumberStringBuilder& outString, +int32_t NumberFormatterImpl::format(DecimalQuantity& inValue, NumberStringBuilder& outString, UErrorCode& status) const { - if (U_FAILURE(status)) { return; } MicroProps micros; - if (!fMicroPropsGenerator) { return; } - fMicroPropsGenerator->processQuantity(inValue, micros, status); - if (U_FAILURE(status)) { return; } - microsToString(micros, inValue, outString, status); + preProcess(inValue, micros, status); + if (U_FAILURE(status)) { return 0; } + int32_t length = writeNumber(micros, inValue, outString, 0, status); + length += writeAffixes(micros, outString, 0, length, status); + return length; } -void NumberFormatterImpl::applyUnsafe(DecimalQuantity& inValue, NumberStringBuilder& outString, - UErrorCode& status) { +void NumberFormatterImpl::preProcess(DecimalQuantity& inValue, MicroProps& microsOut, + UErrorCode& status) const { if (U_FAILURE(status)) { return; } + if (fMicroPropsGenerator == nullptr) { + status = U_INTERNAL_PROGRAM_ERROR; + return; + } + fMicroPropsGenerator->processQuantity(inValue, microsOut, status); + microsOut.rounder.apply(inValue, status); + microsOut.integerWidth.apply(inValue, status); +} + +MicroProps& NumberFormatterImpl::preProcessUnsafe(DecimalQuantity& inValue, UErrorCode& status) { + if (U_FAILURE(status)) { + return fMicros; // must always return a value + } + if (fMicroPropsGenerator == nullptr) { + status = U_INTERNAL_PROGRAM_ERROR; + return fMicros; // must always return a value + } fMicroPropsGenerator->processQuantity(inValue, fMicros, status); - if (U_FAILURE(status)) { return; } - microsToString(fMicros, inValue, outString, status); + fMicros.rounder.apply(inValue, status); + fMicros.integerWidth.apply(inValue, status); + return fMicros; } int32_t NumberFormatterImpl::getPrefixSuffix(int8_t signum, StandardPlural::Form plural, @@ -115,7 +137,7 @@ int32_t NumberFormatterImpl::getPrefixSuffix(int8_t signum, StandardPlural::Form const Modifier* modifier = fImmutablePatternModifier->getModifier(signum, plural); modifier->apply(outString, 0, 0, status); if (U_FAILURE(status)) { return 0; } - return modifier->getPrefixLength(status); + return modifier->getPrefixLength(); } int32_t NumberFormatterImpl::getPrefixSuffixUnsafe(int8_t signum, StandardPlural::Form plural, @@ -126,7 +148,7 @@ int32_t NumberFormatterImpl::getPrefixSuffixUnsafe(int8_t signum, StandardPlural fPatternModifier->setNumberProperties(signum, plural); fPatternModifier->apply(outString, 0, 0, status); if (U_FAILURE(status)) { return 0; } - return fPatternModifier->getPrefixLength(status); + return fPatternModifier->getPrefixLength(); } NumberFormatterImpl::NumberFormatterImpl(const MacroProps& macros, bool safe, UErrorCode& status) { @@ -344,25 +366,23 @@ NumberFormatterImpl::macrosToMicroGenerator(const MacroProps& macros, bool safe, // Outer modifier (CLDR units and currency long names) if (isCldrUnit) { fLongNameHandler.adoptInstead( - new LongNameHandler( - LongNameHandler::forMeasureUnit( - macros.locale, - macros.unit, - macros.perUnit, - unitWidth, - resolvePluralRules(macros.rules, macros.locale, status), - chain, - status))); + LongNameHandler::forMeasureUnit( + macros.locale, + macros.unit, + macros.perUnit, + unitWidth, + resolvePluralRules(macros.rules, macros.locale, status), + chain, + status)); chain = fLongNameHandler.getAlias(); } else if (isCurrency && unitWidth == UNUM_UNIT_WIDTH_FULL_NAME) { fLongNameHandler.adoptInstead( - new LongNameHandler( - LongNameHandler::forCurrencyLongNames( - macros.locale, - currency, - resolvePluralRules(macros.rules, macros.locale, status), - chain, - status))); + LongNameHandler::forCurrencyLongNames( + macros.locale, + currency, + resolvePluralRules(macros.rules, macros.locale, status), + chain, + status)); chain = fLongNameHandler.getAlias(); } else { // No outer modifier required @@ -404,50 +424,46 @@ NumberFormatterImpl::resolvePluralRules(const PluralRules* rulesPtr, const Local return fRules.getAlias(); } -int32_t NumberFormatterImpl::microsToString(const MicroProps& micros, DecimalQuantity& quantity, - NumberStringBuilder& string, UErrorCode& status) { - micros.rounder.apply(quantity, status); - micros.integerWidth.apply(quantity, status); - int32_t length = writeNumber(micros, quantity, string, status); - // NOTE: When range formatting is added, these modifiers can bubble up. - // For now, apply them all here at once. +int32_t NumberFormatterImpl::writeAffixes(const MicroProps& micros, NumberStringBuilder& string, + int32_t start, int32_t end, UErrorCode& status) { // Always apply the inner modifier (which is "strong"). - length += micros.modInner->apply(string, 0, length, status); + int32_t length = micros.modInner->apply(string, start, end, status); if (micros.padding.isValid()) { length += micros.padding - .padAndApply(*micros.modMiddle, *micros.modOuter, string, 0, length, status); + .padAndApply(*micros.modMiddle, *micros.modOuter, string, start, length + end, status); } else { - length += micros.modMiddle->apply(string, 0, length, status); - length += micros.modOuter->apply(string, 0, length, status); + length += micros.modMiddle->apply(string, start, length + end, status); + length += micros.modOuter->apply(string, start, length + end, status); } return length; } int32_t NumberFormatterImpl::writeNumber(const MicroProps& micros, DecimalQuantity& quantity, - NumberStringBuilder& string, UErrorCode& status) { + NumberStringBuilder& string, int32_t index, + UErrorCode& status) { int32_t length = 0; if (quantity.isInfinite()) { length += string.insert( - length, + length + index, micros.symbols->getSymbol(DecimalFormatSymbols::ENumberFormatSymbol::kInfinitySymbol), UNUM_INTEGER_FIELD, status); } else if (quantity.isNaN()) { length += string.insert( - length, + length + index, micros.symbols->getSymbol(DecimalFormatSymbols::ENumberFormatSymbol::kNaNSymbol), UNUM_INTEGER_FIELD, status); } else { // Add the integer digits - length += writeIntegerDigits(micros, quantity, string, status); + length += writeIntegerDigits(micros, quantity, string, length + index, status); // Add the decimal point if (quantity.getLowerDisplayMagnitude() < 0 || micros.decimal == UNUM_DECIMAL_SEPARATOR_ALWAYS) { length += string.insert( - length, + length + index, micros.useCurrency ? micros.symbols->getSymbol( DecimalFormatSymbols::ENumberFormatSymbol::kMonetarySeparatorSymbol) : micros .symbols @@ -458,21 +474,22 @@ int32_t NumberFormatterImpl::writeNumber(const MicroProps& micros, DecimalQuanti } // Add the fraction digits - length += writeFractionDigits(micros, quantity, string, status); + length += writeFractionDigits(micros, quantity, string, length + index, status); } return length; } int32_t NumberFormatterImpl::writeIntegerDigits(const MicroProps& micros, DecimalQuantity& quantity, - NumberStringBuilder& string, UErrorCode& status) { + NumberStringBuilder& string, int32_t index, + UErrorCode& status) { int length = 0; int integerCount = quantity.getUpperDisplayMagnitude() + 1; for (int i = 0; i < integerCount; i++) { // Add grouping separator if (micros.grouping.groupAtPosition(i, quantity)) { length += string.insert( - 0, + index, micros.useCurrency ? micros.symbols->getSymbol( DecimalFormatSymbols::ENumberFormatSymbol::kMonetaryGroupingSeparatorSymbol) : micros.symbols->getSymbol( @@ -484,20 +501,21 @@ int32_t NumberFormatterImpl::writeIntegerDigits(const MicroProps& micros, Decima // Get and append the next digit value int8_t nextDigit = quantity.getDigit(i); length += utils::insertDigitFromSymbols( - string, 0, nextDigit, *micros.symbols, UNUM_INTEGER_FIELD, status); + string, index, nextDigit, *micros.symbols, UNUM_INTEGER_FIELD, status); } return length; } int32_t NumberFormatterImpl::writeFractionDigits(const MicroProps& micros, DecimalQuantity& quantity, - NumberStringBuilder& string, UErrorCode& status) { + NumberStringBuilder& string, int32_t index, + UErrorCode& status) { int length = 0; int fractionCount = -quantity.getLowerDisplayMagnitude(); for (int i = 0; i < fractionCount; i++) { // Get and append the next digit value int8_t nextDigit = quantity.getDigit(-i - 1); length += utils::insertDigitFromSymbols( - string, string.length(), nextDigit, *micros.symbols, UNUM_FRACTION_FIELD, status); + string, length + index, nextDigit, *micros.symbols, UNUM_FRACTION_FIELD, status); } return length; } diff --git a/deps/icu-small/source/i18n/number_formatimpl.h b/deps/icu-small/source/i18n/number_formatimpl.h index 744fecec13f984..fda38c92845f87 100644 --- a/deps/icu-small/source/i18n/number_formatimpl.h +++ b/deps/icu-small/source/i18n/number_formatimpl.h @@ -29,14 +29,14 @@ class NumberFormatterImpl : public UMemory { * Builds a "safe" MicroPropsGenerator, which is thread-safe and can be used repeatedly. * The caller owns the returned NumberFormatterImpl. */ - static NumberFormatterImpl *fromMacros(const MacroProps ¯os, UErrorCode &status); + NumberFormatterImpl(const MacroProps ¯os, UErrorCode &status); /** * Builds and evaluates an "unsafe" MicroPropsGenerator, which is cheaper but can be used only once. */ - static void - applyStatic(const MacroProps ¯os, DecimalQuantity &inValue, NumberStringBuilder &outString, - UErrorCode &status); + static int32_t + formatStatic(const MacroProps ¯os, DecimalQuantity &inValue, NumberStringBuilder &outString, + UErrorCode &status); /** * Prints only the prefix and suffix; used for DecimalFormat getters. @@ -51,7 +51,12 @@ class NumberFormatterImpl : public UMemory { /** * Evaluates the "safe" MicroPropsGenerator created by "fromMacros". */ - void apply(DecimalQuantity& inValue, NumberStringBuilder& outString, UErrorCode& status) const; + int32_t format(DecimalQuantity& inValue, NumberStringBuilder& outString, UErrorCode& status) const; + + /** + * Like format(), but saves the result into an output MicroProps without additional processing. + */ + void preProcess(DecimalQuantity& inValue, MicroProps& microsOut, UErrorCode& status) const; /** * Like getPrefixSuffixStatic() but uses the safe compiled object. @@ -59,6 +64,19 @@ class NumberFormatterImpl : public UMemory { int32_t getPrefixSuffix(int8_t signum, StandardPlural::Form plural, NumberStringBuilder& outString, UErrorCode& status) const; + /** + * Synthesizes the output string from a MicroProps and DecimalQuantity. + * This method formats only the main number, not affixes. + */ + static int32_t writeNumber(const MicroProps& micros, DecimalQuantity& quantity, + NumberStringBuilder& string, int32_t index, UErrorCode& status); + + /** + * Adds the affixes. Intended to be called immediately after formatNumber. + */ + static int32_t writeAffixes(const MicroProps& micros, NumberStringBuilder& string, int32_t start, + int32_t end, UErrorCode& status); + private: // Head of the MicroPropsGenerator linked list: const MicroPropsGenerator *fMicroPropsGenerator = nullptr; @@ -85,7 +103,7 @@ class NumberFormatterImpl : public UMemory { NumberFormatterImpl(const MacroProps ¯os, bool safe, UErrorCode &status); - void applyUnsafe(DecimalQuantity &inValue, NumberStringBuilder &outString, UErrorCode &status); + MicroProps& preProcessUnsafe(DecimalQuantity &inValue, UErrorCode &status); int32_t getPrefixSuffixUnsafe(int8_t signum, StandardPlural::Form plural, NumberStringBuilder& outString, UErrorCode& status); @@ -113,31 +131,13 @@ class NumberFormatterImpl : public UMemory { const MicroPropsGenerator * macrosToMicroGenerator(const MacroProps ¯os, bool safe, UErrorCode &status); - /** - * Synthesizes the output string from a MicroProps and DecimalQuantity. - * - * @param micros - * The MicroProps after the quantity has been consumed. Will not be mutated. - * @param quantity - * The DecimalQuantity to be rendered. May be mutated. - * @param string - * The output string. Will be mutated. - */ - static int32_t - microsToString(const MicroProps µs, DecimalQuantity &quantity, NumberStringBuilder &string, - UErrorCode &status); - - static int32_t - writeNumber(const MicroProps µs, DecimalQuantity &quantity, NumberStringBuilder &string, - UErrorCode &status); - static int32_t writeIntegerDigits(const MicroProps µs, DecimalQuantity &quantity, NumberStringBuilder &string, - UErrorCode &status); + int32_t index, UErrorCode &status); static int32_t writeFractionDigits(const MicroProps µs, DecimalQuantity &quantity, NumberStringBuilder &string, - UErrorCode &status); + int32_t index, UErrorCode &status); }; } // namespace impl diff --git a/deps/icu-small/source/i18n/number_grouping.cpp b/deps/icu-small/source/i18n/number_grouping.cpp index 4a1cceb49948b9..da32cca99a38df 100644 --- a/deps/icu-small/source/i18n/number_grouping.cpp +++ b/deps/icu-small/source/i18n/number_grouping.cpp @@ -80,7 +80,7 @@ void Grouper::setLocaleData(const impl::ParsedPatternInfo &patternInfo, const Lo if (fMinGrouping == -2) { fMinGrouping = getMinGroupingForLocale(locale); } else if (fMinGrouping == -3) { - fMinGrouping = uprv_max(2, getMinGroupingForLocale(locale)); + fMinGrouping = static_cast(uprv_max(2, getMinGroupingForLocale(locale))); } else { // leave fMinGrouping alone } diff --git a/deps/icu-small/source/i18n/number_longnames.cpp b/deps/icu-small/source/i18n/number_longnames.cpp index 26f9af4c9bdbfe..fd8e8d381a1d76 100644 --- a/deps/icu-small/source/i18n/number_longnames.cpp +++ b/deps/icu-small/source/i18n/number_longnames.cpp @@ -39,7 +39,7 @@ static int32_t getIndex(const char* pluralKeyword, UErrorCode& status) { static UnicodeString getWithPlural( const UnicodeString* strings, - int32_t plural, + StandardPlural::Form plural, UErrorCode& status) { UnicodeString result = strings[plural]; if (result.isBogus()) { @@ -156,7 +156,7 @@ UnicodeString getPerUnitFormat(const Locale& locale, const UNumberUnitWidth &wid } // namespace -LongNameHandler +LongNameHandler* LongNameHandler::forMeasureUnit(const Locale &loc, const MeasureUnit &unitRef, const MeasureUnit &perUnit, const UNumberUnitWidth &width, const PluralRules *rules, const MicroPropsGenerator *parent, UErrorCode &status) { @@ -173,20 +173,28 @@ LongNameHandler::forMeasureUnit(const Locale &loc, const MeasureUnit &unitRef, c } } - LongNameHandler result(rules, parent); + auto* result = new LongNameHandler(rules, parent); + if (result == nullptr) { + status = U_MEMORY_ALLOCATION_ERROR; + return nullptr; + } UnicodeString simpleFormats[ARRAY_LENGTH]; getMeasureData(loc, unit, width, simpleFormats, status); if (U_FAILURE(status)) { return result; } // TODO: What field to use for units? - simpleFormatsToModifiers(simpleFormats, UNUM_FIELD_COUNT, result.fModifiers, status); + result->simpleFormatsToModifiers(simpleFormats, UNUM_FIELD_COUNT, status); return result; } -LongNameHandler +LongNameHandler* LongNameHandler::forCompoundUnit(const Locale &loc, const MeasureUnit &unit, const MeasureUnit &perUnit, const UNumberUnitWidth &width, const PluralRules *rules, const MicroPropsGenerator *parent, UErrorCode &status) { - LongNameHandler result(rules, parent); + auto* result = new LongNameHandler(rules, parent); + if (result == nullptr) { + status = U_MEMORY_ALLOCATION_ERROR; + return nullptr; + } UnicodeString primaryData[ARRAY_LENGTH]; getMeasureData(loc, unit, width, primaryData, status); if (U_FAILURE(status)) { return result; } @@ -213,46 +221,52 @@ LongNameHandler::forCompoundUnit(const Locale &loc, const MeasureUnit &unit, con if (U_FAILURE(status)) { return result; } } // TODO: What field to use for units? - multiSimpleFormatsToModifiers(primaryData, perUnitFormat, UNUM_FIELD_COUNT, result.fModifiers, status); + result->multiSimpleFormatsToModifiers(primaryData, perUnitFormat, UNUM_FIELD_COUNT, status); return result; } -LongNameHandler LongNameHandler::forCurrencyLongNames(const Locale &loc, const CurrencyUnit ¤cy, +LongNameHandler* LongNameHandler::forCurrencyLongNames(const Locale &loc, const CurrencyUnit ¤cy, const PluralRules *rules, const MicroPropsGenerator *parent, UErrorCode &status) { - LongNameHandler result(rules, parent); + auto* result = new LongNameHandler(rules, parent); + if (result == nullptr) { + status = U_MEMORY_ALLOCATION_ERROR; + return nullptr; + } UnicodeString simpleFormats[ARRAY_LENGTH]; getCurrencyLongNameData(loc, currency, simpleFormats, status); - if (U_FAILURE(status)) { return result; } - simpleFormatsToModifiers(simpleFormats, UNUM_CURRENCY_FIELD, result.fModifiers, status); + if (U_FAILURE(status)) { return nullptr; } + result->simpleFormatsToModifiers(simpleFormats, UNUM_CURRENCY_FIELD, status); return result; } void LongNameHandler::simpleFormatsToModifiers(const UnicodeString *simpleFormats, Field field, - SimpleModifier *output, UErrorCode &status) { + UErrorCode &status) { for (int32_t i = 0; i < StandardPlural::Form::COUNT; i++) { - UnicodeString simpleFormat = getWithPlural(simpleFormats, i, status); + StandardPlural::Form plural = static_cast(i); + UnicodeString simpleFormat = getWithPlural(simpleFormats, plural, status); if (U_FAILURE(status)) { return; } SimpleFormatter compiledFormatter(simpleFormat, 0, 1, status); if (U_FAILURE(status)) { return; } - output[i] = SimpleModifier(compiledFormatter, field, false); + fModifiers[i] = SimpleModifier(compiledFormatter, field, false, {this, 0, plural}); } } void LongNameHandler::multiSimpleFormatsToModifiers(const UnicodeString *leadFormats, UnicodeString trailFormat, - Field field, SimpleModifier *output, UErrorCode &status) { + Field field, UErrorCode &status) { SimpleFormatter trailCompiled(trailFormat, 1, 1, status); if (U_FAILURE(status)) { return; } for (int32_t i = 0; i < StandardPlural::Form::COUNT; i++) { - UnicodeString leadFormat = getWithPlural(leadFormats, i, status); + StandardPlural::Form plural = static_cast(i); + UnicodeString leadFormat = getWithPlural(leadFormats, plural, status); if (U_FAILURE(status)) { return; } UnicodeString compoundFormat; trailCompiled.format(leadFormat, compoundFormat, status); if (U_FAILURE(status)) { return; } SimpleFormatter compoundCompiled(compoundFormat, 0, 1, status); if (U_FAILURE(status)) { return; } - output[i] = SimpleModifier(compoundCompiled, field, false); + fModifiers[i] = SimpleModifier(compoundCompiled, field, false, {this, 0, plural}); } } @@ -265,4 +279,8 @@ void LongNameHandler::processQuantity(DecimalQuantity &quantity, MicroProps &mic micros.modOuter = &fModifiers[utils::getStandardPlural(rules, copy)]; } +const Modifier* LongNameHandler::getModifier(int8_t /*signum*/, StandardPlural::Form plural) const { + return &fModifiers[plural]; +} + #endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/deps/icu-small/source/i18n/number_longnames.h b/deps/icu-small/source/i18n/number_longnames.h index 1d1e7dd3e864a6..a71d0caadf125c 100644 --- a/deps/icu-small/source/i18n/number_longnames.h +++ b/deps/icu-small/source/i18n/number_longnames.h @@ -14,13 +14,13 @@ U_NAMESPACE_BEGIN namespace number { namespace impl { -class LongNameHandler : public MicroPropsGenerator, public UMemory { +class LongNameHandler : public MicroPropsGenerator, public ModifierStore, public UMemory { public: - static LongNameHandler + static LongNameHandler* forCurrencyLongNames(const Locale &loc, const CurrencyUnit ¤cy, const PluralRules *rules, const MicroPropsGenerator *parent, UErrorCode &status); - static LongNameHandler + static LongNameHandler* forMeasureUnit(const Locale &loc, const MeasureUnit &unit, const MeasureUnit &perUnit, const UNumberUnitWidth &width, const PluralRules *rules, const MicroPropsGenerator *parent, UErrorCode &status); @@ -28,6 +28,8 @@ class LongNameHandler : public MicroPropsGenerator, public UMemory { void processQuantity(DecimalQuantity &quantity, MicroProps µs, UErrorCode &status) const U_OVERRIDE; + const Modifier* getModifier(int8_t signum, StandardPlural::Form plural) const U_OVERRIDE; + private: SimpleModifier fModifiers[StandardPlural::Form::COUNT]; const PluralRules *rules; @@ -36,15 +38,14 @@ class LongNameHandler : public MicroPropsGenerator, public UMemory { LongNameHandler(const PluralRules *rules, const MicroPropsGenerator *parent) : rules(rules), parent(parent) {} - static LongNameHandler + static LongNameHandler* forCompoundUnit(const Locale &loc, const MeasureUnit &unit, const MeasureUnit &perUnit, const UNumberUnitWidth &width, const PluralRules *rules, const MicroPropsGenerator *parent, UErrorCode &status); - static void simpleFormatsToModifiers(const UnicodeString *simpleFormats, Field field, - SimpleModifier *output, UErrorCode &status); - static void multiSimpleFormatsToModifiers(const UnicodeString *leadFormats, UnicodeString trailFormat, - Field field, SimpleModifier *output, UErrorCode &status); + void simpleFormatsToModifiers(const UnicodeString *simpleFormats, Field field, UErrorCode &status); + void multiSimpleFormatsToModifiers(const UnicodeString *leadFormats, UnicodeString trailFormat, + Field field, UErrorCode &status); }; } // namespace impl diff --git a/deps/icu-small/source/i18n/number_mapper.cpp b/deps/icu-small/source/i18n/number_mapper.cpp index d260632f93b0db..2c9a8e5178f35e 100644 --- a/deps/icu-small/source/i18n/number_mapper.cpp +++ b/deps/icu-small/source/i18n/number_mapper.cpp @@ -225,8 +225,8 @@ MacroProps NumberPropertyMapper::oldToNew(const DecimalFormatProperties& propert // TODO: Overriding here is a bit of a hack. Should this logic go earlier? if (macros.precision.fType == Precision::PrecisionType::RND_FRACTION) { // For the purposes of rounding, get the original min/max int/frac, since the local - // variables - // have been manipulated for display purposes. + // variables have been manipulated for display purposes. + int maxInt_ = properties.maximumIntegerDigits; int minInt_ = properties.minimumIntegerDigits; int minFrac_ = properties.minimumFractionDigits; int maxFrac_ = properties.maximumFractionDigits; @@ -237,9 +237,15 @@ MacroProps NumberPropertyMapper::oldToNew(const DecimalFormatProperties& propert // Patterns like "#.##E0" (no zeros in the mantissa), which mean round to maxFrac+1 macros.precision = Precision::constructSignificant(1, maxFrac_ + 1).withMode(roundingMode); } else { - // All other scientific patterns, which mean round to minInt+maxFrac - macros.precision = Precision::constructSignificant( - minInt_ + minFrac_, minInt_ + maxFrac_).withMode(roundingMode); + int maxSig_ = minInt_ + maxFrac_; + // Bug #20058: if maxInt_ > minInt_ > 1, then minInt_ should be 1. + if (maxInt_ > minInt_ && minInt_ > 1) { + minInt_ = 1; + } + int minSig_ = minInt_ + minFrac_; + // To avoid regression, maxSig is not reset when minInt_ set to 1. + // TODO: Reset maxSig_ = 1 + minFrac_ to follow the spec. + macros.precision = Precision::constructSignificant(minSig_, maxSig_).withMode(roundingMode); } } } diff --git a/deps/icu-small/source/i18n/number_modifiers.cpp b/deps/icu-small/source/i18n/number_modifiers.cpp index 4385499b54f603..d92ec63b08da58 100644 --- a/deps/icu-small/source/i18n/number_modifiers.cpp +++ b/deps/icu-small/source/i18n/number_modifiers.cpp @@ -53,6 +53,21 @@ void U_CALLCONV initDefaultCurrencySpacing(UErrorCode &status) { Modifier::~Modifier() = default; +Modifier::Parameters::Parameters() + : obj(nullptr) {} + +Modifier::Parameters::Parameters( + const ModifierStore* _obj, int8_t _signum, StandardPlural::Form _plural) + : obj(_obj), signum(_signum), plural(_plural) {} + +ModifierStore::~ModifierStore() = default; + +AdoptingModifierStore::~AdoptingModifierStore() { + for (const Modifier *mod : mods) { + delete mod; + } +} + int32_t ConstantAffixModifier::apply(NumberStringBuilder &output, int leftIndex, int rightIndex, UErrorCode &status) const { @@ -62,13 +77,11 @@ int32_t ConstantAffixModifier::apply(NumberStringBuilder &output, int leftIndex, return length; } -int32_t ConstantAffixModifier::getPrefixLength(UErrorCode &status) const { - (void)status; +int32_t ConstantAffixModifier::getPrefixLength() const { return fPrefix.length(); } -int32_t ConstantAffixModifier::getCodePointCount(UErrorCode &status) const { - (void)status; +int32_t ConstantAffixModifier::getCodePointCount() const { return fPrefix.countChar32() + fSuffix.countChar32(); } @@ -76,8 +89,38 @@ bool ConstantAffixModifier::isStrong() const { return fStrong; } +bool ConstantAffixModifier::containsField(UNumberFormatFields field) const { + (void)field; + // This method is not currently used. + U_ASSERT(false); + return false; +} + +void ConstantAffixModifier::getParameters(Parameters& output) const { + (void)output; + // This method is not currently used. + U_ASSERT(false); +} + +bool ConstantAffixModifier::semanticallyEquivalent(const Modifier& other) const { + auto* _other = dynamic_cast(&other); + if (_other == nullptr) { + return false; + } + return fPrefix == _other->fPrefix + && fSuffix == _other->fSuffix + && fField == _other->fField + && fStrong == _other->fStrong; +} + + SimpleModifier::SimpleModifier(const SimpleFormatter &simpleFormatter, Field field, bool strong) - : fCompiledPattern(simpleFormatter.compiledPattern), fField(field), fStrong(strong) { + : SimpleModifier(simpleFormatter, field, strong, {}) {} + +SimpleModifier::SimpleModifier(const SimpleFormatter &simpleFormatter, Field field, bool strong, + const Modifier::Parameters parameters) + : fCompiledPattern(simpleFormatter.compiledPattern), fField(field), fStrong(strong), + fParameters(parameters) { int32_t argLimit = SimpleFormatter::getArgumentLimit( fCompiledPattern.getBuffer(), fCompiledPattern.length()); if (argLimit == 0) { @@ -90,15 +133,19 @@ SimpleModifier::SimpleModifier(const SimpleFormatter &simpleFormatter, Field fie } else { U_ASSERT(argLimit == 1); if (fCompiledPattern.charAt(1) != 0) { + // Found prefix fPrefixLength = fCompiledPattern.charAt(1) - ARG_NUM_LIMIT; fSuffixOffset = 3 + fPrefixLength; } else { + // No prefix fPrefixLength = 0; fSuffixOffset = 2; } if (3 + fPrefixLength < fCompiledPattern.length()) { + // Found suffix fSuffixLength = fCompiledPattern.charAt(fSuffixOffset) - ARG_NUM_LIMIT; } else { + // No suffix fSuffixLength = 0; } } @@ -113,13 +160,11 @@ int32_t SimpleModifier::apply(NumberStringBuilder &output, int leftIndex, int ri return formatAsPrefixSuffix(output, leftIndex, rightIndex, fField, status); } -int32_t SimpleModifier::getPrefixLength(UErrorCode &status) const { - (void)status; +int32_t SimpleModifier::getPrefixLength() const { return fPrefixLength; } -int32_t SimpleModifier::getCodePointCount(UErrorCode &status) const { - (void)status; +int32_t SimpleModifier::getCodePointCount() const { int32_t count = 0; if (fPrefixLength > 0) { count += fCompiledPattern.countChar32(2, fPrefixLength); @@ -134,10 +179,35 @@ bool SimpleModifier::isStrong() const { return fStrong; } +bool SimpleModifier::containsField(UNumberFormatFields field) const { + (void)field; + // This method is not currently used. + U_ASSERT(false); + return false; +} + +void SimpleModifier::getParameters(Parameters& output) const { + output = fParameters; +} + +bool SimpleModifier::semanticallyEquivalent(const Modifier& other) const { + auto* _other = dynamic_cast(&other); + if (_other == nullptr) { + return false; + } + if (fParameters.obj != nullptr) { + return fParameters.obj == _other->fParameters.obj; + } + return fCompiledPattern == _other->fCompiledPattern + && fField == _other->fField + && fStrong == _other->fStrong; +} + + int32_t SimpleModifier::formatAsPrefixSuffix(NumberStringBuilder &result, int32_t startIndex, int32_t endIndex, Field field, UErrorCode &status) const { - if (fSuffixOffset == -1) { + if (fSuffixOffset == -1 && fPrefixLength + fSuffixLength > 0) { // There is no argument for the inner number; overwrite the entire segment with our string. return result.splice(startIndex, endIndex, fCompiledPattern, 2, 2 + fPrefixLength, field, status); } else { @@ -157,6 +227,65 @@ SimpleModifier::formatAsPrefixSuffix(NumberStringBuilder &result, int32_t startI } } + +int32_t +SimpleModifier::formatTwoArgPattern(const SimpleFormatter& compiled, NumberStringBuilder& result, + int32_t index, int32_t* outPrefixLength, int32_t* outSuffixLength, + Field field, UErrorCode& status) { + const UnicodeString& compiledPattern = compiled.compiledPattern; + int32_t argLimit = SimpleFormatter::getArgumentLimit( + compiledPattern.getBuffer(), compiledPattern.length()); + if (argLimit != 2) { + status = U_INTERNAL_PROGRAM_ERROR; + return 0; + } + int32_t offset = 1; // offset into compiledPattern + int32_t length = 0; // chars added to result + + int32_t prefixLength = compiledPattern.charAt(offset); + offset++; + if (prefixLength < ARG_NUM_LIMIT) { + // No prefix + prefixLength = 0; + } else { + prefixLength -= ARG_NUM_LIMIT; + result.insert(index + length, compiledPattern, offset, offset + prefixLength, field, status); + offset += prefixLength; + length += prefixLength; + offset++; + } + + int32_t infixLength = compiledPattern.charAt(offset); + offset++; + if (infixLength < ARG_NUM_LIMIT) { + // No infix + infixLength = 0; + } else { + infixLength -= ARG_NUM_LIMIT; + result.insert(index + length, compiledPattern, offset, offset + infixLength, field, status); + offset += infixLength; + length += infixLength; + offset++; + } + + int32_t suffixLength; + if (offset == compiledPattern.length()) { + // No suffix + suffixLength = 0; + } else { + suffixLength = compiledPattern.charAt(offset) - ARG_NUM_LIMIT; + offset++; + result.insert(index + length, compiledPattern, offset, offset + suffixLength, field, status); + length += suffixLength; + } + + *outPrefixLength = prefixLength; + *outSuffixLength = suffixLength; + + return length; +} + + int32_t ConstantMultiFieldModifier::apply(NumberStringBuilder &output, int leftIndex, int rightIndex, UErrorCode &status) const { int32_t length = output.insert(leftIndex, fPrefix, status); @@ -171,13 +300,11 @@ int32_t ConstantMultiFieldModifier::apply(NumberStringBuilder &output, int leftI return length; } -int32_t ConstantMultiFieldModifier::getPrefixLength(UErrorCode &status) const { - (void)status; +int32_t ConstantMultiFieldModifier::getPrefixLength() const { return fPrefix.length(); } -int32_t ConstantMultiFieldModifier::getCodePointCount(UErrorCode &status) const { - (void)status; +int32_t ConstantMultiFieldModifier::getCodePointCount() const { return fPrefix.codePointCount() + fSuffix.codePointCount(); } @@ -185,6 +312,29 @@ bool ConstantMultiFieldModifier::isStrong() const { return fStrong; } +bool ConstantMultiFieldModifier::containsField(UNumberFormatFields field) const { + return fPrefix.containsField(field) || fSuffix.containsField(field); +} + +void ConstantMultiFieldModifier::getParameters(Parameters& output) const { + output = fParameters; +} + +bool ConstantMultiFieldModifier::semanticallyEquivalent(const Modifier& other) const { + auto* _other = dynamic_cast(&other); + if (_other == nullptr) { + return false; + } + if (fParameters.obj != nullptr) { + return fParameters.obj == _other->fParameters.obj; + } + return fPrefix.contentEquals(_other->fPrefix) + && fSuffix.contentEquals(_other->fSuffix) + && fOverwrite == _other->fOverwrite + && fStrong == _other->fStrong; +} + + CurrencySpacingEnabledModifier::CurrencySpacingEnabledModifier(const NumberStringBuilder &prefix, const NumberStringBuilder &suffix, bool overwrite, diff --git a/deps/icu-small/source/i18n/number_modifiers.h b/deps/icu-small/source/i18n/number_modifiers.h index a553100cd92a9b..65ada937d03345 100644 --- a/deps/icu-small/source/i18n/number_modifiers.h +++ b/deps/icu-small/source/i18n/number_modifiers.h @@ -31,12 +31,18 @@ class U_I18N_API ConstantAffixModifier : public Modifier, public UObject { int32_t apply(NumberStringBuilder &output, int32_t leftIndex, int32_t rightIndex, UErrorCode &status) const U_OVERRIDE; - int32_t getPrefixLength(UErrorCode &status) const U_OVERRIDE; + int32_t getPrefixLength() const U_OVERRIDE; - int32_t getCodePointCount(UErrorCode &status) const U_OVERRIDE; + int32_t getCodePointCount() const U_OVERRIDE; bool isStrong() const U_OVERRIDE; + bool containsField(UNumberFormatFields field) const U_OVERRIDE; + + void getParameters(Parameters& output) const U_OVERRIDE; + + bool semanticallyEquivalent(const Modifier& other) const U_OVERRIDE; + private: UnicodeString fPrefix; UnicodeString fSuffix; @@ -52,21 +58,30 @@ class U_I18N_API SimpleModifier : public Modifier, public UMemory { public: SimpleModifier(const SimpleFormatter &simpleFormatter, Field field, bool strong); + SimpleModifier(const SimpleFormatter &simpleFormatter, Field field, bool strong, + const Modifier::Parameters parameters); + // Default constructor for LongNameHandler.h SimpleModifier(); int32_t apply(NumberStringBuilder &output, int32_t leftIndex, int32_t rightIndex, UErrorCode &status) const U_OVERRIDE; - int32_t getPrefixLength(UErrorCode &status) const U_OVERRIDE; + int32_t getPrefixLength() const U_OVERRIDE; - int32_t getCodePointCount(UErrorCode &status) const U_OVERRIDE; + int32_t getCodePointCount() const U_OVERRIDE; bool isStrong() const U_OVERRIDE; + bool containsField(UNumberFormatFields field) const U_OVERRIDE; + + void getParameters(Parameters& output) const U_OVERRIDE; + + bool semanticallyEquivalent(const Modifier& other) const U_OVERRIDE; + /** * TODO: This belongs in SimpleFormatterImpl. The only reason I haven't moved it there yet is because - * DoubleSidedStringBuilder is an internal class and SimpleFormatterImpl feels like it should not depend on it. + * NumberStringBuilder is an internal class and SimpleFormatterImpl feels like it should not depend on it. * *

    * Formats a value that is already stored inside the StringBuilder result between the indices @@ -85,16 +100,33 @@ class U_I18N_API SimpleModifier : public Modifier, public UMemory { * @return The number of characters (UTF-16 code points) that were added to the StringBuilder. */ int32_t - formatAsPrefixSuffix(NumberStringBuilder &result, int32_t startIndex, int32_t endIndex, Field field, - UErrorCode &status) const; + formatAsPrefixSuffix(NumberStringBuilder& result, int32_t startIndex, int32_t endIndex, Field field, + UErrorCode& status) const; + + /** + * TODO: Like above, this belongs with the rest of the SimpleFormatterImpl code. + * I put it here so that the SimpleFormatter uses in NumberStringBuilder are near each other. + * + *

    + * Applies the compiled two-argument pattern to the NumberStringBuilder. + * + *

    + * This method is optimized for the case where the prefix and suffix are often empty, such as + * in the range pattern like "{0}-{1}". + */ + static int32_t + formatTwoArgPattern(const SimpleFormatter& compiled, NumberStringBuilder& result, + int32_t index, int32_t* outPrefixLength, int32_t* outSuffixLength, + Field field, UErrorCode& status); private: UnicodeString fCompiledPattern; Field fField; - bool fStrong; - int32_t fPrefixLength; - int32_t fSuffixOffset; - int32_t fSuffixLength; + bool fStrong = false; + int32_t fPrefixLength = 0; + int32_t fSuffixOffset = -1; + int32_t fSuffixLength = 0; + Modifier::Parameters fParameters; }; /** @@ -103,6 +135,18 @@ class U_I18N_API SimpleModifier : public Modifier, public UMemory { */ class U_I18N_API ConstantMultiFieldModifier : public Modifier, public UMemory { public: + ConstantMultiFieldModifier( + const NumberStringBuilder &prefix, + const NumberStringBuilder &suffix, + bool overwrite, + bool strong, + const Modifier::Parameters parameters) + : fPrefix(prefix), + fSuffix(suffix), + fOverwrite(overwrite), + fStrong(strong), + fParameters(parameters) {} + ConstantMultiFieldModifier( const NumberStringBuilder &prefix, const NumberStringBuilder &suffix, @@ -116,12 +160,18 @@ class U_I18N_API ConstantMultiFieldModifier : public Modifier, public UMemory { int32_t apply(NumberStringBuilder &output, int32_t leftIndex, int32_t rightIndex, UErrorCode &status) const U_OVERRIDE; - int32_t getPrefixLength(UErrorCode &status) const U_OVERRIDE; + int32_t getPrefixLength() const U_OVERRIDE; - int32_t getCodePointCount(UErrorCode &status) const U_OVERRIDE; + int32_t getCodePointCount() const U_OVERRIDE; bool isStrong() const U_OVERRIDE; + bool containsField(UNumberFormatFields field) const U_OVERRIDE; + + void getParameters(Parameters& output) const U_OVERRIDE; + + bool semanticallyEquivalent(const Modifier& other) const U_OVERRIDE; + protected: // NOTE: In Java, these are stored as array pointers. In C++, the NumberStringBuilder is stored by // value and is treated internally as immutable. @@ -129,6 +179,7 @@ class U_I18N_API ConstantMultiFieldModifier : public Modifier, public UMemory { NumberStringBuilder fSuffix; bool fOverwrite; bool fStrong; + Modifier::Parameters fParameters; }; /** Identical to {@link ConstantMultiFieldModifier}, but supports currency spacing. */ @@ -192,13 +243,11 @@ class U_I18N_API EmptyModifier : public Modifier, public UMemory { return 0; } - int32_t getPrefixLength(UErrorCode &status) const U_OVERRIDE { - (void)status; + int32_t getPrefixLength() const U_OVERRIDE { return 0; } - int32_t getCodePointCount(UErrorCode &status) const U_OVERRIDE { - (void)status; + int32_t getCodePointCount() const U_OVERRIDE { return 0; } @@ -206,55 +255,75 @@ class U_I18N_API EmptyModifier : public Modifier, public UMemory { return fStrong; } + bool containsField(UNumberFormatFields field) const U_OVERRIDE { + (void)field; + return false; + } + + void getParameters(Parameters& output) const U_OVERRIDE { + output.obj = nullptr; + } + + bool semanticallyEquivalent(const Modifier& other) const U_OVERRIDE { + return other.getCodePointCount() == 0; + } + private: bool fStrong; }; /** - * A ParameterizedModifier by itself is NOT a Modifier. Rather, it wraps a data structure containing two or more - * Modifiers and returns the modifier appropriate for the current situation. + * This implementation of ModifierStore adopts Modifer pointers. */ -class U_I18N_API ParameterizedModifier : public UMemory { +class U_I18N_API AdoptingModifierStore : public ModifierStore, public UMemory { public: - // NOTE: mods is zero-initialized (to nullptr) - ParameterizedModifier() : mods() { - } + virtual ~AdoptingModifierStore(); - // No copying! - ParameterizedModifier(const ParameterizedModifier &other) = delete; + static constexpr StandardPlural::Form DEFAULT_STANDARD_PLURAL = StandardPlural::OTHER; - ~ParameterizedModifier() { - for (const Modifier *mod : mods) { - delete mod; - } - } + AdoptingModifierStore() = default; - void adoptPositiveNegativeModifiers( - const Modifier *positive, const Modifier *zero, const Modifier *negative) { - mods[2] = positive; - mods[1] = zero; - mods[0] = negative; - } + // No copying! + AdoptingModifierStore(const AdoptingModifierStore &other) = delete; - /** The modifier is ADOPTED. */ - void adoptSignPluralModifier(int8_t signum, StandardPlural::Form plural, const Modifier *mod) { + /** + * Sets the Modifier with the specified signum and plural form. + */ + void adoptModifier(int8_t signum, StandardPlural::Form plural, const Modifier *mod) { + U_ASSERT(mods[getModIndex(signum, plural)] == nullptr); mods[getModIndex(signum, plural)] = mod; } + /** + * Sets the Modifier with the specified signum. + * The modifier will apply to all plural forms. + */ + void adoptModifierWithoutPlural(int8_t signum, const Modifier *mod) { + U_ASSERT(mods[getModIndex(signum, DEFAULT_STANDARD_PLURAL)] == nullptr); + mods[getModIndex(signum, DEFAULT_STANDARD_PLURAL)] = mod; + } + /** Returns a reference to the modifier; no ownership change. */ - const Modifier *getModifier(int8_t signum) const { - return mods[signum + 1]; + const Modifier *getModifier(int8_t signum, StandardPlural::Form plural) const U_OVERRIDE { + const Modifier* modifier = mods[getModIndex(signum, plural)]; + if (modifier == nullptr && plural != DEFAULT_STANDARD_PLURAL) { + modifier = mods[getModIndex(signum, DEFAULT_STANDARD_PLURAL)]; + } + return modifier; } /** Returns a reference to the modifier; no ownership change. */ - const Modifier *getModifier(int8_t signum, StandardPlural::Form plural) const { - return mods[getModIndex(signum, plural)]; + const Modifier *getModifierWithoutPlural(int8_t signum) const { + return mods[getModIndex(signum, DEFAULT_STANDARD_PLURAL)]; } private: - const Modifier *mods[3 * StandardPlural::COUNT]; + // NOTE: mods is zero-initialized (to nullptr) + const Modifier *mods[3 * StandardPlural::COUNT] = {}; inline static int32_t getModIndex(int8_t signum, StandardPlural::Form plural) { + U_ASSERT(signum >= -1 && signum <= 1); + U_ASSERT(plural >= 0 && plural < StandardPlural::COUNT); return static_cast(plural) * 3 + (signum + 1); } }; diff --git a/deps/icu-small/source/i18n/number_multiplier.cpp b/deps/icu-small/source/i18n/number_multiplier.cpp index a27142c9bd689b..ecb50dd9b82019 100644 --- a/deps/icu-small/source/i18n/number_multiplier.cpp +++ b/deps/icu-small/source/i18n/number_multiplier.cpp @@ -143,14 +143,14 @@ void Scale::applyReciprocalTo(impl::DecimalQuantity& quantity) const { void MultiplierFormatHandler::setAndChain(const Scale& multiplier, const MicroPropsGenerator* parent) { - this->multiplier = multiplier; - this->parent = parent; + fMultiplier = multiplier; + fParent = parent; } void MultiplierFormatHandler::processQuantity(DecimalQuantity& quantity, MicroProps& micros, UErrorCode& status) const { - parent->processQuantity(quantity, micros, status); - multiplier.applyTo(quantity); + fParent->processQuantity(quantity, micros, status); + fMultiplier.applyTo(quantity); } #endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/deps/icu-small/source/i18n/number_multiplier.h b/deps/icu-small/source/i18n/number_multiplier.h index 82c30c78426cdb..d8235dc601b559 100644 --- a/deps/icu-small/source/i18n/number_multiplier.h +++ b/deps/icu-small/source/i18n/number_multiplier.h @@ -28,8 +28,8 @@ class U_I18N_API MultiplierFormatHandler : public MicroPropsGenerator, public UM UErrorCode& status) const U_OVERRIDE; private: - Scale multiplier; - const MicroPropsGenerator *parent; + Scale fMultiplier; + const MicroPropsGenerator *fParent; }; diff --git a/deps/icu-small/source/i18n/number_padding.cpp b/deps/icu-small/source/i18n/number_padding.cpp index 97e7b6014f9aac..31684d7208b606 100644 --- a/deps/icu-small/source/i18n/number_padding.cpp +++ b/deps/icu-small/source/i18n/number_padding.cpp @@ -62,7 +62,7 @@ Padder Padder::forProperties(const DecimalFormatProperties& properties) { int32_t Padder::padAndApply(const Modifier &mod1, const Modifier &mod2, NumberStringBuilder &string, int32_t leftIndex, int32_t rightIndex, UErrorCode &status) const { - int32_t modLength = mod1.getCodePointCount(status) + mod2.getCodePointCount(status); + int32_t modLength = mod1.getCodePointCount() + mod2.getCodePointCount(); int32_t requiredPadding = fWidth - modLength - string.codePointCount(); U_ASSERT(leftIndex == 0 && rightIndex == string.length()); // fix the previous line to remove this assertion diff --git a/deps/icu-small/source/i18n/number_patternmodifier.cpp b/deps/icu-small/source/i18n/number_patternmodifier.cpp index 6417e14378bea6..4c61a0d35bca82 100644 --- a/deps/icu-small/source/i18n/number_patternmodifier.cpp +++ b/deps/icu-small/source/i18n/number_patternmodifier.cpp @@ -24,11 +24,11 @@ MutablePatternModifier::MutablePatternModifier(bool isStrong) : fStrong(isStrong) {} void MutablePatternModifier::setPatternInfo(const AffixPatternProvider* patternInfo) { - this->patternInfo = patternInfo; + fPatternInfo = patternInfo; } void MutablePatternModifier::setPatternAttributes(UNumberSignDisplay signDisplay, bool perMille) { - this->signDisplay = signDisplay; + fSignDisplay = signDisplay; this->perMilleReplacesPercent = perMille; } @@ -36,20 +36,20 @@ void MutablePatternModifier::setSymbols(const DecimalFormatSymbols* symbols, const CurrencySymbols* currencySymbols, const UNumberUnitWidth unitWidth, const PluralRules* rules) { U_ASSERT((rules != nullptr) == needsPlurals()); - this->symbols = symbols; - this->currencySymbols = currencySymbols; - this->unitWidth = unitWidth; - this->rules = rules; + fSymbols = symbols; + fCurrencySymbols = currencySymbols; + fUnitWidth = unitWidth; + fRules = rules; } void MutablePatternModifier::setNumberProperties(int8_t signum, StandardPlural::Form plural) { - this->signum = signum; - this->plural = plural; + fSignum = signum; + fPlural = plural; } bool MutablePatternModifier::needsPlurals() const { UErrorCode statusLocal = U_ZERO_ERROR; - return patternInfo->containsSymbolType(AffixPatternType::TYPE_CURRENCY_TRIPLE, statusLocal); + return fPatternInfo->containsSymbolType(AffixPatternType::TYPE_CURRENCY_TRIPLE, statusLocal); // Silently ignore any error codes. } @@ -69,7 +69,7 @@ MutablePatternModifier::createImmutableAndChain(const MicroPropsGenerator* paren StandardPlural::Form::MANY, StandardPlural::Form::OTHER}; - auto pm = new ParameterizedModifier(); + auto pm = new AdoptingModifierStore(); if (pm == nullptr) { status = U_MEMORY_ALLOCATION_ERROR; return nullptr; @@ -79,26 +79,25 @@ MutablePatternModifier::createImmutableAndChain(const MicroPropsGenerator* paren // Slower path when we require the plural keyword. for (StandardPlural::Form plural : STANDARD_PLURAL_VALUES) { setNumberProperties(1, plural); - pm->adoptSignPluralModifier(1, plural, createConstantModifier(status)); + pm->adoptModifier(1, plural, createConstantModifier(status)); setNumberProperties(0, plural); - pm->adoptSignPluralModifier(0, plural, createConstantModifier(status)); + pm->adoptModifier(0, plural, createConstantModifier(status)); setNumberProperties(-1, plural); - pm->adoptSignPluralModifier(-1, plural, createConstantModifier(status)); + pm->adoptModifier(-1, plural, createConstantModifier(status)); } if (U_FAILURE(status)) { delete pm; return nullptr; } - return new ImmutablePatternModifier(pm, rules, parent); // adopts pm + return new ImmutablePatternModifier(pm, fRules, parent); // adopts pm } else { // Faster path when plural keyword is not needed. setNumberProperties(1, StandardPlural::Form::COUNT); - Modifier* positive = createConstantModifier(status); + pm->adoptModifierWithoutPlural(1, createConstantModifier(status)); setNumberProperties(0, StandardPlural::Form::COUNT); - Modifier* zero = createConstantModifier(status); + pm->adoptModifierWithoutPlural(0, createConstantModifier(status)); setNumberProperties(-1, StandardPlural::Form::COUNT); - Modifier* negative = createConstantModifier(status); - pm->adoptPositiveNegativeModifiers(positive, zero, negative); + pm->adoptModifierWithoutPlural(-1, createConstantModifier(status)); if (U_FAILURE(status)) { delete pm; return nullptr; @@ -112,15 +111,15 @@ ConstantMultiFieldModifier* MutablePatternModifier::createConstantModifier(UErro NumberStringBuilder b; insertPrefix(a, 0, status); insertSuffix(b, 0, status); - if (patternInfo->hasCurrencySign()) { + if (fPatternInfo->hasCurrencySign()) { return new CurrencySpacingEnabledModifier( - a, b, !patternInfo->hasBody(), fStrong, *symbols, status); + a, b, !fPatternInfo->hasBody(), fStrong, *fSymbols, status); } else { - return new ConstantMultiFieldModifier(a, b, !patternInfo->hasBody(), fStrong); + return new ConstantMultiFieldModifier(a, b, !fPatternInfo->hasBody(), fStrong); } } -ImmutablePatternModifier::ImmutablePatternModifier(ParameterizedModifier* pm, const PluralRules* rules, +ImmutablePatternModifier::ImmutablePatternModifier(AdoptingModifierStore* pm, const PluralRules* rules, const MicroPropsGenerator* parent) : pm(pm), rules(rules), parent(parent) {} @@ -132,7 +131,7 @@ void ImmutablePatternModifier::processQuantity(DecimalQuantity& quantity, MicroP void ImmutablePatternModifier::applyToMicros(MicroProps& micros, DecimalQuantity& quantity) const { if (rules == nullptr) { - micros.modMiddle = pm->getModifier(quantity.signum()); + micros.modMiddle = pm->getModifierWithoutPlural(quantity.signum()); } else { // TODO: Fix this. Avoid the copy. DecimalQuantity copy(quantity); @@ -144,7 +143,7 @@ void ImmutablePatternModifier::applyToMicros(MicroProps& micros, DecimalQuantity const Modifier* ImmutablePatternModifier::getModifier(int8_t signum, StandardPlural::Form plural) const { if (rules == nullptr) { - return pm->getModifier(signum); + return pm->getModifierWithoutPlural(signum); } else { return pm->getModifier(signum, plural); } @@ -153,13 +152,13 @@ const Modifier* ImmutablePatternModifier::getModifier(int8_t signum, StandardPlu /** Used by the unsafe code path. */ MicroPropsGenerator& MutablePatternModifier::addToChain(const MicroPropsGenerator* parent) { - this->parent = parent; + fParent = parent; return *this; } void MutablePatternModifier::processQuantity(DecimalQuantity& fq, MicroProps& micros, UErrorCode& status) const { - parent->processQuantity(fq, micros, status); + fParent->processQuantity(fq, micros, status); // The unsafe code path performs self-mutation, so we need a const_cast. // This method needs to be const because it overrides a const method in the parent class. auto nonConstThis = const_cast(this); @@ -167,7 +166,7 @@ void MutablePatternModifier::processQuantity(DecimalQuantity& fq, MicroProps& mi // TODO: Fix this. Avoid the copy. DecimalQuantity copy(fq); micros.rounder.apply(copy, status); - nonConstThis->setNumberProperties(fq.signum(), utils::getStandardPlural(rules, copy)); + nonConstThis->setNumberProperties(fq.signum(), utils::getStandardPlural(fRules, copy)); } else { nonConstThis->setNumberProperties(fq.signum(), StandardPlural::Form::COUNT); } @@ -183,7 +182,7 @@ int32_t MutablePatternModifier::apply(NumberStringBuilder& output, int32_t leftI int32_t suffixLen = nonConstThis->insertSuffix(output, rightIndex + prefixLen, status); // If the pattern had no decimal stem body (like #,##0.00), overwrite the value. int32_t overwriteLen = 0; - if (!patternInfo->hasBody()) { + if (!fPatternInfo->hasBody()) { overwriteLen = output.splice( leftIndex + prefixLen, rightIndex + prefixLen, @@ -199,28 +198,30 @@ int32_t MutablePatternModifier::apply(NumberStringBuilder& output, int32_t leftI prefixLen, rightIndex + overwriteLen + prefixLen, suffixLen, - *symbols, + *fSymbols, status); return prefixLen + overwriteLen + suffixLen; } -int32_t MutablePatternModifier::getPrefixLength(UErrorCode& status) const { +int32_t MutablePatternModifier::getPrefixLength() const { // The unsafe code path performs self-mutation, so we need a const_cast. // This method needs to be const because it overrides a const method in the parent class. auto nonConstThis = const_cast(this); // Enter and exit CharSequence Mode to get the length. + UErrorCode status = U_ZERO_ERROR; // status fails only with an iilegal argument exception nonConstThis->prepareAffix(true); int result = AffixUtils::unescapedCodePointCount(currentAffix, *this, status); // prefix length return result; } -int32_t MutablePatternModifier::getCodePointCount(UErrorCode& status) const { +int32_t MutablePatternModifier::getCodePointCount() const { // The unsafe code path performs self-mutation, so we need a const_cast. // This method needs to be const because it overrides a const method in the parent class. auto nonConstThis = const_cast(this); // Render the affixes to get the length + UErrorCode status = U_ZERO_ERROR; // status fails only with an iilegal argument exception nonConstThis->prepareAffix(true); int result = AffixUtils::unescapedCodePointCount(currentAffix, *this, status); // prefix length nonConstThis->prepareAffix(false); @@ -232,6 +233,26 @@ bool MutablePatternModifier::isStrong() const { return fStrong; } +bool MutablePatternModifier::containsField(UNumberFormatFields field) const { + (void)field; + // This method is not currently used. + U_ASSERT(false); + return false; +} + +void MutablePatternModifier::getParameters(Parameters& output) const { + (void)output; + // This method is not currently used. + U_ASSERT(false); +} + +bool MutablePatternModifier::semanticallyEquivalent(const Modifier& other) const { + (void)other; + // This method is not currently used. + U_ASSERT(false); + return false; +} + int32_t MutablePatternModifier::insertPrefix(NumberStringBuilder& sb, int position, UErrorCode& status) { prepareAffix(true); int length = AffixUtils::unescape(currentAffix, sb, position, *this, status); @@ -247,40 +268,40 @@ int32_t MutablePatternModifier::insertSuffix(NumberStringBuilder& sb, int positi /** This method contains the heart of the logic for rendering LDML affix strings. */ void MutablePatternModifier::prepareAffix(bool isPrefix) { PatternStringUtils::patternInfoToStringBuilder( - *patternInfo, isPrefix, signum, signDisplay, plural, perMilleReplacesPercent, currentAffix); + *fPatternInfo, isPrefix, fSignum, fSignDisplay, fPlural, perMilleReplacesPercent, currentAffix); } UnicodeString MutablePatternModifier::getSymbol(AffixPatternType type) const { UErrorCode localStatus = U_ZERO_ERROR; switch (type) { case AffixPatternType::TYPE_MINUS_SIGN: - return symbols->getSymbol(DecimalFormatSymbols::ENumberFormatSymbol::kMinusSignSymbol); + return fSymbols->getSymbol(DecimalFormatSymbols::ENumberFormatSymbol::kMinusSignSymbol); case AffixPatternType::TYPE_PLUS_SIGN: - return symbols->getSymbol(DecimalFormatSymbols::ENumberFormatSymbol::kPlusSignSymbol); + return fSymbols->getSymbol(DecimalFormatSymbols::ENumberFormatSymbol::kPlusSignSymbol); case AffixPatternType::TYPE_PERCENT: - return symbols->getSymbol(DecimalFormatSymbols::ENumberFormatSymbol::kPercentSymbol); + return fSymbols->getSymbol(DecimalFormatSymbols::ENumberFormatSymbol::kPercentSymbol); case AffixPatternType::TYPE_PERMILLE: - return symbols->getSymbol(DecimalFormatSymbols::ENumberFormatSymbol::kPerMillSymbol); + return fSymbols->getSymbol(DecimalFormatSymbols::ENumberFormatSymbol::kPerMillSymbol); case AffixPatternType::TYPE_CURRENCY_SINGLE: { // UnitWidth ISO and HIDDEN overrides the singular currency symbol. - if (unitWidth == UNumberUnitWidth::UNUM_UNIT_WIDTH_ISO_CODE) { - return currencySymbols->getIntlCurrencySymbol(localStatus); - } else if (unitWidth == UNumberUnitWidth::UNUM_UNIT_WIDTH_HIDDEN) { + if (fUnitWidth == UNumberUnitWidth::UNUM_UNIT_WIDTH_ISO_CODE) { + return fCurrencySymbols->getIntlCurrencySymbol(localStatus); + } else if (fUnitWidth == UNumberUnitWidth::UNUM_UNIT_WIDTH_HIDDEN) { return UnicodeString(); - } else if (unitWidth == UNumberUnitWidth::UNUM_UNIT_WIDTH_NARROW) { - return currencySymbols->getNarrowCurrencySymbol(localStatus); + } else if (fUnitWidth == UNumberUnitWidth::UNUM_UNIT_WIDTH_NARROW) { + return fCurrencySymbols->getNarrowCurrencySymbol(localStatus); } else { - return currencySymbols->getCurrencySymbol(localStatus); + return fCurrencySymbols->getCurrencySymbol(localStatus); } } case AffixPatternType::TYPE_CURRENCY_DOUBLE: - return currencySymbols->getIntlCurrencySymbol(localStatus); + return fCurrencySymbols->getIntlCurrencySymbol(localStatus); case AffixPatternType::TYPE_CURRENCY_TRIPLE: // NOTE: This is the code path only for patterns containing "¤¤¤". // Plural currencies set via the API are formatted in LongNameHandler. // This code path is used by DecimalFormat via CurrencyPluralInfo. - U_ASSERT(plural != StandardPlural::Form::COUNT); - return currencySymbols->getPluralName(plural, localStatus); + U_ASSERT(fPlural != StandardPlural::Form::COUNT); + return fCurrencySymbols->getPluralName(fPlural, localStatus); case AffixPatternType::TYPE_CURRENCY_QUAD: return UnicodeString(u"\uFFFD"); case AffixPatternType::TYPE_CURRENCY_QUINT: diff --git a/deps/icu-small/source/i18n/number_patternmodifier.h b/deps/icu-small/source/i18n/number_patternmodifier.h index f1359bd5747d89..ea80d6305e75b4 100644 --- a/deps/icu-small/source/i18n/number_patternmodifier.h +++ b/deps/icu-small/source/i18n/number_patternmodifier.h @@ -18,13 +18,13 @@ U_NAMESPACE_BEGIN // Export an explicit template instantiation of the LocalPointer that is used as a -// data member of ParameterizedModifier. +// data member of AdoptingModifierStore. // (When building DLLs for Windows this is required.) #if U_PF_WINDOWS <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN // Ignore warning 4661 as LocalPointerBase does not use operator== or operator!= #pragma warning(suppress: 4661) -template class U_I18N_API LocalPointerBase; -template class U_I18N_API LocalPointer; +template class U_I18N_API LocalPointerBase; +template class U_I18N_API LocalPointer; #endif namespace number { @@ -45,10 +45,10 @@ class U_I18N_API ImmutablePatternModifier : public MicroPropsGenerator, public U const Modifier* getModifier(int8_t signum, StandardPlural::Form plural) const; private: - ImmutablePatternModifier(ParameterizedModifier* pm, const PluralRules* rules, + ImmutablePatternModifier(AdoptingModifierStore* pm, const PluralRules* rules, const MicroPropsGenerator* parent); - const LocalPointer pm; + const LocalPointer pm; const PluralRules* rules; const MicroPropsGenerator* parent; @@ -178,12 +178,18 @@ class U_I18N_API MutablePatternModifier int32_t apply(NumberStringBuilder &output, int32_t leftIndex, int32_t rightIndex, UErrorCode &status) const U_OVERRIDE; - int32_t getPrefixLength(UErrorCode &status) const U_OVERRIDE; + int32_t getPrefixLength() const U_OVERRIDE; - int32_t getCodePointCount(UErrorCode &status) const U_OVERRIDE; + int32_t getCodePointCount() const U_OVERRIDE; bool isStrong() const U_OVERRIDE; + bool containsField(UNumberFormatFields field) const U_OVERRIDE; + + void getParameters(Parameters& output) const U_OVERRIDE; + + bool semanticallyEquivalent(const Modifier& other) const U_OVERRIDE; + /** * Returns the string that substitutes a given symbol type in a pattern. */ @@ -196,22 +202,22 @@ class U_I18N_API MutablePatternModifier const bool fStrong; // Pattern details (initialized in setPatternInfo and setPatternAttributes) - const AffixPatternProvider *patternInfo; - UNumberSignDisplay signDisplay; + const AffixPatternProvider *fPatternInfo; + UNumberSignDisplay fSignDisplay; bool perMilleReplacesPercent; // Symbol details (initialized in setSymbols) - const DecimalFormatSymbols *symbols; - UNumberUnitWidth unitWidth; - const CurrencySymbols *currencySymbols; - const PluralRules *rules; + const DecimalFormatSymbols *fSymbols; + UNumberUnitWidth fUnitWidth; + const CurrencySymbols *fCurrencySymbols; + const PluralRules *fRules; // Number details (initialized in setNumberProperties) - int8_t signum; - StandardPlural::Form plural; + int8_t fSignum; + StandardPlural::Form fPlural; // QuantityChain details (initialized in addToChain) - const MicroPropsGenerator *parent; + const MicroPropsGenerator *fParent; // Transient fields for rendering UnicodeString currentAffix; diff --git a/deps/icu-small/source/i18n/number_scientific.cpp b/deps/icu-small/source/i18n/number_scientific.cpp index 40952024e995cc..07c1ce9dac2c89 100644 --- a/deps/icu-small/source/i18n/number_scientific.cpp +++ b/deps/icu-small/source/i18n/number_scientific.cpp @@ -76,17 +76,16 @@ int32_t ScientificModifier::apply(NumberStringBuilder &output, int32_t /*leftInd return i - rightIndex; } -int32_t ScientificModifier::getPrefixLength(UErrorCode &status) const { - (void)status; +int32_t ScientificModifier::getPrefixLength() const { // TODO: Localized exponent separator location. return 0; } -int32_t ScientificModifier::getCodePointCount(UErrorCode &status) const { - (void)status; - // This method is not used for strong modifiers. - U_ASSERT(false); - return 0; +int32_t ScientificModifier::getCodePointCount() const { + // NOTE: This method is only called one place, NumberRangeFormatterImpl. + // The call site only cares about != 0 and != 1. + // Return a very large value so that if this method is used elsewhere, we should notice. + return 999; } bool ScientificModifier::isStrong() const { @@ -94,6 +93,27 @@ bool ScientificModifier::isStrong() const { return true; } +bool ScientificModifier::containsField(UNumberFormatFields field) const { + (void)field; + // This method is not used for inner modifiers. + U_ASSERT(false); + return false; +} + +void ScientificModifier::getParameters(Parameters& output) const { + // Not part of any plural sets + output.obj = nullptr; +} + +bool ScientificModifier::semanticallyEquivalent(const Modifier& other) const { + auto* _other = dynamic_cast(&other); + if (_other == nullptr) { + return false; + } + // TODO: Check for locale symbols and settings as well? Could be less efficient. + return fExponent == _other->fExponent; +} + // Note: Visual Studio does not compile this function without full name space. Why? icu::number::impl::ScientificHandler::ScientificHandler(const Notation *notation, const DecimalFormatSymbols *symbols, const MicroPropsGenerator *parent) : diff --git a/deps/icu-small/source/i18n/number_scientific.h b/deps/icu-small/source/i18n/number_scientific.h index 974ab3adb614ca..e377bd941efaeb 100644 --- a/deps/icu-small/source/i18n/number_scientific.h +++ b/deps/icu-small/source/i18n/number_scientific.h @@ -24,12 +24,18 @@ class U_I18N_API ScientificModifier : public UMemory, public Modifier { int32_t apply(NumberStringBuilder &output, int32_t leftIndex, int32_t rightIndex, UErrorCode &status) const U_OVERRIDE; - int32_t getPrefixLength(UErrorCode &status) const U_OVERRIDE; + int32_t getPrefixLength() const U_OVERRIDE; - int32_t getCodePointCount(UErrorCode &status) const U_OVERRIDE; + int32_t getCodePointCount() const U_OVERRIDE; bool isStrong() const U_OVERRIDE; + bool containsField(UNumberFormatFields field) const U_OVERRIDE; + + void getParameters(Parameters& output) const U_OVERRIDE; + + bool semanticallyEquivalent(const Modifier& other) const U_OVERRIDE; + private: int32_t fExponent; const ScientificHandler *fHandler; diff --git a/deps/icu-small/source/i18n/number_stringbuilder.cpp b/deps/icu-small/source/i18n/number_stringbuilder.cpp index 37770d11d51dfb..74ba33fbbc159f 100644 --- a/deps/icu-small/source/i18n/number_stringbuilder.cpp +++ b/deps/icu-small/source/i18n/number_stringbuilder.cpp @@ -241,6 +241,9 @@ NumberStringBuilder::insert(int32_t index, const NumberStringBuilder &other, UEr } int32_t NumberStringBuilder::prepareForInsert(int32_t index, int32_t count, UErrorCode &status) { + U_ASSERT(index >= 0); + U_ASSERT(index <= fLength); + U_ASSERT(count >= 0); if (index == 0 && fZero - count >= 0) { // Append to start fZero -= count; @@ -485,4 +488,13 @@ void NumberStringBuilder::getAllFieldPositions(FieldPositionIteratorHandler& fpi } } +bool NumberStringBuilder::containsField(Field field) const { + for (int32_t i = 0; i < fLength; i++) { + if (field == fieldAt(i)) { + return true; + } + } + return false; +} + #endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/deps/icu-small/source/i18n/number_stringbuilder.h b/deps/icu-small/source/i18n/number_stringbuilder.h index cd8ce2f805e994..b14ad9ede2f90f 100644 --- a/deps/icu-small/source/i18n/number_stringbuilder.h +++ b/deps/icu-small/source/i18n/number_stringbuilder.h @@ -106,6 +106,8 @@ class U_I18N_API NumberStringBuilder : public UMemory { void getAllFieldPositions(FieldPositionIteratorHandler& fpih, UErrorCode& status) const; + bool containsField(Field field) const; + private: bool fUsingHeap = false; ValueOrHeapArray fChars; diff --git a/deps/icu-small/source/i18n/number_types.h b/deps/icu-small/source/i18n/number_types.h index 57da72f8aa0ac1..00a6818869fdc2 100644 --- a/deps/icu-small/source/i18n/number_types.h +++ b/deps/icu-small/source/i18n/number_types.h @@ -16,6 +16,7 @@ #include "uassert.h" #include "unicode/platform.h" #include "unicode/uniset.h" +#include "standardplural.h" U_NAMESPACE_BEGIN namespace number { namespace impl { @@ -45,6 +46,7 @@ class Modifier; class MutablePatternModifier; class DecimalQuantity; class NumberStringBuilder; +class ModifierStore; struct MicroProps; @@ -127,12 +129,13 @@ class U_I18N_API AffixPatternProvider { virtual bool hasBody() const = 0; }; + /** * A Modifier is an object that can be passed through the formatting pipeline until it is finally applied to the string * builder. A Modifier usually contains a prefix and a suffix that are applied, but it could contain something else, * like a {@link com.ibm.icu.text.SimpleFormatter} pattern. * - * A Modifier is usually immutable, except in cases such as {@link MurkyModifier}, which are mutable for performance + * A Modifier is usually immutable, except in cases such as {@link MutablePatternModifier}, which are mutable for performance * reasons. * * Exported as U_I18N_API because it is a base class for other exported types @@ -162,12 +165,12 @@ class U_I18N_API Modifier { * * @return The number of characters (UTF-16 code units) in the prefix. */ - virtual int32_t getPrefixLength(UErrorCode& status) const = 0; + virtual int32_t getPrefixLength() const = 0; /** * Returns the number of code points in the modifier, prefix plus suffix. */ - virtual int32_t getCodePointCount(UErrorCode& status) const = 0; + virtual int32_t getCodePointCount() const = 0; /** * Whether this modifier is strong. If a modifier is strong, it should always be applied immediately and not allowed @@ -177,8 +180,57 @@ class U_I18N_API Modifier { * @return Whether the modifier is strong. */ virtual bool isStrong() const = 0; + + /** + * Whether the modifier contains at least one occurrence of the given field. + */ + virtual bool containsField(UNumberFormatFields field) const = 0; + + /** + * A fill-in for getParameters(). obj will always be set; if non-null, the other + * two fields are also safe to read. + */ + struct U_I18N_API Parameters { + const ModifierStore* obj = nullptr; + int8_t signum; + StandardPlural::Form plural; + + Parameters(); + Parameters(const ModifierStore* _obj, int8_t _signum, StandardPlural::Form _plural); + }; + + /** + * Gets a set of "parameters" for this Modifier. + * + * TODO: Make this return a `const Parameters*` more like Java? + */ + virtual void getParameters(Parameters& output) const = 0; + + /** + * Returns whether this Modifier is *semantically equivalent* to the other Modifier; + * in many cases, this is the same as equal, but parameters should be ignored. + */ + virtual bool semanticallyEquivalent(const Modifier& other) const = 0; }; + +/** + * This is *not* a modifier; rather, it is an object that can return modifiers + * based on given parameters. + * + * Exported as U_I18N_API because it is a base class for other exported types. + */ +class U_I18N_API ModifierStore { + public: + virtual ~ModifierStore(); + + /** + * Returns a Modifier with the given parameters (best-effort). + */ + virtual const Modifier* getModifier(int8_t signum, StandardPlural::Form plural) const = 0; +}; + + /** * This interface is used when all number formatting settings, including the locale, are known, except for the quantity * itself. The {@link #processQuantity} method performs the final step in the number processing pipeline: it uses the diff --git a/deps/icu-small/source/i18n/numfmt.cpp b/deps/icu-small/source/i18n/numfmt.cpp index 13f23131b1851b..ef47e1e01b5ee6 100644 --- a/deps/icu-small/source/i18n/numfmt.cpp +++ b/deps/icu-small/source/i18n/numfmt.cpp @@ -1326,13 +1326,13 @@ NumberFormat::makeInstance(const Locale& desiredLocale, // if the locale has "@compat=host", create a host-specific NumberFormat if (U_SUCCESS(status) && count > 0 && uprv_strcmp(buffer, "host") == 0) { - Win32NumberFormat *f = NULL; UBool curr = TRUE; switch (style) { case UNUM_DECIMAL: curr = FALSE; // fall-through + U_FALLTHROUGH; case UNUM_CURRENCY: case UNUM_CURRENCY_ISO: // do not support plural formatting here @@ -1340,14 +1340,13 @@ NumberFormat::makeInstance(const Locale& desiredLocale, case UNUM_CURRENCY_ACCOUNTING: case UNUM_CASH_CURRENCY: case UNUM_CURRENCY_STANDARD: - f = new Win32NumberFormat(desiredLocale, curr, status); - + { + LocalPointer f(new Win32NumberFormat(desiredLocale, curr, status), status); if (U_SUCCESS(status)) { - return f; + return f.orphan(); } - - delete f; - break; + } + break; default: break; } @@ -1417,8 +1416,7 @@ NumberFormat::makeInstance(const Locale& desiredLocale, } } - - NumberFormat *f; + LocalPointer f; if (ns->isAlgorithmic()) { UnicodeString nsDesc; UnicodeString nsRuleSetGroup; @@ -1453,7 +1451,7 @@ NumberFormat::makeInstance(const Locale& desiredLocale, return NULL; } r->setDefaultRuleSet(nsRuleSetName,status); - f = r; + f.adoptInstead(r); } else { // replace single currency sign in the pattern with double currency sign // if the style is UNUM_CURRENCY_ISO @@ -1462,9 +1460,22 @@ NumberFormat::makeInstance(const Locale& desiredLocale, UnicodeString(TRUE, gDoubleCurrencySign, 2)); } - // "new DecimalFormat()" does not adopt the symbols if its memory allocation fails. - DecimalFormatSymbols *syms = symbolsToAdopt.orphan(); - DecimalFormat* df = new DecimalFormat(pattern, syms, style, status); + // "new DecimalFormat()" does not adopt the symbols argument if its memory allocation fails. + // So we can't use adoptInsteadAndCheckErrorCode as we need to know if the 'new' failed. + DecimalFormatSymbols *syms = symbolsToAdopt.getAlias(); + LocalPointer df(new DecimalFormat(pattern, syms, style, status)); + + if (df.isValid()) { + // if the DecimalFormat object was successfully new'ed, then it will own symbolsToAdopt, even if the status is a failure. + symbolsToAdopt.orphan(); + } + else { + status = U_MEMORY_ALLOCATION_ERROR; + } + + if (U_FAILURE(status)) { + return nullptr; + } // if it is cash currency style, setCurrencyUsage with usage if (style == UNUM_CASH_CURRENCY){ @@ -1472,25 +1483,18 @@ NumberFormat::makeInstance(const Locale& desiredLocale, } if (U_FAILURE(status)) { - delete df; - return NULL; + return nullptr; } - f = df; - if (f == NULL) { - delete syms; - status = U_MEMORY_ALLOCATION_ERROR; - return NULL; - } + f.adoptInstead(df.orphan()); } f->setLocaleIDs(ures_getLocaleByType(ownedResource.getAlias(), ULOC_VALID_LOCALE, &status), ures_getLocaleByType(ownedResource.getAlias(), ULOC_ACTUAL_LOCALE, &status)); if (U_FAILURE(status)) { - delete f; return NULL; } - return f; + return f.orphan(); } /** diff --git a/deps/icu-small/source/i18n/numparse_currency.cpp b/deps/icu-small/source/i18n/numparse_currency.cpp index ae8196ec483799..598ace56533c36 100644 --- a/deps/icu-small/source/i18n/numparse_currency.cpp +++ b/deps/icu-small/source/i18n/numparse_currency.cpp @@ -111,7 +111,9 @@ bool CombinedCurrencyMatcher::matchCurrency(StringSegment& segment, ParsedNumber int32_t overlap2; if (!fCurrency2.isEmpty()) { - overlap2 = segment.getCaseSensitivePrefixLength(fCurrency2); + // ISO codes should be accepted case-insensitive. + // https://unicode-org.atlassian.net/browse/ICU-13696 + overlap2 = segment.getCommonPrefixLength(fCurrency2); } else { overlap2 = -1; } diff --git a/deps/icu-small/source/i18n/numparse_impl.cpp b/deps/icu-small/source/i18n/numparse_impl.cpp index 5fa52f63351c31..3192a3959389a7 100644 --- a/deps/icu-small/source/i18n/numparse_impl.cpp +++ b/deps/icu-small/source/i18n/numparse_impl.cpp @@ -159,10 +159,10 @@ NumberParserImpl::createParserFromProperties(const number::impl::DecimalFormatPr // ICU-TC meeting, April 11, 2018: accept percent/permille only if it is in the pattern, // and to maintain regressive behavior, divide by 100 even if no percent sign is present. - if (affixProvider->containsSymbolType(AffixPatternType::TYPE_PERCENT, status)) { + if (!isStrict && affixProvider->containsSymbolType(AffixPatternType::TYPE_PERCENT, status)) { parser->addMatcher(parser->fLocalMatchers.percent = {symbols}); } - if (affixProvider->containsSymbolType(AffixPatternType::TYPE_PERMILLE, status)) { + if (!isStrict && affixProvider->containsSymbolType(AffixPatternType::TYPE_PERMILLE, status)) { parser->addMatcher(parser->fLocalMatchers.permille = {symbols}); } diff --git a/deps/icu-small/source/i18n/numparse_scientific.cpp b/deps/icu-small/source/i18n/numparse_scientific.cpp index 611695e57d4743..de38957440817c 100644 --- a/deps/icu-small/source/i18n/numparse_scientific.cpp +++ b/deps/icu-small/source/i18n/numparse_scientific.cpp @@ -56,6 +56,11 @@ bool ScientificMatcher::match(StringSegment& segment, ParsedNumber& result, UErr return false; } + // Only accept one exponent per string. + if (0 != (result.flags & FLAG_HAS_EXPONENT)) { + return false; + } + // First match the scientific separator, and then match another number after it. // NOTE: This is guarded by the smoke test; no need to check fExponentSeparatorString length again. int overlap1 = segment.getCommonPrefixLength(fExponentSeparatorString); diff --git a/deps/icu-small/source/i18n/numrange_fluent.cpp b/deps/icu-small/source/i18n/numrange_fluent.cpp new file mode 100644 index 00000000000000..12b006c8ad5540 --- /dev/null +++ b/deps/icu-small/source/i18n/numrange_fluent.cpp @@ -0,0 +1,472 @@ +// © 2018 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html + +#include "unicode/utypes.h" + +#if !UCONFIG_NO_FORMATTING + +// Allow implicit conversion from char16_t* to UnicodeString for this file: +// Helpful in toString methods and elsewhere. +#define UNISTR_FROM_STRING_EXPLICIT + +#include "numrange_impl.h" +#include "util.h" +#include "number_utypes.h" + +using namespace icu; +using namespace icu::number; +using namespace icu::number::impl; + + +// This function needs to be declared in this namespace so it can be friended. +// NOTE: In Java, this logic is handled in the resolve() function. +void icu::number::impl::touchRangeLocales(RangeMacroProps& macros) { + macros.formatter1.fMacros.locale = macros.locale; + macros.formatter2.fMacros.locale = macros.locale; +} + + +template +Derived NumberRangeFormatterSettings::numberFormatterBoth(const UnlocalizedNumberFormatter& formatter) const& { + Derived copy(*this); + copy.fMacros.formatter1 = formatter; + copy.fMacros.singleFormatter = true; + touchRangeLocales(copy.fMacros); + return copy; +} + +template +Derived NumberRangeFormatterSettings::numberFormatterBoth(const UnlocalizedNumberFormatter& formatter) && { + Derived move(std::move(*this)); + move.fMacros.formatter1 = formatter; + move.fMacros.singleFormatter = true; + touchRangeLocales(move.fMacros); + return move; +} + +template +Derived NumberRangeFormatterSettings::numberFormatterBoth(UnlocalizedNumberFormatter&& formatter) const& { + Derived copy(*this); + copy.fMacros.formatter1 = std::move(formatter); + copy.fMacros.singleFormatter = true; + touchRangeLocales(copy.fMacros); + return copy; +} + +template +Derived NumberRangeFormatterSettings::numberFormatterBoth(UnlocalizedNumberFormatter&& formatter) && { + Derived move(std::move(*this)); + move.fMacros.formatter1 = std::move(formatter); + move.fMacros.singleFormatter = true; + touchRangeLocales(move.fMacros); + return move; +} + +template +Derived NumberRangeFormatterSettings::numberFormatterFirst(const UnlocalizedNumberFormatter& formatter) const& { + Derived copy(*this); + copy.fMacros.formatter1 = formatter; + copy.fMacros.singleFormatter = false; + touchRangeLocales(copy.fMacros); + return copy; +} + +template +Derived NumberRangeFormatterSettings::numberFormatterFirst(const UnlocalizedNumberFormatter& formatter) && { + Derived move(std::move(*this)); + move.fMacros.formatter1 = formatter; + move.fMacros.singleFormatter = false; + touchRangeLocales(move.fMacros); + return move; +} + +template +Derived NumberRangeFormatterSettings::numberFormatterFirst(UnlocalizedNumberFormatter&& formatter) const& { + Derived copy(*this); + copy.fMacros.formatter1 = std::move(formatter); + copy.fMacros.singleFormatter = false; + touchRangeLocales(copy.fMacros); + return copy; +} + +template +Derived NumberRangeFormatterSettings::numberFormatterFirst(UnlocalizedNumberFormatter&& formatter) && { + Derived move(std::move(*this)); + move.fMacros.formatter1 = std::move(formatter); + move.fMacros.singleFormatter = false; + touchRangeLocales(move.fMacros); + return move; +} + +template +Derived NumberRangeFormatterSettings::numberFormatterSecond(const UnlocalizedNumberFormatter& formatter) const& { + Derived copy(*this); + copy.fMacros.formatter2 = formatter; + copy.fMacros.singleFormatter = false; + touchRangeLocales(copy.fMacros); + return copy; +} + +template +Derived NumberRangeFormatterSettings::numberFormatterSecond(const UnlocalizedNumberFormatter& formatter) && { + Derived move(std::move(*this)); + move.fMacros.formatter2 = formatter; + move.fMacros.singleFormatter = false; + touchRangeLocales(move.fMacros); + return move; +} + +template +Derived NumberRangeFormatterSettings::numberFormatterSecond(UnlocalizedNumberFormatter&& formatter) const& { + Derived copy(*this); + copy.fMacros.formatter2 = std::move(formatter); + copy.fMacros.singleFormatter = false; + touchRangeLocales(copy.fMacros); + return copy; +} + +template +Derived NumberRangeFormatterSettings::numberFormatterSecond(UnlocalizedNumberFormatter&& formatter) && { + Derived move(std::move(*this)); + move.fMacros.formatter2 = std::move(formatter); + move.fMacros.singleFormatter = false; + touchRangeLocales(move.fMacros); + return move; +} + +template +Derived NumberRangeFormatterSettings::collapse(UNumberRangeCollapse collapse) const& { + Derived copy(*this); + copy.fMacros.collapse = collapse; + return copy; +} + +template +Derived NumberRangeFormatterSettings::collapse(UNumberRangeCollapse collapse) && { + Derived move(std::move(*this)); + move.fMacros.collapse = collapse; + return move; +} + +template +Derived NumberRangeFormatterSettings::identityFallback(UNumberRangeIdentityFallback identityFallback) const& { + Derived copy(*this); + copy.fMacros.identityFallback = identityFallback; + return copy; +} + +template +Derived NumberRangeFormatterSettings::identityFallback(UNumberRangeIdentityFallback identityFallback) && { + Derived move(std::move(*this)); + move.fMacros.identityFallback = identityFallback; + return move; +} + +// Declare all classes that implement NumberRangeFormatterSettings +// See https://stackoverflow.com/a/495056/1407170 +template +class icu::number::NumberRangeFormatterSettings; +template +class icu::number::NumberRangeFormatterSettings; + + +UnlocalizedNumberRangeFormatter NumberRangeFormatter::with() { + UnlocalizedNumberRangeFormatter result; + return result; +} + +LocalizedNumberRangeFormatter NumberRangeFormatter::withLocale(const Locale& locale) { + return with().locale(locale); +} + + +template using NFS = NumberRangeFormatterSettings; +using LNF = LocalizedNumberRangeFormatter; +using UNF = UnlocalizedNumberRangeFormatter; + +UnlocalizedNumberRangeFormatter::UnlocalizedNumberRangeFormatter(const UNF& other) + : UNF(static_cast&>(other)) {} + +UnlocalizedNumberRangeFormatter::UnlocalizedNumberRangeFormatter(const NFS& other) + : NFS(other) { + // No additional fields to assign +} + +// Make default copy constructor call the NumberRangeFormatterSettings copy constructor. +UnlocalizedNumberRangeFormatter::UnlocalizedNumberRangeFormatter(UNF&& src) U_NOEXCEPT + : UNF(static_cast&&>(src)) {} + +UnlocalizedNumberRangeFormatter::UnlocalizedNumberRangeFormatter(NFS&& src) U_NOEXCEPT + : NFS(std::move(src)) { + // No additional fields to assign +} + +UnlocalizedNumberRangeFormatter& UnlocalizedNumberRangeFormatter::operator=(const UNF& other) { + NFS::operator=(static_cast&>(other)); + // No additional fields to assign + return *this; +} + +UnlocalizedNumberRangeFormatter& UnlocalizedNumberRangeFormatter::operator=(UNF&& src) U_NOEXCEPT { + NFS::operator=(static_cast&&>(src)); + // No additional fields to assign + return *this; +} + +// Make default copy constructor call the NumberRangeFormatterSettings copy constructor. +LocalizedNumberRangeFormatter::LocalizedNumberRangeFormatter(const LNF& other) + : LNF(static_cast&>(other)) {} + +LocalizedNumberRangeFormatter::LocalizedNumberRangeFormatter(const NFS& other) + : NFS(other) { + // No additional fields to assign +} + +LocalizedNumberRangeFormatter::LocalizedNumberRangeFormatter(LocalizedNumberRangeFormatter&& src) U_NOEXCEPT + : LNF(static_cast&&>(src)) {} + +LocalizedNumberRangeFormatter::LocalizedNumberRangeFormatter(NFS&& src) U_NOEXCEPT + : NFS(std::move(src)) { + // Steal the compiled formatter + LNF&& _src = static_cast(src); + auto* stolen = _src.fAtomicFormatter.exchange(nullptr); + delete fAtomicFormatter.exchange(stolen); +} + +LocalizedNumberRangeFormatter& LocalizedNumberRangeFormatter::operator=(const LNF& other) { + NFS::operator=(static_cast&>(other)); + // Do not steal; just clear + delete fAtomicFormatter.exchange(nullptr); + return *this; +} + +LocalizedNumberRangeFormatter& LocalizedNumberRangeFormatter::operator=(LNF&& src) U_NOEXCEPT { + NFS::operator=(static_cast&&>(src)); + // Steal the compiled formatter + auto* stolen = src.fAtomicFormatter.exchange(nullptr); + delete fAtomicFormatter.exchange(stolen); + return *this; +} + + +LocalizedNumberRangeFormatter::~LocalizedNumberRangeFormatter() { + delete fAtomicFormatter.exchange(nullptr); +} + +LocalizedNumberRangeFormatter::LocalizedNumberRangeFormatter(const RangeMacroProps& macros, const Locale& locale) { + fMacros = macros; + fMacros.locale = locale; + touchRangeLocales(fMacros); +} + +LocalizedNumberRangeFormatter::LocalizedNumberRangeFormatter(RangeMacroProps&& macros, const Locale& locale) { + fMacros = std::move(macros); + fMacros.locale = locale; + touchRangeLocales(fMacros); +} + +LocalizedNumberRangeFormatter UnlocalizedNumberRangeFormatter::locale(const Locale& locale) const& { + return LocalizedNumberRangeFormatter(fMacros, locale); +} + +LocalizedNumberRangeFormatter UnlocalizedNumberRangeFormatter::locale(const Locale& locale)&& { + return LocalizedNumberRangeFormatter(std::move(fMacros), locale); +} + + +FormattedNumberRange LocalizedNumberRangeFormatter::formatFormattableRange( + const Formattable& first, const Formattable& second, UErrorCode& status) const { + if (U_FAILURE(status)) { + return FormattedNumberRange(U_ILLEGAL_ARGUMENT_ERROR); + } + + auto results = new UFormattedNumberRangeData(); + if (results == nullptr) { + status = U_MEMORY_ALLOCATION_ERROR; + return FormattedNumberRange(status); + } + + first.populateDecimalQuantity(results->quantity1, status); + if (U_FAILURE(status)) { + return FormattedNumberRange(status); + } + + second.populateDecimalQuantity(results->quantity2, status); + if (U_FAILURE(status)) { + return FormattedNumberRange(status); + } + + formatImpl(*results, first == second, status); + + // Do not save the results object if we encountered a failure. + if (U_SUCCESS(status)) { + return FormattedNumberRange(results); + } else { + delete results; + return FormattedNumberRange(status); + } +} + +void LocalizedNumberRangeFormatter::formatImpl( + UFormattedNumberRangeData& results, bool equalBeforeRounding, UErrorCode& status) const { + auto* impl = getFormatter(status); + if (U_FAILURE(status)) { + return; + } + if (impl == nullptr) { + status = U_INTERNAL_PROGRAM_ERROR; + return; + } + impl->format(results, equalBeforeRounding, status); +} + +const impl::NumberRangeFormatterImpl* +LocalizedNumberRangeFormatter::getFormatter(UErrorCode& status) const { + // TODO: Move this into umutex.h? (similar logic also in decimfmt.cpp) + // See ICU-20146 + + if (U_FAILURE(status)) { + return nullptr; + } + + // First try to get the pre-computed formatter + auto* ptr = fAtomicFormatter.load(); + if (ptr != nullptr) { + return ptr; + } + + // Try computing the formatter on our own + auto* temp = new NumberRangeFormatterImpl(fMacros, status); + if (U_FAILURE(status)) { + return nullptr; + } + if (temp == nullptr) { + status = U_MEMORY_ALLOCATION_ERROR; + return nullptr; + } + + // Note: ptr starts as nullptr; during compare_exchange, + // it is set to what is actually stored in the atomic + // if another thread beat us to computing the formatter object. + auto* nonConstThis = const_cast(this); + if (!nonConstThis->fAtomicFormatter.compare_exchange_strong(ptr, temp)) { + // Another thread beat us to computing the formatter + delete temp; + return ptr; + } else { + // Our copy of the formatter got stored in the atomic + return temp; + } + +} + + +FormattedNumberRange::FormattedNumberRange(FormattedNumberRange&& src) U_NOEXCEPT + : fResults(src.fResults), fErrorCode(src.fErrorCode) { + // Disown src.fResults to prevent double-deletion + src.fResults = nullptr; + src.fErrorCode = U_INVALID_STATE_ERROR; +} + +FormattedNumberRange& FormattedNumberRange::operator=(FormattedNumberRange&& src) U_NOEXCEPT { + delete fResults; + fResults = src.fResults; + fErrorCode = src.fErrorCode; + // Disown src.fResults to prevent double-deletion + src.fResults = nullptr; + src.fErrorCode = U_INVALID_STATE_ERROR; + return *this; +} + +UnicodeString FormattedNumberRange::toString(UErrorCode& status) const { + if (U_FAILURE(status)) { + return ICU_Utility::makeBogusString(); + } + if (fResults == nullptr) { + status = fErrorCode; + return ICU_Utility::makeBogusString(); + } + return fResults->string.toUnicodeString(); +} + +Appendable& FormattedNumberRange::appendTo(Appendable& appendable, UErrorCode& status) const { + if (U_FAILURE(status)) { + return appendable; + } + if (fResults == nullptr) { + status = fErrorCode; + return appendable; + } + appendable.appendString(fResults->string.chars(), fResults->string.length()); + return appendable; +} + +UBool FormattedNumberRange::nextFieldPosition(FieldPosition& fieldPosition, UErrorCode& status) const { + if (U_FAILURE(status)) { + return FALSE; + } + if (fResults == nullptr) { + status = fErrorCode; + return FALSE; + } + // NOTE: MSVC sometimes complains when implicitly converting between bool and UBool + return fResults->string.nextFieldPosition(fieldPosition, status) ? TRUE : FALSE; +} + +void FormattedNumberRange::getAllFieldPositions(FieldPositionIterator& iterator, UErrorCode& status) const { + FieldPositionIteratorHandler fpih(&iterator, status); + getAllFieldPositionsImpl(fpih, status); +} + +void FormattedNumberRange::getAllFieldPositionsImpl( + FieldPositionIteratorHandler& fpih, UErrorCode& status) const { + if (U_FAILURE(status)) { + return; + } + if (fResults == nullptr) { + status = fErrorCode; + return; + } + fResults->string.getAllFieldPositions(fpih, status); +} + +UnicodeString FormattedNumberRange::getFirstDecimal(UErrorCode& status) const { + if (U_FAILURE(status)) { + return ICU_Utility::makeBogusString(); + } + if (fResults == nullptr) { + status = fErrorCode; + return ICU_Utility::makeBogusString(); + } + return fResults->quantity1.toScientificString(); +} + +UnicodeString FormattedNumberRange::getSecondDecimal(UErrorCode& status) const { + if (U_FAILURE(status)) { + return ICU_Utility::makeBogusString(); + } + if (fResults == nullptr) { + status = fErrorCode; + return ICU_Utility::makeBogusString(); + } + return fResults->quantity2.toScientificString(); +} + +UNumberRangeIdentityResult FormattedNumberRange::getIdentityResult(UErrorCode& status) const { + if (U_FAILURE(status)) { + return UNUM_IDENTITY_RESULT_NOT_EQUAL; + } + if (fResults == nullptr) { + status = fErrorCode; + return UNUM_IDENTITY_RESULT_NOT_EQUAL; + } + return fResults->identityResult; +} + +FormattedNumberRange::~FormattedNumberRange() { + delete fResults; +} + + + +#endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/deps/icu-small/source/i18n/numrange_impl.cpp b/deps/icu-small/source/i18n/numrange_impl.cpp new file mode 100644 index 00000000000000..21365bfc59bca3 --- /dev/null +++ b/deps/icu-small/source/i18n/numrange_impl.cpp @@ -0,0 +1,486 @@ +// © 2018 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html + +#include "unicode/utypes.h" + +#if !UCONFIG_NO_FORMATTING + +// Allow implicit conversion from char16_t* to UnicodeString for this file: +// Helpful in toString methods and elsewhere. +#define UNISTR_FROM_STRING_EXPLICIT + +#include "unicode/numberrangeformatter.h" +#include "numrange_impl.h" +#include "patternprops.h" +#include "uresimp.h" +#include "util.h" + +using namespace icu; +using namespace icu::number; +using namespace icu::number::impl; + +namespace { + +// Helper function for 2-dimensional switch statement +constexpr int8_t identity2d(UNumberRangeIdentityFallback a, UNumberRangeIdentityResult b) { + return static_cast(a) | (static_cast(b) << 4); +} + + +struct NumberRangeData { + SimpleFormatter rangePattern; + SimpleFormatter approximatelyPattern; +}; + +class NumberRangeDataSink : public ResourceSink { + public: + NumberRangeDataSink(NumberRangeData& data) : fData(data) {} + + void put(const char* key, ResourceValue& value, UBool /*noFallback*/, UErrorCode& status) U_OVERRIDE { + ResourceTable miscTable = value.getTable(status); + if (U_FAILURE(status)) { return; } + for (int i = 0; miscTable.getKeyAndValue(i, key, value); i++) { + if (uprv_strcmp(key, "range") == 0) { + if (fData.rangePattern.getArgumentLimit() != 0) { + continue; // have already seen this pattern + } + fData.rangePattern = {value.getUnicodeString(status), status}; + } else if (uprv_strcmp(key, "approximately") == 0) { + if (fData.approximatelyPattern.getArgumentLimit() != 0) { + continue; // have already seen this pattern + } + fData.approximatelyPattern = {value.getUnicodeString(status), status}; + } + } + } + + private: + NumberRangeData& fData; +}; + +void getNumberRangeData(const char* localeName, const char* nsName, NumberRangeData& data, UErrorCode& status) { + if (U_FAILURE(status)) { return; } + LocalUResourceBundlePointer rb(ures_open(NULL, localeName, &status)); + if (U_FAILURE(status)) { return; } + NumberRangeDataSink sink(data); + + CharString dataPath; + dataPath.append("NumberElements/", -1, status); + dataPath.append(nsName, -1, status); + dataPath.append("/miscPatterns", -1, status); + ures_getAllItemsWithFallback(rb.getAlias(), dataPath.data(), sink, status); + if (U_FAILURE(status)) { return; } + + // TODO: Is it necessary to manually fall back to latn, or does the data sink take care of that? + + if (data.rangePattern.getArgumentLimit() == 0) { + // No data! + data.rangePattern = {u"{0}–{1}", status}; + } + if (data.approximatelyPattern.getArgumentLimit() == 0) { + // No data! + data.approximatelyPattern = {u"~{0}", status}; + } +} + +class PluralRangesDataSink : public ResourceSink { + public: + PluralRangesDataSink(StandardPluralRanges& output) : fOutput(output) {} + + void put(const char* /*key*/, ResourceValue& value, UBool /*noFallback*/, UErrorCode& status) U_OVERRIDE { + ResourceArray entriesArray = value.getArray(status); + if (U_FAILURE(status)) { return; } + fOutput.setCapacity(entriesArray.getSize()); + for (int i = 0; entriesArray.getValue(i, value); i++) { + ResourceArray pluralFormsArray = value.getArray(status); + if (U_FAILURE(status)) { return; } + pluralFormsArray.getValue(0, value); + StandardPlural::Form first = StandardPlural::fromString(value.getUnicodeString(status), status); + if (U_FAILURE(status)) { return; } + pluralFormsArray.getValue(1, value); + StandardPlural::Form second = StandardPlural::fromString(value.getUnicodeString(status), status); + if (U_FAILURE(status)) { return; } + pluralFormsArray.getValue(2, value); + StandardPlural::Form result = StandardPlural::fromString(value.getUnicodeString(status), status); + if (U_FAILURE(status)) { return; } + fOutput.addPluralRange(first, second, result); + } + } + + private: + StandardPluralRanges& fOutput; +}; + +void getPluralRangesData(const Locale& locale, StandardPluralRanges& output, UErrorCode& status) { + if (U_FAILURE(status)) { return; } + LocalUResourceBundlePointer rb(ures_openDirect(nullptr, "pluralRanges", &status)); + if (U_FAILURE(status)) { return; } + + CharString dataPath; + dataPath.append("locales/", -1, status); + dataPath.append(locale.getLanguage(), -1, status); + if (U_FAILURE(status)) { return; } + int32_t setLen; + // Not all languages are covered: fail gracefully + UErrorCode internalStatus = U_ZERO_ERROR; + const UChar* set = ures_getStringByKeyWithFallback(rb.getAlias(), dataPath.data(), &setLen, &internalStatus); + if (U_FAILURE(internalStatus)) { return; } + + dataPath.clear(); + dataPath.append("rules/", -1, status); + dataPath.appendInvariantChars(set, setLen, status); + if (U_FAILURE(status)) { return; } + PluralRangesDataSink sink(output); + ures_getAllItemsWithFallback(rb.getAlias(), dataPath.data(), sink, status); + if (U_FAILURE(status)) { return; } +} + +} // namespace + + +void StandardPluralRanges::initialize(const Locale& locale, UErrorCode& status) { + getPluralRangesData(locale, *this, status); +} + +void StandardPluralRanges::addPluralRange( + StandardPlural::Form first, + StandardPlural::Form second, + StandardPlural::Form result) { + U_ASSERT(fTriplesLen < fTriples.getCapacity()); + fTriples[fTriplesLen] = {first, second, result}; + fTriplesLen++; +} + +void StandardPluralRanges::setCapacity(int32_t length) { + if (length > fTriples.getCapacity()) { + fTriples.resize(length, 0); + } +} + +StandardPlural::Form +StandardPluralRanges::resolve(StandardPlural::Form first, StandardPlural::Form second) const { + for (int32_t i=0; isemanticallyEquivalent(*micros2.modInner) + || !micros1.modMiddle->semanticallyEquivalent(*micros2.modMiddle) + || !micros1.modOuter->semanticallyEquivalent(*micros2.modOuter)) { + formatRange(data, micros1, micros2, status); + data.identityResult = UNUM_IDENTITY_RESULT_NOT_EQUAL; + return; + } + + // Check for identity + if (equalBeforeRounding) { + data.identityResult = UNUM_IDENTITY_RESULT_EQUAL_BEFORE_ROUNDING; + } else if (data.quantity1 == data.quantity2) { + data.identityResult = UNUM_IDENTITY_RESULT_EQUAL_AFTER_ROUNDING; + } else { + data.identityResult = UNUM_IDENTITY_RESULT_NOT_EQUAL; + } + + switch (identity2d(fIdentityFallback, data.identityResult)) { + case identity2d(UNUM_IDENTITY_FALLBACK_RANGE, + UNUM_IDENTITY_RESULT_NOT_EQUAL): + case identity2d(UNUM_IDENTITY_FALLBACK_RANGE, + UNUM_IDENTITY_RESULT_EQUAL_AFTER_ROUNDING): + case identity2d(UNUM_IDENTITY_FALLBACK_RANGE, + UNUM_IDENTITY_RESULT_EQUAL_BEFORE_ROUNDING): + case identity2d(UNUM_IDENTITY_FALLBACK_APPROXIMATELY, + UNUM_IDENTITY_RESULT_NOT_EQUAL): + case identity2d(UNUM_IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE, + UNUM_IDENTITY_RESULT_NOT_EQUAL): + case identity2d(UNUM_IDENTITY_FALLBACK_SINGLE_VALUE, + UNUM_IDENTITY_RESULT_NOT_EQUAL): + formatRange(data, micros1, micros2, status); + break; + + case identity2d(UNUM_IDENTITY_FALLBACK_APPROXIMATELY, + UNUM_IDENTITY_RESULT_EQUAL_AFTER_ROUNDING): + case identity2d(UNUM_IDENTITY_FALLBACK_APPROXIMATELY, + UNUM_IDENTITY_RESULT_EQUAL_BEFORE_ROUNDING): + case identity2d(UNUM_IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE, + UNUM_IDENTITY_RESULT_EQUAL_AFTER_ROUNDING): + formatApproximately(data, micros1, micros2, status); + break; + + case identity2d(UNUM_IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE, + UNUM_IDENTITY_RESULT_EQUAL_BEFORE_ROUNDING): + case identity2d(UNUM_IDENTITY_FALLBACK_SINGLE_VALUE, + UNUM_IDENTITY_RESULT_EQUAL_AFTER_ROUNDING): + case identity2d(UNUM_IDENTITY_FALLBACK_SINGLE_VALUE, + UNUM_IDENTITY_RESULT_EQUAL_BEFORE_ROUNDING): + formatSingleValue(data, micros1, micros2, status); + break; + + default: + U_ASSERT(false); + break; + } +} + + +void NumberRangeFormatterImpl::formatSingleValue(UFormattedNumberRangeData& data, + MicroProps& micros1, MicroProps& micros2, + UErrorCode& status) const { + if (U_FAILURE(status)) { return; } + if (fSameFormatters) { + int32_t length = NumberFormatterImpl::writeNumber(micros1, data.quantity1, data.string, 0, status); + NumberFormatterImpl::writeAffixes(micros1, data.string, 0, length, status); + } else { + formatRange(data, micros1, micros2, status); + } +} + + +void NumberRangeFormatterImpl::formatApproximately (UFormattedNumberRangeData& data, + MicroProps& micros1, MicroProps& micros2, + UErrorCode& status) const { + if (U_FAILURE(status)) { return; } + if (fSameFormatters) { + int32_t length = NumberFormatterImpl::writeNumber(micros1, data.quantity1, data.string, 0, status); + // HEURISTIC: Desired modifier order: inner, middle, approximately, outer. + length += micros1.modInner->apply(data.string, 0, length, status); + length += micros1.modMiddle->apply(data.string, 0, length, status); + length += fApproximatelyModifier.apply(data.string, 0, length, status); + micros1.modOuter->apply(data.string, 0, length, status); + } else { + formatRange(data, micros1, micros2, status); + } +} + + +void NumberRangeFormatterImpl::formatRange(UFormattedNumberRangeData& data, + MicroProps& micros1, MicroProps& micros2, + UErrorCode& status) const { + if (U_FAILURE(status)) { return; } + + // modInner is always notation (scientific); collapsable in ALL. + // modOuter is always units; collapsable in ALL, AUTO, and UNIT. + // modMiddle could be either; collapsable in ALL and sometimes AUTO and UNIT. + // Never collapse an outer mod but not an inner mod. + bool collapseOuter, collapseMiddle, collapseInner; + switch (fCollapse) { + case UNUM_RANGE_COLLAPSE_ALL: + case UNUM_RANGE_COLLAPSE_AUTO: + case UNUM_RANGE_COLLAPSE_UNIT: + { + // OUTER MODIFIER + collapseOuter = micros1.modOuter->semanticallyEquivalent(*micros2.modOuter); + + if (!collapseOuter) { + // Never collapse inner mods if outer mods are not collapsable + collapseMiddle = false; + collapseInner = false; + break; + } + + // MIDDLE MODIFIER + collapseMiddle = micros1.modMiddle->semanticallyEquivalent(*micros2.modMiddle); + + if (!collapseMiddle) { + // Never collapse inner mods if outer mods are not collapsable + collapseInner = false; + break; + } + + // MIDDLE MODIFIER HEURISTICS + // (could disable collapsing of the middle modifier) + // The modifiers are equal by this point, so we can look at just one of them. + const Modifier* mm = micros1.modMiddle; + if (fCollapse == UNUM_RANGE_COLLAPSE_UNIT) { + // Only collapse if the modifier is a unit. + // TODO: Make a better way to check for a unit? + // TODO: Handle case where the modifier has both notation and unit (compact currency)? + if (!mm->containsField(UNUM_CURRENCY_FIELD) && !mm->containsField(UNUM_PERCENT_FIELD)) { + collapseMiddle = false; + } + } else if (fCollapse == UNUM_RANGE_COLLAPSE_AUTO) { + // Heuristic as of ICU 63: collapse only if the modifier is more than one code point. + if (mm->getCodePointCount() <= 1) { + collapseMiddle = false; + } + } + + if (!collapseMiddle || fCollapse != UNUM_RANGE_COLLAPSE_ALL) { + collapseInner = false; + break; + } + + // INNER MODIFIER + collapseInner = micros1.modInner->semanticallyEquivalent(*micros2.modInner); + + // All done checking for collapsability. + break; + } + + default: + collapseOuter = false; + collapseMiddle = false; + collapseInner = false; + break; + } + + NumberStringBuilder& string = data.string; + int32_t lengthPrefix = 0; + int32_t length1 = 0; + int32_t lengthInfix = 0; + int32_t length2 = 0; + int32_t lengthSuffix = 0; + + // Use #define so that these are evaluated at the call site. + #define UPRV_INDEX_0 (lengthPrefix) + #define UPRV_INDEX_1 (lengthPrefix + length1) + #define UPRV_INDEX_2 (lengthPrefix + length1 + lengthInfix) + #define UPRV_INDEX_3 (lengthPrefix + length1 + lengthInfix + length2) + + int32_t lengthRange = SimpleModifier::formatTwoArgPattern( + fRangeFormatter, + string, + 0, + &lengthPrefix, + &lengthSuffix, + UNUM_FIELD_COUNT, + status); + if (U_FAILURE(status)) { return; } + lengthInfix = lengthRange - lengthPrefix - lengthSuffix; + U_ASSERT(lengthInfix > 0); + + // SPACING HEURISTIC + // Add spacing unless all modifiers are collapsed. + // TODO: add API to control this? + // TODO: Use a data-driven heuristic like currency spacing? + // TODO: Use Unicode [:whitespace:] instead of PatternProps whitespace? (consider speed implications) + { + bool repeatInner = !collapseInner && micros1.modInner->getCodePointCount() > 0; + bool repeatMiddle = !collapseMiddle && micros1.modMiddle->getCodePointCount() > 0; + bool repeatOuter = !collapseOuter && micros1.modOuter->getCodePointCount() > 0; + if (repeatInner || repeatMiddle || repeatOuter) { + // Add spacing if there is not already spacing + if (!PatternProps::isWhiteSpace(string.charAt(UPRV_INDEX_1))) { + lengthInfix += string.insertCodePoint(UPRV_INDEX_1, u'\u0020', UNUM_FIELD_COUNT, status); + } + if (!PatternProps::isWhiteSpace(string.charAt(UPRV_INDEX_2 - 1))) { + lengthInfix += string.insertCodePoint(UPRV_INDEX_2, u'\u0020', UNUM_FIELD_COUNT, status); + } + } + } + + length1 += NumberFormatterImpl::writeNumber(micros1, data.quantity1, string, UPRV_INDEX_0, status); + length2 += NumberFormatterImpl::writeNumber(micros2, data.quantity2, string, UPRV_INDEX_2, status); + + // TODO: Support padding? + + if (collapseInner) { + // Note: this is actually a mix of prefix and suffix, but adding to infix length works + const Modifier& mod = resolveModifierPlurals(*micros1.modInner, *micros2.modInner); + lengthInfix += mod.apply(string, UPRV_INDEX_0, UPRV_INDEX_3, status); + } else { + length1 += micros1.modInner->apply(string, UPRV_INDEX_0, UPRV_INDEX_1, status); + length2 += micros2.modInner->apply(string, UPRV_INDEX_2, UPRV_INDEX_3, status); + } + + if (collapseMiddle) { + // Note: this is actually a mix of prefix and suffix, but adding to infix length works + const Modifier& mod = resolveModifierPlurals(*micros1.modMiddle, *micros2.modMiddle); + lengthInfix += mod.apply(string, UPRV_INDEX_0, UPRV_INDEX_3, status); + } else { + length1 += micros1.modMiddle->apply(string, UPRV_INDEX_0, UPRV_INDEX_1, status); + length2 += micros2.modMiddle->apply(string, UPRV_INDEX_2, UPRV_INDEX_3, status); + } + + if (collapseOuter) { + // Note: this is actually a mix of prefix and suffix, but adding to infix length works + const Modifier& mod = resolveModifierPlurals(*micros1.modOuter, *micros2.modOuter); + lengthInfix += mod.apply(string, UPRV_INDEX_0, UPRV_INDEX_3, status); + } else { + length1 += micros1.modOuter->apply(string, UPRV_INDEX_0, UPRV_INDEX_1, status); + length2 += micros2.modOuter->apply(string, UPRV_INDEX_2, UPRV_INDEX_3, status); + } +} + + +const Modifier& +NumberRangeFormatterImpl::resolveModifierPlurals(const Modifier& first, const Modifier& second) const { + Modifier::Parameters parameters; + first.getParameters(parameters); + if (parameters.obj == nullptr) { + // No plural form; return a fallback (e.g., the first) + return first; + } + StandardPlural::Form firstPlural = parameters.plural; + + second.getParameters(parameters); + if (parameters.obj == nullptr) { + // No plural form; return a fallback (e.g., the first) + return first; + } + StandardPlural::Form secondPlural = parameters.plural; + + // Get the required plural form from data + StandardPlural::Form resultPlural = fPluralRanges.resolve(firstPlural, secondPlural); + + // Get and return the new Modifier + const Modifier* mod = parameters.obj->getModifier(parameters.signum, resultPlural); + U_ASSERT(mod != nullptr); + return *mod; +} + + + +#endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/deps/icu-small/source/i18n/numrange_impl.h b/deps/icu-small/source/i18n/numrange_impl.h new file mode 100644 index 00000000000000..787fc656860d53 --- /dev/null +++ b/deps/icu-small/source/i18n/numrange_impl.h @@ -0,0 +1,114 @@ +// © 2018 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html + +#include "unicode/utypes.h" + +#if !UCONFIG_NO_FORMATTING +#ifndef __SOURCE_NUMRANGE_TYPES_H__ +#define __SOURCE_NUMRANGE_TYPES_H__ + +#include "unicode/numberformatter.h" +#include "unicode/numberrangeformatter.h" +#include "unicode/simpleformatter.h" +#include "number_types.h" +#include "number_decimalquantity.h" +#include "number_formatimpl.h" +#include "number_stringbuilder.h" + +U_NAMESPACE_BEGIN namespace number { +namespace impl { + + +/** + * Class similar to UFormattedNumberData. + * + * Has incomplete magic number logic that will need to be finished + * if this is to be exposed as C API in the future. + */ +struct UFormattedNumberRangeData : public UMemory { + // The magic number to identify incoming objects. + // Reads in ASCII as "FDR" (FormatteDnumberRange with room at the end) + static constexpr int32_t kMagic = 0x46445200; + + // Data members: + int32_t fMagic = kMagic; + DecimalQuantity quantity1; + DecimalQuantity quantity2; + NumberStringBuilder string; + UNumberRangeIdentityResult identityResult = UNUM_IDENTITY_RESULT_COUNT; + + // No C conversion methods (no C API yet) +}; + + +class StandardPluralRanges : public UMemory { + public: + void initialize(const Locale& locale, UErrorCode& status); + StandardPlural::Form resolve(StandardPlural::Form first, StandardPlural::Form second) const; + + /** Used for data loading. */ + void addPluralRange( + StandardPlural::Form first, + StandardPlural::Form second, + StandardPlural::Form result); + + /** Used for data loading. */ + void setCapacity(int32_t length); + + private: + struct StandardPluralRangeTriple { + StandardPlural::Form first; + StandardPlural::Form second; + StandardPlural::Form result; + }; + + // TODO: An array is simple here, but it results in linear lookup time. + // Certain locales have 20-30 entries in this list. + // Consider changing to a smarter data structure. + typedef MaybeStackArray PluralRangeTriples; + PluralRangeTriples fTriples; + int32_t fTriplesLen = 0; +}; + + +class NumberRangeFormatterImpl : public UMemory { + public: + NumberRangeFormatterImpl(const RangeMacroProps& macros, UErrorCode& status); + + void format(UFormattedNumberRangeData& data, bool equalBeforeRounding, UErrorCode& status) const; + + private: + NumberFormatterImpl formatterImpl1; + NumberFormatterImpl formatterImpl2; + bool fSameFormatters; + + UNumberRangeCollapse fCollapse; + UNumberRangeIdentityFallback fIdentityFallback; + + SimpleFormatter fRangeFormatter; + SimpleModifier fApproximatelyModifier; + + StandardPluralRanges fPluralRanges; + + void formatSingleValue(UFormattedNumberRangeData& data, + MicroProps& micros1, MicroProps& micros2, + UErrorCode& status) const; + + void formatApproximately(UFormattedNumberRangeData& data, + MicroProps& micros1, MicroProps& micros2, + UErrorCode& status) const; + + void formatRange(UFormattedNumberRangeData& data, + MicroProps& micros1, MicroProps& micros2, + UErrorCode& status) const; + + const Modifier& resolveModifierPlurals(const Modifier& first, const Modifier& second) const; +}; + + +} // namespace impl +} // namespace number +U_NAMESPACE_END + +#endif //__SOURCE_NUMRANGE_TYPES_H__ +#endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/deps/icu-small/source/i18n/numsys.cpp b/deps/icu-small/source/i18n/numsys.cpp index 087dd277eb4dd8..514fe05e5ae6de 100644 --- a/deps/icu-small/source/i18n/numsys.cpp +++ b/deps/icu-small/source/i18n/numsys.cpp @@ -79,43 +79,45 @@ NumberingSystem* U_EXPORT2 NumberingSystem::createInstance(int32_t radix_in, UBool isAlgorithmic_in, const UnicodeString & desc_in, UErrorCode &status) { if (U_FAILURE(status)) { - return NULL; + return nullptr; } if ( radix_in < 2 ) { status = U_ILLEGAL_ARGUMENT_ERROR; - return NULL; + return nullptr; } if ( !isAlgorithmic_in ) { if ( desc_in.countChar32() != radix_in ) { status = U_ILLEGAL_ARGUMENT_ERROR; - return NULL; + return nullptr; } } - NumberingSystem *ns = new NumberingSystem(); + LocalPointer ns(new NumberingSystem(), status); + if (U_FAILURE(status)) { + return nullptr; + } ns->setRadix(radix_in); ns->setDesc(desc_in); ns->setAlgorithmic(isAlgorithmic_in); - ns->setName(NULL); - return ns; + ns->setName(nullptr); + return ns.orphan(); } - NumberingSystem* U_EXPORT2 NumberingSystem::createInstance(const Locale & inLocale, UErrorCode& status) { if (U_FAILURE(status)) { - return NULL; + return nullptr; } UBool nsResolved = TRUE; UBool usingFallback = FALSE; char buffer[ULOC_KEYWORDS_CAPACITY]; - int32_t count = inLocale.getKeywordValue("numbers",buffer, sizeof(buffer),status); + int32_t count = inLocale.getKeywordValue("numbers", buffer, sizeof(buffer), status); if (U_FAILURE(status) || status == U_STRING_NOT_TERMINATED_WARNING) { // the "numbers" keyword exceeds ULOC_KEYWORDS_CAPACITY; ignore and use default. count = 0; @@ -129,20 +131,30 @@ NumberingSystem::createInstance(const Locale & inLocale, UErrorCode& status) { nsResolved = FALSE; } } else { - uprv_strcpy(buffer,gDefault); + uprv_strcpy(buffer, gDefault); nsResolved = FALSE; } if (!nsResolved) { // Resolve the numbering system ( default, native, traditional or finance ) into a "real" numbering system UErrorCode localStatus = U_ZERO_ERROR; - UResourceBundle *resource = ures_open(NULL, inLocale.getName(), &localStatus); - UResourceBundle *numberElementsRes = ures_getByKey(resource,gNumberElements,NULL,&localStatus); + LocalUResourceBundlePointer resource(ures_open(nullptr, inLocale.getName(), &localStatus)); + LocalUResourceBundlePointer numberElementsRes(ures_getByKey(resource.getAlias(), gNumberElements, nullptr, &localStatus)); + // Don't stomp on the catastrophic failure of OOM. + if (localStatus == U_MEMORY_ALLOCATION_ERROR) { + status = U_MEMORY_ALLOCATION_ERROR; + return nullptr; + } while (!nsResolved) { localStatus = U_ZERO_ERROR; count = 0; - const UChar *nsName = ures_getStringByKeyWithFallback(numberElementsRes, buffer, &count, &localStatus); + const UChar *nsName = ures_getStringByKeyWithFallback(numberElementsRes.getAlias(), buffer, &count, &localStatus); + // Don't stomp on the catastrophic failure of OOM. + if (localStatus == U_MEMORY_ALLOCATION_ERROR) { + status = U_MEMORY_ALLOCATION_ERROR; + return nullptr; + } if ( count > 0 && count < ULOC_KEYWORDS_CAPACITY ) { // numbering system found - u_UCharsToChars(nsName,buffer,count); + u_UCharsToChars(nsName, buffer, count); buffer[count] = '\0'; // Make sure it is null terminated. nsResolved = TRUE; } @@ -158,16 +170,17 @@ NumberingSystem::createInstance(const Locale & inLocale, UErrorCode& status) { } } } - ures_close(numberElementsRes); - ures_close(resource); } if (usingFallback) { status = U_USING_FALLBACK_WARNING; NumberingSystem *ns = new NumberingSystem(); + if (ns == nullptr) { + status = U_MEMORY_ALLOCATION_ERROR; + } return ns; } else { - return NumberingSystem::createInstanceByName(buffer,status); + return NumberingSystem::createInstanceByName(buffer, status); } } @@ -178,36 +191,37 @@ NumberingSystem::createInstance(UErrorCode& status) { NumberingSystem* U_EXPORT2 NumberingSystem::createInstanceByName(const char *name, UErrorCode& status) { - UResourceBundle *numberingSystemsInfo = NULL; - UResourceBundle *nsTop, *nsCurrent; int32_t radix = 10; int32_t algorithmic = 0; - numberingSystemsInfo = ures_openDirect(NULL,gNumberingSystems, &status); - nsCurrent = ures_getByKey(numberingSystemsInfo,gNumberingSystems,NULL,&status); - nsTop = ures_getByKey(nsCurrent,name,NULL,&status); - UnicodeString nsd = ures_getUnicodeStringByKey(nsTop,gDesc,&status); + LocalUResourceBundlePointer numberingSystemsInfo(ures_openDirect(nullptr, gNumberingSystems, &status)); + LocalUResourceBundlePointer nsCurrent(ures_getByKey(numberingSystemsInfo.getAlias(), gNumberingSystems, nullptr, &status)); + LocalUResourceBundlePointer nsTop(ures_getByKey(nsCurrent.getAlias(), name, nullptr, &status)); - ures_getByKey(nsTop,gRadix,nsCurrent,&status); - radix = ures_getInt(nsCurrent,&status); + UnicodeString nsd = ures_getUnicodeStringByKey(nsTop.getAlias(), gDesc, &status); - ures_getByKey(nsTop,gAlgorithmic,nsCurrent,&status); - algorithmic = ures_getInt(nsCurrent,&status); + ures_getByKey(nsTop.getAlias(), gRadix, nsCurrent.getAlias(), &status); + radix = ures_getInt(nsCurrent.getAlias(), &status); - UBool isAlgorithmic = ( algorithmic == 1 ); + ures_getByKey(nsTop.getAlias(), gAlgorithmic, nsCurrent.getAlias(), &status); + algorithmic = ures_getInt(nsCurrent.getAlias(), &status); - ures_close(nsCurrent); - ures_close(nsTop); - ures_close(numberingSystemsInfo); + UBool isAlgorithmic = ( algorithmic == 1 ); if (U_FAILURE(status)) { - status = U_UNSUPPORTED_ERROR; - return NULL; + // Don't stomp on the catastrophic failure of OOM. + if (status != U_MEMORY_ALLOCATION_ERROR) { + status = U_UNSUPPORTED_ERROR; + } + return nullptr; } - NumberingSystem* ns = NumberingSystem::createInstance(radix,isAlgorithmic,nsd,status); + LocalPointer ns(NumberingSystem::createInstance(radix, isAlgorithmic, nsd, status), status); + if (U_FAILURE(status)) { + return nullptr; + } ns->setName(name); - return ns; + return ns.orphan(); } /** @@ -241,11 +255,11 @@ void NumberingSystem::setDesc(const UnicodeString &d) { desc.setTo(d); } void NumberingSystem::setName(const char *n) { - if ( n == NULL ) { + if ( n == nullptr ) { name[0] = (char) 0; } else { uprv_strncpy(name,n,NUMSYS_NAME_CAPACITY); - name[NUMSYS_NAME_CAPACITY] = (char)0; // Make sure it is null terminated. + name[NUMSYS_NAME_CAPACITY] = '\0'; // Make sure it is null terminated. } } UBool NumberingSystem::isAlgorithmic() const { @@ -254,43 +268,57 @@ UBool NumberingSystem::isAlgorithmic() const { StringEnumeration* NumberingSystem::getAvailableNames(UErrorCode &status) { // TODO(ticket #11908): Init-once static cache, with u_cleanup() callback. - static StringEnumeration* availableNames = NULL; + static StringEnumeration* availableNames = nullptr; if (U_FAILURE(status)) { - return NULL; + return nullptr; } - if ( availableNames == NULL ) { + if ( availableNames == nullptr ) { // TODO: Simple array of UnicodeString objects, based on length of table resource? - LocalPointer numsysNames(new UVector(uprv_deleteUObject, NULL, status), status); + LocalPointer numsysNames(new UVector(uprv_deleteUObject, nullptr, status), status); if (U_FAILURE(status)) { - return NULL; + return nullptr; } UErrorCode rbstatus = U_ZERO_ERROR; - UResourceBundle *numberingSystemsInfo = ures_openDirect(NULL, "numberingSystems", &rbstatus); - numberingSystemsInfo = ures_getByKey(numberingSystemsInfo,"numberingSystems",numberingSystemsInfo,&rbstatus); - if(U_FAILURE(rbstatus)) { - status = U_MISSING_RESOURCE_ERROR; + UResourceBundle *numberingSystemsInfo = ures_openDirect(nullptr, "numberingSystems", &rbstatus); + numberingSystemsInfo = ures_getByKey(numberingSystemsInfo, "numberingSystems", numberingSystemsInfo, &rbstatus); + if (U_FAILURE(rbstatus)) { + // Don't stomp on the catastrophic failure of OOM. + if (rbstatus == U_MEMORY_ALLOCATION_ERROR) { + status = rbstatus; + } else { + status = U_MISSING_RESOURCE_ERROR; + } ures_close(numberingSystemsInfo); - return NULL; + return nullptr; } - while ( ures_hasNext(numberingSystemsInfo) ) { - UResourceBundle *nsCurrent = ures_getNextResource(numberingSystemsInfo,NULL,&rbstatus); - const char *nsName = ures_getKey(nsCurrent); - numsysNames->addElement(new UnicodeString(nsName, -1, US_INV),status); - ures_close(nsCurrent); + while ( ures_hasNext(numberingSystemsInfo) && U_SUCCESS(status) ) { + LocalUResourceBundlePointer nsCurrent(ures_getNextResource(numberingSystemsInfo, nullptr, &rbstatus)); + if (rbstatus == U_MEMORY_ALLOCATION_ERROR) { + status = rbstatus; // we want to report OOM failure back to the caller. + break; + } + const char *nsName = ures_getKey(nsCurrent.getAlias()); + LocalPointer newElem(new UnicodeString(nsName, -1, US_INV), status); + if (U_SUCCESS(status)) { + numsysNames->addElement(newElem.getAlias(), status); + if (U_SUCCESS(status)) { + newElem.orphan(); // on success, the numsysNames vector owns newElem. + } + } } ures_close(numberingSystemsInfo); if (U_FAILURE(status)) { - return NULL; + return nullptr; } availableNames = new NumsysNameEnumeration(numsysNames.getAlias(), status); - if (availableNames == NULL) { + if (availableNames == nullptr) { status = U_MEMORY_ALLOCATION_ERROR; - return NULL; + return nullptr; } numsysNames.orphan(); // The names got adopted. } @@ -305,10 +333,10 @@ NumsysNameEnumeration::NumsysNameEnumeration(UVector *numsysNames, UErrorCode& / const UnicodeString* NumsysNameEnumeration::snext(UErrorCode& status) { - if (U_SUCCESS(status) && pos < fNumsysNames->size()) { + if (U_SUCCESS(status) && (fNumsysNames != nullptr) && (pos < fNumsysNames->size())) { return (const UnicodeString*)fNumsysNames->elementAt(pos++); } - return NULL; + return nullptr; } void @@ -318,7 +346,7 @@ NumsysNameEnumeration::reset(UErrorCode& /*status*/) { int32_t NumsysNameEnumeration::count(UErrorCode& /*status*/) const { - return (fNumsysNames==NULL) ? 0 : fNumsysNames->size(); + return (fNumsysNames==nullptr) ? 0 : fNumsysNames->size(); } NumsysNameEnumeration::~NumsysNameEnumeration() { diff --git a/deps/icu-small/source/i18n/numsys_impl.h b/deps/icu-small/source/i18n/numsys_impl.h index 6385fa5408a152..733e102365369d 100644 --- a/deps/icu-small/source/i18n/numsys_impl.h +++ b/deps/icu-small/source/i18n/numsys_impl.h @@ -37,7 +37,7 @@ class NumsysNameEnumeration : public StringEnumeration { virtual int32_t count(UErrorCode& status) const; private: int32_t pos; - UVector *fNumsysNames; + UVector *fNumsysNames = nullptr; }; U_NAMESPACE_END diff --git a/deps/icu-small/source/i18n/olsontz.cpp b/deps/icu-small/source/i18n/olsontz.cpp index df025c0808388e..c3500574662585 100644 --- a/deps/icu-small/source/i18n/olsontz.cpp +++ b/deps/icu-small/source/i18n/olsontz.cpp @@ -140,7 +140,7 @@ OlsonTimeZone::OlsonTimeZone(const UResourceBundle* top, // Pre-32bit second transitions ures_getByKey(res, kTRANSPRE32, &r, &ec); transitionTimesPre32 = ures_getIntVector(&r, &len, &ec); - transitionCountPre32 = len >> 1; + transitionCountPre32 = static_cast(len >> 1); if (ec == U_MISSING_RESOURCE_ERROR) { // No pre-32bit transitions transitionTimesPre32 = NULL; @@ -153,7 +153,7 @@ OlsonTimeZone::OlsonTimeZone(const UResourceBundle* top, // 32bit second transitions ures_getByKey(res, kTRANS, &r, &ec); transitionTimes32 = ures_getIntVector(&r, &len, &ec); - transitionCount32 = len; + transitionCount32 = static_cast(len); if (ec == U_MISSING_RESOURCE_ERROR) { // No 32bit transitions transitionTimes32 = NULL; @@ -166,7 +166,7 @@ OlsonTimeZone::OlsonTimeZone(const UResourceBundle* top, // Post-32bit second transitions ures_getByKey(res, kTRANSPOST32, &r, &ec); transitionTimesPost32 = ures_getIntVector(&r, &len, &ec); - transitionCountPost32 = len >> 1; + transitionCountPost32 = static_cast(len >> 1); if (ec == U_MISSING_RESOURCE_ERROR) { // No pre-32bit transitions transitionTimesPost32 = NULL; diff --git a/deps/icu-small/source/i18n/plurrule.cpp b/deps/icu-small/source/i18n/plurrule.cpp index 9597e8eb00d023..3caa48a57bb700 100644 --- a/deps/icu-small/source/i18n/plurrule.cpp +++ b/deps/icu-small/source/i18n/plurrule.cpp @@ -65,13 +65,15 @@ UOBJECT_DEFINE_RTTI_IMPLEMENTATION(PluralKeywordEnumeration) PluralRules::PluralRules(UErrorCode& /*status*/) : UObject(), - mRules(NULL) + mRules(nullptr), + mInternalStatus(U_ZERO_ERROR) { } PluralRules::PluralRules(const PluralRules& other) : UObject(other), - mRules(NULL) + mRules(nullptr), + mInternalStatus(U_ZERO_ERROR) { *this=other; } @@ -86,54 +88,67 @@ SharedPluralRules::~SharedPluralRules() { PluralRules* PluralRules::clone() const { - return new PluralRules(*this); + PluralRules* newObj = new PluralRules(*this); + // Since clone doesn't have a 'status' parameter, the best we can do is return nullptr if + // the newly created object was not fully constructed properly (an error occurred). + if (newObj != nullptr && U_FAILURE(newObj->mInternalStatus)) { + delete newObj; + newObj = nullptr; + } + return newObj; } PluralRules& PluralRules::operator=(const PluralRules& other) { if (this != &other) { delete mRules; - if (other.mRules==NULL) { - mRules = NULL; + mRules = nullptr; + mInternalStatus = other.mInternalStatus; + if (U_FAILURE(mInternalStatus)) { + // bail out early if the object we were copying from was already 'invalid'. + return *this; } - else { + if (other.mRules != nullptr) { mRules = new RuleChain(*other.mRules); + if (mRules == nullptr) { + mInternalStatus = U_MEMORY_ALLOCATION_ERROR; + } + else if (U_FAILURE(mRules->fInternalStatus)) { + // If the RuleChain wasn't fully copied, then set our status to failure as well. + mInternalStatus = mRules->fInternalStatus; + } } } - return *this; } StringEnumeration* PluralRules::getAvailableLocales(UErrorCode &status) { - StringEnumeration *result = new PluralAvailableLocalesEnumeration(status); - if (result == NULL && U_SUCCESS(status)) { - status = U_MEMORY_ALLOCATION_ERROR; + if (U_FAILURE(status)) { + return nullptr; } + LocalPointer result(new PluralAvailableLocalesEnumeration(status), status); if (U_FAILURE(status)) { - delete result; - result = NULL; + return nullptr; } - return result; + return result.orphan(); } PluralRules* U_EXPORT2 PluralRules::createRules(const UnicodeString& description, UErrorCode& status) { if (U_FAILURE(status)) { - return NULL; + return nullptr; } - PluralRuleParser parser; - PluralRules *newRules = new PluralRules(status); - if (U_SUCCESS(status) && newRules == NULL) { - status = U_MEMORY_ALLOCATION_ERROR; + LocalPointer newRules(new PluralRules(status), status); + if (U_FAILURE(status)) { + return nullptr; } - parser.parse(description, newRules, status); + parser.parse(description, newRules.getAlias(), status); if (U_FAILURE(status)) { - delete newRules; - newRules = NULL; + newRules.adoptInstead(nullptr); } - return newRules; + return newRules.orphan(); } @@ -149,19 +164,17 @@ template<> U_I18N_API const SharedPluralRules *LocaleCacheKey::createObject( const void * /*unused*/, UErrorCode &status) const { const char *localeId = fLoc.getName(); - PluralRules *pr = PluralRules::internalForLocale( - localeId, UPLURAL_TYPE_CARDINAL, status); + LocalPointer pr(PluralRules::internalForLocale(localeId, UPLURAL_TYPE_CARDINAL, status), status); if (U_FAILURE(status)) { - return NULL; + return nullptr; } - SharedPluralRules *result = new SharedPluralRules(pr); - if (result == NULL) { - status = U_MEMORY_ALLOCATION_ERROR; - delete pr; - return NULL; + LocalPointer result(new SharedPluralRules(pr.getAlias()), status); + if (U_FAILURE(status)) { + return nullptr; } + pr.orphan(); // result was successfully created so it nows pr. result->addRef(); - return result; + return result.orphan(); } /* end plural rules cache */ @@ -171,13 +184,13 @@ const SharedPluralRules* U_EXPORT2 PluralRules::createSharedInstance( const Locale& locale, UPluralType type, UErrorCode& status) { if (U_FAILURE(status)) { - return NULL; + return nullptr; } if (type != UPLURAL_TYPE_CARDINAL) { status = U_UNSUPPORTED_ERROR; - return NULL; + return nullptr; } - const SharedPluralRules *result = NULL; + const SharedPluralRules *result = nullptr; UnifiedCache::getByLocale(locale, result, status); return result; } @@ -195,11 +208,11 @@ PluralRules::forLocale(const Locale& locale, UPluralType type, UErrorCode& statu const SharedPluralRules *shared = createSharedInstance( locale, type, status); if (U_FAILURE(status)) { - return NULL; + return nullptr; } PluralRules *result = (*shared)->clone(); shared->removeRef(); - if (result == NULL) { + if (result == nullptr) { status = U_MEMORY_ALLOCATION_ERROR; } return result; @@ -208,20 +221,23 @@ PluralRules::forLocale(const Locale& locale, UPluralType type, UErrorCode& statu PluralRules* U_EXPORT2 PluralRules::internalForLocale(const Locale& locale, UPluralType type, UErrorCode& status) { if (U_FAILURE(status)) { - return NULL; + return nullptr; } if (type >= UPLURAL_TYPE_COUNT) { status = U_ILLEGAL_ARGUMENT_ERROR; - return NULL; + return nullptr; } - PluralRules *newObj = new PluralRules(status); - if (newObj==NULL || U_FAILURE(status)) { - delete newObj; - return NULL; + LocalPointer newObj(new PluralRules(status), status); + if (U_FAILURE(status)) { + return nullptr; } UnicodeString locRule = newObj->getRuleFromResource(locale, type, status); - // TODO: which errors, if any, should be returned? + // TODO: which other errors, if any, should be returned? if (locRule.length() == 0) { + // If an out-of-memory error occurred, then stop and report the failure. + if (status == U_MEMORY_ALLOCATION_ERROR) { + return nullptr; + } // Locales with no specific rules (all numbers have the "other" category // will return a U_MISSING_RESOURCE_ERROR at this point. This is not // an error. @@ -229,13 +245,13 @@ PluralRules::internalForLocale(const Locale& locale, UPluralType type, UErrorCod status = U_ZERO_ERROR; } PluralRuleParser parser; - parser.parse(locRule, newObj, status); + parser.parse(locRule, newObj.getAlias(), status); // TODO: should rule parse errors be returned, or // should we silently use default rules? // Original impl used default rules. // Ask the question to ICU Core. - return newObj; + return newObj.orphan(); } UnicodeString @@ -250,7 +266,7 @@ PluralRules::select(double number) const { UnicodeString PluralRules::select(const IFixedDecimal &number) const { - if (mRules == NULL) { + if (mRules == nullptr) { return UnicodeString(TRUE, PLURAL_DEFAULT_RULE, -1); } else { @@ -262,14 +278,18 @@ PluralRules::select(const IFixedDecimal &number) const { StringEnumeration* PluralRules::getKeywords(UErrorCode& status) const { - if (U_FAILURE(status)) return NULL; - StringEnumeration* nameEnumerator = new PluralKeywordEnumeration(mRules, status); if (U_FAILURE(status)) { - delete nameEnumerator; - return NULL; + return nullptr; } - - return nameEnumerator; + if (U_FAILURE(mInternalStatus)) { + status = mInternalStatus; + return nullptr; + } + LocalPointer nameEnumerator(new PluralKeywordEnumeration(mRules, status), status); + if (U_FAILURE(status)) { + return nullptr; + } + return nameEnumerator.orphan(); } double @@ -367,8 +387,15 @@ getSamplesFromString(const UnicodeString &samples, double *dest, int32_t PluralRules::getSamples(const UnicodeString &keyword, double *dest, int32_t destCapacity, UErrorCode& status) { + if (destCapacity == 0 || U_FAILURE(status)) { + return 0; + } + if (U_FAILURE(mInternalStatus)) { + status = mInternalStatus; + return 0; + } RuleChain *rc = rulesForKeyword(keyword); - if (rc == NULL || destCapacity == 0 || U_FAILURE(status)) { + if (rc == nullptr) { return 0; } int32_t numSamples = getSamplesFromString(rc->fIntegerSamples, dest, destCapacity, status); @@ -381,7 +408,7 @@ PluralRules::getSamples(const UnicodeString &keyword, double *dest, RuleChain *PluralRules::rulesForKeyword(const UnicodeString &keyword) const { RuleChain *rc; - for (rc = mRules; rc != NULL; rc = rc->fNext) { + for (rc = mRules; rc != nullptr; rc = rc->fNext) { if (rc->fKeyword == keyword) { break; } @@ -395,7 +422,7 @@ PluralRules::isKeyword(const UnicodeString& keyword) const { if (0 == keyword.compare(PLURAL_KEYWORD_OTHER, 5)) { return true; } - return rulesForKeyword(keyword) != NULL; + return rulesForKeyword(keyword) != nullptr; } UnicodeString @@ -421,13 +448,13 @@ PluralRules::operator==(const PluralRules& other) const { return FALSE; } myKeywordList->reset(status); - while ((ptrKeyword=myKeywordList->snext(status))!=NULL) { + while ((ptrKeyword=myKeywordList->snext(status))!=nullptr) { if (!other.isKeyword(*ptrKeyword)) { return FALSE; } } otherKeywordList->reset(status); - while ((ptrKeyword=otherKeywordList->snext(status))!=NULL) { + while ((ptrKeyword=otherKeywordList->snext(status))!=nullptr) { if (!this->isKeyword(*ptrKeyword)) { return FALSE; } @@ -460,29 +487,33 @@ PluralRuleParser::parse(const UnicodeString& ruleData, PluralRules *prules, UErr } switch (type) { case tAnd: - U_ASSERT(curAndConstraint != NULL); - curAndConstraint = curAndConstraint->add(); + U_ASSERT(curAndConstraint != nullptr); + curAndConstraint = curAndConstraint->add(status); break; case tOr: { - U_ASSERT(currentChain != NULL); + U_ASSERT(currentChain != nullptr); OrConstraint *orNode=currentChain->ruleHeader; - while (orNode->next != NULL) { + while (orNode->next != nullptr) { orNode = orNode->next; } orNode->next= new OrConstraint(); + if (orNode->next == nullptr) { + status = U_MEMORY_ALLOCATION_ERROR; + break; + } orNode=orNode->next; - orNode->next=NULL; - curAndConstraint = orNode->add(); + orNode->next=nullptr; + curAndConstraint = orNode->add(status); } break; case tIs: - U_ASSERT(curAndConstraint != NULL); + U_ASSERT(curAndConstraint != nullptr); U_ASSERT(curAndConstraint->value == -1); - U_ASSERT(curAndConstraint->rangeList == NULL); + U_ASSERT(curAndConstraint->rangeList == nullptr); break; case tNot: - U_ASSERT(curAndConstraint != NULL); + U_ASSERT(curAndConstraint != nullptr); curAndConstraint->negated=TRUE; break; @@ -492,23 +523,29 @@ PluralRuleParser::parse(const UnicodeString& ruleData, PluralRules *prules, UErr case tIn: case tWithin: case tEqual: - U_ASSERT(curAndConstraint != NULL); - curAndConstraint->rangeList = new UVector32(status); - curAndConstraint->rangeList->addElement(-1, status); // range Low - curAndConstraint->rangeList->addElement(-1, status); // range Hi - rangeLowIdx = 0; - rangeHiIdx = 1; - curAndConstraint->value=PLURAL_RANGE_HIGH; - curAndConstraint->integerOnly = (type != tWithin); + { + U_ASSERT(curAndConstraint != nullptr); + LocalPointer newRangeList(new UVector32(status), status); + if (U_FAILURE(status)) { + break; + } + curAndConstraint->rangeList = newRangeList.orphan(); + curAndConstraint->rangeList->addElement(-1, status); // range Low + curAndConstraint->rangeList->addElement(-1, status); // range Hi + rangeLowIdx = 0; + rangeHiIdx = 1; + curAndConstraint->value=PLURAL_RANGE_HIGH; + curAndConstraint->integerOnly = (type != tWithin); + } break; case tNumber: - U_ASSERT(curAndConstraint != NULL); + U_ASSERT(curAndConstraint != nullptr); if ( (curAndConstraint->op==AndConstraint::MOD)&& (curAndConstraint->opNum == -1 ) ) { curAndConstraint->opNum=getNumberValue(token); } else { - if (curAndConstraint->rangeList == NULL) { + if (curAndConstraint->rangeList == nullptr) { // this is for an 'is' rule curAndConstraint->value = getNumberValue(token); } else { @@ -534,7 +571,7 @@ PluralRuleParser::parse(const UnicodeString& ruleData, PluralRules *prules, UErr case tComma: // TODO: rule syntax checking is inadequate, can happen with badly formed rules. // Catch cases like "n mod 10, is 1" here instead. - if (curAndConstraint == NULL || curAndConstraint->rangeList == NULL) { + if (curAndConstraint == nullptr || curAndConstraint->rangeList == nullptr) { status = U_UNEXPECTED_TOKEN; break; } @@ -545,7 +582,7 @@ PluralRuleParser::parse(const UnicodeString& ruleData, PluralRules *prules, UErr curAndConstraint->rangeList->addElement(-1, status); // range Hi break; case tMod: - U_ASSERT(curAndConstraint != NULL); + U_ASSERT(curAndConstraint != nullptr); curAndConstraint->op=AndConstraint::MOD; break; case tVariableN: @@ -553,24 +590,24 @@ PluralRuleParser::parse(const UnicodeString& ruleData, PluralRules *prules, UErr case tVariableF: case tVariableT: case tVariableV: - U_ASSERT(curAndConstraint != NULL); + U_ASSERT(curAndConstraint != nullptr); curAndConstraint->digitsType = type; break; case tKeyword: { RuleChain *newChain = new RuleChain; - if (newChain == NULL) { + if (newChain == nullptr) { status = U_MEMORY_ALLOCATION_ERROR; break; } newChain->fKeyword = token; - if (prules->mRules == NULL) { + if (prules->mRules == nullptr) { prules->mRules = newChain; } else { // The new rule chain goes at the end of the linked list of rule chains, // unless there is an "other" keyword & chain. "other" must remain last. RuleChain *insertAfter = prules->mRules; - while (insertAfter->fNext!=NULL && + while (insertAfter->fNext!=nullptr && insertAfter->fNext->fKeyword.compare(PLURAL_KEYWORD_OTHER, 5) != 0 ){ insertAfter=insertAfter->fNext; } @@ -578,8 +615,12 @@ PluralRuleParser::parse(const UnicodeString& ruleData, PluralRules *prules, UErr insertAfter->fNext = newChain; } OrConstraint *orNode = new OrConstraint(); + if (orNode == nullptr) { + status = U_MEMORY_ALLOCATION_ERROR; + break; + } newChain->ruleHeader = orNode; - curAndConstraint = orNode->add(); + curAndConstraint = orNode->add(status); currentChain = newChain; } break; @@ -629,7 +670,7 @@ PluralRules::getRuleFromResource(const Locale& locale, UPluralType type, UErrorC if (U_FAILURE(errCode)) { return emptyStr; } - LocalUResourceBundlePointer rb(ures_openDirect(NULL, "plurals", &errCode)); + LocalUResourceBundlePointer rb(ures_openDirect(nullptr, "plurals", &errCode)); if(U_FAILURE(errCode)) { return emptyStr; } @@ -646,7 +687,7 @@ PluralRules::getRuleFromResource(const Locale& locale, UPluralType type, UErrorC errCode = U_ILLEGAL_ARGUMENT_ERROR; return emptyStr; } - LocalUResourceBundlePointer locRes(ures_getByKey(rb.getAlias(), typeKey, NULL, &errCode)); + LocalUResourceBundlePointer locRes(ures_getByKey(rb.getAlias(), typeKey, nullptr, &errCode)); if(U_FAILURE(errCode)) { return emptyStr; } @@ -654,25 +695,25 @@ PluralRules::getRuleFromResource(const Locale& locale, UPluralType type, UErrorC const char *curLocaleName=locale.getName(); const UChar* s = ures_getStringByKey(locRes.getAlias(), curLocaleName, &resLen, &errCode); - if (s == NULL) { + if (s == nullptr) { // Check parent locales. UErrorCode status = U_ZERO_ERROR; char parentLocaleName[ULOC_FULLNAME_CAPACITY]; - const char *curLocaleName=locale.getName(); - uprv_strcpy(parentLocaleName, curLocaleName); + const char *curLocaleName2=locale.getName(); + uprv_strcpy(parentLocaleName, curLocaleName2); while (uloc_getParent(parentLocaleName, parentLocaleName, ULOC_FULLNAME_CAPACITY, &status) > 0) { resLen=0; s = ures_getStringByKey(locRes.getAlias(), parentLocaleName, &resLen, &status); - if (s != NULL) { + if (s != nullptr) { errCode = U_ZERO_ERROR; break; } status = U_ZERO_ERROR; } } - if (s==NULL) { + if (s==nullptr) { return emptyStr; } @@ -680,18 +721,18 @@ PluralRules::getRuleFromResource(const Locale& locale, UPluralType type, UErrorC u_UCharsToChars(s, setKey, resLen + 1); // printf("\n PluralRule: %s\n", setKey); - LocalUResourceBundlePointer ruleRes(ures_getByKey(rb.getAlias(), "rules", NULL, &errCode)); + LocalUResourceBundlePointer ruleRes(ures_getByKey(rb.getAlias(), "rules", nullptr, &errCode)); if(U_FAILURE(errCode)) { return emptyStr; } - LocalUResourceBundlePointer setRes(ures_getByKey(ruleRes.getAlias(), setKey, NULL, &errCode)); + LocalUResourceBundlePointer setRes(ures_getByKey(ruleRes.getAlias(), setKey, nullptr, &errCode)); if (U_FAILURE(errCode)) { return emptyStr; } int32_t numberKeys = ures_getSize(setRes.getAlias()); UnicodeString result; - const char *key=NULL; + const char *key=nullptr; for(int32_t i=0; idumpRules(rules); } return rules; } - -AndConstraint::AndConstraint() { - op = AndConstraint::NONE; - opNum=-1; - value = -1; - rangeList = NULL; - negated = FALSE; - integerOnly = FALSE; - digitsType = none; - next=NULL; -} - - AndConstraint::AndConstraint(const AndConstraint& other) { + this->fInternalStatus = other.fInternalStatus; + if (U_FAILURE(fInternalStatus)) { + return; // stop early if the object we are copying from is invalid. + } this->op = other.op; this->opNum=other.opNum; this->value=other.value; - this->rangeList=NULL; - if (other.rangeList != NULL) { - UErrorCode status = U_ZERO_ERROR; - this->rangeList = new UVector32(status); - this->rangeList->assign(*other.rangeList, status); + if (other.rangeList != nullptr) { + LocalPointer newRangeList(new UVector32(fInternalStatus), fInternalStatus); + if (U_FAILURE(fInternalStatus)) { + return; + } + this->rangeList = newRangeList.orphan(); + this->rangeList->assign(*other.rangeList, fInternalStatus); } this->integerOnly=other.integerOnly; this->negated=other.negated; this->digitsType = other.digitsType; - if (other.next==NULL) { - this->next=NULL; - } - else { + if (other.next != nullptr) { this->next = new AndConstraint(*other.next); + if (this->next == nullptr) { + fInternalStatus = U_MEMORY_ALLOCATION_ERROR; + } } } AndConstraint::~AndConstraint() { delete rangeList; - if (next!=NULL) { - delete next; - } + rangeList = nullptr; + delete next; + next = nullptr; } - UBool AndConstraint::isFulfilled(const IFixedDecimal &number) { UBool result = TRUE; @@ -776,7 +809,7 @@ AndConstraint::isFulfilled(const IFixedDecimal &number) { if (op == MOD) { n = fmod(n, opNum); } - if (rangeList == NULL) { + if (rangeList == nullptr) { result = value == -1 || // empty rule n == value; // 'is' rule break; @@ -796,53 +829,67 @@ AndConstraint::isFulfilled(const IFixedDecimal &number) { return result; } - AndConstraint* -AndConstraint::add() -{ +AndConstraint::add(UErrorCode& status) { + if (U_FAILURE(fInternalStatus)) { + status = fInternalStatus; + return nullptr; + } this->next = new AndConstraint(); + if (this->next == nullptr) { + status = U_MEMORY_ALLOCATION_ERROR; + } return this->next; } -OrConstraint::OrConstraint() { - childNode=NULL; - next=NULL; -} OrConstraint::OrConstraint(const OrConstraint& other) { - if ( other.childNode == NULL ) { - this->childNode = NULL; + this->fInternalStatus = other.fInternalStatus; + if (U_FAILURE(fInternalStatus)) { + return; // stop early if the object we are copying from is invalid. } - else { + if ( other.childNode != nullptr ) { this->childNode = new AndConstraint(*(other.childNode)); + if (this->childNode == nullptr) { + fInternalStatus = U_MEMORY_ALLOCATION_ERROR; + return; + } } - if (other.next == NULL ) { - this->next = NULL; - } - else { + if (other.next != nullptr ) { this->next = new OrConstraint(*(other.next)); + if (this->next == nullptr) { + fInternalStatus = U_MEMORY_ALLOCATION_ERROR; + return; + } + if (U_FAILURE(this->next->fInternalStatus)) { + this->fInternalStatus = this->next->fInternalStatus; + } } } OrConstraint::~OrConstraint() { - if (childNode!=NULL) { - delete childNode; - } - if (next!=NULL) { - delete next; - } + delete childNode; + childNode = nullptr; + delete next; + next = nullptr; } AndConstraint* -OrConstraint::add() -{ +OrConstraint::add(UErrorCode& status) { + if (U_FAILURE(fInternalStatus)) { + status = fInternalStatus; + return nullptr; + } OrConstraint *curOrConstraint=this; { - while (curOrConstraint->next!=NULL) { + while (curOrConstraint->next!=nullptr) { curOrConstraint = curOrConstraint->next; } - U_ASSERT(curOrConstraint->childNode == NULL); + U_ASSERT(curOrConstraint->childNode == nullptr); curOrConstraint->childNode = new AndConstraint(); + if (curOrConstraint->childNode == nullptr) { + status = U_MEMORY_ALLOCATION_ERROR; + } } return curOrConstraint->childNode; } @@ -852,10 +899,10 @@ OrConstraint::isFulfilled(const IFixedDecimal &number) { OrConstraint* orRule=this; UBool result=FALSE; - while (orRule!=NULL && !result) { + while (orRule!=nullptr && !result) { result=TRUE; AndConstraint* andRule = orRule->childNode; - while (andRule!=NULL && result) { + while (andRule!=nullptr && result) { result = andRule->isFulfilled(number); andRule=andRule->next; } @@ -866,19 +913,33 @@ OrConstraint::isFulfilled(const IFixedDecimal &number) { } -RuleChain::RuleChain(): fKeyword(), fNext(NULL), ruleHeader(NULL), fDecimalSamples(), fIntegerSamples(), - fDecimalSamplesUnbounded(FALSE), fIntegerSamplesUnbounded(FALSE) { -} - RuleChain::RuleChain(const RuleChain& other) : - fKeyword(other.fKeyword), fNext(NULL), ruleHeader(NULL), fDecimalSamples(other.fDecimalSamples), + fKeyword(other.fKeyword), fDecimalSamples(other.fDecimalSamples), fIntegerSamples(other.fIntegerSamples), fDecimalSamplesUnbounded(other.fDecimalSamplesUnbounded), - fIntegerSamplesUnbounded(other.fIntegerSamplesUnbounded) { - if (other.ruleHeader != NULL) { + fIntegerSamplesUnbounded(other.fIntegerSamplesUnbounded), fInternalStatus(other.fInternalStatus) { + if (U_FAILURE(this->fInternalStatus)) { + return; // stop early if the object we are copying from is invalid. + } + if (other.ruleHeader != nullptr) { this->ruleHeader = new OrConstraint(*(other.ruleHeader)); + if (this->ruleHeader == nullptr) { + this->fInternalStatus = U_MEMORY_ALLOCATION_ERROR; + } + else if (U_FAILURE(this->ruleHeader->fInternalStatus)) { + // If the OrConstraint wasn't fully copied, then set our status to failure as well. + this->fInternalStatus = this->ruleHeader->fInternalStatus; + return; // exit early. + } } - if (other.fNext != NULL ) { + if (other.fNext != nullptr ) { this->fNext = new RuleChain(*other.fNext); + if (this->fNext == nullptr) { + this->fInternalStatus = U_MEMORY_ALLOCATION_ERROR; + } + else if (U_FAILURE(this->fNext->fInternalStatus)) { + // If the RuleChain wasn't fully copied, then set our status to failure as well. + this->fInternalStatus = this->fNext->fInternalStatus; + } } } @@ -887,11 +948,10 @@ RuleChain::~RuleChain() { delete ruleHeader; } - UnicodeString RuleChain::select(const IFixedDecimal &number) const { if (!number.isNaN() && !number.isInfinite()) { - for (const RuleChain *rules = this; rules != NULL; rules = rules->fNext) { + for (const RuleChain *rules = this; rules != nullptr; rules = rules->fNext) { if (rules->ruleHeader->isFulfilled(number)) { return rules->fKeyword; } @@ -923,17 +983,17 @@ void RuleChain::dumpRules(UnicodeString& result) { UChar digitString[16]; - if ( ruleHeader != NULL ) { + if ( ruleHeader != nullptr ) { result += fKeyword; result += COLON; result += SPACE; OrConstraint* orRule=ruleHeader; - while ( orRule != NULL ) { + while ( orRule != nullptr ) { AndConstraint* andRule=orRule->childNode; - while ( andRule != NULL ) { - if ((andRule->op==AndConstraint::NONE) && (andRule->rangeList==NULL) && (andRule->value == -1)) { + while ( andRule != nullptr ) { + if ((andRule->op==AndConstraint::NONE) && (andRule->rangeList==nullptr) && (andRule->value == -1)) { // Empty Rules. - } else if ( (andRule->op==AndConstraint::NONE) && (andRule->rangeList==NULL) ) { + } else if ( (andRule->op==AndConstraint::NONE) && (andRule->rangeList==nullptr) ) { result += tokenString(andRule->digitsType); result += UNICODE_STRING_SIMPLE(" is "); if (andRule->negated) { @@ -950,7 +1010,7 @@ RuleChain::dumpRules(UnicodeString& result) { uprv_itou(digitString,16, andRule->opNum,10,0); result += UnicodeString(digitString); } - if (andRule->rangeList==NULL) { + if (andRule->rangeList==nullptr) { if (andRule->negated) { result += UNICODE_STRING_SIMPLE(" is not "); uprv_itou(digitString,16, andRule->value,10,0); @@ -993,16 +1053,16 @@ RuleChain::dumpRules(UnicodeString& result) { } } } - if ( (andRule=andRule->next) != NULL) { + if ( (andRule=andRule->next) != nullptr) { result += UNICODE_STRING_SIMPLE(" and "); } } - if ( (orRule = orRule->next) != NULL ) { + if ( (orRule = orRule->next) != nullptr ) { result += UNICODE_STRING_SIMPLE(" or "); } } } - if ( fNext != NULL ) { + if ( fNext != nullptr ) { result += UNICODE_STRING_SIMPLE("; "); fNext->dumpRules(result); } @@ -1011,6 +1071,9 @@ RuleChain::dumpRules(UnicodeString& result) { UErrorCode RuleChain::getKeywords(int32_t capacityOfKeywords, UnicodeString* keywords, int32_t& arraySize) const { + if (U_FAILURE(fInternalStatus)) { + return fInternalStatus; + } if ( arraySize < capacityOfKeywords-1 ) { keywords[arraySize++]=fKeyword; } @@ -1018,7 +1081,7 @@ RuleChain::getKeywords(int32_t capacityOfKeywords, UnicodeString* keywords, int3 return U_BUFFER_OVERFLOW_ERROR; } - if ( fNext != NULL ) { + if ( fNext != nullptr ) { return fNext->getKeywords(capacityOfKeywords, keywords, arraySize); } else { @@ -1032,7 +1095,7 @@ RuleChain::isKeyword(const UnicodeString& keywordParam) const { return TRUE; } - if ( fNext != NULL ) { + if ( fNext != nullptr ) { return fNext->isKeyword(keywordParam); } else { @@ -1043,7 +1106,7 @@ RuleChain::isKeyword(const UnicodeString& keywordParam) const { PluralRuleParser::PluralRuleParser() : ruleIndex(0), token(), type(none), prevType(none), - curAndConstraint(NULL), currentChain(NULL), rangeLowIdx(-1), rangeHiIdx(-1) + curAndConstraint(nullptr), currentChain(nullptr), rangeLowIdx(-1), rangeHiIdx(-1) { } @@ -1341,21 +1404,36 @@ PluralKeywordEnumeration::PluralKeywordEnumeration(RuleChain *header, UErrorCode return; } fKeywordNames.setDeleter(uprv_deleteUObject); - UBool addKeywordOther=TRUE; - RuleChain *node=header; - while(node!=NULL) { - fKeywordNames.addElement(new UnicodeString(node->fKeyword), status); + UBool addKeywordOther = TRUE; + RuleChain *node = header; + while (node != nullptr) { + auto newElem = new UnicodeString(node->fKeyword); + if (newElem == nullptr) { + status = U_MEMORY_ALLOCATION_ERROR; + return; + } + fKeywordNames.addElement(newElem, status); if (U_FAILURE(status)) { + delete newElem; return; } if (0 == node->fKeyword.compare(PLURAL_KEYWORD_OTHER, 5)) { - addKeywordOther= FALSE; + addKeywordOther = FALSE; } - node=node->fNext; + node = node->fNext; } if (addKeywordOther) { - fKeywordNames.addElement(new UnicodeString(PLURAL_KEYWORD_OTHER), status); + auto newElem = new UnicodeString(PLURAL_KEYWORD_OTHER); + if (newElem == nullptr) { + status = U_MEMORY_ALLOCATION_ERROR; + return; + } + fKeywordNames.addElement(newElem, status); + if (U_FAILURE(status)) { + delete newElem; + return; + } } } @@ -1364,7 +1442,7 @@ PluralKeywordEnumeration::snext(UErrorCode& status) { if (U_SUCCESS(status) && pos < fKeywordNames.size()) { return (const UnicodeString*)fKeywordNames.elementAt(pos++); } - return NULL; + return nullptr; } void @@ -1374,7 +1452,7 @@ PluralKeywordEnumeration::reset(UErrorCode& /*status*/) { int32_t PluralKeywordEnumeration::count(UErrorCode& /*status*/) const { - return fKeywordNames.size(); + return fKeywordNames.size(); } PluralKeywordEnumeration::~PluralKeywordEnumeration() { @@ -1634,41 +1712,39 @@ int32_t FixedDecimal::getVisibleFractionDigitCount() const { PluralAvailableLocalesEnumeration::PluralAvailableLocalesEnumeration(UErrorCode &status) { - fLocales = NULL; - fRes = NULL; fOpenStatus = status; if (U_FAILURE(status)) { return; } - fOpenStatus = U_ZERO_ERROR; - LocalUResourceBundlePointer rb(ures_openDirect(NULL, "plurals", &fOpenStatus)); - fLocales = ures_getByKey(rb.getAlias(), "locales", NULL, &fOpenStatus); + fOpenStatus = U_ZERO_ERROR; // clear any warnings. + LocalUResourceBundlePointer rb(ures_openDirect(nullptr, "plurals", &fOpenStatus)); + fLocales = ures_getByKey(rb.getAlias(), "locales", nullptr, &fOpenStatus); } PluralAvailableLocalesEnumeration::~PluralAvailableLocalesEnumeration() { ures_close(fLocales); ures_close(fRes); - fLocales = NULL; - fRes = NULL; + fLocales = nullptr; + fRes = nullptr; } const char *PluralAvailableLocalesEnumeration::next(int32_t *resultLength, UErrorCode &status) { if (U_FAILURE(status)) { - return NULL; + return nullptr; } if (U_FAILURE(fOpenStatus)) { status = fOpenStatus; - return NULL; + return nullptr; } fRes = ures_getNextResource(fLocales, fRes, &status); - if (fRes == NULL || U_FAILURE(status)) { + if (fRes == nullptr || U_FAILURE(status)) { if (status == U_INDEX_OUTOFBOUNDS_ERROR) { status = U_ZERO_ERROR; } - return NULL; + return nullptr; } const char *result = ures_getKey(fRes); - if (resultLength != NULL) { + if (resultLength != nullptr) { *resultLength = static_cast(uprv_strlen(result)); } return result; diff --git a/deps/icu-small/source/i18n/plurrule_impl.h b/deps/icu-small/source/i18n/plurrule_impl.h index 3ab445d5843c8b..f23ae168569d66 100644 --- a/deps/icu-small/source/i18n/plurrule_impl.h +++ b/deps/icu-small/source/i18n/plurrule_impl.h @@ -181,7 +181,6 @@ class PluralRuleParser: public UMemory { kRangeList, kSamples }; - }; enum PluralOperand { @@ -311,32 +310,36 @@ class AndConstraint : public UMemory { NONE, MOD } RuleOp; - RuleOp op; - int32_t opNum; // for mod expressions, the right operand of the mod. - int32_t value; // valid for 'is' rules only. - UVector32 *rangeList; // for 'in', 'within' rules. Null otherwise. - UBool negated; // TRUE for negated rules. - UBool integerOnly; // TRUE for 'within' rules. - tokenType digitsType; // n | i | v | f constraint. - AndConstraint *next; - - AndConstraint(); + RuleOp op = AndConstraint::NONE; + int32_t opNum = -1; // for mod expressions, the right operand of the mod. + int32_t value = -1; // valid for 'is' rules only. + UVector32 *rangeList = nullptr; // for 'in', 'within' rules. Null otherwise. + UBool negated = FALSE; // TRUE for negated rules. + UBool integerOnly = FALSE; // TRUE for 'within' rules. + tokenType digitsType = none; // n | i | v | f constraint. + AndConstraint *next = nullptr; + // Internal error status, used for errors that occur during the copy constructor. + UErrorCode fInternalStatus = U_ZERO_ERROR; + + AndConstraint() = default; AndConstraint(const AndConstraint& other); virtual ~AndConstraint(); - AndConstraint* add(); + AndConstraint* add(UErrorCode& status); // UBool isFulfilled(double number); UBool isFulfilled(const IFixedDecimal &number); }; class OrConstraint : public UMemory { public: - AndConstraint *childNode; - OrConstraint *next; - OrConstraint(); + AndConstraint *childNode = nullptr; + OrConstraint *next = nullptr; + // Internal error status, used for errors that occur during the copy constructor. + UErrorCode fInternalStatus = U_ZERO_ERROR; + OrConstraint() = default; OrConstraint(const OrConstraint& other); virtual ~OrConstraint(); - AndConstraint* add(); + AndConstraint* add(UErrorCode& status); // UBool isFulfilled(double number); UBool isFulfilled(const IFixedDecimal &number); }; @@ -344,15 +347,16 @@ class OrConstraint : public UMemory { class RuleChain : public UMemory { public: UnicodeString fKeyword; - RuleChain *fNext; - OrConstraint *ruleHeader; + RuleChain *fNext = nullptr; + OrConstraint *ruleHeader = nullptr; UnicodeString fDecimalSamples; // Samples strings from rule source UnicodeString fIntegerSamples; // without @decimal or @integer, otherwise unprocessed. - UBool fDecimalSamplesUnbounded; - UBool fIntegerSamplesUnbounded; - + UBool fDecimalSamplesUnbounded = FALSE; + UBool fIntegerSamplesUnbounded = FALSE; + // Internal error status, used for errors that occur during the copy constructor. + UErrorCode fInternalStatus = U_ZERO_ERROR; - RuleChain(); + RuleChain() = default; RuleChain(const RuleChain& other); virtual ~RuleChain(); @@ -386,8 +390,8 @@ class U_I18N_API PluralAvailableLocalesEnumeration: public StringEnumeration { virtual int32_t count(UErrorCode& status) const; private: UErrorCode fOpenStatus; - UResourceBundle *fLocales; - UResourceBundle *fRes; + UResourceBundle *fLocales = nullptr; + UResourceBundle *fRes = nullptr; }; U_NAMESPACE_END diff --git a/deps/icu-small/source/i18n/rbnf.cpp b/deps/icu-small/source/i18n/rbnf.cpp index ab9ad15e8c720d..74707ccd22d2ac 100644 --- a/deps/icu-small/source/i18n/rbnf.cpp +++ b/deps/icu-small/source/i18n/rbnf.cpp @@ -680,7 +680,7 @@ StringLocalizationInfo::getDisplayName(int32_t localeIndex, int32_t ruleIndex) c RuleBasedNumberFormat::RuleBasedNumberFormat(const UnicodeString& description, const UnicodeString& locs, const Locale& alocale, UParseError& perror, UErrorCode& status) - : ruleSets(NULL) + : fRuleSets(NULL) , ruleSetDescriptions(NULL) , numRuleSets(0) , defaultRuleSet(NULL) @@ -689,7 +689,7 @@ RuleBasedNumberFormat::RuleBasedNumberFormat(const UnicodeString& description, , decimalFormatSymbols(NULL) , defaultInfinityRule(NULL) , defaultNaNRule(NULL) - , roundingMode(DecimalFormat::ERoundingMode::kRoundUnnecessary) + , fRoundingMode(DecimalFormat::ERoundingMode::kRoundUnnecessary) , lenient(FALSE) , lenientParseRules(NULL) , localizations(NULL) @@ -705,7 +705,7 @@ RuleBasedNumberFormat::RuleBasedNumberFormat(const UnicodeString& description, RuleBasedNumberFormat::RuleBasedNumberFormat(const UnicodeString& description, const UnicodeString& locs, UParseError& perror, UErrorCode& status) - : ruleSets(NULL) + : fRuleSets(NULL) , ruleSetDescriptions(NULL) , numRuleSets(0) , defaultRuleSet(NULL) @@ -714,7 +714,7 @@ RuleBasedNumberFormat::RuleBasedNumberFormat(const UnicodeString& description, , decimalFormatSymbols(NULL) , defaultInfinityRule(NULL) , defaultNaNRule(NULL) - , roundingMode(DecimalFormat::ERoundingMode::kRoundUnnecessary) + , fRoundingMode(DecimalFormat::ERoundingMode::kRoundUnnecessary) , lenient(FALSE) , lenientParseRules(NULL) , localizations(NULL) @@ -730,7 +730,7 @@ RuleBasedNumberFormat::RuleBasedNumberFormat(const UnicodeString& description, RuleBasedNumberFormat::RuleBasedNumberFormat(const UnicodeString& description, LocalizationInfo* info, const Locale& alocale, UParseError& perror, UErrorCode& status) - : ruleSets(NULL) + : fRuleSets(NULL) , ruleSetDescriptions(NULL) , numRuleSets(0) , defaultRuleSet(NULL) @@ -739,7 +739,7 @@ RuleBasedNumberFormat::RuleBasedNumberFormat(const UnicodeString& description, , decimalFormatSymbols(NULL) , defaultInfinityRule(NULL) , defaultNaNRule(NULL) - , roundingMode(DecimalFormat::ERoundingMode::kRoundUnnecessary) + , fRoundingMode(DecimalFormat::ERoundingMode::kRoundUnnecessary) , lenient(FALSE) , lenientParseRules(NULL) , localizations(NULL) @@ -754,7 +754,7 @@ RuleBasedNumberFormat::RuleBasedNumberFormat(const UnicodeString& description, RuleBasedNumberFormat::RuleBasedNumberFormat(const UnicodeString& description, UParseError& perror, UErrorCode& status) - : ruleSets(NULL) + : fRuleSets(NULL) , ruleSetDescriptions(NULL) , numRuleSets(0) , defaultRuleSet(NULL) @@ -763,7 +763,7 @@ RuleBasedNumberFormat::RuleBasedNumberFormat(const UnicodeString& description, , decimalFormatSymbols(NULL) , defaultInfinityRule(NULL) , defaultNaNRule(NULL) - , roundingMode(DecimalFormat::ERoundingMode::kRoundUnnecessary) + , fRoundingMode(DecimalFormat::ERoundingMode::kRoundUnnecessary) , lenient(FALSE) , lenientParseRules(NULL) , localizations(NULL) @@ -779,7 +779,7 @@ RuleBasedNumberFormat::RuleBasedNumberFormat(const UnicodeString& description, const Locale& aLocale, UParseError& perror, UErrorCode& status) - : ruleSets(NULL) + : fRuleSets(NULL) , ruleSetDescriptions(NULL) , numRuleSets(0) , defaultRuleSet(NULL) @@ -788,7 +788,7 @@ RuleBasedNumberFormat::RuleBasedNumberFormat(const UnicodeString& description, , decimalFormatSymbols(NULL) , defaultInfinityRule(NULL) , defaultNaNRule(NULL) - , roundingMode(DecimalFormat::ERoundingMode::kRoundUnnecessary) + , fRoundingMode(DecimalFormat::ERoundingMode::kRoundUnnecessary) , lenient(FALSE) , lenientParseRules(NULL) , localizations(NULL) @@ -801,7 +801,7 @@ RuleBasedNumberFormat::RuleBasedNumberFormat(const UnicodeString& description, } RuleBasedNumberFormat::RuleBasedNumberFormat(URBNFRuleSetTag tag, const Locale& alocale, UErrorCode& status) - : ruleSets(NULL) + : fRuleSets(NULL) , ruleSetDescriptions(NULL) , numRuleSets(0) , defaultRuleSet(NULL) @@ -810,7 +810,7 @@ RuleBasedNumberFormat::RuleBasedNumberFormat(URBNFRuleSetTag tag, const Locale& , decimalFormatSymbols(NULL) , defaultInfinityRule(NULL) , defaultNaNRule(NULL) - , roundingMode(DecimalFormat::ERoundingMode::kRoundUnnecessary) + , fRoundingMode(DecimalFormat::ERoundingMode::kRoundUnnecessary) , lenient(FALSE) , lenientParseRules(NULL) , localizations(NULL) @@ -868,7 +868,7 @@ RuleBasedNumberFormat::RuleBasedNumberFormat(URBNFRuleSetTag tag, const Locale& RuleBasedNumberFormat::RuleBasedNumberFormat(const RuleBasedNumberFormat& rhs) : NumberFormat(rhs) - , ruleSets(NULL) + , fRuleSets(NULL) , ruleSetDescriptions(NULL) , numRuleSets(0) , defaultRuleSet(NULL) @@ -877,7 +877,7 @@ RuleBasedNumberFormat::RuleBasedNumberFormat(const RuleBasedNumberFormat& rhs) , decimalFormatSymbols(NULL) , defaultInfinityRule(NULL) , defaultNaNRule(NULL) - , roundingMode(DecimalFormat::ERoundingMode::kRoundUnnecessary) + , fRoundingMode(DecimalFormat::ERoundingMode::kRoundUnnecessary) , lenient(FALSE) , lenientParseRules(NULL) , localizations(NULL) @@ -950,8 +950,8 @@ RuleBasedNumberFormat::operator==(const Format& other) const ? FALSE : *localizations == rhs.localizations))) { - NFRuleSet** p = ruleSets; - NFRuleSet** q = rhs.ruleSets; + NFRuleSet** p = fRuleSets; + NFRuleSet** q = rhs.fRuleSets; if (p == NULL) { return q == NULL; } else if (q == NULL) { @@ -972,8 +972,8 @@ UnicodeString RuleBasedNumberFormat::getRules() const { UnicodeString result; - if (ruleSets != NULL) { - for (NFRuleSet** p = ruleSets; *p; ++p) { + if (fRuleSets != NULL) { + for (NFRuleSet** p = fRuleSets; *p; ++p) { (*p)->appendRules(result); } } @@ -987,9 +987,9 @@ RuleBasedNumberFormat::getRuleSetName(int32_t index) const UnicodeString string(TRUE, localizations->getRuleSetName(index), (int32_t)-1); return string; } - else if (ruleSets) { + else if (fRuleSets) { UnicodeString result; - for (NFRuleSet** p = ruleSets; *p; ++p) { + for (NFRuleSet** p = fRuleSets; *p; ++p) { NFRuleSet* rs = *p; if (rs->isPublic()) { if (--index == -1) { @@ -1010,8 +1010,8 @@ RuleBasedNumberFormat::getNumberOfRuleSetNames() const if (localizations) { result = localizations->getNumberOfRuleSets(); } - else if (ruleSets) { - for (NFRuleSet** p = ruleSets; *p; ++p) { + else if (fRuleSets) { + for (NFRuleSet** p = fRuleSets; *p; ++p) { if ((**p).isPublic()) { ++result; } @@ -1098,8 +1098,8 @@ RuleBasedNumberFormat::getRuleSetDisplayName(const UnicodeString& ruleSetName, c NFRuleSet* RuleBasedNumberFormat::findRuleSet(const UnicodeString& name, UErrorCode& status) const { - if (U_SUCCESS(status) && ruleSets) { - for (NFRuleSet** p = ruleSets; *p; ++p) { + if (U_SUCCESS(status) && fRuleSets) { + for (NFRuleSet** p = fRuleSets; *p; ++p) { NFRuleSet* rs = *p; if (rs->isNamed(name)) { return rs; @@ -1132,11 +1132,17 @@ RuleBasedNumberFormat::format(const DecimalQuantity &number, // The DecimalFormat will provide more accurate results. // TODO this section should probably be optimized. The DecimalFormat is shared in ICU4J. - NumberFormat *decimalFormat = NumberFormat::createInstance(locale, UNUM_DECIMAL, status); + LocalPointer decimalFormat(NumberFormat::createInstance(locale, UNUM_DECIMAL, status), status); + if (decimalFormat.isNull()) { + return appendTo; + } Formattable f; - f.adoptDecimalQuantity(new DecimalQuantity(number)); + LocalPointer decimalQuantity(new DecimalQuantity(number), status); + if (decimalQuantity.isNull()) { + return appendTo; + } + f.adoptDecimalQuantity(decimalQuantity.orphan()); // f now owns decimalQuantity. decimalFormat->format(f, appendTo, posIter, status); - delete decimalFormat; } } return appendTo; @@ -1165,11 +1171,17 @@ RuleBasedNumberFormat::format(const DecimalQuantity &number, // The DecimalFormat will provide more accurate results. // TODO this section should probably be optimized. The DecimalFormat is shared in ICU4J. - NumberFormat *decimalFormat = NumberFormat::createInstance(locale, UNUM_DECIMAL, status); + LocalPointer decimalFormat(NumberFormat::createInstance(locale, UNUM_DECIMAL, status), status); + if (decimalFormat.isNull()) { + return appendTo; + } Formattable f; - f.adoptDecimalQuantity(new DecimalQuantity(number)); + LocalPointer decimalQuantity(new DecimalQuantity(number), status); + if (decimalQuantity.isNull()) { + return appendTo; + } + f.adoptDecimalQuantity(decimalQuantity.orphan()); // f now owns decimalQuantity. decimalFormat->format(f, appendTo, pos, status); - delete decimalFormat; } } return appendTo; @@ -1312,11 +1324,19 @@ RuleBasedNumberFormat::format(int64_t number, NFRuleSet *ruleSet, UnicodeString& // TODO this section should probably be optimized. The DecimalFormat is shared in ICU4J. NumberFormat *decimalFormat = NumberFormat::createInstance(locale, UNUM_DECIMAL, status); + if (decimalFormat == nullptr) { + return toAppendTo; + } Formattable f; FieldPosition pos(FieldPosition::DONT_CARE); - DecimalQuantity *digitList = new DecimalQuantity(); - digitList->setToLong(number); - f.adoptDecimalQuantity(digitList); + DecimalQuantity *decimalQuantity = new DecimalQuantity(); + if (decimalQuantity == nullptr) { + status = U_MEMORY_ALLOCATION_ERROR; + delete decimalFormat; + return toAppendTo; + } + decimalQuantity->setToLong(number); + f.adoptDecimalQuantity(decimalQuantity); // f now owns decimalQuantity. decimalFormat->format(f, toAppendTo, pos, status); delete decimalFormat; } @@ -1358,7 +1378,7 @@ RuleBasedNumberFormat::parse(const UnicodeString& text, Formattable& result, ParsePosition& parsePosition) const { - if (!ruleSets) { + if (!fRuleSets) { parsePosition.setErrorIndex(0); return; } @@ -1369,7 +1389,7 @@ RuleBasedNumberFormat::parse(const UnicodeString& text, ParsePosition high_pp(0); Formattable high_result; - for (NFRuleSet** p = ruleSets; *p; ++p) { + for (NFRuleSet** p = fRuleSets; *p; ++p) { NFRuleSet *rp = *p; if (rp->isPublic() && rp->isParseable()) { ParsePosition working_pp(0); @@ -1457,7 +1477,7 @@ void RuleBasedNumberFormat::initDefaultRuleSet() { defaultRuleSet = NULL; - if (!ruleSets) { + if (!fRuleSets) { return; } @@ -1465,7 +1485,7 @@ RuleBasedNumberFormat::initDefaultRuleSet() const UnicodeString ordinal(UNICODE_STRING_SIMPLE("%digits-ordinal")); const UnicodeString duration(UNICODE_STRING_SIMPLE("%duration")); - NFRuleSet**p = &ruleSets[0]; + NFRuleSet**p = &fRuleSets[0]; while (*p) { if ((*p)->isNamed(spellout) || (*p)->isNamed(ordinal) || (*p)->isNamed(duration)) { defaultRuleSet = *p; @@ -1477,7 +1497,7 @@ RuleBasedNumberFormat::initDefaultRuleSet() defaultRuleSet = *--p; if (!defaultRuleSet->isPublic()) { - while (p != ruleSets) { + while (p != fRuleSets) { if ((*--p)->isPublic()) { defaultRuleSet = *p; break; @@ -1547,7 +1567,7 @@ RuleBasedNumberFormat::init(const UnicodeString& rules, LocalizationInfo* locali // from the description lenientParseRules = new UnicodeString(); /* test for NULL */ - if (lenientParseRules == 0) { + if (lenientParseRules == nullptr) { status = U_MEMORY_ALLOCATION_ERROR; return; } @@ -1568,15 +1588,15 @@ RuleBasedNumberFormat::init(const UnicodeString& rules, LocalizationInfo* locali ++numRuleSets; // our rule list is an array of the appropriate size - ruleSets = (NFRuleSet **)uprv_malloc((numRuleSets + 1) * sizeof(NFRuleSet *)); + fRuleSets = (NFRuleSet **)uprv_malloc((numRuleSets + 1) * sizeof(NFRuleSet *)); /* test for NULL */ - if (ruleSets == 0) { + if (fRuleSets == 0) { status = U_MEMORY_ALLOCATION_ERROR; return; } for (int i = 0; i <= numRuleSets; ++i) { - ruleSets[i] = NULL; + fRuleSets[i] = NULL; } // divide up the descriptions into individual rule-set descriptions @@ -1592,7 +1612,7 @@ RuleBasedNumberFormat::init(const UnicodeString& rules, LocalizationInfo* locali } ruleSetDescriptions = new UnicodeString[numRuleSets]; - if (ruleSetDescriptions == 0) { + if (ruleSetDescriptions == nullptr) { status = U_MEMORY_ALLOCATION_ERROR; return; } @@ -1602,8 +1622,8 @@ RuleBasedNumberFormat::init(const UnicodeString& rules, LocalizationInfo* locali int32_t start = 0; for (int32_t p = description.indexOf(gSemiPercent, 2, 0); p != -1; p = description.indexOf(gSemiPercent, 2, start)) { ruleSetDescriptions[curRuleSet].setTo(description, start, p + 1 - start); - ruleSets[curRuleSet] = new NFRuleSet(this, ruleSetDescriptions, curRuleSet, status); - if (ruleSets[curRuleSet] == 0) { + fRuleSets[curRuleSet] = new NFRuleSet(this, ruleSetDescriptions, curRuleSet, status); + if (fRuleSets[curRuleSet] == nullptr) { status = U_MEMORY_ALLOCATION_ERROR; return; } @@ -1611,8 +1631,8 @@ RuleBasedNumberFormat::init(const UnicodeString& rules, LocalizationInfo* locali start = p + 1; } ruleSetDescriptions[curRuleSet].setTo(description, start, description.length() - start); - ruleSets[curRuleSet] = new NFRuleSet(this, ruleSetDescriptions, curRuleSet, status); - if (ruleSets[curRuleSet] == 0) { + fRuleSets[curRuleSet] = new NFRuleSet(this, ruleSetDescriptions, curRuleSet, status); + if (fRuleSets[curRuleSet] == nullptr) { status = U_MEMORY_ALLOCATION_ERROR; return; } @@ -1630,11 +1650,11 @@ RuleBasedNumberFormat::init(const UnicodeString& rules, LocalizationInfo* locali initDefaultRuleSet(); // finally, we can go back through the temporary descriptions - // list and finish seting up the substructure (and we throw + // list and finish setting up the substructure (and we throw // away the temporary descriptions as we go) { for (int i = 0; i < numRuleSets; i++) { - ruleSets[i]->parseRules(ruleSetDescriptions[i], status); + fRuleSets[i]->parseRules(ruleSetDescriptions[i], status); } } @@ -1680,7 +1700,7 @@ RuleBasedNumberFormat::setContext(UDisplayContext value, UErrorCode& status) if ( capitalizationBrkIter == NULL && (value==UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE || (value==UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU && capitalizationForUIListMenu) || (value==UDISPCTX_CAPITALIZATION_FOR_STANDALONE && capitalizationForStandAlone)) ) { - UErrorCode status = U_ZERO_ERROR; + status = U_ZERO_ERROR; capitalizationBrkIter = BreakIterator::createSentenceInstance(locale, status); if (U_FAILURE(status)) { delete capitalizationBrkIter; @@ -1704,8 +1724,8 @@ RuleBasedNumberFormat::initCapitalizationContextInfo(const Locale& thelocale) int32_t len = 0; const int32_t * intVector = ures_getIntVector(rb, &len, &status); if (U_SUCCESS(status) && intVector != NULL && len >= 2) { - capitalizationForUIListMenu = intVector[0]; - capitalizationForStandAlone = intVector[1]; + capitalizationForUIListMenu = static_cast(intVector[0]); + capitalizationForStandAlone = static_cast(intVector[1]); } } ures_close(rb); @@ -1740,7 +1760,7 @@ RuleBasedNumberFormat::stripWhitespace(UnicodeString& description) start = p + 1; } - // when we get here, we've seeked off the end of the sring, and + // when we get here, we've seeked off the end of the string, and // we terminate the loop (we continue until *start* is -1 rather // than until *p* is -1, because otherwise we'd miss the last // rule in the description) @@ -1756,12 +1776,12 @@ RuleBasedNumberFormat::stripWhitespace(UnicodeString& description) void RuleBasedNumberFormat::dispose() { - if (ruleSets) { - for (NFRuleSet** p = ruleSets; *p; ++p) { + if (fRuleSets) { + for (NFRuleSet** p = fRuleSets; *p; ++p) { delete *p; } - uprv_free(ruleSets); - ruleSets = NULL; + uprv_free(fRuleSets); + fRuleSets = NULL; } if (ruleSetDescriptions) { @@ -1811,7 +1831,7 @@ const RuleBasedCollator* RuleBasedNumberFormat::getCollator() const { #if !UCONFIG_NO_COLLATION - if (!ruleSets) { + if (!fRuleSets) { return NULL; } @@ -1820,7 +1840,7 @@ RuleBasedNumberFormat::getCollator() const // create a default collator based on the formatter's locale, // then pull out that collator's rules, append any additional // rules specified in the description, and create a _new_ - // collator based on the combinaiton of those rules + // collator based on the combination of those rules UErrorCode status = U_ZERO_ERROR; @@ -1863,13 +1883,10 @@ RuleBasedNumberFormat::initializeDecimalFormatSymbols(UErrorCode &status) // lazy-evaluate the DecimalFormatSymbols object. This object // is shared by all DecimalFormat instances belonging to this // formatter - if (decimalFormatSymbols == NULL) { - DecimalFormatSymbols* temp = new DecimalFormatSymbols(locale, status); + if (decimalFormatSymbols == nullptr) { + LocalPointer temp(new DecimalFormatSymbols(locale, status), status); if (U_SUCCESS(status)) { - decimalFormatSymbols = temp; - } - else { - delete temp; + decimalFormatSymbols = temp.orphan(); } } return decimalFormatSymbols; @@ -1889,17 +1906,14 @@ NFRule* RuleBasedNumberFormat::initializeDefaultInfinityRule(UErrorCode &status) { if (U_FAILURE(status)) { - return NULL; + return nullptr; } if (defaultInfinityRule == NULL) { UnicodeString rule(UNICODE_STRING_SIMPLE("Inf: ")); rule.append(getDecimalFormatSymbols()->getSymbol(DecimalFormatSymbols::kInfinitySymbol)); - NFRule* temp = new NFRule(this, rule, status); + LocalPointer temp(new NFRule(this, rule, status), status); if (U_SUCCESS(status)) { - defaultInfinityRule = temp; - } - else { - delete temp; + defaultInfinityRule = temp.orphan(); } } return defaultInfinityRule; @@ -1915,17 +1929,14 @@ NFRule* RuleBasedNumberFormat::initializeDefaultNaNRule(UErrorCode &status) { if (U_FAILURE(status)) { - return NULL; + return nullptr; } - if (defaultNaNRule == NULL) { + if (defaultNaNRule == nullptr) { UnicodeString rule(UNICODE_STRING_SIMPLE("NaN: ")); rule.append(getDecimalFormatSymbols()->getSymbol(DecimalFormatSymbols::kNaNSymbol)); - NFRule* temp = new NFRule(this, rule, status); + LocalPointer temp(new NFRule(this, rule, status), status); if (U_SUCCESS(status)) { - defaultNaNRule = temp; - } - else { - delete temp; + defaultNaNRule = temp.orphan(); } } return defaultNaNRule; @@ -1963,15 +1974,15 @@ RuleBasedNumberFormat::adoptDecimalFormatSymbols(DecimalFormatSymbols* symbolsTo defaultNaNRule = NULL; initializeDefaultNaNRule(status); // Reset with the new DecimalFormatSymbols - if (ruleSets) { + if (fRuleSets) { for (int32_t i = 0; i < numRuleSets; i++) { - ruleSets[i]->setDecimalFormatSymbols(*symbolsToAdopt, status); + fRuleSets[i]->setDecimalFormatSymbols(*symbolsToAdopt, status); } } } } -// Setting the symbols is equlivalent to adopting a newly created localized symbols. +// Setting the symbols is equivalent to adopting a newly created localized symbols. void RuleBasedNumberFormat::setDecimalFormatSymbols(const DecimalFormatSymbols& symbols) { @@ -1983,7 +1994,11 @@ RuleBasedNumberFormat::createPluralFormat(UPluralType pluralType, const UnicodeString &pattern, UErrorCode& status) const { - return new PluralFormat(locale, pluralType, pattern, status); + auto *pf = new PluralFormat(locale, pluralType, pattern, status); + if (pf == nullptr) { + status = U_MEMORY_ALLOCATION_ERROR; + } + return pf; } /** @@ -1991,7 +2006,7 @@ RuleBasedNumberFormat::createPluralFormat(UPluralType pluralType, * @return A rounding mode */ DecimalFormat::ERoundingMode RuleBasedNumberFormat::getRoundingMode() const { - return roundingMode; + return fRoundingMode; } /** @@ -2000,7 +2015,7 @@ DecimalFormat::ERoundingMode RuleBasedNumberFormat::getRoundingMode() const { * @param roundingMode A rounding mode */ void RuleBasedNumberFormat::setRoundingMode(DecimalFormat::ERoundingMode roundingMode) { - this->roundingMode = roundingMode; + fRoundingMode = roundingMode; } U_NAMESPACE_END diff --git a/deps/icu-small/source/i18n/rbt.h b/deps/icu-small/source/i18n/rbt.h index 005fb853847b11..a18452ab2ecb49 100644 --- a/deps/icu-small/source/i18n/rbt.h +++ b/deps/icu-small/source/i18n/rbt.h @@ -29,261 +29,9 @@ class TransliterationRuleData; /** * RuleBasedTransliterator is a transliterator - * that reads a set of rules in order to determine how to perform - * translations. Rule sets are stored in resource bundles indexed by - * name. Rules within a rule set are separated by semicolons (';'). - * To include a literal semicolon, prefix it with a backslash ('\'). - * Whitespace, as defined by Character.isWhitespace(), - * is ignored. If the first non-blank character on a line is '#', - * the entire line is ignored as a comment.

    - * - *

    Each set of rules consists of two groups, one forward, and one - * reverse. This is a convention that is not enforced; rules for one - * direction may be omitted, with the result that translations in - * that direction will not modify the source text. In addition, - * bidirectional forward-reverse rules may be specified for - * symmetrical transformations.

    - * - *

    Rule syntax

    - * - *

    Rule statements take one of the following forms:

    - * - *
    - *
    $alefmadda=\u0622;
    - *
    Variable definition. The name on the - * left is assigned the text on the right. In this example, - * after this statement, instances of the left hand name, - * "$alefmadda", will be replaced by - * the Unicode character U+0622. Variable names must begin - * with a letter and consist only of letters, digits, and - * underscores. Case is significant. Duplicate names cause - * an exception to be thrown, that is, variables cannot be - * redefined. The right hand side may contain well-formed - * text of any length, including no text at all ("$empty=;"). - * The right hand side may contain embedded UnicodeSet - * patterns, for example, "$softvowel=[eiyEIY]".
    - *
     
    - *
    ai>$alefmadda;
    - *
    Forward translation rule. This rule - * states that the string on the left will be changed to the - * string on the right when performing forward - * transliteration.
    - *
     
    - *
    ai<$alefmadda;
    - *
    Reverse translation rule. This rule - * states that the string on the right will be changed to - * the string on the left when performing reverse - * transliteration.
    - *
    - * - *
    - *
    ai<>$alefmadda;
    - *
    Bidirectional translation rule. This - * rule states that the string on the right will be changed - * to the string on the left when performing forward - * transliteration, and vice versa when performing reverse - * transliteration.
    - *
    - * - *

    Translation rules consist of a match pattern and an output - * string. The match pattern consists of literal characters, - * optionally preceded by context, and optionally followed by - * context. Context characters, like literal pattern characters, - * must be matched in the text being transliterated. However, unlike - * literal pattern characters, they are not replaced by the output - * text. For example, the pattern "abc{def}" - * indicates the characters "def" must be - * preceded by "abc" for a successful match. - * If there is a successful match, "def" will - * be replaced, but not "abc". The final '}' - * is optional, so "abc{def" is equivalent to - * "abc{def}". Another example is "{123}456" - * (or "123}456") in which the literal - * pattern "123" must be followed by "456". - *

    - * - *

    The output string of a forward or reverse rule consists of - * characters to replace the literal pattern characters. If the - * output string contains the character '|', this is - * taken to indicate the location of the cursor after - * replacement. The cursor is the point in the text at which the - * next replacement, if any, will be applied. The cursor is usually - * placed within the replacement text; however, it can actually be - * placed into the precending or following context by using the - * special character '@'. Examples:

    - * - *
    - *

    a {foo} z > | @ bar; # foo -> bar, move cursor - * before a
    - * {foo} xyz > bar @@|; # foo -> bar, cursor between - * y and z

    - *
    - * - *

    UnicodeSet

    - * - *

    UnicodeSet patterns may appear anywhere that - * makes sense. They may appear in variable definitions. - * Contrariwise, UnicodeSet patterns may themselves - * contain variable references, such as "$a=[a-z];$not_a=[^$a]", - * or "$range=a-z;$ll=[$range]".

    - * - *

    UnicodeSet patterns may also be embedded directly - * into rule strings. Thus, the following two rules are equivalent:

    - * - *
    - *

    $vowel=[aeiou]; $vowel>'*'; # One way to do this
    - * [aeiou]>'*'; - *                # - * Another way

    - *
    - * - *

    See {@link UnicodeSet} for more documentation and examples.

    - * - *

    Segments

    - * - *

    Segments of the input string can be matched and copied to the - * output string. This makes certain sets of rules simpler and more - * general, and makes reordering possible. For example:

    - * - *
    - *

    ([a-z]) > $1 $1; - *           # - * double lowercase letters
    - * ([:Lu:]) ([:Ll:]) > $2 $1; # reverse order of Lu-Ll pairs

    - *
    - * - *

    The segment of the input string to be copied is delimited by - * "(" and ")". Up to - * nine segments may be defined. Segments may not overlap. In the - * output string, "$1" through "$9" - * represent the input string segments, in left-to-right order of - * definition.

    - * - *

    Anchors

    - * - *

    Patterns can be anchored to the beginning or the end of the text. This is done with the - * special characters '^' and '$'. For example:

    - * - *
    - *

    ^ a   > 'BEG_A';   # match 'a' at start of text
    - *   a   > 'A';       # match other instances - * of 'a'
    - *   z $ > 'END_Z';   # match 'z' at end of text
    - *   z   > 'Z';       # match other instances - * of 'z'

    - *
    - * - *

    It is also possible to match the beginning or the end of the text using a UnicodeSet. - * This is done by including a virtual anchor character '$' at the end of the - * set pattern. Although this is usually the match chafacter for the end anchor, the set will - * match either the beginning or the end of the text, depending on its placement. For - * example:

    - * - *
    - *

    $x = [a-z$];   # match 'a' through 'z' OR anchor
    - * $x 1    > 2;   # match '1' after a-z or at the start
    - *    3 $x > 4;   # match '3' before a-z or at the end

    - *
    - * - *

    Example

    - * - *

    The following example rules illustrate many of the features of - * the rule language.

    - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
    Rule 1.abc{def}>x|y
    Rule 2.xyz>r
    Rule 3.yz>q
    - * - *

    Applying these rules to the string "adefabcdefz" - * yields the following results:

    - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
    |adefabcdefzInitial state, no rules match. Advance - * cursor.
    a|defabcdefzStill no match. Rule 1 does not match - * because the preceding context is not present.
    ad|efabcdefzStill no match. Keep advancing until - * there is a match...
    ade|fabcdefz...
    adef|abcdefz...
    adefa|bcdefz...
    adefab|cdefz...
    adefabc|defzRule 1 matches; replace "def" - * with "xy" and back up the cursor - * to before the 'y'.
    adefabcx|yzAlthough "xyz" is - * present, rule 2 does not match because the cursor is - * before the 'y', not before the 'x'. - * Rule 3 does match. Replace "yz" - * with "q".
    adefabcxq|The cursor is at the end; - * transliteration is complete.
    - * - *

    The order of rules is significant. If multiple rules may match - * at some point, the first matching rule is applied.

    - * - *

    Forward and reverse rules may have an empty output string. - * Otherwise, an empty left or right hand side of any statement is a - * syntax error.

    - * - *

    Single quotes are used to quote any character other than a - * digit or letter. To specify a single quote itself, inside or - * outside of quotes, use two single quotes in a row. For example, - * the rule "'>'>o''clock" changes the - * string ">" to the string "o'clock". - *

    - * - *

    Notes

    - * - *

    While a RuleBasedTransliterator is being built, it checks that - * the rules are added in proper order. For example, if the rule - * "a>x" is followed by the rule "ab>y", - * then the second rule will throw an exception. The reason is that - * the second rule can never be triggered, since the first rule - * always matches anything it matches. In other words, the first - * rule masks the second rule.

    + * built from a set of rules as defined for + * Transliterator::createFromRules(). + * See the C++ class Transliterator documentation for the rule syntax. * * @author Alan Liu * @internal Use transliterator factory methods instead since this class will be removed in that release. diff --git a/deps/icu-small/source/i18n/rbt_pars.cpp b/deps/icu-small/source/i18n/rbt_pars.cpp index 8e49a8473a5ab0..e07cc8b63a408c 100644 --- a/deps/icu-small/source/i18n/rbt_pars.cpp +++ b/deps/icu-small/source/i18n/rbt_pars.cpp @@ -194,9 +194,9 @@ const UnicodeFunctor* ParseData::lookupMatcher(UChar32 ch) const { const UnicodeFunctor* set = NULL; int32_t i = ch - data->variablesBase; if (i >= 0 && i < variablesVector->size()) { - int32_t i = ch - data->variablesBase; - set = (i < variablesVector->size()) ? - (UnicodeFunctor*) variablesVector->elementAt(i) : 0; + int32_t j = ch - data->variablesBase; + set = (j < variablesVector->size()) ? + (UnicodeFunctor*) variablesVector->elementAt(j) : 0; } return set; } @@ -1108,8 +1108,8 @@ void TransliteratorParser::parseRules(const UnicodeString& rule, } data->variableNames.removeAll(); - int32_t pos = UHASH_FIRST; - const UHashElement* he = variableNames.nextElement(pos); + int32_t p = UHASH_FIRST; + const UHashElement* he = variableNames.nextElement(p); while (he != NULL) { UnicodeString* tempus = (UnicodeString*)(((UnicodeString*)(he->value.pointer))->clone()); if (tempus == NULL) { @@ -1118,7 +1118,7 @@ void TransliteratorParser::parseRules(const UnicodeString& rule, } data->variableNames.put(*((UnicodeString*)(he->key.pointer)), tempus, status); - he = variableNames.nextElement(pos); + he = variableNames.nextElement(p); } } variablesVector.removeAllElements(); // keeps them from getting deleted when we succeed diff --git a/deps/icu-small/source/i18n/regexcmp.cpp b/deps/icu-small/source/i18n/regexcmp.cpp index 410ff9513bb82a..0c5fca6f67b3f9 100644 --- a/deps/icu-small/source/i18n/regexcmp.cpp +++ b/deps/icu-small/source/i18n/regexcmp.cpp @@ -28,6 +28,7 @@ #include "patternprops.h" #include "putilimp.h" #include "cmemory.h" +#include "cstr.h" #include "cstring.h" #include "uvectr32.h" #include "uvectr64.h" @@ -3892,7 +3893,7 @@ void RegexCompile::stripNOPs() { // //------------------------------------------------------------------------------ void RegexCompile::error(UErrorCode e) { - if (U_SUCCESS(*fStatus)) { + if (U_SUCCESS(*fStatus) || e == U_MEMORY_ALLOCATION_ERROR) { *fStatus = e; // Hmm. fParseErr (UParseError) line & offset fields are int32_t in public // API (see common/unicode/parseerr.h), while fLineNum and fCharNum are @@ -4370,209 +4371,209 @@ static inline void addIdentifierIgnorable(UnicodeSet *set, UErrorCode& ec) { // Includes trying the Java "properties" that aren't supported as // normal ICU UnicodeSet properties // -static const UChar posSetPrefix[] = {0x5b, 0x5c, 0x70, 0x7b, 0}; // "[\p{" -static const UChar negSetPrefix[] = {0x5b, 0x5c, 0x50, 0x7b, 0}; // "[\P{" UnicodeSet *RegexCompile::createSetForProperty(const UnicodeString &propName, UBool negated) { - UnicodeString setExpr; - UnicodeSet *set; - uint32_t usetFlags = 0; if (U_FAILURE(*fStatus)) { - return NULL; + return nullptr; } + LocalPointer set; + UErrorCode status = U_ZERO_ERROR; - // - // First try the property as we received it - // - if (negated) { - setExpr.append(negSetPrefix, -1); - } else { - setExpr.append(posSetPrefix, -1); - } - setExpr.append(propName); - setExpr.append(chRBrace); - setExpr.append(chRBracket); - if (fModeFlags & UREGEX_CASE_INSENSITIVE) { - usetFlags |= USET_CASE_INSENSITIVE; - } - set = new UnicodeSet(setExpr, usetFlags, NULL, *fStatus); - if (U_SUCCESS(*fStatus)) { - return set; - } - delete set; - set = NULL; - - // - // The property as it was didn't work. - - // Do [:word:]. It is not recognized as a property by UnicodeSet. "word" not standard POSIX - // or standard Java, but many other regular expression packages do recognize it. - - if (propName.caseCompare(UNICODE_STRING_SIMPLE("word"), 0) == 0) { - *fStatus = U_ZERO_ERROR; - set = new UnicodeSet(*(fRXPat->fStaticSets[URX_ISWORD_SET])); - if (set == NULL) { - *fStatus = U_MEMORY_ALLOCATION_ERROR; - return set; + do { // non-loop, exists to allow breaks from the block. + // + // First try the property as we received it + // + UnicodeString setExpr; + uint32_t usetFlags = 0; + setExpr.append(u"[\\p{", -1); + setExpr.append(propName); + setExpr.append(u"}]", -1); + if (fModeFlags & UREGEX_CASE_INSENSITIVE) { + usetFlags |= USET_CASE_INSENSITIVE; } - if (negated) { - set->complement(); + set.adoptInsteadAndCheckErrorCode(new UnicodeSet(setExpr, usetFlags, NULL, status), status); + if (U_SUCCESS(status) || status == U_MEMORY_ALLOCATION_ERROR) { + break; } - return set; - } + // + // The incoming property wasn't directly recognized by ICU. - // Do Java fixes - - // InGreek -> InGreek or Coptic, that being the official Unicode name for that block. - // InCombiningMarksforSymbols -> InCombiningDiacriticalMarksforSymbols. - // - // Note on Spaces: either "InCombiningMarksForSymbols" or "InCombining Marks for Symbols" - // is accepted by Java. The property part of the name is compared - // case-insenstively. The spaces must be exactly as shown, either - // all there, or all omitted, with exactly one at each position - // if they are present. From checking against JDK 1.6 - // - // This code should be removed when ICU properties support the Java compatibility names - // (ICU 4.0?) - // - UnicodeString mPropName = propName; - if (mPropName.caseCompare(UNICODE_STRING_SIMPLE("InGreek"), 0) == 0) { - mPropName = UNICODE_STRING_SIMPLE("InGreek and Coptic"); - } - if (mPropName.caseCompare(UNICODE_STRING_SIMPLE("InCombining Marks for Symbols"), 0) == 0 || - mPropName.caseCompare(UNICODE_STRING_SIMPLE("InCombiningMarksforSymbols"), 0) == 0) { - mPropName = UNICODE_STRING_SIMPLE("InCombining Diacritical Marks for Symbols"); - } - else if (mPropName.compare(UNICODE_STRING_SIMPLE("all")) == 0) { - mPropName = UNICODE_STRING_SIMPLE("javaValidCodePoint"); - } + // Check [:word:] and [:all:]. These are not recognized as a properties by ICU UnicodeSet. + // Java accepts 'word' with mixed case. + // Java accepts 'all' only in all lower case. - // See if the property looks like a Java "InBlockName", which - // we will recast as "Block=BlockName" - // - if (mPropName.startsWith(u"In", 2) && propName.length()>=3) { - setExpr.truncate(4); // Leaves "[\p{", or "[\P{" - setExpr.append(u"Block=", -1); - setExpr.append(UnicodeString(mPropName, 2)); // Property with the leading "In" removed. - setExpr.append(chRBrace); - setExpr.append(chRBracket); - *fStatus = U_ZERO_ERROR; - set = new UnicodeSet(setExpr, usetFlags, NULL, *fStatus); - if (U_SUCCESS(*fStatus)) { - return set; + status = U_ZERO_ERROR; + if (propName.caseCompare(u"word", -1, 0) == 0) { + set.adoptInsteadAndCheckErrorCode(new UnicodeSet(*(fRXPat->fStaticSets[URX_ISWORD_SET])), status); + break; + } + if (propName.compare(u"all", -1) == 0) { + set.adoptInsteadAndCheckErrorCode(new UnicodeSet(0, 0x10ffff), status); + break; } - delete set; - set = NULL; - } - if (propName.startsWith(UNICODE_STRING_SIMPLE("java")) || - propName.compare(UNICODE_STRING_SIMPLE("all")) == 0) - { - UErrorCode localStatus = U_ZERO_ERROR; - //setExpr.remove(); - set = new UnicodeSet(); - // - // Try the various Java specific properties. - // These all begin with "java" + + // Do Java InBlock expressions // - if (mPropName.compare(UNICODE_STRING_SIMPLE("javaDefined")) == 0) { - addCategory(set, U_GC_CN_MASK, localStatus); - set->complement(); - } - else if (mPropName.compare(UNICODE_STRING_SIMPLE("javaDigit")) == 0) { - addCategory(set, U_GC_ND_MASK, localStatus); - } - else if (mPropName.compare(UNICODE_STRING_SIMPLE("javaIdentifierIgnorable")) == 0) { - addIdentifierIgnorable(set, localStatus); - } - else if (mPropName.compare(UNICODE_STRING_SIMPLE("javaISOControl")) == 0) { - set->add(0, 0x1F).add(0x7F, 0x9F); - } - else if (mPropName.compare(UNICODE_STRING_SIMPLE("javaJavaIdentifierPart")) == 0) { - addCategory(set, U_GC_L_MASK, localStatus); - addCategory(set, U_GC_SC_MASK, localStatus); - addCategory(set, U_GC_PC_MASK, localStatus); - addCategory(set, U_GC_ND_MASK, localStatus); - addCategory(set, U_GC_NL_MASK, localStatus); - addCategory(set, U_GC_MC_MASK, localStatus); - addCategory(set, U_GC_MN_MASK, localStatus); - addIdentifierIgnorable(set, localStatus); - } - else if (mPropName.compare(UNICODE_STRING_SIMPLE("javaJavaIdentifierStart")) == 0) { - addCategory(set, U_GC_L_MASK, localStatus); - addCategory(set, U_GC_NL_MASK, localStatus); - addCategory(set, U_GC_SC_MASK, localStatus); - addCategory(set, U_GC_PC_MASK, localStatus); - } - else if (mPropName.compare(UNICODE_STRING_SIMPLE("javaLetter")) == 0) { - addCategory(set, U_GC_L_MASK, localStatus); - } - else if (mPropName.compare(UNICODE_STRING_SIMPLE("javaLetterOrDigit")) == 0) { - addCategory(set, U_GC_L_MASK, localStatus); - addCategory(set, U_GC_ND_MASK, localStatus); - } - else if (mPropName.compare(UNICODE_STRING_SIMPLE("javaLowerCase")) == 0) { - addCategory(set, U_GC_LL_MASK, localStatus); - } - else if (mPropName.compare(UNICODE_STRING_SIMPLE("javaMirrored")) == 0) { - set->applyIntPropertyValue(UCHAR_BIDI_MIRRORED, 1, localStatus); - } - else if (mPropName.compare(UNICODE_STRING_SIMPLE("javaSpaceChar")) == 0) { - addCategory(set, U_GC_Z_MASK, localStatus); - } - else if (mPropName.compare(UNICODE_STRING_SIMPLE("javaSupplementaryCodePoint")) == 0) { - set->add(0x10000, UnicodeSet::MAX_VALUE); - } - else if (mPropName.compare(UNICODE_STRING_SIMPLE("javaTitleCase")) == 0) { - addCategory(set, U_GC_LT_MASK, localStatus); - } - else if (mPropName.compare(UNICODE_STRING_SIMPLE("javaUnicodeIdentifierStart")) == 0) { - addCategory(set, U_GC_L_MASK, localStatus); - addCategory(set, U_GC_NL_MASK, localStatus); - } - else if (mPropName.compare(UNICODE_STRING_SIMPLE("javaUnicodeIdentifierPart")) == 0) { - addCategory(set, U_GC_L_MASK, localStatus); - addCategory(set, U_GC_PC_MASK, localStatus); - addCategory(set, U_GC_ND_MASK, localStatus); - addCategory(set, U_GC_NL_MASK, localStatus); - addCategory(set, U_GC_MC_MASK, localStatus); - addCategory(set, U_GC_MN_MASK, localStatus); - addIdentifierIgnorable(set, localStatus); - } - else if (mPropName.compare(UNICODE_STRING_SIMPLE("javaUpperCase")) == 0) { - addCategory(set, U_GC_LU_MASK, localStatus); - } - else if (mPropName.compare(UNICODE_STRING_SIMPLE("javaValidCodePoint")) == 0) { - set->add(0, UnicodeSet::MAX_VALUE); - } - else if (mPropName.compare(UNICODE_STRING_SIMPLE("javaWhitespace")) == 0) { - addCategory(set, U_GC_Z_MASK, localStatus); - set->removeAll(UnicodeSet().add(0xa0).add(0x2007).add(0x202f)); - set->add(9, 0x0d).add(0x1c, 0x1f); - } - else if (mPropName.compare(UNICODE_STRING_SIMPLE("all")) == 0) { - set->add(0, UnicodeSet::MAX_VALUE); + UnicodeString mPropName = propName; + if (mPropName.startsWith(u"In", 2) && mPropName.length() >= 3) { + status = U_ZERO_ERROR; + set.adoptInsteadAndCheckErrorCode(new UnicodeSet(), status); + if (U_FAILURE(status)) { + break; + } + UnicodeString blockName(mPropName, 2); // Property with the leading "In" removed. + set->applyPropertyAlias(UnicodeString(u"Block"), blockName, status); + break; } - if (U_SUCCESS(localStatus) && !set->isEmpty()) { - *fStatus = U_ZERO_ERROR; - if (usetFlags & USET_CASE_INSENSITIVE) { + // Check for the Java form "IsBooleanPropertyValue", which we will recast + // as "BooleanPropertyValue". The property value can be either a + // a General Category or a Script Name. + + if (propName.startsWith(u"Is", 2) && propName.length()>=3) { + mPropName.remove(0, 2); // Strip the "Is" + if (mPropName.indexOf(u'=') >= 0) { + // Reject any "Is..." property expression containing an '=', that is, + // any non-binary property expression. + status = U_REGEX_PROPERTY_SYNTAX; + break; + } + + if (mPropName.caseCompare(u"assigned", -1, 0) == 0) { + mPropName.setTo(u"unassigned", -1); + negated = !negated; + } else if (mPropName.caseCompare(u"TitleCase", -1, 0) == 0) { + mPropName.setTo(u"Titlecase_Letter", -1); + } + + mPropName.insert(0, u"[\\p{", -1); + mPropName.append(u"}]", -1); + set.adoptInsteadAndCheckErrorCode(new UnicodeSet(mPropName, *fStatus), status); + + if (U_SUCCESS(status) && !set->isEmpty() && (usetFlags & USET_CASE_INSENSITIVE)) { set->closeOver(USET_CASE_INSENSITIVE); } - if (negated) { + break; + + } + + if (propName.startsWith(u"java", -1)) { + status = U_ZERO_ERROR; + set.adoptInsteadAndCheckErrorCode(new UnicodeSet(), status); + if (U_FAILURE(status)) { + break; + } + // + // Try the various Java specific properties. + // These all begin with "java" + // + if (propName.compare(u"javaDefined", -1) == 0) { + addCategory(set.getAlias(), U_GC_CN_MASK, status); set->complement(); } - return set; + else if (propName.compare(u"javaDigit", -1) == 0) { + addCategory(set.getAlias(), U_GC_ND_MASK, status); + } + else if (propName.compare(u"javaIdentifierIgnorable", -1) == 0) { + addIdentifierIgnorable(set.getAlias(), status); + } + else if (propName.compare(u"javaISOControl", -1) == 0) { + set->add(0, 0x1F).add(0x7F, 0x9F); + } + else if (propName.compare(u"javaJavaIdentifierPart", -1) == 0) { + addCategory(set.getAlias(), U_GC_L_MASK, status); + addCategory(set.getAlias(), U_GC_SC_MASK, status); + addCategory(set.getAlias(), U_GC_PC_MASK, status); + addCategory(set.getAlias(), U_GC_ND_MASK, status); + addCategory(set.getAlias(), U_GC_NL_MASK, status); + addCategory(set.getAlias(), U_GC_MC_MASK, status); + addCategory(set.getAlias(), U_GC_MN_MASK, status); + addIdentifierIgnorable(set.getAlias(), status); + } + else if (propName.compare(u"javaJavaIdentifierStart", -1) == 0) { + addCategory(set.getAlias(), U_GC_L_MASK, status); + addCategory(set.getAlias(), U_GC_NL_MASK, status); + addCategory(set.getAlias(), U_GC_SC_MASK, status); + addCategory(set.getAlias(), U_GC_PC_MASK, status); + } + else if (propName.compare(u"javaLetter", -1) == 0) { + addCategory(set.getAlias(), U_GC_L_MASK, status); + } + else if (propName.compare(u"javaLetterOrDigit", -1) == 0) { + addCategory(set.getAlias(), U_GC_L_MASK, status); + addCategory(set.getAlias(), U_GC_ND_MASK, status); + } + else if (propName.compare(u"javaLowerCase", -1) == 0) { + addCategory(set.getAlias(), U_GC_LL_MASK, status); + } + else if (propName.compare(u"javaMirrored", -1) == 0) { + set->applyIntPropertyValue(UCHAR_BIDI_MIRRORED, 1, status); + } + else if (propName.compare(u"javaSpaceChar", -1) == 0) { + addCategory(set.getAlias(), U_GC_Z_MASK, status); + } + else if (propName.compare(u"javaSupplementaryCodePoint", -1) == 0) { + set->add(0x10000, UnicodeSet::MAX_VALUE); + } + else if (propName.compare(u"javaTitleCase", -1) == 0) { + addCategory(set.getAlias(), U_GC_LT_MASK, status); + } + else if (propName.compare(u"javaUnicodeIdentifierStart", -1) == 0) { + addCategory(set.getAlias(), U_GC_L_MASK, status); + addCategory(set.getAlias(), U_GC_NL_MASK, status); + } + else if (propName.compare(u"javaUnicodeIdentifierPart", -1) == 0) { + addCategory(set.getAlias(), U_GC_L_MASK, status); + addCategory(set.getAlias(), U_GC_PC_MASK, status); + addCategory(set.getAlias(), U_GC_ND_MASK, status); + addCategory(set.getAlias(), U_GC_NL_MASK, status); + addCategory(set.getAlias(), U_GC_MC_MASK, status); + addCategory(set.getAlias(), U_GC_MN_MASK, status); + addIdentifierIgnorable(set.getAlias(), status); + } + else if (propName.compare(u"javaUpperCase", -1) == 0) { + addCategory(set.getAlias(), U_GC_LU_MASK, status); + } + else if (propName.compare(u"javaValidCodePoint", -1) == 0) { + set->add(0, UnicodeSet::MAX_VALUE); + } + else if (propName.compare(u"javaWhitespace", -1) == 0) { + addCategory(set.getAlias(), U_GC_Z_MASK, status); + set->removeAll(UnicodeSet().add(0xa0).add(0x2007).add(0x202f)); + set->add(9, 0x0d).add(0x1c, 0x1f); + } else { + status = U_REGEX_PROPERTY_SYNTAX; + } + + if (U_SUCCESS(status) && !set->isEmpty() && (usetFlags & USET_CASE_INSENSITIVE)) { + set->closeOver(USET_CASE_INSENSITIVE); + } + break; + } + + // Unrecognized property. ICU didn't like it as it was, and none of the Java compatibility + // extensions matched it. + status = U_REGEX_PROPERTY_SYNTAX; + } while (false); // End of do loop block. Code above breaks out of the block on success or hard failure. + + if (U_SUCCESS(status)) { + U_ASSERT(set.isValid()); + if (negated) { + set->complement(); } - delete set; - set = NULL; + return set.orphan(); + } else { + if (status == U_ILLEGAL_ARGUMENT_ERROR) { + status = U_REGEX_PROPERTY_SYNTAX; + } + error(status); + return nullptr; } - error(*fStatus); - return NULL; } - // // SetEval Part of the evaluation of [set expressions]. // Perform any pending (stacked) operations with precedence diff --git a/deps/icu-small/source/i18n/region.cpp b/deps/icu-small/source/i18n/region.cpp index 66f9ef35ded9ee..f182f61486e6d3 100644 --- a/deps/icu-small/source/i18n/region.cpp +++ b/deps/icu-small/source/i18n/region.cpp @@ -168,10 +168,18 @@ void U_CALLCONV Region::loadRegionData(UErrorCode &status) { continents->addElement(continentName,status); } + UResourceBundle *groupingBundle = nullptr; while ( ures_hasNext(groupingContainment.getAlias()) ) { - UnicodeString *groupingName = new UnicodeString(ures_getNextUnicodeString(groupingContainment.getAlias(),NULL,&status)); - groupings->addElement(groupingName,status); + groupingBundle = ures_getNextResource(groupingContainment.getAlias(), groupingBundle, &status); + if (U_FAILURE(status)) { + break; + } + UnicodeString *groupingName = new UnicodeString(ures_getKey(groupingBundle), -1, US_INV); + if (groupingName) { + groupings->addElement(groupingName,status); + } } + ures_close(groupingBundle); for ( int32_t i = 0 ; i < allRegions->size() ; i++ ) { LocalPointer r(new Region(), status); @@ -182,7 +190,7 @@ void U_CALLCONV Region::loadRegionData(UErrorCode &status) { r->idStr = *regionName; r->idStr.extract(0,r->idStr.length(),r->id,sizeof(r->id),US_INV); - r->type = URGN_TERRITORY; // Only temporary - figure out the real type later once the aliases are known. + r->fType = URGN_TERRITORY; // Only temporary - figure out the real type later once the aliases are known. Formattable result; UErrorCode ps = U_ZERO_ERROR; @@ -190,7 +198,7 @@ void U_CALLCONV Region::loadRegionData(UErrorCode &status) { if ( U_SUCCESS(ps) ) { r->code = result.getLong(); // Convert string to number uhash_iput(newNumericCodeMap.getAlias(),r->code,(void *)(r.getAlias()),&status); - r->type = URGN_SUBCONTINENT; + r->fType = URGN_SUBCONTINENT; } else { r->code = -1; } @@ -231,9 +239,9 @@ void U_CALLCONV Region::loadRegionData(UErrorCode &status) { } else { aliasFromRegion->code = -1; } - aliasFromRegion->type = URGN_DEPRECATED; + aliasFromRegion->fType = URGN_DEPRECATED; } else { - aliasFromRegion->type = URGN_DEPRECATED; + aliasFromRegion->fType = URGN_DEPRECATED; } { @@ -290,26 +298,26 @@ void U_CALLCONV Region::loadRegionData(UErrorCode &status) { UnicodeString WORLD_ID_STRING(WORLD_ID); r = (Region *) uhash_get(newRegionIDMap.getAlias(),(void *)&WORLD_ID_STRING); if ( r ) { - r->type = URGN_WORLD; + r->fType = URGN_WORLD; } UnicodeString UNKNOWN_REGION_ID_STRING(UNKNOWN_REGION_ID); r = (Region *) uhash_get(newRegionIDMap.getAlias(),(void *)&UNKNOWN_REGION_ID_STRING); if ( r ) { - r->type = URGN_UNKNOWN; + r->fType = URGN_UNKNOWN; } for ( int32_t i = 0 ; i < continents->size() ; i++ ) { r = (Region *) uhash_get(newRegionIDMap.getAlias(),(void *)continents->elementAt(i)); if ( r ) { - r->type = URGN_CONTINENT; + r->fType = URGN_CONTINENT; } } for ( int32_t i = 0 ; i < groupings->size() ; i++ ) { r = (Region *) uhash_get(newRegionIDMap.getAlias(),(void *)groupings->elementAt(i)); if ( r ) { - r->type = URGN_GROUPING; + r->fType = URGN_GROUPING; } } @@ -319,7 +327,7 @@ void U_CALLCONV Region::loadRegionData(UErrorCode &status) { UnicodeString OUTLYING_OCEANIA_REGION_ID_STRING(OUTLYING_OCEANIA_REGION_ID); r = (Region *) uhash_get(newRegionIDMap.getAlias(),(void *)&OUTLYING_OCEANIA_REGION_ID_STRING); if ( r ) { - r->type = URGN_SUBCONTINENT; + r->fType = URGN_SUBCONTINENT; } // Load territory containment info from the supplemental data. @@ -356,7 +364,7 @@ void U_CALLCONV Region::loadRegionData(UErrorCode &status) { // Set the parent region to be the containing region of the child. // Regions of type GROUPING can't be set as the parent, since another region // such as a SUBCONTINENT, CONTINENT, or WORLD must always be the parent. - if ( parentRegion->type != URGN_GROUPING) { + if ( parentRegion->fType != URGN_GROUPING) { childRegion->containingRegion = parentRegion; } } @@ -367,15 +375,15 @@ void U_CALLCONV Region::loadRegionData(UErrorCode &status) { int32_t pos = UHASH_FIRST; while ( const UHashElement* element = uhash_nextElement(newRegionIDMap.getAlias(),&pos)) { Region *ar = (Region *)element->value.pointer; - if ( availableRegions[ar->type] == NULL ) { + if ( availableRegions[ar->fType] == NULL ) { LocalPointer newAr(new UVector(uprv_deleteUObject, uhash_compareUnicodeString, status), status); - availableRegions[ar->type] = newAr.orphan(); + availableRegions[ar->fType] = newAr.orphan(); } LocalPointer arString(new UnicodeString(ar->idStr), status); if( U_FAILURE(status) ) { return; // error out } - availableRegions[ar->type]->addElement((void *)arString.orphan(),status); + availableRegions[ar->fType]->addElement((void *)arString.orphan(),status); } ucln_i18n_registerCleanup(UCLN_I18N_REGION, region_cleanup); @@ -416,7 +424,7 @@ void Region::cleanupRegionData() { Region::Region () : code(-1), - type(URGN_UNKNOWN), + fType(URGN_UNKNOWN), containingRegion(NULL), containedRegions(NULL), preferredValues(NULL) { @@ -481,7 +489,7 @@ Region::getInstance(const char *region_code, UErrorCode &status) { return NULL; } - if ( r->type == URGN_DEPRECATED && r->preferredValues->size() == 1) { + if ( r->fType == URGN_DEPRECATED && r->preferredValues->size() == 1) { StringEnumeration *pv = r->getPreferredValues(status); pv->reset(status); const UnicodeString *ustr = pv->snext(status); @@ -529,7 +537,7 @@ Region::getInstance (int32_t code, UErrorCode &status) { return NULL; } - if ( r->type == URGN_DEPRECATED && r->preferredValues->size() == 1) { + if ( r->fType == URGN_DEPRECATED && r->preferredValues->size() == 1) { StringEnumeration *pv = r->getPreferredValues(status); pv->reset(status); const UnicodeString *ustr = pv->snext(status); @@ -580,7 +588,7 @@ Region::getContainingRegion(URegionType type) const { return NULL; } - return ( containingRegion->type == type )? containingRegion: containingRegion->getContainingRegion(type); + return ( containingRegion->fType == type)? containingRegion: containingRegion->getContainingRegion(type); } /** @@ -618,9 +626,9 @@ Region::getContainedRegions( URegionType type, UErrorCode &status ) const { StringEnumeration *cr = getContainedRegions(status); for ( int32_t i = 0 ; i < cr->count(status) ; i++ ) { - const char *id = cr->next(NULL,status); - const Region *r = Region::getInstance(id,status); - if ( r->getType() == type ) { + const char *regionId = cr->next(NULL,status); + const Region *r = Region::getInstance(regionId,status); + if ( r->getType() == type) { result->addElement((void *)&r->idStr,status); } else { StringEnumeration *children = r->getContainedRegions(type, status); @@ -672,7 +680,7 @@ Region::contains(const Region &other) const { StringEnumeration* Region::getPreferredValues(UErrorCode &status) const { umtx_initOnce(gRegionDataInitOnce, &loadRegionData, status); // returns immediately if U_FAILURE(status) - if (U_FAILURE(status) || type != URGN_DEPRECATED) { + if (U_FAILURE(status) || fType != URGN_DEPRECATED) { return NULL; } return new RegionNameEnumeration(preferredValues,status); @@ -697,7 +705,7 @@ Region::getNumericCode() const { */ URegionType Region::getType() const { - return type; + return fType; } RegionNameEnumeration::RegionNameEnumeration(UVector *fNameList, UErrorCode& status) { diff --git a/deps/icu-small/source/i18n/reldatefmt.cpp b/deps/icu-small/source/i18n/reldatefmt.cpp index 42ede7ae4d9903..ae251ed20b46a3 100644 --- a/deps/icu-small/source/i18n/reldatefmt.cpp +++ b/deps/icu-small/source/i18n/reldatefmt.cpp @@ -51,13 +51,13 @@ U_NAMESPACE_BEGIN // RelativeDateTimeFormatter specific data for a single locale class RelativeDateTimeCacheData: public SharedObject { public: - RelativeDateTimeCacheData() : combinedDateAndTime(NULL) { + RelativeDateTimeCacheData() : combinedDateAndTime(nullptr) { // Initialize the cache arrays for (int32_t style = 0; style < UDAT_STYLE_COUNT; ++style) { - for (int32_t relUnit = 0; relUnit < UDAT_RELATIVE_UNIT_COUNT; ++relUnit) { + for (int32_t relUnit = 0; relUnit < UDAT_REL_UNIT_COUNT; ++relUnit) { for (int32_t pl = 0; pl < StandardPlural::COUNT; ++pl) { - relativeUnitsFormatters[style][relUnit][0][pl] = NULL; - relativeUnitsFormatters[style][relUnit][1][pl] = NULL; + relativeUnitsFormatters[style][relUnit][0][pl] = nullptr; + relativeUnitsFormatters[style][relUnit][1][pl] = nullptr; } } } @@ -74,7 +74,7 @@ class RelativeDateTimeCacheData: public SharedObject { // e.g., Next Tuesday; Yesterday; etc. For third index, 0 // means past, e.g., 5 days ago; 1 means future, e.g., in 5 days. SimpleFormatter *relativeUnitsFormatters[UDAT_STYLE_COUNT] - [UDAT_RELATIVE_UNIT_COUNT][2][StandardPlural::COUNT]; + [UDAT_REL_UNIT_COUNT][2][StandardPlural::COUNT]; const UnicodeString& getAbsoluteUnitString(int32_t fStyle, UDateAbsoluteUnit unit, @@ -83,6 +83,10 @@ class RelativeDateTimeCacheData: public SharedObject { UDateRelativeUnit unit, int32_t pastFutureIndex, int32_t pluralUnit) const; + const SimpleFormatter* getRelativeDateTimeUnitFormatter(int32_t fStyle, + URelativeDateTimeUnit unit, + int32_t pastFutureIndex, + int32_t pluralUnit) const; const UnicodeString emptyString; @@ -107,7 +111,7 @@ class RelativeDateTimeCacheData: public SharedObject { RelativeDateTimeCacheData::~RelativeDateTimeCacheData() { // clear out the cache arrays for (int32_t style = 0; style < UDAT_STYLE_COUNT; ++style) { - for (int32_t relUnit = 0; relUnit < UDAT_RELATIVE_UNIT_COUNT; ++relUnit) { + for (int32_t relUnit = 0; relUnit < UDAT_REL_UNIT_COUNT; ++relUnit) { for (int32_t pl = 0; pl < StandardPlural::COUNT; ++pl) { delete relativeUnitsFormatters[style][relUnit][0][pl]; delete relativeUnitsFormatters[style][relUnit][1][pl]; @@ -131,20 +135,41 @@ const UnicodeString& RelativeDateTimeCacheData::getAbsoluteUnitString( return emptyString; } - // Use fallback cache for SimpleFormatter relativeUnits. const SimpleFormatter* RelativeDateTimeCacheData::getRelativeUnitFormatter( int32_t fStyle, UDateRelativeUnit unit, int32_t pastFutureIndex, int32_t pluralUnit) const { + URelativeDateTimeUnit rdtunit = UDAT_REL_UNIT_COUNT; + switch (unit) { + case UDAT_RELATIVE_YEARS: rdtunit = UDAT_REL_UNIT_YEAR; break; + case UDAT_RELATIVE_MONTHS: rdtunit = UDAT_REL_UNIT_MONTH; break; + case UDAT_RELATIVE_WEEKS: rdtunit = UDAT_REL_UNIT_WEEK; break; + case UDAT_RELATIVE_DAYS: rdtunit = UDAT_REL_UNIT_DAY; break; + case UDAT_RELATIVE_HOURS: rdtunit = UDAT_REL_UNIT_HOUR; break; + case UDAT_RELATIVE_MINUTES: rdtunit = UDAT_REL_UNIT_MINUTE; break; + case UDAT_RELATIVE_SECONDS: rdtunit = UDAT_REL_UNIT_SECOND; break; + default: // a unit that the above method does not handle + return nullptr; + } + + return getRelativeDateTimeUnitFormatter(fStyle, rdtunit, pastFutureIndex, pluralUnit); + } + + // Use fallback cache for SimpleFormatter relativeUnits. + const SimpleFormatter* RelativeDateTimeCacheData::getRelativeDateTimeUnitFormatter( + int32_t fStyle, + URelativeDateTimeUnit unit, + int32_t pastFutureIndex, + int32_t pluralUnit) const { int32_t style = fStyle; do { - if (relativeUnitsFormatters[style][unit][pastFutureIndex][pluralUnit] != NULL) { + if (relativeUnitsFormatters[style][unit][pastFutureIndex][pluralUnit] != nullptr) { return relativeUnitsFormatters[style][unit][pastFutureIndex][pluralUnit]; } style = fallBackCache[style]; } while (style != -1); - return NULL; // No formatter found. + return nullptr; // No formatter found. } static UBool getStringWithFallback( @@ -217,23 +242,35 @@ struct RelDateTimeFmtDataSink : public ResourceSink { // Converts the generic units to UDAT_RELATIVE version. switch (genUnit) { case SECOND: - return UDAT_RELATIVE_SECONDS; + return UDAT_REL_UNIT_SECOND; case MINUTE: - return UDAT_RELATIVE_MINUTES; + return UDAT_REL_UNIT_MINUTE; case HOUR: - return UDAT_RELATIVE_HOURS; + return UDAT_REL_UNIT_HOUR; case DAY: - return UDAT_RELATIVE_DAYS; + return UDAT_REL_UNIT_DAY; case WEEK: - return UDAT_RELATIVE_WEEKS; + return UDAT_REL_UNIT_WEEK; case MONTH: - return UDAT_RELATIVE_MONTHS; - /* - * case QUARTER: - * return UDATE_RELATIVE_QUARTERS; - */ + return UDAT_REL_UNIT_MONTH; + case QUARTER: + return UDAT_REL_UNIT_QUARTER; case YEAR: - return UDAT_RELATIVE_YEARS; + return UDAT_REL_UNIT_YEAR; + case SUNDAY: + return UDAT_REL_UNIT_SUNDAY; + case MONDAY: + return UDAT_REL_UNIT_MONDAY; + case TUESDAY: + return UDAT_REL_UNIT_TUESDAY; + case WEDNESDAY: + return UDAT_REL_UNIT_WEDNESDAY; + case THURSDAY: + return UDAT_REL_UNIT_THURSDAY; + case FRIDAY: + return UDAT_REL_UNIT_FRIDAY; + case SATURDAY: + return UDAT_REL_UNIT_SATURDAY; default: return -1; } @@ -248,10 +285,8 @@ struct RelDateTimeFmtDataSink : public ResourceSink { return UDAT_ABSOLUTE_WEEK; case MONTH: return UDAT_ABSOLUTE_MONTH; - /* TODO: Add in QUARTER - * case QUARTER: - * return UDAT_ABSOLUTE_QUARTER; - */ + case QUARTER: + return UDAT_ABSOLUTE_QUARTER; case YEAR: return UDAT_ABSOLUTE_YEAR; case SUNDAY: @@ -312,7 +347,7 @@ struct RelDateTimeFmtDataSink : public ResourceSink { // Utility functions static UDateRelativeDateTimeFormatterStyle styleFromString(const char *s) { - int32_t len = uprv_strlen(s); + int32_t len = static_cast(uprv_strlen(s)); if (len >= 7 && uprv_strcmp(s + len - 7, "-narrow") == 0) { return UDAT_STYLE_NARROW; } @@ -430,7 +465,7 @@ struct RelDateTimeFmtDataSink : public ResourceSink { } int32_t relUnitIndex = relUnitFromGeneric(genericUnit); - if (relUnitIndex == UDAT_RELATIVE_SECONDS && uprv_strcmp(key, "0") == 0 && + if (relUnitIndex == UDAT_REL_UNIT_SECOND && uprv_strcmp(key, "0") == 0 && outputData.absoluteUnits[style][UDAT_ABSOLUTE_NOW][UDAT_DIRECTION_PLAIN].isEmpty()) { // Handle "NOW" outputData.absoluteUnits[style][UDAT_ABSOLUTE_NOW] @@ -463,10 +498,10 @@ struct RelDateTimeFmtDataSink : public ResourceSink { outputData.relativeUnitsFormatters[style][relUnitIndex] [pastFutureIndex]; // Only set if not already established. - if (patterns[pluralIndex] == NULL) { + if (patterns[pluralIndex] == nullptr) { patterns[pluralIndex] = new SimpleFormatter( value.getUnicodeString(errorCode), 0, 1, errorCode); - if (patterns[pluralIndex] == NULL) { + if (patterns[pluralIndex] == nullptr) { errorCode = U_MEMORY_ALLOCATION_ERROR; } } @@ -546,7 +581,7 @@ struct RelDateTimeFmtDataSink : public ResourceSink { consumeAlias(key, value, errorCode); } else { style = styleFromString(key); - int32_t unitSize = uprv_strlen(key) - styleSuffixLength(style); + int32_t unitSize = static_cast(uprv_strlen(key)) - styleSuffixLength(style); genericUnit = unitOrNegativeFromString(key, unitSize); if (style >= 0 && genericUnit != INVALID_UNIT) { consumeTimeUnit(key, value, errorCode); @@ -570,8 +605,14 @@ static void loadWeekdayNames(UnicodeString absoluteUnits[UDAT_STYLE_COUNT] [UDAT_ABSOLUTE_UNIT_COUNT][UDAT_DIRECTION_COUNT], const char* localeId, UErrorCode& status) { + if (U_FAILURE(status)) { + return; + } Locale locale(localeId); DateFormatSymbols dfSym(locale, status); + if (U_FAILURE(status)) { + return; + } for (int32_t style = 0; style < UDAT_STYLE_COUNT; ++style) { DateFormatSymbols::DtWidthType dtfmtWidth = styleToDateFormatSymbolWidth[style]; int32_t count; @@ -595,6 +636,9 @@ static UBool loadUnitData( RelDateTimeFmtDataSink sink(cacheData); ures_getAllItemsWithFallback(resource, "fields", sink, status); + if (U_FAILURE(status)) { + return false; + } // Get the weekday names from DateFormatSymbols. loadWeekdayNames(cacheData.absoluteUnits, localeId, status); @@ -619,7 +663,7 @@ static UBool getDateTimePattern( .append("/DateTimePatterns", status); LocalUResourceBundlePointer topLevel( ures_getByKeyWithFallback( - resource, pathBuffer.data(), NULL, &status)); + resource, pathBuffer.data(), nullptr, &status)); if (U_FAILURE(status)) { return FALSE; } @@ -636,68 +680,68 @@ static UBool getDateTimePattern( template<> U_I18N_API const RelativeDateTimeCacheData *LocaleCacheKey::createObject(const void * /*unused*/, UErrorCode &status) const { const char *localeId = fLoc.getName(); - LocalUResourceBundlePointer topLevel(ures_open(NULL, localeId, &status)); + LocalUResourceBundlePointer topLevel(ures_open(nullptr, localeId, &status)); if (U_FAILURE(status)) { - return NULL; + return nullptr; } LocalPointer result( new RelativeDateTimeCacheData()); if (result.isNull()) { status = U_MEMORY_ALLOCATION_ERROR; - return NULL; + return nullptr; } if (!loadUnitData( topLevel.getAlias(), *result, localeId, status)) { - return NULL; + return nullptr; } UnicodeString dateTimePattern; if (!getDateTimePattern(topLevel.getAlias(), dateTimePattern, status)) { - return NULL; + return nullptr; } result->adoptCombinedDateAndTime( new SimpleFormatter(dateTimePattern, 2, 2, status)); if (U_FAILURE(status)) { - return NULL; + return nullptr; } result->addRef(); return result.orphan(); } RelativeDateTimeFormatter::RelativeDateTimeFormatter(UErrorCode& status) : - fCache(NULL), - fNumberFormat(NULL), - fPluralRules(NULL), + fCache(nullptr), + fNumberFormat(nullptr), + fPluralRules(nullptr), fStyle(UDAT_STYLE_LONG), fContext(UDISPCTX_CAPITALIZATION_NONE), - fOptBreakIterator(NULL) { - init(NULL, NULL, status); + fOptBreakIterator(nullptr) { + init(nullptr, nullptr, status); } RelativeDateTimeFormatter::RelativeDateTimeFormatter( const Locale& locale, UErrorCode& status) : - fCache(NULL), - fNumberFormat(NULL), - fPluralRules(NULL), + fCache(nullptr), + fNumberFormat(nullptr), + fPluralRules(nullptr), fStyle(UDAT_STYLE_LONG), fContext(UDISPCTX_CAPITALIZATION_NONE), - fOptBreakIterator(NULL), + fOptBreakIterator(nullptr), fLocale(locale) { - init(NULL, NULL, status); + init(nullptr, nullptr, status); } RelativeDateTimeFormatter::RelativeDateTimeFormatter( const Locale& locale, NumberFormat *nfToAdopt, UErrorCode& status) : - fCache(NULL), - fNumberFormat(NULL), - fPluralRules(NULL), + fCache(nullptr), + fNumberFormat(nullptr), + fPluralRules(nullptr), fStyle(UDAT_STYLE_LONG), fContext(UDISPCTX_CAPITALIZATION_NONE), - fOptBreakIterator(NULL), + fOptBreakIterator(nullptr), fLocale(locale) { - init(nfToAdopt, NULL, status); + init(nfToAdopt, nullptr, status); } RelativeDateTimeFormatter::RelativeDateTimeFormatter( @@ -706,12 +750,12 @@ RelativeDateTimeFormatter::RelativeDateTimeFormatter( UDateRelativeDateTimeFormatterStyle styl, UDisplayContext capitalizationContext, UErrorCode& status) : - fCache(NULL), - fNumberFormat(NULL), - fPluralRules(NULL), + fCache(nullptr), + fNumberFormat(nullptr), + fPluralRules(nullptr), fStyle(styl), fContext(capitalizationContext), - fOptBreakIterator(NULL), + fOptBreakIterator(nullptr), fLocale(locale) { if (U_FAILURE(status)) { return; @@ -727,7 +771,7 @@ RelativeDateTimeFormatter::RelativeDateTimeFormatter( } init(nfToAdopt, bi, status); } else { - init(nfToAdopt, NULL, status); + init(nfToAdopt, nullptr, status); } } @@ -744,7 +788,7 @@ RelativeDateTimeFormatter::RelativeDateTimeFormatter( fCache->addRef(); fNumberFormat->addRef(); fPluralRules->addRef(); - if (fOptBreakIterator != NULL) { + if (fOptBreakIterator != nullptr) { fOptBreakIterator->addRef(); } } @@ -764,16 +808,16 @@ RelativeDateTimeFormatter& RelativeDateTimeFormatter::operator=( } RelativeDateTimeFormatter::~RelativeDateTimeFormatter() { - if (fCache != NULL) { + if (fCache != nullptr) { fCache->removeRef(); } - if (fNumberFormat != NULL) { + if (fNumberFormat != nullptr) { fNumberFormat->removeRef(); } - if (fPluralRules != NULL) { + if (fPluralRules != nullptr) { fPluralRules->removeRef(); } - if (fOptBreakIterator != NULL) { + if (fOptBreakIterator != nullptr) { fOptBreakIterator->removeRef(); } } @@ -812,7 +856,7 @@ UnicodeString& RelativeDateTimeFormatter::format( const SimpleFormatter* formatter = fCache->getRelativeUnitFormatter(fStyle, unit, bFuture, pluralIndex); - if (formatter == NULL) { + if (formatter == nullptr) { // TODO: WARN - look at quantity formatter's action with an error. status = U_INVALID_FORMAT_ERROR; return appendTo; @@ -828,33 +872,35 @@ UnicodeString& RelativeDateTimeFormatter::formatNumeric( if (U_FAILURE(status)) { return appendTo; } - // TODO: - // The full implementation of this depends on CLDR data that is not yet available, - // see: http://unicode.org/cldr/trac/ticket/9165 Add more relative field data. - // In the meantime do a quick bring-up by calling the old format method; this - // leaves some holes (even for data that is currently available, such as quarter). - // When the new CLDR data is available, update the data storage accordingly, - // rewrite this to use it directly, and rewrite the old format method to call this - // new one; that is covered by http://bugs.icu-project.org/trac/ticket/12171. - UDateRelativeUnit relunit = UDAT_RELATIVE_UNIT_COUNT; - switch (unit) { - case UDAT_REL_UNIT_YEAR: relunit = UDAT_RELATIVE_YEARS; break; - case UDAT_REL_UNIT_MONTH: relunit = UDAT_RELATIVE_MONTHS; break; - case UDAT_REL_UNIT_WEEK: relunit = UDAT_RELATIVE_WEEKS; break; - case UDAT_REL_UNIT_DAY: relunit = UDAT_RELATIVE_DAYS; break; - case UDAT_REL_UNIT_HOUR: relunit = UDAT_RELATIVE_HOURS; break; - case UDAT_REL_UNIT_MINUTE: relunit = UDAT_RELATIVE_MINUTES; break; - case UDAT_REL_UNIT_SECOND: relunit = UDAT_RELATIVE_SECONDS; break; - default: // a unit that the above method does not handle - status = U_UNSUPPORTED_ERROR; - return appendTo; - } UDateDirection direction = UDAT_DIRECTION_NEXT; if (std::signbit(offset)) { // needed to handle -0.0 direction = UDAT_DIRECTION_LAST; offset = -offset; } - return format(offset, direction, relunit, appendTo, status); + if (direction != UDAT_DIRECTION_LAST && direction != UDAT_DIRECTION_NEXT) { + status = U_ILLEGAL_ARGUMENT_ERROR; + return appendTo; + } + int32_t bFuture = direction == UDAT_DIRECTION_NEXT ? 1 : 0; + FieldPosition pos(FieldPosition::DONT_CARE); + + UnicodeString result; + UnicodeString formattedNumber; + + StandardPlural::Form pluralIndex = QuantityFormatter::selectPlural( + offset, **fNumberFormat, **fPluralRules, formattedNumber, pos, + status); + + const SimpleFormatter* formatter = + fCache->getRelativeDateTimeUnitFormatter(fStyle, unit, bFuture, pluralIndex); + if (formatter == nullptr) { + // TODO: WARN - look at quantity formatter's action with an error. + status = U_INVALID_FORMAT_ERROR; + return appendTo; + } + formatter->format(formattedNumber, result, status); + adjustForContext(result); + return appendTo.append(result); } UnicodeString& RelativeDateTimeFormatter::format( @@ -871,7 +917,7 @@ UnicodeString& RelativeDateTimeFormatter::format( // Get string using fallback. UnicodeString result; result.fastCopyFrom(fCache->getAbsoluteUnitString(fStyle, unit, direction)); - if (fOptBreakIterator != NULL) { + if (fOptBreakIterator != nullptr) { adjustForContext(result); } return appendTo.append(result); @@ -908,6 +954,7 @@ UnicodeString& RelativeDateTimeFormatter::format( UDateAbsoluteUnit absunit = UDAT_ABSOLUTE_UNIT_COUNT; switch (unit) { case UDAT_REL_UNIT_YEAR: absunit = UDAT_ABSOLUTE_YEAR; break; + case UDAT_REL_UNIT_QUARTER: absunit = UDAT_ABSOLUTE_QUARTER; break; case UDAT_REL_UNIT_MONTH: absunit = UDAT_ABSOLUTE_MONTH; break; case UDAT_REL_UNIT_WEEK: absunit = UDAT_ABSOLUTE_WEEK; break; case UDAT_REL_UNIT_DAY: absunit = UDAT_ABSOLUTE_DAY; break; @@ -930,7 +977,7 @@ UnicodeString& RelativeDateTimeFormatter::format( const UnicodeString &unitFormatString = fCache->getAbsoluteUnitString(fStyle, absunit, direction); if (!unitFormatString.isEmpty()) { - if (fOptBreakIterator != NULL) { + if (fOptBreakIterator != nullptr) { UnicodeString result(unitFormatString); adjustForContext(result); return appendTo.append(result); @@ -951,7 +998,7 @@ UnicodeString& RelativeDateTimeFormatter::combineDateAndTime( } void RelativeDateTimeFormatter::adjustForContext(UnicodeString &str) const { - if (fOptBreakIterator == NULL + if (fOptBreakIterator == nullptr || str.length() == 0 || !u_islower(str.char32At(0))) { return; } @@ -992,7 +1039,7 @@ void RelativeDateTimeFormatter::init( shared->removeRef(); } else { SharedNumberFormat *shared = new SharedNumberFormat(nf.getAlias()); - if (shared == NULL) { + if (shared == nullptr) { status = U_MEMORY_ALLOCATION_ERROR; return; } @@ -1003,7 +1050,7 @@ void RelativeDateTimeFormatter::init( SharedObject::clearPtr(fOptBreakIterator); } else { SharedBreakIterator *shared = new SharedBreakIterator(bi.getAlias()); - if (shared == NULL) { + if (shared == nullptr) { status = U_MEMORY_ALLOCATION_ERROR; return; } @@ -1026,13 +1073,13 @@ ureldatefmt_open( const char* locale, UErrorCode* status ) { if (U_FAILURE(*status)) { - return NULL; + return nullptr; } LocalPointer formatter(new RelativeDateTimeFormatter(Locale(locale), (NumberFormat*)nfToAdopt, width, capitalizationContext, *status), *status); if (U_FAILURE(*status)) { - return NULL; + return nullptr; } return (URelativeDateTimeFormatter*)formatter.orphan(); } @@ -1054,13 +1101,13 @@ ureldatefmt_formatNumeric( const URelativeDateTimeFormatter* reldatefmt, if (U_FAILURE(*status)) { return 0; } - if (result == NULL ? resultCapacity != 0 : resultCapacity < 0) { + if (result == nullptr ? resultCapacity != 0 : resultCapacity < 0) { *status = U_ILLEGAL_ARGUMENT_ERROR; return 0; } UnicodeString res; - if (result != NULL) { - // NULL destination for pure preflighting: empty dummy string + if (result != nullptr) { + // nullptr destination for pure preflighting: empty dummy string // otherwise, alias the destination buffer (copied from udat_format) res.setTo(result, 0, resultCapacity); } @@ -1082,13 +1129,13 @@ ureldatefmt_format( const URelativeDateTimeFormatter* reldatefmt, if (U_FAILURE(*status)) { return 0; } - if (result == NULL ? resultCapacity != 0 : resultCapacity < 0) { + if (result == nullptr ? resultCapacity != 0 : resultCapacity < 0) { *status = U_ILLEGAL_ARGUMENT_ERROR; return 0; } UnicodeString res; - if (result != NULL) { - // NULL destination for pure preflighting: empty dummy string + if (result != nullptr) { + // nullptr destination for pure preflighting: empty dummy string // otherwise, alias the destination buffer (copied from udat_format) res.setTo(result, 0, resultCapacity); } @@ -1112,9 +1159,9 @@ ureldatefmt_combineDateAndTime( const URelativeDateTimeFormatter* reldatefmt, if (U_FAILURE(*status)) { return 0; } - if (result == NULL ? resultCapacity != 0 : resultCapacity < 0 || - (relativeDateString == NULL ? relativeDateStringLen != 0 : relativeDateStringLen < -1) || - (timeString == NULL ? timeStringLen != 0 : timeStringLen < -1)) { + if (result == nullptr ? resultCapacity != 0 : resultCapacity < 0 || + (relativeDateString == nullptr ? relativeDateStringLen != 0 : relativeDateStringLen < -1) || + (timeString == nullptr ? timeStringLen != 0 : timeStringLen < -1)) { *status = U_ILLEGAL_ARGUMENT_ERROR; return 0; } diff --git a/deps/icu-small/source/i18n/reldtfmt.cpp b/deps/icu-small/source/i18n/reldtfmt.cpp index d3ab45dc631ba0..753672d905f16b 100644 --- a/deps/icu-small/source/i18n/reldtfmt.cpp +++ b/deps/icu-small/source/i18n/reldtfmt.cpp @@ -430,7 +430,7 @@ RelativeDateFormat::setContext(UDisplayContext value, UErrorCode& status) if ( fCapitalizationBrkIter == NULL && (value==UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE || (value==UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU && fCapitalizationOfRelativeUnitsForUIListMenu) || (value==UDISPCTX_CAPITALIZATION_FOR_STANDALONE && fCapitalizationOfRelativeUnitsForStandAlone)) ) { - UErrorCode status = U_ZERO_ERROR; + status = U_ZERO_ERROR; fCapitalizationBrkIter = BreakIterator::createSentenceInstance(fLocale, status); if (U_FAILURE(status)) { delete fCapitalizationBrkIter; @@ -456,8 +456,8 @@ RelativeDateFormat::initCapitalizationContextInfo(const Locale& thelocale) const int32_t * intVector = ures_getIntVector(rb.getAlias(), &len, &status); if (U_SUCCESS(status) && intVector != NULL && len >= 2) { - fCapitalizationOfRelativeUnitsForUIListMenu = intVector[0]; - fCapitalizationOfRelativeUnitsForStandAlone = intVector[1]; + fCapitalizationOfRelativeUnitsForUIListMenu = static_cast(intVector[0]); + fCapitalizationOfRelativeUnitsForStandAlone = static_cast(intVector[1]); } } #endif diff --git a/deps/icu-small/source/i18n/reldtfmt.h b/deps/icu-small/source/i18n/reldtfmt.h index 5063a6388f63b0..0403da11efda76 100644 --- a/deps/icu-small/source/i18n/reldtfmt.h +++ b/deps/icu-small/source/i18n/reldtfmt.h @@ -235,7 +235,6 @@ class RelativeDateFormat : public DateFormat { */ virtual const DateFormatSymbols* getDateFormatSymbols(void) const; - /* Cannot use #ifndef U_HIDE_DRAFT_API for the following draft method since it is virtual */ /** * Set a particular UDisplayContext value in the formatter, such as * UDISPCTX_CAPITALIZATION_FOR_STANDALONE. Note: For getContext, see diff --git a/deps/icu-small/source/i18n/rematch.cpp b/deps/icu-small/source/i18n/rematch.cpp index f2521822078169..95fd0d2240af95 100644 --- a/deps/icu-small/source/i18n/rematch.cpp +++ b/deps/icu-small/source/i18n/rematch.cpp @@ -801,7 +801,7 @@ UBool RegexMatcher::find(UErrorCode &status) { case START_LINE: { - UChar32 c; + UChar32 ch; if (startPos == fAnchorStart) { MatchAt(startPos, FALSE, status); if (U_FAILURE(status)) { @@ -811,17 +811,17 @@ UBool RegexMatcher::find(UErrorCode &status) { return TRUE; } UTEXT_SETNATIVEINDEX(fInputText, startPos); - c = UTEXT_NEXT32(fInputText); + ch = UTEXT_NEXT32(fInputText); startPos = UTEXT_GETNATIVEINDEX(fInputText); } else { UTEXT_SETNATIVEINDEX(fInputText, startPos); - c = UTEXT_PREVIOUS32(fInputText); + ch = UTEXT_PREVIOUS32(fInputText); UTEXT_SETNATIVEINDEX(fInputText, startPos); } if (fPattern->fFlags & UREGEX_UNIX_LINES) { for (;;) { - if (c == 0x0a) { + if (ch == 0x0a) { MatchAt(startPos, FALSE, status); if (U_FAILURE(status)) { return FALSE; @@ -836,7 +836,7 @@ UBool RegexMatcher::find(UErrorCode &status) { fHitEnd = TRUE; return FALSE; } - c = UTEXT_NEXT32(fInputText); + ch = UTEXT_NEXT32(fInputText); startPos = UTEXT_GETNATIVEINDEX(fInputText); // Note that it's perfectly OK for a pattern to have a zero-length // match at the end of a string, so we must make sure that the loop @@ -846,8 +846,8 @@ UBool RegexMatcher::find(UErrorCode &status) { } } else { for (;;) { - if (isLineTerminator(c)) { - if (c == 0x0d && startPos < fActiveLimit && UTEXT_CURRENT32(fInputText) == 0x0a) { + if (isLineTerminator(ch)) { + if (ch == 0x0d && startPos < fActiveLimit && UTEXT_CURRENT32(fInputText) == 0x0a) { (void)UTEXT_NEXT32(fInputText); startPos = UTEXT_GETNATIVEINDEX(fInputText); } @@ -865,7 +865,7 @@ UBool RegexMatcher::find(UErrorCode &status) { fHitEnd = TRUE; return FALSE; } - c = UTEXT_NEXT32(fInputText); + ch = UTEXT_NEXT32(fInputText); startPos = UTEXT_GETNATIVEINDEX(fInputText); // Note that it's perfectly OK for a pattern to have a zero-length // match at the end of a string, so we must make sure that the loop @@ -1034,7 +1034,7 @@ UBool RegexMatcher::findUsingChunk(UErrorCode &status) { return FALSE; } } - U_ASSERT(FALSE); + U_ASSERT(FALSE); case START_STRING: case START_CHAR: @@ -1067,7 +1067,7 @@ UBool RegexMatcher::findUsingChunk(UErrorCode &status) { case START_LINE: { - UChar32 c; + UChar32 ch; if (startPos == fAnchorStart) { MatchChunkAt(startPos, FALSE, status); if (U_FAILURE(status)) { @@ -1081,8 +1081,8 @@ UBool RegexMatcher::findUsingChunk(UErrorCode &status) { if (fPattern->fFlags & UREGEX_UNIX_LINES) { for (;;) { - c = inputBuf[startPos-1]; - if (c == 0x0a) { + ch = inputBuf[startPos-1]; + if (ch == 0x0a) { MatchChunkAt(startPos, FALSE, status); if (U_FAILURE(status)) { return FALSE; @@ -1105,9 +1105,9 @@ UBool RegexMatcher::findUsingChunk(UErrorCode &status) { } } else { for (;;) { - c = inputBuf[startPos-1]; - if (isLineTerminator(c)) { - if (c == 0x0d && startPos < fActiveLimit && inputBuf[startPos] == 0x0a) { + ch = inputBuf[startPos-1]; + if (isLineTerminator(ch)) { + if (ch == 0x0d && startPos < fActiveLimit && inputBuf[startPos] == 0x0a) { startPos++; } MatchChunkAt(startPos, FALSE, status); @@ -2774,7 +2774,7 @@ void RegexMatcher::MatchAt(int64_t startIdx, UBool toEnd, UErrorCode &status) { int64_t *pat = fPattern->fCompiledPat->getBuffer(); const UChar *litText = fPattern->fLiteralText.getBuffer(); - UVector *sets = fPattern->fSets; + UVector *fSets = fPattern->fSets; fFrameSize = fPattern->fFrameSize; REStackFrame *fp = resetStack(); @@ -3376,7 +3376,7 @@ void RegexMatcher::MatchAt(int64_t startIdx, UBool toEnd, UErrorCode &status) { // There is input left. Pick up one char and test it for set membership. UChar32 c = UTEXT_NEXT32(fInputText); - U_ASSERT(opValue > 0 && opValue < sets->size()); + U_ASSERT(opValue > 0 && opValue < fSets->size()); if (c<256) { Regex8BitSet *s8 = &fPattern->fSets8[opValue]; if (s8->contains(c)) { @@ -3384,7 +3384,7 @@ void RegexMatcher::MatchAt(int64_t startIdx, UBool toEnd, UErrorCode &status) { break; } } else { - UnicodeSet *s = (UnicodeSet *)sets->elementAt(opValue); + UnicodeSet *s = (UnicodeSet *)fSets->elementAt(opValue); if (s->contains(c)) { // The character is in the set. A Match. fp->fInputIdx = UTEXT_GETNATIVEINDEX(fInputText); @@ -3671,9 +3671,9 @@ void RegexMatcher::MatchAt(int64_t startIdx, UBool toEnd, UErrorCode &status) { if (newFP == (int64_t *)fp) { break; } - int32_t i; - for (i=0; isetSize(newStackSize); @@ -3830,9 +3830,9 @@ void RegexMatcher::MatchAt(int64_t startIdx, UBool toEnd, UErrorCode &status) { // This makes the capture groups from within the look-ahead // expression available. int64_t *newFP = fStack->getBuffer() + newStackSize - fFrameSize; - int32_t i; - for (i=0; isetSize(newStackSize); @@ -4123,9 +4123,9 @@ void RegexMatcher::MatchAt(int64_t startIdx, UBool toEnd, UErrorCode &status) { // This op scans through all matching input. // The following LOOP_C op emulates stack unwinding if the following pattern fails. { - U_ASSERT(opValue > 0 && opValue < sets->size()); + U_ASSERT(opValue > 0 && opValue < fSets->size()); Regex8BitSet *s8 = &fPattern->fSets8[opValue]; - UnicodeSet *s = (UnicodeSet *)sets->elementAt(opValue); + UnicodeSet *s = (UnicodeSet *)fSets->elementAt(opValue); // Loop through input, until either the input is exhausted or // we reach a character that is not a member of the set. @@ -4350,7 +4350,7 @@ void RegexMatcher::MatchChunkAt(int32_t startIdx, UBool toEnd, UErrorCode &statu int64_t *pat = fPattern->fCompiledPat->getBuffer(); const UChar *litText = fPattern->fLiteralText.getBuffer(); - UVector *sets = fPattern->fSets; + UVector *fSets = fPattern->fSets; const UChar *inputBuf = fInputText->chunkContents; @@ -4928,7 +4928,7 @@ void RegexMatcher::MatchChunkAt(int32_t startIdx, UBool toEnd, UErrorCode &statu break; } - U_ASSERT(opValue > 0 && opValue < sets->size()); + U_ASSERT(opValue > 0 && opValue < fSets->size()); // There is input left. Pick up one char and test it for set membership. UChar32 c; @@ -4940,7 +4940,7 @@ void RegexMatcher::MatchChunkAt(int32_t startIdx, UBool toEnd, UErrorCode &statu break; } } else { - UnicodeSet *s = (UnicodeSet *)sets->elementAt(opValue); + UnicodeSet *s = (UnicodeSet *)fSets->elementAt(opValue); if (s->contains(c)) { // The character is in the set. A Match. break; @@ -5214,9 +5214,9 @@ void RegexMatcher::MatchChunkAt(int32_t startIdx, UBool toEnd, UErrorCode &statu if (newFP == (int64_t *)fp) { break; } - int32_t i; - for (i=0; isetSize(newStackSize); @@ -5361,9 +5361,9 @@ void RegexMatcher::MatchChunkAt(int32_t startIdx, UBool toEnd, UErrorCode &statu // This makes the capture groups from within the look-ahead // expression available. int64_t *newFP = fStack->getBuffer() + newStackSize - fFrameSize; - int32_t i; - for (i=0; isetSize(newStackSize); @@ -5623,9 +5623,9 @@ void RegexMatcher::MatchChunkAt(int32_t startIdx, UBool toEnd, UErrorCode &statu // This op scans through all matching input. // The following LOOP_C op emulates stack unwinding if the following pattern fails. { - U_ASSERT(opValue > 0 && opValue < sets->size()); + U_ASSERT(opValue > 0 && opValue < fSets->size()); Regex8BitSet *s8 = &fPattern->fSets8[opValue]; - UnicodeSet *s = (UnicodeSet *)sets->elementAt(opValue); + UnicodeSet *s = (UnicodeSet *)fSets->elementAt(opValue); // Loop through input, until either the input is exhausted or // we reach a character that is not a member of the set. diff --git a/deps/icu-small/source/i18n/rulebasedcollator.cpp b/deps/icu-small/source/i18n/rulebasedcollator.cpp index ab65f10a3bdfa8..b057b6bbd5a12f 100644 --- a/deps/icu-small/source/i18n/rulebasedcollator.cpp +++ b/deps/icu-small/source/i18n/rulebasedcollator.cpp @@ -764,9 +764,9 @@ RuleBasedCollator::internalCompareUTF8(const char *left, int32_t leftLength, // Make sure both or neither strings have a known length. // We do not optimize for mixed length/termination. if(leftLength >= 0) { - if(rightLength < 0) { rightLength = uprv_strlen(right); } + if(rightLength < 0) { rightLength = static_cast(uprv_strlen(right)); } } else { - if(rightLength >= 0) { leftLength = uprv_strlen(left); } + if(rightLength >= 0) { leftLength = static_cast(uprv_strlen(left)); } } return doCompare(reinterpret_cast(left), leftLength, reinterpret_cast(right), rightLength, errorCode); @@ -862,9 +862,9 @@ class FCDUTF16NFDIterator : public UTF16NFDIterator { } else { str.setTo(text, (int32_t)(spanLimit - text)); { - ReorderingBuffer buffer(nfcImpl, str); - if(buffer.init(str.length(), errorCode)) { - nfcImpl.makeFCD(spanLimit, textLimit, &buffer, errorCode); + ReorderingBuffer r_buffer(nfcImpl, str); + if(r_buffer.init(str.length(), errorCode)) { + nfcImpl.makeFCD(spanLimit, textLimit, &r_buffer, errorCode); } } if(U_SUCCESS(errorCode)) { diff --git a/deps/icu-small/source/i18n/scriptset.cpp b/deps/icu-small/source/i18n/scriptset.cpp index 9358e63b9ee403..558d178e2f97ca 100644 --- a/deps/icu-small/source/i18n/scriptset.cpp +++ b/deps/icu-small/source/i18n/scriptset.cpp @@ -298,7 +298,7 @@ uhash_compareScriptSet(UElement key0, UElement key1) { icu::ScriptSet *s0 = static_cast(key0.pointer); icu::ScriptSet *s1 = static_cast(key1.pointer); int32_t diff = s0->countMembers() - s1->countMembers(); - if (diff != 0) return diff; + if (diff != 0) return static_cast(diff); int32_t i0 = s0->nextSetBit(0); int32_t i1 = s1->nextSetBit(0); while ((diff = i0-i1) == 0 && i0 > 0) { diff --git a/deps/icu-small/source/i18n/shareddateformatsymbols.h b/deps/icu-small/source/i18n/shareddateformatsymbols.h index ca9a2108190c4d..66a06ecae5476a 100644 --- a/deps/icu-small/source/i18n/shareddateformatsymbols.h +++ b/deps/icu-small/source/i18n/shareddateformatsymbols.h @@ -12,6 +12,9 @@ #define __SHARED_DATEFORMATSYMBOLS_H__ #include "unicode/utypes.h" + +#if !UCONFIG_NO_FORMATTING + #include "sharedobject.h" #include "unicode/dtfmtsym.h" @@ -33,4 +36,6 @@ class U_I18N_API SharedDateFormatSymbols : public SharedObject { U_NAMESPACE_END +#endif /* !UCONFIG_NO_FORMATTING */ + #endif diff --git a/deps/icu-small/source/i18n/smpdtfmt.cpp b/deps/icu-small/source/i18n/smpdtfmt.cpp index b1b90882fceead..2bc8e49625fe29 100644 --- a/deps/icu-small/source/i18n/smpdtfmt.cpp +++ b/deps/icu-small/source/i18n/smpdtfmt.cpp @@ -244,9 +244,9 @@ SimpleDateFormat::NSOverride::~NSOverride() { void SimpleDateFormat::NSOverride::free() { NSOverride *cur = this; while (cur) { - NSOverride *next = cur->next; + NSOverride *next_temp = cur->next; delete cur; - cur = next; + cur = next_temp; } } @@ -1304,15 +1304,15 @@ SimpleDateFormat::processOverrideString(const Locale &locale, const UnicodeStrin int32_t nsNameHash = nsName.hashCode(); // See if the numbering system is in the override list, if not, then add it. - NSOverride *cur = overrideList; + NSOverride *curr = overrideList; const SharedNumberFormat *snf = NULL; UBool found = FALSE; - while ( cur && !found ) { - if ( cur->hash == nsNameHash ) { - snf = cur->snf; + while ( curr && !found ) { + if ( curr->hash == nsNameHash ) { + snf = curr->snf; found = TRUE; } - cur = cur->next; + curr = curr->next; } if (!found) { @@ -1824,14 +1824,14 @@ SimpleDateFormat::subFormat(UnicodeString &appendTo, // Stealing am/pm value to use as our array index. // It works out: am/midnight are both 0, pm/noon are both 1, // 12 am is 12 midnight, and 12 pm is 12 noon. - int32_t value = cal.get(UCAL_AM_PM, status); + int32_t val = cal.get(UCAL_AM_PM, status); if (count <= 3) { - toAppend = &fSymbols->fAbbreviatedDayPeriods[value]; + toAppend = &fSymbols->fAbbreviatedDayPeriods[val]; } else if (count == 4 || count > 5) { - toAppend = &fSymbols->fWideDayPeriods[value]; + toAppend = &fSymbols->fWideDayPeriods[val]; } else { // count == 5 - toAppend = &fSymbols->fNarrowDayPeriods[value]; + toAppend = &fSymbols->fNarrowDayPeriods[val]; } } @@ -2281,10 +2281,10 @@ SimpleDateFormat::parse(const UnicodeString& text, Calendar& cal, ParsePosition& if (i+1 < fPattern.length()) { // move to next pattern character - UChar ch = fPattern.charAt(i+1); + UChar c = fPattern.charAt(i+1); // check for whitespace - if (PatternProps::isWhiteSpace(ch)) { + if (PatternProps::isWhiteSpace(c)) { i++; // Advance over run in pattern while ((i+1)isLeapYear(hc->get(UCAL_YEAR,status)) && value >= 6) { + UErrorCode monthStatus = U_ZERO_ERROR; + if (!hc->isLeapYear(hc->get(UCAL_YEAR, monthStatus)) && value >= 6) { cal.set(UCAL_MONTH, value); } else { cal.set(UCAL_MONTH, value - 1); @@ -3571,21 +3571,21 @@ int32_t SimpleDateFormat::subParse(const UnicodeString& text, int32_t& start, UC static const UChar alt_sep = DateFormatSymbols::ALTERNATE_TIME_SEPARATOR; // Try matching a time separator. - int32_t count = 1; + int32_t count_sep = 1; UnicodeString data[3]; fSymbols->getTimeSeparatorString(data[0]); // Add the default, if different from the locale. if (data[0].compare(&def_sep, 1) != 0) { - data[count++].setTo(def_sep); + data[count_sep++].setTo(def_sep); } // If lenient, add also the alternate, if different from the locale. if (isLenient() && data[0].compare(&alt_sep, 1) != 0) { - data[count++].setTo(alt_sep); + data[count_sep++].setTo(alt_sep); } - return matchString(text, start, UCAL_FIELD_COUNT /* => nothing to set */, data, count, NULL, cal); + return matchString(text, start, UCAL_FIELD_COUNT /* => nothing to set */, data, count_sep, NULL, cal); } case UDAT_AM_PM_MIDNIGHT_NOON_FIELD: @@ -3674,7 +3674,7 @@ int32_t SimpleDateFormat::subParse(const UnicodeString& text, int32_t& start, UC } parseInt(*src, number, pos, allowNegative,currentNumberFormat); if (pos.getIndex() != parseStart) { - int32_t value = number.getLong(); + int32_t val = number.getLong(); // Don't need suffix processing here (as in number processing at the beginning of the function); // the new fields being handled as numeric values (month, weekdays, quarters) should not have suffixes. @@ -3682,7 +3682,7 @@ int32_t SimpleDateFormat::subParse(const UnicodeString& text, int32_t& start, UC if (!getBooleanAttribute(UDAT_PARSE_ALLOW_NUMERIC, status)) { // Check the range of the value int32_t bias = gFieldRangeBias[patternCharIndex]; - if (bias >= 0 && (value > cal.getMaximum(field) + bias || value < cal.getMinimum(field) + bias)) { + if (bias >= 0 && (val > cal.getMaximum(field) + bias || val < cal.getMinimum(field) + bias)) { return -start; } } @@ -3696,35 +3696,35 @@ int32_t SimpleDateFormat::subParse(const UnicodeString& text, int32_t& start, UC if (!strcmp(cal.getType(),"hebrew")) { HebrewCalendar *hc = (HebrewCalendar*)&cal; if (cal.isSet(UCAL_YEAR)) { - UErrorCode status = U_ZERO_ERROR; - if (!hc->isLeapYear(hc->get(UCAL_YEAR,status)) && value >= 6) { - cal.set(UCAL_MONTH, value); + UErrorCode monthStatus = U_ZERO_ERROR; + if (!hc->isLeapYear(hc->get(UCAL_YEAR, monthStatus)) && val >= 6) { + cal.set(UCAL_MONTH, val); } else { - cal.set(UCAL_MONTH, value - 1); + cal.set(UCAL_MONTH, val - 1); } } else { - saveHebrewMonth = value; + saveHebrewMonth = val; } } else { - cal.set(UCAL_MONTH, value - 1); + cal.set(UCAL_MONTH, val - 1); } break; case UDAT_STANDALONE_MONTH_FIELD: - cal.set(UCAL_MONTH, value - 1); + cal.set(UCAL_MONTH, val - 1); break; case UDAT_DOW_LOCAL_FIELD: case UDAT_STANDALONE_DAY_FIELD: - cal.set(UCAL_DOW_LOCAL, value); + cal.set(UCAL_DOW_LOCAL, val); break; case UDAT_QUARTER_FIELD: case UDAT_STANDALONE_QUARTER_FIELD: - cal.set(UCAL_MONTH, (value - 1) * 3); + cal.set(UCAL_MONTH, (val - 1) * 3); break; case UDAT_RELATED_YEAR_FIELD: - cal.setRelatedYear(value); + cal.setRelatedYear(val); break; default: - cal.set(field, value); + cal.set(field, val); break; } return pos.getIndex(); @@ -3971,7 +3971,7 @@ SimpleDateFormat::setContext(UDisplayContext value, UErrorCode& status) if (U_SUCCESS(status)) { if ( fCapitalizationBrkIter == NULL && (value==UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE || value==UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU || value==UDISPCTX_CAPITALIZATION_FOR_STANDALONE) ) { - UErrorCode status = U_ZERO_ERROR; + status = U_ZERO_ERROR; fCapitalizationBrkIter = BreakIterator::createSentenceInstance(fLocale, status); if (U_FAILURE(status)) { delete fCapitalizationBrkIter; diff --git a/deps/icu-small/source/i18n/timezone.cpp b/deps/icu-small/source/i18n/timezone.cpp index f7f45c7d3eeffd..dbf614469e8311 100644 --- a/deps/icu-small/source/i18n/timezone.cpp +++ b/deps/icu-small/source/i18n/timezone.cpp @@ -1031,8 +1031,8 @@ TimeZone::getEquivalentID(const UnicodeString& id, int32_t index) { UResourceBundle *ares = ures_getByKey(top, kNAMES, NULL, &ec); // dereference Zones section if (U_SUCCESS(ec)) { int32_t idLen = 0; - const UChar* id = ures_getStringByIndex(ares, zone, &idLen, &ec); - result.fastCopyFrom(UnicodeString(TRUE, id, idLen)); + const UChar* id2 = ures_getStringByIndex(ares, zone, &idLen, &ec); + result.fastCopyFrom(UnicodeString(TRUE, id2, idLen)); U_DEBUG_TZ_MSG(("gei(%d) -> %d, len%d, %s\n", index, zone, result.length(), u_errorName(ec))); } ures_close(ares); @@ -1199,7 +1199,7 @@ TimeZone::getDisplayName(UBool daylight, EDisplayType style, const Locale& local { UErrorCode status = U_ZERO_ERROR; UDate date = Calendar::getNow(); - UTimeZoneFormatTimeType timeType; + UTimeZoneFormatTimeType timeType = UTZFMT_TIME_TYPE_UNKNOWN; int32_t offset; if (style == GENERIC_LOCATION || style == LONG_GENERIC || style == SHORT_GENERIC) { @@ -1612,7 +1612,7 @@ TimeZone::getWindowsID(const UnicodeString& id, UnicodeString& winid, UErrorCode end = tzids + len; hasNext = FALSE; } - if (canonicalID.compare(start, end - start) == 0) { + if (canonicalID.compare(start, static_cast(end - start)) == 0) { winid = UnicodeString(ures_getKey(winzone), -1 , US_INV); found = TRUE; break; @@ -1673,7 +1673,7 @@ TimeZone::getIDForWindowsID(const UnicodeString& winid, const char* region, Unic if (end == NULL) { id.setTo(tzids, -1); } else { - id.setTo(tzids, end - tzids); + id.setTo(tzids, static_cast(end - tzids)); } gotID = TRUE; } diff --git a/deps/icu-small/source/i18n/transreg.cpp b/deps/icu-small/source/i18n/transreg.cpp index 331f4efdeb339a..4884773faf5ac3 100644 --- a/deps/icu-small/source/i18n/transreg.cpp +++ b/deps/icu-small/source/i18n/transreg.cpp @@ -1330,12 +1330,12 @@ Transliterator* TransliteratorRegistry::instantiateEntry(const UnicodeString& ID int32_t passNumber = 1; for (int32_t i = 0; U_SUCCESS(status) && i < entry->u.dataVector->size(); i++) { // TODO: Should passNumber be turned into a decimal-string representation (1 -> "1")? - Transliterator* t = new RuleBasedTransliterator(UnicodeString(CompoundTransliterator::PASS_STRING) + UnicodeString(passNumber++), + Transliterator* tl = new RuleBasedTransliterator(UnicodeString(CompoundTransliterator::PASS_STRING) + UnicodeString(passNumber++), (TransliterationRuleData*)(entry->u.dataVector->elementAt(i)), FALSE); - if (t == 0) + if (tl == 0) status = U_MEMORY_ALLOCATION_ERROR; else - rbts->addElement(t, status); + rbts->addElement(tl, status); } if (U_FAILURE(status)) { delete rbts; diff --git a/deps/icu-small/source/i18n/tzfmt.cpp b/deps/icu-small/source/i18n/tzfmt.cpp index 69da4667bc89ac..df4dec1febf60a 100644 --- a/deps/icu-small/source/i18n/tzfmt.cpp +++ b/deps/icu-small/source/i18n/tzfmt.cpp @@ -2648,12 +2648,12 @@ TimeZoneFormat::checkAbuttingHoursAndMinutes() { UVector *items = fGMTOffsetPatternItems[type]; for (int32_t i = 0; i < items->size(); i++) { const GMTOffsetField* item = (GMTOffsetField*)items->elementAt(i); - GMTOffsetField::FieldType type = item->getType(); - if (type != GMTOffsetField::TEXT) { + GMTOffsetField::FieldType fieldType = item->getType(); + if (fieldType != GMTOffsetField::TEXT) { if (afterH) { fAbuttingOffsetHoursAndMinutes = TRUE; break; - } else if (type == GMTOffsetField::HOUR) { + } else if (fieldType == GMTOffsetField::HOUR) { afterH = TRUE; } } else if (afterH) { diff --git a/deps/icu-small/source/i18n/tzgnames.cpp b/deps/icu-small/source/i18n/tzgnames.cpp index c2e685272e9b36..5f5b7db30227cc 100644 --- a/deps/icu-small/source/i18n/tzgnames.cpp +++ b/deps/icu-small/source/i18n/tzgnames.cpp @@ -407,7 +407,7 @@ TZGNCore::initialize(const Locale& locale, UErrorCode& status) { // target region const char* region = fLocale.getCountry(); - int32_t regionLen = uprv_strlen(region); + int32_t regionLen = static_cast(uprv_strlen(region)); if (regionLen == 0) { char loc[ULOC_FULLNAME_CAPACITY]; uloc_addLikelySubtags(fLocale.getName(), loc, sizeof(loc), &status); diff --git a/deps/icu-small/source/i18n/tznames.cpp b/deps/icu-small/source/i18n/tznames.cpp index 689fdeb0915300..5a79c22aacf8f9 100644 --- a/deps/icu-small/source/i18n/tznames.cpp +++ b/deps/icu-small/source/i18n/tznames.cpp @@ -87,7 +87,7 @@ static void sweepCache() { const UHashElement* elem; double now = (double)uprv_getUTCtime(); - while ((elem = uhash_nextElement(gTimeZoneNamesCache, &pos))) { + while ((elem = uhash_nextElement(gTimeZoneNamesCache, &pos)) != 0) { TimeZoneNamesCacheEntry *entry = (TimeZoneNamesCacheEntry *)elem->value.pointer; if (entry->refCount <= 0 && (now - entry->lastAccess) > CACHE_EXPIRATION) { // delete this entry diff --git a/deps/icu-small/source/i18n/tznames_impl.cpp b/deps/icu-small/source/i18n/tznames_impl.cpp index ef04b31c1357f4..6a303ea4a0110f 100644 --- a/deps/icu-small/source/i18n/tznames_impl.cpp +++ b/deps/icu-small/source/i18n/tznames_impl.cpp @@ -1285,7 +1285,7 @@ static void mergeTimeZoneKey(const UnicodeString& mzID, char* result) { char mzIdChar[ZID_KEY_MAX + 1]; int32_t keyLen; - int32_t prefixLen = uprv_strlen(gMZPrefix); + int32_t prefixLen = static_cast(uprv_strlen(gMZPrefix)); keyLen = mzID.extract(0, mzID.length(), mzIdChar, ZID_KEY_MAX + 1, US_INV); uprv_memcpy((void *)result, (void *)gMZPrefix, prefixLen); uprv_memcpy((void *)(result + prefixLen), (void *)mzIdChar, keyLen); @@ -1453,7 +1453,7 @@ struct TimeZoneNamesImpl::ZoneStringsLoader : public ResourceSink { virtual ~ZoneStringsLoader(); void* createKey(const char* key, UErrorCode& status) { - int32_t len = sizeof(char) * (uprv_strlen(key) + 1); + int32_t len = sizeof(char) * (static_cast(uprv_strlen(key)) + 1); char* newKey = (char*) uprv_malloc(len); if (newKey == NULL) { status = U_MEMORY_ALLOCATION_ERROR; @@ -1469,7 +1469,7 @@ struct TimeZoneNamesImpl::ZoneStringsLoader : public ResourceSink { } UnicodeString mzIDFromKey(const char* key) { - return UnicodeString(key + MZ_PREFIX_LEN, uprv_strlen(key) - MZ_PREFIX_LEN, US_INV); + return UnicodeString(key + MZ_PREFIX_LEN, static_cast(uprv_strlen(key)) - MZ_PREFIX_LEN, US_INV); } UnicodeString tzIDFromKey(const char* key) { @@ -1944,8 +1944,8 @@ TZDBNameSearchHandler::handleMatch(int32_t matchLength, const CharacterNode *nod // metazone mapping for "CST" is America_Central, // but if region is one of CN/MO/TW, "CST" is parsed // as metazone China (China Standard Time). - for (int32_t i = 0; i < ninfo->nRegions; i++) { - const char *region = ninfo->parseRegions[i]; + for (int32_t j = 0; j < ninfo->nRegions; j++) { + const char *region = ninfo->parseRegions[j]; if (uprv_strcmp(fRegion, region) == 0) { match = ninfo; matchRegion = TRUE; @@ -2059,7 +2059,7 @@ static void U_CALLCONV prepareFind(UErrorCode &status) { const UnicodeString *mzID; StringEnumeration *mzIDs = TimeZoneNamesImpl::_getAvailableMetaZoneIDs(status); if (U_SUCCESS(status)) { - while ((mzID = mzIDs->snext(status)) && U_SUCCESS(status)) { + while ((mzID = mzIDs->snext(status)) != 0 && U_SUCCESS(status)) { const TZDBNames *names = TZDBTimeZoneNames::getMetaZoneNames(*mzID, status); if (U_FAILURE(status)) { break; @@ -2128,7 +2128,7 @@ TZDBTimeZoneNames::TZDBTimeZoneNames(const Locale& locale) : fLocale(locale) { UBool useWorld = TRUE; const char* region = fLocale.getCountry(); - int32_t regionLen = uprv_strlen(region); + int32_t regionLen = static_cast(uprv_strlen(region)); if (regionLen == 0) { UErrorCode status = U_ZERO_ERROR; char loc[ULOC_FULLNAME_CAPACITY]; diff --git a/deps/icu-small/source/i18n/ucln_in.h b/deps/icu-small/source/i18n/ucln_in.h index 318eafc143c968..4c13b9ffcb539a 100644 --- a/deps/icu-small/source/i18n/ucln_in.h +++ b/deps/icu-small/source/i18n/ucln_in.h @@ -32,6 +32,7 @@ typedef enum ECleanupI18NType { UCLN_I18N_SPOOFDATA, UCLN_I18N_TRANSLITERATOR, UCLN_I18N_REGEX, + UCLN_I18N_JAPANESE_CALENDAR, UCLN_I18N_ISLAMIC_CALENDAR, UCLN_I18N_CHINESE_CALENDAR, UCLN_I18N_HEBREW_CALENDAR, @@ -58,6 +59,7 @@ typedef enum ECleanupI18NType { UCLN_I18N_GENDERINFO, UCLN_I18N_CDFINFO, UCLN_I18N_REGION, + UCLN_I18N_LIST_FORMATTER, UCLN_I18N_COUNT /* This must be last */ } ECleanupI18NType; diff --git a/deps/icu-small/source/i18n/ucol_res.cpp b/deps/icu-small/source/i18n/ucol_res.cpp index 76975ecc01de63..56ed5b3c19caca 100644 --- a/deps/icu-small/source/i18n/ucol_res.cpp +++ b/deps/icu-small/source/i18n/ucol_res.cpp @@ -400,11 +400,11 @@ CollationLoader::loadFromData(UErrorCode &errorCode) { // Try to fetch the optional rules string. { UErrorCode internalErrorCode = U_ZERO_ERROR; - int32_t length; - const UChar *s = ures_getStringByKey(data, "Sequence", &length, + int32_t len; + const UChar *s = ures_getStringByKey(data, "Sequence", &len, &internalErrorCode); if(U_SUCCESS(internalErrorCode)) { - t->rules.setTo(TRUE, s, length); + t->rules.setTo(TRUE, s, len); } } @@ -426,10 +426,10 @@ CollationLoader::loadFromData(UErrorCode &errorCode) { LocalUResourceBundlePointer def( ures_getByKeyWithFallback(actualBundle.getAlias(), "collations/default", NULL, &internalErrorCode)); - int32_t length; - const UChar *s = ures_getString(def.getAlias(), &length, &internalErrorCode); - if(U_SUCCESS(internalErrorCode) && length < UPRV_LENGTHOF(defaultType)) { - u_UCharsToChars(s, defaultType, length + 1); + int32_t len; + const UChar *s = ures_getString(def.getAlias(), &len, &internalErrorCode); + if(U_SUCCESS(internalErrorCode) && len < UPRV_LENGTHOF(defaultType)) { + u_UCharsToChars(s, defaultType, len + 1); } else { uprv_strcpy(defaultType, "standard"); } diff --git a/deps/icu-small/source/i18n/udat.cpp b/deps/icu-small/source/i18n/udat.cpp index d086067c034da6..b7d85cc179ef9a 100644 --- a/deps/icu-small/source/i18n/udat.cpp +++ b/deps/icu-small/source/i18n/udat.cpp @@ -603,7 +603,7 @@ udat_getSymbols(const UDateFormat *fmt, } else { return -1; } - int32_t count; + int32_t count = 0; const UnicodeString *res = NULL; switch(type) { diff --git a/deps/icu-small/source/common/ulistformatter.cpp b/deps/icu-small/source/i18n/ulistformatter.cpp similarity index 100% rename from deps/icu-small/source/common/ulistformatter.cpp rename to deps/icu-small/source/i18n/ulistformatter.cpp diff --git a/deps/icu-small/source/i18n/ulocdata.cpp b/deps/icu-small/source/i18n/ulocdata.cpp index 551f6c64ed5668..f651fee6fc4efa 100644 --- a/deps/icu-small/source/i18n/ulocdata.cpp +++ b/deps/icu-small/source/i18n/ulocdata.cpp @@ -372,7 +372,7 @@ ulocdata_getLocaleSeparator(ULocaleData *uld, p1=u_strstr(separator, sub1); if (p0!=NULL && p1!=NULL && p0<=p1) { separator = (const UChar *)p0 + subLen; - len = p1 - separator; + len = static_cast(p1 - separator); /* Desired separator is no longer zero-terminated; handle that if necessary */ if (len < resultCapacity) { u_strncpy(result, separator, len); diff --git a/deps/icu-small/source/i18n/unicode/alphaindex.h b/deps/icu-small/source/i18n/unicode/alphaindex.h index 54bd29ff88668a..4ebdf1cc56a1a8 100644 --- a/deps/icu-small/source/i18n/unicode/alphaindex.h +++ b/deps/icu-small/source/i18n/unicode/alphaindex.h @@ -266,6 +266,8 @@ class U_I18N_API AlphabeticIndex: public UObject { * Use getBucket() to get the bucket's properties. * * @param name the string to be sorted into an index bucket + * @param errorCode Error code, will be set with the reason if the + * operation fails. * @return the bucket number for the name * @stable ICU 51 */ @@ -377,9 +379,10 @@ class U_I18N_API AlphabeticIndex: public UObject { /** - * Get the default label used for abbreviated buckets between other index characters. - * For example, consider the labels when Latin and Greek are used: - * X Y Z ... Α Β Γ. + * Get the default label used for abbreviated buckets *between* other index characters. + * For example, consider the labels when Latin (X Y Z) and Greek (Α Β Γ) are used: + * + * X Y Z ... Α Β Γ. * * @return inflow label * @stable ICU 4.8 @@ -700,6 +703,7 @@ class U_I18N_API AlphabeticIndex: public UObject { /** * A (name, data) pair, to be sorted by name into one of the index buckets. * The user data is not used by the index implementation. + * \cond * @internal */ struct Record: public UMemory { @@ -708,6 +712,7 @@ class U_I18N_API AlphabeticIndex: public UObject { Record(const UnicodeString &name, const void *data); ~Record(); }; + /** \endcond */ #endif /* U_HIDE_INTERNAL_API */ private: diff --git a/deps/icu-small/source/i18n/unicode/calendar.h b/deps/icu-small/source/i18n/unicode/calendar.h index 48021534b422f6..023cf053f254fb 100644 --- a/deps/icu-small/source/i18n/unicode/calendar.h +++ b/deps/icu-small/source/i18n/unicode/calendar.h @@ -52,83 +52,64 @@ typedef int32_t UFieldResolutionTable[12][8]; class BasicTimeZone; /** - * Calendar is an abstract base class for converting between - * a UDate object and a set of integer fields such as - * YEAR, MONTH, DAY, HOUR, - * and so on. (A UDate object represents a specific instant in + * `Calendar` is an abstract base class for converting between + * a `UDate` object and a set of integer fields such as + * `YEAR`, `MONTH`, `DAY`, `HOUR`, and so on. + * (A `UDate` object represents a specific instant in * time with millisecond precision. See UDate - * for information about the UDate class.) + * for information about the `UDate` class.) * - *

    - * Subclasses of Calendar interpret a UDate + * Subclasses of `Calendar` interpret a `UDate` * according to the rules of a specific calendar system. - * The most commonly used subclass of Calendar is - * GregorianCalendar. Other subclasses could represent + * The most commonly used subclass of `Calendar` is + * `GregorianCalendar`. Other subclasses could represent * the various types of lunar calendars in use in many parts of the world. * - *

    - * NOTE: (ICU 2.6) The subclass interface should be considered unstable - * - it WILL change. + * **NOTE**: (ICU 2.6) The subclass interface should be considered unstable - + * it WILL change. * - *

    - * Like other locale-sensitive classes, Calendar provides a - * static method, createInstance, for getting a generally useful - * object of this type. Calendar's createInstance method - * returns the appropriate Calendar subclass whose + * Like other locale-sensitive classes, `Calendar` provides a + * static method, `createInstance`, for getting a generally useful + * object of this type. `Calendar`'s `createInstance` method + * returns the appropriate `Calendar` subclass whose * time fields have been initialized with the current date and time: - * \htmlonly

    \endhtmlonly - *
    - * Calendar *rightNow = Calendar::createInstance(errCode);
    - * 
    - * \htmlonly
    \endhtmlonly * - *

    - * A Calendar object can produce all the time field values + * Calendar *rightNow = Calendar::createInstance(errCode); + * + * A `Calendar` object can produce all the time field values * needed to implement the date-time formatting for a particular language * and calendar style (for example, Japanese-Gregorian, Japanese-Traditional). * - *

    - * When computing a UDate from time fields, some special circumstances + * When computing a `UDate` from time fields, some special circumstances * may arise: there may be insufficient information to compute the - * UDate (such as only year and month but no day in the month), + * `UDate` (such as only year and month but no day in the month), * there may be inconsistent information (such as "Tuesday, July 15, 1996" * -- July 15, 1996 is actually a Monday), or the input time might be ambiguous * because of time zone transition. * - *

    - * Insufficient information. The calendar will use default + * **Insufficient information.** The calendar will use default * information to specify the missing fields. This may vary by calendar; for * the Gregorian calendar, the default for a field is the same as that of the * start of the epoch: i.e., YEAR = 1970, MONTH = JANUARY, DATE = 1, etc. * - *

    - * Inconsistent information. If fields conflict, the calendar + * **Inconsistent information.** If fields conflict, the calendar * will give preference to fields set more recently. For example, when * determining the day, the calendar will look for one of the following * combinations of fields. The most recent combination, as determined by the * most recently set single field, will be used. * - * \htmlonly

    \endhtmlonly - *
    - * MONTH + DAY_OF_MONTH
    - * MONTH + WEEK_OF_MONTH + DAY_OF_WEEK
    - * MONTH + DAY_OF_WEEK_IN_MONTH + DAY_OF_WEEK
    - * DAY_OF_YEAR
    - * DAY_OF_WEEK + WEEK_OF_YEAR
    - * 
    - * \htmlonly
    \endhtmlonly + * MONTH + DAY_OF_MONTH + * MONTH + WEEK_OF_MONTH + DAY_OF_WEEK + * MONTH + DAY_OF_WEEK_IN_MONTH + DAY_OF_WEEK + * DAY_OF_YEAR + * DAY_OF_WEEK + WEEK_OF_YEAR * * For the time of day: * - * \htmlonly
    \endhtmlonly - *
    - * HOUR_OF_DAY
    - * AM_PM + HOUR
    - * 
    - * \htmlonly
    \endhtmlonly + * HOUR_OF_DAY + * AM_PM + HOUR * - *

    - * Ambiguous Wall Clock Time. When time offset from UTC has + * **Ambiguous Wall Clock Time.** When time offset from UTC has * changed, it produces an ambiguous time slot around the transition. For example, * many US locations observe daylight saving time. On the date switching to daylight * saving time in US, wall clock time jumps from 12:59 AM (standard) to 2:00 AM @@ -138,64 +119,66 @@ class BasicTimeZone; * In this example, 1:30 AM is interpreted as 1:30 AM standard time (non-exist), * so the final result will be 2:30 AM daylight time. * - *

    On the date switching back to standard time, wall clock time is moved back one + * On the date switching back to standard time, wall clock time is moved back one * hour at 2:00 AM. So wall clock time from 1:00 AM to 1:59 AM occur twice. In this * case, the ICU Calendar resolves the time using the UTC offset after the transition * by default. For example, 1:30 AM on the date is resolved as 1:30 AM standard time. * - *

    Ambiguous wall clock time resolution behaviors can be customized by Calendar APIs + * Ambiguous wall clock time resolution behaviors can be customized by Calendar APIs * {@link #setRepeatedWallTimeOption} and {@link #setSkippedWallTimeOption}. * These methods are available in ICU 49 or later versions. * - *

    - * Note: for some non-Gregorian calendars, different + * **Note:** for some non-Gregorian calendars, different * fields may be necessary for complete disambiguation. For example, a full - * specification of the historial Arabic astronomical calendar requires year, - * month, day-of-month and day-of-week in some cases. + * specification of the historical Arabic astronomical calendar requires year, + * month, day-of-month *and* day-of-week in some cases. * - *

    - * Note: There are certain possible ambiguities in + * **Note:** There are certain possible ambiguities in * interpretation of certain singular times, which are resolved in the * following ways: - *

      - *
    1. 24:00:00 "belongs" to the following day. That is, - * 23:59 on Dec 31, 1969 < 24:00 on Jan 1, 1970 < 24:01:00 on Jan 1, 1970 * - *
    2. Although historically not precise, midnight also belongs to "am", - * and noon belongs to "pm", so on the same day, - * 12:00 am (midnight) < 12:01 am, and 12:00 pm (noon) < 12:01 pm - *
    + * 1. 24:00:00 "belongs" to the following day. That is, + * 23:59 on Dec 31, 1969 < 24:00 on Jan 1, 1970 < 24:01:00 on Jan 1, 1970 + * 2. Although historically not precise, midnight also belongs to "am", + * and noon belongs to "pm", so on the same day, + * 12:00 am (midnight) < 12:01 am, and 12:00 pm (noon) < 12:01 pm * - *

    * The date or time format strings are not part of the definition of a * calendar, as those must be modifiable or overridable by the user at - * runtime. Use {@link DateFormat} - * to format dates. + * runtime. Use `DateFormat` to format dates. * - *

    - * Calendar provides an API for field "rolling", where fields + * `Calendar` provides an API for field "rolling", where fields * can be incremented or decremented, but wrap around. For example, rolling the - * month up in the date December 12, 1996 results in - * January 12, 1996. + * month up in the date December 12, **1996** results in + * January 12, **1996**. * - *

    - * Calendar also provides a date arithmetic function for + * `Calendar` also provides a date arithmetic function for * adding the specified (signed) amount of time to a particular time field. - * For example, subtracting 5 days from the date September 12, 1996 - * results in September 7, 1996. + * For example, subtracting 5 days from the date `September 12, 1996` + * results in `September 7, 1996`. * - *

    Supported range + * ***Supported range*** * - *

    The allowable range of Calendar has been - * narrowed. GregorianCalendar used to attempt to support - * the range of dates with millisecond values from - * Long.MIN_VALUE to Long.MAX_VALUE. - * The new Calendar protocol specifies the + * The allowable range of `Calendar` has been narrowed. `GregorianCalendar` used + * to attempt to support the range of dates with millisecond values from + * `Long.MIN_VALUE` to `Long.MAX_VALUE`. The new `Calendar` protocol specifies the * maximum range of supportable dates as those having Julian day numbers - * of -0x7F000000 to +0x7F000000. This - * corresponds to years from ~5,800,000 BCE to ~5,800,000 CE. Programmers - * should use the protected constants in Calendar to - * specify an extremely early or extremely late date.

    + * of `-0x7F000000` to `+0x7F000000`. This corresponds to years from ~5,800,000 BCE + * to ~5,800,000 CE. Programmers should use the protected constants in `Calendar` to + * specify an extremely early or extremely late date. + * + *

    + * The Japanese calendar uses a combination of era name and year number. + * When an emperor of Japan abdicates and a new emperor ascends the throne, + * a new era is declared and year number is reset to 1. Even if the date of + * abdication is scheduled ahead of time, the new era name might not be + * announced until just before the date. In such case, ICU4C may include + * a start date of future era without actual era name, but not enabled + * by default. ICU4C users who want to test the behavior of the future era + * can enable the tentative era by: + *

      + *
    • Environment variable ICU_ENABLE_TENTATIVE_ERA=true.
    • + *
    * * @stable ICU 2.0 */ @@ -903,7 +886,7 @@ class U_I18N_API Calendar : public UObject { /** * Sets the behavior for handling wall time repeating multiple times * at negative time zone offset transitions. For example, 1:30 AM on - * November 6, 2011 in US Eastern time (Ameirca/New_York) occurs twice; + * November 6, 2011 in US Eastern time (America/New_York) occurs twice; * 1:30 AM EDT, then 1:30 AM EST one hour later. When UCAL_WALLTIME_FIRST * is used, the wall time 1:30AM in this example will be interpreted as 1:30 AM EDT * (first occurrence). When UCAL_WALLTIME_LAST is used, it will be @@ -1718,9 +1701,7 @@ class U_I18N_API Calendar : public UObject { /** * Validate a single field of this calendar. Subclasses should * override this method to validate any calendar-specific fields. - * Generic fields can be handled by - * Calendar::validateField(). - * @see #validateField(int, int, int, int&) + * Generic fields can be handled by `Calendar::validateField()`. * @internal */ virtual void validateField(UCalendarDateFields field, UErrorCode &status); @@ -2171,7 +2152,7 @@ class U_I18N_API Calendar : public UObject { TimeZone* fZone; /** - * Option for rpeated wall time + * Option for repeated wall time * @see #setRepeatedWallTimeOption */ UCalendarWallTimeOption fRepeatedWallTime; @@ -2456,7 +2437,7 @@ class U_I18N_API Calendar : public UObject { BasicTimeZone* getBasicTimeZone() const; /** - * Find the previous zone transtion near the given time. + * Find the previous zone transition near the given time. * @param base The base time, inclusive * @param transitionTime Receives the result time * @param status The error status diff --git a/deps/icu-small/source/i18n/unicode/coll.h b/deps/icu-small/source/i18n/unicode/coll.h index d03570509ecebb..653434f54ca664 100644 --- a/deps/icu-small/source/i18n/unicode/coll.h +++ b/deps/icu-small/source/i18n/unicode/coll.h @@ -235,16 +235,16 @@ class U_I18N_API Collator : public UObject { * Returns TRUE if "other" is the same as "this". * * The base class implementation returns TRUE if "other" has the same type/class as "this": - * typeid(*this) == typeid(other). + * `typeid(*this) == typeid(other)`. * * Subclass implementations should do something like the following: - *
    -     *   if (this == &other) { return TRUE; }
    -     *   if (!Collator::operator==(other)) { return FALSE; }  // not the same class
          *
    -     *   const MyCollator &o = (const MyCollator&)other;
    -     *   (compare this vs. o's subclass fields)
    -     * 
    + * if (this == &other) { return TRUE; } + * if (!Collator::operator==(other)) { return FALSE; } // not the same class + * + * const MyCollator &o = (const MyCollator&)other; + * (compare this vs. o's subclass fields) + * * @param other Collator object to be compared * @return TRUE if other is the same as this. * @stable ICU 2.0 diff --git a/deps/icu-small/source/i18n/unicode/compactdecimalformat.h b/deps/icu-small/source/i18n/unicode/compactdecimalformat.h index 7dc92f610062f4..9c1e9183f4657b 100644 --- a/deps/icu-small/source/i18n/unicode/compactdecimalformat.h +++ b/deps/icu-small/source/i18n/unicode/compactdecimalformat.h @@ -30,30 +30,31 @@ U_NAMESPACE_BEGIN class PluralRules; /** - *

    IMPORTANT: New users are strongly encouraged to see if + * **IMPORTANT:** New users are strongly encouraged to see if * numberformatter.h fits their use case. Although not deprecated, this header * is provided for backwards compatibility only. - *


    + * + * ----------------------------------------------------------------------------- * * The CompactDecimalFormat produces abbreviated numbers, suitable for display in * environments will limited real estate. For example, 'Hits: 1.2B' instead of * 'Hits: 1,200,000,000'. The format will be appropriate for the given language, * such as "1,2 Mrd." for German. - *

    + * * For numbers under 1000 trillion (under 10^15, such as 123,456,789,012,345), * the result will be short for supported languages. However, the result may * sometimes exceed 7 characters, such as when there are combining marks or thin * characters. In such cases, the visual width in fonts should still be short. - *

    + * * By default, there are 3 significant digits. After creation, if more than * three significant digits are set (with setMaximumSignificantDigits), or if a * fixed number of digits are set (with setMaximumIntegerDigits or * setMaximumFractionDigits), then result may be wider. - *

    + * * At this time, parsing is not supported, and will produce a U_UNSUPPORTED_ERROR. * Resetting the pattern prefixes or suffixes is not supported; the method calls * are ignored. - *

    + * * @stable ICU 51 */ class U_I18N_API CompactDecimalFormat : public DecimalFormat { @@ -61,9 +62,9 @@ class U_I18N_API CompactDecimalFormat : public DecimalFormat { /** * Returns a compact decimal instance for specified locale. - *

    - * NOTE: New users are strongly encouraged to use - * {@link NumberFormatter} instead of NumberFormat. + * + * **NOTE:** New users are strongly encouraged to use + * `number::NumberFormatter` instead of NumberFormat. * @param inLocale the given locale. * @param style whether to use short or long style. * @param status error code returned here. diff --git a/deps/icu-small/source/i18n/unicode/currpinf.h b/deps/icu-small/source/i18n/unicode/currpinf.h index 1a327c5bae0033..80b046251323e9 100644 --- a/deps/icu-small/source/i18n/unicode/currpinf.h +++ b/deps/icu-small/source/i18n/unicode/currpinf.h @@ -2,7 +2,7 @@ // License & terms of use: http://www.unicode.org/copyright.html /* ******************************************************************************* - * Copyright (C) 2009-2015, International Business Machines Corporation and * + * Copyright (C) 2009-2015, International Business Machines Corporation and * * others. All Rights Reserved. * ******************************************************************************* */ @@ -240,18 +240,27 @@ class U_I18N_API CurrencyPluralInfo : public UObject { /* * The plural rule is used to format currency plural name, * for example: "3.00 US Dollars". - * If there are 3 currency signs in the currency patttern, + * If there are 3 currency signs in the currency pattern, * the 3 currency signs will be replaced by currency plural name. */ PluralRules* fPluralRules; // locale Locale* fLocale; + +private: + /** + * An internal status variable used to indicate that the object is in an 'invalid' state. + * Used by copy constructor, the assignment operator and the clone method. + */ + UErrorCode fInternalStatus; }; inline UBool -CurrencyPluralInfo::operator!=(const CurrencyPluralInfo& info) const { return !operator==(info); } +CurrencyPluralInfo::operator!=(const CurrencyPluralInfo& info) const { + return !operator==(info); +} U_NAMESPACE_END diff --git a/deps/icu-small/source/i18n/unicode/currunit.h b/deps/icu-small/source/i18n/unicode/currunit.h index d5bc4aa6d6d482..48cadc10b704af 100644 --- a/deps/icu-small/source/i18n/unicode/currunit.h +++ b/deps/icu-small/source/i18n/unicode/currunit.h @@ -38,7 +38,7 @@ class U_I18N_API CurrencyUnit: public MeasureUnit { public: /** * Default constructor. Initializes currency code to "XXX" (no currency). - * @draft ICU 60 + * @stable ICU 60 */ CurrencyUnit(); @@ -59,17 +59,15 @@ class U_I18N_API CurrencyUnit: public MeasureUnit { */ CurrencyUnit(const CurrencyUnit& other); -#ifndef U_HIDE_DRAFT_API /** * Copy constructor from MeasureUnit. This constructor allows you to * restore a CurrencyUnit that was sliced to MeasureUnit. * * @param measureUnit The MeasureUnit to copy from. * @param ec Set to a failing value if the MeasureUnit is not a currency. - * @draft ICU 60 + * @stable ICU 60 */ CurrencyUnit(const MeasureUnit& measureUnit, UErrorCode &ec); -#endif /* U_HIDE_DRAFT_API */ /** * Assignment operator diff --git a/deps/icu-small/source/i18n/unicode/datefmt.h b/deps/icu-small/source/i18n/unicode/datefmt.h index c895183931546e..13c63d937675ea 100644 --- a/deps/icu-small/source/i18n/unicode/datefmt.h +++ b/deps/icu-small/source/i18n/unicode/datefmt.h @@ -43,13 +43,17 @@ U_NAMESPACE_BEGIN class TimeZone; class DateTimePatternGenerator; -// explicit template instantiation. see digitlst.h -// (When building DLLs for Windows this is required.) -#if U_PF_WINDOWS <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN +/** + * \cond + * Export an explicit template instantiation. (See digitlst.h, datefmt.h, and others.) + * (When building DLLs for Windows this is required.) + */ +#if U_PF_WINDOWS <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN && !defined(U_IN_DOXYGEN) template class U_I18N_API EnumSet; #endif +/** \endcond */ /** * DateFormat is an abstract class for a family of classes that convert dates and diff --git a/deps/icu-small/source/i18n/unicode/dcfmtsym.h b/deps/icu-small/source/i18n/unicode/dcfmtsym.h index 2f824cec3087f5..55e3d8a6b3b5ec 100644 --- a/deps/icu-small/source/i18n/unicode/dcfmtsym.h +++ b/deps/icu-small/source/i18n/unicode/dcfmtsym.h @@ -181,7 +181,6 @@ class U_I18N_API DecimalFormatSymbols : public UObject { */ DecimalFormatSymbols(const Locale& locale, UErrorCode& status); -#ifndef U_HIDE_DRAFT_API /** * Creates a DecimalFormatSymbols instance for the given locale with digits and symbols * corresponding to the given NumberingSystem. @@ -196,10 +195,9 @@ class U_I18N_API DecimalFormatSymbols : public UObject { * @param ns The numbering system. * @param status Input/output parameter, set to success or * failure code upon return. - * @draft ICU 60 + * @stable ICU 60 */ DecimalFormatSymbols(const Locale& locale, const NumberingSystem& ns, UErrorCode& status); -#endif /* U_HIDE_DRAFT_API */ /** * Create a DecimalFormatSymbols object for the default locale. @@ -406,7 +404,7 @@ class U_I18N_API DecimalFormatSymbols : public UObject { * returning a const reference to one of the symbol strings. * The returned reference becomes invalid when the symbol is changed * or when the DecimalFormatSymbols are destroyed. - * Note: moved #ifndef U_HIDE_INTERNAL_API after this, since this is needed for inline in DecimalFormat + * Note: moved \#ifndef U_HIDE_INTERNAL_API after this, since this is needed for inline in DecimalFormat * * This is not currently stable API, but if you think it should be stable, * post a comment on the following ticket and the ICU team will take a look: @@ -531,7 +529,7 @@ inline const UnicodeString& DecimalFormatSymbols::getConstDigitSymbol(int32_t di ENumberFormatSymbol key = static_cast(kOneDigitSymbol + digit - 1); return fSymbols[key]; } -#endif +#endif /* U_HIDE_INTERNAL_API */ // ------------------------------------- diff --git a/deps/icu-small/source/i18n/unicode/decimfmt.h b/deps/icu-small/source/i18n/unicode/decimfmt.h index 3747f510f79c79..b3a5cc0495f144 100644 --- a/deps/icu-small/source/i18n/unicode/decimfmt.h +++ b/deps/icu-small/source/i18n/unicode/decimfmt.h @@ -63,19 +63,22 @@ class NumberParserImpl; } } -// explicit template instantiation. see digitlst.h -// (When building DLLs for Windows this is required.) -#if U_PF_WINDOWS <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN +/** + * \cond + * explicit template instantiation. see digitlst.h + * (When building DLLs for Windows this is required.) + */ +#if U_PF_WINDOWS <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN && !defined(U_IN_DOXYGEN) template class U_I18N_API EnumSet; #endif +/** \endcond */ /** - *

    IMPORTANT: New users are strongly encouraged to see if + * **IMPORTANT:** New users are strongly encouraged to see if * numberformatter.h fits their use case. Although not deprecated, this header * is provided for backwards compatibility only. - *


    * * DecimalFormat is a concrete subclass of NumberFormat that formats decimal * numbers. It has a variety of features designed to make it possible to parse @@ -85,13 +88,13 @@ template class U_I18N_API EnumSetTo obtain a NumberFormat for a specific locale (including the default + * To obtain a NumberFormat for a specific locale (including the default * locale) call one of NumberFormat's factory methods such as * createInstance(). Do not call the DecimalFormat constructors directly, unless * you know what you are doing, since the NumberFormat factory methods may * return subclasses other than DecimalFormat. * - *

    Example Usage + * **Example Usage** * * \code * // Normally we would have a GUI with a menu for this @@ -135,11 +138,11 @@ template class U_I18N_API EnumSet - * Another example use createInstance(style) - *

    - *

    - * // Print out a number using the localized number, currency,
    + *
    + * **Another example use createInstance(style)**
    + *
    + * \code
    + * // Print out a number using the localized number, currency,
      * // percent, scientific, integer, iso currency, and plural currency
      * // format for each locale
      * Locale* locale = new Locale("en", "US");
    @@ -150,11 +153,13 @@ template class U_I18N_API    EnumSetformat(myNumber, str) << endl;
      *     format->parse(form->format(myNumber, str), fmtable, success);
    - * }
    + * delete form; + * } + * \endcode * * *

    Patterns @@ -690,7 +695,7 @@ class U_I18N_API DecimalFormat : public NumberFormat { * locale. *

    * NOTE: New users are strongly encouraged to use - * {@link NumberFormatter} instead of DecimalFormat. + * #icu::number::NumberFormatter instead of DecimalFormat. * @param status Output param set to success/failure code. If the * pattern is invalid this will be set to a failure code. * @stable ICU 2.0 @@ -708,7 +713,7 @@ class U_I18N_API DecimalFormat : public NumberFormat { * locale. *

    * NOTE: New users are strongly encouraged to use - * {@link NumberFormatter} instead of DecimalFormat. + * #icu::number::NumberFormatter instead of DecimalFormat. * @param pattern A non-localized pattern string. * @param status Output param set to success/failure code. If the * pattern is invalid this will be set to a failure code. @@ -728,7 +733,7 @@ class U_I18N_API DecimalFormat : public NumberFormat { * a NumberFormat factory method. *

    * NOTE: New users are strongly encouraged to use - * {@link NumberFormatter} instead of DecimalFormat. + * #icu::number::NumberFormatter instead of DecimalFormat. * * @param pattern a non-localized pattern string * @param symbolsToAdopt the set of symbols to be used. The caller should not @@ -782,7 +787,7 @@ class U_I18N_API DecimalFormat : public NumberFormat { * May return U_UNSUPPORTED_ERROR if this instance does not support * the specified attribute. * @param attr the attribute to set - * @param newvalue new value + * @param newValue new value * @param status the error type * @return *this - for chaining (example: format.setAttribute(...).setAttribute(...) ) * @stable ICU 51 @@ -839,7 +844,7 @@ class U_I18N_API DecimalFormat : public NumberFormat { * a NumberFormat factory method. *

    * NOTE: New users are strongly encouraged to use - * {@link NumberFormatter} instead of DecimalFormat. + * #icu::number::NumberFormatter instead of DecimalFormat. * * @param pattern a non-localized pattern string * @param symbolsToAdopt the set of symbols to be used. The caller should not @@ -864,7 +869,7 @@ class U_I18N_API DecimalFormat : public NumberFormat { * a NumberFormat factory method. *

    * NOTE: New users are strongly encouraged to use - * {@link NumberFormatter} instead of DecimalFormat. + * #icu::number::NumberFormatter instead of DecimalFormat. * * @param pattern a non-localized pattern string * @param symbols the set of symbols to be used @@ -986,6 +991,7 @@ class U_I18N_API DecimalFormat : public NumberFormat { * Result is appended to existing contents. * @param pos On input: an alignment field, if desired. * On output: the offsets of the alignment field. + * @param status Output param filled with success/failure status. * @return Reference to 'appendTo' parameter. * @internal */ @@ -1031,6 +1037,7 @@ class U_I18N_API DecimalFormat : public NumberFormat { * Result is appended to existing contents. * @param pos On input: an alignment field, if desired. * On output: the offsets of the alignment field. + * @param status Output param filled with success/failure status. * @return Reference to 'appendTo' parameter. * @internal */ @@ -1726,7 +1733,7 @@ class U_I18N_API DecimalFormat : public NumberFormat { virtual void setDecimalPatternMatchRequired(UBool newValue); /** - * {@icu} Returns whether to ignore exponents when parsing. + * Returns whether to ignore exponents when parsing. * * @see #setParseNoExponent * @internal This API is a technical preview. It may change in an upcoming release. @@ -1734,7 +1741,7 @@ class U_I18N_API DecimalFormat : public NumberFormat { virtual UBool isParseNoExponent() const; /** - * {@icu} Specifies whether to stop parsing when an exponent separator is encountered. For + * Specifies whether to stop parsing when an exponent separator is encountered. For * example, parses "123E4" to 123 (with parse position 3) instead of 1230000 (with parse position * 5). * @@ -1744,7 +1751,7 @@ class U_I18N_API DecimalFormat : public NumberFormat { virtual void setParseNoExponent(UBool value); /** - * {@icu} Returns whether parsing is sensitive to case (lowercase/uppercase). + * Returns whether parsing is sensitive to case (lowercase/uppercase). * * @see #setParseCaseSensitive * @internal This API is a technical preview. It may change in an upcoming release. @@ -1752,7 +1759,7 @@ class U_I18N_API DecimalFormat : public NumberFormat { virtual UBool isParseCaseSensitive() const; /** - * {@icu} Whether to pay attention to case when parsing; default is to ignore case (perform + * Whether to pay attention to case when parsing; default is to ignore case (perform * case-folding). For example, "A" == "a" in case-insensitive but not case-sensitive mode. * * Currency symbols are never case-folded. For example, "us$1.00" will not parse in case-insensitive @@ -1763,7 +1770,7 @@ class U_I18N_API DecimalFormat : public NumberFormat { virtual void setParseCaseSensitive(UBool value); /** - * {@icu} Returns whether truncation of high-order integer digits should result in an error. + * Returns whether truncation of high-order integer digits should result in an error. * By default, setMaximumIntegerDigits truncates high-order digits silently. * * @see setFormatFailIfMoreThanMaxDigits @@ -1772,7 +1779,7 @@ class U_I18N_API DecimalFormat : public NumberFormat { virtual UBool isFormatFailIfMoreThanMaxDigits() const; /** - * {@icu} Sets whether truncation of high-order integer digits should result in an error. + * Sets whether truncation of high-order integer digits should result in an error. * By default, setMaximumIntegerDigits truncates high-order digits silently. * * @internal This API is a technical preview. It may change in an upcoming release. @@ -2017,16 +2024,17 @@ class U_I18N_API DecimalFormat : public NumberFormat { virtual void setCurrency(const char16_t* theCurrency); /** - * Sets the Currency Context object used to display currency. + * Sets the `Currency Usage` object used to display currency. * This takes effect immediately, if this format is a * currency format. - * @param currencyContext new currency context object to use. + * @param newUsage new currency usage object to use. + * @param ec input-output error code * @stable ICU 54 */ void setCurrencyUsage(UCurrencyUsage newUsage, UErrorCode* ec); /** - * Returns the Currency Context object used to display currency + * Returns the `Currency Usage` object used to display currency * @stable ICU 54 */ UCurrencyUsage getCurrencyUsage() const; @@ -2050,7 +2058,7 @@ class U_I18N_API DecimalFormat : public NumberFormat { void formatToDecimalQuantity(const Formattable& number, number::impl::DecimalQuantity& output, UErrorCode& status) const; -#endif +#endif /* U_HIDE_INTERNAL_API */ #ifndef U_HIDE_DRAFT_API /** @@ -2072,7 +2080,6 @@ class U_I18N_API DecimalFormat : public NumberFormat { * FormattedNumber result = df->toNumberFormatter().formatDouble(123, status); * * - * @param output The variable into which to store the LocalizedNumberFormatter. * @return The output variable, for chaining. * @draft ICU 62 */ diff --git a/deps/icu-small/source/i18n/unicode/dtptngen.h b/deps/icu-small/source/i18n/unicode/dtptngen.h index feb465e7997401..26ccc64060f15a 100644 --- a/deps/icu-small/source/i18n/unicode/dtptngen.h +++ b/deps/icu-small/source/i18n/unicode/dtptngen.h @@ -498,27 +498,23 @@ class U_I18N_API DateTimePatternGenerator : public UObject { private: /** * Constructor. - * @stable ICU 3.8 */ DateTimePatternGenerator(UErrorCode & status); /** * Constructor. - * @stable ICU 3.8 */ DateTimePatternGenerator(const Locale& locale, UErrorCode & status); /** * Copy constructor. * @param other DateTimePatternGenerator to copy - * @stable ICU 3.8 */ DateTimePatternGenerator(const DateTimePatternGenerator& other); /** * Default assignment operator. * @param other DateTimePatternGenerator to copy - * @stable ICU 3.8 */ DateTimePatternGenerator& operator=(const DateTimePatternGenerator& other); @@ -542,6 +538,11 @@ class U_I18N_API DateTimePatternGenerator : public UObject { int32_t fAllowedHourFormats[7]; // Actually an array of AllowedHourFormat enum type, ending with UNKNOWN. + // Internal error code used for recording/reporting errors that occur during methods that do not + // have a UErrorCode parameter. For example: the Copy Constructor, or the ::clone() method. + // When this is set to an error the object is in an invalid state. + UErrorCode internalErrorCode; + /* internal flags masks for adjustFieldTypes etc. */ enum { kDTPGNoFlags = 0, @@ -569,11 +570,10 @@ class U_I18N_API DateTimePatternGenerator : public UObject { #endif // U_HIDE_DRAFT_API void getAppendName(UDateTimePatternField field, UnicodeString& value); UnicodeString mapSkeletonMetacharacters(const UnicodeString& patternForm, int32_t* flags, UErrorCode& status); - int32_t getCanonicalIndex(const UnicodeString& field); - const UnicodeString* getBestRaw(DateTimeMatcher& source, int32_t includeMask, DistanceInfo* missingFields, const PtnSkeleton** specifiedSkeletonPtr = 0); + const UnicodeString* getBestRaw(DateTimeMatcher& source, int32_t includeMask, DistanceInfo* missingFields, UErrorCode& status, const PtnSkeleton** specifiedSkeletonPtr = 0); UnicodeString adjustFieldTypes(const UnicodeString& pattern, const PtnSkeleton* specifiedSkeleton, int32_t flags, UDateTimePatternMatchOptions options = UDATPG_MATCH_NO_OPTIONS); - UnicodeString getBestAppending(int32_t missingFields, int32_t flags, UDateTimePatternMatchOptions options = UDATPG_MATCH_NO_OPTIONS); - int32_t getTopBitNumber(int32_t foundMask); + UnicodeString getBestAppending(int32_t missingFields, int32_t flags, UErrorCode& status, UDateTimePatternMatchOptions options = UDATPG_MATCH_NO_OPTIONS); + int32_t getTopBitNumber(int32_t foundMask) const; void setAvailableFormat(const UnicodeString &key, UErrorCode& status); UBool isAvailableFormatSet(const UnicodeString &key) const; void copyHashtable(Hashtable *other, UErrorCode &status); diff --git a/deps/icu-small/source/i18n/unicode/fmtable.h b/deps/icu-small/source/i18n/unicode/fmtable.h index 2359b61d46186e..a06c23dc3bd532 100644 --- a/deps/icu-small/source/i18n/unicode/fmtable.h +++ b/deps/icu-small/source/i18n/unicode/fmtable.h @@ -658,7 +658,7 @@ class U_I18N_API Formattable : public UObject { /** * Adopt, and set value from, a DecimalQuantity * Internal Function, do not use. - * @param dl the DecimalQuantity to be adopted + * @param dq the DecimalQuantity to be adopted * @internal */ void adoptDecimalQuantity(number::impl::DecimalQuantity *dq); diff --git a/deps/icu-small/source/i18n/unicode/gender.h b/deps/icu-small/source/i18n/unicode/gender.h index 467b64ec5ebad0..b7c31cb554a696 100644 --- a/deps/icu-small/source/i18n/unicode/gender.h +++ b/deps/icu-small/source/i18n/unicode/gender.h @@ -18,6 +18,11 @@ #ifndef _GENDER #define _GENDER +/** + * \file + * \brief C++ API: GenderInfo computes the gender of a list. + */ + #include "unicode/utypes.h" #if !UCONFIG_NO_FORMATTING @@ -30,7 +35,7 @@ class GenderInfoTest; U_NAMESPACE_BEGIN -// Forward Declaration +/** \internal Forward Declaration */ void U_CALLCONV GenderInfo_initCache(UErrorCode &status); /** diff --git a/deps/icu-small/source/common/unicode/listformatter.h b/deps/icu-small/source/i18n/unicode/listformatter.h similarity index 79% rename from deps/icu-small/source/common/unicode/listformatter.h rename to deps/icu-small/source/i18n/unicode/listformatter.h index 180fbcb5cde5b7..5e36cf71cc54b7 100644 --- a/deps/icu-small/source/common/unicode/listformatter.h +++ b/deps/icu-small/source/i18n/unicode/listformatter.h @@ -26,6 +26,9 @@ U_NAMESPACE_BEGIN +class FieldPositionIterator; +class FieldPositionHandler; + /** @internal */ class Hashtable; @@ -33,7 +36,10 @@ class Hashtable; struct ListFormatInternal; /* The following can't be #ifndef U_HIDE_INTERNAL_API, needed for other .h file declarations */ -/** @internal */ +/** + * @internal + * \cond + */ struct ListFormatData : public UMemory { UnicodeString twoPattern; UnicodeString startPattern; @@ -43,6 +49,7 @@ struct ListFormatData : public UMemory { ListFormatData(const UnicodeString& two, const UnicodeString& start, const UnicodeString& middle, const UnicodeString& end) : twoPattern(two), startPattern(start), middlePattern(middle), endPattern(end) {} }; +/** \endcond */ /** @@ -61,7 +68,7 @@ struct ListFormatData : public UMemory { * The ListFormatter class is not intended for public subclassing. * @stable ICU 50 */ -class U_COMMON_API ListFormatter : public UObject{ +class U_I18N_API ListFormatter : public UObject{ public: @@ -133,6 +140,27 @@ class U_COMMON_API ListFormatter : public UObject{ UnicodeString& format(const UnicodeString items[], int32_t n_items, UnicodeString& appendTo, UErrorCode& errorCode) const; +#ifndef U_HIDE_DRAFT_API + /** + * Format a list of strings. + * + * @param items An array of strings to be combined and formatted. + * @param n_items Length of the array items. + * @param appendTo The string to which the formatted result will be + * appended. + * @param posIter On return, can be used to iterate over positions of + * fields generated by this format call. Field values are + * defined in UListFormatterField. Can be NULL. + * @param errorCode ICU error code returned here. + * @return Formatted string combining the elements of items, + * appended to appendTo. + * @draft ICU 63 + */ + UnicodeString& format(const UnicodeString items[], int32_t n_items, + UnicodeString & appendTo, FieldPositionIterator* posIter, + UErrorCode& errorCode) const; +#endif /* U_HIDE_DRAFT_API */ + #ifndef U_HIDE_INTERNAL_API /** @internal for MeasureFormat @@ -160,6 +188,10 @@ class U_COMMON_API ListFormatter : public UObject{ struct ListPatternsSink; static ListFormatInternal* loadListFormatInternal(const Locale& locale, const char* style, UErrorCode& errorCode); + UnicodeString& format_( + const UnicodeString items[], int32_t n_items, UnicodeString& appendTo, + int32_t index, int32_t &offset, FieldPositionHandler* handler, UErrorCode& errorCode) const; + ListFormatter(); ListFormatInternal* owned; diff --git a/deps/icu-small/source/i18n/unicode/measfmt.h b/deps/icu-small/source/i18n/unicode/measfmt.h index 14399dd59a700a..bbdd2364bdd997 100644 --- a/deps/icu-small/source/i18n/unicode/measfmt.h +++ b/deps/icu-small/source/i18n/unicode/measfmt.h @@ -104,7 +104,7 @@ class U_I18N_API MeasureFormat : public Format { * Constructor. *

    * NOTE: New users are strongly encouraged to use - * {@link NumberFormatter} instead of NumberFormat. + * {@link icu::number::NumberFormatter} instead of NumberFormat. * @stable ICU 53 */ MeasureFormat( @@ -114,7 +114,7 @@ class U_I18N_API MeasureFormat : public Format { * Constructor. *

    * NOTE: New users are strongly encouraged to use - * {@link NumberFormatter} instead of NumberFormat. + * {@link icu::number::NumberFormatter} instead of NumberFormat. * @stable ICU 53 */ MeasureFormat( @@ -202,7 +202,7 @@ class U_I18N_API MeasureFormat : public Format { * formatted string is 3.5 meters per second. * @param measure The measure object. In above example, 3.5 meters. * @param perUnit The per unit. In above example, it is - * *MeasureUnit::createSecond(status). + * `*%MeasureUnit::createSecond(status)`. * @param appendTo formatted string appended here. * @param pos the field position. * @param status the error. @@ -223,7 +223,7 @@ class U_I18N_API MeasureFormat : public Format { * @param unit The unit for which to get a display name. * @param status the error. * @return The display name in the locale and width specified in - * {@link MeasureFormat#getInstance}, or null if there is no display name available + * the MeasureFormat constructor, or null if there is no display name available * for the specified unit. * * @stable ICU 58 @@ -236,7 +236,7 @@ class U_I18N_API MeasureFormat : public Format { * locale. *

    * NOTE: New users are strongly encouraged to use - * {@link NumberFormatter} instead of NumberFormat. + * {@link icu::number::NumberFormatter} instead of NumberFormat. * @param locale desired locale * @param ec input-output error code * @return a formatter object, or NULL upon error @@ -250,7 +250,7 @@ class U_I18N_API MeasureFormat : public Format { * locale. *

    * NOTE: New users are strongly encouraged to use - * {@link NumberFormatter} instead of NumberFormat. + * {@link icu::number::NumberFormatter} instead of NumberFormat. * @param ec input-output error code * @return a formatter object, or NULL upon error * @stable ICU 3.0 @@ -348,7 +348,7 @@ class U_I18N_API MeasureFormat : public Format { const MeasureFormatCacheData *cache; const SharedNumberFormat *numberFormat; const SharedPluralRules *pluralRules; - UMeasureFormatWidth width; + UMeasureFormatWidth fWidth; // Declared outside of MeasureFormatSharedData because ListFormatter // objects are relatively cheap to copy; therefore, they don't need to be diff --git a/deps/icu-small/source/i18n/unicode/measunit.h b/deps/icu-small/source/i18n/unicode/measunit.h index f552253544f890..676fdeb9c8cd8a 100644 --- a/deps/icu-small/source/i18n/unicode/measunit.h +++ b/deps/icu-small/source/i18n/unicode/measunit.h @@ -368,6 +368,26 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createPartPerMillion(UErrorCode &status); +#ifndef U_HIDE_DRAFT_API + /** + * Returns unit of concentr: percent. + * Caller owns returned value and must free it. + * @param status ICU error code. + * @draft ICU 63 + */ + static MeasureUnit *createPercent(UErrorCode &status); +#endif /* U_HIDE_DRAFT_API */ + +#ifndef U_HIDE_DRAFT_API + /** + * Returns unit of concentr: permille. + * Caller owns returned value and must free it. + * @param status ICU error code. + * @draft ICU 63 + */ + static MeasureUnit *createPermille(UErrorCode &status); +#endif /* U_HIDE_DRAFT_API */ + /** * Returns unit of consumption: liter-per-100kilometers. * Caller owns returned value and must free it. @@ -464,6 +484,16 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createMegabyte(UErrorCode &status); +#ifndef U_HIDE_DRAFT_API + /** + * Returns unit of digital: petabyte. + * Caller owns returned value and must free it. + * @param status ICU error code. + * @draft ICU 63 + */ + static MeasureUnit *createPetabyte(UErrorCode &status); +#endif /* U_HIDE_DRAFT_API */ + /** * Returns unit of digital: terabit. * Caller owns returned value and must free it. @@ -984,6 +1014,16 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createWatt(UErrorCode &status); +#ifndef U_HIDE_DRAFT_API + /** + * Returns unit of pressure: atmosphere. + * Caller owns returned value and must free it. + * @param status ICU error code. + * @draft ICU 63 + */ + static MeasureUnit *createAtmosphere(UErrorCode &status); +#endif /* U_HIDE_DRAFT_API */ + /** * Returns unit of pressure: hectopascal. * Caller owns returned value and must free it. diff --git a/deps/icu-small/source/i18n/unicode/msgfmt.h b/deps/icu-small/source/i18n/unicode/msgfmt.h index fef80107747bf8..074d93354000ef 100644 --- a/deps/icu-small/source/i18n/unicode/msgfmt.h +++ b/deps/icu-small/source/i18n/unicode/msgfmt.h @@ -124,7 +124,7 @@ class NumberFormat; * argNumber = '0' | ('1'..'9' ('0'..'9')*) * * argType = "number" | "date" | "time" | "spellout" | "ordinal" | "duration" - * argStyle = "short" | "medium" | "long" | "full" | "integer" | "currency" | "percent" | argStyleText + * argStyle = "short" | "medium" | "long" | "full" | "integer" | "currency" | "percent" | argStyleText | "::" argSkeletonText * * *

      @@ -166,7 +166,7 @@ class NumberFormat; * (none) * null * - * number + * number * (none) * NumberFormat.createInstance(getLocale(), status) * @@ -182,6 +182,9 @@ class NumberFormat; * argStyleText * new DecimalFormat(argStyleText, new DecimalFormatSymbols(getLocale(), status), status) * + * argSkeletonText + * NumberFormatter::forSkeleton(argSkeletonText, status).locale(getLocale()).toFormat(status) + * * date * (none) * DateFormat.createDateInstance(kDefault, getLocale(), status) @@ -199,7 +202,7 @@ class NumberFormat; * DateFormat.createDateInstance(kFull, getLocale(), status) * * argStyleText - * new SimpleDateFormat(argStyleText, getLocale(), status) + * new SimpleDateFormat(argStyleText, getLocale(), status) * * time * (none) @@ -218,7 +221,7 @@ class NumberFormat; * DateFormat.createTimeInstance(kFull, getLocale(), status) * * argStyleText - * new SimpleDateFormat(argStyleText, getLocale(), status) + * new SimpleDateFormat(argStyleText, getLocale(), status) * * spellout * argStyleText (optional) diff --git a/deps/icu-small/source/i18n/unicode/numberformatter.h b/deps/icu-small/source/i18n/unicode/numberformatter.h index 3ab08319f73bc7..469949a2878eb4 100644 --- a/deps/icu-small/source/i18n/unicode/numberformatter.h +++ b/deps/icu-small/source/i18n/unicode/numberformatter.h @@ -144,11 +144,31 @@ class MultiplierFormatHandler; class CurrencySymbols; class GeneratorHelpers; class DecNum; +class NumberRangeFormatterImpl; +struct RangeMacroProps; + +/** + * Used for NumberRangeFormatter and implemented in numrange_fluent.cpp. + * Declared here so it can be friended. + * + * @internal + */ +void touchRangeLocales(impl::RangeMacroProps& macros); } // namespace impl -// Reserve extra names in case they are added as classes in the future: +/** + * Extra name reserved in case it is needed in the future. + * + * @draft ICU 63 + */ typedef Notation CompactNotation; + +/** + * Extra name reserved in case it is needed in the future. + * + * @draft ICU 63 + */ typedef Notation SimpleNotation; /** @@ -308,10 +328,15 @@ class U_I18N_API Notation : public UMemory { union NotationUnion { // For NTN_SCIENTIFIC + /** @internal */ struct ScientificSettings { + /** @internal */ int8_t fEngineeringInterval; + /** @internal */ bool fRequireMinInt; + /** @internal */ impl::digits_t fMinExponentDigits; + /** @internal */ UNumberSignDisplay fExponentSignDisplay; } scientific; @@ -407,15 +432,39 @@ class U_I18N_API ScientificNotation : public Notation { friend class impl::NumberPropertyMapper; }; -// Reserve extra names in case they are added as classes in the future: +/** + * Extra name reserved in case it is needed in the future. + * + * @draft ICU 63 + */ typedef Precision SignificantDigitsPrecision; // Typedefs for ICU 60/61 compatibility. // These will be removed in ICU 64. // See http://bugs.icu-project.org/trac/ticket/13746 + +/** + * This will be removed in ICU 64. See ICU-13746. + * @deprecated ICU 63 + */ typedef Precision Rounder; + +/** + * This will be removed in ICU 64. See ICU-13746. + * @deprecated ICU 63 + */ typedef FractionPrecision FractionRounder; + +/** + * This will be removed in ICU 64. See ICU-13746. + * @deprecated ICU 63 + */ typedef IncrementPrecision IncrementRounder; + +/** + * This will be removed in ICU 64. See ICU-13746. + * @deprecated ICU 63 + */ typedef CurrencyPrecision CurrencyRounder; /** @@ -672,16 +721,25 @@ class U_I18N_API Precision : public UMemory { } fType; union PrecisionUnion { + /** @internal */ struct FractionSignificantSettings { // For RND_FRACTION, RND_SIGNIFICANT, and RND_FRACTION_SIGNIFICANT + /** @internal */ impl::digits_t fMinFrac; + /** @internal */ impl::digits_t fMaxFrac; + /** @internal */ impl::digits_t fMinSig; + /** @internal */ impl::digits_t fMaxSig; } fracSig; + /** @internal */ struct IncrementSettings { + /** @internal */ double fIncrement; + /** @internal */ impl::digits_t fMinFrac; + /** @internal */ impl::digits_t fMaxFrac; } increment; // For RND_INCREMENT UCurrencyUsage currencyUsage; // For RND_CURRENCY @@ -1205,7 +1263,7 @@ class U_I18N_API Grouper : public UMemory { public: #ifndef U_HIDE_INTERNAL_API /** @internal */ - static Grouper forStrategy(UGroupingStrategy grouping); + static Grouper forStrategy(UNumberGroupingStrategy grouping); /** * Resolve the values in Properties to a Grouper object. @@ -1216,7 +1274,7 @@ class U_I18N_API Grouper : public UMemory { // Future: static Grouper forProperties(DecimalFormatProperties& properties); /** @internal */ - Grouper(int16_t grouping1, int16_t grouping2, int16_t minGrouping, UGroupingStrategy strategy) + Grouper(int16_t grouping1, int16_t grouping2, int16_t minGrouping, UNumberGroupingStrategy strategy) : fGrouping1(grouping1), fGrouping2(grouping2), fMinGrouping(minGrouping), @@ -1251,10 +1309,10 @@ class U_I18N_API Grouper : public UMemory { int16_t fMinGrouping; /** - * The UGroupingStrategy that was used to create this Grouper, or UNUM_GROUPING_COUNT if this - * was not created from a UGroupingStrategy. + * The UNumberGroupingStrategy that was used to create this Grouper, or UNUM_GROUPING_COUNT if this + * was not created from a UNumberGroupingStrategy. */ - UGroupingStrategy fStrategy; + UNumberGroupingStrategy fStrategy; Grouper() : fGrouping1(-3) {}; @@ -1423,7 +1481,8 @@ struct U_I18N_API MacroProps : public UMemory { /** * An abstract base class for specifying settings related to number formatting. This class is implemented by - * {@link UnlocalizedNumberFormatter} and {@link LocalizedNumberFormatter}. + * {@link UnlocalizedNumberFormatter} and {@link LocalizedNumberFormatter}. This class is not intended for + * public subclassing. */ template class U_I18N_API NumberFormatterSettings { @@ -1710,7 +1769,7 @@ class U_I18N_API NumberFormatterSettings { * The exact grouping widths will be chosen based on the locale. * *

      - * Pass this method an element from the {@link UGroupingStrategy} enum. For example: + * Pass this method an element from the {@link UNumberGroupingStrategy} enum. For example: * *

            * NumberFormatter::with().grouping(UNUM_GROUPING_MIN2)
      @@ -1724,7 +1783,7 @@ class U_I18N_API NumberFormatterSettings {
            * @return The fluent chain.
            * @draft ICU 61
            */
      -    Derived grouping(UGroupingStrategy strategy) const &;
      +    Derived grouping(UNumberGroupingStrategy strategy) const &;
       
           /**
            * Overload of grouping() for use on an rvalue reference.
      @@ -1733,10 +1792,9 @@ class U_I18N_API NumberFormatterSettings {
            *            The grouping strategy to use.
            * @return The fluent chain.
            * @see #grouping
      -     * @provisional This API might change or be removed in a future release.
            * @draft ICU 62
            */
      -    Derived grouping(UGroupingStrategy strategy) &&;
      +    Derived grouping(UNumberGroupingStrategy strategy) &&;
       
           /**
            * Specifies the minimum and maximum number of digits to render before the decimal mark.
      @@ -1748,7 +1806,7 @@ class U_I18N_API NumberFormatterSettings {
            * 
    * *

    - * Pass this method the return value of {@link IntegerWidth#zeroFillTo(int)}. For example: + * Pass this method the return value of {@link IntegerWidth#zeroFillTo}. For example: * *

          * NumberFormatter::with().integerWidth(IntegerWidth::zeroFillTo(2))
    @@ -2099,15 +2157,18 @@ class U_I18N_API NumberFormatterSettings {
     
         // NOTE: Uses default copy and move constructors.
     
    -  protected:
    +  private:
         impl::MacroProps fMacros;
     
    -  private:
         // Don't construct me directly!  Use (Un)LocalizedNumberFormatter.
         NumberFormatterSettings() = default;
     
         friend class LocalizedNumberFormatter;
         friend class UnlocalizedNumberFormatter;
    +
    +    // Give NumberRangeFormatter access to the MacroProps
    +    friend void impl::touchRangeLocales(impl::RangeMacroProps& macros);
    +    friend class impl::NumberRangeFormatterImpl;
     };
     
     /**
    @@ -2124,13 +2185,6 @@ class U_I18N_API UnlocalizedNumberFormatter
          * Associate the given locale with the number formatter. The locale is used for picking the appropriate symbols,
          * formats, and other data for number display.
          *
    -     * 

    - * To use the Java default locale, call Locale::getDefault(): - * - *

    -     * NumberFormatter::with(). ... .locale(Locale::getDefault())
    -     * 
    - * * @param locale * The locale to use when loading data for number formatting. * @return The fluent chain. @@ -2156,7 +2210,6 @@ class U_I18N_API UnlocalizedNumberFormatter */ UnlocalizedNumberFormatter() = default; - // Make default copy constructor call the NumberFormatterSettings copy constructor. /** * Returns a copy of this UnlocalizedNumberFormatter. * @draft ICU 60 @@ -2271,7 +2324,7 @@ class U_I18N_API LocalizedNumberFormatter */ int32_t getCallCount() const; -#endif +#endif /* U_HIDE_INTERNAL_API */ /** * Creates a representation of this LocalizedNumberFormat as an icu::Format, enabling the use @@ -2295,7 +2348,6 @@ class U_I18N_API LocalizedNumberFormatter */ LocalizedNumberFormatter() = default; - // Make default copy constructor call the NumberFormatterSettings copy constructor. /** * Returns a copy of this LocalizedNumberFormatter. * @draft ICU 60 @@ -2333,11 +2385,12 @@ class U_I18N_API LocalizedNumberFormatter * * @param results * The results object. This method will mutate it to save the results. + * @param status * @internal */ void formatImpl(impl::UFormattedNumberData *results, UErrorCode &status) const; -#endif +#endif /* U_HIDE_INTERNAL_API */ /** * Destruct this LocalizedNumberFormatter, cleaning up any memory it might own. @@ -2359,6 +2412,8 @@ class U_I18N_API LocalizedNumberFormatter LocalizedNumberFormatter(impl::MacroProps &¯os, const Locale &locale); + void clear(); + void lnfMoveHelper(LocalizedNumberFormatter&& src); /** @@ -2430,7 +2485,7 @@ class U_I18N_API FormattedNumber : public UMemory { * @draft ICU 62 * @see Appendable */ - Appendable &appendTo(Appendable &appendable, UErrorCode& status); + Appendable &appendTo(Appendable &appendable, UErrorCode& status) const; #ifndef U_HIDE_DEPRECATED_API /** @@ -2457,9 +2512,9 @@ class U_I18N_API FormattedNumber : public UMemory { #endif /* U_HIDE_DEPRECATED_API */ /** - * Determines the start and end indices of the next occurrence of the given field in the - * output string. This allows you to determine the locations of, for example, the integer part, - * fraction part, or symbols. + * Determines the start (inclusive) and end (exclusive) indices of the next occurrence of the given + * field in the output string. This allows you to determine the locations of, for example, + * the integer part, fraction part, or symbols. * * If a field occurs just once, calling this method will find that occurrence and return it. If a * field occurs multiple times, this method may be called repeatedly with the following pattern: @@ -2478,7 +2533,7 @@ class U_I18N_API FormattedNumber : public UMemory { * Input+output variable. On input, the "field" property determines which field to look * up, and the "beginIndex" and "endIndex" properties determine where to begin the search. * On output, the "beginIndex" is set to the beginning of the first occurrence of the - * field with either begin or end indices after the input indices, "endIndex" is set to + * field with either begin or end indices after the input indices; "endIndex" is set to * the end of that occurrence of the field (exclusive index). If a field position is not * found, the method returns FALSE and the FieldPosition may or may not be changed. * @param status @@ -2537,7 +2592,7 @@ class U_I18N_API FormattedNumber : public UMemory { */ void getAllFieldPositionsImpl(FieldPositionIteratorHandler& fpih, UErrorCode& status) const; -#endif +#endif /* U_HIDE_INTERNAL_API */ /** * Copying not supported; use move constructor instead. diff --git a/deps/icu-small/source/i18n/unicode/numberrangeformatter.h b/deps/icu-small/source/i18n/unicode/numberrangeformatter.h new file mode 100644 index 00000000000000..3e6248d934de61 --- /dev/null +++ b/deps/icu-small/source/i18n/unicode/numberrangeformatter.h @@ -0,0 +1,866 @@ +// © 2018 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html + +#if !UCONFIG_NO_FORMATTING +#ifndef __NUMBERRANGEFORMATTER_H__ +#define __NUMBERRANGEFORMATTER_H__ + +#include +#include "unicode/appendable.h" +#include "unicode/fieldpos.h" +#include "unicode/fpositer.h" +#include "unicode/numberformatter.h" + +#ifndef U_HIDE_DRAFT_API + +/** + * \file + * \brief C++ API: Library for localized formatting of number, currency, and unit ranges. + * + * The main entrypoint to the formatting of ranges of numbers, including currencies and other units of measurement. + *

    + * Usage example: + *

    + *

    + * NumberRangeFormatter::with()
    + *     .identityFallback(UNUM_IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE)
    + *     .numberFormatterFirst(NumberFormatter::with().adoptUnit(MeasureUnit::createMeter()))
    + *     .numberFormatterSecond(NumberFormatter::with().adoptUnit(MeasureUnit::createKilometer()))
    + *     .locale("en-GB")
    + *     .formatRange(750, 1.2, status)
    + *     .toString(status);
    + * // => "750 m - 1.2 km"
    + * 
    + *

    + * Like NumberFormatter, NumberRangeFormatter instances are immutable and thread-safe. This API is based on the + * fluent design pattern popularized by libraries such as Google's Guava. + * + * @author Shane Carr + */ + + +/** + * Defines how to merge fields that are identical across the range sign. + * + * @draft ICU 63 + */ +typedef enum UNumberRangeCollapse { + /** + * Use locale data and heuristics to determine how much of the string to collapse. Could end up collapsing none, + * some, or all repeated pieces in a locale-sensitive way. + * + * The heuristics used for this option are subject to change over time. + * + * @draft ICU 63 + */ + UNUM_RANGE_COLLAPSE_AUTO, + + /** + * Do not collapse any part of the number. Example: "3.2 thousand kilograms – 5.3 thousand kilograms" + * + * @draft ICU 63 + */ + UNUM_RANGE_COLLAPSE_NONE, + + /** + * Collapse the unit part of the number, but not the notation, if present. Example: "3.2 thousand – 5.3 thousand + * kilograms" + * + * @draft ICU 63 + */ + UNUM_RANGE_COLLAPSE_UNIT, + + /** + * Collapse any field that is equal across the range sign. May introduce ambiguity on the magnitude of the + * number. Example: "3.2 – 5.3 thousand kilograms" + * + * @draft ICU 63 + */ + UNUM_RANGE_COLLAPSE_ALL +} UNumberRangeCollapse; + +/** + * Defines the behavior when the two numbers in the range are identical after rounding. To programmatically detect + * when the identity fallback is used, compare the lower and upper BigDecimals via FormattedNumber. + * + * @draft ICU 63 + * @see NumberRangeFormatter + */ +typedef enum UNumberRangeIdentityFallback { + /** + * Show the number as a single value rather than a range. Example: "$5" + * + * @draft ICU 63 + */ + UNUM_IDENTITY_FALLBACK_SINGLE_VALUE, + + /** + * Show the number using a locale-sensitive approximation pattern. If the numbers were the same before rounding, + * show the single value. Example: "~$5" or "$5" + * + * @draft ICU 63 + */ + UNUM_IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE, + + /** + * Show the number using a locale-sensitive approximation pattern. Use the range pattern always, even if the + * inputs are the same. Example: "~$5" + * + * @draft ICU 63 + */ + UNUM_IDENTITY_FALLBACK_APPROXIMATELY, + + /** + * Show the number as the range of two equal values. Use the range pattern always, even if the inputs are the + * same. Example (with RangeCollapse.NONE): "$5 – $5" + * + * @draft ICU 63 + */ + UNUM_IDENTITY_FALLBACK_RANGE +} UNumberRangeIdentityFallback; + +/** + * Used in the result class FormattedNumberRange to indicate to the user whether the numbers formatted in the range + * were equal or not, and whether or not the identity fallback was applied. + * + * @draft ICU 63 + * @see NumberRangeFormatter + */ +typedef enum UNumberRangeIdentityResult { + /** + * Used to indicate that the two numbers in the range were equal, even before any rounding rules were applied. + * + * @draft ICU 63 + * @see NumberRangeFormatter + */ + UNUM_IDENTITY_RESULT_EQUAL_BEFORE_ROUNDING, + + /** + * Used to indicate that the two numbers in the range were equal, but only after rounding rules were applied. + * + * @draft ICU 63 + * @see NumberRangeFormatter + */ + UNUM_IDENTITY_RESULT_EQUAL_AFTER_ROUNDING, + + /** + * Used to indicate that the two numbers in the range were not equal, even after rounding rules were applied. + * + * @draft ICU 63 + * @see NumberRangeFormatter + */ + UNUM_IDENTITY_RESULT_NOT_EQUAL, + +#ifndef U_HIDE_INTERNAL_API + /** + * The number of entries in this enum. + * @internal + */ + UNUM_IDENTITY_RESULT_COUNT +#endif + +} UNumberRangeIdentityResult; + +U_NAMESPACE_BEGIN + +namespace number { // icu::number + +// Forward declarations: +class UnlocalizedNumberRangeFormatter; +class LocalizedNumberRangeFormatter; +class FormattedNumberRange; + +namespace impl { + +// Forward declarations: +struct RangeMacroProps; +class DecimalQuantity; +struct UFormattedNumberRangeData; +class NumberRangeFormatterImpl; + +} // namespace impl + +/** + * \cond + * Export an explicit template instantiation. See datefmt.h + * (When building DLLs for Windows this is required.) + */ +#if U_PF_WINDOWS <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN && !defined(U_IN_DOXYGEN) +template struct U_I18N_API std::atomic; +#endif +/** \endcond */ + +// Other helper classes would go here, but there are none. + +namespace impl { // icu::number::impl + +// Do not enclose entire MacroProps with #ifndef U_HIDE_INTERNAL_API, needed for a protected field +/** @internal */ +struct U_I18N_API RangeMacroProps : public UMemory { + /** @internal */ + UnlocalizedNumberFormatter formatter1; // = NumberFormatter::with(); + + /** @internal */ + UnlocalizedNumberFormatter formatter2; // = NumberFormatter::with(); + + /** @internal */ + bool singleFormatter = true; + + /** @internal */ + UNumberRangeCollapse collapse = UNUM_RANGE_COLLAPSE_AUTO; + + /** @internal */ + UNumberRangeIdentityFallback identityFallback = UNUM_IDENTITY_FALLBACK_APPROXIMATELY; + + /** @internal */ + Locale locale; + + // NOTE: Uses default copy and move constructors. + + /** + * Check all members for errors. + * @internal + */ + bool copyErrorTo(UErrorCode &status) const { + return formatter1.copyErrorTo(status) || formatter2.copyErrorTo(status); + } +}; + +} // namespace impl + +/** + * An abstract base class for specifying settings related to number formatting. This class is implemented by + * {@link UnlocalizedNumberRangeFormatter} and {@link LocalizedNumberRangeFormatter}. This class is not intended for + * public subclassing. + */ +template +class U_I18N_API NumberRangeFormatterSettings { + public: + /** + * Sets the NumberFormatter instance to use for the numbers in the range. The same formatter is applied to both + * sides of the range. + *

    + * The NumberFormatter instances must not have a locale applied yet; the locale specified on the + * NumberRangeFormatter will be used. + * + * @param formatter + * The formatter to use for both numbers in the range. + * @return The fluent chain. + * @draft ICU 63 + */ + Derived numberFormatterBoth(const UnlocalizedNumberFormatter &formatter) const &; + + /** + * Overload of numberFormatterBoth() for use on an rvalue reference. + * + * @param formatter + * The formatter to use for both numbers in the range. + * @return The fluent chain. + * @see #numberFormatterBoth + * @draft ICU 63 + */ + Derived numberFormatterBoth(const UnlocalizedNumberFormatter &formatter) &&; + + /** + * Overload of numberFormatterBoth() for use on an rvalue reference. + * + * @param formatter + * The formatter to use for both numbers in the range. + * @return The fluent chain. + * @see #numberFormatterBoth + * @draft ICU 63 + */ + Derived numberFormatterBoth(UnlocalizedNumberFormatter &&formatter) const &; + + /** + * Overload of numberFormatterBoth() for use on an rvalue reference. + * + * @param formatter + * The formatter to use for both numbers in the range. + * @return The fluent chain. + * @see #numberFormatterBoth + * @draft ICU 63 + */ + Derived numberFormatterBoth(UnlocalizedNumberFormatter &&formatter) &&; + + /** + * Sets the NumberFormatter instance to use for the first number in the range. + *

    + * The NumberFormatter instances must not have a locale applied yet; the locale specified on the + * NumberRangeFormatter will be used. + * + * @param formatterFirst + * The formatter to use for the first number in the range. + * @return The fluent chain. + * @draft ICU 63 + */ + Derived numberFormatterFirst(const UnlocalizedNumberFormatter &formatterFirst) const &; + + /** + * Overload of numberFormatterFirst() for use on an rvalue reference. + * + * @param formatterFirst + * The formatter to use for the first number in the range. + * @return The fluent chain. + * @see #numberFormatterFirst + * @draft ICU 63 + */ + Derived numberFormatterFirst(const UnlocalizedNumberFormatter &formatterFirst) &&; + + /** + * Overload of numberFormatterFirst() for use on an rvalue reference. + * + * @param formatterFirst + * The formatter to use for the first number in the range. + * @return The fluent chain. + * @see #numberFormatterFirst + * @draft ICU 63 + */ + Derived numberFormatterFirst(UnlocalizedNumberFormatter &&formatterFirst) const &; + + /** + * Overload of numberFormatterFirst() for use on an rvalue reference. + * + * @param formatterFirst + * The formatter to use for the first number in the range. + * @return The fluent chain. + * @see #numberFormatterFirst + * @draft ICU 63 + */ + Derived numberFormatterFirst(UnlocalizedNumberFormatter &&formatterFirst) &&; + + /** + * Sets the NumberFormatter instance to use for the second number in the range. + *

    + * The NumberFormatter instances must not have a locale applied yet; the locale specified on the + * NumberRangeFormatter will be used. + * + * @param formatterSecond + * The formatter to use for the second number in the range. + * @return The fluent chain. + * @draft ICU 63 + */ + Derived numberFormatterSecond(const UnlocalizedNumberFormatter &formatterSecond) const &; + + /** + * Overload of numberFormatterSecond() for use on an rvalue reference. + * + * @param formatterSecond + * The formatter to use for the second number in the range. + * @return The fluent chain. + * @see #numberFormatterSecond + * @draft ICU 63 + */ + Derived numberFormatterSecond(const UnlocalizedNumberFormatter &formatterSecond) &&; + + /** + * Overload of numberFormatterSecond() for use on an rvalue reference. + * + * @param formatterSecond + * The formatter to use for the second number in the range. + * @return The fluent chain. + * @see #numberFormatterSecond + * @draft ICU 63 + */ + Derived numberFormatterSecond(UnlocalizedNumberFormatter &&formatterSecond) const &; + + /** + * Overload of numberFormatterSecond() for use on an rvalue reference. + * + * @param formatterSecond + * The formatter to use for the second number in the range. + * @return The fluent chain. + * @see #numberFormatterSecond + * @draft ICU 63 + */ + Derived numberFormatterSecond(UnlocalizedNumberFormatter &&formatterSecond) &&; + + /** + * Sets the aggressiveness of "collapsing" fields across the range separator. Possible values: + *

    + *

      + *
    • ALL: "3-5K miles"
    • + *
    • UNIT: "3K - 5K miles"
    • + *
    • NONE: "3K miles - 5K miles"
    • + *
    • AUTO: usually UNIT or NONE, depending on the locale and formatter settings
    • + *
    + *

    + * The default value is AUTO. + * + * @param collapse + * The collapsing strategy to use for this range. + * @return The fluent chain. + * @draft ICU 63 + */ + Derived collapse(UNumberRangeCollapse collapse) const &; + + /** + * Overload of collapse() for use on an rvalue reference. + * + * @param collapse + * The collapsing strategy to use for this range. + * @return The fluent chain. + * @see #collapse + * @draft ICU 63 + */ + Derived collapse(UNumberRangeCollapse collapse) &&; + + /** + * Sets the behavior when the two sides of the range are the same. This could happen if the same two numbers are + * passed to the formatRange function, or if different numbers are passed to the function but they become the same + * after rounding rules are applied. Possible values: + *

    + *

      + *
    • SINGLE_VALUE: "5 miles"
    • + *
    • APPROXIMATELY_OR_SINGLE_VALUE: "~5 miles" or "5 miles", depending on whether the number was the same before + * rounding was applied
    • + *
    • APPROXIMATELY: "~5 miles"
    • + *
    • RANGE: "5-5 miles" (with collapse=UNIT)
    • + *
    + *

    + * The default value is APPROXIMATELY. + * + * @param identityFallback + * The strategy to use when formatting two numbers that end up being the same. + * @return The fluent chain. + * @draft ICU 63 + */ + Derived identityFallback(UNumberRangeIdentityFallback identityFallback) const &; + + /** + * Overload of identityFallback() for use on an rvalue reference. + * + * @param identityFallback + * The strategy to use when formatting two numbers that end up being the same. + * @return The fluent chain. + * @see #identityFallback + * @draft ICU 63 + */ + Derived identityFallback(UNumberRangeIdentityFallback identityFallback) &&; + + /** + * Sets the UErrorCode if an error occurred in the fluent chain. + * Preserves older error codes in the outErrorCode. + * @return TRUE if U_FAILURE(outErrorCode) + * @draft ICU 63 + */ + UBool copyErrorTo(UErrorCode &outErrorCode) const { + if (U_FAILURE(outErrorCode)) { + // Do not overwrite the older error code + return TRUE; + } + fMacros.copyErrorTo(outErrorCode); + return U_FAILURE(outErrorCode); + }; + + // NOTE: Uses default copy and move constructors. + + private: + impl::RangeMacroProps fMacros; + + // Don't construct me directly! Use (Un)LocalizedNumberFormatter. + NumberRangeFormatterSettings() = default; + + friend class LocalizedNumberRangeFormatter; + friend class UnlocalizedNumberRangeFormatter; +}; + +/** + * A NumberRangeFormatter that does not yet have a locale. In order to format, a locale must be specified. + * + * @see NumberRangeFormatter + * @draft ICU 63 + */ +class U_I18N_API UnlocalizedNumberRangeFormatter + : public NumberRangeFormatterSettings, public UMemory { + + public: + /** + * Associate the given locale with the number range formatter. The locale is used for picking the + * appropriate symbols, formats, and other data for number display. + * + * @param locale + * The locale to use when loading data for number formatting. + * @return The fluent chain. + * @draft ICU 63 + */ + LocalizedNumberRangeFormatter locale(const icu::Locale &locale) const &; + + /** + * Overload of locale() for use on an rvalue reference. + * + * @param locale + * The locale to use when loading data for number formatting. + * @return The fluent chain. + * @see #locale + * @draft ICU 63 + */ + LocalizedNumberRangeFormatter locale(const icu::Locale &locale) &&; + + /** + * Default constructor: puts the formatter into a valid but undefined state. + * + * @draft ICU 63 + */ + UnlocalizedNumberRangeFormatter() = default; + + /** + * Returns a copy of this UnlocalizedNumberRangeFormatter. + * @draft ICU 63 + */ + UnlocalizedNumberRangeFormatter(const UnlocalizedNumberRangeFormatter &other); + + /** + * Move constructor: + * The source UnlocalizedNumberRangeFormatter will be left in a valid but undefined state. + * @draft ICU 63 + */ + UnlocalizedNumberRangeFormatter(UnlocalizedNumberRangeFormatter&& src) U_NOEXCEPT; + + /** + * Copy assignment operator. + * @draft ICU 63 + */ + UnlocalizedNumberRangeFormatter& operator=(const UnlocalizedNumberRangeFormatter& other); + + /** + * Move assignment operator: + * The source UnlocalizedNumberRangeFormatter will be left in a valid but undefined state. + * @draft ICU 63 + */ + UnlocalizedNumberRangeFormatter& operator=(UnlocalizedNumberRangeFormatter&& src) U_NOEXCEPT; + + private: + explicit UnlocalizedNumberRangeFormatter( + const NumberRangeFormatterSettings& other); + + explicit UnlocalizedNumberRangeFormatter( + NumberRangeFormatterSettings&& src) U_NOEXCEPT; + + // To give the fluent setters access to this class's constructor: + friend class NumberRangeFormatterSettings; + + // To give NumberRangeFormatter::with() access to this class's constructor: + friend class NumberRangeFormatter; +}; + +/** + * A NumberRangeFormatter that has a locale associated with it; this means .formatRange() methods are available. + * + * @see NumberFormatter + * @draft ICU 63 + */ +class U_I18N_API LocalizedNumberRangeFormatter + : public NumberRangeFormatterSettings, public UMemory { + public: + /** + * Format the given Formattables to a string using the settings specified in the NumberRangeFormatter fluent setting + * chain. + * + * @param first + * The first number in the range, usually to the left in LTR locales. + * @param second + * The second number in the range, usually to the right in LTR locales. + * @param status + * Set if an error occurs while formatting. + * @return A FormattedNumberRange object; call .toString() to get the string. + * @draft ICU 63 + */ + FormattedNumberRange formatFormattableRange( + const Formattable& first, const Formattable& second, UErrorCode& status) const; + + /** + * Default constructor: puts the formatter into a valid but undefined state. + * + * @draft ICU 63 + */ + LocalizedNumberRangeFormatter() = default; + + /** + * Returns a copy of this LocalizedNumberRangeFormatter. + * @draft ICU 63 + */ + LocalizedNumberRangeFormatter(const LocalizedNumberRangeFormatter &other); + + /** + * Move constructor: + * The source LocalizedNumberRangeFormatter will be left in a valid but undefined state. + * @draft ICU 63 + */ + LocalizedNumberRangeFormatter(LocalizedNumberRangeFormatter&& src) U_NOEXCEPT; + + /** + * Copy assignment operator. + * @draft ICU 63 + */ + LocalizedNumberRangeFormatter& operator=(const LocalizedNumberRangeFormatter& other); + + /** + * Move assignment operator: + * The source LocalizedNumberRangeFormatter will be left in a valid but undefined state. + * @draft ICU 63 + */ + LocalizedNumberRangeFormatter& operator=(LocalizedNumberRangeFormatter&& src) U_NOEXCEPT; + +#ifndef U_HIDE_INTERNAL_API + + /** + * @param results + * The results object. This method will mutate it to save the results. + * @param equalBeforeRounding + * Whether the number was equal before copying it into a DecimalQuantity. + * Used for determining the identity fallback behavior. + * @param status + * Set if an error occurs while formatting. + * @internal + */ + void formatImpl(impl::UFormattedNumberRangeData& results, bool equalBeforeRounding, + UErrorCode& status) const; + +#endif + + /** + * Destruct this LocalizedNumberRangeFormatter, cleaning up any memory it might own. + * @draft ICU 63 + */ + ~LocalizedNumberRangeFormatter(); + + private: + std::atomic fAtomicFormatter = {}; + + const impl::NumberRangeFormatterImpl* getFormatter(UErrorCode& stauts) const; + + explicit LocalizedNumberRangeFormatter( + const NumberRangeFormatterSettings& other); + + explicit LocalizedNumberRangeFormatter( + NumberRangeFormatterSettings&& src) U_NOEXCEPT; + + LocalizedNumberRangeFormatter(const impl::RangeMacroProps ¯os, const Locale &locale); + + LocalizedNumberRangeFormatter(impl::RangeMacroProps &¯os, const Locale &locale); + + void clear(); + + // To give the fluent setters access to this class's constructor: + friend class NumberRangeFormatterSettings; + friend class NumberRangeFormatterSettings; + + // To give UnlocalizedNumberRangeFormatter::locale() access to this class's constructor: + friend class UnlocalizedNumberRangeFormatter; +}; + +/** + * The result of a number range formatting operation. This class allows the result to be exported in several data types, + * including a UnicodeString and a FieldPositionIterator. + * + * @draft ICU 63 + */ +class U_I18N_API FormattedNumberRange : public UMemory { + public: + /** + * Returns a UnicodeString representation of the formatted number range. + * + * @param status + * Set if an error occurs while formatting the number to the UnicodeString. + * @return a UnicodeString containing the localized number range. + * @draft ICU 63 + */ + UnicodeString toString(UErrorCode& status) const; + + /** + * Appends the formatted number range to an Appendable. + * + * @param appendable + * The Appendable to which to append the formatted number range string. + * @param status + * Set if an error occurs while formatting the number range to the Appendable. + * @return The same Appendable, for chaining. + * @draft ICU 63 + * @see Appendable + */ + Appendable &appendTo(Appendable &appendable, UErrorCode& status) const; + + /** + * Determines the start (inclusive) and end (exclusive) indices of the next occurrence of the given + * field in the output string. This allows you to determine the locations of, for example, + * the integer part, fraction part, or symbols. + * + * If both sides of the range have the same field, the field will occur twice, once before the + * range separator and once after the range separator, if applicable. + * + * If a field occurs just once, calling this method will find that occurrence and return it. If a + * field occurs multiple times, this method may be called repeatedly with the following pattern: + * + *

    +     * FieldPosition fpos(UNUM_INTEGER_FIELD);
    +     * while (formattedNumberRange.nextFieldPosition(fpos, status)) {
    +     *   // do something with fpos.
    +     * }
    +     * 
    + * + * This method is useful if you know which field to query. If you want all available field position + * information, use #getAllFieldPositions(). + * + * @param fieldPosition + * Input+output variable. See {@link FormattedNumber#nextFieldPosition}. + * @param status + * Set if an error occurs while populating the FieldPosition. + * @return TRUE if a new occurrence of the field was found; FALSE otherwise. + * @draft ICU 63 + * @see UNumberFormatFields + */ + UBool nextFieldPosition(FieldPosition& fieldPosition, UErrorCode& status) const; + + /** + * Export the formatted number range to a FieldPositionIterator. This allows you to determine which characters in + * the output string correspond to which fields, such as the integer part, fraction part, and sign. + * + * If information on only one field is needed, use #nextFieldPosition() instead. + * + * @param iterator + * The FieldPositionIterator to populate with all of the fields present in the formatted number. + * @param status + * Set if an error occurs while populating the FieldPositionIterator. + * @draft ICU 63 + * @see UNumberFormatFields + */ + void getAllFieldPositions(FieldPositionIterator &iterator, UErrorCode &status) const; + + /** + * Export the first formatted number as a decimal number. This endpoint + * is useful for obtaining the exact number being printed after scaling + * and rounding have been applied by the number range formatting pipeline. + * + * The syntax of the unformatted number is a "numeric string" + * as defined in the Decimal Arithmetic Specification, available at + * http://speleotrove.com/decimal + * + * @return A decimal representation of the first formatted number. + * @draft ICU 63 + * @see NumberRangeFormatter + * @see #getSecondDecimal + */ + UnicodeString getFirstDecimal(UErrorCode& status) const; + + /** + * Export the second formatted number as a decimal number. This endpoint + * is useful for obtaining the exact number being printed after scaling + * and rounding have been applied by the number range formatting pipeline. + * + * The syntax of the unformatted number is a "numeric string" + * as defined in the Decimal Arithmetic Specification, available at + * http://speleotrove.com/decimal + * + * @return A decimal representation of the second formatted number. + * @draft ICU 63 + * @see NumberRangeFormatter + * @see #getFirstDecimal + */ + UnicodeString getSecondDecimal(UErrorCode& status) const; + + /** + * Returns whether the pair of numbers was successfully formatted as a range or whether an identity fallback was + * used. For example, if the first and second number were the same either before or after rounding occurred, an + * identity fallback was used. + * + * @return An indication the resulting identity situation in the formatted number range. + * @draft ICU 63 + * @see UNumberRangeIdentityFallback + */ + UNumberRangeIdentityResult getIdentityResult(UErrorCode& status) const; + + /** + * Copying not supported; use move constructor instead. + */ + FormattedNumberRange(const FormattedNumberRange&) = delete; + + /** + * Copying not supported; use move assignment instead. + */ + FormattedNumberRange& operator=(const FormattedNumberRange&) = delete; + + /** + * Move constructor: + * Leaves the source FormattedNumberRange in an undefined state. + * @draft ICU 63 + */ + FormattedNumberRange(FormattedNumberRange&& src) U_NOEXCEPT; + + /** + * Move assignment: + * Leaves the source FormattedNumberRange in an undefined state. + * @draft ICU 63 + */ + FormattedNumberRange& operator=(FormattedNumberRange&& src) U_NOEXCEPT; + + /** + * Destruct an instance of FormattedNumberRange, cleaning up any memory it might own. + * @draft ICU 63 + */ + ~FormattedNumberRange(); + + private: + // Can't use LocalPointer because UFormattedNumberRangeData is forward-declared + const impl::UFormattedNumberRangeData *fResults; + + // Error code for the terminal methods + UErrorCode fErrorCode; + + /** + * Internal constructor from data type. Adopts the data pointer. + * @internal + */ + explicit FormattedNumberRange(impl::UFormattedNumberRangeData *results) + : fResults(results), fErrorCode(U_ZERO_ERROR) {}; + + explicit FormattedNumberRange(UErrorCode errorCode) + : fResults(nullptr), fErrorCode(errorCode) {}; + + void getAllFieldPositionsImpl(FieldPositionIteratorHandler& fpih, UErrorCode& status) const; + + // To give LocalizedNumberRangeFormatter format methods access to this class's constructor: + friend class LocalizedNumberRangeFormatter; +}; + +/** + * See the main description in numberrangeformatter.h for documentation and examples. + * + * @draft ICU 63 + */ +class U_I18N_API NumberRangeFormatter final { + public: + /** + * Call this method at the beginning of a NumberRangeFormatter fluent chain in which the locale is not currently + * known at the call site. + * + * @return An {@link UnlocalizedNumberRangeFormatter}, to be used for chaining. + * @draft ICU 63 + */ + static UnlocalizedNumberRangeFormatter with(); + + /** + * Call this method at the beginning of a NumberRangeFormatter fluent chain in which the locale is known at the call + * site. + * + * @param locale + * The locale from which to load formats and symbols for number range formatting. + * @return A {@link LocalizedNumberRangeFormatter}, to be used for chaining. + * @draft ICU 63 + */ + static LocalizedNumberRangeFormatter withLocale(const Locale &locale); + + /** + * Use factory methods instead of the constructor to create a NumberFormatter. + */ + NumberRangeFormatter() = delete; +}; + +} // namespace number +U_NAMESPACE_END + +#endif // U_HIDE_DRAFT_API + +#endif // __NUMBERRANGEFORMATTER_H__ + +#endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/deps/icu-small/source/i18n/unicode/numfmt.h b/deps/icu-small/source/i18n/unicode/numfmt.h index 572e6afc71b807..871fbd93e15e2e 100644 --- a/deps/icu-small/source/i18n/unicode/numfmt.h +++ b/deps/icu-small/source/i18n/unicode/numfmt.h @@ -56,7 +56,6 @@ class StringEnumeration; *

    IMPORTANT: New users are strongly encouraged to see if * numberformatter.h fits their use case. Although not deprecated, this header * is provided for backwards compatibility only. - *


    * * Abstract base class for all number formats. Provides interface for * formatting and parsing a number. Also provides methods for @@ -710,7 +709,7 @@ class U_I18N_API NumberFormat : public Format { * The default formatting style is locale dependent. *

    * NOTE: New users are strongly encouraged to use - * {@link NumberFormatter} instead of NumberFormat. + * {@link icu::number::NumberFormatter} instead of NumberFormat. * @stable ICU 2.0 */ static NumberFormat* U_EXPORT2 createInstance(UErrorCode&); @@ -721,7 +720,7 @@ class U_I18N_API NumberFormat : public Format { * @param inLocale the given locale. *

    * NOTE: New users are strongly encouraged to use - * {@link NumberFormatter} instead of NumberFormat. + * {@link icu::number::NumberFormatter} instead of NumberFormat. * @stable ICU 2.0 */ static NumberFormat* U_EXPORT2 createInstance(const Locale& inLocale, @@ -731,7 +730,7 @@ class U_I18N_API NumberFormat : public Format { * Create a specific style NumberFormat for the specified locale. *

    * NOTE: New users are strongly encouraged to use - * {@link NumberFormatter} instead of NumberFormat. + * {@link icu::number::NumberFormatter} instead of NumberFormat. * @param desiredLocale the given locale. * @param style the given style. * @param errorCode Output param filled with success/failure status. @@ -770,7 +769,7 @@ class U_I18N_API NumberFormat : public Format { * Returns a currency format for the current default locale. *

    * NOTE: New users are strongly encouraged to use - * {@link NumberFormatter} instead of NumberFormat. + * {@link icu::number::NumberFormatter} instead of NumberFormat. * @stable ICU 2.0 */ static NumberFormat* U_EXPORT2 createCurrencyInstance(UErrorCode&); @@ -779,7 +778,7 @@ class U_I18N_API NumberFormat : public Format { * Returns a currency format for the specified locale. *

    * NOTE: New users are strongly encouraged to use - * {@link NumberFormatter} instead of NumberFormat. + * {@link icu::number::NumberFormatter} instead of NumberFormat. * @param inLocale the given locale. * @stable ICU 2.0 */ @@ -790,7 +789,7 @@ class U_I18N_API NumberFormat : public Format { * Returns a percentage format for the current default locale. *

    * NOTE: New users are strongly encouraged to use - * {@link NumberFormatter} instead of NumberFormat. + * {@link icu::number::NumberFormatter} instead of NumberFormat. * @stable ICU 2.0 */ static NumberFormat* U_EXPORT2 createPercentInstance(UErrorCode&); @@ -799,7 +798,7 @@ class U_I18N_API NumberFormat : public Format { * Returns a percentage format for the specified locale. *

    * NOTE: New users are strongly encouraged to use - * {@link NumberFormatter} instead of NumberFormat. + * {@link icu::number::NumberFormatter} instead of NumberFormat. * @param inLocale the given locale. * @stable ICU 2.0 */ @@ -810,7 +809,7 @@ class U_I18N_API NumberFormat : public Format { * Returns a scientific format for the current default locale. *

    * NOTE: New users are strongly encouraged to use - * {@link NumberFormatter} instead of NumberFormat. + * {@link icu::number::NumberFormatter} instead of NumberFormat. * @stable ICU 2.0 */ static NumberFormat* U_EXPORT2 createScientificInstance(UErrorCode&); @@ -819,7 +818,7 @@ class U_I18N_API NumberFormat : public Format { * Returns a scientific format for the specified locale. *

    * NOTE: New users are strongly encouraged to use - * {@link NumberFormatter} instead of NumberFormat. + * {@link icu::number::NumberFormatter} instead of NumberFormat. * @param inLocale the given locale. * @stable ICU 2.0 */ @@ -1028,14 +1027,14 @@ class U_I18N_API NumberFormat : public Format { * Get the rounding mode. This will always return NumberFormat::ERoundingMode::kRoundUnnecessary * if the subclass does not support rounding. * @return A rounding mode - * @draft ICU 60 + * @stable ICU 60 */ virtual ERoundingMode getRoundingMode(void) const; /** * Set the rounding mode. If a subclass does not support rounding, this will do nothing. * @param roundingMode A rounding mode - * @draft ICU 60 + * @stable ICU 60 */ virtual void setRoundingMode(ERoundingMode roundingMode); diff --git a/deps/icu-small/source/i18n/unicode/plurfmt.h b/deps/icu-small/source/i18n/unicode/plurfmt.h index 9a83e52550c540..6b757c88419316 100644 --- a/deps/icu-small/source/i18n/unicode/plurfmt.h +++ b/deps/icu-small/source/i18n/unicode/plurfmt.h @@ -520,15 +520,7 @@ class U_I18N_API PluralFormat : public Format { */ virtual UClassID getDynamicClassID() const; -#if (defined(__xlC__) && (__xlC__ < 0x0C00)) || (U_PLATFORM == U_PF_OS390) || (U_PLATFORM ==U_PF_OS400) -// Work around a compiler bug on xlC 11.1 on AIX 7.1 that would -// prevent PluralSelectorAdapter from implementing private PluralSelector. -// xlC error message: -// 1540-0300 (S) The "private" member "class icu_49::PluralFormat::PluralSelector" cannot be accessed. -public: -#else private: -#endif /** * @internal */ @@ -564,10 +556,6 @@ class U_I18N_API PluralFormat : public Format { PluralRules* pluralRules; }; -#if defined(__xlC__) -// End of xlC bug workaround, keep remaining definitions private. -private: -#endif Locale locale; MessagePattern msgPattern; NumberFormat* numberFormat; diff --git a/deps/icu-small/source/i18n/unicode/plurrule.h b/deps/icu-small/source/i18n/unicode/plurrule.h index 03dea3f1b92988..daeed52bee632e 100644 --- a/deps/icu-small/source/i18n/unicode/plurrule.h +++ b/deps/icu-small/source/i18n/unicode/plurrule.h @@ -118,7 +118,6 @@ class SharedPluralRules; * Examples are in the following table: *

    * - * * * * @@ -155,7 +154,6 @@ class SharedPluralRules; * * * - * *
    ni232
    *

    * The difference between 'in' and 'within' is that 'in' only includes integers in the specified range, while 'within' @@ -499,6 +497,12 @@ class U_I18N_API PluralRules : public UObject { UnicodeString getRuleFromResource(const Locale& locale, UPluralType type, UErrorCode& status); RuleChain *rulesForKeyword(const UnicodeString &keyword) const; + /** + * An internal status variable used to indicate that the object is in an 'invalid' state. + * Used by copy constructor, the assignment operator and the clone method. + */ + UErrorCode mInternalStatus; + friend class PluralRuleParser; }; diff --git a/deps/icu-small/source/i18n/unicode/rbnf.h b/deps/icu-small/source/i18n/unicode/rbnf.h index 2d284909f8a1d4..f7cd85a322d1f5 100644 --- a/deps/icu-small/source/i18n/unicode/rbnf.h +++ b/deps/icu-small/source/i18n/unicode/rbnf.h @@ -313,7 +313,6 @@ enum URBNFRuleSetTag { * The rule for an IEEE 754 NaN (not a number). * * - * * nothing * If the rule's rule descriptor is left out, the base value is one plus the * preceding rule's base value (or zero if this is the first rule in the list) in a normal @@ -1013,14 +1012,14 @@ class U_I18N_API RuleBasedNumberFormat : public NumberFormat { /** * Get the rounding mode. * @return A rounding mode - * @draft ICU 60 + * @stable ICU 60 */ virtual ERoundingMode getRoundingMode(void) const; /** * Set the rounding mode. * @param roundingMode A rounding mode - * @draft ICU 60 + * @stable ICU 60 */ virtual void setRoundingMode(ERoundingMode roundingMode); @@ -1095,7 +1094,7 @@ class U_I18N_API RuleBasedNumberFormat : public NumberFormat { void format(double number, NFRuleSet& rs, UnicodeString& toAppendTo, UErrorCode& status) const; private: - NFRuleSet **ruleSets; + NFRuleSet **fRuleSets; UnicodeString* ruleSetDescriptions; int32_t numRuleSets; NFRuleSet *defaultRuleSet; @@ -1104,7 +1103,7 @@ class U_I18N_API RuleBasedNumberFormat : public NumberFormat { DecimalFormatSymbols* decimalFormatSymbols; NFRule *defaultInfinityRule; NFRule *defaultNaNRule; - ERoundingMode roundingMode; + ERoundingMode fRoundingMode; UBool lenient; UnicodeString* lenientParseRules; LocalizationInfo* localizations; diff --git a/deps/icu-small/source/i18n/unicode/region.h b/deps/icu-small/source/i18n/unicode/region.h index 667c4051f0eb74..ccd63901a5d1b1 100644 --- a/deps/icu-small/source/i18n/unicode/region.h +++ b/deps/icu-small/source/i18n/unicode/region.h @@ -192,7 +192,7 @@ class U_I18N_API Region : public UObject { char id[4]; UnicodeString idStr; int32_t code; - URegionType type; + URegionType fType; Region *containingRegion; UVector *containedRegions; UVector *preferredValues; diff --git a/deps/icu-small/source/i18n/unicode/reldatefmt.h b/deps/icu-small/source/i18n/unicode/reldatefmt.h index abd43522c3a965..dd8bc53d55f500 100644 --- a/deps/icu-small/source/i18n/unicode/reldatefmt.h +++ b/deps/icu-small/source/i18n/unicode/reldatefmt.h @@ -165,12 +165,20 @@ typedef enum UDateAbsoluteUnit { */ UDAT_ABSOLUTE_NOW, +#ifndef U_HIDE_DRAFT_API + /** + * Quarter + * @draft ICU 63 + */ + UDAT_ABSOLUTE_QUARTER, +#endif // U_HIDE_DRAFT_API + #ifndef U_HIDE_DEPRECATED_API /** * One more than the highest normal UDateAbsoluteUnit value. * @deprecated ICU 58 The numeric value may change over time, see ICU ticket #12420. */ - UDAT_ABSOLUTE_UNIT_COUNT + UDAT_ABSOLUTE_UNIT_COUNT = UDAT_ABSOLUTE_NOW + 2 #endif // U_HIDE_DEPRECATED_API } UDateAbsoluteUnit; @@ -328,7 +336,7 @@ class U_I18N_API RelativeDateTimeFormatter : public UObject { * @param nfToAdopt Constructed object takes ownership of this pointer. * It is an error for caller to delete this pointer or change its * contents after calling this constructor. - * @status Any error is returned here. + * @param status Any error is returned here. * @stable ICU 53 */ RelativeDateTimeFormatter( @@ -346,7 +354,7 @@ class U_I18N_API RelativeDateTimeFormatter : public UObject { * @param style the format style. The UDAT_RELATIVE bit field has no effect. * @param capitalizationContext A value from UDisplayContext that pertains to * capitalization. - * @status Any error is returned here. + * @param status Any error is returned here. * @stable ICU 54 */ RelativeDateTimeFormatter( diff --git a/deps/icu-small/source/i18n/unicode/smpdtfmt.h b/deps/icu-small/source/i18n/unicode/smpdtfmt.h index 305412b8d1535f..929c1b4675b407 100644 --- a/deps/icu-small/source/i18n/unicode/smpdtfmt.h +++ b/deps/icu-small/source/i18n/unicode/smpdtfmt.h @@ -1147,7 +1147,7 @@ class U_I18N_API SimpleDateFormat: public DateFormat { * Overrides base class method and * This method clears per field NumberFormat instances * previously set by {@see adoptNumberFormat(const UnicodeString&, NumberFormat*, UErrorCode)} - * @param adoptNF the NumbeferFormat used + * @param formatToAdopt the NumbeferFormat used * @stable ICU 54 */ void adoptNumberFormat(NumberFormat *formatToAdopt); @@ -1162,7 +1162,7 @@ class U_I18N_API SimpleDateFormat: public DateFormat { * Per field NumberFormat can also be cleared in {@see DateFormat::setNumberFormat(const NumberFormat& newNumberFormat)} * * @param fields the fields to override(like y) - * @param adoptNF the NumbeferFormat used + * @param formatToAdopt the NumbeferFormat used * @param status Receives a status code, which will be U_ZERO_ERROR * if the operation succeeds. * @stable ICU 54 diff --git a/deps/icu-small/source/i18n/unicode/translit.h b/deps/icu-small/source/i18n/unicode/translit.h index dc31d97bc63643..6b4888145f1be5 100644 --- a/deps/icu-small/source/i18n/unicode/translit.h +++ b/deps/icu-small/source/i18n/unicode/translit.h @@ -31,7 +31,6 @@ U_NAMESPACE_BEGIN class UnicodeFilter; class UnicodeSet; -class CompoundTransliterator; class TransliteratorParser; class NormalizationTransliterator; class TransliteratorIDParser; @@ -77,8 +76,7 @@ class TransliteratorIDParser; * transliteration. For example, given a string input * and a transliterator t, the call * - * \htmlonly

    \endhtmlonlyString result = t.transliterate(input); - * \htmlonly
    \endhtmlonly + * String result = t.transliterate(input); * * will transliterate it and return the result. Other methods allow * the client to specify a substring to be transliterated and to use @@ -98,22 +96,20 @@ class TransliteratorIDParser; * contents of the buffer may show text being modified as each new * character arrives. * - *

    Consider the simple RuleBasedTransliterator: - * - * \htmlonly

    \endhtmlonly - * th>{theta}
    - * t>{tau} - *
    \htmlonly
    \endhtmlonly + *

    Consider the simple rule-based Transliterator: + *

    + *     th>{theta}
    + *     t>{tau}
    + * 
    * * When the user types 't', nothing will happen, since the * transliterator is waiting to see if the next character is 'h'. To * remedy this, we introduce the notion of a cursor, marked by a '|' * in the output string: - * - * \htmlonly
    \endhtmlonly - * t>|{tau}
    - * {tau}h>{theta} - *
    \htmlonly
    \endhtmlonly + *
    + *     t>|{tau}
    + *     {tau}h>{theta}
    + * 
    * * Now when the user types 't', tau appears, and if the next character * is 'h', the tau changes to a theta. This is accomplished by @@ -135,7 +131,7 @@ class TransliteratorIDParser; * which the transliterator last stopped, either because it reached * the end, or because it required more characters to disambiguate * between possible inputs. The CURSOR can also be - * explicitly set by rules in a RuleBasedTransliterator. + * explicitly set by rules in a rule-based Transliterator. * Any characters before the CURSOR index are frozen; * future keyboard transliteration calls within this input sequence * will not change them. New text is inserted at the @@ -237,6 +233,255 @@ class TransliteratorIDParser; * if the performance of these methods can be improved over the * performance obtained by the default implementations in this class. * + *

    Rule syntax + * + *

    A set of rules determines how to perform translations. + * Rules within a rule set are separated by semicolons (';'). + * To include a literal semicolon, prefix it with a backslash ('\'). + * Unicode Pattern_White_Space is ignored. + * If the first non-blank character on a line is '#', + * the entire line is ignored as a comment. + * + *

    Each set of rules consists of two groups, one forward, and one + * reverse. This is a convention that is not enforced; rules for one + * direction may be omitted, with the result that translations in + * that direction will not modify the source text. In addition, + * bidirectional forward-reverse rules may be specified for + * symmetrical transformations. + * + *

    Note: Another description of the Transliterator rule syntax is available in + * section + * Transform Rules Syntax of UTS #35: Unicode LDML. + * The rules are shown there using arrow symbols ← and → and ↔. + * ICU supports both those and the equivalent ASCII symbols < and > and <>. + * + *

    Rule statements take one of the following forms: + * + *

    + *
    $alefmadda=\\u0622;
    + *
    Variable definition. The name on the + * left is assigned the text on the right. In this example, + * after this statement, instances of the left hand name, + * "$alefmadda", will be replaced by + * the Unicode character U+0622. Variable names must begin + * with a letter and consist only of letters, digits, and + * underscores. Case is significant. Duplicate names cause + * an exception to be thrown, that is, variables cannot be + * redefined. The right hand side may contain well-formed + * text of any length, including no text at all ("$empty=;"). + * The right hand side may contain embedded UnicodeSet + * patterns, for example, "$softvowel=[eiyEIY]".
    + *
    ai>$alefmadda;
    + *
    Forward translation rule. This rule + * states that the string on the left will be changed to the + * string on the right when performing forward + * transliteration.
    + *
    ai<$alefmadda;
    + *
    Reverse translation rule. This rule + * states that the string on the right will be changed to + * the string on the left when performing reverse + * transliteration.
    + *
    + * + *
    + *
    ai<>$alefmadda;
    + *
    Bidirectional translation rule. This + * rule states that the string on the right will be changed + * to the string on the left when performing forward + * transliteration, and vice versa when performing reverse + * transliteration.
    + *
    + * + *

    Translation rules consist of a match pattern and an output + * string. The match pattern consists of literal characters, + * optionally preceded by context, and optionally followed by + * context. Context characters, like literal pattern characters, + * must be matched in the text being transliterated. However, unlike + * literal pattern characters, they are not replaced by the output + * text. For example, the pattern "abc{def}" + * indicates the characters "def" must be + * preceded by "abc" for a successful match. + * If there is a successful match, "def" will + * be replaced, but not "abc". The final '}' + * is optional, so "abc{def" is equivalent to + * "abc{def}". Another example is "{123}456" + * (or "123}456") in which the literal + * pattern "123" must be followed by "456". + * + *

    The output string of a forward or reverse rule consists of + * characters to replace the literal pattern characters. If the + * output string contains the character '|', this is + * taken to indicate the location of the cursor after + * replacement. The cursor is the point in the text at which the + * next replacement, if any, will be applied. The cursor is usually + * placed within the replacement text; however, it can actually be + * placed into the precending or following context by using the + * special character '@'. Examples: + * + *

    + *     a {foo} z > | @ bar; # foo -> bar, move cursor before a
    + *     {foo} xyz > bar @@|; # foo -> bar, cursor between y and z
    + * 
    + * + *

    UnicodeSet + * + *

    UnicodeSet patterns may appear anywhere that + * makes sense. They may appear in variable definitions. + * Contrariwise, UnicodeSet patterns may themselves + * contain variable references, such as "$a=[a-z];$not_a=[^$a]", + * or "$range=a-z;$ll=[$range]". + * + *

    UnicodeSet patterns may also be embedded directly + * into rule strings. Thus, the following two rules are equivalent: + * + *

    + *     $vowel=[aeiou]; $vowel>'*'; # One way to do this
    + *     [aeiou]>'*'; # Another way
    + * 
    + * + *

    See {@link UnicodeSet} for more documentation and examples. + * + *

    Segments + * + *

    Segments of the input string can be matched and copied to the + * output string. This makes certain sets of rules simpler and more + * general, and makes reordering possible. For example: + * + *

    + *     ([a-z]) > $1 $1; # double lowercase letters
    + *     ([:Lu:]) ([:Ll:]) > $2 $1; # reverse order of Lu-Ll pairs
    + * 
    + * + *

    The segment of the input string to be copied is delimited by + * "(" and ")". Up to + * nine segments may be defined. Segments may not overlap. In the + * output string, "$1" through "$9" + * represent the input string segments, in left-to-right order of + * definition. + * + *

    Anchors + * + *

    Patterns can be anchored to the beginning or the end of the text. This is done with the + * special characters '^' and '$'. For example: + * + *

    + *   ^ a   > 'BEG_A';   # match 'a' at start of text
    + *     a   > 'A'; # match other instances of 'a'
    + *     z $ > 'END_Z';   # match 'z' at end of text
    + *     z   > 'Z';       # match other instances of 'z'
    + * 
    + * + *

    It is also possible to match the beginning or the end of the text using a UnicodeSet. + * This is done by including a virtual anchor character '$' at the end of the + * set pattern. Although this is usually the match chafacter for the end anchor, the set will + * match either the beginning or the end of the text, depending on its placement. For + * example: + * + *

    + *   $x = [a-z$];   # match 'a' through 'z' OR anchor
    + *   $x 1    > 2;   # match '1' after a-z or at the start
    + *      3 $x > 4;   # match '3' before a-z or at the end
    + * 
    + * + *

    Example + * + *

    The following example rules illustrate many of the features of + * the rule language. + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
    Rule 1.abc{def}>x|y
    Rule 2.xyz>r
    Rule 3.yz>q
    + * + *

    Applying these rules to the string "adefabcdefz" + * yields the following results: + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
    |adefabcdefzInitial state, no rules match. Advance + * cursor.
    a|defabcdefzStill no match. Rule 1 does not match + * because the preceding context is not present.
    ad|efabcdefzStill no match. Keep advancing until + * there is a match...
    ade|fabcdefz...
    adef|abcdefz...
    adefa|bcdefz...
    adefab|cdefz...
    adefabc|defzRule 1 matches; replace "def" + * with "xy" and back up the cursor + * to before the 'y'.
    adefabcx|yzAlthough "xyz" is + * present, rule 2 does not match because the cursor is + * before the 'y', not before the 'x'. + * Rule 3 does match. Replace "yz" + * with "q".
    adefabcxq|The cursor is at the end; + * transliteration is complete.
    + * + *

    The order of rules is significant. If multiple rules may match + * at some point, the first matching rule is applied. + * + *

    Forward and reverse rules may have an empty output string. + * Otherwise, an empty left or right hand side of any statement is a + * syntax error. + * + *

    Single quotes are used to quote any character other than a + * digit or letter. To specify a single quote itself, inside or + * outside of quotes, use two single quotes in a row. For example, + * the rule "'>'>o''clock" changes the + * string ">" to the string "o'clock". + * + *

    Notes + * + *

    While a Transliterator is being built from rules, it checks that + * the rules are added in proper order. For example, if the rule + * "a>x" is followed by the rule "ab>y", + * then the second rule will throw an exception. The reason is that + * the second rule can never be triggered, since the first rule + * always matches anything it matches. In other words, the first + * rule masks the second rule. + * * @author Alan Liu * @stable ICU 2.0 */ @@ -499,9 +744,9 @@ class U_I18N_API Transliterator : public UObject { * for details. * @param text the buffer holding transliterated and * untransliterated text - * @param index an array of three integers. See {@link #transliterate(Replaceable&, UTransPosition&, const UnicodeString*, UErrorCode&) const }. + * @param index an array of three integers. * @param status Output param to filled in with a success or an error. - * @see #transliterate(Replaceable, int[], String) + * @see #transliterate(Replaceable&, UTransPosition&, const UnicodeString&, UErrorCode &) const * @stable ICU 2.0 */ virtual void transliterate(Replaceable& text, UTransPosition& index, @@ -632,7 +877,7 @@ class U_I18N_API Transliterator : public UObject { /** * Transliterate a substring of text, as specified by index, taking filters * into account. This method is for subclasses that need to delegate to - * another transliterator, such as CompoundTransliterator. + * another transliterator. * @param text the text to be transliterated * @param index the position indices * @param incremental if TRUE, then assume more characters may be inserted @@ -846,17 +1091,19 @@ class U_I18N_API Transliterator : public UObject { /** * Returns a Transliterator object constructed from - * the given rule string. This will be a RuleBasedTransliterator, + * the given rule string. This will be a rule-based Transliterator, * if the rule string contains only rules, or a - * CompoundTransliterator, if it contains ID blocks, or a - * NullTransliterator, if it contains ID blocks which parse as + * compound Transliterator, if it contains ID blocks, or a + * null Transliterator, if it contains ID blocks which parse as * empty for the given direction. + * * @param ID the id for the transliterator. * @param rules rules, separated by ';' * @param dir either FORWARD or REVERSE. - * @param parseError Struct to recieve information on position + * @param parseError Struct to receive information on position * of error if an error is encountered * @param status Output param set to success/failure code. + * @return a newly created Transliterator * @stable ICU 2.0 */ static Transliterator* U_EXPORT2 createFromRules(const UnicodeString& ID, diff --git a/deps/icu-small/source/i18n/unicode/tzfmt.h b/deps/icu-small/source/i18n/unicode/tzfmt.h index 633cd8dc6987ce..d2aa768b8c8b34 100644 --- a/deps/icu-small/source/i18n/unicode/tzfmt.h +++ b/deps/icu-small/source/i18n/unicode/tzfmt.h @@ -237,10 +237,10 @@ typedef enum UTimeZoneFormatParseOption { */ UTZFMT_PARSE_OPTION_ALL_STYLES = 0x01, /** - * When parsing a time zone display name in UTZFMT_STYLE_SPECIFIC_SHORT, + * When parsing a time zone display name in \link UTZFMT_STYLE_SPECIFIC_SHORT \endlink, * look for the IANA tz database compatible zone abbreviations in addition - * to the localized names coming from the {@link TimeZoneNames} currently - * used by the {@link TimeZoneFormat}. + * to the localized names coming from the icu::TimeZoneNames currently + * used by the icu::TimeZoneFormat. * @stable ICU 54 */ UTZFMT_PARSE_OPTION_TZ_DATABASE_ABBREVIATIONS = 0x02 diff --git a/deps/icu-small/source/i18n/unicode/ucal.h b/deps/icu-small/source/i18n/unicode/ucal.h index 10d8bc52745d2b..889a1ec51db52c 100644 --- a/deps/icu-small/source/i18n/unicode/ucal.h +++ b/deps/icu-small/source/i18n/unicode/ucal.h @@ -139,6 +139,19 @@ * For example, subtracting 5 days from the date September 12, 1996 * results in September 7, 1996. * + *

    + * The Japanese calendar uses a combination of era name and year number. + * When an emperor of Japan abdicates and a new emperor ascends the throne, + * a new era is declared and year number is reset to 1. Even if the date of + * abdication is scheduled ahead of time, the new era name might not be + * announced until just before the date. In such case, ICU4C may include + * a start date of future era without actual era name, but not enabled + * by default. ICU4C users who want to test the behavior of the future era + * can enable the tentative era by: + *

      + *
    • Environment variable ICU_ENABLE_TENTATIVE_ERA=true.
    • + *
    + * * @stable ICU 2.0 */ diff --git a/deps/icu-small/source/i18n/unicode/ucol.h b/deps/icu-small/source/i18n/unicode/ucol.h index b5bacbfcb4734e..f084ac61e614f3 100644 --- a/deps/icu-small/source/i18n/unicode/ucol.h +++ b/deps/icu-small/source/i18n/unicode/ucol.h @@ -1149,7 +1149,7 @@ ucol_getUCAVersion(const UCollator* coll, UVersionInfo info); * The recommended way to achieve "merged" sorting is by * concatenating strings with U+FFFE between them. * The concatenation has the same sort order as the merged sort keys, - * but merge(getSortKey(str1), getSortKey(str2)) may differ from getSortKey(str1 + '\uFFFE' + str2). + * but merge(getSortKey(str1), getSortKey(str2)) may differ from getSortKey(str1 + '\\uFFFE' + str2). * Using strings with U+FFFE may yield shorter sort keys. * * For details about Sort Key Features see @@ -1294,6 +1294,7 @@ U_STABLE uint32_t U_EXPORT2 ucol_getVariableTop(const UCollator *coll, UErrorCod * the top of one of the supported reordering groups, * and it must not be beyond the last of those groups. * See ucol_setMaxVariable(). + * @param coll collator to be set * @param varTop primary weight, as returned by ucol_setVariableTop or ucol_getVariableTop * @param status error code * @see ucol_getVariableTop diff --git a/deps/icu-small/source/i18n/unicode/ugender.h b/deps/icu-small/source/i18n/unicode/ugender.h index d015a2300cf6d6..903f3dd5deebbe 100644 --- a/deps/icu-small/source/i18n/unicode/ugender.h +++ b/deps/icu-small/source/i18n/unicode/ugender.h @@ -49,11 +49,11 @@ enum UGender { */ typedef enum UGender UGender; +struct UGenderInfo; /** * Opaque UGenderInfo object for use in C programs. * @stable ICU 50 */ -struct UGenderInfo; typedef struct UGenderInfo UGenderInfo; /** @@ -77,7 +77,7 @@ ugender_getInstance(const char *locale, UErrorCode *status); * @stable ICU 50 */ U_STABLE UGender U_EXPORT2 -ugender_getListGender(const UGenderInfo* genderinfo, const UGender *genders, int32_t size, UErrorCode *status); +ugender_getListGender(const UGenderInfo* genderInfo, const UGender *genders, int32_t size, UErrorCode *status); #endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/deps/icu-small/source/common/unicode/ulistformatter.h b/deps/icu-small/source/i18n/unicode/ulistformatter.h similarity index 90% rename from deps/icu-small/source/common/unicode/ulistformatter.h rename to deps/icu-small/source/i18n/unicode/ulistformatter.h index e98a9f045221d9..242d7d21644762 100644 --- a/deps/icu-small/source/common/unicode/ulistformatter.h +++ b/deps/icu-small/source/i18n/unicode/ulistformatter.h @@ -33,6 +33,26 @@ struct UListFormatter; typedef struct UListFormatter UListFormatter; /**< C typedef for struct UListFormatter. @stable ICU 55 */ +#ifndef U_HIDE_DRAFT_API +/** + * FieldPosition and UFieldPosition selectors for format fields + * defined by ListFormatter. + * @draft ICU 63 + */ +typedef enum UListFormatterField { + /** + * The literal text in the result which came from the resources. + * @draft ICU 63 + */ + ULISTFMT_LITERAL_FIELD, + /** + * The element text in the result which came from the input strings. + * @draft ICU 63 + */ + ULISTFMT_ELEMENT_FIELD +} UListFormatterField; +#endif // U_HIDE_DRAFT_API + /** * Open a new UListFormatter object using the rules for a given locale. * @param locale diff --git a/deps/icu-small/source/i18n/unicode/unumberformatter.h b/deps/icu-small/source/i18n/unicode/unumberformatter.h index b37f80c503a76d..d05b15cdeccafb 100644 --- a/deps/icu-small/source/i18n/unicode/unumberformatter.h +++ b/deps/icu-small/source/i18n/unicode/unumberformatter.h @@ -91,7 +91,7 @@ * * *

    - * This enum is similar to {@link com.ibm.icu.text.MeasureFormat.FormatWidth}. + * This enum is similar to {@link UMeasureFormatWidth}. * * @draft ICU 60 */ @@ -190,10 +190,9 @@ typedef enum UNumberUnitWidth { * Note: This enum specifies the strategy for grouping sizes. To set which character to use as the * grouping separator, use the "symbols" setter. * - * @draft ICU 61 -- TODO: This should be renamed to UNumberGroupingStrategy before promoting to stable, - * for consistency with the other enums. + * @draft ICU 63 */ -typedef enum UGroupingStrategy { +typedef enum UNumberGroupingStrategy { /** * Do not display grouping separators in any locale. * @@ -254,16 +253,28 @@ typedef enum UGroupingStrategy { * * @draft ICU 61 */ - UNUM_GROUPING_THOUSANDS, + UNUM_GROUPING_THOUSANDS +#ifndef U_HIDE_INTERNAL_API + , /** - * One more than the highest UGroupingStrategy value. + * One more than the highest UNumberGroupingStrategy value. * * @internal ICU 62: The numeric value may change over time; see ICU ticket #12420. */ UNUM_GROUPING_COUNT +#endif /* U_HIDE_INTERNAL_API */ + +} UNumberGroupingStrategy; + +#ifndef U_HIDE_DEPRECATED_API +/** + * Old name for compatibility: will be removed in ICU 64. + * @deprecated ICU 63 + */ +typedef UNumberGroupingStrategy UGroupingStrategy; +#endif /* U_HIDE_DEPRECATED_API */ -} UGroupingStrategy; #endif /* U_HIDE_DRAFT_API */ #ifndef U_HIDE_DRAFT_API @@ -398,6 +409,8 @@ typedef enum UNumberDecimalSeparatorDisplay { #endif /* U_HIDE_DRAFT_API */ #ifndef U_HIDE_DRAFT_API + +struct UNumberFormatter; /** * C-compatible version of icu::number::LocalizedNumberFormatter. * @@ -405,10 +418,9 @@ typedef enum UNumberDecimalSeparatorDisplay { * * @draft ICU 62 */ -struct UNumberFormatter; typedef struct UNumberFormatter UNumberFormatter; - +struct UFormattedNumber; /** * C-compatible version of icu::number::FormattedNumber. * @@ -416,7 +428,6 @@ typedef struct UNumberFormatter UNumberFormatter; * * @draft ICU 62 */ -struct UFormattedNumber; typedef struct UFormattedNumber UFormattedNumber; @@ -559,7 +570,8 @@ unumf_resultToString(const UFormattedNumber* uresult, UChar* buffer, int32_t buf * * NOTE: All fields of the UFieldPosition must be initialized before calling this method. * - * @param fieldPosition + * @param uresult The object containing the formatted number. + * @param ufpos * Input+output variable. On input, the "field" property determines which field to look up, * and the "endIndex" property determines where to begin the search. On output, the * "beginIndex" field is set to the beginning of the first occurrence of the field after the @@ -580,7 +592,7 @@ unumf_resultNextFieldPosition(const UFormattedNumber* uresult, UFieldPosition* u * If you need information on only one field, use unumf_resultNextFieldPosition(). * * @param uresult The object containing the formatted number. - * @param fpositer + * @param ufpositer * A pointer to a UFieldPositionIterator created by {@link #ufieldpositer_open}. Iteration * information already present in the UFieldPositionIterator is deleted, and the iterator is reset * to apply to the fields in the formatted string created by this function call. The field values diff --git a/deps/icu-small/source/i18n/unicode/usearch.h b/deps/icu-small/source/i18n/unicode/usearch.h index 600f9142b45021..6b495ef00140f1 100644 --- a/deps/icu-small/source/i18n/unicode/usearch.h +++ b/deps/icu-small/source/i18n/unicode/usearch.h @@ -257,10 +257,9 @@ typedef enum { * match an e with the same diacritic or a plain e in the searched text. * * This option is similar to "asymmetric search" as described in - * - * UTS #10 Unicode Collation Algorithm * UTS 39 defines two strings to be confusable if they map to the same skeleton string. A skeleton can * be thought of as a "hash code". {@link uspoof_getSkeleton} computes the skeleton for a particular string, so * the following snippet is equivalent to the example above: @@ -128,7 +127,6 @@ * free(skel2); * \endcode * - *

    * If you need to check if a string is confusable with any string in a dictionary of many strings, rather than calling * {@link uspoof_areConfusable} many times in a loop, {@link uspoof_getSkeleton} can be used instead, as shown below: * @@ -172,14 +170,12 @@ * uspoof_close(sc); * \endcode * - *

    * Note: Since the Unicode confusables mapping table is frequently updated, confusable skeletons are not * guaranteed to be the same between ICU releases. We therefore recommend that you always compute confusable skeletons * at runtime and do not rely on creating a permanent, or difficult to update, database of skeletons. * *

    Spoof Detection

    * - *

    * The following snippet shows a minimal example of using USpoofChecker to perform spoof detection on a * string: * @@ -204,16 +200,13 @@ * uset_close(allowed); * \endcode * - *

    * As in the case for confusability checking, it is good practice to create one USpoofChecker instance at * startup, and call the cheaper {@link uspoof_check} online. We specify the set of * allowed characters to be those with type RECOMMENDED or INCLUSION, according to the recommendation in UTS 39. * - *

    * In addition to {@link uspoof_check}, the function {@link uspoof_checkUTF8} is exposed for UTF8-encoded char* strings, * and {@link uspoof_checkUnicodeString} is exposed for C++ programmers. * - *

    * If the {@link USPOOF_AUX_INFO} check is enabled, a limited amount of information on why a string failed the checks * is available in the returned bitmask. For complete information, use the {@link uspoof_check2} class of functions * with a {@link USpoofCheckResult} parameter: @@ -274,7 +267,6 @@ * // Explicit cleanup not necessary. * \endcode * - *

    * The return value is a bitmask of the checks that failed. In this case, there was one check that failed: * {@link USPOOF_RESTRICTION_LEVEL}, corresponding to the fifth bit (16). The possible checks are: * @@ -307,7 +299,6 @@ * uspoof_close(sc); * \endcode * - *

    * Here is an example in C++ showing how to compute the restriction level of a string: * * \code{.cpp} @@ -334,11 +325,9 @@ * printf("Restriction level: %#010x (status: %s)\n", restrictionLevel, u_errorName(status)); * \endcode * - *

    * The code '0x50000000' corresponds to the restriction level USPOOF_MINIMALLY_RESTRICTIVE. Since * USPOOF_MINIMALLY_RESTRICTIVE is weaker than USPOOF_MODERATELY_RESTRICTIVE, the string fails the check. * - *

    * Note: The Restriction Level is the most powerful of the checks. The full logic is documented in * UTS 39, but the basic idea is that strings * are restricted to contain characters from only a single script, except that most scripts are allowed to have @@ -352,15 +341,12 @@ * *

    Additional Information

    * - *

    * A USpoofChecker instance may be used repeatedly to perform checks on any number of identifiers. * - *

    * Thread Safety: The test functions for checking a single identifier, or for testing whether * two identifiers are possible confusable, are thread safe. They may called concurrently, from multiple threads, * using the same USpoofChecker instance. * - *

    * More generally, the standard ICU thread safety rules apply: functions that take a const USpoofChecker parameter are * thread safe. Those that take a non-const USpoofChecker are not thread safe.. * @@ -1219,14 +1205,21 @@ U_NAMESPACE_BEGIN /** * \class LocalUSpoofCheckResultPointer - * "Smart pointer" class, closes a USpoofCheckResult via {@link uspoof_closeCheckResult}. + * "Smart pointer" class, closes a USpoofCheckResult via `uspoof_closeCheckResult()`. * For most methods see the LocalPointerBase base class. * * @see LocalPointerBase * @see LocalPointer * @stable ICU 58 */ + +/** + * \cond + * Note: Doxygen is giving a bogus warning on this U_DEFINE_LOCAL_OPEN_POINTER. + * For now, suppress with a Doxygen cond + */ U_DEFINE_LOCAL_OPEN_POINTER(LocalUSpoofCheckResultPointer, USpoofCheckResult, uspoof_closeCheckResult); +/** \endcond */ U_NAMESPACE_END diff --git a/deps/icu-small/source/i18n/uregex.cpp b/deps/icu-small/source/i18n/uregex.cpp index 370384363483e7..f504aec91bd7c3 100644 --- a/deps/icu-small/source/i18n/uregex.cpp +++ b/deps/icu-small/source/i18n/uregex.cpp @@ -1654,8 +1654,8 @@ int32_t RegexCImpl::appendTail(RegularExpression *regexp, } else if (UTEXT_USES_U16(m->fInputText)) { srcIdx = (int32_t)nativeIdx; } else { - UErrorCode status = U_ZERO_ERROR; - srcIdx = utext_extract(m->fInputText, 0, nativeIdx, NULL, 0, &status); + UErrorCode newStatus = U_ZERO_ERROR; + srcIdx = utext_extract(m->fInputText, 0, nativeIdx, NULL, 0, &newStatus); } for (;;) { diff --git a/deps/icu-small/source/i18n/usearch.cpp b/deps/icu-small/source/i18n/usearch.cpp index e1e6c28e2bc985..0e4cca77a13ae0 100644 --- a/deps/icu-small/source/i18n/usearch.cpp +++ b/deps/icu-small/source/i18n/usearch.cpp @@ -498,7 +498,7 @@ inline void setShiftTable(int16_t shift[], int16_t backshift[], for (count = 0; count < cesize; count ++) { // number of ces from right of array to the count int temp = defaultforward - count - 1; - shift[hashFromCE32(cetable[count])] = temp > 1 ? temp : 1; + shift[hashFromCE32(cetable[count])] = temp > 1 ? static_cast(temp) : 1; } shift[hashFromCE32(cetable[cesize])] = 1; // for ignorables we just shift by one. see test examples. diff --git a/deps/icu-small/source/i18n/uspoof_impl.h b/deps/icu-small/source/i18n/uspoof_impl.h index 470a31f2c979bc..7d6d0f76e34275 100644 --- a/deps/icu-small/source/i18n/uspoof_impl.h +++ b/deps/icu-small/source/i18n/uspoof_impl.h @@ -20,7 +20,7 @@ #include "unicode/uspoof.h" #include "unicode/uscript.h" #include "unicode/udata.h" - +#include "udataswp.h" #include "utrie2.h" #if !UCONFIG_NO_NORMALIZATION diff --git a/deps/icu-small/source/i18n/vtzone.cpp b/deps/icu-small/source/i18n/vtzone.cpp index 0c76c9b6c98bf2..e39eada51b7f61 100644 --- a/deps/icu-small/source/i18n/vtzone.cpp +++ b/deps/icu-small/source/i18n/vtzone.cpp @@ -135,7 +135,7 @@ static UnicodeString& appendAsciiDigits(int32_t number, uint8_t length, UnicodeS digits[i++] = number % 10; number /= 10; } while (number != 0); - length = i; + length = static_cast(i); } else { // fixed digits for (i = 0; i < length; i++) { diff --git a/deps/icu-small/source/i18n/zonemeta.cpp b/deps/icu-small/source/i18n/zonemeta.cpp index 02562048a525da..b7139a807b3fb7 100644 --- a/deps/icu-small/source/i18n/zonemeta.cpp +++ b/deps/icu-small/source/i18n/zonemeta.cpp @@ -319,10 +319,10 @@ ZoneMeta::getCanonicalCLDRID(const UnicodeString &tzid, UErrorCode& status) { id[len] = (char) 0; // Make sure it is null terminated. // replace '/' with ':' - char *p = id; - while (*p++) { - if (*p == '/') { - *p = ':'; + char *q = id; + while (*q++) { + if (*q == '/') { + *q = ':'; } } @@ -850,13 +850,13 @@ ZoneMeta::createCustomTimeZone(int32_t offset) { negative = TRUE; tmp = -offset; } - int32_t hour, min, sec; + uint8_t hour, min, sec; tmp /= 1000; - sec = tmp % 60; + sec = static_cast(tmp % 60); tmp /= 60; - min = tmp % 60; - hour = tmp / 60; + min = static_cast(tmp % 60); + hour = static_cast(tmp / 60); UnicodeString zid; formatCustomID(hour, min, sec, negative, zid); diff --git a/deps/icu-small/source/tools/genrb/parse.cpp b/deps/icu-small/source/tools/genrb/parse.cpp index ddfb082afe63f4..1f6246d3cfbf46 100644 --- a/deps/icu-small/source/tools/genrb/parse.cpp +++ b/deps/icu-small/source/tools/genrb/parse.cpp @@ -1018,6 +1018,11 @@ addCollation(ParseState* state, TableResource *result, const char *collationTyp icu::CollationInfo::printReorderRanges( *t->data, t->settings->reorderCodes, t->settings->reorderCodesLength); } +#if 0 // debugging output + } else { + printf("%s~%s collation tailoring part sizes:\n", state->filename, collationType); + icu::CollationInfo::printSizes(totalSize, indexes); +#endif } struct SResource *collationBin = bin_open(state->bundle, "%%CollationBin", totalSize, dest, NULL, NULL, status); result->add(collationBin, line, *status); diff --git a/deps/icu-small/source/tools/genrb/reslist.cpp b/deps/icu-small/source/tools/genrb/reslist.cpp index 2e04bbce21ef74..0493347ebe5194 100644 --- a/deps/icu-small/source/tools/genrb/reslist.cpp +++ b/deps/icu-small/source/tools/genrb/reslist.cpp @@ -1395,7 +1395,7 @@ SRBRoot::compactKeys(UErrorCode &errorCode) { int32_t offset; suffix = keys + map[j].oldpos; for (suffixLimit = suffix; *suffixLimit != 0; ++suffixLimit) {} - offset = (int32_t)(keyLimit - key) - (suffixLimit - suffix); + offset = static_cast((keyLimit - key) - (suffixLimit - suffix)); if (offset < 0) { break; /* suffix cannot be longer than the original */ } diff --git a/deps/icu-small/source/tools/pkgdata/pkgdata.cpp b/deps/icu-small/source/tools/pkgdata/pkgdata.cpp index d4dc271732d80f..d7e5721c2d0fab 100644 --- a/deps/icu-small/source/tools/pkgdata/pkgdata.cpp +++ b/deps/icu-small/source/tools/pkgdata/pkgdata.cpp @@ -511,7 +511,7 @@ main(int argc, char* argv[]) { static int runCommand(const char* command, UBool specialHandling) { char *cmd = NULL; char cmdBuffer[SMALL_BUFFER_MAX_SIZE]; - int32_t len = strlen(command); + int32_t len = static_cast(strlen(command)); if (len == 0) { return 0; @@ -904,7 +904,8 @@ static void createFileNames(UPKGOptions *o, const char mode, const char *version if (IN_DLL_MODE(mode)) { sprintf(libFileNames[LIB_FILE], "%s", libName); } else { - sprintf(libFileNames[LIB_FILE], "%s%s", + sprintf(libFileNames[LIB_FILE], "%s%s%s", + (strstr(libName, "icudt") ? "lib" : ""), pkgDataFlags[LIBPREFIX], libName); } @@ -1020,7 +1021,7 @@ static int32_t pkg_createSymLinks(const char *targetDir, UBool specialHandling) char name2[SMALL_BUFFER_MAX_SIZE]; /* file name to symlink */ const char* FILE_EXTENSION_SEP = uprv_strlen(pkgDataFlags[SO_EXT]) == 0 ? "" : "."; -#if !defined(USING_CYGWIN) && U_PLATFORM != U_PF_MINGW +#if U_PLATFORM != U_PF_CYGWIN /* No symbolic link to make. */ if (uprv_strlen(libFileNames[LIB_FILE_VERSION]) == 0 || uprv_strlen(libFileNames[LIB_FILE_VERSION_MAJOR]) == 0 || uprv_strcmp(libFileNames[LIB_FILE_VERSION], libFileNames[LIB_FILE_VERSION_MAJOR]) == 0) { @@ -1225,7 +1226,7 @@ static int32_t pkg_installFileMode(const char *installDir, const char *srcDir, c if (f != NULL) { for(;;) { if (T_FileStream_readLine(f, buffer, SMALL_BUFFER_MAX_SIZE) != NULL) { - bufferLength = uprv_strlen(buffer); + bufferLength = static_cast(uprv_strlen(buffer)); /* Remove new line character. */ if (bufferLength > 0) { buffer[bufferLength-1] = 0; diff --git a/deps/icu-small/source/tools/toolutil/filestrm.cpp b/deps/icu-small/source/tools/toolutil/filestrm.cpp index cfffa1b75d7724..a170c7b0f29e2e 100644 --- a/deps/icu-small/source/tools/toolutil/filestrm.cpp +++ b/deps/icu-small/source/tools/toolutil/filestrm.cpp @@ -104,14 +104,14 @@ T_FileStream_tmpfile() U_CAPI int32_t U_EXPORT2 T_FileStream_read(FileStream* fileStream, void* addr, int32_t len) { - return fread(addr, 1, len, (FILE*)fileStream); + return static_cast(fread(addr, 1, len, (FILE*)fileStream)); } U_CAPI int32_t U_EXPORT2 T_FileStream_write(FileStream* fileStream, const void* addr, int32_t len) { - return fwrite(addr, 1, len, (FILE*)fileStream); + return static_cast(fwrite(addr, 1, len, (FILE*)fileStream)); } U_CAPI void U_EXPORT2 diff --git a/deps/icu-small/source/tools/toolutil/filetools.cpp b/deps/icu-small/source/tools/toolutil/filetools.cpp index 176a791b0df853..6e88c94b5200b5 100644 --- a/deps/icu-small/source/tools/toolutil/filetools.cpp +++ b/deps/icu-small/source/tools/toolutil/filetools.cpp @@ -134,7 +134,7 @@ static int32_t whichFileModTimeIsLater(const char *file1, const char *file2) { /* Swap the file separater character given with the new one in the file path. */ U_CAPI void U_EXPORT2 swapFileSepChar(char *filePath, const char oldFileSepChar, const char newFileSepChar) { - for (int32_t i = 0, length = uprv_strlen(filePath); i < length; i++) { + for (int32_t i = 0, length = static_cast(uprv_strlen(filePath)); i < length; i++) { filePath[i] = (filePath[i] == oldFileSepChar ) ? newFileSepChar : filePath[i]; } } diff --git a/deps/icu-small/source/tools/toolutil/package.cpp b/deps/icu-small/source/tools/toolutil/package.cpp index d96c6dd36ddb41..f4e428a37e7153 100644 --- a/deps/icu-small/source/tools/toolutil/package.cpp +++ b/deps/icu-small/source/tools/toolutil/package.cpp @@ -610,7 +610,7 @@ Package::readPackage(const char *filename) { memcpy(prefix, s, ++prefixLength); // include the / } else { // Use the package basename as prefix. - int32_t inPkgNameLength=strlen(inPkgName); + int32_t inPkgNameLength= static_cast(strlen(inPkgName)); memcpy(prefix, inPkgName, inPkgNameLength); prefixLength=inPkgNameLength; @@ -1043,7 +1043,7 @@ Package::addItem(const char *name, uint8_t *data, int32_t length, UBool isDataOw memset(items+idx, 0, sizeof(Item)); // copy the item's name - items[idx].name=allocString(TRUE, strlen(name)); + items[idx].name=allocString(TRUE, static_cast(strlen(name))); strcpy(items[idx].name, name); pathToTree(items[idx].name); } else { diff --git a/deps/icu-small/source/tools/toolutil/swapimpl.cpp b/deps/icu-small/source/tools/toolutil/swapimpl.cpp index f3f333a005eb43..e8850cb9864168 100644 --- a/deps/icu-small/source/tools/toolutil/swapimpl.cpp +++ b/deps/icu-small/source/tools/toolutil/swapimpl.cpp @@ -243,7 +243,7 @@ uprops_swap(const UDataSwapper *ds, * swap the main properties UTrie * PT serialized properties trie, see utrie.h (byte size: 4*(i0-16)) */ - utrie2_swapAnyVersion(ds, + utrie_swapAnyVersion(ds, inData32+UPROPS_INDEX_COUNT, 4*(dataIndexes[UPROPS_PROPS32_INDEX]-UPROPS_INDEX_COUNT), outData32+UPROPS_INDEX_COUNT, @@ -274,7 +274,7 @@ uprops_swap(const UDataSwapper *ds, * swap the additional UTrie * i3 additionalTrieIndex; -- 32-bit unit index to the additional trie for more properties */ - utrie2_swapAnyVersion(ds, + utrie_swapAnyVersion(ds, inData32+dataIndexes[UPROPS_ADDITIONAL_TRIE_INDEX], 4*(dataIndexes[UPROPS_ADDITIONAL_VECTORS_INDEX]-dataIndexes[UPROPS_ADDITIONAL_TRIE_INDEX]), outData32+dataIndexes[UPROPS_ADDITIONAL_TRIE_INDEX], @@ -336,7 +336,7 @@ ucase_swap(const UDataSwapper *ds, ((pInfo->formatVersion[0]==1 && pInfo->formatVersion[2]==UTRIE_SHIFT && pInfo->formatVersion[3]==UTRIE_INDEX_SHIFT) || - 2<=pInfo->formatVersion[0] || pInfo->formatVersion[0]<=4) + (2<=pInfo->formatVersion[0] && pInfo->formatVersion[0]<=4)) )) { udata_printError(ds, "ucase_swap(): data format %02x.%02x.%02x.%02x (format version %02x) is not recognized as case mapping data\n", pInfo->dataFormat[0], pInfo->dataFormat[1], @@ -391,7 +391,7 @@ ucase_swap(const UDataSwapper *ds, /* swap the UTrie */ count=indexes[UCASE_IX_TRIE_SIZE]; - utrie2_swapAnyVersion(ds, inBytes+offset, count, outBytes+offset, pErrorCode); + utrie_swapAnyVersion(ds, inBytes+offset, count, outBytes+offset, pErrorCode); offset+=count; /* swap the uint16_t exceptions[] and unfold[] */ @@ -493,7 +493,7 @@ ubidi_swap(const UDataSwapper *ds, /* swap the UTrie */ count=indexes[UBIDI_IX_TRIE_SIZE]; - utrie2_swapAnyVersion(ds, inBytes+offset, count, outBytes+offset, pErrorCode); + utrie_swapAnyVersion(ds, inBytes+offset, count, outBytes+offset, pErrorCode); offset+=count; /* swap the uint32_t mirrors[] */ diff --git a/deps/icu-small/source/tools/toolutil/udbgutil.cpp b/deps/icu-small/source/tools/toolutil/udbgutil.cpp index dcc80ebe069519..285f68a0ec66a1 100644 --- a/deps/icu-small/source/tools/toolutil/udbgutil.cpp +++ b/deps/icu-small/source/tools/toolutil/udbgutil.cpp @@ -400,7 +400,7 @@ U_CAPI int32_t paramStatic(const USystemParams *param, char *target, int32_t targetCapacity, UErrorCode *status) { if(param->paramStr==NULL) return paramEmpty(param,target,targetCapacity,status); if(U_FAILURE(*status))return 0; - int32_t len = uprv_strlen(param->paramStr); + int32_t len = static_cast(uprv_strlen(param->paramStr)); if(target!=NULL) { uprv_strncpy(target,param->paramStr,uprv_min(len,targetCapacity)); } @@ -412,14 +412,14 @@ static const char *nullString = "(null)"; static int32_t stringToStringBuffer(char *target, int32_t targetCapacity, const char *str, UErrorCode *status) { if(str==NULL) str=nullString; - int32_t len = uprv_strlen(str); + int32_t len = static_cast(uprv_strlen(str)); if (U_SUCCESS(*status)) { if(target!=NULL) { uprv_strncpy(target,str,uprv_min(len,targetCapacity)); } } else { const char *s = u_errorName(*status); - len = uprv_strlen(s); + len = static_cast(uprv_strlen(s)); if(target!=NULL) { uprv_strncpy(target,s,uprv_min(len,targetCapacity)); } diff --git a/deps/icu-small/source/tools/toolutil/unewdata.cpp b/deps/icu-small/source/tools/toolutil/unewdata.cpp index 5c28e992c9a98b..22d8540881f454 100644 --- a/deps/icu-small/source/tools/toolutil/unewdata.cpp +++ b/deps/icu-small/source/tools/toolutil/unewdata.cpp @@ -61,17 +61,17 @@ udata_create(const char *dir, const char *type, const char *name, length = 0; /* Start with nothing */ if(dir != NULL && *dir !=0) /* Add directory length if one was given */ { - length += strlen(dir); + length += static_cast(strlen(dir)); /* Add 1 if dir doesn't end with path sep */ if (dir[strlen(dir) - 1]!= U_FILE_SEP_CHAR) { length++; } } - length += strlen(name); /* Add the filename length */ + length += static_cast(strlen(name)); /* Add the filename length */ if(type != NULL && *type !=0) { /* Add directory length if given */ - length += strlen(type); + length += static_cast(strlen(type)); } diff --git a/deps/icu-small/source/tools/toolutil/writesrc.cpp b/deps/icu-small/source/tools/toolutil/writesrc.cpp index c05a07acd3aa34..1a1dd3964d34a2 100644 --- a/deps/icu-small/source/tools/toolutil/writesrc.cpp +++ b/deps/icu-small/source/tools/toolutil/writesrc.cpp @@ -22,13 +22,14 @@ #include #include "unicode/utypes.h" #include "unicode/putil.h" +#include "unicode/ucptrie.h" #include "utrie2.h" #include "cstring.h" #include "writesrc.h" static FILE * usrc_createWithHeader(const char *path, const char *filename, - const char *generator, const char *header) { + const char *header, const char *generator) { char buffer[1024]; const char *p; char *q; @@ -71,20 +72,34 @@ usrc_createWithHeader(const char *path, const char *filename, } U_CAPI FILE * U_EXPORT2 -usrc_create(const char *path, const char *filename, const char *generator) { - // TODO: Add parameter for the first year this file was generated, not before 2016. - static const char *header= - "// © 2016 and later: Unicode, Inc. and others.\n" - "// License & terms of use: http://www.unicode.org/copyright.html\n" - "//\n" - "// Copyright (C) 1999-2016, International Business Machines\n" - "// Corporation and others. All Rights Reserved.\n" - "//\n" - "// file name: %s\n" - "//\n" - "// machine-generated by: %s\n" - "\n\n"; - return usrc_createWithHeader(path, filename, generator, header); +usrc_create(const char *path, const char *filename, int32_t copyrightYear, const char *generator) { + const char *header; + char buffer[200]; + if(copyrightYear<=2016) { + header= + "// © 2016 and later: Unicode, Inc. and others.\n" + "// License & terms of use: http://www.unicode.org/copyright.html\n" + "//\n" + "// Copyright (C) 1999-2016, International Business Machines\n" + "// Corporation and others. All Rights Reserved.\n" + "//\n" + "// file name: %s\n" + "//\n" + "// machine-generated by: %s\n" + "\n\n"; + } else { + sprintf(buffer, + "// © %d and later: Unicode, Inc. and others.\n" + "// License & terms of use: http://www.unicode.org/copyright.html\n" + "//\n" + "// file name: %%s\n" + "//\n" + "// machine-generated by: %%s\n" + "\n\n", + (int)copyrightYear); + header=buffer; + } + return usrc_createWithHeader(path, filename, header, generator); } U_CAPI FILE * U_EXPORT2 @@ -100,7 +115,7 @@ usrc_createTextData(const char *path, const char *filename, const char *generato "#\n" "# machine-generated by: %s\n" "\n\n"; - return usrc_createWithHeader(path, filename, generator, header); + return usrc_createWithHeader(path, filename, header, generator); } U_CAPI void U_EXPORT2 @@ -228,6 +243,68 @@ usrc_writeUTrie2Struct(FILE *f, } } +U_CAPI void U_EXPORT2 +usrc_writeUCPTrieArrays(FILE *f, + const char *indexPrefix, const char *dataPrefix, + const UCPTrie *pTrie, + const char *postfix) { + usrc_writeArray(f, indexPrefix, pTrie->index, 16, pTrie->indexLength, postfix); + int32_t width= + pTrie->valueWidth==UCPTRIE_VALUE_BITS_16 ? 16 : + pTrie->valueWidth==UCPTRIE_VALUE_BITS_32 ? 32 : + pTrie->valueWidth==UCPTRIE_VALUE_BITS_8 ? 8 : 0; + usrc_writeArray(f, dataPrefix, pTrie->data.ptr0, width, pTrie->dataLength, postfix); +} + +U_CAPI void U_EXPORT2 +usrc_writeUCPTrieStruct(FILE *f, + const char *prefix, + const UCPTrie *pTrie, + const char *indexName, const char *dataName, + const char *postfix) { + if(prefix!=NULL) { + fputs(prefix, f); + } + fprintf( + f, + " %s,\n" // index + " { %s },\n", // data (union) + indexName, + dataName); + fprintf( + f, + " %ld, %ld,\n" // indexLength, dataLength + " 0x%lx, 0x%x,\n" // highStart, shifted12HighStart + " %d, %d,\n" // type, valueWidth + " 0, 0,\n" // reserved32, reserved16 + " 0x%x, 0x%lx,\n" // index3NullOffset, dataNullOffset + " 0x%lx,\n", // nullValue + (long)pTrie->indexLength, (long)pTrie->dataLength, + (long)pTrie->highStart, pTrie->shifted12HighStart, + pTrie->type, pTrie->valueWidth, + pTrie->index3NullOffset, (long)pTrie->dataNullOffset, + (long)pTrie->nullValue); + if(postfix!=NULL) { + fputs(postfix, f); + } +} + +U_CAPI void U_EXPORT2 +usrc_writeUCPTrie(FILE *f, const char *name, const UCPTrie *pTrie) { + int32_t width= + pTrie->valueWidth==UCPTRIE_VALUE_BITS_16 ? 16 : + pTrie->valueWidth==UCPTRIE_VALUE_BITS_32 ? 32 : + pTrie->valueWidth==UCPTRIE_VALUE_BITS_8 ? 8 : 0; + char line[100], line2[100], line3[100]; + sprintf(line, "static const uint16_t %s_trieIndex[%%ld]={\n", name); + sprintf(line2, "static const uint%d_t %s_trieData[%%ld]={\n", (int)width, name); + usrc_writeUCPTrieArrays(f, line, line2, pTrie, "\n};\n\n"); + sprintf(line, "static const UCPTrie %s_trie={\n", name); + sprintf(line2, "%s_trieIndex", name); + sprintf(line3, "%s_trieData", name); + usrc_writeUCPTrieStruct(f, line, pTrie, line2, line3, "};\n\n"); +} + U_CAPI void U_EXPORT2 usrc_writeArrayOfMostlyInvChars(FILE *f, const char *prefix, diff --git a/deps/icu-small/source/tools/toolutil/writesrc.h b/deps/icu-small/source/tools/toolutil/writesrc.h index fdcf1f9a6b40f3..35ba256793c03a 100644 --- a/deps/icu-small/source/tools/toolutil/writesrc.h +++ b/deps/icu-small/source/tools/toolutil/writesrc.h @@ -23,6 +23,7 @@ #include #include "unicode/utypes.h" +#include "unicode/ucptrie.h" #include "utrie2.h" /** @@ -30,7 +31,7 @@ * Writes a C/Java-style comment with the generator name. */ U_CAPI FILE * U_EXPORT2 -usrc_create(const char *path, const char *filename, const char *generator); +usrc_create(const char *path, const char *filename, int32_t copyrightYear, const char *generator); /** * Creates a source text file and writes a header comment with the ICU copyright. @@ -75,6 +76,33 @@ usrc_writeUTrie2Struct(FILE *f, const char *indexName, const char *dataName, const char *postfix); +/** + * Calls usrc_writeArray() for the index and data arrays of a UCPTrie. + */ +U_CAPI void U_EXPORT2 +usrc_writeUCPTrieArrays(FILE *f, + const char *indexPrefix, const char *dataPrefix, + const UCPTrie *pTrie, + const char *postfix); + +/** + * Writes the UCPTrie struct values. + * The {} and declaration etc. need to be included in prefix/postfix or + * printed before and after the array contents. + */ +U_CAPI void U_EXPORT2 +usrc_writeUCPTrieStruct(FILE *f, + const char *prefix, + const UCPTrie *pTrie, + const char *indexName, const char *dataName, + const char *postfix); + +/** + * Writes the UCPTrie arrays and struct values. + */ +U_CAPI void U_EXPORT2 +usrc_writeUCPTrie(FILE *f, const char *name, const UCPTrie *pTrie); + /** * Writes the contents of an array of mostly invariant characters. * Characters 0..0x1f are printed as numbers, diff --git a/tools/icu/current_ver.dep b/tools/icu/current_ver.dep index 5e439928ebb540..ce0d89485ab312 100644 --- a/tools/icu/current_ver.dep +++ b/tools/icu/current_ver.dep @@ -1,6 +1,14 @@ [ { - "url": "https://sourceforge.net/projects/icu/files/ICU4C/62.1/icu4c-62_1-src.zip", - "md5": "408854f7b9b58311b68fab4b4dfc80be" + "url": "https://github.com/unicode-org/icu/releases/download/release-63-1/icu4c-63_1-src.zip", + "md5": "d25bc38089db64668fd86f34b4aa9b93" + }, + { + "url": "https://sourceforge.net/projects/icu/files/ICU4C/63.1/icu4c-63_1-src.zip", + "md5": "d25bc38089db64668fd86f34b4aa9b93" + }, + { + "url": "https://download.icu-project.org/files/icu4c/63.1/icu4c-63_1-src.zip", + "md5": "d25bc38089db64668fd86f34b4aa9b93" } ]