From 538acead6670d711ddb71c0b852089b792c996e3 Mon Sep 17 00:00:00 2001 From: "Steven R. Loomis" Date: Mon, 9 Jul 2018 13:46:16 -0700 Subject: [PATCH] deps: icu 62.1 bump (Unicode 11, CLDR 33.1) - Full release notes: http://site.icu-project.org/download/62 Fixes: https://github.com/nodejs/node/issues/21452 PR-URL: https://github.com/nodejs/node/pull/21728 Reviewed-By: James M Snell Reviewed-By: Bradley Farias Reviewed-By: Gus Caplan Reviewed-By: Tiancheng "Timothy" Gu Reviewed-By: Richard Lau --- configure | 4 +- deps/icu-small/README-SMALL-ICU.txt | 4 +- deps/icu-small/source/common/charstr.cpp | 12 + deps/icu-small/source/common/charstr.h | 12 + deps/icu-small/source/common/cmemory.h | 45 +- deps/icu-small/source/common/edits.cpp | 29 +- deps/icu-small/source/common/locmap.cpp | 2 +- deps/icu-small/source/common/norm2_nfc_data.h | 1155 +-- deps/icu-small/source/common/propname_data.h | 1744 ++--- deps/icu-small/source/common/putil.cpp | 22 + deps/icu-small/source/common/putilimp.h | 26 + deps/icu-small/source/common/rbbi.cpp | 112 +- deps/icu-small/source/common/rbbi_cache.cpp | 49 +- deps/icu-small/source/common/rbbidata.cpp | 41 - deps/icu-small/source/common/rbbidata.h | 8 +- deps/icu-small/source/common/rbbirb.cpp | 206 +- deps/icu-small/source/common/rbbirb.h | 23 +- deps/icu-small/source/common/rbbiscan.cpp | 18 +- deps/icu-small/source/common/rbbisetb.cpp | 12 +- deps/icu-small/source/common/rbbisetb.h | 8 +- deps/icu-small/source/common/rbbitblb.cpp | 345 +- deps/icu-small/source/common/rbbitblb.h | 77 +- deps/icu-small/source/common/serv.cpp | 3 +- .../source/common/static_unicode_sets.cpp | 222 + .../source/common/static_unicode_sets.h | 119 + .../source/common/ubidi_props_data.h | 1403 ++-- deps/icu-small/source/common/ucase.cpp | 53 +- deps/icu-small/source/common/ucase.h | 18 +- .../source/common/ucase_props_data.h | 1501 ++-- .../source/common/uchar_props_data.h | 6399 +++++++++-------- deps/icu-small/source/common/ucln_cmn.h | 1 + deps/icu-small/source/common/ucnv_bld.cpp | 11 +- deps/icu-small/source/common/ucnv_bld.h | 3 + deps/icu-small/source/common/ucurr.cpp | 189 +- deps/icu-small/source/common/ucurrimp.h | 17 + .../icu-small/source/common/unicode/brkiter.h | 2 +- .../source/common/unicode/bytestriebuilder.h | 2 +- .../icu-small/source/common/unicode/caniter.h | 4 +- .../icu-small/source/common/unicode/docmain.h | 2 +- deps/icu-small/source/common/unicode/edits.h | 150 +- .../source/common/unicode/platform.h | 14 - deps/icu-small/source/common/unicode/rbbi.h | 24 +- deps/icu-small/source/common/unicode/uchar.h | 45 +- deps/icu-small/source/common/unicode/unistr.h | 6 +- .../icu-small/source/common/unicode/urename.h | 13 + .../icu-small/source/common/unicode/uscript.h | 17 +- deps/icu-small/source/common/unicode/utypes.h | 5 +- .../icu-small/source/common/unicode/uvernum.h | 10 +- deps/icu-small/source/common/uprops.cpp | 1 + deps/icu-small/source/common/uprops.h | 6 +- .../icu-small/source/common/uscript_props.cpp | 9 +- deps/icu-small/source/common/ustr_cnv.cpp | 3 +- deps/icu-small/source/common/util.h | 7 + deps/icu-small/source/common/utypes.cpp | 3 +- deps/icu-small/source/common/wintz.cpp | 28 +- .../data/in/{icudt61l.dat => icudt62l.dat} | Bin 2795984 -> 2808160 bytes .../source/i18n/affixpatternparser.cpp | 698 -- .../source/i18n/affixpatternparser.h | 402 -- deps/icu-small/source/i18n/collationfcd.cpp | 98 +- .../source/i18n/compactdecimalformat.cpp | 1020 +-- deps/icu-small/source/i18n/currpinf.cpp | 3 + deps/icu-small/source/i18n/currunit.cpp | 33 +- deps/icu-small/source/i18n/dcfmtimp.h | 54 - deps/icu-small/source/i18n/dcfmtsym.cpp | 10 +- deps/icu-small/source/i18n/decfmtst.cpp | 251 - deps/icu-small/source/i18n/decfmtst.h | 69 - .../source/i18n/decimalformatpattern.cpp | 656 -- .../source/i18n/decimalformatpattern.h | 106 - .../source/i18n/decimalformatpatternimpl.h | 35 - deps/icu-small/source/i18n/decimfmt.cpp | 4228 +++-------- deps/icu-small/source/i18n/decimfmtimpl.cpp | 1596 ---- deps/icu-small/source/i18n/decimfmtimpl.h | 549 -- deps/icu-small/source/i18n/digitaffix.cpp | 109 - deps/icu-small/source/i18n/digitaffix.h | 104 - .../source/i18n/digitaffixesandpadding.cpp | 175 - .../source/i18n/digitaffixesandpadding.h | 179 - deps/icu-small/source/i18n/digitformatter.cpp | 417 -- deps/icu-small/source/i18n/digitformatter.h | 288 - deps/icu-small/source/i18n/digitgrouping.cpp | 58 - deps/icu-small/source/i18n/digitgrouping.h | 112 - deps/icu-small/source/i18n/digitinterval.cpp | 55 - deps/icu-small/source/i18n/digitinterval.h | 159 - deps/icu-small/source/i18n/digitlst.cpp | 1143 --- deps/icu-small/source/i18n/digitlst.h | 529 -- .../source/i18n/double-conversion-strtod.cpp | 574 ++ .../source/i18n/double-conversion-strtod.h | 63 + .../source/i18n/double-conversion-utils.h | 4 +- .../source/i18n/double-conversion.cpp | 7 +- .../icu-small/source/i18n/double-conversion.h | 2 +- deps/icu-small/source/i18n/fmtable.cpp | 160 +- deps/icu-small/source/i18n/fmtableimp.h | 12 +- deps/icu-small/source/i18n/fphdlimp.cpp | 21 +- deps/icu-small/source/i18n/fphdlimp.h | 23 +- deps/icu-small/source/i18n/measunit.cpp | 87 +- deps/icu-small/source/i18n/msgfmt.cpp | 32 +- deps/icu-small/source/i18n/nfsubs.cpp | 25 +- .../source/i18n/number_affixutils.cpp | 62 +- .../icu-small/source/i18n/number_affixutils.h | 65 +- .../icu-small/source/i18n/number_asformat.cpp | 105 + deps/icu-small/source/i18n/number_asformat.h | 107 + deps/icu-small/source/i18n/number_capi.cpp | 213 + deps/icu-small/source/i18n/number_compact.cpp | 15 +- deps/icu-small/source/i18n/number_compact.h | 2 +- .../source/i18n/number_currencysymbols.cpp | 123 + .../source/i18n/number_currencysymbols.h | 65 + .../source/i18n/number_decimalquantity.cpp | 418 +- .../source/i18n/number_decimalquantity.h | 92 +- .../source/i18n/number_decimfmtprops.cpp | 80 +- .../source/i18n/number_decimfmtprops.h | 81 +- deps/icu-small/source/i18n/number_decnum.h | 77 + deps/icu-small/source/i18n/number_fluent.cpp | 627 +- .../source/i18n/number_formatimpl.cpp | 274 +- .../icu-small/source/i18n/number_formatimpl.h | 33 +- .../icu-small/source/i18n/number_grouping.cpp | 33 +- .../source/i18n/number_integerwidth.cpp | 28 +- .../source/i18n/number_longnames.cpp | 7 +- deps/icu-small/source/i18n/number_longnames.h | 2 +- deps/icu-small/source/i18n/number_mapper.cpp | 502 ++ deps/icu-small/source/i18n/number_mapper.h | 206 + .../icu-small/source/i18n/number_microprops.h | 82 + .../source/i18n/number_modifiers.cpp | 6 +- deps/icu-small/source/i18n/number_modifiers.h | 2 +- .../source/i18n/number_multiplier.cpp | 156 + .../icu-small/source/i18n/number_multiplier.h | 57 + .../icu-small/source/i18n/number_notation.cpp | 15 +- deps/icu-small/source/i18n/number_padding.cpp | 14 +- .../source/i18n/number_patternmodifier.cpp | 243 +- .../source/i18n/number_patternmodifier.h | 52 +- .../source/i18n/number_patternstring.cpp | 323 +- .../source/i18n/number_patternstring.h | 117 +- .../icu-small/source/i18n/number_rounding.cpp | 203 +- .../source/i18n/number_roundingutils.h | 57 +- .../source/i18n/number_scientific.cpp | 23 +- .../icu-small/source/i18n/number_scientific.h | 2 +- .../source/i18n/number_skeletons.cpp | 1510 ++++ deps/icu-small/source/i18n/number_skeletons.h | 327 + .../source/i18n/number_stringbuilder.cpp | 59 +- .../source/i18n/number_stringbuilder.h | 16 +- deps/icu-small/source/i18n/number_types.h | 92 +- deps/icu-small/source/i18n/number_utils.cpp | 253 + deps/icu-small/source/i18n/number_utils.h | 150 +- deps/icu-small/source/i18n/number_utypes.h | 79 + deps/icu-small/source/i18n/numfmt.cpp | 92 +- .../source/i18n/numparse_affixes.cpp | 470 ++ deps/icu-small/source/i18n/numparse_affixes.h | 255 + .../source/i18n/numparse_compositions.cpp | 107 + .../source/i18n/numparse_compositions.h | 124 + .../source/i18n/numparse_currency.cpp | 186 + .../icu-small/source/i18n/numparse_currency.h | 74 + .../source/i18n/numparse_decimal.cpp | 458 ++ deps/icu-small/source/i18n/numparse_decimal.h | 76 + deps/icu-small/source/i18n/numparse_impl.cpp | 361 + deps/icu-small/source/i18n/numparse_impl.h | 109 + .../source/i18n/numparse_parsednumber.cpp | 122 + .../source/i18n/numparse_scientific.cpp | 133 + .../source/i18n/numparse_scientific.h | 45 + .../source/i18n/numparse_stringsegment.cpp | 146 + .../source/i18n/numparse_stringsegment.h | 24 + .../source/i18n/numparse_symbols.cpp | 193 + deps/icu-small/source/i18n/numparse_symbols.h | 173 + deps/icu-small/source/i18n/numparse_types.h | 377 + deps/icu-small/source/i18n/numparse_utils.h | 43 + .../source/i18n/numparse_validators.cpp | 85 + .../source/i18n/numparse_validators.h | 95 + deps/icu-small/source/i18n/pluralaffix.cpp | 104 - deps/icu-small/source/i18n/pluralaffix.h | 177 - deps/icu-small/source/i18n/plurfmt.cpp | 59 +- deps/icu-small/source/i18n/plurrule.cpp | 63 +- deps/icu-small/source/i18n/plurrule_impl.h | 133 +- deps/icu-small/source/i18n/precision.cpp | 444 -- deps/icu-small/source/i18n/precision.h | 323 - .../source/i18n/quantityformatter.cpp | 10 +- deps/icu-small/source/i18n/rbnf.cpp | 54 +- deps/icu-small/source/i18n/reldatefmt.cpp | 3 +- .../source/i18n/scientificnumberformatter.cpp | 17 +- .../source/i18n/significantdigitinterval.h | 92 - .../source/i18n/smallintformatter.cpp | 2622 ------- .../icu-small/source/i18n/smallintformatter.h | 90 - deps/icu-small/source/i18n/smpdtfmt.cpp | 358 +- deps/icu-small/source/i18n/timezone.cpp | 5 +- deps/icu-small/source/i18n/ucln_in.h | 1 + .../i18n/unicode/compactdecimalformat.h | 267 +- deps/icu-small/source/i18n/unicode/currunit.h | 5 +- deps/icu-small/source/i18n/unicode/dcfmtsym.h | 9 +- deps/icu-small/source/i18n/unicode/decimfmt.h | 754 +- deps/icu-small/source/i18n/unicode/fmtable.h | 35 +- deps/icu-small/source/i18n/unicode/fpositer.h | 8 - deps/icu-small/source/i18n/unicode/measunit.h | 8 - deps/icu-small/source/i18n/unicode/nounit.h | 12 +- .../source/i18n/unicode/numberformatter.h | 1498 ++-- deps/icu-small/source/i18n/unicode/numfmt.h | 18 +- deps/icu-small/source/i18n/unicode/plurrule.h | 21 - deps/icu-small/source/i18n/unicode/rbnf.h | 4 +- .../i18n/unicode/scientificnumberformatter.h | 5 - deps/icu-small/source/i18n/unicode/smpdtfmt.h | 39 +- deps/icu-small/source/i18n/unicode/timezone.h | 2 + deps/icu-small/source/i18n/unicode/unum.h | 31 +- .../source/i18n/unicode/unumberformatter.h | 666 ++ deps/icu-small/source/i18n/unicode/uspoof.h | 25 +- deps/icu-small/source/i18n/upluralrules.cpp | 37 +- deps/icu-small/source/i18n/uspoof.cpp | 197 +- deps/icu-small/source/i18n/uspoof_build.cpp | 21 + deps/icu-small/source/i18n/uspoof_conf.cpp | 37 +- deps/icu-small/source/i18n/uspoof_impl.cpp | 50 +- deps/icu-small/source/i18n/uspoof_impl.h | 3 + deps/icu-small/source/i18n/valueformatter.cpp | 223 - deps/icu-small/source/i18n/valueformatter.h | 161 - deps/icu-small/source/i18n/visibledigits.cpp | 186 - deps/icu-small/source/i18n/visibledigits.h | 162 - deps/icu-small/source/i18n/windtfmt.cpp | 3 +- deps/icu-small/source/i18n/zonemeta.cpp | 1 + .../source/tools/toolutil/swapimpl.cpp | 2 +- .../source/tools/toolutil/udbgutil.cpp | 1 - 213 files changed, 22259 insertions(+), 25980 deletions(-) create mode 100644 deps/icu-small/source/common/static_unicode_sets.cpp create mode 100644 deps/icu-small/source/common/static_unicode_sets.h rename deps/icu-small/source/data/in/{icudt61l.dat => icudt62l.dat} (65%) delete mode 100644 deps/icu-small/source/i18n/affixpatternparser.cpp delete mode 100644 deps/icu-small/source/i18n/affixpatternparser.h delete mode 100644 deps/icu-small/source/i18n/dcfmtimp.h delete mode 100644 deps/icu-small/source/i18n/decfmtst.cpp delete mode 100644 deps/icu-small/source/i18n/decfmtst.h delete mode 100644 deps/icu-small/source/i18n/decimalformatpattern.cpp delete mode 100644 deps/icu-small/source/i18n/decimalformatpattern.h delete mode 100644 deps/icu-small/source/i18n/decimalformatpatternimpl.h delete mode 100644 deps/icu-small/source/i18n/decimfmtimpl.cpp delete mode 100644 deps/icu-small/source/i18n/decimfmtimpl.h delete mode 100644 deps/icu-small/source/i18n/digitaffix.cpp delete mode 100644 deps/icu-small/source/i18n/digitaffix.h delete mode 100644 deps/icu-small/source/i18n/digitaffixesandpadding.cpp delete mode 100644 deps/icu-small/source/i18n/digitaffixesandpadding.h delete mode 100644 deps/icu-small/source/i18n/digitformatter.cpp delete mode 100644 deps/icu-small/source/i18n/digitformatter.h delete mode 100644 deps/icu-small/source/i18n/digitgrouping.cpp delete mode 100644 deps/icu-small/source/i18n/digitgrouping.h delete mode 100644 deps/icu-small/source/i18n/digitinterval.cpp delete mode 100644 deps/icu-small/source/i18n/digitinterval.h delete mode 100644 deps/icu-small/source/i18n/digitlst.cpp delete mode 100644 deps/icu-small/source/i18n/digitlst.h create mode 100644 deps/icu-small/source/i18n/double-conversion-strtod.cpp create mode 100644 deps/icu-small/source/i18n/double-conversion-strtod.h create mode 100644 deps/icu-small/source/i18n/number_asformat.cpp create mode 100644 deps/icu-small/source/i18n/number_asformat.h create mode 100644 deps/icu-small/source/i18n/number_capi.cpp create mode 100644 deps/icu-small/source/i18n/number_currencysymbols.cpp create mode 100644 deps/icu-small/source/i18n/number_currencysymbols.h create mode 100644 deps/icu-small/source/i18n/number_decnum.h create mode 100644 deps/icu-small/source/i18n/number_mapper.cpp create mode 100644 deps/icu-small/source/i18n/number_mapper.h create mode 100644 deps/icu-small/source/i18n/number_microprops.h create mode 100644 deps/icu-small/source/i18n/number_multiplier.cpp create mode 100644 deps/icu-small/source/i18n/number_multiplier.h create mode 100644 deps/icu-small/source/i18n/number_skeletons.cpp create mode 100644 deps/icu-small/source/i18n/number_skeletons.h create mode 100644 deps/icu-small/source/i18n/number_utils.cpp create mode 100644 deps/icu-small/source/i18n/number_utypes.h create mode 100644 deps/icu-small/source/i18n/numparse_affixes.cpp create mode 100644 deps/icu-small/source/i18n/numparse_affixes.h create mode 100644 deps/icu-small/source/i18n/numparse_compositions.cpp create mode 100644 deps/icu-small/source/i18n/numparse_compositions.h create mode 100644 deps/icu-small/source/i18n/numparse_currency.cpp create mode 100644 deps/icu-small/source/i18n/numparse_currency.h create mode 100644 deps/icu-small/source/i18n/numparse_decimal.cpp create mode 100644 deps/icu-small/source/i18n/numparse_decimal.h create mode 100644 deps/icu-small/source/i18n/numparse_impl.cpp create mode 100644 deps/icu-small/source/i18n/numparse_impl.h create mode 100644 deps/icu-small/source/i18n/numparse_parsednumber.cpp create mode 100644 deps/icu-small/source/i18n/numparse_scientific.cpp create mode 100644 deps/icu-small/source/i18n/numparse_scientific.h create mode 100644 deps/icu-small/source/i18n/numparse_stringsegment.cpp create mode 100644 deps/icu-small/source/i18n/numparse_stringsegment.h create mode 100644 deps/icu-small/source/i18n/numparse_symbols.cpp create mode 100644 deps/icu-small/source/i18n/numparse_symbols.h create mode 100644 deps/icu-small/source/i18n/numparse_types.h create mode 100644 deps/icu-small/source/i18n/numparse_utils.h create mode 100644 deps/icu-small/source/i18n/numparse_validators.cpp create mode 100644 deps/icu-small/source/i18n/numparse_validators.h delete mode 100644 deps/icu-small/source/i18n/pluralaffix.cpp delete mode 100644 deps/icu-small/source/i18n/pluralaffix.h delete mode 100644 deps/icu-small/source/i18n/precision.cpp delete mode 100644 deps/icu-small/source/i18n/precision.h delete mode 100644 deps/icu-small/source/i18n/significantdigitinterval.h delete mode 100644 deps/icu-small/source/i18n/smallintformatter.cpp delete mode 100644 deps/icu-small/source/i18n/smallintformatter.h create mode 100644 deps/icu-small/source/i18n/unicode/unumberformatter.h delete mode 100644 deps/icu-small/source/i18n/valueformatter.cpp delete mode 100644 deps/icu-small/source/i18n/valueformatter.h delete mode 100644 deps/icu-small/source/i18n/visibledigits.cpp delete mode 100644 deps/icu-small/source/i18n/visibledigits.h diff --git a/configure b/configure index 3a9ab424145..094d8e09f74 100755 --- a/configure +++ b/configure @@ -1185,8 +1185,8 @@ def glob_to_var(dir_base, dir_sub, patch_dir): def configure_intl(o): icus = [ { - 'url': 'https://ssl.icu-project.org/files/icu4c/61.1/icu4c-61_1-src.zip', - 'md5': '780d8524c8a860ed8d8f6fe75cb7ce3f', + 'url': 'https://sourceforge.net/projects/icu/files/ICU4C/62.1/icu4c-62_1-src.zip', + 'md5': '408854f7b9b58311b68fab4b4dfc80be', }, ] def icu_download(path): diff --git a/deps/icu-small/README-SMALL-ICU.txt b/deps/icu-small/README-SMALL-ICU.txt index b3919ec52b2..b98a5284856 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 61 source files with the following exception(s): -* deps/icu-small/source/data/in/icudt61l.dat : Reduced-size data file +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 To rebuild this directory, see ../../tools/icu/README.md diff --git a/deps/icu-small/source/common/charstr.cpp b/deps/icu-small/source/common/charstr.cpp index 8bacd20ddc7..353f1d52542 100644 --- a/deps/icu-small/source/common/charstr.cpp +++ b/deps/icu-small/source/common/charstr.cpp @@ -23,6 +23,18 @@ U_NAMESPACE_BEGIN +CharString::CharString(CharString&& src) U_NOEXCEPT + : buffer(std::move(src.buffer)), len(src.len) { + src.len = 0; // not strictly necessary because we make no guarantees on the source string +} + +CharString& CharString::operator=(CharString&& src) U_NOEXCEPT { + buffer = std::move(src.buffer); + len = src.len; + src.len = 0; // not strictly necessary because we make no guarantees on the source string + return *this; +} + CharString &CharString::copyFrom(const CharString &s, UErrorCode &errorCode) { if(U_SUCCESS(errorCode) && this!=&s && ensureCapacity(s.len+1, 0, errorCode)) { len=s.len; diff --git a/deps/icu-small/source/common/charstr.h b/deps/icu-small/source/common/charstr.h index 3cfdf6a897a..86f69c383a0 100644 --- a/deps/icu-small/source/common/charstr.h +++ b/deps/icu-small/source/common/charstr.h @@ -55,6 +55,18 @@ public: } ~CharString() {} + /** + * Move constructor; might leave src in an undefined state. + * This string will have the same contents and state that the source string had. + */ + CharString(CharString &&src) U_NOEXCEPT; + /** + * Move assignment operator; might leave src in an undefined state. + * This string will have the same contents and state that the source string had. + * The behavior is undefined if *this and src are the same object. + */ + CharString &operator=(CharString &&src) U_NOEXCEPT; + /** * Replaces this string's contents with the other string's contents. * CharString does not support the standard copy constructor nor diff --git a/deps/icu-small/source/common/cmemory.h b/deps/icu-small/source/common/cmemory.h index a44f9a19029..f98e13efc0f 100644 --- a/deps/icu-small/source/common/cmemory.h +++ b/deps/icu-small/source/common/cmemory.h @@ -299,6 +299,14 @@ public: * Destructor deletes the array (if owned). */ ~MaybeStackArray() { releaseArray(); } + /** + * Move constructor: transfers ownership or copies the stack array. + */ + MaybeStackArray(MaybeStackArray &&src) U_NOEXCEPT; + /** + * Move assignment: transfers ownership or copies the stack array. + */ + MaybeStackArray &operator=(MaybeStackArray &&src) U_NOEXCEPT; /** * Returns the array capacity (number of T items). * @return array capacity @@ -376,6 +384,11 @@ private: uprv_free(ptr); } } + void resetToStackArray() { + ptr=stackArray; + capacity=stackCapacity; + needToRelease=FALSE; + } /* No comparison operators with other MaybeStackArray's. */ bool operator==(const MaybeStackArray & /*other*/) {return FALSE;} bool operator!=(const MaybeStackArray & /*other*/) {return TRUE;} @@ -398,6 +411,34 @@ private: #endif }; +template +icu::MaybeStackArray::MaybeStackArray( + MaybeStackArray && src) U_NOEXCEPT + : ptr(src.ptr), capacity(src.capacity), needToRelease(src.needToRelease) { + if (src.ptr == src.stackArray) { + ptr = stackArray; + uprv_memcpy(stackArray, src.stackArray, sizeof(T) * src.capacity); + } else { + src.resetToStackArray(); // take ownership away from src + } +} + +template +inline MaybeStackArray & +MaybeStackArray::operator=(MaybeStackArray && src) U_NOEXCEPT { + releaseArray(); // in case this instance had its own memory allocated + capacity = src.capacity; + needToRelease = src.needToRelease; + if (src.ptr == src.stackArray) { + ptr = stackArray; + uprv_memcpy(stackArray, src.stackArray, sizeof(T) * src.capacity); + } else { + ptr = src.ptr; + src.resetToStackArray(); // take ownership away from src + } + return *this; +} + template inline T *MaybeStackArray::resize(int32_t newCapacity, int32_t length) { if(newCapacity>0) { @@ -447,9 +488,7 @@ inline T *MaybeStackArray::orphanOrClone(int32_t length, int32 uprv_memcpy(p, ptr, (size_t)length*sizeof(T)); } resultCapacity=length; - ptr=stackArray; - capacity=stackCapacity; - needToRelease=FALSE; + resetToStackArray(); return p; } diff --git a/deps/icu-small/source/common/edits.cpp b/deps/icu-small/source/common/edits.cpp index 9ec005624fe..3b3611fcf80 100644 --- a/deps/icu-small/source/common/edits.cpp +++ b/deps/icu-small/source/common/edits.cpp @@ -4,10 +4,12 @@ // edits.cpp // created: 2017feb08 Markus W. Scherer -#include "unicode/utypes.h" #include "unicode/edits.h" +#include "unicode/unistr.h" +#include "unicode/utypes.h" #include "cmemory.h" #include "uassert.h" +#include "util.h" U_NAMESPACE_BEGIN @@ -773,4 +775,29 @@ int32_t Edits::Iterator::sourceIndexFromDestinationIndex(int32_t i, UErrorCode & } } +UnicodeString& Edits::Iterator::toString(UnicodeString& sb) const { + sb.append(u"{ src[", -1); + ICU_Utility::appendNumber(sb, srcIndex); + sb.append(u"..", -1); + ICU_Utility::appendNumber(sb, srcIndex + oldLength_); + if (changed) { + sb.append(u"] ⇝ dest[", -1); + } else { + sb.append(u"] ≡ dest[", -1); + } + ICU_Utility::appendNumber(sb, destIndex); + sb.append(u"..", -1); + ICU_Utility::appendNumber(sb, destIndex + newLength_); + if (changed) { + sb.append(u"], repl[", -1); + ICU_Utility::appendNumber(sb, replIndex); + sb.append(u"..", -1); + ICU_Utility::appendNumber(sb, replIndex + newLength_); + sb.append(u"] }", -1); + } else { + sb.append(u"] (no-change) }", -1); + } + return sb; +} + U_NAMESPACE_END diff --git a/deps/icu-small/source/common/locmap.cpp b/deps/icu-small/source/common/locmap.cpp index 029c1edf032..a3cf2d5eb2d 100644 --- a/deps/icu-small/source/common/locmap.cpp +++ b/deps/icu-small/source/common/locmap.cpp @@ -1015,7 +1015,7 @@ static const char* getPosixID(const ILcidPosixMap *this_0, uint32_t hostID) { uint32_t i; - for (i = 0; i <= this_0->numRegions; i++) + for (i = 0; i < this_0->numRegions; i++) { if (this_0->regionMaps[i].hostID == hostID) { diff --git a/deps/icu-small/source/common/norm2_nfc_data.h b/deps/icu-small/source/common/norm2_nfc_data.h index 8f5c4346db5..c8bf440ae10 100644 --- a/deps/icu-small/source/common/norm2_nfc_data.h +++ b/deps/icu-small/source/common/norm2_nfc_data.h @@ -12,625 +12,638 @@ #ifdef INCLUDED_FROM_NORMALIZER2_CPP static const UVersionInfo norm2_nfc_data_formatVersion={3,0,0,0}; -static const UVersionInfo norm2_nfc_data_dataVersion={0xa,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,0x4cc0,0x8918,0x8a18,0x8a18,0x8a18,0x8a18,0x8a18,0xc0,0x300,0xadc,0x29d0,0x3c56,0xfc00,0x1282,0x3b8c, +0x50,0x4e50,0x8aa8,0x8ba8,0x8ba8,0x8ba8,0x8ba8,0x8ba8,0xc0,0x300,0xadc,0x29d0,0x3c56,0xfc00,0x1282,0x3b8c, 0x3c24,0x3c56,0x300,0 }; -static const uint16_t norm2_nfc_data_trieIndex[9776]={ -0x2a8,0x2b0,0x2b8,0x2c0,0x2ce,0x2d6,0x2de,0x2e6,0x2ee,0x2f6,0x2fe,0x306,0x30e,0x316,0x31c,0x324, -0x32c,0x334,0x2c7,0x2cf,0x339,0x341,0x2c7,0x2cf,0x349,0x351,0x359,0x361,0x369,0x371,0x379,0x381, -0x389,0x391,0x399,0x3a1,0x3a9,0x3b1,0x3b9,0x3c1,0x2c7,0x2cf,0x2c7,0x2cf,0x3c8,0x3d0,0x3d8,0x3e0, -0x3e4,0x3ec,0x3f2,0x3fa,0x2c7,0x2cf,0x402,0x40a,0x40e,0x416,0x41e,0x426,0x2c7,0x2cf,0x424,0x42c, -0x431,0x438,0x43c,0x2c7,0x2c7,0x2c7,0x443,0x44b,0x2c7,0x453,0x45b,0x2c7,0x2c7,0x463,0x46b,0x2c7, -0x2c7,0x473,0x47b,0x2c7,0x2c7,0x483,0x48b,0x2c7,0x2c7,0x463,0x492,0x2c7,0x49a,0x4a0,0x4a8,0x2c7, -0x2c7,0x2c7,0x4af,0x2c7,0x2c7,0x4b5,0x4bd,0x2c7,0x2c7,0x4c3,0x4cb,0x2c7,0x2c7,0x2c7,0x4d1,0x2c7, -0x2c7,0x4d9,0x4e0,0x2c7,0x2c7,0x4e3,0x4ea,0x2c7,0x4ed,0x4f4,0x4fc,0x504,0x50c,0x514,0x51b,0x2c7, -0x2c7,0x522,0x2c7,0x2c7,0x529,0x2c7,0x2c7,0x2c7,0x93b,0x2c7,0x2c7,0x943,0x2c7,0x949,0x951,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x52d,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x535,0x535,0x2c7,0x2c7,0x2c7,0x2c7,0x53b,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x543,0x2c7,0x2c7,0x2c7,0x546,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x54d,0x2c7,0x2c7,0x555,0x2c7,0x55d,0x2c7,0x2c7,0x565,0x56a,0x572,0x578,0x2c7,0x57e,0x2c7,0x585, -0x2c7,0x58a,0x2c7,0x2c7,0x2c7,0x2c7,0x590,0x598,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x5a0,0x5a5, -0x5ad,0x5b5,0x5bd,0x5c5,0x5cd,0x5d5,0x5dd,0x5e5,0x5ed,0x5f5,0x5fd,0x605,0x60d,0x615,0x61d,0x625, -0x62d,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x631,0x639,0x2c7,0x640,0x2c7,0x2c7,0x644,0x64b,0x650,0x2c7, -0x658,0x660,0x668,0x670,0x678,0x680,0x2c7,0x688,0x2c7,0x68e,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x691,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x699,0x2c7,0x2c7,0x2c7,0x69e,0x2c7,0x2c7,0x2c7,0x6a6, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x6ae,0x6b5,0x6bd,0x6c5,0x6cd,0x6d5,0x6dd,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x6e5,0x6ed,0x2c7,0x2c7,0x6f5,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x6fc,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x703,0x70b,0x2c7,0x711,0x715,0x2c7,0x2c7,0x58b,0x71d,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x721,0x729,0x72c,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x48b, -0x959,0x95a,0x95b,0x95c,0x95d,0x95e,0x96d,0x959,0x95a,0x95b,0x95c,0x95d,0x95e,0x96d,0x959,0x95a, -0x95b,0x95c,0x95d,0x95e,0x96d,0x959,0x95a,0x95b,0x95c,0x95d,0x95e,0x96d,0x959,0x95a,0x95b,0x95c, -0x95d,0x95e,0x96d,0x959,0x95a,0x95b,0x95c,0x95d,0x95e,0x96d,0x959,0x95a,0x95b,0x95c,0x95d,0x95e, -0x96d,0x959,0x95a,0x95b,0x95c,0x95d,0x95e,0x96d,0x959,0x95a,0x95b,0x95c,0x95d,0x95e,0x96d,0x959, -0x95a,0x95b,0x95c,0x95d,0x95e,0x96d,0x959,0x95a,0x95b,0x95c,0x95d,0x95e,0x96d,0x959,0x95a,0x95b, -0x95c,0x95d,0x95e,0x96d,0x959,0x95a,0x95b,0x95c,0x95d,0x95e,0x96d,0x959,0x95a,0x95b,0x95c,0x95d, -0x95e,0x96d,0x959,0x95a,0x95b,0x95c,0x95d,0x95e,0x96d,0x959,0x95a,0x95b,0x95c,0x95d,0x95e,0x96d, -0x959,0x95a,0x95b,0x95c,0x95d,0x95e,0x96d,0x959,0x95a,0x95b,0x95c,0x95d,0x95e,0x96d,0x959,0x95a, -0x95b,0x95c,0x95d,0x95e,0x96d,0x959,0x95a,0x95b,0x95c,0x95d,0x95e,0x96d,0x959,0x95a,0x95b,0x95c, -0x95d,0x95e,0x96d,0x959,0x95a,0x95b,0x95c,0x95d,0x95e,0x96d,0x959,0x95a,0x95b,0x95c,0x95d,0x95e, -0x96d,0x959,0x95a,0x95b,0x95c,0x95d,0x95e,0x96d,0x959,0x95a,0x95b,0x95c,0x95d,0x95e,0x96d,0x959, -0x95a,0x95b,0x95c,0x95d,0x95e,0x96d,0x959,0x95a,0x95b,0x95c,0x95d,0x95e,0x96d,0x959,0x95a,0x95b, -0x95c,0x95d,0x95e,0x96d,0x959,0x95a,0x95b,0x95c,0x95d,0x95e,0x96d,0x959,0x95a,0x95b,0x95c,0x95d, -0x95e,0x96d,0x959,0x95a,0x95b,0x95c,0x95d,0x95e,0x96d,0x959,0x95a,0x95b,0x95c,0x95d,0x95e,0x96d, -0x959,0x95a,0x95b,0x95c,0x95d,0x95e,0x96d,0x959,0x95a,0x95b,0x95c,0x95d,0x95e,0x96d,0x959,0x95a, -0x95b,0x95c,0x95d,0x95e,0x96d,0x959,0x95a,0x95b,0x95c,0x95d,0x95e,0x96d,0x959,0x95a,0x95b,0x95c, -0x95d,0x95e,0x96d,0x959,0x95a,0x95b,0x95c,0x95d,0x95e,0x96d,0x959,0x95a,0x95b,0x95c,0x95d,0x95e, -0x96d,0x959,0x95a,0x95b,0x95c,0x95d,0x95e,0x96d,0x959,0x95a,0x95b,0x95c,0x95d,0x95e,0x96d,0x959, -0x95a,0x95b,0x95c,0x95d,0x95e,0x96d,0x959,0x95a,0x95b,0x95c,0x95d,0x95e,0x96d,0x959,0x95a,0x95b, -0x95c,0x95d,0x95e,0x96d,0x959,0x95a,0x95b,0x95c,0x95d,0x95e,0x96d,0x959,0x95a,0x95b,0x95c,0x95d, -0x95e,0x96d,0x959,0x95a,0x95b,0x95c,0x95d,0x95e,0x96d,0x959,0x95a,0x95b,0x95c,0x95d,0x95e,0x96d, -0x959,0x95a,0x95b,0x95c,0x95d,0x95e,0x96d,0x959,0x95a,0x95b,0x95c,0x95d,0x95e,0x965,0x2c7,0x2c7, -0x975,0x97c,0x2a8,0x983,0x2a8,0x2a8,0x2a8,0x2a8,0x2a8,0x2a8,0x2a8,0x2a8,0x2a8,0x2a8,0x2a8,0x2a8, -0x2a8,0x2a8,0x2a8,0x2a8,0x2a8,0x2a8,0x2a8,0x2a8,0x2a8,0x2a8,0x2a8,0x2a8,0x2a8,0x2a8,0x2a8,0x2a8, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x734,0x73c,0x744,0x74c,0x754,0x75c,0x764,0x76c, -0x774,0x77c,0x784,0x78c,0x794,0x79c,0x7a4,0x2c7,0x7ab,0x7b3,0x7bb,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x7c3,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0xb20,0xb20,0xb38,0xb78,0xbb8,0xbf8,0xc38,0xc70,0xcb0,0xb1c,0xce4,0xb1c,0xd24,0xd64,0xda4,0xde4, -0xe24,0xe64,0xea4,0xee4,0xb1c,0xb1c,0xf20,0xf60,0xf90,0xfc8,0xb1c,0x1008,0x1038,0x1078,0xb1c,0x1090, -0x880,0x8b0,0x8ee,0x928,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x953,0x188,0x188, -0x188,0x188,0x188,0x188,0x188,0x188,0x188,0x96f,0x188,0x188,0x9a5,0x188,0x9e5,0xa1f,0x188,0x188, +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,0xa5f, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x7c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x7cf,0x2c7,0x2c7,0x2c7,0x7d2,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x7d9,0x7dd,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x7e5,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x6fc,0x69e,0x7e7,0x7ef,0x2c7,0x2c7,0x7f7,0x7fe,0x2c7,0x58b,0x2c7,0x2c7,0x806,0x2c7,0x2c7,0x809, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x80f,0x2c7,0x463,0x816,0x81d,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x825,0x2c7,0x2c7,0x829,0x831,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x836,0x83e,0x2c7,0x2c7,0x69e, -0x2c7,0x2c7,0x2c7,0x841,0x2c7,0x2c7,0x2c7,0x847,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x535,0x848,0x2c7,0x84a,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x69e,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x852,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x856,0x2c7,0x85c,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x862,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x86a, -0x872,0x87a,0x880,0x888,0x2c7,0x2c7,0x2c7,0x890,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x898,0x8a0,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x8a4,0x2c7,0x2c7,0x2c7,0x8ab,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x8b3, -0x8bb,0x8c3,0x8cb,0x8d3,0x8db,0x8e3,0x8eb,0x8f3,0x8fb,0x903,0x90b,0x913,0x91b,0x923,0x92b,0x933, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7, -0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2c7,0x2a7, +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,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,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, -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, +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, -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, +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,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,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, -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,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,0xfe24,0xfe26,0xfe26,0xfe28,0xfe2a,0xfe2c,1,0xfe2e, -1,0xfe30,0xfe32,1,0xffcc,0xffb8,1,0xfe24,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,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,0xfe3c,0xfe3e,0xfe40,1,1,1,1,1, -1,1,0x195c,0x1962,0x1969,0x196f,0x1975,0x844,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -0x850,1,0x854,0xfe36,0xfe38,0xfe3a,0xfe3c,0xfe3e,0xfe40,0xfe42,0xfe44,0xfdcc,0xfdcc,0xfdb8,0xffb8,0xffcc, -0xffcc,0xffcc,0xffcc,0xffcc,0xffb8,0xffcc,0xffcc,0xffb8,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,0xfe46,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,0x197b,0x858,0x1981,1,1,1,1,1, -1,1,1,1,1,1,1,1,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,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,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,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,1, -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,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,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,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,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,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,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, +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,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,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,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,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, +0xfe24,0xfe26,0xfe26,0xfe28,0xfe2a,0xfe2c,1,0xfe2e,1,0xfe30,0xfe32,1,0xffcc,0xffb8,1,0xfe24, 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,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc, +0xfe3c,0xfe3e,0xfe40,1,1,1,1,1,1,1,0x195c,0x1962,0x1969,0x196f,0x1975,0x844, 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,0x850,1,0x854,0xfe36,0xfe38,0xfe3a,0xfe3c,0xfe3e, +0xfe40,0xfe42,0xfe44,0xfdcc,0xfdcc,0xfdb8,0xffb8,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffb8,0xffcc,0xffcc,0xffb8, 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, +0xfe46,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +0x197b,0x858,0x1981,1,1,1,1,1,1,1,1,1,1,1,1,1, +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,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, +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,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,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,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,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,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,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,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,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, -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,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,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,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,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,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,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, +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,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,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,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,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,0xffb8,1,1,0xffb8,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,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,1,1,0xffcc,0xfe02,0xffb8,1, -1,1,1,0xfe12,1,1,1,1,1,0xffcc,0xffb8,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,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,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,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,1,1, +0xffcc,0xfe02,0xffb8,1,1,1,1,0xfe12,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,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,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, 1,1,1,1,1,1,1,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,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,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,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,1,1,0xfc00,1,1,1,1,1,1,1,1,0xabe,0xfc00,0x299f, -0x29a9,0xfc00,0x29b3,1,1,1,0xfe12,0xfe0e,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,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, +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,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,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,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,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,1,1,1,1,1,1,0xfe02,0xfe02,0xfe02,0xfe02,0xfe02,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, -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,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,0xfe02,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, +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,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,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,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, -0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,0xffcc,1,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, +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, +1,1,1,1,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,1,1,1,1,1,1,1,1, +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,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,1,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 +1,1,0x3b87,1,1,1,1,1 }; static const uint16_t norm2_nfc_data_extraData[7724]={ @@ -1120,7 +1133,7 @@ static const uint16_t norm2_nfc_data_extraData[7724]={ }; static const uint8_t norm2_nfc_data_smallFCD[256]={ -0xc0,0xef,3,0x7f,0xdf,0x70,0xcf,0x87,0xc7,0x66,0x66,0x46,0x64,0x46,0x66,0x5b, +0xc0,0xef,3,0x7f,0xdf,0x70,0xcf,0x87,0xc7,0xe6,0x66,0x46,0x64,0x46,0x66,0x5b, 0x12,0,0,4,0,0,0,0x43,0x20,2,0x29,0xae,0xc2,0xc0,0xff,0xff, 0xc0,0x72,0xbf,0,0,0,0,0,0,0,0x40,0,0x80,0x88,0,0, 0xfe,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, @@ -1140,16 +1153,16 @@ static const uint8_t norm2_nfc_data_smallFCD[256]={ static const UTrie2 norm2_nfc_data_trie={ norm2_nfc_data_trieIndex, - norm2_nfc_data_trieIndex+2720, + norm2_nfc_data_trieIndex+2728, NULL, - 2720, - 7056, + 2728, + 7248, 0x188, - 0xb1c, + 0xb24, 0x1, 0x1, 0x30000, - 0x262c, + 0x26f4, NULL, 0, FALSE, FALSE, 0, NULL }; diff --git a/deps/icu-small/source/common/propname_data.h b/deps/icu-small/source/common/propname_data.h index 5876fc7073a..afa876c0fa8 100644 --- a/deps/icu-small/source/common/propname_data.h +++ b/deps/icu-small/source/common/propname_data.h @@ -13,91 +13,93 @@ U_NAMESPACE_BEGIN -const int32_t PropNameData::indexes[8]={0x20,0x13c8,0x4831,0x92bb,0x92bb,0x92bb,0x2f,0}; +const int32_t PropNameData::indexes[8]={0x20,0x1424,0x49e9,0x966c,0x966c,0x966c,0x2f,0}; -const int32_t PropNameData::valueMaps[1258]={ -6,0,0x40,0,0xdb,0x356,0xdb,0x36c,0xdb,0x381,0xdb,0x397,0xdb,0x3a2,0xdb,0x3c3, -0xdb,0x3d3,0xdb,0x3e2,0xdb,0x3f0,0xdb,0x414,0xdb,0x42b,0xdb,0x443,0xdb,0x45a,0xdb,0x469, -0xdb,0x478,0xdb,0x489,0xdb,0x497,0xdb,0x4a9,0xdb,0x4c3,0xdb,0x4de,0xdb,0x4f3,0xdb,0x510, -0xdb,0x521,0xdb,0x52c,0xdb,0x54b,0xdb,0x561,0xdb,0x572,0xdb,0x582,0xdb,0x59d,0xdb,0x5b6, -0xdb,0x5c7,0xdb,0x5e1,0xdb,0x5f4,0xdb,0x604,0xdb,0x61e,0xdb,0x637,0xdb,0x64e,0xdb,0x662, -0xdb,0x678,0xdb,0x68c,0xdb,0x6a2,0xdb,0x6bc,0xdb,0x6d4,0xdb,0x6f0,0xdb,0x6f8,0xdb,0x700, -0xdb,0x708,0xdb,0x710,0xdb,0x719,0xdb,0x726,0xdb,0x739,0xdb,0x756,0xdb,0x773,0xdb,0x790, -0xdb,0x7ae,0xdb,0x7cc,0xdb,0x7f0,0xdb,0x7fd,0xdb,0x824,0xdb,0x843,0xdb,0x86c,0xdb,0x88d, -0xdb,0x8a4,0xdb,0x1000,0x1016,0x8c6,0x155,0xae6,0x170,0x2b81,0xe1,0x2ba0,0x28d,0x2cde,0x2a3,0x2d38, -0x2ad,0x2f95,0x2cf,0x3836,0x337,0x38a6,0x341,0x3b40,0x370,0x3b7e,0x378,0x4567,0x42e,0x45e5,0x438,0x460a, -0x43e,0x4624,0x444,0x4645,0x44b,0x465f,0xe1,0x4684,0xe1,0x46aa,0x452,0x4754,0x468,0x47cd,0x47b,0x486a, -0x495,0x2000,0x2001,0x48a1,0x49c,0x3000,0x3001,0x492d,0,0x4000,0x400e,0x493f,0,0x4948,0,0x4962, -0,0x4973,0,0x4984,0,0x499a,0,0x49a3,0,0x49c0,0,0x49de,0,0x49fc,0,0x4a1a, -0,0x4a30,0,0x4a44,0,0x4a5a,0,0x7000,0x7001,0x4a73,0,0x748,0x12,0,1,0x12, -0x20,0x766,0x49,0,1,7,8,9,0xa,0xb,0xc,0xd,0xe,0xf,0x10,0x11, -0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x20,0x21, -0x22,0x23,0x24,0x54,0x5b,0x67,0x6b,0x76,0x7a,0x81,0x82,0x84,0x85,0xc8,0xca,0xd6, -0xd8,0xda,0xdc,0xde,0xe0,0xe2,0xe4,0xe6,0xe8,0xe9,0xea,0xf0,0x2e,0x40,0x4c,0x56, -0x67,0x72,0x7f,0x8c,0x99,0xa6,0xb3,0xc0,0xcd,0xda,0xe7,0xf4,0x101,0x10e,0x11b,0x128, -0x135,0x142,0x14f,0x15c,0x169,0x176,0x183,0x190,0x19d,0x1aa,0x1b7,0x1c4,0x1d1,0x1de,0x1eb,0x1fa, -0x209,0x218,0x227,0x236,0x245,0x254,0x263,0x27d,0x291,0x2a5,0x2c0,0x2cf,0x2d8,0x2e8,0x2f0,0x2f9, -0x308,0x311,0x321,0x332,0x343,0x8f8,1,0,0x17,0x8d5,0x8e6,0x8f7,0x90b,0x922,0x93a,0x94c, -0x961,0x978,0x98d,0x99d,0x9af,0x9cc,0x9e8,0x9fa,0xa17,0xa33,0xa4f,0xa64,0xa79,0xa93,0xaae,0xac9, -0xa9a,1,0,0x119,0xaf1,0xafe,0xb11,0xb39,0xb57,0xb75,0xb8d,0xbb8,0xbe2,0xbfa,0xc0d,0xc20, -0xc2f,0xc3e,0xc4d,0xc5c,0xc73,0xc84,0xc97,0xcaa,0xcb7,0xcc4,0xcd3,0xce4,0xcf9,0xd0a,0xd15,0xd1e, -0xd2f,0xd40,0xd53,0xd65,0xd78,0xd8b,0xdca,0xdd7,0xde4,0xdf1,0xe06,0xe36,0xe50,0xe71,0xe9c,0xebf, -0xf1d,0xf44,0xf5f,0xf6e,0xf95,0xfbd,0xfe0,0x1003,0x102d,0x1046,0x1065,0x1088,0x10ac,0x10bf,0x10d9,0x1103, -0x111b,0x1143,0x116c,0x117f,0x1192,0x11a5,0x11cc,0x11db,0x11fb,0x1229,0x1247,0x1275,0x1291,0x12ac,0x12c5,0x12de, -0x12ff,0x132f,0x134e,0x1370,0x13a4,0x13d1,0x1416,0x1437,0x1461,0x1482,0x14ab,0x14be,0x14f1,0x1508,0x1517,0x1528, -0x1553,0x156a,0x159b,0x15c9,0x160c,0x1617,0x1650,0x1661,0x1672,0x167f,0x1692,0x16cc,0x16f0,0x1714,0x174e,0x1786, -0x17b1,0x17c9,0x17f5,0x1821,0x182e,0x183d,0x185a,0x187c,0x18aa,0x18ca,0x18f1,0x1918,0x1937,0x194a,0x195b,0x196c, -0x1991,0x19b6,0x19dd,0x1a11,0x1a3e,0x1a5c,0x1a6f,0x1a88,0x1ac1,0x1ad0,0x1af0,0x1b12,0x1b34,0x1b4b,0x1b62,0x1b8f, -0x1ba8,0x1bc1,0x1bf2,0x1c1c,0x1c37,0x1c4a,0x1c69,0x1c72,0x1c85,0x1ca3,0x1cc1,0x1cd4,0x1ceb,0x1d00,0x1d35,0x1d59, -0x1d6e,0x1d7d,0x1d90,0x1db4,0x1dbd,0x1de1,0x1df8,0x1e0b,0x1e1a,0x1e25,0x1e46,0x1e5e,0x1e6d,0x1e7c,0x1e8b,0x1ea2, -0x1eb7,0x1ecc,0x1f05,0x1f18,0x1f34,0x1f3f,0x1f4c,0x1f7a,0x1f9e,0x1fc1,0x1fd4,0x1ff6,0x2009,0x2024,0x2047,0x206a, -0x208f,0x20a0,0x20cf,0x20fc,0x2113,0x212e,0x213d,0x2168,0x21a0,0x21da,0x2208,0x2219,0x2226,0x224a,0x2259,0x2275, -0x228f,0x22ac,0x22e4,0x22f9,0x2326,0x2345,0x2373,0x2393,0x23c7,0x23d6,0x2400,0x2423,0x244e,0x2459,0x246a,0x2485, -0x24a9,0x24b6,0x24cb,0x24f2,0x251d,0x2554,0x2567,0x2578,0x25a8,0x25b9,0x25c8,0x25dd,0x25fb,0x260e,0x2621,0x2638, -0x2655,0x2660,0x2669,0x268b,0x26a0,0x26c5,0x26dc,0x2705,0x2720,0x2735,0x274e,0x276f,0x27a4,0x27b5,0x27e6,0x280a, -0x281b,0x2834,0x283f,0x286c,0x288e,0x28bc,0x28ef,0x28fe,0x290f,0x292c,0x296e,0x2995,0x29a2,0x29b7,0x29db,0x2a01, -0x2a3a,0x2a4b,0x2a6f,0x2a7a,0x2a87,0x2a96,0x2abb,0x2ae9,0x2b05,0x2b22,0x2b2f,0x2b40,0x2b5e,0x1c30,1,0, -0x12,0x2bb7,0x2bc7,0x2bda,0x2bea,0x2bfa,0x2c09,0x2c19,0x2c2b,0x2c3e,0x2c50,0x2c60,0x2c70,0x2c7f,0x2c8e,0x2c9e, -0x2cab,0x2cba,0x2cce,0x1cee,1,0,6,0x2cf3,0x2cfe,0x2d0b,0x2d18,0x2d25,0x2d30,0x1d32,1,0, -0x1e,0x2d4d,0x2d5c,0x2d71,0x2d86,0x2d9b,0x2daf,0x2dc0,0x2dd4,0x2de7,0x2df8,0x2e11,0x2e23,0x2e34,0x2e48,0x2e5b, -0x2e73,0x2e85,0x2e90,0x2ea0,0x2eae,0x2ec3,0x2ed8,0x2eee,0x2f08,0x2f1e,0x2f2e,0x2f42,0x2f56,0x2f67,0x2f7f,0x1f5d, -1,0,0x64,0x2fa7,0x2fca,0x2fd3,0x2fe0,0x2feb,0x2ff4,0x2fff,0x3008,0x3021,0x3026,0x302f,0x304c,0x3055, -0x3062,0x306b,0x308f,0x3096,0x309f,0x30b2,0x30bd,0x30c6,0x30d1,0x30ea,0x30f3,0x3102,0x310d,0x3116,0x3121,0x312a, -0x3131,0x313a,0x3145,0x314e,0x3167,0x3170,0x317d,0x3188,0x3199,0x31a4,0x31b9,0x31d0,0x31d9,0x31e2,0x31fb,0x3206, -0x320f,0x3218,0x322f,0x324c,0x3257,0x3268,0x3273,0x327a,0x3287,0x3294,0x32c1,0x32d6,0x32df,0x32fa,0x331d,0x333e, -0x335f,0x3384,0x33ab,0x33cc,0x33ef,0x3410,0x3437,0x3458,0x347d,0x349c,0x34bb,0x34da,0x34f7,0x3518,0x3539,0x355c, -0x3581,0x35a0,0x35bf,0x35e0,0x3607,0x362c,0x364b,0x366c,0x368f,0x36aa,0x36c3,0x36de,0x36f7,0x3714,0x372f,0x374c, -0x376b,0x3788,0x37a5,0x37c4,0x37e1,0x37fc,0x3819,0x2283,1,0,6,0x3847,0x3856,0x3866,0x3876,0x3886, -0x3897,0x22e1,1,0,0x2b,0x38b5,0x38c1,0x38cf,0x38de,0x38ed,0x38fd,0x390e,0x3922,0x3937,0x394d,0x3960, -0x3974,0x3984,0x398d,0x3998,0x39a8,0x39c4,0x39d6,0x39e4,0x39f3,0x39ff,0x3a14,0x3a28,0x3a3b,0x3a49,0x3a5d,0x3a6b, -0x3a75,0x3a87,0x3a93,0x3aa1,0x3ab1,0x3ab8,0x3abf,0x3ac6,0x3acd,0x3ad4,0x3aea,0x3b0b,0x88d,0x3b1d,0x3b28,0x3b37, -0x253a,1,0,4,0x3b51,0x3b5c,0x3b68,0x3b72,0x2560,1,0,0xb2,0x3b89,0x3b96,0x3bab,0x3bb8, -0x3bc7,0x3bd5,0x3be4,0x3bf3,0x3c05,0x3c14,0x3c22,0x3c33,0x3c42,0x3c51,0x3c5e,0x3c6a,0x3c79,0x3c88,0x3c92,0x3c9f, -0x3cac,0x3cbb,0x3cc9,0x3cd8,0x3ce4,0x3cee,0x3cfa,0x3d0a,0x3d1a,0x3d28,0x3d34,0x3d45,0x3d51,0x3d5d,0x3d6b,0x3d78, -0x3d84,0x3d91,0xd0a,0x3d9e,0x3dac,0x3dc6,0x3dcf,0x3ddd,0x3deb,0x3df7,0x3e06,0x3e14,0x3e22,0x3e2e,0x3e3d,0x3e4b, -0x3e59,0x3e66,0x3e75,0x3e90,0x3e9f,0x3eb0,0x3ec1,0x3ed4,0x3ee6,0x3ef5,0x3f07,0x3f16,0x3f22,0x3f2d,0x1e1a,0x3f3a, -0x3f45,0x3f50,0x3f5b,0x3f66,0x3f81,0x3f8c,0x3f97,0x3fa2,0x3fb5,0x3fc9,0x3fd4,0x3fe3,0x3ff2,0x3ffd,0x4008,0x4015, -0x4024,0x4032,0x403d,0x4058,0x4062,0x4073,0x4084,0x4093,0x40a4,0x40af,0x40ba,0x40c5,0x40d0,0x40db,0x40e6,0x40f1, -0x40fb,0x4106,0x4116,0x4121,0x412f,0x413c,0x4147,0x4156,0x4163,0x4170,0x417f,0x418c,0x419d,0x41af,0x41bf,0x41ca, -0x41dd,0x41f4,0x4202,0x420f,0x421a,0x4227,0x4238,0x4254,0x426a,0x4275,0x4292,0x42a2,0x42b1,0x42bc,0x42c7,0x1f34, -0x42d3,0x42de,0x42f6,0x4306,0x4315,0x4323,0x4331,0x433c,0x4347,0x435b,0x4372,0x438a,0x439a,0x43aa,0x43ba,0x43cc, -0x43d7,0x43e2,0x43ec,0x43f8,0x4406,0x4419,0x4425,0x4432,0x443d,0x4459,0x4466,0x4474,0x448d,0x2834,0x449c,0x2655, -0x44a9,0x44b7,0x44c9,0x44d7,0x44e3,0x44f3,0x2a6f,0x4501,0x450d,0x4518,0x4523,0x452e,0x4542,0x4550,0x2e57,1, -0,6,0x4581,0x4594,0x45a4,0x45b2,0x45c3,0x45d3,0x2eb3,0x12,0,1,0x45fd,0x4603,0x2ec0,0x12, -0,1,0x45fd,0x4603,0x2ecd,1,0,3,0x45fd,0x4603,0x463c,0x2ee3,1,0,3,0x45fd, -0x4603,0x463c,0x2ef9,1,0,0x12,0x46c6,0x46d0,0x46dc,0x46e3,0x46ee,0x46f3,0x46fa,0x4701,0x470a,0x470f, -0x4714,0x4724,0x88d,0x3b1d,0x4730,0x3b28,0x4740,0x3b37,0x2fa2,1,0,0xf,0x46c6,0x4767,0x4771,0x477b, -0x4786,0x39f3,0x4790,0x479c,0x47a4,0x47ab,0x47b5,0x46dc,0x46e3,0x46f3,0x47bf,0x3029,1,0,0x16,0x46c6, -0x47dc,0x477b,0x47e8,0x47f5,0x4803,0x39f3,0x480e,0x46dc,0x481f,0x46f3,0x482e,0x483c,0x88d,0x3b0b,0x4848,0x4859, -0x3b1d,0x4730,0x3b28,0x4740,0x3b37,0x3139,1,0,3,0x4888,0x4890,0x4898,0x3152,0x36,1,2, -4,8,0xe,0x10,0x20,0x3e,0x40,0x80,0x100,0x1c0,0x200,0x400,0x800,0xe00,0x1000,0x2000, -0x4000,0x7000,0x8000,0x10000,0x20000,0x40000,0x78001,0x80000,0x100000,0x200000,0x400000,0x800000,0x1000000,0x2000000,0x4000000,0x8000000, -0xf000000,0x10000000,0x20000000,0x30f80000,0x2d4d,0x2d5c,0x2d71,0x2d86,0x48cf,0x2d9b,0x2daf,0x48c5,0x2dc0,0x2dd4,0x2de7,0x48e0, -0x2df8,0x2e11,0x2e23,0x48f7,0x2e34,0x2e48,0x2e5b,0x4920,0x2e73,0x2e85,0x2e90,0x2ea0,0x48bc,0x2eae,0x2ec3,0x2ed8, -0x2eee,0x2f08,0x2f1e,0x2f2e,0x2f42,0x2f56,0x4916,0x2f67,0x2f7f,0x4901 +const int32_t PropNameData::valueMaps[1281]={ +6,0,0x41,0,0xdd,0x356,0xdd,0x36c,0xdd,0x381,0xdd,0x397,0xdd,0x3a2,0xdd,0x3c3, +0xdd,0x3d3,0xdd,0x3e2,0xdd,0x3f0,0xdd,0x414,0xdd,0x42b,0xdd,0x443,0xdd,0x45a,0xdd,0x469, +0xdd,0x478,0xdd,0x489,0xdd,0x497,0xdd,0x4a9,0xdd,0x4c3,0xdd,0x4de,0xdd,0x4f3,0xdd,0x510, +0xdd,0x521,0xdd,0x52c,0xdd,0x54b,0xdd,0x561,0xdd,0x572,0xdd,0x582,0xdd,0x59d,0xdd,0x5b6, +0xdd,0x5c7,0xdd,0x5e1,0xdd,0x5f4,0xdd,0x604,0xdd,0x61e,0xdd,0x637,0xdd,0x64e,0xdd,0x662, +0xdd,0x678,0xdd,0x68c,0xdd,0x6a2,0xdd,0x6bc,0xdd,0x6d4,0xdd,0x6f0,0xdd,0x6f8,0xdd,0x700, +0xdd,0x708,0xdd,0x710,0xdd,0x719,0xdd,0x726,0xdd,0x739,0xdd,0x756,0xdd,0x773,0xdd,0x790, +0xdd,0x7ae,0xdd,0x7cc,0xdd,0x7f0,0xdd,0x7fd,0xdd,0x817,0xdd,0x82c,0xdd,0x847,0xdd,0x85e, +0xdd,0x875,0xdd,0x897,0xdd,0x1000,0x1016,0x8b6,0x157,0xad6,0x172,0x2c95,0xe3,0x2cb4,0x29a,0x2df2, +0x2b0,0x2e4c,0x2ba,0x30a9,0x2dc,0x39a4,0x346,0x3a14,0x350,0x3cae,0x37f,0x3cec,0x387,0x474b,0x444,0x47c9, +0x44e,0x47ee,0x454,0x4808,0x45a,0x4829,0x461,0x4843,0xe3,0x4868,0xe3,0x488e,0x468,0x4938,0x47e,0x49b1, +0x491,0x4a63,0x4ac,0x2000,0x2001,0x4a9a,0x4b3,0x3000,0x3001,0x4b26,0,0x4000,0x400e,0x4b38,0,0x4b41, +0,0x4b5b,0,0x4b6c,0,0x4b7d,0,0x4b93,0,0x4b9c,0,0x4bb9,0,0x4bd7,0,0x4bf5, +0,0x4c13,0,0x4c29,0,0x4c3d,0,0x4c53,0,0x7000,0x7001,0x4c6c,0,0x77c,0x12,0, +1,0x12,0x20,0x79a,0x49,0,1,7,8,9,0xa,0xb,0xc,0xd,0xe,0xf, +0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f, +0x20,0x21,0x22,0x23,0x24,0x54,0x5b,0x67,0x6b,0x76,0x7a,0x81,0x82,0x84,0x85,0xc8, +0xca,0xd6,0xd8,0xda,0xdc,0xde,0xe0,0xe2,0xe4,0xe6,0xe8,0xe9,0xea,0xf0,0x2e,0x40, +0x4c,0x56,0x67,0x72,0x7f,0x8c,0x99,0xa6,0xb3,0xc0,0xcd,0xda,0xe7,0xf4,0x101,0x10e, +0x11b,0x128,0x135,0x142,0x14f,0x15c,0x169,0x176,0x183,0x190,0x19d,0x1aa,0x1b7,0x1c4,0x1d1,0x1de, +0x1eb,0x1fa,0x209,0x218,0x227,0x236,0x245,0x254,0x263,0x27d,0x291,0x2a5,0x2c0,0x2cf,0x2d8,0x2e8, +0x2f0,0x2f9,0x308,0x311,0x321,0x332,0x343,0x92c,1,0,0x17,0x8c5,0x8d6,0x8e7,0x8fb,0x912, +0x92a,0x93c,0x951,0x968,0x97d,0x98d,0x99f,0x9bc,0x9d8,0x9ea,0xa07,0xa23,0xa3f,0xa54,0xa69,0xa83, +0xa9e,0xab9,0xace,1,0,0x124,0xae1,0xaee,0xb01,0xb29,0xb47,0xb65,0xb7d,0xba8,0xbd2,0xbea, +0xbfd,0xc10,0xc1f,0xc2e,0xc3d,0xc4c,0xc63,0xc74,0xc87,0xc9a,0xca7,0xcb4,0xcc3,0xcd4,0xce9,0xcfa, +0xd05,0xd0e,0xd1f,0xd30,0xd43,0xd55,0xd68,0xd7b,0xdba,0xdc7,0xdd4,0xde1,0xdf6,0xe26,0xe40,0xe61, +0xe8c,0xeaf,0xf0d,0xf34,0xf4f,0xf5e,0xf85,0xfad,0xfd0,0xff3,0x101d,0x1036,0x1055,0x1078,0x109c,0x10af, +0x10c9,0x10f3,0x110b,0x1133,0x115c,0x116f,0x1182,0x1195,0x11bc,0x11cb,0x11eb,0x1219,0x1237,0x1265,0x1281,0x129c, +0x12b5,0x12ce,0x12ef,0x131f,0x133e,0x1360,0x1394,0x13c1,0x1406,0x1427,0x1451,0x1472,0x149b,0x14ae,0x14e1,0x14f8, +0x1507,0x1518,0x1543,0x155a,0x158b,0x15b9,0x15fc,0x1607,0x1640,0x1651,0x1662,0x166f,0x1682,0x16bc,0x16e0,0x1704, +0x173e,0x1776,0x17a1,0x17b9,0x17e5,0x1811,0x181e,0x182d,0x184a,0x186c,0x189a,0x18ba,0x18e1,0x1908,0x1927,0x193a, +0x194b,0x195c,0x1981,0x19a6,0x19cd,0x1a01,0x1a2e,0x1a4c,0x1a5f,0x1a78,0x1ab1,0x1ac0,0x1ae0,0x1b02,0x1b24,0x1b3b, +0x1b52,0x1b7f,0x1b98,0x1bb1,0x1be2,0x1c0c,0x1c27,0x1c3a,0x1c59,0x1c62,0x1c75,0x1c93,0x1cb1,0x1cc4,0x1cdb,0x1cf0, +0x1d25,0x1d49,0x1d5e,0x1d6d,0x1d80,0x1da4,0x1dad,0x1dd1,0x1de8,0x1dfb,0x1e0a,0x1e15,0x1e36,0x1e4e,0x1e5d,0x1e6c, +0x1e7b,0x1e92,0x1ea7,0x1ebc,0x1ef5,0x1f08,0x1f24,0x1f2f,0x1f3c,0x1f6a,0x1f8e,0x1fb1,0x1fc4,0x1fe6,0x1ff9,0x2014, +0x2037,0x205a,0x207f,0x2090,0x20bf,0x20ec,0x2103,0x211e,0x212d,0x2158,0x2190,0x21ca,0x21f8,0x2209,0x2216,0x223a, +0x2249,0x2265,0x227f,0x229c,0x22d4,0x22e9,0x2316,0x2335,0x2363,0x2383,0x23b7,0x23c6,0x23f0,0x2413,0x243e,0x2449, +0x245a,0x2475,0x2499,0x24a6,0x24bb,0x24e2,0x250d,0x2544,0x2557,0x2568,0x2598,0x25a9,0x25b8,0x25cd,0x25eb,0x25fe, +0x2611,0x2628,0x2645,0x2650,0x2659,0x267b,0x2690,0x26b5,0x26cc,0x26f5,0x2710,0x2725,0x273e,0x275f,0x2794,0x27a5, +0x27d6,0x27fa,0x280b,0x2824,0x282f,0x285c,0x287e,0x28ac,0x28df,0x28ee,0x28ff,0x291c,0x295e,0x2985,0x2992,0x29a7, +0x29cb,0x29f1,0x2a2a,0x2a3b,0x2a5f,0x2a6a,0x2a77,0x2a86,0x2aab,0x2ad9,0x2af5,0x2b12,0x2b1f,0x2b30,0x2b4e,0x2b71, +0x2b8e,0x2b9b,0x2bbb,0x2bd8,0x2bf9,0x2c22,0x2c33,0x2c52,0x2c6b,0x2c84,0x1cf4,1,0,0x12,0x2ccb,0x2cdb, +0x2cee,0x2cfe,0x2d0e,0x2d1d,0x2d2d,0x2d3f,0x2d52,0x2d64,0x2d74,0x2d84,0x2d93,0x2da2,0x2db2,0x2dbf,0x2dce,0x2de2, +0x1db2,1,0,6,0x2e07,0x2e12,0x2e1f,0x2e2c,0x2e39,0x2e44,0x1df6,1,0,0x1e,0x2e61,0x2e70, +0x2e85,0x2e9a,0x2eaf,0x2ec3,0x2ed4,0x2ee8,0x2efb,0x2f0c,0x2f25,0x2f37,0x2f48,0x2f5c,0x2f6f,0x2f87,0x2f99,0x2fa4, +0x2fb4,0x2fc2,0x2fd7,0x2fec,0x3002,0x301c,0x3032,0x3042,0x3056,0x306a,0x307b,0x3093,0x2021,1,0,0x66, +0x30bb,0x30de,0x30e7,0x30f4,0x30ff,0x3108,0x3113,0x311c,0x3135,0x313a,0x3143,0x3160,0x3169,0x3176,0x317f,0x31a3, +0x31aa,0x31b3,0x31c6,0x31d1,0x31da,0x31e5,0x31fe,0x3207,0x3216,0x3221,0x322a,0x3235,0x323e,0x3245,0x324e,0x3259, +0x3262,0x327b,0x3284,0x3291,0x329c,0x32ad,0x32b8,0x32cd,0x32e4,0x32ed,0x32f6,0x330f,0x331a,0x3323,0x332c,0x3343, +0x3360,0x336b,0x337c,0x3387,0x338e,0x339b,0x33a8,0x33d5,0x33ea,0x33f3,0x340e,0x3431,0x3452,0x3473,0x3498,0x34bf, +0x34e0,0x3503,0x3524,0x354b,0x356c,0x3591,0x35b0,0x35cf,0x35ee,0x360b,0x362c,0x364d,0x3670,0x3695,0x36b4,0x36d3, +0x36f4,0x371b,0x3740,0x375f,0x3780,0x37a3,0x37be,0x37d7,0x37f2,0x380b,0x3828,0x3843,0x3860,0x387f,0x389c,0x38b9, +0x38d8,0x38f5,0x3910,0x392d,0x394a,0x397d,0x2366,1,0,6,0x39b5,0x39c4,0x39d4,0x39e4,0x39f4,0x3a05, +0x23c4,1,0,0x2b,0x3a23,0x3a2f,0x3a3d,0x3a4c,0x3a5b,0x3a6b,0x3a7c,0x3a90,0x3aa5,0x3abb,0x3ace,0x3ae2, +0x3af2,0x3afb,0x3b06,0x3b16,0x3b32,0x3b44,0x3b52,0x3b61,0x3b6d,0x3b82,0x3b96,0x3ba9,0x3bb7,0x3bcb,0x3bd9,0x3be3, +0x3bf5,0x3c01,0x3c0f,0x3c1f,0x3c26,0x3c2d,0x3c34,0x3c3b,0x3c42,0x3c58,0x3c79,0x85e,0x3c8b,0x3c96,0x3ca5,0x261d, +1,0,4,0x3cbf,0x3cca,0x3cd6,0x3ce0,0x2643,1,0,0xb9,0x3cf7,0x3d04,0x3d19,0x3d26,0x3d35, +0x3d43,0x3d52,0x3d61,0x3d73,0x3d82,0x3d90,0x3da1,0x3db0,0x3dbf,0x3dcc,0x3dd8,0x3de7,0x3df6,0x3e00,0x3e0d,0x3e1a, +0x3e29,0x3e37,0x3e46,0x3e52,0x3e5c,0x3e68,0x3e78,0x3e88,0x3e96,0x3ea2,0x3eb3,0x3ebf,0x3ecb,0x3ed9,0x3ee6,0x3ef2, +0x3eff,0xcfa,0x3f0c,0x3f1a,0x3f34,0x3f3d,0x3f4b,0x3f59,0x3f65,0x3f74,0x3f82,0x3f90,0x3f9c,0x3fab,0x3fb9,0x3fc7, +0x3fd4,0x3fe3,0x3ffe,0x400d,0x401e,0x402f,0x4042,0x4054,0x4063,0x4075,0x4084,0x4090,0x409b,0x1e0a,0x40a8,0x40b3, +0x40be,0x40c9,0x40d4,0x40ef,0x40fa,0x4105,0x4110,0x4123,0x4137,0x4142,0x4151,0x4160,0x416b,0x4176,0x4183,0x4192, +0x41a0,0x41ab,0x41c6,0x41d0,0x41e1,0x41f2,0x4201,0x4212,0x421d,0x4228,0x4233,0x423e,0x4249,0x4254,0x425f,0x4269, +0x4274,0x4284,0x428f,0x429d,0x42aa,0x42b5,0x42c4,0x42d1,0x42de,0x42ed,0x42fa,0x430b,0x431d,0x432d,0x4338,0x434b, +0x4362,0x4370,0x437d,0x4388,0x4395,0x43a6,0x43c2,0x43d8,0x43e3,0x4400,0x4410,0x441f,0x442a,0x4435,0x1f24,0x4441, +0x444c,0x4464,0x4474,0x4483,0x4491,0x449f,0x44aa,0x44b5,0x44c9,0x44e0,0x44f8,0x4508,0x4518,0x4528,0x453a,0x4545, +0x4550,0x455a,0x4566,0x4574,0x4587,0x4593,0x45a0,0x45ab,0x45c7,0x45d4,0x45e2,0x45fb,0x2824,0x460a,0x2645,0x4617, +0x4625,0x4637,0x4645,0x4651,0x4661,0x2a5f,0x466f,0x467b,0x4686,0x4691,0x469c,0x46b0,0x46be,0x46d5,0x46e1,0x46f5, +0x4703,0x4715,0x472b,0x4739,0x2fa6,1,0,6,0x4765,0x4778,0x4788,0x4796,0x47a7,0x47b7,0x3002,0x12, +0,1,0x47e1,0x47e7,0x300f,0x12,0,1,0x47e1,0x47e7,0x301c,1,0,3,0x47e1,0x47e7, +0x4820,0x3032,1,0,3,0x47e1,0x47e7,0x4820,0x3048,1,0,0x12,0x48aa,0x48b4,0x48c0,0x48c7, +0x48d2,0x48d7,0x48de,0x48e5,0x48ee,0x48f3,0x48f8,0x4908,0x85e,0x3c8b,0x4914,0x3c96,0x4924,0x3ca5,0x30f1,1, +0,0xf,0x48aa,0x494b,0x4955,0x495f,0x496a,0x3b61,0x4974,0x4980,0x4988,0x498f,0x4999,0x48c0,0x48c7,0x48d7, +0x49a3,0x3178,1,0,0x17,0x48aa,0x49c0,0x495f,0x49cc,0x49d9,0x49e7,0x3b61,0x49f2,0x48c0,0x4a03,0x48d7, +0x4a12,0x4a20,0x85e,0x3c79,0x4a2c,0x4a3d,0x3c8b,0x4914,0x3c96,0x4924,0x3ca5,0x4a4e,0x3295,1,0,3, +0x4a81,0x4a89,0x4a91,0x32ae,0x36,1,2,4,8,0xe,0x10,0x20,0x3e,0x40,0x80,0x100, +0x1c0,0x200,0x400,0x800,0xe00,0x1000,0x2000,0x4000,0x7000,0x8000,0x10000,0x20000,0x40000,0x78001,0x80000,0x100000, +0x200000,0x400000,0x800000,0x1000000,0x2000000,0x4000000,0x8000000,0xf000000,0x10000000,0x20000000,0x30f80000,0x2e61,0x2e70,0x2e85,0x2e9a,0x4ac8, +0x2eaf,0x2ec3,0x4abe,0x2ed4,0x2ee8,0x2efb,0x4ad9,0x2f0c,0x2f25,0x2f37,0x4af0,0x2f48,0x2f5c,0x2f6f,0x4b19,0x2f87, +0x2f99,0x2fa4,0x2fb4,0x4ab5,0x2fc2,0x2fd7,0x2fec,0x3002,0x301c,0x3032,0x3042,0x3056,0x306a,0x4b0f,0x307b,0x3093, +0x4afa }; -const uint8_t PropNameData::bytesTries[13417]={ +const uint8_t PropNameData::bytesTries[13765]={ 0,0x15,0x6d,0xc3,0x5d,0x73,0xc1,0xf7,0x76,0x5f,0x76,0x68,0x77,0x90,0x78,1, 0x64,0x50,0x69,0x10,0x64,1,0x63,0x30,0x73,0x62,0x13,0x74,0x61,0x72,0x74,0x63, 0x60,0x16,0x6f,0x6e,0x74,0x69,0x6e,0x75,0x65,0x61,0x13,0x69,0x67,0x69,0x74,0x81, @@ -180,766 +182,788 @@ const uint8_t PropNameData::bytesTries[13417]={ 0x6e,0x64,0x37,0x12,0x61,0x73,0x65,0x35,0x11,0x78,0x74,0x37,0xc2,5,1,0x62, 0xc3,0x12,0x6d,0xd9,0x20,0,0x1c,0x6e,0x65,0x72,0x61,0x6c,0x63,0x61,0x74,0x65, 0x67,0x6f,0x72,0x79,0xc2,5,0x13,0x6d,0x61,0x73,0x6b,0xd9,0x20,0,0x61,0xa2, -0x5c,0x62,0xa2,0x8a,0x63,0xa2,0xfc,0x64,0xa4,0xc9,0x65,2,0x61,0x3a,0x6d,0x58, -0x78,0x10,0x74,0x30,0x14,0x65,0x6e,0x64,0x65,0x72,0x31,0xc2,4,0x1b,0x73,0x74, -0x61,0x73,0x69,0x61,0x6e,0x77,0x69,0x64,0x74,0x68,0xc3,4,0x12,0x6f,0x6a,0x69, -0x92,2,0x63,0x40,0x6d,0x50,0x70,0x1a,0x72,0x65,0x73,0x65,0x6e,0x74,0x61,0x74, -0x69,0x6f,0x6e,0x95,0x17,0x6f,0x6d,0x70,0x6f,0x6e,0x65,0x6e,0x74,0x9b,0x16,0x6f, -0x64,0x69,0x66,0x69,0x65,0x72,0x96,0x13,0x62,0x61,0x73,0x65,0x99,3,0x67,0x44, -0x68,0x4a,0x6c,0x4e,0x73,0x1a,0x63,0x69,0x69,0x68,0x65,0x78,0x64,0x69,0x67,0x69, -0x74,0x23,0x10,0x65,0xd9,0x40,0,0x11,0x65,0x78,0x23,1,0x6e,0x38,0x70,0x11, -0x68,0x61,0x20,0x14,0x62,0x65,0x74,0x69,0x63,0x21,0x11,0x75,0x6d,0x79,4,0x63, -0xc3,0,0x69,0x3e,0x6c,0xa2,0x57,0x6d,0xa2,0x64,0x70,1,0x62,0xd9,0x40,0xd, -0x74,0xc3,0x15,0x11,0x64,0x69,2,0x63,0x54,0x6d,0x74,0x70,0x1b,0x61,0x69,0x72, -0x65,0x64,0x62,0x72,0x61,0x63,0x6b,0x65,0x74,0xd8,0x40,0xd,0x13,0x74,0x79,0x70, -0x65,0xc3,0x15,0x24,1,0x6c,0x30,0x6f,0x14,0x6e,0x74,0x72,0x6f,0x6c,0x25,0x12, -0x61,0x73,0x73,0xc3,0,0x26,0x14,0x69,0x72,0x72,0x6f,0x72,1,0x65,0x38,0x69, -0x16,0x6e,0x67,0x67,0x6c,0x79,0x70,0x68,0xd9,0x40,1,0x10,0x64,0x27,2,0x61, -0x32,0x6b,0xc3,1,0x6f,0x11,0x63,0x6b,0xc3,1,0x11,0x6e,0x6b,0x7b,0x10,0x67, -0xd9,0x40,1,6,0x68,0x7c,0x68,0x54,0x69,0x85,0x6f,0xa2,0x6f,0x77,4,0x63, -0x30,0x6b,0x36,0x6c,0x87,0x74,0x8b,0x75,0x89,1,0x66,0x8d,0x6d,0x8f,0x11,0x63, -0x66,0x91,0x18,0x61,0x6e,0x67,0x65,0x73,0x77,0x68,0x65,0x6e,4,0x63,0x44,0x6c, -0x6c,0x6e,0x7e,0x74,0x98,0x75,0x18,0x70,0x70,0x65,0x72,0x63,0x61,0x73,0x65,0x64, -0x89,0x12,0x61,0x73,0x65,1,0x66,0x30,0x6d,0x14,0x61,0x70,0x70,0x65,0x64,0x8f, -0x14,0x6f,0x6c,0x64,0x65,0x64,0x8d,0x18,0x6f,0x77,0x65,0x72,0x63,0x61,0x73,0x65, -0x64,0x87,0x1c,0x66,0x6b,0x63,0x63,0x61,0x73,0x65,0x66,0x6f,0x6c,0x64,0x65,0x64, -0x91,0x18,0x69,0x74,0x6c,0x65,0x63,0x61,0x73,0x65,0x64,0x8b,0x13,0x6d,0x70,0x65, -0x78,0x33,0x61,0x2e,0x63,0xa2,0x48,0x66,0xd9,0x40,2,1,0x6e,0x72,0x73,0x10, -0x65,3,0x64,0x83,0x66,0x3a,0x69,0x4a,0x73,0x17,0x65,0x6e,0x73,0x69,0x74,0x69, -0x76,0x65,0x65,0x15,0x6f,0x6c,0x64,0x69,0x6e,0x67,0xd9,0x40,2,0x17,0x67,0x6e, -0x6f,0x72,0x61,0x62,0x6c,0x65,0x85,0x13,0x6f,0x6e,0x69,0x63,0x1f,0x61,0x6c,0x63, -0x6f,0x6d,0x62,0x69,0x6e,0x69,0x6e,0x67,0x63,0x6c,0x61,0x73,0x73,0xc3,2,0x10, -0x63,0xc3,2,3,0x61,0x30,0x65,0x34,0x69,0xa2,0x41,0x74,0xc3,3,0x11,0x73, -0x68,0x29,2,0x63,0x3a,0x66,0x58,0x70,0x2c,0x16,0x72,0x65,0x63,0x61,0x74,0x65, -0x64,0x2d,0x1d,0x6f,0x6d,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x74,0x79,0x70, -0x65,0xc3,3,0x15,0x61,0x75,0x6c,0x74,0x69,0x67,0x1f,0x6e,0x6f,0x72,0x61,0x62, -0x6c,0x65,0x63,0x6f,0x64,0x65,0x70,0x6f,0x69,0x6e,0x74,0x2b,0x2a,0x10,0x61,0x2e, -0x15,0x63,0x72,0x69,0x74,0x69,0x63,0x2f,3,0x66,0x34,0x6e,0x3e,0x74,0x42,0x79, -0x22,0x11,0x65,0x73,0x23,0x20,0x13,0x61,0x6c,0x73,0x65,0x21,0x20,0x10,0x6f,0x21, -0x22,0x12,0x72,0x75,0x65,0x23,0xa,0x6b,0x5b,0x6f,0x23,0x6f,0x3c,0x72,0x4c,0x76, -1,0x69,0x24,0x72,0x33,0x13,0x72,0x61,0x6d,0x61,0x33,0x10,0x76,0x22,0x14,0x65, -0x72,0x6c,0x61,0x79,0x23,0xa2,0xe2,0x13,0x69,0x67,0x68,0x74,0xa3,0xe2,0x6b,0x58, -0x6c,0x74,0x6e,3,0x6b,0x2f,0x6f,0x30,0x72,0x21,0x75,0x12,0x6b,0x74,0x61,0x2f, -0x19,0x74,0x72,0x65,0x6f,0x72,0x64,0x65,0x72,0x65,0x64,0x21,1,0x61,0x24,0x76, -0x31,0x18,0x6e,0x61,0x76,0x6f,0x69,0x63,0x69,0x6e,0x67,0x31,0xa2,0xe0,0x12,0x65, -0x66,0x74,0xa3,0xe0,0x61,0x5c,0x62,0xa2,0x77,0x63,0xa2,0x96,0x64,0xa4,0xa,0x69, -1,0x6f,0x26,0x73,0xa3,0xf0,0x1a,0x74,0x61,0x73,0x75,0x62,0x73,0x63,0x72,0x69, -0x70,0x74,0xa3,0xf0,0xa2,0xe6,3,0x62,0xa0,0x6c,0xa3,0xe4,0x72,0xa3,0xe8,0x74, -2,0x61,0x74,0x62,0x7c,0x74,0x14,0x61,0x63,0x68,0x65,0x64,1,0x61,0x3e,0x62, -0x13,0x65,0x6c,0x6f,0x77,0xa2,0xca,0x13,0x6c,0x65,0x66,0x74,0xa3,0xc8,0x13,0x62, -0x6f,0x76,0x65,0xa2,0xd6,0x14,0x72,0x69,0x67,0x68,0x74,0xa3,0xd8,0xa2,0xd6,0x10, -0x72,0xa3,0xd8,0xa2,0xca,0x10,0x6c,0xa3,0xc8,0x12,0x6f,0x76,0x65,0xa2,0xe6,1, -0x6c,0x30,0x72,0x13,0x69,0x67,0x68,0x74,0xa3,0xe8,0x12,0x65,0x66,0x74,0xa3,0xe4, -0xa2,0xdc,2,0x65,0x2c,0x6c,0xa3,0xda,0x72,0xa3,0xde,0x12,0x6c,0x6f,0x77,0xa2, -0xdc,1,0x6c,0x30,0x72,0x13,0x69,0x67,0x68,0x74,0xa3,0xde,0x12,0x65,0x66,0x74, -0xa3,0xda,0x11,0x63,0x63,4,0x31,0x3c,0x32,0xa2,0x42,0x33,0xa2,0x56,0x38,0xa2, -0x64,0x39,0x10,0x31,0xa3,0x5b,9,0x35,0xa,0x35,0x3f,0x36,0x41,0x37,0x43,0x38, -0x45,0x39,0x47,0x30,0x30,0x31,0x3c,0x32,0x42,0x33,0x4e,0x34,0x3d,0x34,1,0x33, -0xa3,0x67,0x37,0xa3,0x6b,0x36,0x10,0x38,0xa3,0x76,0x38,1,0x32,0xa3,0x7a,0x39, -0xa3,0x81,0x3a,2,0x30,0xa3,0x82,0x32,0xa3,0x84,0x33,0xa3,0x85,9,0x35,0xa, -0x35,0x53,0x36,0x55,0x37,0x57,0x38,0x59,0x39,0x5b,0x30,0x49,0x31,0x4b,0x32,0x4d, -0x33,0x4f,0x34,0x51,6,0x33,8,0x33,0x63,0x34,0x65,0x35,0x67,0x36,0x69,0x30, -0x5d,0x31,0x5f,0x32,0x61,0x10,0x34,0xa3,0x54,2,0x61,0xa3,0xea,0x62,0xa3,0xe9, -0x6f,0x13,0x75,0x62,0x6c,0x65,1,0x61,0x30,0x62,0x13,0x65,0x6c,0x6f,0x77,0xa3, -0xe9,0x13,0x62,0x6f,0x76,0x65,0xa3,0xea,0xb,0x6e,0xc0,0xca,0x72,0x5f,0x72,0x46, -0x73,0xa2,0x48,0x77,1,0x68,0x24,0x73,0x33,0x17,0x69,0x74,0x65,0x73,0x70,0x61, -0x63,0x65,0x33,0x22,1,0x69,0x30,0x6c,2,0x65,0x3d,0x69,0x4b,0x6f,0x3f,0x18, -0x67,0x68,0x74,0x74,0x6f,0x6c,0x65,0x66,0x74,0x22,2,0x65,0x38,0x69,0x48,0x6f, -0x16,0x76,0x65,0x72,0x72,0x69,0x64,0x65,0x3f,0x17,0x6d,0x62,0x65,0x64,0x64,0x69, -0x6e,0x67,0x3d,0x15,0x73,0x6f,0x6c,0x61,0x74,0x65,0x4b,0x30,0x1e,0x65,0x67,0x6d, -0x65,0x6e,0x74,0x73,0x65,0x70,0x61,0x72,0x61,0x74,0x6f,0x72,0x31,0x6e,0xa2,0x41, -0x6f,0xa2,0x53,0x70,2,0x61,0x66,0x64,0x86,0x6f,0x1b,0x70,0x64,0x69,0x72,0x65, -0x63,0x74,0x69,0x6f,0x6e,0x61,0x6c,1,0x66,0x32,0x69,0x15,0x73,0x6f,0x6c,0x61, -0x74,0x65,0x4d,0x14,0x6f,0x72,0x6d,0x61,0x74,0x41,0x1f,0x72,0x61,0x67,0x72,0x61, -0x70,0x68,0x73,0x65,0x70,0x61,0x72,0x61,0x74,0x6f,0x72,0x2f,1,0x66,0x41,0x69, -0x4d,1,0x6f,0x28,0x73,0x10,0x6d,0x43,0x1b,0x6e,0x73,0x70,0x61,0x63,0x69,0x6e, -0x67,0x6d,0x61,0x72,0x6b,0x43,1,0x6e,0x35,0x74,0x19,0x68,0x65,0x72,0x6e,0x65, -0x75,0x74,0x72,0x61,0x6c,0x35,0x65,0x88,0x65,0x98,0x66,0xa2,0x6a,0x6c,0x20,1, -0x65,0x30,0x72,2,0x65,0x37,0x69,0x49,0x6f,0x39,0x18,0x66,0x74,0x74,0x6f,0x72, -0x69,0x67,0x68,0x74,0x20,2,0x65,0x38,0x69,0x48,0x6f,0x16,0x76,0x65,0x72,0x72, -0x69,0x64,0x65,0x39,0x17,0x6d,0x62,0x65,0x64,0x64,0x69,0x6e,0x67,0x37,0x15,0x73, -0x6f,0x6c,0x61,0x74,0x65,0x49,3,0x6e,0x25,0x73,0x27,0x74,0x29,0x75,0x15,0x72, -0x6f,0x70,0x65,0x61,0x6e,2,0x6e,0x3c,0x73,0x46,0x74,0x18,0x65,0x72,0x6d,0x69, -0x6e,0x61,0x74,0x6f,0x72,0x29,0x14,0x75,0x6d,0x62,0x65,0x72,0x25,0x17,0x65,0x70, -0x61,0x72,0x61,0x74,0x6f,0x72,0x27,1,0x69,0x28,0x73,0x10,0x69,0x47,0x1f,0x72, -0x73,0x74,0x73,0x74,0x72,0x6f,0x6e,0x67,0x69,0x73,0x6f,0x6c,0x61,0x74,0x65,0x47, -0x61,0x4e,0x62,0x84,0x63,1,0x6f,0x24,0x73,0x2d,0x1c,0x6d,0x6d,0x6f,0x6e,0x73, -0x65,0x70,0x61,0x72,0x61,0x74,0x6f,0x72,0x2d,2,0x6c,0x3b,0x6e,0x2b,0x72,0x13, -0x61,0x62,0x69,0x63,1,0x6c,0x30,0x6e,0x14,0x75,0x6d,0x62,0x65,0x72,0x2b,0x14, -0x65,0x74,0x74,0x65,0x72,0x3b,0x2e,1,0x6e,0x45,0x6f,0x1c,0x75,0x6e,0x64,0x61, -0x72,0x79,0x6e,0x65,0x75,0x74,0x72,0x61,0x6c,0x45,0,0x16,0x6d,0xc7,0xc5,0x74, -0xc1,0xb8,0x77,0x57,0x77,0x48,0x79,0x5c,0x7a,0x1d,0x61,0x6e,0x61,0x62,0x61,0x7a, -0x61,0x72,0x73,0x71,0x75,0x61,0x72,0x65,0xa5,0x18,0x18,0x61,0x72,0x61,0x6e,0x67, -0x63,0x69,0x74,0x69,0xa3,0xfc,0x10,0x69,2,0x6a,0x3c,0x72,0x68,0x73,0x17,0x79, -0x6c,0x6c,0x61,0x62,0x6c,0x65,0x73,0xa3,0x48,0x12,0x69,0x6e,0x67,0xa2,0x74,0x1e, -0x68,0x65,0x78,0x61,0x67,0x72,0x61,0x6d,0x73,0x79,0x6d,0x62,0x6f,0x6c,0x73,0xa3, -0x74,0x16,0x61,0x64,0x69,0x63,0x61,0x6c,0x73,0xa3,0x49,0x74,0xa2,0x59,0x75,0xa4, -0x12,0x76,2,0x61,0x36,0x65,0x7a,0x73,0xa2,0x6c,0x12,0x73,0x75,0x70,0xa3,0x7d, -1,0x69,0xa3,0x9f,0x72,0x1e,0x69,0x61,0x74,0x69,0x6f,0x6e,0x73,0x65,0x6c,0x65, -0x63,0x74,0x6f,0x72,0x73,0xa2,0x6c,0x19,0x73,0x75,0x70,0x70,0x6c,0x65,0x6d,0x65, -0x6e,0x74,0xa3,0x7d,1,0x64,0x3c,0x72,0x19,0x74,0x69,0x63,0x61,0x6c,0x66,0x6f, -0x72,0x6d,0x73,0xa3,0x91,0x14,0x69,0x63,0x65,0x78,0x74,0xa2,0xaf,0x16,0x65,0x6e, -0x73,0x69,0x6f,0x6e,0x73,0xa3,0xaf,4,0x61,0x68,0x65,0xa2,0x8a,0x68,0xa2,0x8d, -0x69,0xa2,0x95,0x72,0x1c,0x61,0x6e,0x73,0x70,0x6f,0x72,0x74,0x61,0x6e,0x64,0x6d, -0x61,0x70,0xa2,0xcf,0x16,0x73,0x79,0x6d,0x62,0x6f,0x6c,0x73,0xa3,0xcf,4,0x67, -0x58,0x69,0x7e,0x6b,0xa2,0x58,0x6d,0xa2,0x5a,0x6e,0x12,0x67,0x75,0x74,0xa4,0x10, -0x19,0x63,0x6f,0x6d,0x70,0x6f,0x6e,0x65,0x6e,0x74,0x73,0xa5,0x11,2,0x61,0x2a, -0x62,0x32,0x73,0xa3,0x60,0x12,0x6c,0x6f,0x67,0xa3,0x62,0x13,0x61,0x6e,0x77,0x61, -0xa3,0x65,3,0x6c,0x52,0x74,0x56,0x76,0x5e,0x78,0x16,0x75,0x61,0x6e,0x6a,0x69, -0x6e,0x67,0xa2,0x7c,0x16,0x73,0x79,0x6d,0x62,0x6f,0x6c,0x73,0xa3,0x7c,0x10,0x65, -0xa3,0x70,0x12,0x68,0x61,0x6d,0xa3,0xae,0x12,0x69,0x65,0x74,0xa3,0xb7,0x11,0x72, -0x69,0xa3,0xdc,0x11,0x69,0x6c,0x49,0x13,0x6c,0x75,0x67,0x75,0x4b,0x10,0x61,1, -0x61,0x24,0x69,0x53,0x11,0x6e,0x61,0x3d,2,0x62,0x34,0x66,0x3c,0x72,0x13,0x68, -0x75,0x74,0x61,0xa3,0xfb,0x13,0x65,0x74,0x61,0x6e,0x57,0x14,0x69,0x6e,0x61,0x67, -0x68,0xa3,0x90,2,0x63,0x82,0x67,0x92,0x6e,0x1f,0x69,0x66,0x69,0x65,0x64,0x63, -0x61,0x6e,0x61,0x64,0x69,0x61,0x6e,0x61,0x62,0x6f,0x1f,0x72,0x69,0x67,0x69,0x6e, -0x61,0x6c,0x73,0x79,0x6c,0x6c,0x61,0x62,0x69,0x63,0x73,0x62,0x17,0x65,0x78,0x74, -0x65,0x6e,0x64,0x65,0x64,0xa3,0xad,0x11,0x61,0x73,0x62,0x12,0x65,0x78,0x74,0xa3, -0xad,0x15,0x61,0x72,0x69,0x74,0x69,0x63,0xa3,0x78,0x70,0xc2,0xeb,0x70,0xa6,1, -0x72,0xa6,0xbd,0x73,7,0x6f,0xc1,0x75,0x6f,0x74,0x70,0x9c,0x75,0xa2,0x5d,0x79, -1,0x6c,0x4c,0x72,0x12,0x69,0x61,0x63,0x3a,0x12,0x73,0x75,0x70,0xa4,0x17,0x16, -0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0xa5,0x17,0x17,0x6f,0x74,0x69,0x6e,0x61,0x67, -0x72,0x69,0xa3,0x8f,1,0x72,0x30,0x79,0x13,0x6f,0x6d,0x62,0x6f,0xa5,0x16,0x17, -0x61,0x73,0x6f,0x6d,0x70,0x65,0x6e,0x67,0xa3,0xda,1,0x61,0x32,0x65,0x14,0x63, -0x69,0x61,0x6c,0x73,0xa3,0x56,0x12,0x63,0x69,0x6e,0x1f,0x67,0x6d,0x6f,0x64,0x69, -0x66,0x69,0x65,0x72,0x6c,0x65,0x74,0x74,0x65,0x72,0x73,0x2d,2,0x6e,0x48,0x70, -0x76,0x74,0x1d,0x74,0x6f,0x6e,0x73,0x69,0x67,0x6e,0x77,0x72,0x69,0x74,0x69,0x6e, -0x67,0xa5,6,0x15,0x64,0x61,0x6e,0x65,0x73,0x65,0xa2,0x9b,0x12,0x73,0x75,0x70, -0xa2,0xdb,0x16,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0xa3,0xdb,4,0x61,0xa2,0xa8, -0x65,0x5c,0x6d,0x9e,0x70,0xa2,0x4b,0x73,0x13,0x79,0x6d,0x62,0x6f,0x1f,0x6c,0x73, -0x61,0x6e,0x64,0x70,0x69,0x63,0x74,0x6f,0x67,0x72,0x61,0x70,0x68,0x73,0xa5,5, -0x10,0x72,1,0x61,0x4e,0x73,0x12,0x63,0x72,0x69,0x1f,0x70,0x74,0x73,0x61,0x6e, -0x64,0x73,0x75,0x62,0x73,0x63,0x72,0x69,0x70,0x74,0x73,0x73,0x14,0x6e,0x64,0x73, -0x75,0x62,0x73,0x1b,0x61,0x74,0x68,0x6f,0x70,0x65,0x72,0x61,0x74,0x6f,0x72,0x73, -0xa3,0x6a,1,0x6c,0x40,0x75,1,0x61,0x6e,0x6e,0x17,0x63,0x74,0x75,0x61,0x74, -0x69,0x6f,0x6e,0xa3,0x8e,0x15,0x65,0x6d,0x65,0x6e,0x74,0x61,1,0x6c,0x50,0x72, -0x1e,0x79,0x70,0x72,0x69,0x76,0x61,0x74,0x65,0x75,0x73,0x65,0x61,0x72,0x65,0x61, -1,0x61,0xa3,0x6d,0x62,0xa3,0x6e,3,0x61,0x5c,0x6d,0x78,0x70,0xa2,0x41,0x73, -0x13,0x79,0x6d,0x62,0x6f,0x1f,0x6c,0x73,0x61,0x6e,0x64,0x70,0x69,0x63,0x74,0x6f, -0x67,0x72,0x61,0x70,0x68,0x73,0xa5,5,0x14,0x72,0x72,0x6f,0x77,0x73,2,0x61, -0xa3,0x67,0x62,0xa3,0x68,0x63,0xa3,0xfa,0x13,0x61,0x74,0x68,0x65,0x1f,0x6d,0x61, -0x74,0x69,0x63,0x61,0x6c,0x6f,0x70,0x65,0x72,0x61,0x74,0x6f,0x72,0x73,0xa3,0x6a, -0x19,0x75,0x6e,0x63,0x74,0x75,0x61,0x74,0x69,0x6f,0x6e,0xa3,0x8e,0x61,0x5a,0x68, -0x84,0x69,0xa2,0x5b,0x6d,0x16,0x61,0x6c,0x6c,0x66,0x6f,0x72,0x6d,1,0x73,0xa3, -0x54,0x76,0x16,0x61,0x72,0x69,0x61,0x6e,0x74,0x73,0xa3,0x54,1,0x6d,0x36,0x75, -0x16,0x72,0x61,0x73,0x68,0x74,0x72,0x61,0xa3,0xa1,0x15,0x61,0x72,0x69,0x74,0x61, -0x6e,0xa3,0xac,1,0x61,0x52,0x6f,0x13,0x72,0x74,0x68,0x61,0x1f,0x6e,0x64,0x66, -0x6f,0x72,0x6d,0x61,0x74,0x63,0x6f,0x6e,0x74,0x72,0x6f,0x6c,0x73,0xa3,0xf7,1, -0x72,0x2e,0x76,0x12,0x69,0x61,0x6e,0xa3,0x79,0x12,0x61,0x64,0x61,0xa3,0xd9,1, -0x64,0x50,0x6e,0x13,0x68,0x61,0x6c,0x61,0x50,0x1d,0x61,0x72,0x63,0x68,0x61,0x69, -0x63,0x6e,0x75,0x6d,0x62,0x65,0x72,0x73,0xa3,0xf9,0x13,0x64,0x68,0x61,0x6d,0xa3, -0xf8,5,0x72,0x35,0x72,0x44,0x73,0x64,0x75,1,0x61,0xa3,0x4e,0x6e,0x17,0x63, -0x74,0x75,0x61,0x74,0x69,0x6f,0x6e,0x71,0x17,0x69,0x76,0x61,0x74,0x65,0x75,0x73, -0x65,0xa2,0x4e,0x13,0x61,0x72,0x65,0x61,0xa3,0x4e,0x1b,0x61,0x6c,0x74,0x65,0x72, -0x70,0x61,0x68,0x6c,0x61,0x76,0x69,0xa3,0xf6,0x61,0x40,0x68,0x82,0x6c,0x19,0x61, -0x79,0x69,0x6e,0x67,0x63,0x61,0x72,0x64,0x73,0xa3,0xcc,2,0x68,0x38,0x6c,0x4a, -0x75,0x15,0x63,0x69,0x6e,0x68,0x61,0x75,0xa3,0xf5,0x17,0x61,0x77,0x68,0x68,0x6d, -0x6f,0x6e,0x67,0xa3,0xf3,0x15,0x6d,0x79,0x72,0x65,0x6e,0x65,0xa3,0xf4,1,0x61, -0x8e,0x6f,1,0x65,0x74,0x6e,0x16,0x65,0x74,0x69,0x63,0x65,0x78,0x74,0xa2,0x72, -1,0x65,0x2c,0x73,0x11,0x75,0x70,0xa3,0x8d,0x15,0x6e,0x73,0x69,0x6f,0x6e,0x73, -0xa2,0x72,0x19,0x73,0x75,0x70,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0xa3,0x8d,0x15, -0x6e,0x69,0x63,0x69,0x61,0x6e,0xa3,0x97,1,0x67,0x3e,0x69,0x13,0x73,0x74,0x6f, -0x73,0xa2,0xa6,0x13,0x64,0x69,0x73,0x63,0xa3,0xa6,0x12,0x73,0x70,0x61,0xa3,0x96, -1,0x65,0x5c,0x75,1,0x6d,0x2a,0x6e,0x11,0x69,0x63,0x67,0x10,0x69,0xa2,0xc0, -0x1d,0x6e,0x75,0x6d,0x65,0x72,0x61,0x6c,0x73,0x79,0x6d,0x62,0x6f,0x6c,0x73,0xa3, -0xc0,0x13,0x6a,0x61,0x6e,0x67,0xa3,0xa3,0x6d,0xa2,0xc3,0x6e,0xa6,0xd2,0x6f,5, -0x70,0x4b,0x70,0x46,0x72,0x7a,0x73,1,0x61,0x30,0x6d,0x13,0x61,0x6e,0x79,0x61, -0xa3,0x7a,0x11,0x67,0x65,0xa5,0xf,0x18,0x74,0x69,0x63,0x61,0x6c,0x63,0x68,0x61, -0x72,0x1f,0x61,0x63,0x74,0x65,0x72,0x72,0x65,0x63,0x6f,0x67,0x6e,0x69,0x74,0x69, -0x6f,0x6e,0x85,1,0x69,0x46,0x6e,0x1e,0x61,0x6d,0x65,0x6e,0x74,0x61,0x6c,0x64, -0x69,0x6e,0x67,0x62,0x61,0x74,0x73,0xa3,0xf2,0x11,0x79,0x61,0x47,0x63,0xa2,0x66, -0x67,0xa2,0x66,0x6c,1,0x63,0xa2,0x57,0x64,5,0x70,0x2d,0x70,0x36,0x73,0x56, -0x74,0x14,0x75,0x72,0x6b,0x69,0x63,0xa3,0xbf,0x11,0x65,0x72,1,0x6d,0x2e,0x73, -0x12,0x69,0x61,0x6e,0xa3,0x8c,0x11,0x69,0x63,0xa3,0xf1,0x1a,0x6f,0x75,0x74,0x68, -0x61,0x72,0x61,0x62,0x69,0x61,0x6e,0xa3,0xbb,0x68,0x42,0x69,0x54,0x6e,0x1a,0x6f, -0x72,0x74,0x68,0x61,0x72,0x61,0x62,0x69,0x61,0x6e,0xa3,0xf0,0x17,0x75,0x6e,0x67, -0x61,0x72,0x69,0x61,0x6e,0xa5,4,0x14,0x74,0x61,0x6c,0x69,0x63,0xa3,0x58,0x13, -0x68,0x69,0x6b,0x69,0xa3,0x9d,0x10,0x72,0x85,0x12,0x68,0x61,0x6d,0x65,6,0x6f, -0x86,0x6f,0x6c,0x72,0xa2,0x61,0x75,0xa2,0x62,0x79,0x14,0x61,0x6e,0x6d,0x61,0x72, -0x58,0x12,0x65,0x78,0x74,2,0x61,0xa3,0xb6,0x62,0xa3,0xee,0x65,0x13,0x6e,0x64, -0x65,0x64,1,0x61,0xa3,0xb6,0x62,0xa3,0xee,1,0x64,0x52,0x6e,0x15,0x67,0x6f, -0x6c,0x69,0x61,0x6e,0x6a,0x12,0x73,0x75,0x70,0xa4,0xd,0x16,0x70,0x6c,0x65,0x6d, -0x65,0x6e,0x74,0xa5,0xd,0x10,0x69,0xa2,0xec,0x13,0x66,0x69,0x65,0x72,1,0x6c, -0x3c,0x74,0x19,0x6f,0x6e,0x65,0x6c,0x65,0x74,0x74,0x65,0x72,0x73,0xa3,0x8a,0x15, -0x65,0x74,0x74,0x65,0x72,0x73,0x2d,0x10,0x6f,0xa3,0xed,1,0x6c,0x44,0x73,0x11, -0x69,0x63,0xa2,0x5c,0x18,0x61,0x6c,0x73,0x79,0x6d,0x62,0x6f,0x6c,0x73,0xa3,0x5c, -0x13,0x74,0x61,0x6e,0x69,0xa5,3,0x61,0xa2,0x9b,0x65,0xa4,0x36,0x69,1,0x61, -0xa2,0x8f,0x73,0x10,0x63,5,0x70,0x18,0x70,0xa2,0x71,0x73,0x36,0x74,0x17,0x65, -0x63,0x68,0x6e,0x69,0x63,0x61,0x6c,0x81,0x15,0x79,0x6d,0x62,0x6f,0x6c,0x73,0x8f, -0x61,0xa2,0x66,0x65,0x46,0x6d,0x19,0x61,0x74,0x68,0x73,0x79,0x6d,0x62,0x6f,0x6c, -0x73,1,0x61,0xa3,0x66,0x62,0xa3,0x69,0x17,0x6c,0x6c,0x61,0x6e,0x65,0x6f,0x75, -0x73,2,0x6d,0x3a,0x73,0x6c,0x74,0x17,0x65,0x63,0x68,0x6e,0x69,0x63,0x61,0x6c, -0x81,0x11,0x61,0x74,0x1f,0x68,0x65,0x6d,0x61,0x74,0x69,0x63,0x61,0x6c,0x73,0x79, -0x6d,0x62,0x6f,0x6c,0x73,1,0x61,0xa3,0x66,0x62,0xa3,0x69,0x15,0x79,0x6d,0x62, -0x6f,0x6c,0x73,0x8e,0x12,0x61,0x6e,0x64,1,0x61,0x3c,0x70,0x19,0x69,0x63,0x74, -0x6f,0x67,0x72,0x61,0x70,0x68,0x73,0xa3,0xcd,0x14,0x72,0x72,0x6f,0x77,0x73,0xa3, -0x73,0x10,0x6f,0xa3,0xd8,5,0x72,0x62,0x72,0xa2,0x4c,0x73,0xa2,0x50,0x74,0x10, -0x68,2,0x61,0x3a,0x65,0x4a,0x6f,0x17,0x70,0x65,0x72,0x61,0x74,0x6f,0x72,0x73, -0x7f,0x16,0x6c,0x70,0x68,0x61,0x6e,0x75,0x6d,0xa3,0x5d,0x16,0x6d,0x61,0x74,0x69, -0x63,0x61,0x6c,1,0x61,0x36,0x6f,0x17,0x70,0x65,0x72,0x61,0x74,0x6f,0x72,0x73, -0x7f,0x11,0x6c,0x70,0x1f,0x68,0x61,0x6e,0x75,0x6d,0x65,0x72,0x69,0x63,0x73,0x79, -0x6d,0x62,0x6f,0x6c,0x73,0xa3,0x5d,0x13,0x63,0x68,0x65,0x6e,0xa5,0xc,0x18,0x61, -0x72,0x61,0x6d,0x67,0x6f,0x6e,0x64,0x69,0xa5,0x14,0x68,0x4c,0x6c,0x7a,0x6e,1, -0x64,0x34,0x69,0x15,0x63,0x68,0x61,0x65,0x61,0x6e,0xa3,0xea,0x12,0x61,0x69,0x63, -0xa3,0xc6,1,0x61,0x3e,0x6a,0x12,0x6f,0x6e,0x67,0xa2,0xaa,0x14,0x74,0x69,0x6c, -0x65,0x73,0xa3,0xaa,0x13,0x6a,0x61,0x6e,0x69,0xa3,0xe9,0x15,0x61,0x79,0x61,0x6c, -0x61,0x6d,0x4f,2,0x65,0x66,0x6e,0x98,0x72,0x14,0x6f,0x69,0x74,0x69,0x63,1, -0x63,0x3c,0x68,0x19,0x69,0x65,0x72,0x6f,0x67,0x6c,0x79,0x70,0x68,0x73,0xa3,0xd7, -0x15,0x75,0x72,0x73,0x69,0x76,0x65,0xa3,0xd6,0x17,0x74,0x65,0x69,0x6d,0x61,0x79, -0x65,0x6b,0xa2,0xb8,0x12,0x65,0x78,0x74,0xa2,0xd5,0x16,0x65,0x6e,0x73,0x69,0x6f, -0x6e,0x73,0xa3,0xd5,0x18,0x64,0x65,0x6b,0x69,0x6b,0x61,0x6b,0x75,0x69,0xa3,0xeb, -5,0x6b,0x23,0x6b,0x4c,0x6f,0x50,0x75,1,0x6d,0x2c,0x73,0x11,0x68,0x75,0xa5, -0x15,0x17,0x62,0x65,0x72,0x66,0x6f,0x72,0x6d,0x73,0x7b,0x10,0x6f,0xa3,0x92,0x14, -0x62,0x6c,0x6f,0x63,0x6b,0x21,0x61,0x44,0x62,0x21,0x65,0x10,0x77,1,0x61,0xa5, -0xe,0x74,0x14,0x61,0x69,0x6c,0x75,0x65,0xa3,0x8b,0x16,0x62,0x61,0x74,0x61,0x65, -0x61,0x6e,0xa3,0xef,0x67,0xc3,0xcd,0x6a,0xc1,0x95,0x6a,0xa2,0xc5,0x6b,0xa2,0xde, -0x6c,4,0x61,0x54,0x65,0xa2,0x61,0x69,0xa2,0x78,0x6f,0xa2,0xa7,0x79,1,0x63, -0x2e,0x64,0x12,0x69,0x61,0x6e,0xa3,0xa9,0x12,0x69,0x61,0x6e,0xa3,0xa7,1,0x6f, -0x55,0x74,0x11,0x69,0x6e,1,0x31,0x82,0x65,0x11,0x78,0x74,4,0x61,0x5c,0x62, -0x29,0x63,0xa3,0x94,0x64,0xa3,0x95,0x65,0xa2,0xe7,0x13,0x6e,0x64,0x65,0x64,4, -0x61,0x36,0x62,0x29,0x63,0xa3,0x94,0x64,0xa3,0x95,0x65,0xa3,0xe7,0x26,0x18,0x64, -0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x6d,0x24,0x12,0x73,0x75,0x70,0x24,0x16, -0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x25,1,0x70,0x42,0x74,0x1d,0x74,0x65,0x72, -0x6c,0x69,0x6b,0x65,0x73,0x79,0x6d,0x62,0x6f,0x6c,0x73,0x79,0x12,0x63,0x68,0x61, -0xa3,0x9c,2,0x6d,0x2e,0x6e,0x34,0x73,0x10,0x75,0xa3,0xb0,0x11,0x62,0x75,0xa3, -0x6f,0x12,0x65,0x61,0x72,1,0x61,0xa3,0xe8,0x62,1,0x69,0x38,0x73,0x17,0x79, -0x6c,0x6c,0x61,0x62,0x61,0x72,0x79,0xa3,0x75,0x17,0x64,0x65,0x6f,0x67,0x72,0x61, -0x6d,0x73,0xa3,0x76,0x1a,0x77,0x73,0x75,0x72,0x72,0x6f,0x67,0x61,0x74,0x65,0x73, -0xa3,0x4d,0x10,0x61,1,0x6d,0x32,0x76,0x14,0x61,0x6e,0x65,0x73,0x65,0xa3,0xb5, -0x10,0x6f,0x5c,0x12,0x65,0x78,0x74,1,0x61,0xa3,0xb4,0x62,0xa3,0xb9,1,0x61, -0x80,0x68,3,0x61,0x3c,0x6d,0x4c,0x6f,0x64,0x75,0x15,0x64,0x61,0x77,0x61,0x64, -0x69,0xa3,0xe6,0x16,0x72,0x6f,0x73,0x68,0x74,0x68,0x69,0xa3,0x89,0x11,0x65,0x72, -0x68,0x16,0x73,0x79,0x6d,0x62,0x6f,0x6c,0x73,0xa3,0x71,0x12,0x6a,0x6b,0x69,0xa3, -0xe5,3,0x69,0x3a,0x6e,0x42,0x74,0xa2,0x51,0x79,0x13,0x61,0x68,0x6c,0x69,0xa3, -0xa2,0x12,0x74,0x68,0x69,0xa3,0xc1,3,0x61,0x34,0x62,0x76,0x67,0x7c,0x6e,0x12, -0x61,0x64,0x61,0x4d,1,0x65,0x40,0x73,0x11,0x75,0x70,0xa2,0xcb,0x16,0x70,0x6c, -0x65,0x6d,0x65,0x6e,0x74,0xa3,0xcb,0x11,0x78,0x74,1,0x61,0xa5,0x13,0x65,0x14, -0x6e,0x64,0x65,0x64,0x61,0xa5,0x13,0x11,0x75,0x6e,0xa3,0x42,0x11,0x78,0x69,0x96, -0x17,0x72,0x61,0x64,0x69,0x63,0x61,0x6c,0x73,0x97,0x14,0x61,0x6b,0x61,0x6e,0x61, -0x9e,1,0x65,0x4c,0x70,0x10,0x68,0x1f,0x6f,0x6e,0x65,0x74,0x69,0x63,0x65,0x78, -0x74,0x65,0x6e,0x73,0x69,0x6f,0x6e,0x73,0xa3,0x6b,0x11,0x78,0x74,0xa3,0x6b,0x67, -0xa2,0xa3,0x68,0xa4,0x53,0x69,3,0x64,0x4c,0x6d,0xa2,0x55,0x6e,0xa2,0x62,0x70, -0x13,0x61,0x65,0x78,0x74,0x2a,0x16,0x65,0x6e,0x73,0x69,0x6f,0x6e,0x73,0x2b,1, -0x63,0x99,0x65,0x17,0x6f,0x67,0x72,0x61,0x70,0x68,0x69,0x63,1,0x64,0x56,0x73, -0x15,0x79,0x6d,0x62,0x6f,0x6c,0x73,0xa4,0xb,0x1d,0x61,0x6e,0x64,0x70,0x75,0x6e, -0x63,0x74,0x75,0x61,0x74,0x69,0x6f,0x6e,0xa5,0xb,0x13,0x65,0x73,0x63,0x72,0x1f, -0x69,0x70,0x74,0x69,0x6f,0x6e,0x63,0x68,0x61,0x72,0x61,0x63,0x74,0x65,0x72,0x73, -0x99,0x1c,0x70,0x65,0x72,0x69,0x61,0x6c,0x61,0x72,0x61,0x6d,0x61,0x69,0x63,0xa3, -0xba,1,0x64,0x62,0x73,0x1b,0x63,0x72,0x69,0x70,0x74,0x69,0x6f,0x6e,0x61,0x6c, -0x70,0x61,1,0x68,0x32,0x72,0x14,0x74,0x68,0x69,0x61,0x6e,0xa3,0xbd,0x13,0x6c, -0x61,0x76,0x69,0xa3,0xbe,0x1c,0x69,0x63,0x6e,0x75,0x6d,0x62,0x65,0x72,0x66,0x6f, -0x72,0x6d,0x73,0xa3,0xb2,4,0x65,0x58,0x6c,0xa2,0x63,0x6f,0xa2,0x7b,0x72,0xa2, -0x7f,0x75,1,0x6a,0x30,0x72,0x14,0x6d,0x75,0x6b,0x68,0x69,0x43,0x14,0x61,0x72, -0x61,0x74,0x69,0x45,1,0x6e,0x8c,0x6f,1,0x6d,0x4e,0x72,0x13,0x67,0x69,0x61, -0x6e,0x5a,0x12,0x73,0x75,0x70,0xa2,0x87,0x16,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74, -0xa3,0x87,0x1a,0x65,0x74,0x72,0x69,0x63,0x73,0x68,0x61,0x70,0x65,0x73,0x8c,0x12, -0x65,0x78,0x74,0xa2,0xe3,0x14,0x65,0x6e,0x64,0x65,0x64,0xa3,0xe3,0x1e,0x65,0x72, -0x61,0x6c,0x70,0x75,0x6e,0x63,0x74,0x75,0x61,0x74,0x69,0x6f,0x6e,0x71,0x17,0x61, -0x67,0x6f,0x6c,0x69,0x74,0x69,0x63,0xa2,0x88,0x12,0x73,0x75,0x70,0xa4,0xa,0x16, -0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0xa5,0xa,0x13,0x74,0x68,0x69,0x63,0xa3,0x59, -1,0x61,0x5c,0x65,0x11,0x65,0x6b,0x30,1,0x61,0x38,0x65,0x11,0x78,0x74,0x6e, -0x14,0x65,0x6e,0x64,0x65,0x64,0x6f,0x17,0x6e,0x64,0x63,0x6f,0x70,0x74,0x69,0x63, -0x31,0x13,0x6e,0x74,0x68,0x61,0xa3,0xe4,2,0x61,0xa2,0x48,0x65,0xa2,0xcf,0x69, -1,0x67,0x30,0x72,0x14,0x61,0x67,0x61,0x6e,0x61,0x9d,0x10,0x68,1,0x70,0x3a, -0x73,0x18,0x75,0x72,0x72,0x6f,0x67,0x61,0x74,0x65,0x73,0xa3,0x4b,1,0x72,0x3c, -0x75,0x19,0x73,0x75,0x72,0x72,0x6f,0x67,0x61,0x74,0x65,0x73,0xa3,0x4c,0x11,0x69, -0x76,0x1f,0x61,0x74,0x65,0x75,0x73,0x65,0x73,0x75,0x72,0x72,0x6f,0x67,0x61,0x74, -0x65,0x73,0xa3,0x4c,2,0x6c,0x32,0x6e,0x9a,0x74,0x12,0x72,0x61,0x6e,0xa5,2, -0x10,0x66,2,0x61,0x58,0x6d,0x70,0x77,0x14,0x69,0x64,0x74,0x68,0x61,0x1f,0x6e, -0x64,0x66,0x75,0x6c,0x6c,0x77,0x69,0x64,0x74,0x68,0x66,0x6f,0x72,0x6d,0x73,0xa3, -0x57,0x1a,0x6e,0x64,0x66,0x75,0x6c,0x6c,0x66,0x6f,0x72,0x6d,0x73,0xa3,0x57,0x13, -0x61,0x72,0x6b,0x73,0xa3,0x52,1,0x67,0x2e,0x75,0x12,0x6e,0x6f,0x6f,0xa3,0x63, -0x11,0x75,0x6c,0xa2,0x4a,2,0x63,0x3c,0x6a,0x5e,0x73,0x17,0x79,0x6c,0x6c,0x61, -0x62,0x6c,0x65,0x73,0xa3,0x4a,0x1f,0x6f,0x6d,0x70,0x61,0x74,0x69,0x62,0x69,0x6c, -0x69,0x74,0x79,0x6a,0x61,0x6d,0x6f,0xa3,0x41,0x12,0x61,0x6d,0x6f,0x5c,0x17,0x65, -0x78,0x74,0x65,0x6e,0x64,0x65,0x64,1,0x61,0xa3,0xb4,0x62,0xa3,0xb9,0x13,0x62, -0x72,0x65,0x77,0x37,0x61,0xa2,0xe9,0x62,0xa6,0x29,0x63,0xa6,0xfe,0x64,0xac,0x7c, -0x65,5,0x6d,0xa2,0x6d,0x86,0x6e,0x96,0x74,0x15,0x68,0x69,0x6f,0x70,0x69,0x63, -0x5e,1,0x65,0x40,0x73,0x11,0x75,0x70,0xa2,0x86,0x16,0x70,0x6c,0x65,0x6d,0x65, -0x6e,0x74,0xa3,0x86,0x11,0x78,0x74,0xa2,0x85,1,0x61,0xa3,0xc8,0x65,0x13,0x6e, -0x64,0x65,0x64,0xa2,0x85,0x10,0x61,0xa3,0xc8,0x16,0x6f,0x74,0x69,0x63,0x6f,0x6e, -0x73,0xa3,0xce,0x15,0x63,0x6c,0x6f,0x73,0x65,0x64,2,0x61,0x5a,0x63,0x9e,0x69, -0x1c,0x64,0x65,0x6f,0x67,0x72,0x61,0x70,0x68,0x69,0x63,0x73,0x75,0x70,0xa2,0xc4, -0x16,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0xa3,0xc4,0x16,0x6c,0x70,0x68,0x61,0x6e, -0x75,0x6d,0x86,1,0x65,0x2c,0x73,0x11,0x75,0x70,0xa3,0xc3,0x13,0x72,0x69,0x63, -0x73,0x86,0x18,0x75,0x70,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0xa3,0xc3,0x11,0x6a, -0x6b,0xa2,0x44,0x1f,0x6c,0x65,0x74,0x74,0x65,0x72,0x73,0x61,0x6e,0x64,0x6d,0x6f, -0x6e,0x74,0x68,0x73,0xa3,0x44,0x61,0x36,0x67,0x62,0x6c,0x14,0x62,0x61,0x73,0x61, -0x6e,0xa3,0xe2,0x13,0x72,0x6c,0x79,0x64,0x1f,0x79,0x6e,0x61,0x73,0x74,0x69,0x63, -0x63,0x75,0x6e,0x65,0x69,0x66,0x6f,0x72,0x6d,0xa5,1,0x10,0x79,0x1f,0x70,0x74, -0x69,0x61,0x6e,0x68,0x69,0x65,0x72,0x6f,0x67,0x6c,0x79,0x70,0x68,0x73,0xa3,0xc2, -7,0x6e,0xc0,0xe5,0x6e,0x3e,0x72,0xa2,0x5d,0x73,0xa2,0xd8,0x76,0x14,0x65,0x73, -0x74,0x61,0x6e,0xa3,0xbc,1,0x61,0x92,0x63,0x13,0x69,0x65,0x6e,0x74,1,0x67, -0x34,0x73,0x15,0x79,0x6d,0x62,0x6f,0x6c,0x73,0xa3,0xa5,0x13,0x72,0x65,0x65,0x6b, -1,0x6d,0x34,0x6e,0x15,0x75,0x6d,0x62,0x65,0x72,0x73,0xa3,0x7f,0x13,0x75,0x73, -0x69,0x63,0xa2,0x7e,0x19,0x61,0x6c,0x6e,0x6f,0x74,0x61,0x74,0x69,0x6f,0x6e,0xa3, -0x7e,0x10,0x74,0x1f,0x6f,0x6c,0x69,0x61,0x6e,0x68,0x69,0x65,0x72,0x6f,0x67,0x6c, -0x79,0x70,0x68,0x73,0xa3,0xfe,2,0x61,0x32,0x6d,0xa2,0x71,0x72,0x12,0x6f,0x77, -0x73,0x7d,0x12,0x62,0x69,0x63,0x38,3,0x65,0x4a,0x6d,0x66,0x70,0xa2,0x43,0x73, -0x11,0x75,0x70,0xa2,0x80,0x16,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0xa3,0x80,0x11, -0x78,0x74,1,0x61,0xa3,0xd2,0x65,0x14,0x6e,0x64,0x65,0x64,0x61,0xa3,0xd2,0x12, -0x61,0x74,0x68,0xa2,0xd3,0x18,0x65,0x6d,0x61,0x74,0x69,0x63,0x61,0x6c,0x61,0x1f, -0x6c,0x70,0x68,0x61,0x62,0x65,0x74,0x69,0x63,0x73,0x79,0x6d,0x62,0x6f,0x6c,0x73, -0xa3,0xd3,1,0x66,0x42,0x72,0x1e,0x65,0x73,0x65,0x6e,0x74,0x61,0x74,0x69,0x6f, -0x6e,0x66,0x6f,0x72,0x6d,0x73,1,0x61,0xa3,0x51,0x62,0xa3,0x55,0x14,0x65,0x6e, -0x69,0x61,0x6e,0x35,0x12,0x63,0x69,0x69,0x23,0x64,0x9e,0x65,0xa2,0x42,0x68,0xa2, -0x4d,0x6c,1,0x63,0x62,0x70,0x17,0x68,0x61,0x62,0x65,0x74,0x69,0x63,0x70,1, -0x66,0xa3,0x50,0x72,0x1e,0x65,0x73,0x65,0x6e,0x74,0x61,0x74,0x69,0x6f,0x6e,0x66, -0x6f,0x72,0x6d,0x73,0xa3,0x50,0x16,0x68,0x65,0x6d,0x69,0x63,0x61,0x6c,0xa2,0xd0, -0x16,0x73,0x79,0x6d,0x62,0x6f,0x6c,0x73,0xa3,0xd0,0x12,0x6c,0x61,0x6d,0xa5,7, -0x1a,0x67,0x65,0x61,0x6e,0x6e,0x75,0x6d,0x62,0x65,0x72,0x73,0xa3,0x77,0x11,0x6f, -0x6d,0xa3,0xfd,7,0x6f,0x71,0x6f,0x64,0x72,0xa2,0x41,0x75,0xa2,0x58,0x79,0x1b, -0x7a,0x61,0x6e,0x74,0x69,0x6e,0x65,0x6d,0x75,0x73,0x69,0x63,0xa2,0x5b,0x18,0x61, -0x6c,0x73,0x79,0x6d,0x62,0x6f,0x6c,0x73,0xa3,0x5b,1,0x70,0x34,0x78,0x16,0x64, -0x72,0x61,0x77,0x69,0x6e,0x67,0x89,0x14,0x6f,0x6d,0x6f,0x66,0x6f,0xa0,0x12,0x65, -0x78,0x74,0xa2,0x43,0x14,0x65,0x6e,0x64,0x65,0x64,0xa3,0x43,0x10,0x61,1,0x68, -0x40,0x69,0x12,0x6c,0x6c,0x65,0x92,0x17,0x70,0x61,0x74,0x74,0x65,0x72,0x6e,0x73, -0x93,0x11,0x6d,0x69,0xa3,0xc9,1,0x67,0x2c,0x68,0x11,0x69,0x64,0xa3,0x64,0x14, -0x69,0x6e,0x65,0x73,0x65,0xa3,0x81,0x61,0x48,0x65,0xa2,0x4e,0x68,0xa2,0x52,0x6c, -0x1a,0x6f,0x63,0x6b,0x65,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x73,0x8b,3,0x6c,0x34, -0x6d,0x40,0x73,0x66,0x74,0x11,0x61,0x6b,0xa3,0xc7,0x14,0x69,0x6e,0x65,0x73,0x65, -0xa3,0x93,0x11,0x75,0x6d,0xa2,0xb1,0x12,0x73,0x75,0x70,0xa2,0xca,0x16,0x70,0x6c, -0x65,0x6d,0x65,0x6e,0x74,0xa3,0xca,1,0x69,0x30,0x73,0x13,0x61,0x76,0x61,0x68, -0xa3,0xdd,0x15,0x63,0x6c,0x61,0x74,0x69,0x6e,0x23,0x14,0x6e,0x67,0x61,0x6c,0x69, -0x41,0x16,0x61,0x69,0x6b,0x73,0x75,0x6b,0x69,0xa5,8,5,0x6f,0xc1,0x4c,0x6f, -0xa2,0x55,0x75,0xa4,0x10,0x79,1,0x70,0x9c,0x72,0x14,0x69,0x6c,0x6c,0x69,0x63, -0x32,1,0x65,0x4c,0x73,0x11,0x75,0x70,0xa2,0x61,0x16,0x70,0x6c,0x65,0x6d,0x65, -0x6e,0x74,0xa2,0x61,0x12,0x61,0x72,0x79,0xa3,0x61,0x11,0x78,0x74,3,0x61,0xa3, -0x9e,0x62,0xa3,0xa0,0x63,0xa5,9,0x65,0x13,0x6e,0x64,0x65,0x64,2,0x61,0xa3, -0x9e,0x62,0xa3,0xa0,0x63,0xa5,9,0x1c,0x72,0x69,0x6f,0x74,0x73,0x79,0x6c,0x6c, -0x61,0x62,0x61,0x72,0x79,0xa3,0x7b,3,0x6d,0x5a,0x6e,0xa2,0x95,0x70,0xa2,0xa0, -0x75,0x17,0x6e,0x74,0x69,0x6e,0x67,0x72,0x6f,0x64,0xa2,0x9a,0x17,0x6e,0x75,0x6d, -0x65,0x72,0x61,0x6c,0x73,0xa3,0x9a,2,0x62,0x3a,0x6d,0xa2,0x5f,0x70,0x15,0x61, -0x74,0x6a,0x61,0x6d,0x6f,0xa3,0x41,0x14,0x69,0x6e,0x69,0x6e,0x67,2,0x64,0x46, -0x68,0x9e,0x6d,0x1d,0x61,0x72,0x6b,0x73,0x66,0x6f,0x72,0x73,0x79,0x6d,0x62,0x6f, -0x6c,0x73,0x77,0x1e,0x69,0x61,0x63,0x72,0x69,0x74,0x69,0x63,0x61,0x6c,0x6d,0x61, -0x72,0x6b,0x73,0x2e,2,0x65,0x40,0x66,0xa6,0x1c,0x73,0x18,0x75,0x70,0x70,0x6c, -0x65,0x6d,0x65,0x6e,0x74,0xa3,0x83,0x16,0x78,0x74,0x65,0x6e,0x64,0x65,0x64,0xa3, -0xe0,0x17,0x61,0x6c,0x66,0x6d,0x61,0x72,0x6b,0x73,0xa3,0x52,0x11,0x6f,0x6e,0x1f, -0x69,0x6e,0x64,0x69,0x63,0x6e,0x75,0x6d,0x62,0x65,0x72,0x66,0x6f,0x72,0x6d,0x73, -0xa3,0xb2,0x1b,0x74,0x72,0x6f,0x6c,0x70,0x69,0x63,0x74,0x75,0x72,0x65,0x73,0x83, -0x12,0x74,0x69,0x63,0xa2,0x84,0x1b,0x65,0x70,0x61,0x63,0x74,0x6e,0x75,0x6d,0x62, -0x65,0x72,0x73,0xa3,0xdf,1,0x6e,0x3e,0x72,0x1b,0x72,0x65,0x6e,0x63,0x79,0x73, -0x79,0x6d,0x62,0x6f,0x6c,0x73,0x75,0x15,0x65,0x69,0x66,0x6f,0x72,0x6d,0xa2,0x98, -0x16,0x6e,0x75,0x6d,0x62,0x65,0x72,0x73,0xa2,0x99,0x1d,0x61,0x6e,0x64,0x70,0x75, -0x6e,0x63,0x74,0x75,0x61,0x74,0x69,0x6f,0x6e,0xa3,0x99,0x61,0xa2,0xdb,0x68,0xa4, -5,0x6a,0x10,0x6b,0xa2,0x47,4,0x63,0x86,0x65,0xa2,0x7d,0x72,0xa2,0x92,0x73, -0xa2,0xa4,0x75,0x1f,0x6e,0x69,0x66,0x69,0x65,0x64,0x69,0x64,0x65,0x6f,0x67,0x72, -0x61,0x70,0x68,0x73,0xa2,0x47,0x18,0x65,0x78,0x74,0x65,0x6e,0x73,0x69,0x6f,0x6e, -5,0x64,0x65,0x64,0xa3,0xd1,0x65,0xa5,0,0x66,0xa5,0x12,0x14,0x6f,0x6d,0x70, -0x61,0x74,0xa2,0x45,1,0x66,0x96,0x69,1,0x62,0x44,0x64,0x17,0x65,0x6f,0x67, -0x72,0x61,0x70,0x68,0x73,0xa2,0x4f,0x12,0x73,0x75,0x70,0xa3,0x5f,0x14,0x69,0x6c, -0x69,0x74,0x79,0xa2,0x45,1,0x66,0x54,0x69,0x18,0x64,0x65,0x6f,0x67,0x72,0x61, -0x70,0x68,0x73,0xa2,0x4f,0x19,0x73,0x75,0x70,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74, -0xa3,0x5f,0x13,0x6f,0x72,0x6d,0x73,0xa3,0x53,0x11,0x78,0x74,5,0x64,9,0x64, -0xa3,0xd1,0x65,0xa5,0,0x66,0xa5,0x12,0x61,0xa3,0x46,0x62,0xa3,0x5e,0x63,0xa3, -0xc5,0x19,0x61,0x64,0x69,0x63,0x61,0x6c,0x73,0x73,0x75,0x70,0x94,0x16,0x70,0x6c, -0x65,0x6d,0x65,0x6e,0x74,0x95,1,0x74,0x50,0x79,0x14,0x6d,0x62,0x6f,0x6c,0x73, -0x9a,0x1d,0x61,0x6e,0x64,0x70,0x75,0x6e,0x63,0x74,0x75,0x61,0x74,0x69,0x6f,0x6e, -0x9b,0x14,0x72,0x6f,0x6b,0x65,0x73,0xa3,0x82,2,0x6e,0x48,0x72,0x64,0x75,0x1d, -0x63,0x61,0x73,0x69,0x61,0x6e,0x61,0x6c,0x62,0x61,0x6e,0x69,0x61,0x6e,0xa3,0xde, -0x1d,0x61,0x64,0x69,0x61,0x6e,0x73,0x79,0x6c,0x6c,0x61,0x62,0x69,0x63,0x73,0x63, -0x12,0x69,0x61,0x6e,0xa3,0xa8,1,0x61,0x50,0x65,0x14,0x72,0x6f,0x6b,0x65,0x65, -0x60,0x12,0x73,0x75,0x70,0xa2,0xff,0x16,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0xa3, -0xff,1,0x6b,0x26,0x6d,0xa3,0xa4,0x11,0x6d,0x61,0xa3,0xd4,3,0x65,0x3e,0x69, -0x7e,0x6f,0xa2,0x5d,0x75,0x15,0x70,0x6c,0x6f,0x79,0x61,0x6e,0xa3,0xe1,1,0x73, -0x50,0x76,0x16,0x61,0x6e,0x61,0x67,0x61,0x72,0x69,0x3e,0x12,0x65,0x78,0x74,0xa2, -0xb3,0x14,0x65,0x6e,0x64,0x65,0x64,0xa3,0xb3,0x13,0x65,0x72,0x65,0x74,0xa3,0x5a, -1,0x61,0x30,0x6e,0x14,0x67,0x62,0x61,0x74,0x73,0x91,0x18,0x63,0x72,0x69,0x74, -0x69,0x63,0x61,0x6c,0x73,0x2e,2,0x65,0x30,0x66,0x36,0x73,0x11,0x75,0x70,0xa3, -0x83,0x11,0x78,0x74,0xa3,0xe0,0x18,0x6f,0x72,0x73,0x79,0x6d,0x62,0x6f,0x6c,0x73, -0x77,0x13,0x6d,0x69,0x6e,0x6f,0xa2,0xab,0x14,0x74,0x69,0x6c,0x65,0x73,0xa3,0xab, -8,0x6d,0x5f,0x6d,0x3a,0x6e,0x48,0x73,0x7a,0x76,0xa2,0x4b,0x77,0x12,0x69,0x64, -0x65,0x43,0x11,0x65,0x64,0x32,0x12,0x69,0x61,0x6c,0x33,2,0x61,0x40,0x62,0x37, -0x6f,1,0x62,0x28,0x6e,0x10,0x65,0x21,0x13,0x72,0x65,0x61,0x6b,0x37,0x10,0x72, -0x34,0x12,0x72,0x6f,0x77,0x35,2,0x6d,0x38,0x71,0x46,0x75,1,0x62,0x3d,0x70, -0x3e,0x11,0x65,0x72,0x3f,1,0x61,0x24,0x6c,0x39,0x11,0x6c,0x6c,0x39,1,0x72, -0x3b,0x75,0x12,0x61,0x72,0x65,0x3b,0x12,0x65,0x72,0x74,0x40,0x13,0x69,0x63,0x61, -0x6c,0x41,0x63,0x58,0x65,0x92,0x66,0x96,0x69,1,0x6e,0x36,0x73,0x10,0x6f,0x30, -0x14,0x6c,0x61,0x74,0x65,0x64,0x31,0x11,0x69,0x74,0x2e,0x12,0x69,0x61,0x6c,0x2f, -2,0x61,0x36,0x69,0x48,0x6f,0x10,0x6d,0x24,0x12,0x70,0x61,0x74,0x25,0x10,0x6e, -0x22,0x15,0x6f,0x6e,0x69,0x63,0x61,0x6c,0x23,0x13,0x72,0x63,0x6c,0x65,0x27,0x11, -0x6e,0x63,0x27,2,0x69,0x3a,0x6f,0x44,0x72,0x10,0x61,0x2c,0x14,0x63,0x74,0x69, -0x6f,0x6e,0x2d,0x10,0x6e,0x28,0x11,0x61,0x6c,0x29,0x11,0x6e,0x74,0x2b,4,0x61, -0x3a,0x66,0x4c,0x68,0x5e,0x6e,0x70,0x77,0x2a,0x12,0x69,0x64,0x65,0x2b,0x22,0x17, -0x6d,0x62,0x69,0x67,0x75,0x6f,0x75,0x73,0x23,0x26,0x17,0x75,0x6c,0x6c,0x77,0x69, -0x64,0x74,0x68,0x27,0x24,0x17,0x61,0x6c,0x66,0x77,0x69,0x64,0x74,0x68,0x25,0x20, -1,0x61,0x30,0x65,0x14,0x75,0x74,0x72,0x61,0x6c,0x21,0x28,0x13,0x72,0x72,0x6f, -0x77,0x29,0xd,0x6e,0xc0,0xfb,0x73,0x6d,0x73,0x3a,0x74,0x98,0x75,0xa2,0x49,0x7a, -2,0x6c,0x3b,0x70,0x3d,0x73,0x39,5,0x6f,0x28,0x6f,0x57,0x70,0x34,0x75,0x16, -0x72,0x72,0x6f,0x67,0x61,0x74,0x65,0x45,0x11,0x61,0x63,1,0x65,0x32,0x69,0x15, -0x6e,0x67,0x6d,0x61,0x72,0x6b,0x31,0x18,0x73,0x65,0x70,0x61,0x72,0x61,0x74,0x6f, -0x72,0x39,0x63,0x53,0x6b,0x55,0x6d,0x51,0x1d,0x69,0x74,0x6c,0x65,0x63,0x61,0x73, -0x65,0x6c,0x65,0x74,0x74,0x65,0x72,0x27,1,0x6e,0x40,0x70,0x1c,0x70,0x65,0x72, -0x63,0x61,0x73,0x65,0x6c,0x65,0x74,0x74,0x65,0x72,0x23,0x17,0x61,0x73,0x73,0x69, -0x67,0x6e,0x65,0x64,0x21,0x6e,0x8a,0x6f,0xa2,0x47,0x70,8,0x66,0x14,0x66,0x5b, -0x69,0x59,0x6f,0x4f,0x72,0x24,0x73,0x49,0x17,0x69,0x76,0x61,0x74,0x65,0x75,0x73, -0x65,0x43,0x61,0x2c,0x63,0x4d,0x64,0x47,0x65,0x4b,0x1f,0x72,0x61,0x67,0x72,0x61, -0x70,0x68,0x73,0x65,0x70,0x61,0x72,0x61,0x74,0x6f,0x72,0x3d,2,0x64,0x33,0x6c, -0x35,0x6f,0x36,0x1b,0x6e,0x73,0x70,0x61,0x63,0x69,0x6e,0x67,0x6d,0x61,0x72,0x6b, -0x2d,1,0x70,0x7c,0x74,0x12,0x68,0x65,0x72,3,0x6c,0x38,0x6e,0x42,0x70,0x4c, -0x73,0x14,0x79,0x6d,0x62,0x6f,0x6c,0x57,0x14,0x65,0x74,0x74,0x65,0x72,0x2b,0x14, -0x75,0x6d,0x62,0x65,0x72,0x37,0x19,0x75,0x6e,0x63,0x74,0x75,0x61,0x74,0x69,0x6f, -0x6e,0x4f,0x1c,0x65,0x6e,0x70,0x75,0x6e,0x63,0x74,0x75,0x61,0x74,0x69,0x6f,0x6e, -0x49,0x66,0x9e,0x66,0x88,0x69,0xa2,0x4b,0x6c,0xa2,0x5c,0x6d,4,0x61,0x60,0x63, -0x31,0x65,0x2f,0x6e,0x2d,0x6f,0x15,0x64,0x69,0x66,0x69,0x65,0x72,1,0x6c,0x30, -0x73,0x14,0x79,0x6d,0x62,0x6f,0x6c,0x55,0x14,0x65,0x74,0x74,0x65,0x72,0x29,0x17, -0x74,0x68,0x73,0x79,0x6d,0x62,0x6f,0x6c,0x51,1,0x69,0x2e,0x6f,0x13,0x72,0x6d, -0x61,0x74,0x41,0x1d,0x6e,0x61,0x6c,0x70,0x75,0x6e,0x63,0x74,0x75,0x61,0x74,0x69, -0x6f,0x6e,0x5b,0x10,0x6e,0x1f,0x69,0x74,0x69,0x61,0x6c,0x70,0x75,0x6e,0x63,0x74, -0x75,0x61,0x74,0x69,0x6f,0x6e,0x59,6,0x6d,0x18,0x6d,0x29,0x6f,0x28,0x74,0x27, -0x75,0x23,0x2a,0x1c,0x77,0x65,0x72,0x63,0x61,0x73,0x65,0x6c,0x65,0x74,0x74,0x65, -0x72,0x25,0x65,0x28,0x69,0x3c,0x6c,0x25,0x19,0x74,0x74,0x65,0x72,0x6e,0x75,0x6d, -0x62,0x65,0x72,0x35,0x1a,0x6e,0x65,0x73,0x65,0x70,0x61,0x72,0x61,0x74,0x6f,0x72, -0x3b,0x63,0x44,0x64,0xa2,0x60,0x65,0x1b,0x6e,0x63,0x6c,0x6f,0x73,0x69,0x6e,0x67, -0x6d,0x61,0x72,0x6b,0x2f,6,0x6e,0x39,0x6e,0x46,0x6f,0x4e,0x73,0x45,0x75,0x1b, -0x72,0x72,0x65,0x6e,0x63,0x79,0x73,0x79,0x6d,0x62,0x6f,0x6c,0x53,0x20,0x12,0x74, -0x72,0x6c,0x3f,0x42,0x10,0x6e,1,0x6e,0x2c,0x74,0x12,0x72,0x6f,0x6c,0x3f,0x1f, -0x65,0x63,0x74,0x6f,0x72,0x70,0x75,0x6e,0x63,0x74,0x75,0x61,0x74,0x69,0x6f,0x6e, -0x4d,0x63,0x3f,0x66,0x41,0x6c,0x1d,0x6f,0x73,0x65,0x70,0x75,0x6e,0x63,0x74,0x75, -0x61,0x74,0x69,0x6f,0x6e,0x4b,2,0x61,0x30,0x65,0x4a,0x69,0x12,0x67,0x69,0x74, -0x33,0x1c,0x73,0x68,0x70,0x75,0x6e,0x63,0x74,0x75,0x61,0x74,0x69,0x6f,0x6e,0x47, -0x1a,0x63,0x69,0x6d,0x61,0x6c,0x6e,0x75,0x6d,0x62,0x65,0x72,0x33,0,0x12,0x6d, -0xc2,0x3f,0x73,0xa1,0x73,0x4e,0x74,0xa2,0x56,0x77,0xa2,0x72,0x79,0xa2,0x73,0x7a, -1,0x61,0x2c,0x68,0x12,0x61,0x69,0x6e,0x8b,0x11,0x69,0x6e,0x85,5,0x74,0x22, -0x74,0x38,0x77,0x4c,0x79,0x16,0x72,0x69,0x61,0x63,0x77,0x61,0x77,0x6f,0x18,0x72, -0x61,0x69,0x67,0x68,0x74,0x77,0x61,0x77,0xa3,0x55,0x15,0x61,0x73,0x68,0x6b,0x61, -0x66,0x6d,0x61,0x2e,0x65,0x38,0x68,0x11,0x69,0x6e,0x6b,0x10,0x64,0x62,0x11,0x68, -0x65,0x65,1,0x65,0x2e,0x6d,0x13,0x6b,0x61,0x74,0x68,0x69,0x10,0x6e,0x67,1, -0x61,0x4e,0x65,1,0x68,0x28,0x74,0x10,0x68,0x77,0x16,0x6d,0x61,0x72,0x62,0x75, -0x74,0x61,0x74,0x13,0x67,0x6f,0x61,0x6c,0x3d,1,0x68,0x71,0x77,0x73,0x11,0x61, -0x77,0x79,1,0x65,0x32,0x75,0x11,0x64,0x68,0x80,0x11,0x68,0x65,0x83,0x10,0x68, -0x7a,1,0x62,0x34,0x77,0x16,0x69,0x74,0x68,0x74,0x61,0x69,0x6c,0x7f,0x14,0x61, -0x72,0x72,0x65,0x65,0x7d,0x6d,0x6c,0x6e,0xa4,0x6b,0x70,0xa4,0x88,0x71,0xa4,0x88, -0x72,1,0x65,0x38,0x6f,0x18,0x68,0x69,0x6e,0x67,0x79,0x61,0x79,0x65,0x68,0x93, -1,0x68,0x5f,0x76,0x16,0x65,0x72,0x73,0x65,0x64,0x70,0x65,0x61,2,0x61,0x2e, -0x65,0xa4,0x3e,0x69,0x10,0x6d,0x53,1,0x6c,0xa2,0xe7,0x6e,0x16,0x69,0x63,0x68, -0x61,0x65,0x61,0x6e,0,0x12,0x6e,0x76,0x73,0x51,0x73,0x3e,0x74,0x5c,0x77,0xa0, -0x79,0xa2,0x42,0x7a,0x13,0x61,0x79,0x69,0x6e,0xa3,0x54,0x10,0x61,1,0x64,0x2e, -0x6d,0x12,0x65,0x6b,0x68,0xa3,0x4c,0x11,0x68,0x65,0xa3,0x4b,3,0x61,0x38,0x65, -0x3c,0x68,0x4a,0x77,0x13,0x65,0x6e,0x74,0x79,0xa3,0x51,0x10,0x77,0xa3,0x4d,1, -0x6e,0xa3,0x4e,0x74,0x10,0x68,0xa3,0x4f,0x14,0x61,0x6d,0x65,0x64,0x68,0xa3,0x50, -0x11,0x61,0x77,0xa3,0x52,0x12,0x6f,0x64,0x68,0xa3,0x53,0x6e,0x3a,0x6f,0x40,0x70, -0x46,0x71,0x4a,0x72,0x12,0x65,0x73,0x68,0xa3,0x4a,0x11,0x75,0x6e,0xa3,0x46,0x11, -0x6e,0x65,0xa3,0x47,0x10,0x65,0xa3,0x48,0x12,0x6f,0x70,0x68,0xa3,0x49,0x67,0x33, -0x67,0x38,0x68,0x40,0x6b,0x5e,0x6c,0x66,0x6d,0x11,0x65,0x6d,0xa3,0x45,0x13,0x69, -0x6d,0x65,0x6c,0xa1,1,0x65,0x32,0x75,0x14,0x6e,0x64,0x72,0x65,0x64,0xa3,0x42, -0x11,0x74,0x68,0xa3,0x41,0x12,0x61,0x70,0x68,0xa3,0x43,0x14,0x61,0x6d,0x65,0x64, -0x68,0xa3,0x44,0x61,0x34,0x62,0x4a,0x64,0x50,0x66,0x12,0x69,0x76,0x65,0x9f,1, -0x6c,0x2a,0x79,0x11,0x69,0x6e,0x97,0x12,0x65,0x70,0x68,0x95,0x12,0x65,0x74,0x68, -0x99,1,0x61,0x30,0x68,0x14,0x61,0x6d,0x65,0x64,0x68,0x9d,0x13,0x6c,0x65,0x74, -0x68,0x9b,0x15,0x61,0x79,0x61,0x6c,0x61,0x6d,6,0x6e,0x2c,0x6e,0x34,0x72,0x5e, -0x73,0x62,0x74,0x11,0x74,0x61,0xa3,0x63,2,0x67,0x2e,0x6e,0x32,0x79,0x10,0x61, -0xa3,0x60,0x10,0x61,0xa3,0x5d,1,0x61,0xa3,0x5e,0x6e,0x10,0x61,0xa3,0x5f,0x10, -0x61,0xa3,0x61,0x11,0x73,0x61,0xa3,0x62,0x62,0x3c,0x6a,0x42,0x6c,0x10,0x6c,1, -0x61,0xa3,0x5b,0x6c,0x10,0x61,0xa3,0x5c,0x11,0x68,0x61,0xa3,0x59,0x10,0x61,0xa3, -0x5a,0x11,0x65,0x6d,0x51,2,0x6f,0x2c,0x75,0x50,0x79,0x10,0x61,0x91,1,0x6a, -0x28,0x6f,0x10,0x6e,0x55,0x1a,0x6f,0x69,0x6e,0x69,0x6e,0x67,0x67,0x72,0x6f,0x75, -0x70,0x21,0x10,0x6e,0x57,0x10,0x65,0x59,0x10,0x61,1,0x66,0x5b,0x70,0x10,0x68, -0x5d,0x66,0x7b,0x66,0x42,0x67,0x7a,0x68,0x8a,0x6b,0xa2,0x56,0x6c,0x11,0x61,0x6d, -0x4c,0x12,0x61,0x64,0x68,0x4f,2,0x61,0x3e,0x65,0x4a,0x69,0x19,0x6e,0x61,0x6c, -0x73,0x65,0x6d,0x6b,0x61,0x74,0x68,0x35,0x15,0x72,0x73,0x69,0x79,0x65,0x68,0x8f, -0x86,0x10,0x68,0x33,0x10,0x61,1,0x66,0x37,0x6d,0x11,0x61,0x6c,0x39,1,0x61, -0x40,0x65,0x3e,1,0x68,0x28,0x74,0x10,0x68,0x45,0x40,0x13,0x67,0x6f,0x61,0x6c, -0x43,1,0x68,0x3b,0x6d,0x1a,0x7a,0x61,0x6f,0x6e,0x68,0x65,0x68,0x67,0x6f,0x61, -0x6c,0x3d,2,0x61,0x3a,0x68,0x44,0x6e,0x17,0x6f,0x74,0x74,0x65,0x64,0x68,0x65, -0x68,0x4b,1,0x66,0x47,0x70,0x10,0x68,0x49,0x12,0x61,0x70,0x68,0x89,0x61,0x2e, -0x62,0x8a,0x64,0xa2,0x51,0x65,0x31,2,0x66,0x3c,0x69,0x70,0x6c,1,0x61,0x28, -0x65,0x10,0x66,0x27,0x11,0x70,0x68,0x25,0x14,0x72,0x69,0x63,0x61,0x6e,2,0x66, -0x30,0x6e,0x36,0x71,0x11,0x61,0x66,0xa3,0x58,0x11,0x65,0x68,0xa3,0x56,0x12,0x6f, -0x6f,0x6e,0xa3,0x57,0x10,0x6e,0x23,1,0x65,0x4a,0x75,0x10,0x72,0x1f,0x75,0x73, -0x68,0x61,0x73,0x6b,0x69,0x79,0x65,0x68,0x62,0x61,0x72,0x72,0x65,0x65,0x8d,1, -0x68,0x29,0x74,0x10,0x68,0x2b,0x11,0x61,0x6c,0x2c,0x16,0x61,0x74,0x68,0x72,0x69, -0x73,0x68,0x2f,7,0x6e,0x2e,0x6e,0x2c,0x72,0x3e,0x74,0x56,0x75,0x21,0x18,0x6f, -0x6e,0x6a,0x6f,0x69,0x6e,0x69,0x6e,0x67,0x21,0x28,0x1a,0x69,0x67,0x68,0x74,0x6a, -0x6f,0x69,0x6e,0x69,0x6e,0x67,0x29,0x2a,0x19,0x72,0x61,0x6e,0x73,0x70,0x61,0x72, -0x65,0x6e,0x74,0x2b,0x63,0x23,0x64,0x40,0x6a,0x56,0x6c,0x26,0x19,0x65,0x66,0x74, -0x6a,0x6f,0x69,0x6e,0x69,0x6e,0x67,0x27,0x24,0x19,0x75,0x61,0x6c,0x6a,0x6f,0x69, -0x6e,0x69,0x6e,0x67,0x25,0x19,0x6f,0x69,0x6e,0x63,0x61,0x75,0x73,0x69,0x6e,0x67, -0x23,0,0x13,0x6e,0xc0,0xd0,0x73,0x49,0x73,0x48,0x75,0x78,0x77,0x84,0x78,0x9c, -0x7a,0x10,0x77,0x58,1,0x6a,0x75,0x73,0x13,0x70,0x61,0x63,0x65,0x59,4,0x61, -0x51,0x67,0x53,0x70,0x28,0x75,0x30,0x79,0x57,0x54,0x12,0x61,0x63,0x65,0x55,0x16, -0x72,0x72,0x6f,0x67,0x61,0x74,0x65,0x53,0x15,0x6e,0x6b,0x6e,0x6f,0x77,0x6e,0x21, -1,0x6a,0x5d,0x6f,0x17,0x72,0x64,0x6a,0x6f,0x69,0x6e,0x65,0x72,0x5d,0x10,0x78, -0x21,0x6e,0x60,0x6f,0xa2,0x41,0x70,0xa2,0x50,0x71,0xa2,0x6e,0x72,1,0x65,0x24, -0x69,0x6f,0x1e,0x67,0x69,0x6f,0x6e,0x61,0x6c,0x69,0x6e,0x64,0x69,0x63,0x61,0x74, -0x6f,0x72,0x6f,4,0x65,0x3e,0x6c,0x5b,0x6f,0x46,0x73,0x45,0x75,0x46,0x14,0x6d, -0x65,0x72,0x69,0x63,0x47,0x15,0x78,0x74,0x6c,0x69,0x6e,0x65,0x5b,0x17,0x6e,0x73, -0x74,0x61,0x72,0x74,0x65,0x72,0x45,0x10,0x70,0x48,0x1c,0x65,0x6e,0x70,0x75,0x6e, -0x63,0x74,0x75,0x61,0x74,0x69,0x6f,0x6e,0x49,1,0x6f,0x3e,0x72,0x4c,0x1a,0x65, -0x66,0x69,0x78,0x6e,0x75,0x6d,0x65,0x72,0x69,0x63,0x4d,0x4a,0x1b,0x73,0x74,0x66, -0x69,0x78,0x6e,0x75,0x6d,0x65,0x72,0x69,0x63,0x4b,0x10,0x75,0x4e,0x16,0x6f,0x74, -0x61,0x74,0x69,0x6f,0x6e,0x4f,0x68,0x7b,0x68,0x50,0x69,0x86,0x6a,0xa2,0x61,0x6c, -0xa2,0x65,0x6d,0x1c,0x61,0x6e,0x64,0x61,0x74,0x6f,0x72,0x79,0x62,0x72,0x65,0x61, -0x6b,0x2d,4,0x32,0x5f,0x33,0x61,0x65,0x34,0x6c,0x6d,0x79,0x3a,0x13,0x70,0x68, -0x65,0x6e,0x3b,0x19,0x62,0x72,0x65,0x77,0x6c,0x65,0x74,0x74,0x65,0x72,0x6d,2, -0x64,0x28,0x6e,0x3c,0x73,0x41,0x3c,0x18,0x65,0x6f,0x67,0x72,0x61,0x70,0x68,0x69, -0x63,0x3d,0x3e,1,0x66,0x3e,0x73,0x11,0x65,0x70,1,0x61,0x22,0x65,0x14,0x72, -0x61,0x62,0x6c,0x65,0x3f,0x18,0x69,0x78,0x6e,0x75,0x6d,0x65,0x72,0x69,0x63,0x41, -2,0x6c,0x63,0x74,0x65,0x76,0x67,1,0x66,0x43,0x69,0x15,0x6e,0x65,0x66,0x65, -0x65,0x64,0x43,0x61,0x40,0x62,0x70,0x63,0xa2,0x55,0x65,0xa2,0xdb,0x67,0x10,0x6c, -0x38,0x11,0x75,0x65,0x39,2,0x69,0x23,0x6c,0x34,0x6d,0x16,0x62,0x69,0x67,0x75, -0x6f,0x75,0x73,0x23,0x24,0x17,0x70,0x68,0x61,0x62,0x65,0x74,0x69,0x63,0x25,4, -0x32,0x27,0x61,0x29,0x62,0x2b,0x6b,0x2d,0x72,0x12,0x65,0x61,0x6b,2,0x61,0x36, -0x62,0x3e,0x73,0x15,0x79,0x6d,0x62,0x6f,0x6c,0x73,0x57,0x13,0x66,0x74,0x65,0x72, -0x29,1,0x65,0x2a,0x6f,0x11,0x74,0x68,0x27,0x13,0x66,0x6f,0x72,0x65,0x2b,7, -0x6d,0x51,0x6d,0x33,0x6f,0x28,0x70,0x69,0x72,0x35,1,0x6d,0x76,0x6e,1,0x64, -0x3c,0x74,0x1a,0x69,0x6e,0x67,0x65,0x6e,0x74,0x62,0x72,0x65,0x61,0x6b,0x2f,0x15, -0x69,0x74,0x69,0x6f,0x6e,0x61,0x1f,0x6c,0x6a,0x61,0x70,0x61,0x6e,0x65,0x73,0x65, -0x73,0x74,0x61,0x72,0x74,0x65,0x72,0x6b,1,0x62,0x3a,0x70,0x19,0x6c,0x65,0x78, -0x63,0x6f,0x6e,0x74,0x65,0x78,0x74,0x51,0x18,0x69,0x6e,0x69,0x6e,0x67,0x6d,0x61, -0x72,0x6b,0x33,0x61,0x6a,0x62,0x2f,0x6a,0x6b,0x6c,0x30,0x13,0x6f,0x73,0x65,0x70, -1,0x61,0x38,0x75,0x18,0x6e,0x63,0x74,0x75,0x61,0x74,0x69,0x6f,0x6e,0x31,0x18, -0x72,0x65,0x6e,0x74,0x68,0x65,0x73,0x69,0x73,0x69,0x1b,0x72,0x72,0x69,0x61,0x67, -0x65,0x72,0x65,0x74,0x75,0x72,0x6e,0x35,2,0x62,0x3e,0x6d,0x46,0x78,0x36,0x18, -0x63,0x6c,0x61,0x6d,0x61,0x74,0x69,0x6f,0x6e,0x37,0x70,0x12,0x61,0x73,0x65,0x71, -0x72,0x16,0x6f,0x64,0x69,0x66,0x69,0x65,0x72,0x73,1,0x64,0x42,0x6e,1,0x6f, -0x32,0x75,0x26,0x14,0x6d,0x65,0x72,0x69,0x63,0x27,0x11,0x6e,0x65,0x21,1,0x65, -0x2e,0x69,0x24,0x12,0x67,0x69,0x74,0x25,0x22,0x14,0x63,0x69,0x6d,0x61,0x6c,0x23, -0,0x18,0x6e,0xc3,0xc4,0x74,0xc1,0x51,0x77,0x7a,0x77,0xa2,0x4c,0x78,0xa2,0x60, -0x79,0xa2,0x6a,0x7a,6,0x73,0x1e,0x73,0x34,0x78,0x42,0x79,0x48,0x7a,0x11,0x7a, -0x7a,0xa3,0x67,0x10,0x79,1,0x65,0xa3,0xae,0x6d,0xa3,0x81,0x11,0x78,0x78,0xa3, -0x66,0x11,0x79,0x79,0x21,0x61,0x30,0x69,0x58,0x6d,0x11,0x74,0x68,0xa3,0x80,0x10, -0x6e,1,0x61,0x26,0x62,0xa3,0xb1,0x1a,0x62,0x61,0x7a,0x61,0x72,0x73,0x71,0x75, -0x61,0x72,0x65,0xa3,0xb1,0x11,0x6e,0x68,0x23,1,0x61,0x2c,0x6f,0x11,0x6c,0x65, -0xa3,0x9b,0x11,0x72,0x61,0xa2,0x92,0x15,0x6e,0x67,0x63,0x69,0x74,0x69,0xa3,0x92, -1,0x70,0x2c,0x73,0x11,0x75,0x78,0xa3,0x65,0x11,0x65,0x6f,0x9b,0x10,0x69,0x72, -0x11,0x69,0x69,0x73,0x74,0x4a,0x75,0xa2,0xba,0x76,1,0x61,0x2c,0x69,0x11,0x73, -0x70,0xa3,0x64,0x10,0x69,0xa2,0x63,0x10,0x69,0xa3,0x63,5,0x67,0x36,0x67,0x68, -0x68,0x6c,0x69,2,0x62,0x3a,0x66,0x4a,0x72,0x10,0x68,0xa2,0x9e,0x12,0x75,0x74, -0x61,0xa3,0x9e,1,0x65,0x24,0x74,0x6f,0x12,0x74,0x61,0x6e,0x6f,0x14,0x69,0x6e, -0x61,0x67,0x68,0x99,0x11,0x6c,0x67,0x75,0x10,0x61,1,0x61,0x24,0x69,0x6d,0x6a, -0x11,0x6e,0x61,0x6b,0x61,0x30,0x65,0xa2,0x5b,0x66,0x11,0x6e,0x67,0x99,6,0x6c, -0x21,0x6c,0x32,0x6d,0x38,0x6e,0x44,0x76,0x10,0x74,0xa3,0x7f,1,0x65,0x89,0x75, -0x97,1,0x69,0x24,0x6c,0x67,0x10,0x6c,0x67,0x10,0x67,0xa2,0x9a,0x11,0x75,0x74, -0xa3,0x9a,0x67,0x36,0x69,0x52,0x6b,0x10,0x72,0xa2,0x99,0x10,0x69,0xa3,0x99,1, -0x61,0x30,0x62,0x7a,0x13,0x61,0x6e,0x77,0x61,0x7b,0x12,0x6c,0x6f,0x67,0x75,2, -0x6c,0x32,0x74,0x34,0x76,0x12,0x69,0x65,0x74,0xa3,0x7f,0x10,0x65,0x89,0x12,0x68, -0x61,0x6d,0xa3,0x6a,1,0x6c,0x2a,0x6e,0x10,0x67,0xa3,0x62,0x10,0x75,0x68,0x11, -0x67,0x75,0x69,1,0x67,0x32,0x6e,0x14,0x6b,0x6e,0x6f,0x77,0x6e,0xa3,0x67,0x11, -0x61,0x72,0x8a,0x13,0x69,0x74,0x69,0x63,0x8b,0x71,0xc0,0xfc,0x71,0xa2,0xce,0x72, -0xa2,0xd3,0x73,6,0x69,0x7a,0x69,0x72,0x6f,0xa2,0x4c,0x75,0xa2,0x65,0x79,1, -0x6c,0x46,0x72,4,0x63,0x65,0x65,0xa3,0x5f,0x69,0x2c,0x6a,0xa3,0x60,0x6e,0xa3, -0x61,0x11,0x61,0x63,0x65,0x10,0x6f,0x94,0x16,0x74,0x69,0x6e,0x61,0x67,0x72,0x69, -0x95,2,0x64,0x3c,0x67,0x4c,0x6e,1,0x64,0xa3,0x91,0x68,0x62,0x12,0x61,0x6c, -0x61,0x63,0x10,0x64,0xa2,0xa6,0x12,0x68,0x61,0x6d,0xa3,0xa6,0x17,0x6e,0x77,0x72, -0x69,0x74,0x69,0x6e,0x67,0xa3,0x70,1,0x72,0x36,0x79,0x10,0x6f,0xa2,0xb0,0x12, -0x6d,0x62,0x6f,0xa3,0xb0,0x10,0x61,0xa2,0x98,0x16,0x73,0x6f,0x6d,0x70,0x65,0x6e, -0x67,0xa3,0x98,0x11,0x6e,0x64,0xa2,0x71,0x14,0x61,0x6e,0x65,0x73,0x65,0xa3,0x71, -0x61,0x5c,0x67,0xa2,0x43,0x68,1,0x61,0x2a,0x72,0x10,0x64,0xa3,0x97,2,0x72, -0x28,0x76,0x30,0x77,0x87,0x12,0x61,0x64,0x61,0xa3,0x97,0x12,0x69,0x61,0x6e,0x87, -2,0x6d,0x40,0x72,0x58,0x75,0x10,0x72,0xa2,0x6f,0x15,0x61,0x73,0x68,0x74,0x72, -0x61,0xa3,0x6f,1,0x61,0x26,0x72,0xa3,0x7e,0x14,0x72,0x69,0x74,0x61,0x6e,0xa3, -0x7e,1,0x61,0xa3,0x5e,0x62,0xa3,0x85,0x11,0x6e,0x77,0xa3,0x70,0x11,0x61,0x61, -1,0x63,0x2f,0x69,0x23,3,0x65,0x3e,0x6a,0x48,0x6f,0x4e,0x75,0x10,0x6e,1, -0x69,0x24,0x72,0x61,0x10,0x63,0x61,0x13,0x6a,0x61,0x6e,0x67,0xa3,0x6e,0x11,0x6e, -0x67,0xa3,0x6e,0x11,0x72,0x6f,0xa3,0x5d,0x6e,0xa2,0x83,0x6f,0xa2,0xca,0x70,5, -0x6c,0x1e,0x6c,0x44,0x72,0x4a,0x73,0x1b,0x61,0x6c,0x74,0x65,0x72,0x70,0x61,0x68, -0x6c,0x61,0x76,0x69,0xa3,0x7b,0x11,0x72,0x64,0xa3,0x5c,0x11,0x74,0x69,0xa3,0x7d, -0x61,0x7c,0x65,0xa2,0x54,0x68,3,0x61,0x3e,0x6c,0x4e,0x6e,0x5e,0x6f,0x16,0x65, -0x6e,0x69,0x63,0x69,0x61,0x6e,0xa3,0x5b,0x10,0x67,0xa2,0x5a,0x12,0x73,0x70,0x61, -0xa3,0x5a,2,0x69,0xa3,0x7a,0x70,0xa3,0x7b,0x76,0xa3,0x7c,0x10,0x78,0xa3,0x5b, -2,0x68,0x3e,0x6c,0x50,0x75,0x10,0x63,0xa2,0xa5,0x14,0x69,0x6e,0x68,0x61,0x75, -0xa3,0xa5,0x17,0x61,0x77,0x68,0x68,0x6d,0x6f,0x6e,0x67,0xa3,0x4b,0x10,0x6d,0xa2, -0x90,0x14,0x79,0x72,0x65,0x6e,0x65,0xa3,0x90,0x11,0x72,0x6d,0xa3,0x59,5,0x6b, -0x1e,0x6b,0x32,0x73,0x4a,0x75,0x12,0x73,0x68,0x75,0xa3,0x96,1,0x67,0x2e,0x6f, -0xa2,0x57,0x10,0x6f,0xa3,0x57,0x10,0x62,0xa3,0x84,0x11,0x68,0x75,0xa3,0x96,0x61, -0x42,0x62,0x60,0x65,0x10,0x77,1,0x61,0xa3,0xaa,0x74,0x14,0x61,0x69,0x6c,0x75, -0x65,0x97,1,0x62,0x2a,0x72,0x10,0x62,0xa3,0x8e,0x15,0x61,0x74,0x61,0x65,0x61, -0x6e,0xa3,0x8f,0x11,0x61,0x74,0xa3,0x8f,3,0x67,0x5a,0x6c,0x6c,0x72,0xa2,0x88, -0x73,2,0x61,0x36,0x67,0x3c,0x6d,0x10,0x61,0x84,0x12,0x6e,0x79,0x61,0x85,0x11, -0x67,0x65,0xa3,0xab,0x10,0x65,0xa3,0xab,1,0x61,0x2a,0x68,0x11,0x61,0x6d,0x5b, -0x10,0x6d,0x5b,1,0x63,0xa2,0x55,0x64,5,0x70,0x2c,0x70,0x36,0x73,0x54,0x74, -0x14,0x75,0x72,0x6b,0x69,0x63,0xa3,0x58,0x11,0x65,0x72,1,0x6d,0x2c,0x73,0x12, -0x69,0x61,0x6e,0x9b,0x11,0x69,0x63,0xa3,0x59,0x1a,0x6f,0x75,0x74,0x68,0x61,0x72, -0x61,0x62,0x69,0x61,0x6e,0xa3,0x85,0x68,0x42,0x69,0x54,0x6e,0x1a,0x6f,0x72,0x74, -0x68,0x61,0x72,0x61,0x62,0x69,0x61,0x6e,0xa3,0x8e,0x17,0x75,0x6e,0x67,0x61,0x72, -0x69,0x61,0x6e,0xa3,0x4c,0x14,0x74,0x61,0x6c,0x69,0x63,0x5d,1,0x68,0x26,0x6b, -0xa3,0x6d,0x12,0x69,0x6b,0x69,0xa3,0x6d,2,0x69,0x2c,0x6b,0x30,0x79,0x10,0x61, -0x5f,0x11,0x79,0x61,0x5f,0x10,0x68,0xa3,0x58,0x68,0xc2,0xc2,0x6b,0xc1,0xeb,0x6b, -0xa2,0xf8,0x6c,0xa4,0x79,0x6d,8,0x6f,0x46,0x6f,0x48,0x72,0x74,0x74,0x80,0x75, -0x86,0x79,1,0x61,0x28,0x6d,0x10,0x72,0x59,0x13,0x6e,0x6d,0x61,0x72,0x59,2, -0x64,0x2e,0x6e,0x32,0x6f,0x10,0x6e,0xa3,0x72,0x10,0x69,0xa3,0xa3,0x10,0x67,0x56, -0x14,0x6f,0x6c,0x69,0x61,0x6e,0x57,0x10,0x6f,0xa2,0x95,0x10,0x6f,0xa3,0x95,0x11, -0x65,0x69,0xa3,0x73,0x11,0x6c,0x74,0xa2,0xa4,0x12,0x61,0x6e,0x69,0xa3,0xa4,0x61, -0x36,0x65,0xa2,0x5b,0x69,0xa2,0x9e,0x6c,0x11,0x79,0x6d,0x55,5,0x72,0x1f,0x72, -0x2e,0x73,0x3e,0x79,0x10,0x61,0xa3,0x55,0x10,0x63,0xa2,0xa9,0x12,0x68,0x65,0x6e, -0xa3,0xa9,0x18,0x61,0x72,0x61,0x6d,0x67,0x6f,0x6e,0x64,0x69,0xa3,0xaf,0x68,0x54, -0x6c,0x6a,0x6e,1,0x64,0x38,0x69,0xa2,0x79,0x15,0x63,0x68,0x61,0x65,0x61,0x6e, -0xa3,0x79,0xa2,0x54,0x12,0x61,0x69,0x63,0xa3,0x54,1,0x61,0x26,0x6a,0xa3,0xa0, -0x13,0x6a,0x61,0x6e,0x69,0xa3,0xa0,0x15,0x61,0x79,0x61,0x6c,0x61,0x6d,0x55,2, -0x65,0x72,0x6e,0x84,0x72,1,0x63,0xa3,0x8d,0x6f,0xa2,0x56,0x13,0x69,0x74,0x69, +0x90,0x62,0xa2,0xbe,0x63,0xa4,0x30,0x64,0xa4,0xfd,0x65,5,0x6d,0x63,0x6d,0x6e, +0x70,0xa2,0x59,0x78,0x10,0x74,0x30,1,0x65,0x2c,0x70,0x12,0x69,0x63,0x74,0xa1, +0x12,0x6e,0x64,0x65,1,0x64,0x24,0x72,0x31,0x1b,0x70,0x69,0x63,0x74,0x6f,0x67, +0x72,0x61,0x70,0x68,0x69,0x63,0xa1,0x10,0x6f,1,0x64,0x97,0x6a,0x10,0x69,0x92, +2,0x63,0x40,0x6d,0x50,0x70,0x1a,0x72,0x65,0x73,0x65,0x6e,0x74,0x61,0x74,0x69, +0x6f,0x6e,0x95,0x17,0x6f,0x6d,0x70,0x6f,0x6e,0x65,0x6e,0x74,0x9b,0x16,0x6f,0x64, +0x69,0x66,0x69,0x65,0x72,0x96,0x13,0x62,0x61,0x73,0x65,0x99,0x12,0x72,0x65,0x73, +0x95,0x61,0x30,0x62,0x4e,0x63,0x12,0x6f,0x6d,0x70,0x9b,0xc2,4,0x1b,0x73,0x74, +0x61,0x73,0x69,0x61,0x6e,0x77,0x69,0x64,0x74,0x68,0xc3,4,0x12,0x61,0x73,0x65, +0x99,3,0x67,0x44,0x68,0x4a,0x6c,0x4e,0x73,0x1a,0x63,0x69,0x69,0x68,0x65,0x78, +0x64,0x69,0x67,0x69,0x74,0x23,0x10,0x65,0xd9,0x40,0,0x11,0x65,0x78,0x23,1, +0x6e,0x38,0x70,0x11,0x68,0x61,0x20,0x14,0x62,0x65,0x74,0x69,0x63,0x21,0x11,0x75, +0x6d,0x79,4,0x63,0xc3,0,0x69,0x3e,0x6c,0xa2,0x57,0x6d,0xa2,0x64,0x70,1, +0x62,0xd9,0x40,0xd,0x74,0xc3,0x15,0x11,0x64,0x69,2,0x63,0x54,0x6d,0x74,0x70, +0x1b,0x61,0x69,0x72,0x65,0x64,0x62,0x72,0x61,0x63,0x6b,0x65,0x74,0xd8,0x40,0xd, +0x13,0x74,0x79,0x70,0x65,0xc3,0x15,0x24,1,0x6c,0x30,0x6f,0x14,0x6e,0x74,0x72, +0x6f,0x6c,0x25,0x12,0x61,0x73,0x73,0xc3,0,0x26,0x14,0x69,0x72,0x72,0x6f,0x72, +1,0x65,0x38,0x69,0x16,0x6e,0x67,0x67,0x6c,0x79,0x70,0x68,0xd9,0x40,1,0x10, +0x64,0x27,2,0x61,0x32,0x6b,0xc3,1,0x6f,0x11,0x63,0x6b,0xc3,1,0x11,0x6e, +0x6b,0x7b,0x10,0x67,0xd9,0x40,1,6,0x68,0x7c,0x68,0x54,0x69,0x85,0x6f,0xa2, +0x6f,0x77,4,0x63,0x30,0x6b,0x36,0x6c,0x87,0x74,0x8b,0x75,0x89,1,0x66,0x8d, +0x6d,0x8f,0x11,0x63,0x66,0x91,0x18,0x61,0x6e,0x67,0x65,0x73,0x77,0x68,0x65,0x6e, +4,0x63,0x44,0x6c,0x6c,0x6e,0x7e,0x74,0x98,0x75,0x18,0x70,0x70,0x65,0x72,0x63, +0x61,0x73,0x65,0x64,0x89,0x12,0x61,0x73,0x65,1,0x66,0x30,0x6d,0x14,0x61,0x70, +0x70,0x65,0x64,0x8f,0x14,0x6f,0x6c,0x64,0x65,0x64,0x8d,0x18,0x6f,0x77,0x65,0x72, +0x63,0x61,0x73,0x65,0x64,0x87,0x1c,0x66,0x6b,0x63,0x63,0x61,0x73,0x65,0x66,0x6f, +0x6c,0x64,0x65,0x64,0x91,0x18,0x69,0x74,0x6c,0x65,0x63,0x61,0x73,0x65,0x64,0x8b, +0x13,0x6d,0x70,0x65,0x78,0x33,0x61,0x2e,0x63,0xa2,0x48,0x66,0xd9,0x40,2,1, +0x6e,0x72,0x73,0x10,0x65,3,0x64,0x83,0x66,0x3a,0x69,0x4a,0x73,0x17,0x65,0x6e, +0x73,0x69,0x74,0x69,0x76,0x65,0x65,0x15,0x6f,0x6c,0x64,0x69,0x6e,0x67,0xd9,0x40, +2,0x17,0x67,0x6e,0x6f,0x72,0x61,0x62,0x6c,0x65,0x85,0x13,0x6f,0x6e,0x69,0x63, +0x1f,0x61,0x6c,0x63,0x6f,0x6d,0x62,0x69,0x6e,0x69,0x6e,0x67,0x63,0x6c,0x61,0x73, +0x73,0xc3,2,0x10,0x63,0xc3,2,3,0x61,0x30,0x65,0x34,0x69,0xa2,0x41,0x74, +0xc3,3,0x11,0x73,0x68,0x29,2,0x63,0x3a,0x66,0x58,0x70,0x2c,0x16,0x72,0x65, +0x63,0x61,0x74,0x65,0x64,0x2d,0x1d,0x6f,0x6d,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f, +0x6e,0x74,0x79,0x70,0x65,0xc3,3,0x15,0x61,0x75,0x6c,0x74,0x69,0x67,0x1f,0x6e, +0x6f,0x72,0x61,0x62,0x6c,0x65,0x63,0x6f,0x64,0x65,0x70,0x6f,0x69,0x6e,0x74,0x2b, +0x2a,0x10,0x61,0x2e,0x15,0x63,0x72,0x69,0x74,0x69,0x63,0x2f,3,0x66,0x34,0x6e, +0x3e,0x74,0x42,0x79,0x22,0x11,0x65,0x73,0x23,0x20,0x13,0x61,0x6c,0x73,0x65,0x21, +0x20,0x10,0x6f,0x21,0x22,0x12,0x72,0x75,0x65,0x23,0xa,0x6b,0x5b,0x6f,0x23,0x6f, +0x3c,0x72,0x4c,0x76,1,0x69,0x24,0x72,0x33,0x13,0x72,0x61,0x6d,0x61,0x33,0x10, +0x76,0x22,0x14,0x65,0x72,0x6c,0x61,0x79,0x23,0xa2,0xe2,0x13,0x69,0x67,0x68,0x74, +0xa3,0xe2,0x6b,0x58,0x6c,0x74,0x6e,3,0x6b,0x2f,0x6f,0x30,0x72,0x21,0x75,0x12, +0x6b,0x74,0x61,0x2f,0x19,0x74,0x72,0x65,0x6f,0x72,0x64,0x65,0x72,0x65,0x64,0x21, +1,0x61,0x24,0x76,0x31,0x18,0x6e,0x61,0x76,0x6f,0x69,0x63,0x69,0x6e,0x67,0x31, +0xa2,0xe0,0x12,0x65,0x66,0x74,0xa3,0xe0,0x61,0x5c,0x62,0xa2,0x77,0x63,0xa2,0x96, +0x64,0xa4,0xa,0x69,1,0x6f,0x26,0x73,0xa3,0xf0,0x1a,0x74,0x61,0x73,0x75,0x62, +0x73,0x63,0x72,0x69,0x70,0x74,0xa3,0xf0,0xa2,0xe6,3,0x62,0xa0,0x6c,0xa3,0xe4, +0x72,0xa3,0xe8,0x74,2,0x61,0x74,0x62,0x7c,0x74,0x14,0x61,0x63,0x68,0x65,0x64, +1,0x61,0x3e,0x62,0x13,0x65,0x6c,0x6f,0x77,0xa2,0xca,0x13,0x6c,0x65,0x66,0x74, +0xa3,0xc8,0x13,0x62,0x6f,0x76,0x65,0xa2,0xd6,0x14,0x72,0x69,0x67,0x68,0x74,0xa3, +0xd8,0xa2,0xd6,0x10,0x72,0xa3,0xd8,0xa2,0xca,0x10,0x6c,0xa3,0xc8,0x12,0x6f,0x76, +0x65,0xa2,0xe6,1,0x6c,0x30,0x72,0x13,0x69,0x67,0x68,0x74,0xa3,0xe8,0x12,0x65, +0x66,0x74,0xa3,0xe4,0xa2,0xdc,2,0x65,0x2c,0x6c,0xa3,0xda,0x72,0xa3,0xde,0x12, +0x6c,0x6f,0x77,0xa2,0xdc,1,0x6c,0x30,0x72,0x13,0x69,0x67,0x68,0x74,0xa3,0xde, +0x12,0x65,0x66,0x74,0xa3,0xda,0x11,0x63,0x63,4,0x31,0x3c,0x32,0xa2,0x42,0x33, +0xa2,0x56,0x38,0xa2,0x64,0x39,0x10,0x31,0xa3,0x5b,9,0x35,0xa,0x35,0x3f,0x36, +0x41,0x37,0x43,0x38,0x45,0x39,0x47,0x30,0x30,0x31,0x3c,0x32,0x42,0x33,0x4e,0x34, +0x3d,0x34,1,0x33,0xa3,0x67,0x37,0xa3,0x6b,0x36,0x10,0x38,0xa3,0x76,0x38,1, +0x32,0xa3,0x7a,0x39,0xa3,0x81,0x3a,2,0x30,0xa3,0x82,0x32,0xa3,0x84,0x33,0xa3, +0x85,9,0x35,0xa,0x35,0x53,0x36,0x55,0x37,0x57,0x38,0x59,0x39,0x5b,0x30,0x49, +0x31,0x4b,0x32,0x4d,0x33,0x4f,0x34,0x51,6,0x33,8,0x33,0x63,0x34,0x65,0x35, +0x67,0x36,0x69,0x30,0x5d,0x31,0x5f,0x32,0x61,0x10,0x34,0xa3,0x54,2,0x61,0xa3, +0xea,0x62,0xa3,0xe9,0x6f,0x13,0x75,0x62,0x6c,0x65,1,0x61,0x30,0x62,0x13,0x65, +0x6c,0x6f,0x77,0xa3,0xe9,0x13,0x62,0x6f,0x76,0x65,0xa3,0xea,0xb,0x6e,0xc0,0xca, +0x72,0x5f,0x72,0x46,0x73,0xa2,0x48,0x77,1,0x68,0x24,0x73,0x33,0x17,0x69,0x74, +0x65,0x73,0x70,0x61,0x63,0x65,0x33,0x22,1,0x69,0x30,0x6c,2,0x65,0x3d,0x69, +0x4b,0x6f,0x3f,0x18,0x67,0x68,0x74,0x74,0x6f,0x6c,0x65,0x66,0x74,0x22,2,0x65, +0x38,0x69,0x48,0x6f,0x16,0x76,0x65,0x72,0x72,0x69,0x64,0x65,0x3f,0x17,0x6d,0x62, +0x65,0x64,0x64,0x69,0x6e,0x67,0x3d,0x15,0x73,0x6f,0x6c,0x61,0x74,0x65,0x4b,0x30, +0x1e,0x65,0x67,0x6d,0x65,0x6e,0x74,0x73,0x65,0x70,0x61,0x72,0x61,0x74,0x6f,0x72, +0x31,0x6e,0xa2,0x41,0x6f,0xa2,0x53,0x70,2,0x61,0x66,0x64,0x86,0x6f,0x1b,0x70, +0x64,0x69,0x72,0x65,0x63,0x74,0x69,0x6f,0x6e,0x61,0x6c,1,0x66,0x32,0x69,0x15, +0x73,0x6f,0x6c,0x61,0x74,0x65,0x4d,0x14,0x6f,0x72,0x6d,0x61,0x74,0x41,0x1f,0x72, +0x61,0x67,0x72,0x61,0x70,0x68,0x73,0x65,0x70,0x61,0x72,0x61,0x74,0x6f,0x72,0x2f, +1,0x66,0x41,0x69,0x4d,1,0x6f,0x28,0x73,0x10,0x6d,0x43,0x1b,0x6e,0x73,0x70, +0x61,0x63,0x69,0x6e,0x67,0x6d,0x61,0x72,0x6b,0x43,1,0x6e,0x35,0x74,0x19,0x68, +0x65,0x72,0x6e,0x65,0x75,0x74,0x72,0x61,0x6c,0x35,0x65,0x88,0x65,0x98,0x66,0xa2, +0x6a,0x6c,0x20,1,0x65,0x30,0x72,2,0x65,0x37,0x69,0x49,0x6f,0x39,0x18,0x66, +0x74,0x74,0x6f,0x72,0x69,0x67,0x68,0x74,0x20,2,0x65,0x38,0x69,0x48,0x6f,0x16, +0x76,0x65,0x72,0x72,0x69,0x64,0x65,0x39,0x17,0x6d,0x62,0x65,0x64,0x64,0x69,0x6e, +0x67,0x37,0x15,0x73,0x6f,0x6c,0x61,0x74,0x65,0x49,3,0x6e,0x25,0x73,0x27,0x74, +0x29,0x75,0x15,0x72,0x6f,0x70,0x65,0x61,0x6e,2,0x6e,0x3c,0x73,0x46,0x74,0x18, +0x65,0x72,0x6d,0x69,0x6e,0x61,0x74,0x6f,0x72,0x29,0x14,0x75,0x6d,0x62,0x65,0x72, +0x25,0x17,0x65,0x70,0x61,0x72,0x61,0x74,0x6f,0x72,0x27,1,0x69,0x28,0x73,0x10, +0x69,0x47,0x1f,0x72,0x73,0x74,0x73,0x74,0x72,0x6f,0x6e,0x67,0x69,0x73,0x6f,0x6c, +0x61,0x74,0x65,0x47,0x61,0x4e,0x62,0x84,0x63,1,0x6f,0x24,0x73,0x2d,0x1c,0x6d, +0x6d,0x6f,0x6e,0x73,0x65,0x70,0x61,0x72,0x61,0x74,0x6f,0x72,0x2d,2,0x6c,0x3b, +0x6e,0x2b,0x72,0x13,0x61,0x62,0x69,0x63,1,0x6c,0x30,0x6e,0x14,0x75,0x6d,0x62, +0x65,0x72,0x2b,0x14,0x65,0x74,0x74,0x65,0x72,0x3b,0x2e,1,0x6e,0x45,0x6f,0x1c, +0x75,0x6e,0x64,0x61,0x72,0x79,0x6e,0x65,0x75,0x74,0x72,0x61,0x6c,0x45,0,0x16, +0x6d,0xc7,0xfe,0x74,0xc1,0xb8,0x77,0x57,0x77,0x48,0x79,0x5c,0x7a,0x1d,0x61,0x6e, +0x61,0x62,0x61,0x7a,0x61,0x72,0x73,0x71,0x75,0x61,0x72,0x65,0xa5,0x18,0x18,0x61, +0x72,0x61,0x6e,0x67,0x63,0x69,0x74,0x69,0xa3,0xfc,0x10,0x69,2,0x6a,0x3c,0x72, +0x68,0x73,0x17,0x79,0x6c,0x6c,0x61,0x62,0x6c,0x65,0x73,0xa3,0x48,0x12,0x69,0x6e, +0x67,0xa2,0x74,0x1e,0x68,0x65,0x78,0x61,0x67,0x72,0x61,0x6d,0x73,0x79,0x6d,0x62, +0x6f,0x6c,0x73,0xa3,0x74,0x16,0x61,0x64,0x69,0x63,0x61,0x6c,0x73,0xa3,0x49,0x74, +0xa2,0x59,0x75,0xa4,0x12,0x76,2,0x61,0x36,0x65,0x7a,0x73,0xa2,0x6c,0x12,0x73, +0x75,0x70,0xa3,0x7d,1,0x69,0xa3,0x9f,0x72,0x1e,0x69,0x61,0x74,0x69,0x6f,0x6e, +0x73,0x65,0x6c,0x65,0x63,0x74,0x6f,0x72,0x73,0xa2,0x6c,0x19,0x73,0x75,0x70,0x70, +0x6c,0x65,0x6d,0x65,0x6e,0x74,0xa3,0x7d,1,0x64,0x3c,0x72,0x19,0x74,0x69,0x63, +0x61,0x6c,0x66,0x6f,0x72,0x6d,0x73,0xa3,0x91,0x14,0x69,0x63,0x65,0x78,0x74,0xa2, +0xaf,0x16,0x65,0x6e,0x73,0x69,0x6f,0x6e,0x73,0xa3,0xaf,4,0x61,0x68,0x65,0xa2, +0x8a,0x68,0xa2,0x8d,0x69,0xa2,0x95,0x72,0x1c,0x61,0x6e,0x73,0x70,0x6f,0x72,0x74, +0x61,0x6e,0x64,0x6d,0x61,0x70,0xa2,0xcf,0x16,0x73,0x79,0x6d,0x62,0x6f,0x6c,0x73, +0xa3,0xcf,4,0x67,0x58,0x69,0x7e,0x6b,0xa2,0x58,0x6d,0xa2,0x5a,0x6e,0x12,0x67, +0x75,0x74,0xa4,0x10,0x19,0x63,0x6f,0x6d,0x70,0x6f,0x6e,0x65,0x6e,0x74,0x73,0xa5, +0x11,2,0x61,0x2a,0x62,0x32,0x73,0xa3,0x60,0x12,0x6c,0x6f,0x67,0xa3,0x62,0x13, +0x61,0x6e,0x77,0x61,0xa3,0x65,3,0x6c,0x52,0x74,0x56,0x76,0x5e,0x78,0x16,0x75, +0x61,0x6e,0x6a,0x69,0x6e,0x67,0xa2,0x7c,0x16,0x73,0x79,0x6d,0x62,0x6f,0x6c,0x73, +0xa3,0x7c,0x10,0x65,0xa3,0x70,0x12,0x68,0x61,0x6d,0xa3,0xae,0x12,0x69,0x65,0x74, +0xa3,0xb7,0x11,0x72,0x69,0xa3,0xdc,0x11,0x69,0x6c,0x49,0x13,0x6c,0x75,0x67,0x75, +0x4b,0x10,0x61,1,0x61,0x24,0x69,0x53,0x11,0x6e,0x61,0x3d,2,0x62,0x34,0x66, +0x3c,0x72,0x13,0x68,0x75,0x74,0x61,0xa3,0xfb,0x13,0x65,0x74,0x61,0x6e,0x57,0x14, +0x69,0x6e,0x61,0x67,0x68,0xa3,0x90,2,0x63,0x82,0x67,0x92,0x6e,0x1f,0x69,0x66, +0x69,0x65,0x64,0x63,0x61,0x6e,0x61,0x64,0x69,0x61,0x6e,0x61,0x62,0x6f,0x1f,0x72, +0x69,0x67,0x69,0x6e,0x61,0x6c,0x73,0x79,0x6c,0x6c,0x61,0x62,0x69,0x63,0x73,0x62, +0x17,0x65,0x78,0x74,0x65,0x6e,0x64,0x65,0x64,0xa3,0xad,0x11,0x61,0x73,0x62,0x12, +0x65,0x78,0x74,0xa3,0xad,0x15,0x61,0x72,0x69,0x74,0x69,0x63,0xa3,0x78,0x70,0xc2, +0xf5,0x70,0xa6,0xb,0x72,0xa6,0xc7,0x73,7,0x6f,0xc1,0x7f,0x6f,0x76,0x70,0xa2, +0x47,0x75,0xa2,0x66,0x79,1,0x6c,0x4c,0x72,0x12,0x69,0x61,0x63,0x3a,0x12,0x73, +0x75,0x70,0xa4,0x17,0x16,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0xa5,0x17,0x17,0x6f, +0x74,0x69,0x6e,0x61,0x67,0x72,0x69,0xa3,0x8f,2,0x67,0x34,0x72,0x3e,0x79,0x13, +0x6f,0x6d,0x62,0x6f,0xa5,0x16,0x13,0x64,0x69,0x61,0x6e,0xa5,0x23,0x17,0x61,0x73, +0x6f,0x6d,0x70,0x65,0x6e,0x67,0xa3,0xda,1,0x61,0x32,0x65,0x14,0x63,0x69,0x61, +0x6c,0x73,0xa3,0x56,0x12,0x63,0x69,0x6e,0x1f,0x67,0x6d,0x6f,0x64,0x69,0x66,0x69, +0x65,0x72,0x6c,0x65,0x74,0x74,0x65,0x72,0x73,0x2d,2,0x6e,0x48,0x70,0x76,0x74, +0x1d,0x74,0x6f,0x6e,0x73,0x69,0x67,0x6e,0x77,0x72,0x69,0x74,0x69,0x6e,0x67,0xa5, +6,0x15,0x64,0x61,0x6e,0x65,0x73,0x65,0xa2,0x9b,0x12,0x73,0x75,0x70,0xa2,0xdb, +0x16,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0xa3,0xdb,4,0x61,0xa2,0xa8,0x65,0x5c, +0x6d,0x9e,0x70,0xa2,0x4b,0x73,0x13,0x79,0x6d,0x62,0x6f,0x1f,0x6c,0x73,0x61,0x6e, +0x64,0x70,0x69,0x63,0x74,0x6f,0x67,0x72,0x61,0x70,0x68,0x73,0xa5,5,0x10,0x72, +1,0x61,0x4e,0x73,0x12,0x63,0x72,0x69,0x1f,0x70,0x74,0x73,0x61,0x6e,0x64,0x73, +0x75,0x62,0x73,0x63,0x72,0x69,0x70,0x74,0x73,0x73,0x14,0x6e,0x64,0x73,0x75,0x62, +0x73,0x1b,0x61,0x74,0x68,0x6f,0x70,0x65,0x72,0x61,0x74,0x6f,0x72,0x73,0xa3,0x6a, +1,0x6c,0x40,0x75,1,0x61,0x6e,0x6e,0x17,0x63,0x74,0x75,0x61,0x74,0x69,0x6f, +0x6e,0xa3,0x8e,0x15,0x65,0x6d,0x65,0x6e,0x74,0x61,1,0x6c,0x50,0x72,0x1e,0x79, +0x70,0x72,0x69,0x76,0x61,0x74,0x65,0x75,0x73,0x65,0x61,0x72,0x65,0x61,1,0x61, +0xa3,0x6d,0x62,0xa3,0x6e,3,0x61,0x5c,0x6d,0x78,0x70,0xa2,0x41,0x73,0x13,0x79, +0x6d,0x62,0x6f,0x1f,0x6c,0x73,0x61,0x6e,0x64,0x70,0x69,0x63,0x74,0x6f,0x67,0x72, +0x61,0x70,0x68,0x73,0xa5,5,0x14,0x72,0x72,0x6f,0x77,0x73,2,0x61,0xa3,0x67, +0x62,0xa3,0x68,0x63,0xa3,0xfa,0x13,0x61,0x74,0x68,0x65,0x1f,0x6d,0x61,0x74,0x69, +0x63,0x61,0x6c,0x6f,0x70,0x65,0x72,0x61,0x74,0x6f,0x72,0x73,0xa3,0x6a,0x19,0x75, +0x6e,0x63,0x74,0x75,0x61,0x74,0x69,0x6f,0x6e,0xa3,0x8e,0x61,0x5a,0x68,0x84,0x69, +0xa2,0x5b,0x6d,0x16,0x61,0x6c,0x6c,0x66,0x6f,0x72,0x6d,1,0x73,0xa3,0x54,0x76, +0x16,0x61,0x72,0x69,0x61,0x6e,0x74,0x73,0xa3,0x54,1,0x6d,0x36,0x75,0x16,0x72, +0x61,0x73,0x68,0x74,0x72,0x61,0xa3,0xa1,0x15,0x61,0x72,0x69,0x74,0x61,0x6e,0xa3, +0xac,1,0x61,0x52,0x6f,0x13,0x72,0x74,0x68,0x61,0x1f,0x6e,0x64,0x66,0x6f,0x72, +0x6d,0x61,0x74,0x63,0x6f,0x6e,0x74,0x72,0x6f,0x6c,0x73,0xa3,0xf7,1,0x72,0x2e, +0x76,0x12,0x69,0x61,0x6e,0xa3,0x79,0x12,0x61,0x64,0x61,0xa3,0xd9,1,0x64,0x50, +0x6e,0x13,0x68,0x61,0x6c,0x61,0x50,0x1d,0x61,0x72,0x63,0x68,0x61,0x69,0x63,0x6e, +0x75,0x6d,0x62,0x65,0x72,0x73,0xa3,0xf9,0x13,0x64,0x68,0x61,0x6d,0xa3,0xf8,5, +0x72,0x35,0x72,0x44,0x73,0x64,0x75,1,0x61,0xa3,0x4e,0x6e,0x17,0x63,0x74,0x75, +0x61,0x74,0x69,0x6f,0x6e,0x71,0x17,0x69,0x76,0x61,0x74,0x65,0x75,0x73,0x65,0xa2, +0x4e,0x13,0x61,0x72,0x65,0x61,0xa3,0x4e,0x1b,0x61,0x6c,0x74,0x65,0x72,0x70,0x61, +0x68,0x6c,0x61,0x76,0x69,0xa3,0xf6,0x61,0x40,0x68,0x82,0x6c,0x19,0x61,0x79,0x69, +0x6e,0x67,0x63,0x61,0x72,0x64,0x73,0xa3,0xcc,2,0x68,0x38,0x6c,0x4a,0x75,0x15, +0x63,0x69,0x6e,0x68,0x61,0x75,0xa3,0xf5,0x17,0x61,0x77,0x68,0x68,0x6d,0x6f,0x6e, +0x67,0xa3,0xf3,0x15,0x6d,0x79,0x72,0x65,0x6e,0x65,0xa3,0xf4,1,0x61,0x8e,0x6f, +1,0x65,0x74,0x6e,0x16,0x65,0x74,0x69,0x63,0x65,0x78,0x74,0xa2,0x72,1,0x65, +0x2c,0x73,0x11,0x75,0x70,0xa3,0x8d,0x15,0x6e,0x73,0x69,0x6f,0x6e,0x73,0xa2,0x72, +0x19,0x73,0x75,0x70,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0xa3,0x8d,0x15,0x6e,0x69, +0x63,0x69,0x61,0x6e,0xa3,0x97,1,0x67,0x3e,0x69,0x13,0x73,0x74,0x6f,0x73,0xa2, +0xa6,0x13,0x64,0x69,0x73,0x63,0xa3,0xa6,0x12,0x73,0x70,0x61,0xa3,0x96,1,0x65, +0x5c,0x75,1,0x6d,0x2a,0x6e,0x11,0x69,0x63,0x67,0x10,0x69,0xa2,0xc0,0x1d,0x6e, +0x75,0x6d,0x65,0x72,0x61,0x6c,0x73,0x79,0x6d,0x62,0x6f,0x6c,0x73,0xa3,0xc0,0x13, +0x6a,0x61,0x6e,0x67,0xa3,0xa3,0x6d,0xa2,0xce,0x6e,0xa8,1,0x6f,5,0x70,0x4b, +0x70,0x46,0x72,0x7a,0x73,1,0x61,0x30,0x6d,0x13,0x61,0x6e,0x79,0x61,0xa3,0x7a, +0x11,0x67,0x65,0xa5,0xf,0x18,0x74,0x69,0x63,0x61,0x6c,0x63,0x68,0x61,0x72,0x1f, +0x61,0x63,0x74,0x65,0x72,0x72,0x65,0x63,0x6f,0x67,0x6e,0x69,0x74,0x69,0x6f,0x6e, +0x85,1,0x69,0x46,0x6e,0x1e,0x61,0x6d,0x65,0x6e,0x74,0x61,0x6c,0x64,0x69,0x6e, +0x67,0x62,0x61,0x74,0x73,0xa3,0xf2,0x11,0x79,0x61,0x47,0x63,0xa2,0x71,0x67,0xa2, +0x71,0x6c,1,0x63,0xa2,0x62,0x64,5,0x70,0x38,0x70,0x36,0x73,0x56,0x74,0x14, +0x75,0x72,0x6b,0x69,0x63,0xa3,0xbf,0x11,0x65,0x72,1,0x6d,0x2e,0x73,0x12,0x69, +0x61,0x6e,0xa3,0x8c,0x11,0x69,0x63,0xa3,0xf1,0x10,0x6f,1,0x67,0x3a,0x75,0x18, +0x74,0x68,0x61,0x72,0x61,0x62,0x69,0x61,0x6e,0xa3,0xbb,0x13,0x64,0x69,0x61,0x6e, +0xa5,0x22,0x68,0x42,0x69,0x54,0x6e,0x1a,0x6f,0x72,0x74,0x68,0x61,0x72,0x61,0x62, +0x69,0x61,0x6e,0xa3,0xf0,0x17,0x75,0x6e,0x67,0x61,0x72,0x69,0x61,0x6e,0xa5,4, +0x14,0x74,0x61,0x6c,0x69,0x63,0xa3,0x58,0x13,0x68,0x69,0x6b,0x69,0xa3,0x9d,0x10, +0x72,0x85,0x12,0x68,0x61,0x6d,0x65,6,0x6f,0x86,0x6f,0x6c,0x72,0xa2,0x61,0x75, +0xa2,0x62,0x79,0x14,0x61,0x6e,0x6d,0x61,0x72,0x58,0x12,0x65,0x78,0x74,2,0x61, +0xa3,0xb6,0x62,0xa3,0xee,0x65,0x13,0x6e,0x64,0x65,0x64,1,0x61,0xa3,0xb6,0x62, +0xa3,0xee,1,0x64,0x52,0x6e,0x15,0x67,0x6f,0x6c,0x69,0x61,0x6e,0x6a,0x12,0x73, +0x75,0x70,0xa4,0xd,0x16,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0xa5,0xd,0x10,0x69, +0xa2,0xec,0x13,0x66,0x69,0x65,0x72,1,0x6c,0x3c,0x74,0x19,0x6f,0x6e,0x65,0x6c, +0x65,0x74,0x74,0x65,0x72,0x73,0xa3,0x8a,0x15,0x65,0x74,0x74,0x65,0x72,0x73,0x2d, +0x10,0x6f,0xa3,0xed,1,0x6c,0x44,0x73,0x11,0x69,0x63,0xa2,0x5c,0x18,0x61,0x6c, +0x73,0x79,0x6d,0x62,0x6f,0x6c,0x73,0xa3,0x5c,0x13,0x74,0x61,0x6e,0x69,0xa5,3, +0x61,0xa2,0x9b,0x65,0xa4,0x4c,0x69,1,0x61,0xa2,0x8f,0x73,0x10,0x63,5,0x70, +0x18,0x70,0xa2,0x71,0x73,0x36,0x74,0x17,0x65,0x63,0x68,0x6e,0x69,0x63,0x61,0x6c, +0x81,0x15,0x79,0x6d,0x62,0x6f,0x6c,0x73,0x8f,0x61,0xa2,0x66,0x65,0x46,0x6d,0x19, +0x61,0x74,0x68,0x73,0x79,0x6d,0x62,0x6f,0x6c,0x73,1,0x61,0xa3,0x66,0x62,0xa3, +0x69,0x17,0x6c,0x6c,0x61,0x6e,0x65,0x6f,0x75,0x73,2,0x6d,0x3a,0x73,0x6c,0x74, +0x17,0x65,0x63,0x68,0x6e,0x69,0x63,0x61,0x6c,0x81,0x11,0x61,0x74,0x1f,0x68,0x65, +0x6d,0x61,0x74,0x69,0x63,0x61,0x6c,0x73,0x79,0x6d,0x62,0x6f,0x6c,0x73,1,0x61, +0xa3,0x66,0x62,0xa3,0x69,0x15,0x79,0x6d,0x62,0x6f,0x6c,0x73,0x8e,0x12,0x61,0x6e, +0x64,1,0x61,0x3c,0x70,0x19,0x69,0x63,0x74,0x6f,0x67,0x72,0x61,0x70,0x68,0x73, +0xa3,0xcd,0x14,0x72,0x72,0x6f,0x77,0x73,0xa3,0x73,0x10,0x6f,0xa3,0xd8,7,0x72, +0x6f,0x72,0x44,0x73,0x4e,0x74,0x62,0x79,0x19,0x61,0x6e,0x6e,0x75,0x6d,0x65,0x72, +0x61,0x6c,0x73,0xa5,0x20,0x13,0x63,0x68,0x65,0x6e,0xa5,0xc,0x18,0x61,0x72,0x61, +0x6d,0x67,0x6f,0x6e,0x64,0x69,0xa5,0x14,0x10,0x68,2,0x61,0x3a,0x65,0x4a,0x6f, +0x17,0x70,0x65,0x72,0x61,0x74,0x6f,0x72,0x73,0x7f,0x16,0x6c,0x70,0x68,0x61,0x6e, +0x75,0x6d,0xa3,0x5d,0x16,0x6d,0x61,0x74,0x69,0x63,0x61,0x6c,1,0x61,0x36,0x6f, +0x17,0x70,0x65,0x72,0x61,0x74,0x6f,0x72,0x73,0x7f,0x11,0x6c,0x70,0x1f,0x68,0x61, +0x6e,0x75,0x6d,0x65,0x72,0x69,0x63,0x73,0x79,0x6d,0x62,0x6f,0x6c,0x73,0xa3,0x5d, +0x68,0x50,0x6b,0x7e,0x6c,0x88,0x6e,1,0x64,0x34,0x69,0x15,0x63,0x68,0x61,0x65, +0x61,0x6e,0xa3,0xea,0x12,0x61,0x69,0x63,0xa3,0xc6,1,0x61,0x3e,0x6a,0x12,0x6f, +0x6e,0x67,0xa2,0xaa,0x14,0x74,0x69,0x6c,0x65,0x73,0xa3,0xaa,0x13,0x6a,0x61,0x6e, +0x69,0xa3,0xe9,0x13,0x61,0x73,0x61,0x72,0xa5,0x1f,0x15,0x61,0x79,0x61,0x6c,0x61, +0x6d,0x4f,3,0x64,0x6c,0x65,0x7e,0x6e,0xa2,0x47,0x72,0x14,0x6f,0x69,0x74,0x69, 0x63,1,0x63,0x3c,0x68,0x19,0x69,0x65,0x72,0x6f,0x67,0x6c,0x79,0x70,0x68,0x73, -0xa3,0x56,0x15,0x75,0x72,0x73,0x69,0x76,0x65,0xa3,0x8d,0x17,0x74,0x65,0x69,0x6d, -0x61,0x79,0x65,0x6b,0xa3,0x73,0x10,0x64,0xa2,0x8c,0x17,0x65,0x6b,0x69,0x6b,0x61, -0x6b,0x75,0x69,0xa3,0x8c,0x11,0x61,0x6f,0xa3,0x5c,5,0x6f,0x14,0x6f,0x30,0x70, -0x36,0x74,0x11,0x68,0x69,0xa3,0x78,0x11,0x72,0x65,0xa3,0x77,0x11,0x65,0x6c,0xa3, -0x8a,0x61,0x2e,0x68,0x98,0x6e,0x11,0x64,0x61,0x4b,4,0x69,0x3c,0x6c,0x44,0x6e, -0x48,0x74,0x56,0x79,0x13,0x61,0x68,0x6c,0x69,0xa3,0x4f,0x12,0x74,0x68,0x69,0xa3, -0x78,0x10,0x69,0xa3,0x4f,1,0x61,0x4d,0x6e,0x12,0x61,0x64,0x61,0x4b,0x14,0x61, -0x6b,0x61,0x6e,0x61,0x4c,0x19,0x6f,0x72,0x68,0x69,0x72,0x61,0x67,0x61,0x6e,0x61, -0x8d,3,0x61,0x3c,0x6d,0x4e,0x6f,0x5a,0x75,0x15,0x64,0x61,0x77,0x61,0x64,0x69, -0xa3,0x91,0x10,0x72,0x92,0x15,0x6f,0x73,0x68,0x74,0x68,0x69,0x93,1,0x65,0x24, -0x72,0x4f,0x10,0x72,0x4f,0x10,0x6a,0xa2,0x9d,0x11,0x6b,0x69,0xa3,0x9d,4,0x61, -0x5c,0x65,0x90,0x69,0xa0,0x6f,0xa2,0x5d,0x79,1,0x63,0x34,0x64,0x10,0x69,0xa2, -0x6c,0x11,0x61,0x6e,0xa3,0x6c,0x10,0x69,0xa2,0x6b,0x11,0x61,0x6e,0xa3,0x6b,2, -0x6e,0x42,0x6f,0x46,0x74,3,0x66,0xa3,0x50,0x67,0xa3,0x51,0x69,0x24,0x6e,0x53, -0x10,0x6e,0x53,0x10,0x61,0xa3,0x6a,0x50,0x10,0x6f,0x51,0x11,0x70,0x63,0xa2,0x52, -0x11,0x68,0x61,0xa3,0x52,2,0x6d,0x2e,0x6e,0x36,0x73,0x10,0x75,0xa3,0x83,0x10, -0x62,0x80,0x10,0x75,0x81,2,0x61,0xa3,0x53,0x62,0x83,0x65,0x11,0x61,0x72,1, -0x61,0xa3,0x53,0x62,0x83,0x11,0x6d,0x61,0xa3,0x8b,0x68,0x6e,0x69,0xa2,0x83,0x6a, -2,0x61,0x30,0x70,0x52,0x75,0x11,0x72,0x63,0xa3,0x94,1,0x6d,0x38,0x76,0x10, -0x61,0xa2,0x4e,0x13,0x6e,0x65,0x73,0x65,0xa3,0x4e,0x10,0x6f,0xa3,0xad,0x11,0x61, -0x6e,0xa3,0x69,6,0x6c,0x1a,0x6c,0x34,0x6d,0x3a,0x72,0x40,0x75,0x11,0x6e,0x67, -0xa3,0x4c,0x11,0x75,0x77,0xa3,0x9c,0x11,0x6e,0x67,0xa3,0x4b,0x11,0x6b,0x74,0x8d, -0x61,0x3a,0x65,0x8c,0x69,0x11,0x72,0x61,0x48,0x13,0x67,0x61,0x6e,0x61,0x49,1, -0x6e,0x34,0x74,0x10,0x72,0xa2,0xa2,0x11,0x61,0x6e,0xa3,0xa2,0x42,6,0x6f,0xe, -0x6f,0x77,0x73,0xa3,0x49,0x74,0xa3,0x4a,0x75,0x12,0x6e,0x6f,0x6f,0x77,0x62,0xa3, -0xac,0x67,0x24,0x69,0x43,0x44,0x11,0x75,0x6c,0x45,0x11,0x62,0x72,0x46,0x11,0x65, -0x77,0x47,2,0x6d,0x2e,0x6e,0x4a,0x74,0x11,0x61,0x6c,0x5d,0x1c,0x70,0x65,0x72, -0x69,0x61,0x6c,0x61,0x72,0x61,0x6d,0x61,0x69,0x63,0xa3,0x74,2,0x64,0x66,0x68, -0x6a,0x73,0x1b,0x63,0x72,0x69,0x70,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x70,0x61,1, -0x68,0x32,0x72,0x14,0x74,0x68,0x69,0x61,0x6e,0xa3,0x7d,0x13,0x6c,0x61,0x76,0x69, -0xa3,0x7a,0x10,0x73,0xa3,0x4d,0x15,0x65,0x72,0x69,0x74,0x65,0x64,0x23,0x64,0xc0, -0xcf,0x64,0xa2,0x68,0x65,0xa2,0x90,0x67,4,0x65,0x64,0x6c,0x7c,0x6f,0x90,0x72, -0xa2,0x44,0x75,1,0x6a,0x38,0x72,1,0x6d,0x24,0x75,0x41,0x13,0x75,0x6b,0x68, -0x69,0x41,1,0x61,0x24,0x72,0x3f,0x13,0x72,0x61,0x74,0x69,0x3f,0x10,0x6f,1, -0x6b,0xa3,0x48,0x72,0x38,0x13,0x67,0x69,0x61,0x6e,0x39,0x11,0x61,0x67,0x90,0x15, -0x6f,0x6c,0x69,0x74,0x69,0x63,0x91,1,0x6e,0x30,0x74,0x10,0x68,0x3a,0x11,0x69, -0x63,0x3b,0x10,0x6d,0xa3,0xaf,1,0x61,0x32,0x65,1,0x65,0x24,0x6b,0x3d,0x10, -0x6b,0x3d,0x10,0x6e,0xa2,0x89,0x12,0x74,0x68,0x61,0xa3,0x89,2,0x65,0x3e,0x73, -0x64,0x75,0x11,0x70,0x6c,0xa2,0x87,0x13,0x6f,0x79,0x61,0x6e,0xa3,0x87,1,0x73, -0x38,0x76,0x10,0x61,0x34,0x15,0x6e,0x61,0x67,0x61,0x72,0x69,0x35,0x13,0x65,0x72, -0x65,0x74,0x33,0x11,0x72,0x74,0x33,2,0x67,0x3a,0x6c,0x72,0x74,0x11,0x68,0x69, -0x36,0x13,0x6f,0x70,0x69,0x63,0x37,0x10,0x79,2,0x64,0xa3,0x45,0x68,0xa3,0x46, -0x70,0xa2,0x47,0x1e,0x74,0x69,0x61,0x6e,0x68,0x69,0x65,0x72,0x6f,0x67,0x6c,0x79, -0x70,0x68,0x73,0xa3,0x47,0x11,0x62,0x61,0xa2,0x88,0x12,0x73,0x61,0x6e,0xa3,0x88, -0x61,0xa2,0xa2,0x62,0xa4,7,0x63,6,0x6f,0x3d,0x6f,0x5a,0x70,0x76,0x75,0x7a, -0x79,1,0x70,0x3e,0x72,2,0x69,0x2a,0x6c,0x31,0x73,0xa3,0x44,0x13,0x6c,0x6c, -0x69,0x63,0x31,0x13,0x72,0x69,0x6f,0x74,0x7f,1,0x6d,0x30,0x70,0x10,0x74,0x2e, -0x11,0x69,0x63,0x2f,0x12,0x6d,0x6f,0x6e,0x21,0x11,0x72,0x74,0x7f,0x16,0x6e,0x65, -0x69,0x66,0x6f,0x72,0x6d,0xa3,0x65,0x61,0x32,0x68,0xa2,0x41,0x69,0x11,0x72,0x74, -0xa3,0x43,3,0x6b,0x4c,0x6e,0x50,0x72,0x76,0x75,0x1d,0x63,0x61,0x73,0x69,0x61, -0x6e,0x61,0x6c,0x62,0x61,0x6e,0x69,0x61,0x6e,0xa3,0x9f,0x10,0x6d,0xa3,0x76,1, -0x61,0x24,0x73,0x71,0x1d,0x64,0x69,0x61,0x6e,0x61,0x62,0x6f,0x72,0x69,0x67,0x69, -0x6e,0x61,0x6c,0x71,0x10,0x69,0xa2,0x68,0x11,0x61,0x6e,0xa3,0x68,1,0x61,0x34, -0x65,0x10,0x72,0x2c,0x13,0x6f,0x6b,0x65,0x65,0x2d,1,0x6b,0x26,0x6d,0xa3,0x42, -0x11,0x6d,0x61,0xa3,0x76,6,0x68,0x4a,0x68,0x48,0x6e,0x4e,0x72,0x76,0x76,1, -0x65,0x2a,0x73,0x10,0x74,0xa3,0x75,0x13,0x73,0x74,0x61,0x6e,0xa3,0x75,0x11,0x6f, -0x6d,0xa3,0xa1,0x11,0x61,0x74,0x1f,0x6f,0x6c,0x69,0x61,0x6e,0x68,0x69,0x65,0x72, -0x6f,0x67,0x6c,0x79,0x70,0x68,0x73,0xa3,0x9c,1,0x61,0x3e,0x6d,2,0x65,0x2a, -0x69,0xa3,0x74,0x6e,0x27,0x13,0x6e,0x69,0x61,0x6e,0x27,0x10,0x62,0x24,0x11,0x69, -0x63,0x25,0x64,0x30,0x66,0x44,0x67,0x11,0x68,0x62,0xa3,0x9f,0x10,0x6c,1,0x61, -0x26,0x6d,0xa3,0xa7,0x10,0x6d,0xa3,0xa7,0x11,0x61,0x6b,0xa3,0x93,6,0x6c,0x3c, -0x6c,0x52,0x6f,0x56,0x72,0x66,0x75,1,0x67,0x30,0x68,1,0x64,0x79,0x69,0x10, -0x64,0x79,0x10,0x69,0x8e,0x13,0x6e,0x65,0x73,0x65,0x8f,0x11,0x69,0x73,0xa1,0x11, -0x70,0x6f,0x2a,0x13,0x6d,0x6f,0x66,0x6f,0x2b,0x10,0x61,1,0x68,0x2e,0x69,0x7c, -0x12,0x6c,0x6c,0x65,0x7d,0xa2,0x41,0x11,0x6d,0x69,0xa3,0x41,0x61,0x48,0x65,0x9c, -0x68,1,0x61,0x2a,0x6b,0x10,0x73,0xa3,0xa8,0x15,0x69,0x6b,0x73,0x75,0x6b,0x69, -0xa3,0xa8,3,0x6c,0x3a,0x6d,0x48,0x73,0x54,0x74,1,0x61,0x24,0x6b,0x9f,0x10, -0x6b,0x9f,0x10,0x69,0x9c,0x13,0x6e,0x65,0x73,0x65,0x9d,0x10,0x75,0xa2,0x82,0x10, -0x6d,0xa3,0x82,0x10,0x73,0xa2,0x86,0x13,0x61,0x76,0x61,0x68,0xa3,0x86,0x11,0x6e, -0x67,0x28,0x12,0x61,0x6c,0x69,0x29,3,0x6c,0x42,0x6e,0x90,0x74,0xa2,0x46,0x76, -0x24,0x17,0x6f,0x77,0x65,0x6c,0x6a,0x61,0x6d,0x6f,0x25,0x22,1,0x65,0x54,0x76, -0x28,1,0x73,0x38,0x74,0x2a,0x17,0x73,0x79,0x6c,0x6c,0x61,0x62,0x6c,0x65,0x2b, -0x16,0x79,0x6c,0x6c,0x61,0x62,0x6c,0x65,0x29,0x18,0x61,0x64,0x69,0x6e,0x67,0x6a, -0x61,0x6d,0x6f,0x23,1,0x61,0x21,0x6f,0x1a,0x74,0x61,0x70,0x70,0x6c,0x69,0x63, -0x61,0x62,0x6c,0x65,0x21,0x26,0x1a,0x72,0x61,0x69,0x6c,0x69,0x6e,0x67,0x6a,0x61, -0x6d,0x6f,0x27,1,0x6e,0x2c,0x79,0x22,0x11,0x65,0x73,0x23,0x20,0x10,0x6f,0x21, -1,0x6e,0x2c,0x79,0x22,0x11,0x65,0x73,0x23,0x20,0x10,0x6f,0x21,2,0x6d,0x30, -0x6e,0x3a,0x79,0x22,0x11,0x65,0x73,0x23,0x24,0x13,0x61,0x79,0x62,0x65,0x25,0x20, -0x10,0x6f,0x21,2,0x6d,0x30,0x6e,0x3a,0x79,0x22,0x11,0x65,0x73,0x23,0x24,0x13, -0x61,0x79,0x62,0x65,0x25,0x20,0x10,0x6f,0x21,0xb,0x72,0x39,0x76,0xc,0x76,0x33, -0x78,0x2a,0x7a,0x11,0x77,0x6a,0x43,0x10,0x78,0x21,0x72,0x28,0x73,0x50,0x74,0x31, -1,0x65,0x24,0x69,0x39,0x1e,0x67,0x69,0x6f,0x6e,0x61,0x6c,0x69,0x6e,0x64,0x69, -0x63,0x61,0x74,0x6f,0x72,0x39,1,0x6d,0x35,0x70,0x18,0x61,0x63,0x69,0x6e,0x67, -0x6d,0x61,0x72,0x6b,0x35,0x6c,0x1f,0x6c,0x3c,0x6f,0x4a,0x70,1,0x70,0x37,0x72, -0x14,0x65,0x70,0x65,0x6e,0x64,0x37,0x28,1,0x66,0x2b,0x76,0x2c,0x10,0x74,0x2f, -0x13,0x74,0x68,0x65,0x72,0x21,0x63,0x4c,0x65,0x64,0x67,1,0x61,0x3a,0x6c,0x19, -0x75,0x65,0x61,0x66,0x74,0x65,0x72,0x7a,0x77,0x6a,0x41,0x10,0x7a,0x41,2,0x6e, -0x23,0x6f,0x24,0x72,0x25,0x14,0x6e,0x74,0x72,0x6f,0x6c,0x23,2,0x62,0x34,0x6d, -0x4e,0x78,0x26,0x13,0x74,0x65,0x6e,0x64,0x27,0x3a,1,0x61,0x24,0x67,0x3d,0x11, -0x73,0x65,0x3a,0x12,0x67,0x61,0x7a,0x3d,0x3e,0x16,0x6f,0x64,0x69,0x66,0x69,0x65, -0x72,0x3f,9,0x6e,0x4a,0x6e,0x34,0x6f,0x44,0x73,0x60,0x75,0x94,0x78,0x10,0x78, -0x21,0x10,0x75,0x2a,0x14,0x6d,0x65,0x72,0x69,0x63,0x2b,1,0x6c,0x2c,0x74,0x12, -0x68,0x65,0x72,0x21,0x14,0x65,0x74,0x74,0x65,0x72,0x2d,3,0x63,0x36,0x65,0x46, -0x70,0x31,0x74,0x32,0x12,0x65,0x72,0x6d,0x33,0x3c,0x16,0x6f,0x6e,0x74,0x69,0x6e, -0x75,0x65,0x3d,0x2e,0x10,0x70,0x2f,0x10,0x70,0x34,0x12,0x70,0x65,0x72,0x35,0x61, -0x46,0x63,0x52,0x65,0x64,0x66,0x72,0x6c,2,0x65,0x2d,0x66,0x3b,0x6f,0x28,0x12, -0x77,0x65,0x72,0x29,0x10,0x74,0x22,0x12,0x65,0x72,0x6d,0x23,1,0x6c,0x24,0x72, -0x37,0x24,0x12,0x6f,0x73,0x65,0x25,0x10,0x78,0x38,0x13,0x74,0x65,0x6e,0x64,0x39, -0x10,0x6f,0x26,0x13,0x72,0x6d,0x61,0x74,0x27,0xf,0x6c,0x7c,0x72,0x34,0x72,0x32, -0x73,0x5a,0x78,0x76,0x7a,0x11,0x77,0x6a,0x4b,1,0x65,0x24,0x69,0x3b,0x1e,0x67, -0x69,0x6f,0x6e,0x61,0x6c,0x69,0x6e,0x64,0x69,0x63,0x61,0x74,0x6f,0x72,0x3b,1, -0x69,0x24,0x71,0x3f,0x18,0x6e,0x67,0x6c,0x65,0x71,0x75,0x6f,0x74,0x65,0x3f,0x10, -0x78,0x21,0x6c,0x36,0x6d,0x3c,0x6e,0x76,0x6f,0x13,0x74,0x68,0x65,0x72,0x21,1, -0x65,0x23,0x66,0x35,3,0x62,0x37,0x69,0x28,0x6c,0x29,0x6e,0x2b,0x10,0x64,1, -0x6c,0x34,0x6e,0x11,0x75,0x6d,0x2a,0x12,0x6c,0x65,0x74,0x37,0x14,0x65,0x74,0x74, -0x65,0x72,0x29,2,0x65,0x36,0x6c,0x39,0x75,0x2c,0x14,0x6d,0x65,0x72,0x69,0x63, -0x2d,0x14,0x77,0x6c,0x69,0x6e,0x65,0x39,0x66,0x3f,0x66,0x40,0x67,0x4e,0x68,0x70, -0x6b,0x10,0x61,0x26,0x15,0x74,0x61,0x6b,0x61,0x6e,0x61,0x27,0x10,0x6f,0x24,0x13, -0x72,0x6d,0x61,0x74,0x25,1,0x61,0x3a,0x6c,0x19,0x75,0x65,0x61,0x66,0x74,0x65, -0x72,0x7a,0x77,0x6a,0x49,0x10,0x7a,0x49,1,0x65,0x24,0x6c,0x3d,0x19,0x62,0x72, -0x65,0x77,0x6c,0x65,0x74,0x74,0x65,0x72,0x3d,0x61,0x86,0x63,0x92,0x64,0x94,0x65, -2,0x62,0x44,0x6d,0x5e,0x78,0x2e,0x13,0x74,0x65,0x6e,0x64,0x32,0x15,0x6e,0x75, -0x6d,0x6c,0x65,0x74,0x2f,0x42,1,0x61,0x24,0x67,0x45,0x11,0x73,0x65,0x42,0x12, -0x67,0x61,0x7a,0x45,0x46,0x16,0x6f,0x64,0x69,0x66,0x69,0x65,0x72,0x47,0x15,0x6c, -0x65,0x74,0x74,0x65,0x72,0x23,0x10,0x72,0x31,1,0x6f,0x24,0x71,0x41,0x18,0x75, -0x62,0x6c,0x65,0x71,0x75,0x6f,0x74,0x65,0x41,2,0x63,0x32,0x6e,0x3c,0x6f,0x22, -0x12,0x70,0x65,0x6e,0x23,0x24,0x13,0x6c,0x6f,0x73,0x65,0x25,0x20,0x12,0x6f,0x6e, -0x65,0x21,0xd,0x6e,0xc1,0x86,0x73,0xa8,0x73,0x4c,0x74,0xa2,0x76,0x75,0xa2,0x83, -0x7a,0xd8,0x70,0,2,0x6c,0xd9,0x20,0,0x70,0xd9,0x40,0,0x73,0xc3,0, -0xfe,0xf,0,0,0,7,0x6f,0x3c,0x6f,0xff,8,0,0,0,0x70,0x3a, -0x75,0x6e,0x79,0x13,0x6d,0x62,0x6f,0x6c,0xff,0xf,0,0,0,0x11,0x61,0x63, -1,0x65,0x34,0x69,0x15,0x6e,0x67,0x6d,0x61,0x72,0x6b,0xa5,0,0x18,0x73,0x65, -0x70,0x61,0x72,0x61,0x74,0x6f,0x72,0xc3,0,0x16,0x72,0x72,0x6f,0x67,0x61,0x74, -0x65,0xe1,0,0,0x63,0xff,2,0,0,0,0x65,0x38,0x6b,0xff,4,0, -0,0,0x6d,0xff,1,0,0,0,0x16,0x70,0x61,0x72,0x61,0x74,0x6f,0x72, -0xd9,0x70,0,0x1d,0x69,0x74,0x6c,0x65,0x63,0x61,0x73,0x65,0x6c,0x65,0x74,0x74, -0x65,0x72,0x31,1,0x6e,0x40,0x70,0x1c,0x70,0x65,0x72,0x63,0x61,0x73,0x65,0x6c, -0x65,0x74,0x74,0x65,0x72,0x25,0x17,0x61,0x73,0x73,0x69,0x67,0x6e,0x65,0x64,0x23, -0x6e,0xa2,0x69,0x6f,0xa2,0x89,0x70,0xfe,0x30,0xf8,0,0,9,0x69,0x33,0x69, -0xff,0x10,0,0,0,0x6f,0xfd,0x80,0,0,0x72,0x54,0x73,0xf9,0,0, -0x75,0x12,0x6e,0x63,0x74,0xfe,0x30,0xf8,0,0,0x15,0x75,0x61,0x74,0x69,0x6f, -0x6e,0xff,0x30,0xf8,0,0,0x17,0x69,0x76,0x61,0x74,0x65,0x75,0x73,0x65,0xdd, -0,0,0x61,0x48,0x63,0xfd,0x40,0,0,0x64,0xe9,0,0,0x65,0xfd,0x20, -0,0,0x66,0xff,0x20,0,0,0,0x1f,0x72,0x61,0x67,0x72,0x61,0x70,0x68, -0x73,0x65,0x70,0x61,0x72,0x61,0x74,0x6f,0x72,0xd9,0x40,0,0xbe,0,3,0x64, -0xa7,0,0x6c,0xab,0,0x6f,0x30,0x75,0x13,0x6d,0x62,0x65,0x72,0xbf,0,0xb2, -0,0x1b,0x6e,0x73,0x70,0x61,0x63,0x69,0x6e,0x67,0x6d,0x61,0x72,0x6b,0xa1,1, -0x70,0x92,0x74,0x12,0x68,0x65,0x72,0xe6,0x80,1,3,0x6c,0x40,0x6e,0x4a,0x70, -0x56,0x73,0x14,0x79,0x6d,0x62,0x6f,0x6c,0xff,8,0,0,0,0x14,0x65,0x74, -0x74,0x65,0x72,0x61,0x14,0x75,0x6d,0x62,0x65,0x72,0xb3,0,0x19,0x75,0x6e,0x63, -0x74,0x75,0x61,0x74,0x69,0x6f,0x6e,0xfd,0x80,0,0,0x1c,0x65,0x6e,0x70,0x75, -0x6e,0x63,0x74,0x75,0x61,0x74,0x69,0x6f,0x6e,0xf9,0,0,0x66,0xc0,0xc4,0x66, -0xa2,0x47,0x69,0xa2,0x64,0x6c,0xa2,0x79,0x6d,0xa4,0xc0,4,0x61,0x6c,0x63,0xa5, -0,0x65,0xa3,0x80,0x6e,0xa1,0x6f,0x15,0x64,0x69,0x66,0x69,0x65,0x72,1,0x6c, -0x38,0x73,0x14,0x79,0x6d,0x62,0x6f,0x6c,0xff,4,0,0,0,0x14,0x65,0x74, -0x74,0x65,0x72,0x41,1,0x72,0x3c,0x74,0x16,0x68,0x73,0x79,0x6d,0x62,0x6f,0x6c, -0xff,1,0,0,0,0x10,0x6b,0xa5,0xc0,1,0x69,0x32,0x6f,0x13,0x72,0x6d, -0x61,0x74,0xdb,0,0,0x1d,0x6e,0x61,0x6c,0x70,0x75,0x6e,0x63,0x74,0x75,0x61, -0x74,0x69,0x6f,0x6e,0xff,0x20,0,0,0,0x10,0x6e,0x1f,0x69,0x74,0x69,0x61, -0x6c,0x70,0x75,0x6e,0x63,0x74,0x75,0x61,0x74,0x69,0x6f,0x6e,0xff,0x10,0,0, -0,0x9c,7,0x6d,0x18,0x6d,0x41,0x6f,0x28,0x74,0x31,0x75,0x25,0x60,0x1c,0x77, -0x65,0x72,0x63,0x61,0x73,0x65,0x6c,0x65,0x74,0x74,0x65,0x72,0x29,0x63,0x3d,0x65, -0x28,0x69,0x42,0x6c,0x29,0x13,0x74,0x74,0x65,0x72,0x9c,0x15,0x6e,0x75,0x6d,0x62, -0x65,0x72,0xab,0,0x1a,0x6e,0x65,0x73,0x65,0x70,0x61,0x72,0x61,0x74,0x6f,0x72, -0xd9,0x20,0,0x63,0x46,0x64,0xa2,0x96,0x65,0x1b,0x6e,0x63,0x6c,0x6f,0x73,0x69, -0x6e,0x67,0x6d,0x61,0x72,0x6b,0xa3,0x80,0xe6,0x80,1,7,0x6e,0x57,0x6e,0x52, -0x6f,0x5e,0x73,0xe1,0,0,0x75,0x1b,0x72,0x72,0x65,0x6e,0x63,0x79,0x73,0x79, -0x6d,0x62,0x6f,0x6c,0xff,2,0,0,0,0x22,0x12,0x74,0x72,0x6c,0xd9,0x80, -0,0xdc,0,0,1,0x6d,0x62,0x6e,1,0x6e,0x30,0x74,0x12,0x72,0x6f,0x6c, -0xd9,0x80,0,0x1f,0x65,0x63,0x74,0x6f,0x72,0x70,0x75,0x6e,0x63,0x74,0x75,0x61, -0x74,0x69,0x6f,0x6e,0xfd,0x40,0,0,0x19,0x62,0x69,0x6e,0x69,0x6e,0x67,0x6d, -0x61,0x72,0x6b,0xa5,0xc0,0x61,0x58,0x63,0xd9,0x80,0,0x66,0xdb,0,0,0x6c, -0x1d,0x6f,0x73,0x65,0x70,0x75,0x6e,0x63,0x74,0x75,0x61,0x74,0x69,0x6f,0x6e,0xfd, -0x20,0,0,0x18,0x73,0x65,0x64,0x6c,0x65,0x74,0x74,0x65,0x72,0x3d,2,0x61, -0x32,0x65,0x50,0x69,0x12,0x67,0x69,0x74,0xa7,0,0x1c,0x73,0x68,0x70,0x75,0x6e, -0x63,0x74,0x75,0x61,0x74,0x69,0x6f,0x6e,0xe9,0,0,0x1a,0x63,0x69,0x6d,0x61, -0x6c,0x6e,0x75,0x6d,0x62,0x65,0x72,0xa7,0 +0xa3,0xd7,0x15,0x75,0x72,0x73,0x69,0x76,0x65,0xa3,0xd6,0x17,0x65,0x66,0x61,0x69, +0x64,0x72,0x69,0x6e,0xa5,0x21,0x17,0x74,0x65,0x69,0x6d,0x61,0x79,0x65,0x6b,0xa2, +0xb8,0x12,0x65,0x78,0x74,0xa2,0xd5,0x16,0x65,0x6e,0x73,0x69,0x6f,0x6e,0x73,0xa3, +0xd5,0x18,0x64,0x65,0x6b,0x69,0x6b,0x61,0x6b,0x75,0x69,0xa3,0xeb,5,0x6b,0x23, +0x6b,0x4c,0x6f,0x50,0x75,1,0x6d,0x2c,0x73,0x11,0x68,0x75,0xa5,0x15,0x17,0x62, +0x65,0x72,0x66,0x6f,0x72,0x6d,0x73,0x7b,0x10,0x6f,0xa3,0x92,0x14,0x62,0x6c,0x6f, +0x63,0x6b,0x21,0x61,0x44,0x62,0x21,0x65,0x10,0x77,1,0x61,0xa5,0xe,0x74,0x14, +0x61,0x69,0x6c,0x75,0x65,0xa3,0x8b,0x16,0x62,0x61,0x74,0x61,0x65,0x61,0x6e,0xa3, +0xef,0x67,0xc4,0xe,0x6a,0xc1,0x95,0x6a,0xa2,0xc5,0x6b,0xa2,0xde,0x6c,4,0x61, +0x54,0x65,0xa2,0x61,0x69,0xa2,0x78,0x6f,0xa2,0xa7,0x79,1,0x63,0x2e,0x64,0x12, +0x69,0x61,0x6e,0xa3,0xa9,0x12,0x69,0x61,0x6e,0xa3,0xa7,1,0x6f,0x55,0x74,0x11, +0x69,0x6e,1,0x31,0x82,0x65,0x11,0x78,0x74,4,0x61,0x5c,0x62,0x29,0x63,0xa3, +0x94,0x64,0xa3,0x95,0x65,0xa2,0xe7,0x13,0x6e,0x64,0x65,0x64,4,0x61,0x36,0x62, +0x29,0x63,0xa3,0x94,0x64,0xa3,0x95,0x65,0xa3,0xe7,0x26,0x18,0x64,0x64,0x69,0x74, +0x69,0x6f,0x6e,0x61,0x6c,0x6d,0x24,0x12,0x73,0x75,0x70,0x24,0x16,0x70,0x6c,0x65, +0x6d,0x65,0x6e,0x74,0x25,1,0x70,0x42,0x74,0x1d,0x74,0x65,0x72,0x6c,0x69,0x6b, +0x65,0x73,0x79,0x6d,0x62,0x6f,0x6c,0x73,0x79,0x12,0x63,0x68,0x61,0xa3,0x9c,2, +0x6d,0x2e,0x6e,0x34,0x73,0x10,0x75,0xa3,0xb0,0x11,0x62,0x75,0xa3,0x6f,0x12,0x65, +0x61,0x72,1,0x61,0xa3,0xe8,0x62,1,0x69,0x38,0x73,0x17,0x79,0x6c,0x6c,0x61, +0x62,0x61,0x72,0x79,0xa3,0x75,0x17,0x64,0x65,0x6f,0x67,0x72,0x61,0x6d,0x73,0xa3, +0x76,0x1a,0x77,0x73,0x75,0x72,0x72,0x6f,0x67,0x61,0x74,0x65,0x73,0xa3,0x4d,0x10, +0x61,1,0x6d,0x32,0x76,0x14,0x61,0x6e,0x65,0x73,0x65,0xa3,0xb5,0x10,0x6f,0x5c, +0x12,0x65,0x78,0x74,1,0x61,0xa3,0xb4,0x62,0xa3,0xb9,1,0x61,0x80,0x68,3, +0x61,0x3c,0x6d,0x4c,0x6f,0x64,0x75,0x15,0x64,0x61,0x77,0x61,0x64,0x69,0xa3,0xe6, +0x16,0x72,0x6f,0x73,0x68,0x74,0x68,0x69,0xa3,0x89,0x11,0x65,0x72,0x68,0x16,0x73, +0x79,0x6d,0x62,0x6f,0x6c,0x73,0xa3,0x71,0x12,0x6a,0x6b,0x69,0xa3,0xe5,3,0x69, +0x3a,0x6e,0x42,0x74,0xa2,0x51,0x79,0x13,0x61,0x68,0x6c,0x69,0xa3,0xa2,0x12,0x74, +0x68,0x69,0xa3,0xc1,3,0x61,0x34,0x62,0x76,0x67,0x7c,0x6e,0x12,0x61,0x64,0x61, +0x4d,1,0x65,0x40,0x73,0x11,0x75,0x70,0xa2,0xcb,0x16,0x70,0x6c,0x65,0x6d,0x65, +0x6e,0x74,0xa3,0xcb,0x11,0x78,0x74,1,0x61,0xa5,0x13,0x65,0x14,0x6e,0x64,0x65, +0x64,0x61,0xa5,0x13,0x11,0x75,0x6e,0xa3,0x42,0x11,0x78,0x69,0x96,0x17,0x72,0x61, +0x64,0x69,0x63,0x61,0x6c,0x73,0x97,0x14,0x61,0x6b,0x61,0x6e,0x61,0x9e,1,0x65, +0x4c,0x70,0x10,0x68,0x1f,0x6f,0x6e,0x65,0x74,0x69,0x63,0x65,0x78,0x74,0x65,0x6e, +0x73,0x69,0x6f,0x6e,0x73,0xa3,0x6b,0x11,0x78,0x74,0xa3,0x6b,0x67,0xa2,0xb5,0x68, +0xa4,0x84,0x69,3,0x64,0x4c,0x6d,0xa2,0x55,0x6e,0xa2,0x62,0x70,0x13,0x61,0x65, +0x78,0x74,0x2a,0x16,0x65,0x6e,0x73,0x69,0x6f,0x6e,0x73,0x2b,1,0x63,0x99,0x65, +0x17,0x6f,0x67,0x72,0x61,0x70,0x68,0x69,0x63,1,0x64,0x56,0x73,0x15,0x79,0x6d, +0x62,0x6f,0x6c,0x73,0xa4,0xb,0x1d,0x61,0x6e,0x64,0x70,0x75,0x6e,0x63,0x74,0x75, +0x61,0x74,0x69,0x6f,0x6e,0xa5,0xb,0x13,0x65,0x73,0x63,0x72,0x1f,0x69,0x70,0x74, +0x69,0x6f,0x6e,0x63,0x68,0x61,0x72,0x61,0x63,0x74,0x65,0x72,0x73,0x99,0x1c,0x70, +0x65,0x72,0x69,0x61,0x6c,0x61,0x72,0x61,0x6d,0x61,0x69,0x63,0xa3,0xba,1,0x64, +0x62,0x73,0x1b,0x63,0x72,0x69,0x70,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x70,0x61,1, +0x68,0x32,0x72,0x14,0x74,0x68,0x69,0x61,0x6e,0xa3,0xbd,0x13,0x6c,0x61,0x76,0x69, +0xa3,0xbe,0x11,0x69,0x63,1,0x6e,0x3e,0x73,0x1a,0x69,0x79,0x61,0x71,0x6e,0x75, +0x6d,0x62,0x65,0x72,0x73,0xa5,0x1e,0x19,0x75,0x6d,0x62,0x65,0x72,0x66,0x6f,0x72, +0x6d,0x73,0xa3,0xb2,4,0x65,0x74,0x6c,0xa2,0x82,0x6f,0xa2,0x9a,0x72,0xa2,0x9e, +0x75,2,0x6a,0x34,0x6e,0x3e,0x72,0x14,0x6d,0x75,0x6b,0x68,0x69,0x43,0x14,0x61, +0x72,0x61,0x74,0x69,0x45,0x18,0x6a,0x61,0x6c,0x61,0x67,0x6f,0x6e,0x64,0x69,0xa5, +0x1c,1,0x6e,0xa2,0x46,0x6f,1,0x6d,0x6e,0x72,0x13,0x67,0x69,0x61,0x6e,0x5a, +1,0x65,0x40,0x73,0x11,0x75,0x70,0xa2,0x87,0x16,0x70,0x6c,0x65,0x6d,0x65,0x6e, +0x74,0xa3,0x87,0x11,0x78,0x74,0xa4,0x1b,0x14,0x65,0x6e,0x64,0x65,0x64,0xa5,0x1b, +0x1a,0x65,0x74,0x72,0x69,0x63,0x73,0x68,0x61,0x70,0x65,0x73,0x8c,0x12,0x65,0x78, +0x74,0xa2,0xe3,0x14,0x65,0x6e,0x64,0x65,0x64,0xa3,0xe3,0x1e,0x65,0x72,0x61,0x6c, +0x70,0x75,0x6e,0x63,0x74,0x75,0x61,0x74,0x69,0x6f,0x6e,0x71,0x17,0x61,0x67,0x6f, +0x6c,0x69,0x74,0x69,0x63,0xa2,0x88,0x12,0x73,0x75,0x70,0xa4,0xa,0x16,0x70,0x6c, +0x65,0x6d,0x65,0x6e,0x74,0xa5,0xa,0x13,0x74,0x68,0x69,0x63,0xa3,0x59,1,0x61, +0x5c,0x65,0x11,0x65,0x6b,0x30,1,0x61,0x38,0x65,0x11,0x78,0x74,0x6e,0x14,0x65, +0x6e,0x64,0x65,0x64,0x6f,0x17,0x6e,0x64,0x63,0x6f,0x70,0x74,0x69,0x63,0x31,0x13, +0x6e,0x74,0x68,0x61,0xa3,0xe4,2,0x61,0xa2,0x48,0x65,0xa2,0xdf,0x69,1,0x67, +0x30,0x72,0x14,0x61,0x67,0x61,0x6e,0x61,0x9d,0x10,0x68,1,0x70,0x3a,0x73,0x18, +0x75,0x72,0x72,0x6f,0x67,0x61,0x74,0x65,0x73,0xa3,0x4b,1,0x72,0x3c,0x75,0x19, +0x73,0x75,0x72,0x72,0x6f,0x67,0x61,0x74,0x65,0x73,0xa3,0x4c,0x11,0x69,0x76,0x1f, +0x61,0x74,0x65,0x75,0x73,0x65,0x73,0x75,0x72,0x72,0x6f,0x67,0x61,0x74,0x65,0x73, +0xa3,0x4c,2,0x6c,0x32,0x6e,0x9a,0x74,0x12,0x72,0x61,0x6e,0xa5,2,0x10,0x66, +2,0x61,0x58,0x6d,0x70,0x77,0x14,0x69,0x64,0x74,0x68,0x61,0x1f,0x6e,0x64,0x66, +0x75,0x6c,0x6c,0x77,0x69,0x64,0x74,0x68,0x66,0x6f,0x72,0x6d,0x73,0xa3,0x57,0x1a, +0x6e,0x64,0x66,0x75,0x6c,0x6c,0x66,0x6f,0x72,0x6d,0x73,0xa3,0x57,0x13,0x61,0x72, +0x6b,0x73,0xa3,0x52,2,0x67,0x34,0x69,0xa2,0x45,0x75,0x12,0x6e,0x6f,0x6f,0xa3, +0x63,0x11,0x75,0x6c,0xa2,0x4a,2,0x63,0x3c,0x6a,0x5e,0x73,0x17,0x79,0x6c,0x6c, +0x61,0x62,0x6c,0x65,0x73,0xa3,0x4a,0x1f,0x6f,0x6d,0x70,0x61,0x74,0x69,0x62,0x69, +0x6c,0x69,0x74,0x79,0x6a,0x61,0x6d,0x6f,0xa3,0x41,0x12,0x61,0x6d,0x6f,0x5c,0x17, +0x65,0x78,0x74,0x65,0x6e,0x64,0x65,0x64,1,0x61,0xa3,0xb4,0x62,0xa3,0xb9,0x19, +0x66,0x69,0x72,0x6f,0x68,0x69,0x6e,0x67,0x79,0x61,0xa5,0x1d,0x13,0x62,0x72,0x65, +0x77,0x37,0x61,0xa2,0xe9,0x62,0xa6,0x29,0x63,0xa6,0xfe,0x64,0xac,0x8a,0x65,5, +0x6d,0xa2,0x6d,0x86,0x6e,0x96,0x74,0x15,0x68,0x69,0x6f,0x70,0x69,0x63,0x5e,1, +0x65,0x40,0x73,0x11,0x75,0x70,0xa2,0x86,0x16,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74, +0xa3,0x86,0x11,0x78,0x74,0xa2,0x85,1,0x61,0xa3,0xc8,0x65,0x13,0x6e,0x64,0x65, +0x64,0xa2,0x85,0x10,0x61,0xa3,0xc8,0x16,0x6f,0x74,0x69,0x63,0x6f,0x6e,0x73,0xa3, +0xce,0x15,0x63,0x6c,0x6f,0x73,0x65,0x64,2,0x61,0x5a,0x63,0x9e,0x69,0x1c,0x64, +0x65,0x6f,0x67,0x72,0x61,0x70,0x68,0x69,0x63,0x73,0x75,0x70,0xa2,0xc4,0x16,0x70, +0x6c,0x65,0x6d,0x65,0x6e,0x74,0xa3,0xc4,0x16,0x6c,0x70,0x68,0x61,0x6e,0x75,0x6d, +0x86,1,0x65,0x2c,0x73,0x11,0x75,0x70,0xa3,0xc3,0x13,0x72,0x69,0x63,0x73,0x86, +0x18,0x75,0x70,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0xa3,0xc3,0x11,0x6a,0x6b,0xa2, +0x44,0x1f,0x6c,0x65,0x74,0x74,0x65,0x72,0x73,0x61,0x6e,0x64,0x6d,0x6f,0x6e,0x74, +0x68,0x73,0xa3,0x44,0x61,0x36,0x67,0x62,0x6c,0x14,0x62,0x61,0x73,0x61,0x6e,0xa3, +0xe2,0x13,0x72,0x6c,0x79,0x64,0x1f,0x79,0x6e,0x61,0x73,0x74,0x69,0x63,0x63,0x75, +0x6e,0x65,0x69,0x66,0x6f,0x72,0x6d,0xa5,1,0x10,0x79,0x1f,0x70,0x74,0x69,0x61, +0x6e,0x68,0x69,0x65,0x72,0x6f,0x67,0x6c,0x79,0x70,0x68,0x73,0xa3,0xc2,7,0x6e, +0xc0,0xe5,0x6e,0x3e,0x72,0xa2,0x5d,0x73,0xa2,0xd8,0x76,0x14,0x65,0x73,0x74,0x61, +0x6e,0xa3,0xbc,1,0x61,0x92,0x63,0x13,0x69,0x65,0x6e,0x74,1,0x67,0x34,0x73, +0x15,0x79,0x6d,0x62,0x6f,0x6c,0x73,0xa3,0xa5,0x13,0x72,0x65,0x65,0x6b,1,0x6d, +0x34,0x6e,0x15,0x75,0x6d,0x62,0x65,0x72,0x73,0xa3,0x7f,0x13,0x75,0x73,0x69,0x63, +0xa2,0x7e,0x19,0x61,0x6c,0x6e,0x6f,0x74,0x61,0x74,0x69,0x6f,0x6e,0xa3,0x7e,0x10, +0x74,0x1f,0x6f,0x6c,0x69,0x61,0x6e,0x68,0x69,0x65,0x72,0x6f,0x67,0x6c,0x79,0x70, +0x68,0x73,0xa3,0xfe,2,0x61,0x32,0x6d,0xa2,0x71,0x72,0x12,0x6f,0x77,0x73,0x7d, +0x12,0x62,0x69,0x63,0x38,3,0x65,0x4a,0x6d,0x66,0x70,0xa2,0x43,0x73,0x11,0x75, +0x70,0xa2,0x80,0x16,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0xa3,0x80,0x11,0x78,0x74, +1,0x61,0xa3,0xd2,0x65,0x14,0x6e,0x64,0x65,0x64,0x61,0xa3,0xd2,0x12,0x61,0x74, +0x68,0xa2,0xd3,0x18,0x65,0x6d,0x61,0x74,0x69,0x63,0x61,0x6c,0x61,0x1f,0x6c,0x70, +0x68,0x61,0x62,0x65,0x74,0x69,0x63,0x73,0x79,0x6d,0x62,0x6f,0x6c,0x73,0xa3,0xd3, +1,0x66,0x42,0x72,0x1e,0x65,0x73,0x65,0x6e,0x74,0x61,0x74,0x69,0x6f,0x6e,0x66, +0x6f,0x72,0x6d,0x73,1,0x61,0xa3,0x51,0x62,0xa3,0x55,0x14,0x65,0x6e,0x69,0x61, +0x6e,0x35,0x12,0x63,0x69,0x69,0x23,0x64,0x9e,0x65,0xa2,0x42,0x68,0xa2,0x4d,0x6c, +1,0x63,0x62,0x70,0x17,0x68,0x61,0x62,0x65,0x74,0x69,0x63,0x70,1,0x66,0xa3, +0x50,0x72,0x1e,0x65,0x73,0x65,0x6e,0x74,0x61,0x74,0x69,0x6f,0x6e,0x66,0x6f,0x72, +0x6d,0x73,0xa3,0x50,0x16,0x68,0x65,0x6d,0x69,0x63,0x61,0x6c,0xa2,0xd0,0x16,0x73, +0x79,0x6d,0x62,0x6f,0x6c,0x73,0xa3,0xd0,0x12,0x6c,0x61,0x6d,0xa5,7,0x1a,0x67, +0x65,0x61,0x6e,0x6e,0x75,0x6d,0x62,0x65,0x72,0x73,0xa3,0x77,0x11,0x6f,0x6d,0xa3, +0xfd,7,0x6f,0x71,0x6f,0x64,0x72,0xa2,0x41,0x75,0xa2,0x58,0x79,0x1b,0x7a,0x61, +0x6e,0x74,0x69,0x6e,0x65,0x6d,0x75,0x73,0x69,0x63,0xa2,0x5b,0x18,0x61,0x6c,0x73, +0x79,0x6d,0x62,0x6f,0x6c,0x73,0xa3,0x5b,1,0x70,0x34,0x78,0x16,0x64,0x72,0x61, +0x77,0x69,0x6e,0x67,0x89,0x14,0x6f,0x6d,0x6f,0x66,0x6f,0xa0,0x12,0x65,0x78,0x74, +0xa2,0x43,0x14,0x65,0x6e,0x64,0x65,0x64,0xa3,0x43,0x10,0x61,1,0x68,0x40,0x69, +0x12,0x6c,0x6c,0x65,0x92,0x17,0x70,0x61,0x74,0x74,0x65,0x72,0x6e,0x73,0x93,0x11, +0x6d,0x69,0xa3,0xc9,1,0x67,0x2c,0x68,0x11,0x69,0x64,0xa3,0x64,0x14,0x69,0x6e, +0x65,0x73,0x65,0xa3,0x81,0x61,0x48,0x65,0xa2,0x4e,0x68,0xa2,0x52,0x6c,0x1a,0x6f, +0x63,0x6b,0x65,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x73,0x8b,3,0x6c,0x34,0x6d,0x40, +0x73,0x66,0x74,0x11,0x61,0x6b,0xa3,0xc7,0x14,0x69,0x6e,0x65,0x73,0x65,0xa3,0x93, +0x11,0x75,0x6d,0xa2,0xb1,0x12,0x73,0x75,0x70,0xa2,0xca,0x16,0x70,0x6c,0x65,0x6d, +0x65,0x6e,0x74,0xa3,0xca,1,0x69,0x30,0x73,0x13,0x61,0x76,0x61,0x68,0xa3,0xdd, +0x15,0x63,0x6c,0x61,0x74,0x69,0x6e,0x23,0x14,0x6e,0x67,0x61,0x6c,0x69,0x41,0x16, +0x61,0x69,0x6b,0x73,0x75,0x6b,0x69,0xa5,8,5,0x6f,0xc1,0x4c,0x6f,0xa2,0x55, +0x75,0xa4,0x10,0x79,1,0x70,0x9c,0x72,0x14,0x69,0x6c,0x6c,0x69,0x63,0x32,1, +0x65,0x4c,0x73,0x11,0x75,0x70,0xa2,0x61,0x16,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74, +0xa2,0x61,0x12,0x61,0x72,0x79,0xa3,0x61,0x11,0x78,0x74,3,0x61,0xa3,0x9e,0x62, +0xa3,0xa0,0x63,0xa5,9,0x65,0x13,0x6e,0x64,0x65,0x64,2,0x61,0xa3,0x9e,0x62, +0xa3,0xa0,0x63,0xa5,9,0x1c,0x72,0x69,0x6f,0x74,0x73,0x79,0x6c,0x6c,0x61,0x62, +0x61,0x72,0x79,0xa3,0x7b,3,0x6d,0x5a,0x6e,0xa2,0x95,0x70,0xa2,0xa0,0x75,0x17, +0x6e,0x74,0x69,0x6e,0x67,0x72,0x6f,0x64,0xa2,0x9a,0x17,0x6e,0x75,0x6d,0x65,0x72, +0x61,0x6c,0x73,0xa3,0x9a,2,0x62,0x3a,0x6d,0xa2,0x5f,0x70,0x15,0x61,0x74,0x6a, +0x61,0x6d,0x6f,0xa3,0x41,0x14,0x69,0x6e,0x69,0x6e,0x67,2,0x64,0x46,0x68,0x9e, +0x6d,0x1d,0x61,0x72,0x6b,0x73,0x66,0x6f,0x72,0x73,0x79,0x6d,0x62,0x6f,0x6c,0x73, +0x77,0x1e,0x69,0x61,0x63,0x72,0x69,0x74,0x69,0x63,0x61,0x6c,0x6d,0x61,0x72,0x6b, +0x73,0x2e,2,0x65,0x40,0x66,0xa6,0x2a,0x73,0x18,0x75,0x70,0x70,0x6c,0x65,0x6d, +0x65,0x6e,0x74,0xa3,0x83,0x16,0x78,0x74,0x65,0x6e,0x64,0x65,0x64,0xa3,0xe0,0x17, +0x61,0x6c,0x66,0x6d,0x61,0x72,0x6b,0x73,0xa3,0x52,0x11,0x6f,0x6e,0x1f,0x69,0x6e, +0x64,0x69,0x63,0x6e,0x75,0x6d,0x62,0x65,0x72,0x66,0x6f,0x72,0x6d,0x73,0xa3,0xb2, +0x1b,0x74,0x72,0x6f,0x6c,0x70,0x69,0x63,0x74,0x75,0x72,0x65,0x73,0x83,0x12,0x74, +0x69,0x63,0xa2,0x84,0x1b,0x65,0x70,0x61,0x63,0x74,0x6e,0x75,0x6d,0x62,0x65,0x72, +0x73,0xa3,0xdf,1,0x6e,0x3e,0x72,0x1b,0x72,0x65,0x6e,0x63,0x79,0x73,0x79,0x6d, +0x62,0x6f,0x6c,0x73,0x75,0x15,0x65,0x69,0x66,0x6f,0x72,0x6d,0xa2,0x98,0x16,0x6e, +0x75,0x6d,0x62,0x65,0x72,0x73,0xa2,0x99,0x1d,0x61,0x6e,0x64,0x70,0x75,0x6e,0x63, +0x74,0x75,0x61,0x74,0x69,0x6f,0x6e,0xa3,0x99,0x61,0xa2,0xdb,0x68,0xa4,5,0x6a, +0x10,0x6b,0xa2,0x47,4,0x63,0x86,0x65,0xa2,0x7d,0x72,0xa2,0x92,0x73,0xa2,0xa4, +0x75,0x1f,0x6e,0x69,0x66,0x69,0x65,0x64,0x69,0x64,0x65,0x6f,0x67,0x72,0x61,0x70, +0x68,0x73,0xa2,0x47,0x18,0x65,0x78,0x74,0x65,0x6e,0x73,0x69,0x6f,0x6e,5,0x64, +0x65,0x64,0xa3,0xd1,0x65,0xa5,0,0x66,0xa5,0x12,0x14,0x6f,0x6d,0x70,0x61,0x74, +0xa2,0x45,1,0x66,0x96,0x69,1,0x62,0x44,0x64,0x17,0x65,0x6f,0x67,0x72,0x61, +0x70,0x68,0x73,0xa2,0x4f,0x12,0x73,0x75,0x70,0xa3,0x5f,0x14,0x69,0x6c,0x69,0x74, +0x79,0xa2,0x45,1,0x66,0x54,0x69,0x18,0x64,0x65,0x6f,0x67,0x72,0x61,0x70,0x68, +0x73,0xa2,0x4f,0x19,0x73,0x75,0x70,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0xa3,0x5f, +0x13,0x6f,0x72,0x6d,0x73,0xa3,0x53,0x11,0x78,0x74,5,0x64,9,0x64,0xa3,0xd1, +0x65,0xa5,0,0x66,0xa5,0x12,0x61,0xa3,0x46,0x62,0xa3,0x5e,0x63,0xa3,0xc5,0x19, +0x61,0x64,0x69,0x63,0x61,0x6c,0x73,0x73,0x75,0x70,0x94,0x16,0x70,0x6c,0x65,0x6d, +0x65,0x6e,0x74,0x95,1,0x74,0x50,0x79,0x14,0x6d,0x62,0x6f,0x6c,0x73,0x9a,0x1d, +0x61,0x6e,0x64,0x70,0x75,0x6e,0x63,0x74,0x75,0x61,0x74,0x69,0x6f,0x6e,0x9b,0x14, +0x72,0x6f,0x6b,0x65,0x73,0xa3,0x82,2,0x6e,0x48,0x72,0x64,0x75,0x1d,0x63,0x61, +0x73,0x69,0x61,0x6e,0x61,0x6c,0x62,0x61,0x6e,0x69,0x61,0x6e,0xa3,0xde,0x1d,0x61, +0x64,0x69,0x61,0x6e,0x73,0x79,0x6c,0x6c,0x61,0x62,0x69,0x63,0x73,0x63,0x12,0x69, +0x61,0x6e,0xa3,0xa8,1,0x61,0x6c,0x65,1,0x72,0x38,0x73,0x17,0x73,0x73,0x79, +0x6d,0x62,0x6f,0x6c,0x73,0xa5,0x19,0x13,0x6f,0x6b,0x65,0x65,0x60,0x12,0x73,0x75, +0x70,0xa2,0xff,0x16,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0xa3,0xff,1,0x6b,0x26, +0x6d,0xa3,0xa4,0x11,0x6d,0x61,0xa3,0xd4,3,0x65,0x3e,0x69,0x7e,0x6f,0xa2,0x5d, +0x75,0x15,0x70,0x6c,0x6f,0x79,0x61,0x6e,0xa3,0xe1,1,0x73,0x50,0x76,0x16,0x61, +0x6e,0x61,0x67,0x61,0x72,0x69,0x3e,0x12,0x65,0x78,0x74,0xa2,0xb3,0x14,0x65,0x6e, +0x64,0x65,0x64,0xa3,0xb3,0x13,0x65,0x72,0x65,0x74,0xa3,0x5a,1,0x61,0x30,0x6e, +0x14,0x67,0x62,0x61,0x74,0x73,0x91,0x18,0x63,0x72,0x69,0x74,0x69,0x63,0x61,0x6c, +0x73,0x2e,2,0x65,0x30,0x66,0x36,0x73,0x11,0x75,0x70,0xa3,0x83,0x11,0x78,0x74, +0xa3,0xe0,0x18,0x6f,0x72,0x73,0x79,0x6d,0x62,0x6f,0x6c,0x73,0x77,1,0x67,0x3e, +0x6d,0x12,0x69,0x6e,0x6f,0xa2,0xab,0x14,0x74,0x69,0x6c,0x65,0x73,0xa3,0xab,0x11, +0x72,0x61,0xa5,0x1a,8,0x6d,0x5f,0x6d,0x3a,0x6e,0x48,0x73,0x7a,0x76,0xa2,0x4b, +0x77,0x12,0x69,0x64,0x65,0x43,0x11,0x65,0x64,0x32,0x12,0x69,0x61,0x6c,0x33,2, +0x61,0x40,0x62,0x37,0x6f,1,0x62,0x28,0x6e,0x10,0x65,0x21,0x13,0x72,0x65,0x61, +0x6b,0x37,0x10,0x72,0x34,0x12,0x72,0x6f,0x77,0x35,2,0x6d,0x38,0x71,0x46,0x75, +1,0x62,0x3d,0x70,0x3e,0x11,0x65,0x72,0x3f,1,0x61,0x24,0x6c,0x39,0x11,0x6c, +0x6c,0x39,1,0x72,0x3b,0x75,0x12,0x61,0x72,0x65,0x3b,0x12,0x65,0x72,0x74,0x40, +0x13,0x69,0x63,0x61,0x6c,0x41,0x63,0x58,0x65,0x92,0x66,0x96,0x69,1,0x6e,0x36, +0x73,0x10,0x6f,0x30,0x14,0x6c,0x61,0x74,0x65,0x64,0x31,0x11,0x69,0x74,0x2e,0x12, +0x69,0x61,0x6c,0x2f,2,0x61,0x36,0x69,0x48,0x6f,0x10,0x6d,0x24,0x12,0x70,0x61, +0x74,0x25,0x10,0x6e,0x22,0x15,0x6f,0x6e,0x69,0x63,0x61,0x6c,0x23,0x13,0x72,0x63, +0x6c,0x65,0x27,0x11,0x6e,0x63,0x27,2,0x69,0x3a,0x6f,0x44,0x72,0x10,0x61,0x2c, +0x14,0x63,0x74,0x69,0x6f,0x6e,0x2d,0x10,0x6e,0x28,0x11,0x61,0x6c,0x29,0x11,0x6e, +0x74,0x2b,4,0x61,0x3a,0x66,0x4c,0x68,0x5e,0x6e,0x70,0x77,0x2a,0x12,0x69,0x64, +0x65,0x2b,0x22,0x17,0x6d,0x62,0x69,0x67,0x75,0x6f,0x75,0x73,0x23,0x26,0x17,0x75, +0x6c,0x6c,0x77,0x69,0x64,0x74,0x68,0x27,0x24,0x17,0x61,0x6c,0x66,0x77,0x69,0x64, +0x74,0x68,0x25,0x20,1,0x61,0x30,0x65,0x14,0x75,0x74,0x72,0x61,0x6c,0x21,0x28, +0x13,0x72,0x72,0x6f,0x77,0x29,0xd,0x6e,0xc0,0xfb,0x73,0x6d,0x73,0x3a,0x74,0x98, +0x75,0xa2,0x49,0x7a,2,0x6c,0x3b,0x70,0x3d,0x73,0x39,5,0x6f,0x28,0x6f,0x57, +0x70,0x34,0x75,0x16,0x72,0x72,0x6f,0x67,0x61,0x74,0x65,0x45,0x11,0x61,0x63,1, +0x65,0x32,0x69,0x15,0x6e,0x67,0x6d,0x61,0x72,0x6b,0x31,0x18,0x73,0x65,0x70,0x61, +0x72,0x61,0x74,0x6f,0x72,0x39,0x63,0x53,0x6b,0x55,0x6d,0x51,0x1d,0x69,0x74,0x6c, +0x65,0x63,0x61,0x73,0x65,0x6c,0x65,0x74,0x74,0x65,0x72,0x27,1,0x6e,0x40,0x70, +0x1c,0x70,0x65,0x72,0x63,0x61,0x73,0x65,0x6c,0x65,0x74,0x74,0x65,0x72,0x23,0x17, +0x61,0x73,0x73,0x69,0x67,0x6e,0x65,0x64,0x21,0x6e,0x8a,0x6f,0xa2,0x47,0x70,8, +0x66,0x14,0x66,0x5b,0x69,0x59,0x6f,0x4f,0x72,0x24,0x73,0x49,0x17,0x69,0x76,0x61, +0x74,0x65,0x75,0x73,0x65,0x43,0x61,0x2c,0x63,0x4d,0x64,0x47,0x65,0x4b,0x1f,0x72, +0x61,0x67,0x72,0x61,0x70,0x68,0x73,0x65,0x70,0x61,0x72,0x61,0x74,0x6f,0x72,0x3d, +2,0x64,0x33,0x6c,0x35,0x6f,0x36,0x1b,0x6e,0x73,0x70,0x61,0x63,0x69,0x6e,0x67, +0x6d,0x61,0x72,0x6b,0x2d,1,0x70,0x7c,0x74,0x12,0x68,0x65,0x72,3,0x6c,0x38, +0x6e,0x42,0x70,0x4c,0x73,0x14,0x79,0x6d,0x62,0x6f,0x6c,0x57,0x14,0x65,0x74,0x74, +0x65,0x72,0x2b,0x14,0x75,0x6d,0x62,0x65,0x72,0x37,0x19,0x75,0x6e,0x63,0x74,0x75, +0x61,0x74,0x69,0x6f,0x6e,0x4f,0x1c,0x65,0x6e,0x70,0x75,0x6e,0x63,0x74,0x75,0x61, +0x74,0x69,0x6f,0x6e,0x49,0x66,0x9e,0x66,0x88,0x69,0xa2,0x4b,0x6c,0xa2,0x5c,0x6d, +4,0x61,0x60,0x63,0x31,0x65,0x2f,0x6e,0x2d,0x6f,0x15,0x64,0x69,0x66,0x69,0x65, +0x72,1,0x6c,0x30,0x73,0x14,0x79,0x6d,0x62,0x6f,0x6c,0x55,0x14,0x65,0x74,0x74, +0x65,0x72,0x29,0x17,0x74,0x68,0x73,0x79,0x6d,0x62,0x6f,0x6c,0x51,1,0x69,0x2e, +0x6f,0x13,0x72,0x6d,0x61,0x74,0x41,0x1d,0x6e,0x61,0x6c,0x70,0x75,0x6e,0x63,0x74, +0x75,0x61,0x74,0x69,0x6f,0x6e,0x5b,0x10,0x6e,0x1f,0x69,0x74,0x69,0x61,0x6c,0x70, +0x75,0x6e,0x63,0x74,0x75,0x61,0x74,0x69,0x6f,0x6e,0x59,6,0x6d,0x18,0x6d,0x29, +0x6f,0x28,0x74,0x27,0x75,0x23,0x2a,0x1c,0x77,0x65,0x72,0x63,0x61,0x73,0x65,0x6c, +0x65,0x74,0x74,0x65,0x72,0x25,0x65,0x28,0x69,0x3c,0x6c,0x25,0x19,0x74,0x74,0x65, +0x72,0x6e,0x75,0x6d,0x62,0x65,0x72,0x35,0x1a,0x6e,0x65,0x73,0x65,0x70,0x61,0x72, +0x61,0x74,0x6f,0x72,0x3b,0x63,0x44,0x64,0xa2,0x60,0x65,0x1b,0x6e,0x63,0x6c,0x6f, +0x73,0x69,0x6e,0x67,0x6d,0x61,0x72,0x6b,0x2f,6,0x6e,0x39,0x6e,0x46,0x6f,0x4e, +0x73,0x45,0x75,0x1b,0x72,0x72,0x65,0x6e,0x63,0x79,0x73,0x79,0x6d,0x62,0x6f,0x6c, +0x53,0x20,0x12,0x74,0x72,0x6c,0x3f,0x42,0x10,0x6e,1,0x6e,0x2c,0x74,0x12,0x72, +0x6f,0x6c,0x3f,0x1f,0x65,0x63,0x74,0x6f,0x72,0x70,0x75,0x6e,0x63,0x74,0x75,0x61, +0x74,0x69,0x6f,0x6e,0x4d,0x63,0x3f,0x66,0x41,0x6c,0x1d,0x6f,0x73,0x65,0x70,0x75, +0x6e,0x63,0x74,0x75,0x61,0x74,0x69,0x6f,0x6e,0x4b,2,0x61,0x30,0x65,0x4a,0x69, +0x12,0x67,0x69,0x74,0x33,0x1c,0x73,0x68,0x70,0x75,0x6e,0x63,0x74,0x75,0x61,0x74, +0x69,0x6f,0x6e,0x47,0x1a,0x63,0x69,0x6d,0x61,0x6c,0x6e,0x75,0x6d,0x62,0x65,0x72, +0x33,0,0x12,0x6d,0xc2,0x3f,0x73,0xa1,0x73,0x4e,0x74,0xa2,0x56,0x77,0xa2,0x72, +0x79,0xa2,0x73,0x7a,1,0x61,0x2c,0x68,0x12,0x61,0x69,0x6e,0x8b,0x11,0x69,0x6e, +0x85,5,0x74,0x22,0x74,0x38,0x77,0x4c,0x79,0x16,0x72,0x69,0x61,0x63,0x77,0x61, +0x77,0x6f,0x18,0x72,0x61,0x69,0x67,0x68,0x74,0x77,0x61,0x77,0xa3,0x55,0x15,0x61, +0x73,0x68,0x6b,0x61,0x66,0x6d,0x61,0x2e,0x65,0x38,0x68,0x11,0x69,0x6e,0x6b,0x10, +0x64,0x62,0x11,0x68,0x65,0x65,1,0x65,0x2e,0x6d,0x13,0x6b,0x61,0x74,0x68,0x69, +0x10,0x6e,0x67,1,0x61,0x4e,0x65,1,0x68,0x28,0x74,0x10,0x68,0x77,0x16,0x6d, +0x61,0x72,0x62,0x75,0x74,0x61,0x74,0x13,0x67,0x6f,0x61,0x6c,0x3d,1,0x68,0x71, +0x77,0x73,0x11,0x61,0x77,0x79,1,0x65,0x32,0x75,0x11,0x64,0x68,0x80,0x11,0x68, +0x65,0x83,0x10,0x68,0x7a,1,0x62,0x34,0x77,0x16,0x69,0x74,0x68,0x74,0x61,0x69, +0x6c,0x7f,0x14,0x61,0x72,0x72,0x65,0x65,0x7d,0x6d,0x6c,0x6e,0xa4,0x6b,0x70,0xa4, +0x88,0x71,0xa4,0x88,0x72,1,0x65,0x38,0x6f,0x18,0x68,0x69,0x6e,0x67,0x79,0x61, +0x79,0x65,0x68,0x93,1,0x68,0x5f,0x76,0x16,0x65,0x72,0x73,0x65,0x64,0x70,0x65, +0x61,2,0x61,0x2e,0x65,0xa4,0x3e,0x69,0x10,0x6d,0x53,1,0x6c,0xa2,0xe7,0x6e, +0x16,0x69,0x63,0x68,0x61,0x65,0x61,0x6e,0,0x12,0x6e,0x76,0x73,0x51,0x73,0x3e, +0x74,0x5c,0x77,0xa0,0x79,0xa2,0x42,0x7a,0x13,0x61,0x79,0x69,0x6e,0xa3,0x54,0x10, +0x61,1,0x64,0x2e,0x6d,0x12,0x65,0x6b,0x68,0xa3,0x4c,0x11,0x68,0x65,0xa3,0x4b, +3,0x61,0x38,0x65,0x3c,0x68,0x4a,0x77,0x13,0x65,0x6e,0x74,0x79,0xa3,0x51,0x10, +0x77,0xa3,0x4d,1,0x6e,0xa3,0x4e,0x74,0x10,0x68,0xa3,0x4f,0x14,0x61,0x6d,0x65, +0x64,0x68,0xa3,0x50,0x11,0x61,0x77,0xa3,0x52,0x12,0x6f,0x64,0x68,0xa3,0x53,0x6e, +0x3a,0x6f,0x40,0x70,0x46,0x71,0x4a,0x72,0x12,0x65,0x73,0x68,0xa3,0x4a,0x11,0x75, +0x6e,0xa3,0x46,0x11,0x6e,0x65,0xa3,0x47,0x10,0x65,0xa3,0x48,0x12,0x6f,0x70,0x68, +0xa3,0x49,0x67,0x33,0x67,0x38,0x68,0x40,0x6b,0x5e,0x6c,0x66,0x6d,0x11,0x65,0x6d, +0xa3,0x45,0x13,0x69,0x6d,0x65,0x6c,0xa1,1,0x65,0x32,0x75,0x14,0x6e,0x64,0x72, +0x65,0x64,0xa3,0x42,0x11,0x74,0x68,0xa3,0x41,0x12,0x61,0x70,0x68,0xa3,0x43,0x14, +0x61,0x6d,0x65,0x64,0x68,0xa3,0x44,0x61,0x34,0x62,0x4a,0x64,0x50,0x66,0x12,0x69, +0x76,0x65,0x9f,1,0x6c,0x2a,0x79,0x11,0x69,0x6e,0x97,0x12,0x65,0x70,0x68,0x95, +0x12,0x65,0x74,0x68,0x99,1,0x61,0x30,0x68,0x14,0x61,0x6d,0x65,0x64,0x68,0x9d, +0x13,0x6c,0x65,0x74,0x68,0x9b,0x15,0x61,0x79,0x61,0x6c,0x61,0x6d,6,0x6e,0x2c, +0x6e,0x34,0x72,0x5e,0x73,0x62,0x74,0x11,0x74,0x61,0xa3,0x63,2,0x67,0x2e,0x6e, +0x32,0x79,0x10,0x61,0xa3,0x60,0x10,0x61,0xa3,0x5d,1,0x61,0xa3,0x5e,0x6e,0x10, +0x61,0xa3,0x5f,0x10,0x61,0xa3,0x61,0x11,0x73,0x61,0xa3,0x62,0x62,0x3c,0x6a,0x42, +0x6c,0x10,0x6c,1,0x61,0xa3,0x5b,0x6c,0x10,0x61,0xa3,0x5c,0x11,0x68,0x61,0xa3, +0x59,0x10,0x61,0xa3,0x5a,0x11,0x65,0x6d,0x51,2,0x6f,0x2c,0x75,0x50,0x79,0x10, +0x61,0x91,1,0x6a,0x28,0x6f,0x10,0x6e,0x55,0x1a,0x6f,0x69,0x6e,0x69,0x6e,0x67, +0x67,0x72,0x6f,0x75,0x70,0x21,0x10,0x6e,0x57,0x10,0x65,0x59,0x10,0x61,1,0x66, +0x5b,0x70,0x10,0x68,0x5d,0x66,0x9a,0x66,0x42,0x67,0x7a,0x68,0x8a,0x6b,0xa2,0x75, +0x6c,0x11,0x61,0x6d,0x4c,0x12,0x61,0x64,0x68,0x4f,2,0x61,0x3e,0x65,0x4a,0x69, +0x19,0x6e,0x61,0x6c,0x73,0x65,0x6d,0x6b,0x61,0x74,0x68,0x35,0x15,0x72,0x73,0x69, +0x79,0x65,0x68,0x8f,0x86,0x10,0x68,0x33,0x10,0x61,1,0x66,0x37,0x6d,0x11,0x61, +0x6c,0x39,1,0x61,0x40,0x65,0x3e,1,0x68,0x28,0x74,0x10,0x68,0x45,0x40,0x13, +0x67,0x6f,0x61,0x6c,0x43,2,0x68,0x3b,0x6d,0x5c,0x6e,0x1a,0x69,0x66,0x69,0x72, +0x6f,0x68,0x69,0x6e,0x67,0x79,0x61,1,0x6b,0x2a,0x70,0x10,0x61,0xa3,0x65,0x15, +0x69,0x6e,0x6e,0x61,0x79,0x61,0xa3,0x64,0x1a,0x7a,0x61,0x6f,0x6e,0x68,0x65,0x68, +0x67,0x6f,0x61,0x6c,0x3d,2,0x61,0x3a,0x68,0x44,0x6e,0x17,0x6f,0x74,0x74,0x65, +0x64,0x68,0x65,0x68,0x4b,1,0x66,0x47,0x70,0x10,0x68,0x49,0x12,0x61,0x70,0x68, +0x89,0x61,0x2e,0x62,0x8a,0x64,0xa2,0x51,0x65,0x31,2,0x66,0x3c,0x69,0x70,0x6c, +1,0x61,0x28,0x65,0x10,0x66,0x27,0x11,0x70,0x68,0x25,0x14,0x72,0x69,0x63,0x61, +0x6e,2,0x66,0x30,0x6e,0x36,0x71,0x11,0x61,0x66,0xa3,0x58,0x11,0x65,0x68,0xa3, +0x56,0x12,0x6f,0x6f,0x6e,0xa3,0x57,0x10,0x6e,0x23,1,0x65,0x4a,0x75,0x10,0x72, +0x1f,0x75,0x73,0x68,0x61,0x73,0x6b,0x69,0x79,0x65,0x68,0x62,0x61,0x72,0x72,0x65, +0x65,0x8d,1,0x68,0x29,0x74,0x10,0x68,0x2b,0x11,0x61,0x6c,0x2c,0x16,0x61,0x74, +0x68,0x72,0x69,0x73,0x68,0x2f,7,0x6e,0x2e,0x6e,0x2c,0x72,0x3e,0x74,0x56,0x75, +0x21,0x18,0x6f,0x6e,0x6a,0x6f,0x69,0x6e,0x69,0x6e,0x67,0x21,0x28,0x1a,0x69,0x67, +0x68,0x74,0x6a,0x6f,0x69,0x6e,0x69,0x6e,0x67,0x29,0x2a,0x19,0x72,0x61,0x6e,0x73, +0x70,0x61,0x72,0x65,0x6e,0x74,0x2b,0x63,0x23,0x64,0x40,0x6a,0x56,0x6c,0x26,0x19, +0x65,0x66,0x74,0x6a,0x6f,0x69,0x6e,0x69,0x6e,0x67,0x27,0x24,0x19,0x75,0x61,0x6c, +0x6a,0x6f,0x69,0x6e,0x69,0x6e,0x67,0x25,0x19,0x6f,0x69,0x6e,0x63,0x61,0x75,0x73, +0x69,0x6e,0x67,0x23,0,0x13,0x6e,0xc0,0xd0,0x73,0x49,0x73,0x48,0x75,0x78,0x77, +0x84,0x78,0x9c,0x7a,0x10,0x77,0x58,1,0x6a,0x75,0x73,0x13,0x70,0x61,0x63,0x65, +0x59,4,0x61,0x51,0x67,0x53,0x70,0x28,0x75,0x30,0x79,0x57,0x54,0x12,0x61,0x63, +0x65,0x55,0x16,0x72,0x72,0x6f,0x67,0x61,0x74,0x65,0x53,0x15,0x6e,0x6b,0x6e,0x6f, +0x77,0x6e,0x21,1,0x6a,0x5d,0x6f,0x17,0x72,0x64,0x6a,0x6f,0x69,0x6e,0x65,0x72, +0x5d,0x10,0x78,0x21,0x6e,0x60,0x6f,0xa2,0x41,0x70,0xa2,0x50,0x71,0xa2,0x6e,0x72, +1,0x65,0x24,0x69,0x6f,0x1e,0x67,0x69,0x6f,0x6e,0x61,0x6c,0x69,0x6e,0x64,0x69, +0x63,0x61,0x74,0x6f,0x72,0x6f,4,0x65,0x3e,0x6c,0x5b,0x6f,0x46,0x73,0x45,0x75, +0x46,0x14,0x6d,0x65,0x72,0x69,0x63,0x47,0x15,0x78,0x74,0x6c,0x69,0x6e,0x65,0x5b, +0x17,0x6e,0x73,0x74,0x61,0x72,0x74,0x65,0x72,0x45,0x10,0x70,0x48,0x1c,0x65,0x6e, +0x70,0x75,0x6e,0x63,0x74,0x75,0x61,0x74,0x69,0x6f,0x6e,0x49,1,0x6f,0x3e,0x72, +0x4c,0x1a,0x65,0x66,0x69,0x78,0x6e,0x75,0x6d,0x65,0x72,0x69,0x63,0x4d,0x4a,0x1b, +0x73,0x74,0x66,0x69,0x78,0x6e,0x75,0x6d,0x65,0x72,0x69,0x63,0x4b,0x10,0x75,0x4e, +0x16,0x6f,0x74,0x61,0x74,0x69,0x6f,0x6e,0x4f,0x68,0x7b,0x68,0x50,0x69,0x86,0x6a, +0xa2,0x61,0x6c,0xa2,0x65,0x6d,0x1c,0x61,0x6e,0x64,0x61,0x74,0x6f,0x72,0x79,0x62, +0x72,0x65,0x61,0x6b,0x2d,4,0x32,0x5f,0x33,0x61,0x65,0x34,0x6c,0x6d,0x79,0x3a, +0x13,0x70,0x68,0x65,0x6e,0x3b,0x19,0x62,0x72,0x65,0x77,0x6c,0x65,0x74,0x74,0x65, +0x72,0x6d,2,0x64,0x28,0x6e,0x3c,0x73,0x41,0x3c,0x18,0x65,0x6f,0x67,0x72,0x61, +0x70,0x68,0x69,0x63,0x3d,0x3e,1,0x66,0x3e,0x73,0x11,0x65,0x70,1,0x61,0x22, +0x65,0x14,0x72,0x61,0x62,0x6c,0x65,0x3f,0x18,0x69,0x78,0x6e,0x75,0x6d,0x65,0x72, +0x69,0x63,0x41,2,0x6c,0x63,0x74,0x65,0x76,0x67,1,0x66,0x43,0x69,0x15,0x6e, +0x65,0x66,0x65,0x65,0x64,0x43,0x61,0x40,0x62,0x70,0x63,0xa2,0x55,0x65,0xa2,0xdb, +0x67,0x10,0x6c,0x38,0x11,0x75,0x65,0x39,2,0x69,0x23,0x6c,0x34,0x6d,0x16,0x62, +0x69,0x67,0x75,0x6f,0x75,0x73,0x23,0x24,0x17,0x70,0x68,0x61,0x62,0x65,0x74,0x69, +0x63,0x25,4,0x32,0x27,0x61,0x29,0x62,0x2b,0x6b,0x2d,0x72,0x12,0x65,0x61,0x6b, +2,0x61,0x36,0x62,0x3e,0x73,0x15,0x79,0x6d,0x62,0x6f,0x6c,0x73,0x57,0x13,0x66, +0x74,0x65,0x72,0x29,1,0x65,0x2a,0x6f,0x11,0x74,0x68,0x27,0x13,0x66,0x6f,0x72, +0x65,0x2b,7,0x6d,0x51,0x6d,0x33,0x6f,0x28,0x70,0x69,0x72,0x35,1,0x6d,0x76, +0x6e,1,0x64,0x3c,0x74,0x1a,0x69,0x6e,0x67,0x65,0x6e,0x74,0x62,0x72,0x65,0x61, +0x6b,0x2f,0x15,0x69,0x74,0x69,0x6f,0x6e,0x61,0x1f,0x6c,0x6a,0x61,0x70,0x61,0x6e, +0x65,0x73,0x65,0x73,0x74,0x61,0x72,0x74,0x65,0x72,0x6b,1,0x62,0x3a,0x70,0x19, +0x6c,0x65,0x78,0x63,0x6f,0x6e,0x74,0x65,0x78,0x74,0x51,0x18,0x69,0x6e,0x69,0x6e, +0x67,0x6d,0x61,0x72,0x6b,0x33,0x61,0x6a,0x62,0x2f,0x6a,0x6b,0x6c,0x30,0x13,0x6f, +0x73,0x65,0x70,1,0x61,0x38,0x75,0x18,0x6e,0x63,0x74,0x75,0x61,0x74,0x69,0x6f, +0x6e,0x31,0x18,0x72,0x65,0x6e,0x74,0x68,0x65,0x73,0x69,0x73,0x69,0x1b,0x72,0x72, +0x69,0x61,0x67,0x65,0x72,0x65,0x74,0x75,0x72,0x6e,0x35,2,0x62,0x3e,0x6d,0x46, +0x78,0x36,0x18,0x63,0x6c,0x61,0x6d,0x61,0x74,0x69,0x6f,0x6e,0x37,0x70,0x12,0x61, +0x73,0x65,0x71,0x72,0x16,0x6f,0x64,0x69,0x66,0x69,0x65,0x72,0x73,1,0x64,0x42, +0x6e,1,0x6f,0x32,0x75,0x26,0x14,0x6d,0x65,0x72,0x69,0x63,0x27,0x11,0x6e,0x65, +0x21,1,0x65,0x2e,0x69,0x24,0x12,0x67,0x69,0x74,0x25,0x22,0x14,0x63,0x69,0x6d, +0x61,0x6c,0x23,0,0x18,0x6e,0xc3,0xe6,0x74,0xc1,0x51,0x77,0x7a,0x77,0xa2,0x4c, +0x78,0xa2,0x60,0x79,0xa2,0x6a,0x7a,6,0x73,0x1e,0x73,0x34,0x78,0x42,0x79,0x48, +0x7a,0x11,0x7a,0x7a,0xa3,0x67,0x10,0x79,1,0x65,0xa3,0xae,0x6d,0xa3,0x81,0x11, +0x78,0x78,0xa3,0x66,0x11,0x79,0x79,0x21,0x61,0x30,0x69,0x58,0x6d,0x11,0x74,0x68, +0xa3,0x80,0x10,0x6e,1,0x61,0x26,0x62,0xa3,0xb1,0x1a,0x62,0x61,0x7a,0x61,0x72, +0x73,0x71,0x75,0x61,0x72,0x65,0xa3,0xb1,0x11,0x6e,0x68,0x23,1,0x61,0x2c,0x6f, +0x11,0x6c,0x65,0xa3,0x9b,0x11,0x72,0x61,0xa2,0x92,0x15,0x6e,0x67,0x63,0x69,0x74, +0x69,0xa3,0x92,1,0x70,0x2c,0x73,0x11,0x75,0x78,0xa3,0x65,0x11,0x65,0x6f,0x9b, +0x10,0x69,0x72,0x11,0x69,0x69,0x73,0x74,0x4a,0x75,0xa2,0xba,0x76,1,0x61,0x2c, +0x69,0x11,0x73,0x70,0xa3,0x64,0x10,0x69,0xa2,0x63,0x10,0x69,0xa3,0x63,5,0x67, +0x36,0x67,0x68,0x68,0x6c,0x69,2,0x62,0x3a,0x66,0x4a,0x72,0x10,0x68,0xa2,0x9e, +0x12,0x75,0x74,0x61,0xa3,0x9e,1,0x65,0x24,0x74,0x6f,0x12,0x74,0x61,0x6e,0x6f, +0x14,0x69,0x6e,0x61,0x67,0x68,0x99,0x11,0x6c,0x67,0x75,0x10,0x61,1,0x61,0x24, +0x69,0x6d,0x6a,0x11,0x6e,0x61,0x6b,0x61,0x30,0x65,0xa2,0x5b,0x66,0x11,0x6e,0x67, +0x99,6,0x6c,0x21,0x6c,0x32,0x6d,0x38,0x6e,0x44,0x76,0x10,0x74,0xa3,0x7f,1, +0x65,0x89,0x75,0x97,1,0x69,0x24,0x6c,0x67,0x10,0x6c,0x67,0x10,0x67,0xa2,0x9a, +0x11,0x75,0x74,0xa3,0x9a,0x67,0x36,0x69,0x52,0x6b,0x10,0x72,0xa2,0x99,0x10,0x69, +0xa3,0x99,1,0x61,0x30,0x62,0x7a,0x13,0x61,0x6e,0x77,0x61,0x7b,0x12,0x6c,0x6f, +0x67,0x75,2,0x6c,0x32,0x74,0x34,0x76,0x12,0x69,0x65,0x74,0xa3,0x7f,0x10,0x65, +0x89,0x12,0x68,0x61,0x6d,0xa3,0x6a,1,0x6c,0x2a,0x6e,0x10,0x67,0xa3,0x62,0x10, +0x75,0x68,0x11,0x67,0x75,0x69,1,0x67,0x32,0x6e,0x14,0x6b,0x6e,0x6f,0x77,0x6e, +0xa3,0x67,0x11,0x61,0x72,0x8a,0x13,0x69,0x74,0x69,0x63,0x8b,0x71,0xc1,0x13,0x71, +0xa2,0xde,0x72,0xa2,0xe3,0x73,6,0x69,0x8a,0x69,0x72,0x6f,0xa2,0x4c,0x75,0xa2, +0x75,0x79,1,0x6c,0x46,0x72,4,0x63,0x65,0x65,0xa3,0x5f,0x69,0x2c,0x6a,0xa3, +0x60,0x6e,0xa3,0x61,0x11,0x61,0x63,0x65,0x10,0x6f,0x94,0x16,0x74,0x69,0x6e,0x61, +0x67,0x72,0x69,0x95,2,0x64,0x3c,0x67,0x4c,0x6e,1,0x64,0xa3,0x91,0x68,0x62, +0x12,0x61,0x6c,0x61,0x63,0x10,0x64,0xa2,0xa6,0x12,0x68,0x61,0x6d,0xa3,0xa6,0x17, +0x6e,0x77,0x72,0x69,0x74,0x69,0x6e,0x67,0xa3,0x70,2,0x67,0x3a,0x72,0x52,0x79, +0x10,0x6f,0xa2,0xb0,0x12,0x6d,0x62,0x6f,0xa3,0xb0,1,0x64,0x26,0x6f,0xa3,0xb8, +0xa2,0xb7,0x12,0x69,0x61,0x6e,0xa3,0xb7,0x10,0x61,0xa2,0x98,0x16,0x73,0x6f,0x6d, +0x70,0x65,0x6e,0x67,0xa3,0x98,0x11,0x6e,0x64,0xa2,0x71,0x14,0x61,0x6e,0x65,0x73, +0x65,0xa3,0x71,0x61,0x5c,0x67,0xa2,0x43,0x68,1,0x61,0x2a,0x72,0x10,0x64,0xa3, +0x97,2,0x72,0x28,0x76,0x30,0x77,0x87,0x12,0x61,0x64,0x61,0xa3,0x97,0x12,0x69, +0x61,0x6e,0x87,2,0x6d,0x40,0x72,0x58,0x75,0x10,0x72,0xa2,0x6f,0x15,0x61,0x73, +0x68,0x74,0x72,0x61,0xa3,0x6f,1,0x61,0x26,0x72,0xa3,0x7e,0x14,0x72,0x69,0x74, +0x61,0x6e,0xa3,0x7e,1,0x61,0xa3,0x5e,0x62,0xa3,0x85,0x11,0x6e,0x77,0xa3,0x70, +0x11,0x61,0x61,1,0x63,0x2f,0x69,0x23,3,0x65,0x3e,0x6a,0x48,0x6f,0x4e,0x75, +0x10,0x6e,1,0x69,0x24,0x72,0x61,0x10,0x63,0x61,0x13,0x6a,0x61,0x6e,0x67,0xa3, +0x6e,0x11,0x6e,0x67,0xa3,0x6e,1,0x68,0x2a,0x72,0x10,0x6f,0xa3,0x5d,0x10,0x67, +0xa3,0xb6,0x6e,0xa2,0x83,0x6f,0xa2,0xca,0x70,5,0x6c,0x1e,0x6c,0x44,0x72,0x4a, +0x73,0x1b,0x61,0x6c,0x74,0x65,0x72,0x70,0x61,0x68,0x6c,0x61,0x76,0x69,0xa3,0x7b, +0x11,0x72,0x64,0xa3,0x5c,0x11,0x74,0x69,0xa3,0x7d,0x61,0x7c,0x65,0xa2,0x54,0x68, +3,0x61,0x3e,0x6c,0x4e,0x6e,0x5e,0x6f,0x16,0x65,0x6e,0x69,0x63,0x69,0x61,0x6e, +0xa3,0x5b,0x10,0x67,0xa2,0x5a,0x12,0x73,0x70,0x61,0xa3,0x5a,2,0x69,0xa3,0x7a, +0x70,0xa3,0x7b,0x76,0xa3,0x7c,0x10,0x78,0xa3,0x5b,2,0x68,0x3e,0x6c,0x50,0x75, +0x10,0x63,0xa2,0xa5,0x14,0x69,0x6e,0x68,0x61,0x75,0xa3,0xa5,0x17,0x61,0x77,0x68, +0x68,0x6d,0x6f,0x6e,0x67,0xa3,0x4b,0x10,0x6d,0xa2,0x90,0x14,0x79,0x72,0x65,0x6e, +0x65,0xa3,0x90,0x11,0x72,0x6d,0xa3,0x59,5,0x6b,0x1e,0x6b,0x32,0x73,0x4a,0x75, +0x12,0x73,0x68,0x75,0xa3,0x96,1,0x67,0x2e,0x6f,0xa2,0x57,0x10,0x6f,0xa3,0x57, +0x10,0x62,0xa3,0x84,0x11,0x68,0x75,0xa3,0x96,0x61,0x42,0x62,0x60,0x65,0x10,0x77, +1,0x61,0xa3,0xaa,0x74,0x14,0x61,0x69,0x6c,0x75,0x65,0x97,1,0x62,0x2a,0x72, +0x10,0x62,0xa3,0x8e,0x15,0x61,0x74,0x61,0x65,0x61,0x6e,0xa3,0x8f,0x11,0x61,0x74, +0xa3,0x8f,3,0x67,0x5a,0x6c,0x6c,0x72,0xa2,0x93,0x73,2,0x61,0x36,0x67,0x3c, +0x6d,0x10,0x61,0x84,0x12,0x6e,0x79,0x61,0x85,0x11,0x67,0x65,0xa3,0xab,0x10,0x65, +0xa3,0xab,1,0x61,0x2a,0x68,0x11,0x61,0x6d,0x5b,0x10,0x6d,0x5b,1,0x63,0xa2, +0x60,0x64,5,0x70,0x37,0x70,0x36,0x73,0x54,0x74,0x14,0x75,0x72,0x6b,0x69,0x63, +0xa3,0x58,0x11,0x65,0x72,1,0x6d,0x2c,0x73,0x12,0x69,0x61,0x6e,0x9b,0x11,0x69, +0x63,0xa3,0x59,0x10,0x6f,1,0x67,0x3a,0x75,0x18,0x74,0x68,0x61,0x72,0x61,0x62, +0x69,0x61,0x6e,0xa3,0x85,0x13,0x64,0x69,0x61,0x6e,0xa3,0xb8,0x68,0x42,0x69,0x54, +0x6e,0x1a,0x6f,0x72,0x74,0x68,0x61,0x72,0x61,0x62,0x69,0x61,0x6e,0xa3,0x8e,0x17, +0x75,0x6e,0x67,0x61,0x72,0x69,0x61,0x6e,0xa3,0x4c,0x14,0x74,0x61,0x6c,0x69,0x63, +0x5d,1,0x68,0x26,0x6b,0xa3,0x6d,0x12,0x69,0x6b,0x69,0xa3,0x6d,2,0x69,0x2c, +0x6b,0x30,0x79,0x10,0x61,0x5f,0x11,0x79,0x61,0x5f,0x10,0x68,0xa3,0x58,0x68,0xc2, +0xef,0x6b,0xc2,0xa,0x6b,0xa4,0x17,0x6c,0xa4,0x98,0x6d,8,0x6f,0x46,0x6f,0x48, +0x72,0x74,0x74,0x80,0x75,0x86,0x79,1,0x61,0x28,0x6d,0x10,0x72,0x59,0x13,0x6e, +0x6d,0x61,0x72,0x59,2,0x64,0x2e,0x6e,0x32,0x6f,0x10,0x6e,0xa3,0x72,0x10,0x69, +0xa3,0xa3,0x10,0x67,0x56,0x14,0x6f,0x6c,0x69,0x61,0x6e,0x57,0x10,0x6f,0xa2,0x95, +0x10,0x6f,0xa3,0x95,0x11,0x65,0x69,0xa3,0x73,0x11,0x6c,0x74,0xa2,0xa4,0x12,0x61, +0x6e,0x69,0xa3,0xa4,0x61,0x36,0x65,0xa2,0x67,0x69,0xa2,0xbd,0x6c,0x11,0x79,0x6d, +0x55,6,0x6e,0x38,0x6e,0x32,0x72,0x5c,0x73,0x6c,0x79,0x10,0x61,0xa3,0x55,1, +0x64,0x38,0x69,0xa2,0x79,0x15,0x63,0x68,0x61,0x65,0x61,0x6e,0xa3,0x79,0xa2,0x54, +0x12,0x61,0x69,0x63,0xa3,0x54,0x10,0x63,0xa2,0xa9,0x12,0x68,0x65,0x6e,0xa3,0xa9, +0x18,0x61,0x72,0x61,0x6d,0x67,0x6f,0x6e,0x64,0x69,0xa3,0xaf,0x68,0x36,0x6b,0x4c, +0x6c,0x15,0x61,0x79,0x61,0x6c,0x61,0x6d,0x55,1,0x61,0x26,0x6a,0xa3,0xa0,0x13, +0x6a,0x61,0x6e,0x69,0xa3,0xa0,0x10,0x61,0xa2,0xb4,0x12,0x73,0x61,0x72,0xa3,0xb4, +3,0x64,0x78,0x65,0x94,0x6e,0xa2,0x42,0x72,1,0x63,0xa3,0x8d,0x6f,0xa2,0x56, +0x13,0x69,0x74,0x69,0x63,1,0x63,0x3c,0x68,0x19,0x69,0x65,0x72,0x6f,0x67,0x6c, +0x79,0x70,0x68,0x73,0xa3,0x56,0x15,0x75,0x72,0x73,0x69,0x76,0x65,0xa3,0x8d,1, +0x65,0x26,0x66,0xa3,0xb5,0x16,0x66,0x61,0x69,0x64,0x72,0x69,0x6e,0xa3,0xb5,0x17, +0x74,0x65,0x69,0x6d,0x61,0x79,0x65,0x6b,0xa3,0x73,0x10,0x64,0xa2,0x8c,0x17,0x65, +0x6b,0x69,0x6b,0x61,0x6b,0x75,0x69,0xa3,0x8c,0x11,0x61,0x6f,0xa3,0x5c,5,0x6f, +0x14,0x6f,0x30,0x70,0x36,0x74,0x11,0x68,0x69,0xa3,0x78,0x11,0x72,0x65,0xa3,0x77, +0x11,0x65,0x6c,0xa3,0x8a,0x61,0x2e,0x68,0x98,0x6e,0x11,0x64,0x61,0x4b,4,0x69, +0x3c,0x6c,0x44,0x6e,0x48,0x74,0x56,0x79,0x13,0x61,0x68,0x6c,0x69,0xa3,0x4f,0x12, +0x74,0x68,0x69,0xa3,0x78,0x10,0x69,0xa3,0x4f,1,0x61,0x4d,0x6e,0x12,0x61,0x64, +0x61,0x4b,0x14,0x61,0x6b,0x61,0x6e,0x61,0x4c,0x19,0x6f,0x72,0x68,0x69,0x72,0x61, +0x67,0x61,0x6e,0x61,0x8d,3,0x61,0x3c,0x6d,0x4e,0x6f,0x5a,0x75,0x15,0x64,0x61, +0x77,0x61,0x64,0x69,0xa3,0x91,0x10,0x72,0x92,0x15,0x6f,0x73,0x68,0x74,0x68,0x69, +0x93,1,0x65,0x24,0x72,0x4f,0x10,0x72,0x4f,0x10,0x6a,0xa2,0x9d,0x11,0x6b,0x69, +0xa3,0x9d,4,0x61,0x5c,0x65,0x90,0x69,0xa0,0x6f,0xa2,0x5d,0x79,1,0x63,0x34, +0x64,0x10,0x69,0xa2,0x6c,0x11,0x61,0x6e,0xa3,0x6c,0x10,0x69,0xa2,0x6b,0x11,0x61, +0x6e,0xa3,0x6b,2,0x6e,0x42,0x6f,0x46,0x74,3,0x66,0xa3,0x50,0x67,0xa3,0x51, +0x69,0x24,0x6e,0x53,0x10,0x6e,0x53,0x10,0x61,0xa3,0x6a,0x50,0x10,0x6f,0x51,0x11, +0x70,0x63,0xa2,0x52,0x11,0x68,0x61,0xa3,0x52,2,0x6d,0x2e,0x6e,0x36,0x73,0x10, +0x75,0xa3,0x83,0x10,0x62,0x80,0x10,0x75,0x81,2,0x61,0xa3,0x53,0x62,0x83,0x65, +0x11,0x61,0x72,1,0x61,0xa3,0x53,0x62,0x83,0x11,0x6d,0x61,0xa3,0x8b,0x68,0x6e, +0x69,0xa2,0x91,0x6a,2,0x61,0x30,0x70,0x52,0x75,0x11,0x72,0x63,0xa3,0x94,1, +0x6d,0x38,0x76,0x10,0x61,0xa2,0x4e,0x13,0x6e,0x65,0x73,0x65,0xa3,0x4e,0x10,0x6f, +0xa3,0xad,0x11,0x61,0x6e,0xa3,0x69,6,0x6c,0x1a,0x6c,0x34,0x6d,0x3a,0x72,0x40, +0x75,0x11,0x6e,0x67,0xa3,0x4c,0x11,0x75,0x77,0xa3,0x9c,0x11,0x6e,0x67,0xa3,0x4b, +0x11,0x6b,0x74,0x8d,0x61,0x3c,0x65,0xa2,0x43,0x69,0x11,0x72,0x61,0x48,0x13,0x67, +0x61,0x6e,0x61,0x49,1,0x6e,0x34,0x74,0x10,0x72,0xa2,0xa2,0x11,0x61,0x6e,0xa3, +0xa2,0x42,6,0x6f,0xe,0x6f,0x77,0x73,0xa3,0x49,0x74,0xa3,0x4a,0x75,0x12,0x6e, +0x6f,0x6f,0x77,0x62,0xa3,0xac,0x67,0x3e,0x69,0x42,0x19,0x66,0x69,0x72,0x6f,0x68, +0x69,0x6e,0x67,0x79,0x61,0xa3,0xb6,0x44,0x11,0x75,0x6c,0x45,0x11,0x62,0x72,0x46, +0x11,0x65,0x77,0x47,2,0x6d,0x2e,0x6e,0x4a,0x74,0x11,0x61,0x6c,0x5d,0x1c,0x70, +0x65,0x72,0x69,0x61,0x6c,0x61,0x72,0x61,0x6d,0x61,0x69,0x63,0xa3,0x74,2,0x64, +0x66,0x68,0x6a,0x73,0x1b,0x63,0x72,0x69,0x70,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x70, +0x61,1,0x68,0x32,0x72,0x14,0x74,0x68,0x69,0x61,0x6e,0xa3,0x7d,0x13,0x6c,0x61, +0x76,0x69,0xa3,0x7a,0x10,0x73,0xa3,0x4d,0x15,0x65,0x72,0x69,0x74,0x65,0x64,0x23, +0x64,0xc0,0xec,0x64,0xa2,0x7a,0x65,0xa2,0xad,0x67,4,0x65,0x82,0x6c,0x9a,0x6f, +0xa2,0x46,0x72,0xa2,0x55,0x75,2,0x6a,0x3c,0x6e,0x4e,0x72,1,0x6d,0x24,0x75, +0x41,0x13,0x75,0x6b,0x68,0x69,0x41,1,0x61,0x24,0x72,0x3f,0x13,0x72,0x61,0x74, +0x69,0x3f,0x18,0x6a,0x61,0x6c,0x61,0x67,0x6f,0x6e,0x64,0x69,0xa3,0xb3,0x10,0x6f, +1,0x6b,0xa3,0x48,0x72,0x38,0x13,0x67,0x69,0x61,0x6e,0x39,0x11,0x61,0x67,0x90, +0x15,0x6f,0x6c,0x69,0x74,0x69,0x63,0x91,1,0x6e,0x30,0x74,0x10,0x68,0x3a,0x11, +0x69,0x63,0x3b,1,0x67,0xa3,0xb3,0x6d,0xa3,0xaf,1,0x61,0x32,0x65,1,0x65, +0x24,0x6b,0x3d,0x10,0x6b,0x3d,0x10,0x6e,0xa2,0x89,0x12,0x74,0x68,0x61,0xa3,0x89, +3,0x65,0x42,0x6f,0x68,0x73,0x76,0x75,0x11,0x70,0x6c,0xa2,0x87,0x13,0x6f,0x79, +0x61,0x6e,0xa3,0x87,1,0x73,0x38,0x76,0x10,0x61,0x34,0x15,0x6e,0x61,0x67,0x61, +0x72,0x69,0x35,0x13,0x65,0x72,0x65,0x74,0x33,0x11,0x67,0x72,0xa2,0xb2,0x10,0x61, +0xa3,0xb2,0x11,0x72,0x74,0x33,2,0x67,0x3a,0x6c,0x72,0x74,0x11,0x68,0x69,0x36, +0x13,0x6f,0x70,0x69,0x63,0x37,0x10,0x79,2,0x64,0xa3,0x45,0x68,0xa3,0x46,0x70, +0xa2,0x47,0x1e,0x74,0x69,0x61,0x6e,0x68,0x69,0x65,0x72,0x6f,0x67,0x6c,0x79,0x70, +0x68,0x73,0xa3,0x47,0x11,0x62,0x61,0xa2,0x88,0x12,0x73,0x61,0x6e,0xa3,0x88,0x61, +0xa2,0xa2,0x62,0xa4,7,0x63,6,0x6f,0x3d,0x6f,0x5a,0x70,0x76,0x75,0x7a,0x79, +1,0x70,0x3e,0x72,2,0x69,0x2a,0x6c,0x31,0x73,0xa3,0x44,0x13,0x6c,0x6c,0x69, +0x63,0x31,0x13,0x72,0x69,0x6f,0x74,0x7f,1,0x6d,0x30,0x70,0x10,0x74,0x2e,0x11, +0x69,0x63,0x2f,0x12,0x6d,0x6f,0x6e,0x21,0x11,0x72,0x74,0x7f,0x16,0x6e,0x65,0x69, +0x66,0x6f,0x72,0x6d,0xa3,0x65,0x61,0x32,0x68,0xa2,0x41,0x69,0x11,0x72,0x74,0xa3, +0x43,3,0x6b,0x4c,0x6e,0x50,0x72,0x76,0x75,0x1d,0x63,0x61,0x73,0x69,0x61,0x6e, +0x61,0x6c,0x62,0x61,0x6e,0x69,0x61,0x6e,0xa3,0x9f,0x10,0x6d,0xa3,0x76,1,0x61, +0x24,0x73,0x71,0x1d,0x64,0x69,0x61,0x6e,0x61,0x62,0x6f,0x72,0x69,0x67,0x69,0x6e, +0x61,0x6c,0x71,0x10,0x69,0xa2,0x68,0x11,0x61,0x6e,0xa3,0x68,1,0x61,0x34,0x65, +0x10,0x72,0x2c,0x13,0x6f,0x6b,0x65,0x65,0x2d,1,0x6b,0x26,0x6d,0xa3,0x42,0x11, +0x6d,0x61,0xa3,0x76,6,0x68,0x4a,0x68,0x48,0x6e,0x4e,0x72,0x76,0x76,1,0x65, +0x2a,0x73,0x10,0x74,0xa3,0x75,0x13,0x73,0x74,0x61,0x6e,0xa3,0x75,0x11,0x6f,0x6d, +0xa3,0xa1,0x11,0x61,0x74,0x1f,0x6f,0x6c,0x69,0x61,0x6e,0x68,0x69,0x65,0x72,0x6f, +0x67,0x6c,0x79,0x70,0x68,0x73,0xa3,0x9c,1,0x61,0x3e,0x6d,2,0x65,0x2a,0x69, +0xa3,0x74,0x6e,0x27,0x13,0x6e,0x69,0x61,0x6e,0x27,0x10,0x62,0x24,0x11,0x69,0x63, +0x25,0x64,0x30,0x66,0x44,0x67,0x11,0x68,0x62,0xa3,0x9f,0x10,0x6c,1,0x61,0x26, +0x6d,0xa3,0xa7,0x10,0x6d,0xa3,0xa7,0x11,0x61,0x6b,0xa3,0x93,6,0x6c,0x3c,0x6c, +0x52,0x6f,0x56,0x72,0x66,0x75,1,0x67,0x30,0x68,1,0x64,0x79,0x69,0x10,0x64, +0x79,0x10,0x69,0x8e,0x13,0x6e,0x65,0x73,0x65,0x8f,0x11,0x69,0x73,0xa1,0x11,0x70, +0x6f,0x2a,0x13,0x6d,0x6f,0x66,0x6f,0x2b,0x10,0x61,1,0x68,0x2e,0x69,0x7c,0x12, +0x6c,0x6c,0x65,0x7d,0xa2,0x41,0x11,0x6d,0x69,0xa3,0x41,0x61,0x48,0x65,0x9c,0x68, +1,0x61,0x2a,0x6b,0x10,0x73,0xa3,0xa8,0x15,0x69,0x6b,0x73,0x75,0x6b,0x69,0xa3, +0xa8,3,0x6c,0x3a,0x6d,0x48,0x73,0x54,0x74,1,0x61,0x24,0x6b,0x9f,0x10,0x6b, +0x9f,0x10,0x69,0x9c,0x13,0x6e,0x65,0x73,0x65,0x9d,0x10,0x75,0xa2,0x82,0x10,0x6d, +0xa3,0x82,0x10,0x73,0xa2,0x86,0x13,0x61,0x76,0x61,0x68,0xa3,0x86,0x11,0x6e,0x67, +0x28,0x12,0x61,0x6c,0x69,0x29,3,0x6c,0x42,0x6e,0x90,0x74,0xa2,0x46,0x76,0x24, +0x17,0x6f,0x77,0x65,0x6c,0x6a,0x61,0x6d,0x6f,0x25,0x22,1,0x65,0x54,0x76,0x28, +1,0x73,0x38,0x74,0x2a,0x17,0x73,0x79,0x6c,0x6c,0x61,0x62,0x6c,0x65,0x2b,0x16, +0x79,0x6c,0x6c,0x61,0x62,0x6c,0x65,0x29,0x18,0x61,0x64,0x69,0x6e,0x67,0x6a,0x61, +0x6d,0x6f,0x23,1,0x61,0x21,0x6f,0x1a,0x74,0x61,0x70,0x70,0x6c,0x69,0x63,0x61, +0x62,0x6c,0x65,0x21,0x26,0x1a,0x72,0x61,0x69,0x6c,0x69,0x6e,0x67,0x6a,0x61,0x6d, +0x6f,0x27,1,0x6e,0x2c,0x79,0x22,0x11,0x65,0x73,0x23,0x20,0x10,0x6f,0x21,1, +0x6e,0x2c,0x79,0x22,0x11,0x65,0x73,0x23,0x20,0x10,0x6f,0x21,2,0x6d,0x30,0x6e, +0x3a,0x79,0x22,0x11,0x65,0x73,0x23,0x24,0x13,0x61,0x79,0x62,0x65,0x25,0x20,0x10, +0x6f,0x21,2,0x6d,0x30,0x6e,0x3a,0x79,0x22,0x11,0x65,0x73,0x23,0x24,0x13,0x61, +0x79,0x62,0x65,0x25,0x20,0x10,0x6f,0x21,0xb,0x72,0x39,0x76,0xc,0x76,0x33,0x78, +0x2a,0x7a,0x11,0x77,0x6a,0x43,0x10,0x78,0x21,0x72,0x28,0x73,0x50,0x74,0x31,1, +0x65,0x24,0x69,0x39,0x1e,0x67,0x69,0x6f,0x6e,0x61,0x6c,0x69,0x6e,0x64,0x69,0x63, +0x61,0x74,0x6f,0x72,0x39,1,0x6d,0x35,0x70,0x18,0x61,0x63,0x69,0x6e,0x67,0x6d, +0x61,0x72,0x6b,0x35,0x6c,0x1f,0x6c,0x3c,0x6f,0x4a,0x70,1,0x70,0x37,0x72,0x14, +0x65,0x70,0x65,0x6e,0x64,0x37,0x28,1,0x66,0x2b,0x76,0x2c,0x10,0x74,0x2f,0x13, +0x74,0x68,0x65,0x72,0x21,0x63,0x4c,0x65,0x64,0x67,1,0x61,0x3a,0x6c,0x19,0x75, +0x65,0x61,0x66,0x74,0x65,0x72,0x7a,0x77,0x6a,0x41,0x10,0x7a,0x41,2,0x6e,0x23, +0x6f,0x24,0x72,0x25,0x14,0x6e,0x74,0x72,0x6f,0x6c,0x23,2,0x62,0x34,0x6d,0x4e, +0x78,0x26,0x13,0x74,0x65,0x6e,0x64,0x27,0x3a,1,0x61,0x24,0x67,0x3d,0x11,0x73, +0x65,0x3a,0x12,0x67,0x61,0x7a,0x3d,0x3e,0x16,0x6f,0x64,0x69,0x66,0x69,0x65,0x72, +0x3f,9,0x6e,0x4a,0x6e,0x34,0x6f,0x44,0x73,0x60,0x75,0x94,0x78,0x10,0x78,0x21, +0x10,0x75,0x2a,0x14,0x6d,0x65,0x72,0x69,0x63,0x2b,1,0x6c,0x2c,0x74,0x12,0x68, +0x65,0x72,0x21,0x14,0x65,0x74,0x74,0x65,0x72,0x2d,3,0x63,0x36,0x65,0x46,0x70, +0x31,0x74,0x32,0x12,0x65,0x72,0x6d,0x33,0x3c,0x16,0x6f,0x6e,0x74,0x69,0x6e,0x75, +0x65,0x3d,0x2e,0x10,0x70,0x2f,0x10,0x70,0x34,0x12,0x70,0x65,0x72,0x35,0x61,0x46, +0x63,0x52,0x65,0x64,0x66,0x72,0x6c,2,0x65,0x2d,0x66,0x3b,0x6f,0x28,0x12,0x77, +0x65,0x72,0x29,0x10,0x74,0x22,0x12,0x65,0x72,0x6d,0x23,1,0x6c,0x24,0x72,0x37, +0x24,0x12,0x6f,0x73,0x65,0x25,0x10,0x78,0x38,0x13,0x74,0x65,0x6e,0x64,0x39,0x10, +0x6f,0x26,0x13,0x72,0x6d,0x61,0x74,0x27,0,0x10,0x6c,0x88,0x72,0x40,0x72,0x36, +0x73,0x5e,0x77,0x7a,0x78,0x8a,0x7a,0x11,0x77,0x6a,0x4b,1,0x65,0x24,0x69,0x3b, +0x1e,0x67,0x69,0x6f,0x6e,0x61,0x6c,0x69,0x6e,0x64,0x69,0x63,0x61,0x74,0x6f,0x72, +0x3b,1,0x69,0x24,0x71,0x3f,0x18,0x6e,0x67,0x6c,0x65,0x71,0x75,0x6f,0x74,0x65, +0x3f,0x17,0x73,0x65,0x67,0x73,0x70,0x61,0x63,0x65,0x4d,0x10,0x78,0x21,0x6c,0x36, +0x6d,0x3c,0x6e,0x76,0x6f,0x13,0x74,0x68,0x65,0x72,0x21,1,0x65,0x23,0x66,0x35, +3,0x62,0x37,0x69,0x28,0x6c,0x29,0x6e,0x2b,0x10,0x64,1,0x6c,0x34,0x6e,0x11, +0x75,0x6d,0x2a,0x12,0x6c,0x65,0x74,0x37,0x14,0x65,0x74,0x74,0x65,0x72,0x29,2, +0x65,0x36,0x6c,0x39,0x75,0x2c,0x14,0x6d,0x65,0x72,0x69,0x63,0x2d,0x14,0x77,0x6c, +0x69,0x6e,0x65,0x39,0x66,0x3f,0x66,0x40,0x67,0x4e,0x68,0x70,0x6b,0x10,0x61,0x26, +0x15,0x74,0x61,0x6b,0x61,0x6e,0x61,0x27,0x10,0x6f,0x24,0x13,0x72,0x6d,0x61,0x74, +0x25,1,0x61,0x3a,0x6c,0x19,0x75,0x65,0x61,0x66,0x74,0x65,0x72,0x7a,0x77,0x6a, +0x49,0x10,0x7a,0x49,1,0x65,0x24,0x6c,0x3d,0x19,0x62,0x72,0x65,0x77,0x6c,0x65, +0x74,0x74,0x65,0x72,0x3d,0x61,0x86,0x63,0x92,0x64,0x94,0x65,2,0x62,0x44,0x6d, +0x5e,0x78,0x2e,0x13,0x74,0x65,0x6e,0x64,0x32,0x15,0x6e,0x75,0x6d,0x6c,0x65,0x74, +0x2f,0x42,1,0x61,0x24,0x67,0x45,0x11,0x73,0x65,0x42,0x12,0x67,0x61,0x7a,0x45, +0x46,0x16,0x6f,0x64,0x69,0x66,0x69,0x65,0x72,0x47,0x15,0x6c,0x65,0x74,0x74,0x65, +0x72,0x23,0x10,0x72,0x31,1,0x6f,0x24,0x71,0x41,0x18,0x75,0x62,0x6c,0x65,0x71, +0x75,0x6f,0x74,0x65,0x41,2,0x63,0x32,0x6e,0x3c,0x6f,0x22,0x12,0x70,0x65,0x6e, +0x23,0x24,0x13,0x6c,0x6f,0x73,0x65,0x25,0x20,0x12,0x6f,0x6e,0x65,0x21,0xd,0x6e, +0xc1,0x86,0x73,0xa8,0x73,0x4c,0x74,0xa2,0x76,0x75,0xa2,0x83,0x7a,0xd8,0x70,0, +2,0x6c,0xd9,0x20,0,0x70,0xd9,0x40,0,0x73,0xc3,0,0xfe,0xf,0,0, +0,7,0x6f,0x3c,0x6f,0xff,8,0,0,0,0x70,0x3a,0x75,0x6e,0x79,0x13, +0x6d,0x62,0x6f,0x6c,0xff,0xf,0,0,0,0x11,0x61,0x63,1,0x65,0x34,0x69, +0x15,0x6e,0x67,0x6d,0x61,0x72,0x6b,0xa5,0,0x18,0x73,0x65,0x70,0x61,0x72,0x61, +0x74,0x6f,0x72,0xc3,0,0x16,0x72,0x72,0x6f,0x67,0x61,0x74,0x65,0xe1,0,0, +0x63,0xff,2,0,0,0,0x65,0x38,0x6b,0xff,4,0,0,0,0x6d,0xff, +1,0,0,0,0x16,0x70,0x61,0x72,0x61,0x74,0x6f,0x72,0xd9,0x70,0,0x1d, +0x69,0x74,0x6c,0x65,0x63,0x61,0x73,0x65,0x6c,0x65,0x74,0x74,0x65,0x72,0x31,1, +0x6e,0x40,0x70,0x1c,0x70,0x65,0x72,0x63,0x61,0x73,0x65,0x6c,0x65,0x74,0x74,0x65, +0x72,0x25,0x17,0x61,0x73,0x73,0x69,0x67,0x6e,0x65,0x64,0x23,0x6e,0xa2,0x69,0x6f, +0xa2,0x89,0x70,0xfe,0x30,0xf8,0,0,9,0x69,0x33,0x69,0xff,0x10,0,0, +0,0x6f,0xfd,0x80,0,0,0x72,0x54,0x73,0xf9,0,0,0x75,0x12,0x6e,0x63, +0x74,0xfe,0x30,0xf8,0,0,0x15,0x75,0x61,0x74,0x69,0x6f,0x6e,0xff,0x30,0xf8, +0,0,0x17,0x69,0x76,0x61,0x74,0x65,0x75,0x73,0x65,0xdd,0,0,0x61,0x48, +0x63,0xfd,0x40,0,0,0x64,0xe9,0,0,0x65,0xfd,0x20,0,0,0x66,0xff, +0x20,0,0,0,0x1f,0x72,0x61,0x67,0x72,0x61,0x70,0x68,0x73,0x65,0x70,0x61, +0x72,0x61,0x74,0x6f,0x72,0xd9,0x40,0,0xbe,0,3,0x64,0xa7,0,0x6c,0xab, +0,0x6f,0x30,0x75,0x13,0x6d,0x62,0x65,0x72,0xbf,0,0xb2,0,0x1b,0x6e,0x73, +0x70,0x61,0x63,0x69,0x6e,0x67,0x6d,0x61,0x72,0x6b,0xa1,1,0x70,0x92,0x74,0x12, +0x68,0x65,0x72,0xe6,0x80,1,3,0x6c,0x40,0x6e,0x4a,0x70,0x56,0x73,0x14,0x79, +0x6d,0x62,0x6f,0x6c,0xff,8,0,0,0,0x14,0x65,0x74,0x74,0x65,0x72,0x61, +0x14,0x75,0x6d,0x62,0x65,0x72,0xb3,0,0x19,0x75,0x6e,0x63,0x74,0x75,0x61,0x74, +0x69,0x6f,0x6e,0xfd,0x80,0,0,0x1c,0x65,0x6e,0x70,0x75,0x6e,0x63,0x74,0x75, +0x61,0x74,0x69,0x6f,0x6e,0xf9,0,0,0x66,0xc0,0xc4,0x66,0xa2,0x47,0x69,0xa2, +0x64,0x6c,0xa2,0x79,0x6d,0xa4,0xc0,4,0x61,0x6c,0x63,0xa5,0,0x65,0xa3,0x80, +0x6e,0xa1,0x6f,0x15,0x64,0x69,0x66,0x69,0x65,0x72,1,0x6c,0x38,0x73,0x14,0x79, +0x6d,0x62,0x6f,0x6c,0xff,4,0,0,0,0x14,0x65,0x74,0x74,0x65,0x72,0x41, +1,0x72,0x3c,0x74,0x16,0x68,0x73,0x79,0x6d,0x62,0x6f,0x6c,0xff,1,0,0, +0,0x10,0x6b,0xa5,0xc0,1,0x69,0x32,0x6f,0x13,0x72,0x6d,0x61,0x74,0xdb,0, +0,0x1d,0x6e,0x61,0x6c,0x70,0x75,0x6e,0x63,0x74,0x75,0x61,0x74,0x69,0x6f,0x6e, +0xff,0x20,0,0,0,0x10,0x6e,0x1f,0x69,0x74,0x69,0x61,0x6c,0x70,0x75,0x6e, +0x63,0x74,0x75,0x61,0x74,0x69,0x6f,0x6e,0xff,0x10,0,0,0,0x9c,7,0x6d, +0x18,0x6d,0x41,0x6f,0x28,0x74,0x31,0x75,0x25,0x60,0x1c,0x77,0x65,0x72,0x63,0x61, +0x73,0x65,0x6c,0x65,0x74,0x74,0x65,0x72,0x29,0x63,0x3d,0x65,0x28,0x69,0x42,0x6c, +0x29,0x13,0x74,0x74,0x65,0x72,0x9c,0x15,0x6e,0x75,0x6d,0x62,0x65,0x72,0xab,0, +0x1a,0x6e,0x65,0x73,0x65,0x70,0x61,0x72,0x61,0x74,0x6f,0x72,0xd9,0x20,0,0x63, +0x46,0x64,0xa2,0x96,0x65,0x1b,0x6e,0x63,0x6c,0x6f,0x73,0x69,0x6e,0x67,0x6d,0x61, +0x72,0x6b,0xa3,0x80,0xe6,0x80,1,7,0x6e,0x57,0x6e,0x52,0x6f,0x5e,0x73,0xe1, +0,0,0x75,0x1b,0x72,0x72,0x65,0x6e,0x63,0x79,0x73,0x79,0x6d,0x62,0x6f,0x6c, +0xff,2,0,0,0,0x22,0x12,0x74,0x72,0x6c,0xd9,0x80,0,0xdc,0,0, +1,0x6d,0x62,0x6e,1,0x6e,0x30,0x74,0x12,0x72,0x6f,0x6c,0xd9,0x80,0,0x1f, +0x65,0x63,0x74,0x6f,0x72,0x70,0x75,0x6e,0x63,0x74,0x75,0x61,0x74,0x69,0x6f,0x6e, +0xfd,0x40,0,0,0x19,0x62,0x69,0x6e,0x69,0x6e,0x67,0x6d,0x61,0x72,0x6b,0xa5, +0xc0,0x61,0x58,0x63,0xd9,0x80,0,0x66,0xdb,0,0,0x6c,0x1d,0x6f,0x73,0x65, +0x70,0x75,0x6e,0x63,0x74,0x75,0x61,0x74,0x69,0x6f,0x6e,0xfd,0x20,0,0,0x18, +0x73,0x65,0x64,0x6c,0x65,0x74,0x74,0x65,0x72,0x3d,2,0x61,0x32,0x65,0x50,0x69, +0x12,0x67,0x69,0x74,0xa7,0,0x1c,0x73,0x68,0x70,0x75,0x6e,0x63,0x74,0x75,0x61, +0x74,0x69,0x6f,0x6e,0xe9,0,0,0x1a,0x63,0x69,0x6d,0x61,0x6c,0x6e,0x75,0x6d, +0x62,0x65,0x72,0xa7,0 }; -const char PropNameData::nameGroups[19082]={ +const char PropNameData::nameGroups[19587]={ 2,'A','l','p','h','a',0,'A','l','p','h','a','b','e','t','i','c',0, 4,'N',0,'N','o',0,'F',0,'F','a','l','s','e',0,4,'Y',0,'Y','e','s',0,'T',0,'T','r','u','e',0, 2,'N','R',0,'N','o','t','_','R','e','o','r','d','e','r','e','d',0, @@ -1025,14 +1049,14 @@ const char PropNameData::nameGroups[19082]={ 2,'C','W','C','M',0,'C','h','a','n','g','e','s','_','W','h','e','n','_','C','a','s','e','m','a','p','p','e','d',0, 2,'C','W','K','C','F',0,'C','h','a','n','g','e','s','_','W','h','e','n','_','N','F','K','C','_','C','a','s','e','f','o','l', 'd','e','d',0,2,'E','m','o','j','i',0,'E','m','o','j','i',0, -2,'E','m','o','j','i','_','P','r','e','s','e','n','t','a','t','i','o','n',0,'E','m','o','j','i','_','P','r','e','s','e','n', -'t','a','t','i','o','n',0,2,'E','m','o','j','i','_','M','o','d','i','f','i','e','r',0,'E','m','o','j','i','_','M','o','d', -'i','f','i','e','r',0,2,'E','m','o','j','i','_','M','o','d','i','f','i','e','r','_','B','a','s','e',0, -'E','m','o','j','i','_','M','o','d','i','f','i','e','r','_','B','a','s','e',0, -2,'E','m','o','j','i','_','C','o','m','p','o','n','e','n','t',0,'E','m','o','j','i','_','C','o','m','p','o','n','e','n','t', -0,2,'R','I',0,'R','e','g','i','o','n','a','l','_','I','n','d','i','c','a','t','o','r',0, +2,'E','P','r','e','s',0,'E','m','o','j','i','_','P','r','e','s','e','n','t','a','t','i','o','n',0, +2,'E','M','o','d',0,'E','m','o','j','i','_','M','o','d','i','f','i','e','r',0, +2,'E','B','a','s','e',0,'E','m','o','j','i','_','M','o','d','i','f','i','e','r','_','B','a','s','e',0, +2,'E','C','o','m','p',0,'E','m','o','j','i','_','C','o','m','p','o','n','e','n','t',0, +2,'R','I',0,'R','e','g','i','o','n','a','l','_','I','n','d','i','c','a','t','o','r',0, 2,'P','C','M',0,'P','r','e','p','e','n','d','e','d','_','C','o','n','c','a','t','e','n','a','t','i','o','n','_','M','a','r', -'k',0,2,'b','c',0,'B','i','d','i','_','C','l','a','s','s',0, +'k',0,2,'E','x','t','P','i','c','t',0,'E','x','t','e','n','d','e','d','_','P','i','c','t','o','g','r','a','p','h','i','c', +0,2,'b','c',0,'B','i','d','i','_','C','l','a','s','s',0, 2,'L',0,'L','e','f','t','_','T','o','_','R','i','g','h','t',0, 2,'R',0,'R','i','g','h','t','_','T','o','_','L','e','f','t',0, 2,'E','N',0,'E','u','r','o','p','e','a','n','_','N','u','m','b','e','r',0, @@ -1371,8 +1395,19 @@ const char PropNameData::nameGroups[19082]={ 2,'N','u','s','h','u',0,'N','u','s','h','u',0,2,'S','o','y','o','m','b','o',0,'S','o','y','o','m','b','o',0, 2,'S','y','r','i','a','c','_','S','u','p',0,'S','y','r','i','a','c','_','S','u','p','p','l','e','m','e','n','t',0, 2,'Z','a','n','a','b','a','z','a','r','_','S','q','u','a','r','e',0,'Z','a','n','a','b','a','z','a','r','_','S','q','u','a', -'r','e',0,2,'c','c','c',0,'C','a','n','o','n','i','c','a','l','_','C','o','m','b','i','n','i','n','g','_','C','l','a','s', -'s',0,2,'d','t',0,'D','e','c','o','m','p','o','s','i','t','i','o','n','_','T','y','p','e',0, +'r','e',0,2,'C','h','e','s','s','_','S','y','m','b','o','l','s',0,'C','h','e','s','s','_','S','y','m','b','o','l','s',0, +2,'D','o','g','r','a',0,'D','o','g','r','a',0,2,'G','e','o','r','g','i','a','n','_','E','x','t',0, +'G','e','o','r','g','i','a','n','_','E','x','t','e','n','d','e','d',0, +2,'G','u','n','j','a','l','a','_','G','o','n','d','i',0,'G','u','n','j','a','l','a','_','G','o','n','d','i',0, +2,'H','a','n','i','f','i','_','R','o','h','i','n','g','y','a',0,'H','a','n','i','f','i','_','R','o','h','i','n','g','y','a', +0,2,'I','n','d','i','c','_','S','i','y','a','q','_','N','u','m','b','e','r','s',0,'I','n','d','i','c','_','S','i','y','a', +'q','_','N','u','m','b','e','r','s',0,2,'M','a','k','a','s','a','r',0,'M','a','k','a','s','a','r',0, +2,'M','a','y','a','n','_','N','u','m','e','r','a','l','s',0,'M','a','y','a','n','_','N','u','m','e','r','a','l','s',0, +2,'M','e','d','e','f','a','i','d','r','i','n',0,'M','e','d','e','f','a','i','d','r','i','n',0, +2,'O','l','d','_','S','o','g','d','i','a','n',0,'O','l','d','_','S','o','g','d','i','a','n',0, +2,'S','o','g','d','i','a','n',0,'S','o','g','d','i','a','n',0, +2,'c','c','c',0,'C','a','n','o','n','i','c','a','l','_','C','o','m','b','i','n','i','n','g','_','C','l','a','s','s',0, +2,'d','t',0,'D','e','c','o','m','p','o','s','i','t','i','o','n','_','T','y','p','e',0, 3,'N','o','n','e',0,'N','o','n','e',0,'n','o','n','e',0, 3,'C','a','n',0,'C','a','n','o','n','i','c','a','l',0,'c','a','n',0, 3,'C','o','m',0,'C','o','m','p','a','t',0,'c','o','m',0, @@ -1503,7 +1538,10 @@ const char PropNameData::nameGroups[19082]={ 2,'M','a','l','a','y','a','l','a','m','_','R','a',0,'M','a','l','a','y','a','l','a','m','_','R','a',0, 2,'M','a','l','a','y','a','l','a','m','_','S','s','a',0,'M','a','l','a','y','a','l','a','m','_','S','s','a',0, 2,'M','a','l','a','y','a','l','a','m','_','T','t','a',0,'M','a','l','a','y','a','l','a','m','_','T','t','a',0, -2,'j','t',0,'J','o','i','n','i','n','g','_','T','y','p','e',0, +2,'H','a','n','i','f','i','_','R','o','h','i','n','g','y','a','_','K','i','n','n','a','_','Y','a',0, +'H','a','n','i','f','i','_','R','o','h','i','n','g','y','a','_','K','i','n','n','a','_','Y','a',0, +2,'H','a','n','i','f','i','_','R','o','h','i','n','g','y','a','_','P','a',0,'H','a','n','i','f','i','_','R','o','h','i','n', +'g','y','a','_','P','a',0,2,'j','t',0,'J','o','i','n','i','n','g','_','T','y','p','e',0, 2,'U',0,'N','o','n','_','J','o','i','n','i','n','g',0,2,'C',0,'J','o','i','n','_','C','a','u','s','i','n','g',0, 2,'D',0,'D','u','a','l','_','J','o','i','n','i','n','g',0, 2,'L',0,'L','e','f','t','_','J','o','i','n','i','n','g',0, @@ -1644,7 +1682,12 @@ const char PropNameData::nameGroups[19082]={ 2,'H','a','n','b',0,'H','a','n','b',0,2,'J','a','m','o',0,'J','a','m','o',0, 2,'Z','s','y','e',0,'Z','s','y','e',0,2,'G','o','n','m',0,'M','a','s','a','r','a','m','_','G','o','n','d','i',0, 2,'S','o','y','o',0,'S','o','y','o','m','b','o',0,2,'Z','a','n','b',0,'Z','a','n','a','b','a','z','a','r','_','S','q', -'u','a','r','e',0,2,'h','s','t',0,'H','a','n','g','u','l','_','S','y','l','l','a','b','l','e','_','T','y','p','e',0, +'u','a','r','e',0,2,'D','o','g','r',0,'D','o','g','r','a',0, +2,'G','o','n','g',0,'G','u','n','j','a','l','a','_','G','o','n','d','i',0, +2,'M','a','k','a',0,'M','a','k','a','s','a','r',0,2,'M','e','d','f',0,'M','e','d','e','f','a','i','d','r','i','n',0, +2,'R','o','h','g',0,'H','a','n','i','f','i','_','R','o','h','i','n','g','y','a',0, +2,'S','o','g','d',0,'S','o','g','d','i','a','n',0,2,'S','o','g','o',0,'O','l','d','_','S','o','g','d','i','a','n',0, +2,'h','s','t',0,'H','a','n','g','u','l','_','S','y','l','l','a','b','l','e','_','T','y','p','e',0, 2,'N','A',0,'N','o','t','_','A','p','p','l','i','c','a','b','l','e',0, 2,'L',0,'L','e','a','d','i','n','g','_','J','a','m','o',0, 2,'V',0,'V','o','w','e','l','_','J','a','m','o',0,2,'T',0,'T','r','a','i','l','i','n','g','_','J','a','m','o',0, @@ -1676,6 +1719,7 @@ const char PropNameData::nameGroups[19082]={ 2,'E','x','t','e','n','d',0,'E','x','t','e','n','d',0,2,'M','B',0,'M','i','d','N','u','m','L','e','t',0, 2,'N','L',0,'N','e','w','l','i','n','e',0,2,'S','Q',0,'S','i','n','g','l','e','_','Q','u','o','t','e',0, 2,'D','Q',0,'D','o','u','b','l','e','_','Q','u','o','t','e',0, +2,'W','S','e','g','S','p','a','c','e',0,'W','S','e','g','S','p','a','c','e',0, 2,'b','p','t',0,'B','i','d','i','_','P','a','i','r','e','d','_','B','r','a','c','k','e','t','_','T','y','p','e',0, 2,'n',0,'N','o','n','e',0,2,'o',0,'O','p','e','n',0, 2,'c',0,'C','l','o','s','e',0,2,'g','c','m',0,'G','e','n','e','r','a','l','_','C','a','t','e','g','o','r','y','_','M', diff --git a/deps/icu-small/source/common/putil.cpp b/deps/icu-small/source/common/putil.cpp index e367fa6d30e..a1e16a9cd94 100644 --- a/deps/icu-small/source/common/putil.cpp +++ b/deps/icu-small/source/common/putil.cpp @@ -533,6 +533,28 @@ uprv_fmin(double x, double y) return (x > y ? y : x); } +U_CAPI UBool U_EXPORT2 +uprv_add32_overflow(int32_t a, int32_t b, int32_t* res) { + // NOTE: Some compilers (GCC, Clang) have primitives available, like __builtin_add_overflow. + // This function could be optimized by calling one of those primitives. + auto a64 = static_cast(a); + auto b64 = static_cast(b); + int64_t res64 = a64 + b64; + *res = static_cast(res64); + return res64 != *res; +} + +U_CAPI UBool U_EXPORT2 +uprv_mul32_overflow(int32_t a, int32_t b, int32_t* res) { + // NOTE: Some compilers (GCC, Clang) have primitives available, like __builtin_mul_overflow. + // This function could be optimized by calling one of those primitives. + auto a64 = static_cast(a); + auto b64 = static_cast(b); + int64_t res64 = a64 * b64; + *res = static_cast(res64); + return res64 != *res; +} + /** * Truncates the given double. * trunc(3.3) = 3.0, trunc (-3.3) = -3.0 diff --git a/deps/icu-small/source/common/putilimp.h b/deps/icu-small/source/common/putilimp.h index 56ea8df0095..023e06879a0 100644 --- a/deps/icu-small/source/common/putilimp.h +++ b/deps/icu-small/source/common/putilimp.h @@ -391,6 +391,32 @@ U_INTERNAL double U_EXPORT2 uprv_log(double d); */ U_INTERNAL double U_EXPORT2 uprv_round(double x); +/** + * Adds the signed integers a and b, storing the result in res. + * Checks for signed integer overflow. + * Similar to the GCC/Clang extension __builtin_add_overflow + * + * @param a The first operand. + * @param b The second operand. + * @param res a + b + * @return true if overflow occurred; false if no overflow occurred. + * @internal + */ +U_INTERNAL UBool U_EXPORT2 uprv_add32_overflow(int32_t a, int32_t b, int32_t* res); + +/** + * Multiplies the signed integers a and b, storing the result in res. + * Checks for signed integer overflow. + * Similar to the GCC/Clang extension __builtin_mul_overflow + * + * @param a The first multiplicand. + * @param b The second multiplicand. + * @param res a * b + * @return true if overflow occurred; false if no overflow occurred. + * @internal + */ +U_INTERNAL UBool U_EXPORT2 uprv_mul32_overflow(int32_t a, int32_t b, int32_t* res); + #if 0 /** * Returns the number of digits after the decimal point in a double number x. diff --git a/deps/icu-small/source/common/rbbi.cpp b/deps/icu-small/source/common/rbbi.cpp index 69f92d94c60..c5ea2770ba9 100644 --- a/deps/icu-small/source/common/rbbi.cpp +++ b/deps/icu-small/source/common/rbbi.cpp @@ -651,7 +651,7 @@ UBool RuleBasedBreakIterator::isBoundary(int32_t offset) { } // Adjust offset to be on a code point boundary and not beyond the end of the text. - // Note that isBoundary() is always be false for offsets that are not on code point boundaries. + // Note that isBoundary() is always false for offsets that are not on code point boundaries. // But we still need the side effect of leaving iteration at the following boundary. utext_setNativeIndex(&fText, offset); @@ -937,26 +937,23 @@ int32_t RuleBasedBreakIterator::handleNext() { } - //----------------------------------------------------------------------------------- // -// handlePrevious() +// handleSafePrevious() // // Iterate backwards using the safe reverse rules. -// The logic of this function is very similar to handleNext(), above. +// The logic of this function is similar to handleNext(), but simpler +// because the safe table does not require as many options. // //----------------------------------------------------------------------------------- -int32_t RuleBasedBreakIterator::handlePrevious(int32_t fromPosition) { +int32_t RuleBasedBreakIterator::handleSafePrevious(int32_t fromPosition) { int32_t state; uint16_t category = 0; - RBBIRunMode mode; RBBIStateTableRow *row; UChar32 c; - LookAheadResults lookAheadMatches; int32_t result = 0; - int32_t initialPosition = 0; - const RBBIStateTable *stateTable = fData->fSafeRevTable; + const RBBIStateTable *stateTable = fData->fReverseTable; UTEXT_SETNATIVEINDEX(&fText, fromPosition); #ifdef RBBI_DEBUG if (gTrace) { @@ -969,54 +966,24 @@ int32_t RuleBasedBreakIterator::handlePrevious(int32_t fromPosition) { return BreakIterator::DONE; } - // Set up the starting char. - initialPosition = (int32_t)UTEXT_GETNATIVEINDEX(&fText); - result = initialPosition; - c = UTEXT_PREVIOUS32(&fText); - // Set the initial state for the state machine + c = UTEXT_PREVIOUS32(&fText); state = START_STATE; row = (RBBIStateTableRow *) (stateTable->fTableData + (stateTable->fRowLen * state)); - category = 3; - mode = RBBI_RUN; - if (stateTable->fFlags & RBBI_BOF_REQUIRED) { - category = 2; - mode = RBBI_START; - } - // loop until we reach the start of the text or transition to state 0 // - for (;;) { - if (c == U_SENTINEL) { - // Reached end of input string. - if (mode == RBBI_END) { - // We have already run the loop one last time with the - // character set to the psueudo {eof} value. Now it is time - // to unconditionally bail out. - break; - } - // Run the loop one last time with the fake end-of-input character category. - mode = RBBI_END; - category = 1; - } + for (; c != U_SENTINEL; c = UTEXT_PREVIOUS32(&fText)) { + // look up the current character's character category, which tells us + // which column in the state table to look at. + // Note: the 16 in UTRIE_GET16 refers to the size of the data being returned, + // not the size of the character going in, which is a UChar32. // - // Get the char category. An incoming category of 1 or 2 means that - // we are preset for doing the beginning or end of input, and - // that we shouldn't get a category from an actual text input character. - // - if (mode == RBBI_RUN) { - // look up the current character's character category, which tells us - // which column in the state table to look at. - // Note: the 16 in UTRIE_GET16 refers to the size of the data being returned, - // not the size of the character going in, which is a UChar32. - // - // And off the dictionary flag bit. For reverse iteration it is not used. - category = UTRIE2_GET16(fData->fTrie, c); - category &= ~0x4000; - } + // And off the dictionary flag bit. For reverse iteration it is not used. + category = UTRIE2_GET16(fData->fTrie, c); + category &= ~0x4000; #ifdef RBBI_DEBUG if (gTrace) { @@ -1032,65 +999,21 @@ int32_t RuleBasedBreakIterator::handlePrevious(int32_t fromPosition) { // State Transition - move machine to its next state // - // fNextState is a variable-length array. U_ASSERT(categoryfHeader->fCatCount); state = row->fNextState[category]; /*Not accessing beyond memory*/ row = (RBBIStateTableRow *) (stateTable->fTableData + (stateTable->fRowLen * state)); - if (row->fAccepting == -1) { - // Match found, common case. - result = (int32_t)UTEXT_GETNATIVEINDEX(&fText); - } - - int16_t completedRule = row->fAccepting; - if (completedRule > 0) { - // Lookahead match is completed. - int32_t lookaheadResult = lookAheadMatches.getPosition(completedRule); - if (lookaheadResult >= 0) { - UTEXT_SETNATIVEINDEX(&fText, lookaheadResult); - return lookaheadResult; - } - } - int16_t rule = row->fLookAhead; - if (rule != 0) { - // At the position of a '/' in a look-ahead match. Record it. - int32_t pos = (int32_t)UTEXT_GETNATIVEINDEX(&fText); - lookAheadMatches.setPosition(rule, pos); - } - if (state == STOP_STATE) { // This is the normal exit from the lookup state machine. - // We have advanced through the string until it is certain that no - // longer match is possible, no matter what characters follow. + // Transistion to state zero means we have found a safe point. break; } - - // Move (backwards) to the next character to process. - // If this is a beginning-of-input loop iteration, don't advance - // the input position. The next iteration will be processing the - // first real input character. - if (mode == RBBI_RUN) { - c = UTEXT_PREVIOUS32(&fText); - } else { - if (mode == RBBI_START) { - mode = RBBI_RUN; - } - } } // The state machine is done. Check whether it found a match... - - // If the iterator failed to advance in the match engine, force it ahead by one. - // (This really indicates a defect in the break rules. They should always match - // at least one character.) - if (result == initialPosition) { - UTEXT_SETNATIVEINDEX(&fText, initialPosition); - UTEXT_PREVIOUS32(&fText); - result = (int32_t)UTEXT_GETNATIVEINDEX(&fText); - } - + result = (int32_t)UTEXT_GETNATIVEINDEX(&fText); #ifdef RBBI_DEBUG if (gTrace) { RBBIDebugPrintf("result = %d\n\n", result); @@ -1099,7 +1022,6 @@ int32_t RuleBasedBreakIterator::handlePrevious(int32_t fromPosition) { return result; } - //------------------------------------------------------------------------------- // // getRuleStatus() Return the break rule tag associated with the current diff --git a/deps/icu-small/source/common/rbbi_cache.cpp b/deps/icu-small/source/common/rbbi_cache.cpp index ba9329d4771..60316ce6420 100644 --- a/deps/icu-small/source/common/rbbi_cache.cpp +++ b/deps/icu-small/source/common/rbbi_cache.cpp @@ -354,14 +354,31 @@ UBool RuleBasedBreakIterator::BreakCache::populateNear(int32_t position, UErrorC if ((position < fBoundaries[fStartBufIdx] - 15) || position > (fBoundaries[fEndBufIdx] + 15)) { int32_t aBoundary = 0; int32_t ruleStatusIndex = 0; - // TODO: check for position == length of text. Although may still need to back up to get rule status. if (position > 20) { - int32_t backupPos = fBI->handlePrevious(position); - fBI->fPosition = backupPos; - aBoundary = fBI->handleNext(); // Ignore dictionary, just finding a rule based boundary. - ruleStatusIndex = fBI->fRuleStatusIndex; + int32_t backupPos = fBI->handleSafePrevious(position); + + if (backupPos > 0) { + // Advance to the boundary following the backup position. + // There is a complication: the safe reverse rules identify pairs of code points + // that are safe. If advancing from the safe point moves forwards by less than + // two code points, we need to advance one more time to ensure that the boundary + // is good, including a correct rules status value. + // + fBI->fPosition = backupPos; + aBoundary = fBI->handleNext(); + if (aBoundary <= backupPos + 4) { + // +4 is a quick test for possibly having advanced only one codepoint. + // Four being the length of the longest potential code point, a supplementary in UTF-8 + utext_setNativeIndex(&fBI->fText, aBoundary); + if (backupPos == utext_getPreviousNativeIndex(&fBI->fText)) { + // The initial handleNext() only advanced by a single code point. Go again. + aBoundary = fBI->handleNext(); // Safe rules identify safe pairs. + } + } + ruleStatusIndex = fBI->fRuleStatusIndex; + } } - reset(aBoundary, ruleStatusIndex); // Reset cache to hold aBoundary as a single starting point. + reset(aBoundary, ruleStatusIndex); // Reset cache to hold aBoundary as a single starting point. } // Fill in boundaries between existing cache content and the new requested position. @@ -485,16 +502,30 @@ UBool RuleBasedBreakIterator::BreakCache::populatePreceding(UErrorCode &status) if (backupPosition <= 0) { backupPosition = 0; } else { - backupPosition = fBI->handlePrevious(backupPosition); + backupPosition = fBI->handleSafePrevious(backupPosition); } if (backupPosition == UBRK_DONE || backupPosition == 0) { position = 0; positionStatusIdx = 0; } else { - fBI->fPosition = backupPosition; // TODO: pass starting position in a clearer way. + // Advance to the boundary following the backup position. + // There is a complication: the safe reverse rules identify pairs of code points + // that are safe. If advancing from the safe point moves forwards by less than + // two code points, we need to advance one more time to ensure that the boundary + // is good, including a correct rules status value. + // + fBI->fPosition = backupPosition; position = fBI->handleNext(); + if (position <= backupPosition + 4) { + // +4 is a quick test for possibly having advanced only one codepoint. + // Four being the length of the longest potential code point, a supplementary in UTF-8 + utext_setNativeIndex(&fBI->fText, position); + if (backupPosition == utext_getPreviousNativeIndex(&fBI->fText)) { + // The initial handleNext() only advanced by a single code point. Go again. + position = fBI->handleNext(); // Safe rules identify safe pairs. + } + }; positionStatusIdx = fBI->fRuleStatusIndex; - } } while (position >= fromPosition); diff --git a/deps/icu-small/source/common/rbbidata.cpp b/deps/icu-small/source/common/rbbidata.cpp index 18912a6a7b3..fdcb5649613 100644 --- a/deps/icu-small/source/common/rbbidata.cpp +++ b/deps/icu-small/source/common/rbbidata.cpp @@ -81,8 +81,6 @@ void RBBIDataWrapper::init0() { fHeader = NULL; fForwardTable = NULL; fReverseTable = NULL; - fSafeFwdTable = NULL; - fSafeRevTable = NULL; fRuleSource = NULL; fRuleStatusTable = NULL; fTrie = NULL; @@ -111,21 +109,6 @@ void RBBIDataWrapper::init(const RBBIDataHeader *data, UErrorCode &status) { if (data->fRTableLen != 0) { fReverseTable = (RBBIStateTable *)((char *)data + fHeader->fRTable); } - if (data->fSFTableLen != 0) { - fSafeFwdTable = (RBBIStateTable *)((char *)data + fHeader->fSFTable); - } - if (data->fSRTableLen != 0) { - fSafeRevTable = (RBBIStateTable *)((char *)data + fHeader->fSRTable); - } - - // Rule Compatibility Hacks - // If a rule set includes reverse rules but does not explicitly include safe reverse rules, - // the reverse rules are to be treated as safe reverse rules. - - if (fSafeRevTable == NULL && fReverseTable != NULL) { - fSafeRevTable = fReverseTable; - fReverseTable = NULL; - } fTrie = utrie2_openFromSerialized(UTRIE2_16_VALUE_BITS, (uint8_t *)data + fHeader->fTrie, @@ -277,8 +260,6 @@ void RBBIDataWrapper::printData() { printTable("Forward State Transition Table", fForwardTable); printTable("Reverse State Transition Table", fReverseTable); - printTable("Safe Forward State Transition Table", fSafeFwdTable); - printTable("Safe Reverse State Transition Table", fSafeRevTable); RBBIDebugPrintf("\nOrignal Rules source:\n"); for (int32_t c=0; fRuleSource[c] != 0; c++) { @@ -418,28 +399,6 @@ ubrk_swap(const UDataSwapper *ds, const void *inData, int32_t length, void *outD outBytes+tableStartOffset+topSize, status); } - // Safe Forward state table. Same layout as forward table, above. - tableStartOffset = ds->readUInt32(rbbiDH->fSFTable); - tableLength = ds->readUInt32(rbbiDH->fSFTableLen); - - if (tableLength > 0) { - ds->swapArray32(ds, inBytes+tableStartOffset, topSize, - outBytes+tableStartOffset, status); - ds->swapArray16(ds, inBytes+tableStartOffset+topSize, tableLength-topSize, - outBytes+tableStartOffset+topSize, status); - } - - // Safe Reverse state table. Same layout as forward table, above. - tableStartOffset = ds->readUInt32(rbbiDH->fSRTable); - tableLength = ds->readUInt32(rbbiDH->fSRTableLen); - - if (tableLength > 0) { - ds->swapArray32(ds, inBytes+tableStartOffset, topSize, - outBytes+tableStartOffset, status); - ds->swapArray16(ds, inBytes+tableStartOffset+topSize, tableLength-topSize, - outBytes+tableStartOffset+topSize, status); - } - // Trie table for character categories utrie2_swap(ds, inBytes+ds->readUInt32(rbbiDH->fTrie), ds->readUInt32(rbbiDH->fTrieLen), outBytes+ds->readUInt32(rbbiDH->fTrie), status); diff --git a/deps/icu-small/source/common/rbbidata.h b/deps/icu-small/source/common/rbbidata.h index 8b21acca304..3e573039d0f 100644 --- a/deps/icu-small/source/common/rbbidata.h +++ b/deps/icu-small/source/common/rbbidata.h @@ -58,7 +58,7 @@ ubrk_swap(const UDataSwapper *ds, U_NAMESPACE_BEGIN // The current RBBI data format version. -static const uint8_t RBBI_DATA_FORMAT_VERSION[] = {4, 0, 0, 0}; +static const uint8_t RBBI_DATA_FORMAT_VERSION[] = {5, 0, 0, 0}; /* * The following structs map exactly onto the raw data from ICU common data file. @@ -81,10 +81,6 @@ struct RBBIDataHeader { uint32_t fFTableLen; uint32_t fRTable; /* Offset to the reverse state transition table. */ uint32_t fRTableLen; - uint32_t fSFTable; /* safe point forward transition table */ - uint32_t fSFTableLen; - uint32_t fSRTable; /* safe point reverse transition table */ - uint32_t fSRTableLen; uint32_t fTrie; /* Offset to Trie data for character categories */ uint32_t fTrieLen; uint32_t fRuleSource; /* Offset to the source for for the break */ @@ -174,8 +170,6 @@ public: const RBBIDataHeader *fHeader; const RBBIStateTable *fForwardTable; const RBBIStateTable *fReverseTable; - const RBBIStateTable *fSafeFwdTable; - const RBBIStateTable *fSafeRevTable; const UChar *fRuleSource; const int32_t *fRuleStatusTable; diff --git a/deps/icu-small/source/common/rbbirb.cpp b/deps/icu-small/source/common/rbbirb.cpp index 9fc8f8e8142..a46f483d233 100644 --- a/deps/icu-small/source/common/rbbirb.cpp +++ b/deps/icu-small/source/common/rbbirb.cpp @@ -62,10 +62,7 @@ RBBIRuleBuilder::RBBIRuleBuilder(const UnicodeString &rules, fSafeFwdTree = NULL; fSafeRevTree = NULL; fDefaultTree = &fForwardTree; - fForwardTables = NULL; - fReverseTables = NULL; - fSafeFwdTables = NULL; - fSafeRevTables = NULL; + fForwardTable = NULL; fRuleStatusVals = NULL; fChainRules = FALSE; fLBCMNoChain = FALSE; @@ -114,11 +111,7 @@ RBBIRuleBuilder::~RBBIRuleBuilder() { delete fUSetNodes; delete fSetBuilder; - delete fForwardTables; - delete fReverseTables; - delete fSafeFwdTables; - delete fSafeRevTables; - + delete fForwardTable; delete fForwardTree; delete fReverseTree; delete fSafeFwdTree; @@ -157,21 +150,15 @@ RBBIDataHeader *RBBIRuleBuilder::flattenData() { // without the padding. // int32_t headerSize = align8(sizeof(RBBIDataHeader)); - int32_t forwardTableSize = align8(fForwardTables->getTableSize()); - int32_t reverseTableSize = align8(fReverseTables->getTableSize()); - int32_t safeFwdTableSize = align8(fSafeFwdTables->getTableSize()); - int32_t safeRevTableSize = align8(fSafeRevTables->getTableSize()); + int32_t forwardTableSize = align8(fForwardTable->getTableSize()); + int32_t reverseTableSize = align8(fForwardTable->getSafeTableSize()); int32_t trieSize = align8(fSetBuilder->getTrieSize()); int32_t statusTableSize = align8(fRuleStatusVals->size() * sizeof(int32_t)); int32_t rulesSize = align8((fStrippedRules.length()+1) * sizeof(UChar)); - (void)safeFwdTableSize; - int32_t totalSize = headerSize + forwardTableSize - + /* reverseTableSize */ 0 - + /* safeFwdTableSize */ 0 - + (safeRevTableSize ? safeRevTableSize : reverseTableSize) + + reverseTableSize + statusTableSize + trieSize + rulesSize; RBBIDataHeader *data = (RBBIDataHeader *)uprv_malloc(totalSize); @@ -190,38 +177,13 @@ RBBIDataHeader *RBBIRuleBuilder::flattenData() { data->fLength = totalSize; data->fCatCount = fSetBuilder->getNumCharCategories(); - // Only save the forward table and the safe reverse table, - // because these are the only ones used at run-time. - // - // For the moment, we still build the other tables if they are present in the rule source files, - // for backwards compatibility. Old rule files need to work, and this is the simplest approach. - // - // Additional backwards compatibility consideration: if no safe rules are provided, consider the - // reverse rules to actually be the safe reverse rules. - data->fFTable = headerSize; data->fFTableLen = forwardTableSize; - // Do not save Reverse Table. - data->fRTable = data->fFTable + forwardTableSize; - data->fRTableLen = 0; + data->fRTable = data->fFTable + data->fFTableLen; + data->fRTableLen = reverseTableSize; - // Do not save the Safe Forward table. - data->fSFTable = data->fRTable + 0; - data->fSFTableLen = 0; - - data->fSRTable = data->fSFTable + 0; - if (safeRevTableSize > 0) { - data->fSRTableLen = safeRevTableSize; - } else if (reverseTableSize > 0) { - data->fSRTableLen = reverseTableSize; - } else { - U_ASSERT(FALSE); // Rule build should have failed for lack of a reverse table - // before reaching this point. - } - - - data->fTrie = data->fSRTable + data->fSRTableLen; + data->fTrie = data->fRTable + data->fRTableLen; data->fTrieLen = fSetBuilder->getTrieSize(); data->fStatusTable = data->fTrie + trieSize; data->fStatusTableLen= statusTableSize; @@ -230,15 +192,8 @@ RBBIDataHeader *RBBIRuleBuilder::flattenData() { uprv_memset(data->fReserved, 0, sizeof(data->fReserved)); - fForwardTables->exportTable((uint8_t *)data + data->fFTable); - // fReverseTables->exportTable((uint8_t *)data + data->fRTable); - // fSafeFwdTables->exportTable((uint8_t *)data + data->fSFTable); - if (safeRevTableSize > 0) { - fSafeRevTables->exportTable((uint8_t *)data + data->fSRTable); - } else { - fReverseTables->exportTable((uint8_t *)data + data->fSRTable); - } - + fForwardTable->exportTable((uint8_t *)data + data->fFTable); + fForwardTable->exportSafeTable((uint8_t *)data + data->fRTable); fSetBuilder->serializeTrie ((uint8_t *)data + data->fTrie); int32_t *ruleStatusTable = (int32_t *)((uint8_t *)data + data->fStatusTable); @@ -252,10 +207,6 @@ RBBIDataHeader *RBBIRuleBuilder::flattenData() { } - - - - //---------------------------------------------------------------------------------------- // // createRuleBasedBreakIterator construct from source rules that are passed in @@ -267,8 +218,6 @@ RBBIRuleBuilder::createRuleBasedBreakIterator( const UnicodeString &rules, UParseError *parseError, UErrorCode &status) { - // status checked below - // // Read the input rules, generate a parse tree, symbol table, // and list of all Unicode Sets referenced by the rules. @@ -277,66 +226,13 @@ RBBIRuleBuilder::createRuleBasedBreakIterator( const UnicodeString &rules, if (U_FAILURE(status)) { // status checked here bcos build below doesn't return NULL; } - builder.fScanner->parse(); - // - // UnicodeSet processing. - // Munge the Unicode Sets to create a set of character categories. - // Generate the mapping tables (TRIE) from input code points to - // the character categories. - // - builder.fSetBuilder->buildRanges(); + RBBIDataHeader *data = builder.build(status); - - // - // Generate the DFA state transition table. - // - builder.fForwardTables = new RBBITableBuilder(&builder, &builder.fForwardTree); - builder.fReverseTables = new RBBITableBuilder(&builder, &builder.fReverseTree); - builder.fSafeFwdTables = new RBBITableBuilder(&builder, &builder.fSafeFwdTree); - builder.fSafeRevTables = new RBBITableBuilder(&builder, &builder.fSafeRevTree); - if (builder.fForwardTables == NULL || builder.fReverseTables == NULL || - builder.fSafeFwdTables == NULL || builder.fSafeRevTables == NULL) - { - status = U_MEMORY_ALLOCATION_ERROR; - delete builder.fForwardTables; builder.fForwardTables = NULL; - delete builder.fReverseTables; builder.fReverseTables = NULL; - delete builder.fSafeFwdTables; builder.fSafeFwdTables = NULL; - delete builder.fSafeRevTables; builder.fSafeRevTables = NULL; - return NULL; + if (U_FAILURE(status)) { + return nullptr; } - builder.fForwardTables->build(); - builder.fReverseTables->build(); - builder.fSafeFwdTables->build(); - builder.fSafeRevTables->build(); - -#ifdef RBBI_DEBUG - if (builder.fDebugEnv && uprv_strstr(builder.fDebugEnv, "states")) { - builder.fForwardTables->printRuleStatusTable(); - } -#endif - - builder.optimizeTables(); - builder.fSetBuilder->buildTrie(); - - - - // - // Package up the compiled data into a memory image - // in the run-time format. - // - RBBIDataHeader *data = builder.flattenData(); // returns NULL if error - if (U_FAILURE(*builder.fStatus)) { - return NULL; - } - - - // - // Clean up the compiler related stuff - // - - // // Create a break iterator from the compiled rules. // (Identical to creation from stored pre-compiled rules) @@ -353,27 +249,71 @@ RBBIRuleBuilder::createRuleBasedBreakIterator( const UnicodeString &rules, return This; } -void RBBIRuleBuilder::optimizeTables() { - int32_t leftClass; - int32_t rightClass; - - leftClass = 3; - rightClass = 0; - while (fForwardTables->findDuplCharClassFrom(leftClass, rightClass)) { - fSetBuilder->mergeCategories(leftClass, rightClass); - fForwardTables->removeColumn(rightClass); - fReverseTables->removeColumn(rightClass); - fSafeFwdTables->removeColumn(rightClass); - fSafeRevTables->removeColumn(rightClass); +RBBIDataHeader *RBBIRuleBuilder::build(UErrorCode &status) { + if (U_FAILURE(status)) { + return nullptr; } - fForwardTables->removeDuplicateStates(); - fReverseTables->removeDuplicateStates(); - fSafeFwdTables->removeDuplicateStates(); - fSafeRevTables->removeDuplicateStates(); + fScanner->parse(); + if (U_FAILURE(status)) { + return nullptr; + } + + // + // UnicodeSet processing. + // Munge the Unicode Sets to create a set of character categories. + // Generate the mapping tables (TRIE) from input code points to + // the character categories. + // + fSetBuilder->buildRanges(); + + // + // Generate the DFA state transition table. + // + fForwardTable = new RBBITableBuilder(this, &fForwardTree, status); + if (fForwardTable == nullptr) { + status = U_MEMORY_ALLOCATION_ERROR; + return nullptr; + } + + fForwardTable->buildForwardTable(); + optimizeTables(); + fForwardTable->buildSafeReverseTable(status); +#ifdef RBBI_DEBUG + if (fDebugEnv && uprv_strstr(fDebugEnv, "states")) { + fForwardTable->printStates(); + fForwardTable->printRuleStatusTable(); + fForwardTable->printReverseTable(); + } +#endif + fSetBuilder->buildTrie(); + + // + // Package up the compiled data into a memory image + // in the run-time format. + // + RBBIDataHeader *data = flattenData(); // returns NULL if error + if (U_FAILURE(status)) { + return nullptr; + } + return data; +} + +void RBBIRuleBuilder::optimizeTables() { + + // 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(); } U_NAMESPACE_END diff --git a/deps/icu-small/source/common/rbbirb.h b/deps/icu-small/source/common/rbbirb.h index 511f394b458..37992daabb0 100644 --- a/deps/icu-small/source/common/rbbirb.h +++ b/deps/icu-small/source/common/rbbirb.h @@ -18,6 +18,8 @@ #if !UCONFIG_NO_BREAK_ITERATION +#include + #include "unicode/uobject.h" #include "unicode/rbbi.h" #include "unicode/uniset.h" @@ -25,8 +27,7 @@ #include "uhash.h" #include "uvector.h" #include "unicode/symtable.h"// For UnicodeSet parsing, is the interface that - // looks up references to $variables within a set. - + // looks up references to $variables within a set. U_NAMESPACE_BEGIN @@ -123,10 +124,16 @@ public: RBBIRuleBuilder(const UnicodeString &rules, UParseError *parseErr, UErrorCode &status - ); + ); virtual ~RBBIRuleBuilder(); + /** + * Build the state tables and char class Trie from the source rules. + */ + RBBIDataHeader *build(UErrorCode &status); + + /** * Fold together redundant character classes (table columns) and * redundant states (table rows). Done after initial table generation, @@ -162,10 +169,7 @@ public: RBBISetBuilder *fSetBuilder; // Set and Character Category builder. UVector *fUSetNodes; // Vector of all uset nodes. - RBBITableBuilder *fForwardTables; // State transition tables - RBBITableBuilder *fReverseTables; - RBBITableBuilder *fSafeFwdTables; - RBBITableBuilder *fSafeRevTables; + RBBITableBuilder *fForwardTable; // State transition table, build time form. UVector *fRuleStatusVals; // The values that can be returned // from getRuleStatus(). @@ -200,6 +204,11 @@ struct RBBISetTableEl { RBBINode *val; }; +/** + * A pair of ints, used to bundle pairs of states or pairs of character classes. + */ +typedef std::pair IntPair; + //---------------------------------------------------------------------------- // diff --git a/deps/icu-small/source/common/rbbiscan.cpp b/deps/icu-small/source/common/rbbiscan.cpp index e3472ed599e..ecc1663d8f8 100644 --- a/deps/icu-small/source/common/rbbiscan.cpp +++ b/deps/icu-small/source/common/rbbiscan.cpp @@ -372,7 +372,7 @@ UBool RBBIRuleScanner::doParseActions(int32_t action) // (forward, reverse, safe_forward, safe_reverse) // OR this rule into the appropriate group of them. // - RBBINode **destRules = (fReverseRule? &fRB->fReverseTree : fRB->fDefaultTree); + RBBINode **destRules = (fReverseRule? &fRB->fSafeRevTree : fRB->fDefaultTree); if (*destRules != NULL) { // This is not the first rule encounted. @@ -1122,22 +1122,6 @@ void RBBIRuleScanner::parse() { return; } - // - // If there were NO user specified reverse rules, set up the equivalent of ".*;" - // - if (fRB->fReverseTree == NULL) { - fRB->fReverseTree = pushNewNode(RBBINode::opStar); - RBBINode *operand = pushNewNode(RBBINode::setRef); - if (U_FAILURE(*fRB->fStatus)) { - return; - } - findSetFor(UnicodeString(TRUE, kAny, 3), operand); - fRB->fReverseTree->fLeftChild = operand; - operand->fParent = fRB->fReverseTree; - fNodeStackPtr -= 2; - } - - // // Parsing of the input RBBI rules is complete. // We now have a parse tree for the rule expressions diff --git a/deps/icu-small/source/common/rbbisetb.cpp b/deps/icu-small/source/common/rbbisetb.cpp index 4e7389b4af0..e6b98cf3e22 100644 --- a/deps/icu-small/source/common/rbbisetb.cpp +++ b/deps/icu-small/source/common/rbbisetb.cpp @@ -270,15 +270,15 @@ void RBBISetBuilder::buildTrie() { } -void RBBISetBuilder::mergeCategories(int32_t left, int32_t right) { - U_ASSERT(left >= 1); - U_ASSERT(right > left); +void RBBISetBuilder::mergeCategories(IntPair categories) { + U_ASSERT(categories.first >= 1); + U_ASSERT(categories.second > categories.first); for (RangeDescriptor *rd = fRangeList; rd != nullptr; rd = rd->fNext) { int32_t rangeNum = rd->fNum & ~DICT_BIT; int32_t rangeDict = rd->fNum & DICT_BIT; - if (rangeNum == right) { - rd->fNum = left | rangeDict; - } else if (rangeNum > right) { + if (rangeNum == categories.second) { + rd->fNum = categories.first | rangeDict; + } else if (rangeNum > categories.second) { rd->fNum--; } } diff --git a/deps/icu-small/source/common/rbbisetb.h b/deps/icu-small/source/common/rbbisetb.h index a7a91b3b375..ed6a76b1214 100644 --- a/deps/icu-small/source/common/rbbisetb.h +++ b/deps/icu-small/source/common/rbbisetb.h @@ -94,10 +94,12 @@ public: UChar32 getFirstChar(int32_t val) const; UBool sawBOF() const; // Indicate whether any references to the {bof} pseudo // character were encountered. - /** merge two character categories that have been identified as having equivalent behavior. - * The ranges belonging to the right category (table column) will be added to the left. + /** + * Merge two character categories that have been identified as having equivalent behavior. + * The ranges belonging to the second category (table column) will be added to the first. + * @param categories the pair of categories to be merged. */ - void mergeCategories(int32_t left, int32_t right); + void mergeCategories(IntPair categories); static constexpr int32_t DICT_BIT = 0x4000; diff --git a/deps/icu-small/source/common/rbbitblb.cpp b/deps/icu-small/source/common/rbbitblb.cpp index 61661a54424..42116b0f955 100644 --- a/deps/icu-small/source/common/rbbitblb.cpp +++ b/deps/icu-small/source/common/rbbitblb.cpp @@ -27,21 +27,19 @@ U_NAMESPACE_BEGIN -RBBITableBuilder::RBBITableBuilder(RBBIRuleBuilder *rb, RBBINode **rootNode) : - fTree(*rootNode) { - fRB = rb; - fStatus = fRB->fStatus; - UErrorCode status = U_ZERO_ERROR; - fDStates = new UVector(status); - if (U_FAILURE(*fStatus)) { - return; - } +RBBITableBuilder::RBBITableBuilder(RBBIRuleBuilder *rb, RBBINode **rootNode, UErrorCode &status) : + fRB(rb), + fTree(*rootNode), + fStatus(&status), + fDStates(nullptr), + fSafeTable(nullptr) { if (U_FAILURE(status)) { - *fStatus = status; return; } - if (fDStates == NULL) { - *fStatus = U_MEMORY_ALLOCATION_ERROR;; + // fDStates is UVector + fDStates = new UVector(status); + if (U_SUCCESS(status) && fDStates == nullptr ) { + status = U_MEMORY_ALLOCATION_ERROR; } } @@ -52,17 +50,18 @@ RBBITableBuilder::~RBBITableBuilder() { for (i=0; isize(); i++) { delete (RBBIStateDescriptor *)fDStates->elementAt(i); } - delete fDStates; + delete fDStates; + delete fSafeTable; } //----------------------------------------------------------------------------- // -// RBBITableBuilder::build - This is the main function for building the DFA state transtion -// table from the RBBI rules parse tree. +// RBBITableBuilder::buildForwardTable - This is the main function for building +// the DFA state transition table from the RBBI rules parse tree. // //----------------------------------------------------------------------------- -void RBBITableBuilder::build() { +void RBBITableBuilder::buildForwardTable() { if (U_FAILURE(*fStatus)) { return; @@ -189,8 +188,6 @@ void RBBITableBuilder::build() { // for all tables. Merge the ones from this table into the global set. // mergeRuleStatusVals(); - - if (fRB->fDebugEnv && uprv_strstr(fRB->fDebugEnv, "states")) {printStates();}; } @@ -1081,18 +1078,18 @@ void RBBITableBuilder::printPosSets(RBBINode *n) { // // findDuplCharClassFrom() // -bool RBBITableBuilder::findDuplCharClassFrom(int32_t &baseCategory, int32_t &duplCategory) { +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 (; baseCategory < numCols-1; ++baseCategory) { - for (duplCategory=baseCategory+1; duplCategory < numCols; ++duplCategory) { + 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(baseCategory); - table_dupl = (uint16_t)sd->fDtran->elementAti(duplCategory); + table_base = (uint16_t)sd->fDtran->elementAti(categories->first); + table_dupl = (uint16_t)sd->fDtran->elementAti(categories->second); if (table_base != table_dupl) { break; } @@ -1121,14 +1118,14 @@ void RBBITableBuilder::removeColumn(int32_t column) { /* * findDuplicateState */ -bool RBBITableBuilder::findDuplicateState(int32_t &firstState, int32_t &duplState) { +bool RBBITableBuilder::findDuplicateState(IntPair *states) { int32_t numStates = fDStates->size(); int32_t numCols = fRB->fSetBuilder->getNumCharCategories(); - for (; firstStateelementAt(firstState); - for (duplState=firstState+1; duplStateelementAt(duplState); + for (; states->firstfirst++) { + RBBIStateDescriptor *firstSD = (RBBIStateDescriptor *)fDStates->elementAt(states->first); + for (states->second=states->first+1; states->secondsecond++) { + RBBIStateDescriptor *duplSD = (RBBIStateDescriptor *)fDStates->elementAt(states->second); if (firstSD->fAccepting != duplSD->fAccepting || firstSD->fLookAhead != duplSD->fLookAhead || firstSD->fTagsIdx != duplSD->fTagsIdx) { @@ -1139,8 +1136,8 @@ bool RBBITableBuilder::findDuplicateState(int32_t &firstState, int32_t &duplStat int32_t firstVal = firstSD->fDtran->elementAti(col); int32_t duplVal = duplSD->fDtran->elementAti(col); if (!((firstVal == duplVal) || - ((firstVal == firstState || firstVal == duplState) && - (duplVal == firstState || duplVal == duplState)))) { + ((firstVal == states->first || firstVal == states->second) && + (duplVal == states->first || duplVal == states->second)))) { rowsMatch = false; break; } @@ -1153,7 +1150,38 @@ bool RBBITableBuilder::findDuplicateState(int32_t &firstState, int32_t &duplStat return false; } -void RBBITableBuilder::removeState(int32_t keepState, int32_t duplState) { + +bool RBBITableBuilder::findDuplicateSafeState(IntPair *states) { + int32_t numStates = fSafeTable->size(); + + for (; states->firstfirst++) { + UnicodeString *firstRow = static_cast(fSafeTable->elementAt(states->first)); + for (states->second=states->first+1; states->secondsecond++) { + UnicodeString *duplRow = static_cast(fSafeTable->elementAt(states->second)); + bool rowsMatch = true; + int32_t numCols = firstRow->length(); + for (int32_t col=0; col < numCols; ++col) { + int32_t firstVal = firstRow->charAt(col); + int32_t duplVal = duplRow->charAt(col); + if (!((firstVal == duplVal) || + ((firstVal == states->first || firstVal == states->second) && + (duplVal == states->first || duplVal == states->second)))) { + rowsMatch = false; + break; + } + } + if (rowsMatch) { + return true; + } + } + } + return false; +} + + +void RBBITableBuilder::removeState(IntPair duplStates) { + const int32_t keepState = duplStates.first; + const int32_t duplState = duplStates.second; U_ASSERT(keepState < duplState); U_ASSERT(duplState < fDStates->size()); @@ -1188,19 +1216,44 @@ void RBBITableBuilder::removeState(int32_t keepState, int32_t duplState) { } } +void RBBITableBuilder::removeSafeState(IntPair duplStates) { + const int32_t keepState = duplStates.first; + const int32_t duplState = duplStates.second; + U_ASSERT(keepState < duplState); + U_ASSERT(duplState < fSafeTable->size()); + + fSafeTable->removeElementAt(duplState); // Note that fSafeTable has a deleter function + // and will auto-delete the removed element. + int32_t numStates = fSafeTable->size(); + for (int32_t state=0; stateelementAt(state); + int32_t numCols = sd->length(); + for (int32_t col=0; colcharAt(col); + int32_t newVal = existingVal; + if (existingVal == duplState) { + newVal = keepState; + } else if (existingVal > duplState) { + newVal = existingVal - 1; + } + sd->setCharAt(col, newVal); + } + } +} + /* * RemoveDuplicateStates */ void RBBITableBuilder::removeDuplicateStates() { - int32_t firstState = 3; - int32_t duplicateState = 0; - while (findDuplicateState(firstState, duplicateState)) { - // printf("Removing duplicate states (%d, %d)\n", firstState, duplicateState); - removeState(firstState, duplicateState); + IntPair dupls = {3, 0}; + while (findDuplicateState(&dupls)) { + // printf("Removing duplicate states (%d, %d)\n", dupls.first, dupls.second); + removeState(dupls); } } + //----------------------------------------------------------------------------- // // getTableSize() Calculate the size of the runtime form of this @@ -1277,6 +1330,185 @@ void RBBITableBuilder::exportTable(void *where) { } +/** + * Synthesize a safe state table from the main state table. + */ +void RBBITableBuilder::buildSafeReverseTable(UErrorCode &status) { + // The safe table creation has three steps: + + // 1. Identifiy pairs of character classes that are "safe." Safe means that boundaries + // following the pair do not depend on context or state before the pair. To test + // whether a pair is safe, run it through the main forward state table, starting + // from each state. If the the final state is the same, no matter what the starting state, + // the pair is safe. + // + // 2. Build a state table that recognizes the safe pairs. It's similar to their + // forward table, with a column for each input character [class], and a row for + // each state. Row 1 is the start state, and row 0 is the stop state. Initially + // create an additional state for each input character category; being in + // one of these states means that the character has been seen, and is potentially + // the first of a pair. In each of these rows, the entry for the second character + // of a safe pair is set to the stop state (0), indicating that a match was found. + // All other table entries are set to the state corresponding the current input + // character, allowing that charcter to be the of a start following pair. + // + // Because the safe rules are to be run in reverse, moving backwards in the text, + // the first and second pair categories are swapped when building the table. + // + // 3. Compress the table. There are typically many rows (states) that are + // equivalent - that have zeroes (match completed) in the same columns - + // and can be folded together. + + // Each safe pair is stored as two UChars in the safePair string. + UnicodeString safePairs; + + int32_t numCharClasses = fRB->fSetBuilder->getNumCharCategories(); + int32_t numStates = fDStates->size(); + + for (int32_t c1=0; c1(fDStates->elementAt(startState)); + int32_t s2 = startStateD->fDtran->elementAti(c1); + RBBIStateDescriptor *s2StateD = static_cast(fDStates->elementAt(s2)); + endState = s2StateD->fDtran->elementAti(c2); + if (wantedEndState < 0) { + wantedEndState = endState; + } else { + if (wantedEndState != endState) { + break; + } + } + } + if (wantedEndState == endState) { + safePairs.append((char16_t)c1); + safePairs.append((char16_t)c2); + // printf("(%d, %d) ", c1, c2); + } + } + // printf("\n"); + } + + // Populate the initial safe table. + // The table as a whole is UVector + // Each row is represented by a UnicodeString, being used as a Vector. + // Row 0 is the stop state. + // Row 1 is the start sate. + // Row 2 and beyond are other states, initially one per char class, but + // after initial construction, many of the states will be combined, compacting the table. + // The String holds the nextState data only. The four leading fields of a row, fAccepting, + // fLookAhead, etc. are not needed for the safe table, and are omitted at this stage of building. + + U_ASSERT(fSafeTable == nullptr); + fSafeTable = new UVector(uprv_deleteUObject, uhash_compareUnicodeString, numCharClasses + 2, status); + for (int32_t row=0; rowaddElement(new UnicodeString(numCharClasses, 0, numCharClasses+4), status); + } + + // From the start state, each input char class transitions to the state for that input. + 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); + } + + // Initially make every other state table row look like the start state row, + for (int32_t row=2; row(fSafeTable->elementAt(row)); + rowState = startState; // UnicodeString assignment, copies contents. + } + + // Run through the safe pairs, set the next state to zero when pair has been seen. + // Zero being the stop state, meaning we found a safe point. + for (int32_t pairIdx=0; pairIdx(fSafeTable->elementAt(c2 + 2)); + rowState.setCharAt(c1, 0); + } + + // Remove duplicate or redundant rows from the table. + IntPair states = {1, 0}; + while (findDuplicateSafeState(&states)) { + // printf("Removing duplicate safe states (%d, %d)\n", states.first, states.second); + removeSafeState(states); + } +} + + +//----------------------------------------------------------------------------- +// +// getSafeTableSize() Calculate the size of the runtime form of this +// safe state table. +// +//----------------------------------------------------------------------------- +int32_t RBBITableBuilder::getSafeTableSize() const { + int32_t size = 0; + int32_t numRows; + int32_t numCols; + int32_t rowSize; + + if (fSafeTable == nullptr) { + return 0; + } + + size = offsetof(RBBIStateTable, fTableData); // The header, with no rows to the table. + + numRows = fSafeTable->size(); + numCols = fRB->fSetBuilder->getNumCharCategories(); + + rowSize = offsetof(RBBIStateTableRow, fNextState) + sizeof(uint16_t)*numCols; + size += numRows * rowSize; + return size; +} + + +//----------------------------------------------------------------------------- +// +// exportSafeTable() export the state transition table in the format required +// by the runtime engine. getTableSize() bytes of memory +// must be available at the output address "where". +// +//----------------------------------------------------------------------------- +void RBBITableBuilder::exportSafeTable(void *where) { + RBBIStateTable *table = (RBBIStateTable *)where; + uint32_t state; + int col; + + if (U_FAILURE(*fStatus) || fSafeTable == nullptr) { + return; + } + + int32_t catCount = fRB->fSetBuilder->getNumCharCategories(); + if (catCount > 0x7fff || + fSafeTable->size() > 0x7fff) { + *fStatus = U_BRK_INTERNAL_ERROR; + return; + } + + table->fRowLen = offsetof(RBBIStateTableRow, fNextState) + sizeof(uint16_t) * catCount; + table->fNumStates = fSafeTable->size(); + table->fFlags = 0; + table->fReserved = 0; + + for (state=0; statefNumStates; state++) { + UnicodeString *rowString = (UnicodeString *)fSafeTable->elementAt(state); + RBBIStateTableRow *row = (RBBIStateTableRow *)(table->fTableData + state*table->fRowLen); + row->fAccepting = 0; + row->fLookAhead = 0; + row->fTagIdx = 0; + row->fReserved = 0; + for (col=0; colfNextState[col] = rowString->charAt(col); + } + } +} + + + //----------------------------------------------------------------------------- // @@ -1331,6 +1563,47 @@ void RBBITableBuilder::printStates() { #endif +//----------------------------------------------------------------------------- +// +// printSafeTable Debug Function. Dump the fully constructed safe table. +// +//----------------------------------------------------------------------------- +#ifdef RBBI_DEBUG +void RBBITableBuilder::printReverseTable() { + int c; // input "character" + int n; // state number + + RBBIDebugPrintf(" Safe Reverse Table \n"); + if (fSafeTable == nullptr) { + RBBIDebugPrintf(" --- nullptr ---\n"); + return; + } + RBBIDebugPrintf("state | i n p u t s y m b o l s \n"); + RBBIDebugPrintf(" | Acc LA Tag"); + for (c=0; cfSetBuilder->getNumCharCategories(); c++) { + RBBIDebugPrintf(" %2d", c); + } + RBBIDebugPrintf("\n"); + RBBIDebugPrintf(" |---------------"); + for (c=0; cfSetBuilder->getNumCharCategories(); c++) { + RBBIDebugPrintf("---"); + } + RBBIDebugPrintf("\n"); + + for (n=0; nsize(); n++) { + UnicodeString *rowString = (UnicodeString *)fSafeTable->elementAt(n); + RBBIDebugPrintf(" %3d | " , n); + RBBIDebugPrintf("%3d %3d %5d ", 0, 0, 0); // Accepting, LookAhead, Tags + for (c=0; cfSetBuilder->getNumCharCategories(); c++) { + RBBIDebugPrintf(" %2d", rowString->charAt(c)); + } + RBBIDebugPrintf("\n"); + } + RBBIDebugPrintf("\n\n"); +} +#endif + + //----------------------------------------------------------------------------- // diff --git a/deps/icu-small/source/common/rbbitblb.h b/deps/icu-small/source/common/rbbitblb.h index 09b57b5cf0f..eea243e4cdd 100644 --- a/deps/icu-small/source/common/rbbitblb.h +++ b/deps/icu-small/source/common/rbbitblb.h @@ -17,6 +17,7 @@ #include "unicode/utypes.h" #include "unicode/uobject.h" #include "unicode/rbbi.h" +#include "rbbirb.h" #include "rbbinode.h" @@ -37,22 +38,28 @@ class UVector32; class RBBITableBuilder : public UMemory { public: - RBBITableBuilder(RBBIRuleBuilder *rb, RBBINode **rootNode); + RBBITableBuilder(RBBIRuleBuilder *rb, RBBINode **rootNode, UErrorCode &status); ~RBBITableBuilder(); - void build(); - int32_t getTableSize() const; // Return the runtime size in bytes of - // the built state table + void buildForwardTable(); + + /** Return the runtime size in bytes of the built state table. */ + int32_t getTableSize() const; /** Fill in the runtime state table. Sufficient memory must exist at the specified location. */ void exportTable(void *where); - /** Find duplicate (redundant) character classes, beginning after the specifed - * pair, within this state table. This is an iterator-like function, used to - * identify char classes (state table columns) that can be eliminated. + /** + * Find duplicate (redundant) character classes. Begin looking with categories.first. + * Duplicate, if found are returned in the categories parameter. + * This is an iterator-like function, used to identify character classes + * (state table columns) that can be eliminated. + * @param categories in/out parameter, specifies where to start looking for duplicates, + * and returns the first pair of duplicates found, if any. + * @return true if duplicate char classes were found, false otherwise. */ - bool findDuplCharClassFrom(int &baseClass, int &duplClass); + bool findDuplCharClassFrom(IntPair *categories); /** Remove a column from the state table. Used when two character categories * have been found equivalent, and merged together, to eliminate the uneeded table column. @@ -62,6 +69,16 @@ public: /** Check for, and remove dupicate states (table rows). */ void removeDuplicateStates(); + /** Build the safe reverse table from the already-constructed forward table. */ + void buildSafeReverseTable(UErrorCode &status); + + /** Return the runtime size in bytes of the built safe reverse state table. */ + int32_t getSafeTableSize() const; + + /** Fill in the runtime safe state table. Sufficient memory must exist at the specified location. + */ + void exportSafeTable(void *where); + private: void calcNullable(RBBINode *n); @@ -84,20 +101,36 @@ private: void addRuleRootNodes(UVector *dest, RBBINode *node); - /** Find the next duplicate state. An iterator function. - * @param firstState (in/out) begin looking at this state, return the first of the - * pair of duplicates. - * @param duplicateState returns the duplicate state of fistState - * @return true if a duplicate pair of states was found. + /** + * Find duplicate (redundant) states, beginning at the specified pair, + * within this state table. This is an iterator-like function, used to + * identify states (state table rows) that can be eliminated. + * @param states in/out parameter, specifies where to start looking for duplicates, + * and returns the first pair of duplicates found, if any. + * @return true if duplicate states were found, false otherwise. */ - bool findDuplicateState(int32_t &firstState, int32_t &duplicateState); + bool findDuplicateState(IntPair *states); - /** Remove a duplicate state/ - * @param keepState First of the duplicate pair. Keep it. - * @param duplState Duplicate state. Remove it. Redirect all references to the duplicate state - * to refer to keepState instead. + /** Remove a duplicate state. + * @param duplStates The duplicate states. The first is kept, the second is removed. + * All references to the second in the state table are retargeted + * to the first. */ - void removeState(int32_t keepState, int32_t duplState); + void removeState(IntPair duplStates); + + /** Find the next duplicate state in the safe reverse table. An iterator function. + * @param states in/out parameter, specifies where to start looking for duplicates, + * and returns the first pair of duplicates found, if any. + * @return true if a duplicate pair of states was found. + */ + bool findDuplicateSafeState(IntPair *states); + + /** Remove a duplicate state from the safe table. + * @param duplStates The duplicate states. The first is kept, the second is removed. + * All references to the second in the state table are retargeted + * to the first. + */ + void removeSafeState(IntPair duplStates); // Set functions for UVector. // TODO: make a USet subclass of UVector @@ -113,11 +146,13 @@ public: void printPosSets(RBBINode *n /* = NULL*/); void printStates(); void printRuleStatusTable(); + void printReverseTable(); #else #define printSet(s) #define printPosSets(n) #define printStates() #define printRuleStatusTable() + #define printReverseTable() #endif private: @@ -126,10 +161,14 @@ private: // table for. UErrorCode *fStatus; + /** State Descriptors, UVector */ UVector *fDStates; // D states (Aho's terminology) // Index is state number // Contents are RBBIStateDescriptor pointers. + /** Synthesized safe table, UVector of UnicodeString, one string per table row. */ + UVector *fSafeTable; + RBBITableBuilder(const RBBITableBuilder &other); // forbid copying of this class RBBITableBuilder &operator=(const RBBITableBuilder &other); // forbid copying of this class diff --git a/deps/icu-small/source/common/serv.cpp b/deps/icu-small/source/common/serv.cpp index 8913b21e694..35e362b71a8 100644 --- a/deps/icu-small/source/common/serv.cpp +++ b/deps/icu-small/source/common/serv.cpp @@ -547,16 +547,15 @@ outerEnd: if (putInCache && cacheResult) { serviceCache->put(result->actualDescriptor, result, status); if (U_FAILURE(status)) { - delete result; return NULL; } if (cacheDescriptorList._obj != NULL) { for (int32_t i = cacheDescriptorList._obj->size(); --i >= 0;) { UnicodeString* desc = (UnicodeString*)cacheDescriptorList._obj->elementAt(i); + serviceCache->put(*desc, result, status); if (U_FAILURE(status)) { - delete result; return NULL; } diff --git a/deps/icu-small/source/common/static_unicode_sets.cpp b/deps/icu-small/source/common/static_unicode_sets.cpp new file mode 100644 index 00000000000..9e731f5781e --- /dev/null +++ b/deps/icu-small/source/common/static_unicode_sets.cpp @@ -0,0 +1,222 @@ +// © 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 "static_unicode_sets.h" +#include "umutex.h" +#include "ucln_cmn.h" +#include "unicode/uniset.h" +#include "uresimp.h" +#include "cstring.h" +#include "uassert.h" + +using namespace icu; +using namespace icu::unisets; + + +namespace { + +UnicodeSet* gUnicodeSets[COUNT] = {}; + +// Save the empty instance in static memory to have well-defined behavior if a +// regular UnicodeSet cannot be allocated. +char gEmptyUnicodeSet[sizeof(UnicodeSet)]; + +// Whether the gEmptyUnicodeSet is initialized and ready to use. +UBool gEmptyUnicodeSetInitialized = FALSE; + +inline UnicodeSet* getImpl(Key key) { + UnicodeSet* candidate = gUnicodeSets[key]; + if (candidate == nullptr) { + return reinterpret_cast(gEmptyUnicodeSet); + } + return candidate; +} + +UnicodeSet* computeUnion(Key k1, Key k2) { + UnicodeSet* result = new UnicodeSet(); + if (result == nullptr) { + return nullptr; + } + result->addAll(*getImpl(k1)); + result->addAll(*getImpl(k2)); + result->freeze(); + return result; +} + +UnicodeSet* computeUnion(Key k1, Key k2, Key k3) { + UnicodeSet* result = new UnicodeSet(); + if (result == nullptr) { + return nullptr; + } + result->addAll(*getImpl(k1)); + result->addAll(*getImpl(k2)); + result->addAll(*getImpl(k3)); + result->freeze(); + return result; +} + + +void saveSet(Key key, const UnicodeString& unicodeSetPattern, UErrorCode& status) { + // assert unicodeSets.get(key) == null; + gUnicodeSets[key] = new UnicodeSet(unicodeSetPattern, status); +} + +class ParseDataSink : public ResourceSink { + public: + void put(const char* key, ResourceValue& value, UBool /*noFallback*/, UErrorCode& status) U_OVERRIDE { + ResourceTable contextsTable = value.getTable(status); + if (U_FAILURE(status)) { return; } + for (int i = 0; contextsTable.getKeyAndValue(i, key, value); i++) { + if (uprv_strcmp(key, "date") == 0) { + // ignore + } else { + ResourceTable strictnessTable = value.getTable(status); + if (U_FAILURE(status)) { return; } + for (int j = 0; strictnessTable.getKeyAndValue(j, key, value); j++) { + bool isLenient = (uprv_strcmp(key, "lenient") == 0); + ResourceArray array = value.getArray(status); + if (U_FAILURE(status)) { return; } + for (int k = 0; k < array.getSize(); k++) { + array.getValue(k, value); + UnicodeString str = value.getUnicodeString(status); + if (U_FAILURE(status)) { return; } + // There is both lenient and strict data for comma/period, + // but not for any of the other symbols. + if (str.indexOf(u'.') != -1) { + saveSet(isLenient ? PERIOD : STRICT_PERIOD, str, status); + } else if (str.indexOf(u',') != -1) { + saveSet(isLenient ? COMMA : STRICT_COMMA, str, status); + } else if (str.indexOf(u'+') != -1) { + saveSet(PLUS_SIGN, str, status); + } else if (str.indexOf(u'‒') != -1) { + saveSet(MINUS_SIGN, str, status); + } else if (str.indexOf(u'$') != -1) { + saveSet(DOLLAR_SIGN, str, status); + } else if (str.indexOf(u'£') != -1) { + saveSet(POUND_SIGN, str, status); + } else if (str.indexOf(u'₨') != -1) { + saveSet(RUPEE_SIGN, str, status); + } + if (U_FAILURE(status)) { return; } + } + } + } + } + } +}; + + +icu::UInitOnce gNumberParseUniSetsInitOnce = U_INITONCE_INITIALIZER; + +UBool U_CALLCONV cleanupNumberParseUniSets() { + if (gEmptyUnicodeSetInitialized) { + reinterpret_cast(gEmptyUnicodeSet)->~UnicodeSet(); + gEmptyUnicodeSetInitialized = FALSE; + } + for (int32_t i = 0; i < COUNT; i++) { + delete gUnicodeSets[i]; + gUnicodeSets[i] = nullptr; + } + gNumberParseUniSetsInitOnce.reset(); + return TRUE; +} + +void U_CALLCONV initNumberParseUniSets(UErrorCode& status) { + ucln_common_registerCleanup(UCLN_COMMON_NUMPARSE_UNISETS, cleanupNumberParseUniSets); + + // Initialize the empty instance for well-defined fallback behavior + new(gEmptyUnicodeSet) UnicodeSet(); + reinterpret_cast(gEmptyUnicodeSet)->freeze(); + gEmptyUnicodeSetInitialized = TRUE; + + // These sets were decided after discussion with icu-design@. See tickets #13084 and #13309. + // Zs+TAB is "horizontal whitespace" according to UTS #18 (blank property). + gUnicodeSets[DEFAULT_IGNORABLES] = new UnicodeSet( + u"[[:Zs:][\\u0009][:Bidi_Control:][:Variation_Selector:]]", status); + gUnicodeSets[STRICT_IGNORABLES] = new UnicodeSet(u"[[:Bidi_Control:]]", status); + + LocalUResourceBundlePointer rb(ures_open(nullptr, "root", &status)); + if (U_FAILURE(status)) { return; } + ParseDataSink sink; + ures_getAllItemsWithFallback(rb.getAlias(), "parse", sink, status); + if (U_FAILURE(status)) { return; } + + // NOTE: It is OK for these assertions to fail if there was a no-data build. + U_ASSERT(gUnicodeSets[COMMA] != nullptr); + U_ASSERT(gUnicodeSets[STRICT_COMMA] != nullptr); + U_ASSERT(gUnicodeSets[PERIOD] != nullptr); + U_ASSERT(gUnicodeSets[STRICT_PERIOD] != nullptr); + + gUnicodeSets[OTHER_GROUPING_SEPARATORS] = new UnicodeSet( + u"['٬‘’'\\u0020\\u00A0\\u2000-\\u200A\\u202F\\u205F\\u3000]", status); + gUnicodeSets[ALL_SEPARATORS] = computeUnion(COMMA, PERIOD, OTHER_GROUPING_SEPARATORS); + gUnicodeSets[STRICT_ALL_SEPARATORS] = computeUnion( + STRICT_COMMA, STRICT_PERIOD, OTHER_GROUPING_SEPARATORS); + + U_ASSERT(gUnicodeSets[MINUS_SIGN] != nullptr); + U_ASSERT(gUnicodeSets[PLUS_SIGN] != nullptr); + + gUnicodeSets[PERCENT_SIGN] = new UnicodeSet(u"[%٪]", status); + gUnicodeSets[PERMILLE_SIGN] = new UnicodeSet(u"[‰؉]", status); + gUnicodeSets[INFINITY_KEY] = new UnicodeSet(u"[∞]", status); + + U_ASSERT(gUnicodeSets[DOLLAR_SIGN] != nullptr); + U_ASSERT(gUnicodeSets[POUND_SIGN] != nullptr); + U_ASSERT(gUnicodeSets[RUPEE_SIGN] != nullptr); + gUnicodeSets[YEN_SIGN] = new UnicodeSet(u"[¥\\uffe5]", status); + + gUnicodeSets[DIGITS] = new UnicodeSet(u"[:digit:]", status); + + gUnicodeSets[DIGITS_OR_ALL_SEPARATORS] = computeUnion(DIGITS, ALL_SEPARATORS); + gUnicodeSets[DIGITS_OR_STRICT_ALL_SEPARATORS] = computeUnion(DIGITS, STRICT_ALL_SEPARATORS); + + for (auto* uniset : gUnicodeSets) { + if (uniset != nullptr) { + uniset->freeze(); + } + } +} + +} + +const UnicodeSet* unisets::get(Key key) { + UErrorCode localStatus = U_ZERO_ERROR; + umtx_initOnce(gNumberParseUniSetsInitOnce, &initNumberParseUniSets, localStatus); + if (U_FAILURE(localStatus)) { + return reinterpret_cast(gEmptyUnicodeSet); + } + return getImpl(key); +} + +Key unisets::chooseFrom(UnicodeString str, Key key1) { + return get(key1)->contains(str) ? key1 : NONE; +} + +Key unisets::chooseFrom(UnicodeString str, Key key1, Key key2) { + return get(key1)->contains(str) ? key1 : chooseFrom(str, key2); +} + +//Key unisets::chooseCurrency(UnicodeString str) { +// if (get(DOLLAR_SIGN)->contains(str)) { +// return DOLLAR_SIGN; +// } else if (get(POUND_SIGN)->contains(str)) { +// return POUND_SIGN; +// } else if (get(RUPEE_SIGN)->contains(str)) { +// return RUPEE_SIGN; +// } else if (get(YEN_SIGN)->contains(str)) { +// return YEN_SIGN; +// } else { +// return NONE; +// } +//} + + +#endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/deps/icu-small/source/common/static_unicode_sets.h b/deps/icu-small/source/common/static_unicode_sets.h new file mode 100644 index 00000000000..5f18b3217ea --- /dev/null +++ b/deps/icu-small/source/common/static_unicode_sets.h @@ -0,0 +1,119 @@ +// © 2018 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html + +// This file is in common instead of i18n because it is needed by ucurr.cpp. + +#include "unicode/utypes.h" + +#if !UCONFIG_NO_FORMATTING +#ifndef __STATIC_UNICODE_SETS_H__ +#define __STATIC_UNICODE_SETS_H__ + +#include "unicode/uniset.h" +#include "unicode/unistr.h" + +U_NAMESPACE_BEGIN +namespace unisets { + +enum Key { + // NONE is used to indicate null in chooseFrom(). + // EMPTY is used to get an empty UnicodeSet. + NONE = -1, + EMPTY = 0, + + // Ignorables + DEFAULT_IGNORABLES, + STRICT_IGNORABLES, + + // Separators + // Notes: + // - COMMA is a superset of STRICT_COMMA + // - PERIOD is a superset of SCRICT_PERIOD + // - ALL_SEPARATORS is the union of COMMA, PERIOD, and OTHER_GROUPING_SEPARATORS + // - STRICT_ALL_SEPARATORS is the union of STRICT_COMMA, STRICT_PERIOD, and OTHER_GRP_SEPARATORS + COMMA, + PERIOD, + STRICT_COMMA, + STRICT_PERIOD, + OTHER_GROUPING_SEPARATORS, + ALL_SEPARATORS, + STRICT_ALL_SEPARATORS, + + // Symbols + MINUS_SIGN, + PLUS_SIGN, + PERCENT_SIGN, + PERMILLE_SIGN, + INFINITY_KEY, // INFINITY is defined in cmath + + // Currency Symbols + DOLLAR_SIGN, + POUND_SIGN, + RUPEE_SIGN, + YEN_SIGN, // not in CLDR data, but Currency.java wants it + + // Other + DIGITS, + + // Combined Separators with Digits (for lead code points) + DIGITS_OR_ALL_SEPARATORS, + DIGITS_OR_STRICT_ALL_SEPARATORS, + + // The number of elements in the enum. + COUNT +}; + +/** + * Gets the static-allocated UnicodeSet according to the provided key. The + * pointer will be deleted during u_cleanup(); the caller should NOT delete it. + * + * Exported as U_COMMON_API for ucurr.cpp + * + * @param key The desired UnicodeSet according to the enum in this file. + * @return The requested UnicodeSet. Guaranteed to be frozen and non-null, but + * may be empty if an error occurred during data loading. + */ +U_COMMON_API const UnicodeSet* get(Key key); + +/** + * Checks if the UnicodeSet given by key1 contains the given string. + * + * Exported as U_COMMON_API for numparse_decimal.cpp + * + * @param str The string to check. + * @param key1 The set to check. + * @return key1 if the set contains str, or NONE if not. + */ +U_COMMON_API Key chooseFrom(UnicodeString str, Key key1); + +/** + * Checks if the UnicodeSet given by either key1 or key2 contains the string. + * + * Exported as U_COMMON_API for numparse_decimal.cpp + * + * @param str The string to check. + * @param key1 The first set to check. + * @param key2 The second set to check. + * @return key1 if that set contains str; key2 if that set contains str; or + * NONE if neither set contains str. + */ +U_COMMON_API Key chooseFrom(UnicodeString str, Key key1, Key key2); + +// Unused in C++: +// Key chooseCurrency(UnicodeString str); +// Used instead: +static const struct { + Key key; + UChar32 exemplar; +} kCurrencyEntries[] = { + {DOLLAR_SIGN, u'$'}, + {POUND_SIGN, u'£'}, + {RUPEE_SIGN, u'₨'}, + {YEN_SIGN, u'¥'}, +}; + +} // namespace unisets +U_NAMESPACE_END + +#endif //__STATIC_UNICODE_SETS_H__ +#endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/deps/icu-small/source/common/ubidi_props_data.h b/deps/icu-small/source/common/ubidi_props_data.h index 98f21510e7d..55e331b612e 100644 --- a/deps/icu-small/source/common/ubidi_props_data.h +++ b/deps/icu-small/source/common/ubidi_props_data.h @@ -11,538 +11,539 @@ #ifdef INCLUDED_FROM_UBIDI_PROPS_C -static const UVersionInfo ubidi_props_dataVersion={0xa,0,0,0}; +static const UVersionInfo ubidi_props_dataVersion={0xb,0,0,0}; -static const int32_t ubidi_props_indexes[UBIDI_IX_TOP]={0x10,0x6028,0x5cb0,0x1a,0x620,0x8c0,0x10ac0,0x10af0,0,0,0,0,0,0,0,0x6302b6}; +static const int32_t ubidi_props_indexes[UBIDI_IX_TOP]={0x10,0x647c,0x5e98,0x28,0x620,0x8c0,0x10ac0,0x10d24,0,0,0,0,0,0,0,0x6502b6}; -static const uint16_t ubidi_props_trieIndex[11856]={ -0x36a,0x372,0x37a,0x382,0x39a,0x3a2,0x3aa,0x3b2,0x38a,0x392,0x38a,0x392,0x38a,0x392,0x38a,0x392, -0x38a,0x392,0x38a,0x392,0x3b8,0x3c0,0x3c8,0x3d0,0x3d8,0x3e0,0x3dc,0x3e4,0x3ec,0x3f4,0x3ef,0x3f7, -0x38a,0x392,0x38a,0x392,0x3ff,0x407,0x38a,0x392,0x38a,0x392,0x38a,0x392,0x40d,0x415,0x41d,0x425, -0x42d,0x435,0x43d,0x445,0x44b,0x453,0x45b,0x463,0x46b,0x473,0x479,0x481,0x489,0x491,0x499,0x4a1, -0x4ad,0x4a9,0x4b5,0x4bd,0x41f,0x4cd,0x4d5,0x4c5,0x4dd,0x4df,0x4e7,0x4ef,0x4f7,0x4f8,0x500,0x508, -0x510,0x4f8,0x518,0x51d,0x510,0x4f8,0x525,0x52d,0x4f7,0x535,0x53d,0x4ef,0x542,0x38a,0x54a,0x54e, -0x556,0x557,0x55f,0x567,0x4f7,0x56f,0x577,0x4ef,0x401,0x57b,0x500,0x4ef,0x38a,0x38a,0x583,0x38a, -0x38a,0x589,0x591,0x38a,0x38a,0x595,0x59d,0x38a,0x5a1,0x5a8,0x38a,0x5b0,0x5b8,0x5bf,0x541,0x38a, -0x38a,0x5c7,0x5cf,0x5d7,0x5df,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x5e7,0x38a,0x5ef,0x38a,0x38a,0x38a, -0x5f7,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x5ff,0x38a,0x38a,0x38a,0x607,0x607,0x504,0x504,0x38a,0x60d,0x615,0x5ef, -0x62b,0x61d,0x61d,0x633,0x63a,0x623,0x38a,0x38a,0x38a,0x642,0x64a,0x38a,0x38a,0x38a,0x64c,0x654, -0x65c,0x38a,0x663,0x66b,0x38a,0x673,0x38a,0x38a,0x534,0x67b,0x542,0x683,0x401,0x68b,0x38a,0x692, -0x38a,0x697,0x38a,0x38a,0x38a,0x38a,0x69d,0x6a5,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x3d8,0x6ad, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x6b5,0x6bd,0x6c1, -0x6d9,0x6df,0x6c9,0x6d1,0x6e7,0x6ef,0x6f3,0x5c2,0x6fb,0x703,0x70b,0x38a,0x713,0x654,0x654,0x654, -0x723,0x72b,0x733,0x73b,0x740,0x748,0x750,0x71b,0x758,0x760,0x38a,0x766,0x76d,0x654,0x654,0x654, -0x654,0x56d,0x773,0x654,0x77b,0x38a,0x38a,0x651,0x654,0x654,0x654,0x654,0x654,0x654,0x654,0x654, -0x654,0x654,0x654,0x654,0x654,0x783,0x654,0x654,0x654,0x654,0x654,0x789,0x654,0x654,0x791,0x799, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x654,0x654,0x654,0x654,0x7a9,0x7b0,0x7b8,0x7a1, -0x7c8,0x7d0,0x7d8,0x7df,0x7e7,0x7ef,0x7f6,0x7c0,0x654,0x654,0x654,0x7fe,0x804,0x80a,0x812,0x817, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x81e,0x38a,0x38a,0x38a,0x826,0x38a,0x38a,0x38a,0x3d8, -0x82e,0x836,0x763,0x38a,0x839,0x654,0x654,0x657,0x654,0x654,0x654,0x654,0x654,0x654,0x840,0x846, -0x856,0x84e,0x38a,0x38a,0x85e,0x5f7,0x38a,0x3b1,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x654,0x825, -0x3bf,0x38a,0x866,0x86e,0x38a,0x876,0x817,0x38a,0x38a,0x38a,0x38a,0x87e,0x38a,0x38a,0x64c,0x3b0, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x654,0x654, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x866,0x654,0x56d,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x885,0x38a,0x38a,0x88a,0x557,0x38a,0x38a,0x5a3,0x654,0x64b,0x38a,0x38a,0x892,0x38a,0x38a,0x38a, -0x89a,0x8a1,0x61d,0x8a9,0x38a,0x38a,0x579,0x8b1,0x38a,0x8b8,0x8bf,0x38a,0x4dd,0x8c4,0x38a,0x4f6, -0x38a,0x8cc,0x8d4,0x4f8,0x38a,0x8d8,0x4f7,0x8e0,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x8e7, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x8fb,0x8ef,0x8f3,0x489,0x489,0x489,0x489,0x489, -0x489,0x489,0x489,0x489,0x489,0x489,0x489,0x489,0x489,0x903,0x489,0x489,0x489,0x489,0x90b,0x90f, -0x917,0x91f,0x923,0x92b,0x489,0x489,0x489,0x92f,0x937,0x37a,0x93f,0x947,0x38a,0x38a,0x38a,0x94f, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0xe28,0xe28,0xe68,0xea8,0xe28,0xe28,0xe28,0xe28,0xe28,0xe28,0xee0,0xf20,0xf60,0xf70,0xfb0,0xfbc, -0xe28,0xe28,0xffc,0xe28,0xe28,0xe28,0x1034,0x1074,0x10b4,0x10f4,0x112c,0x116c,0x11ac,0x11e4,0x1224,0x1264, -0xa40,0xa80,0xac0,0xafa,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0xb25,0x1a0,0x1a0, -0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0xb62,0x1a0,0x1a0,0xb97,0xbd7,0xc17,0xc57,0xc97,0xcd7, +static const uint16_t ubidi_props_trieIndex[12100]={ +0x36f,0x377,0x37f,0x387,0x39f,0x3a7,0x3af,0x3b7,0x38f,0x397,0x38f,0x397,0x38f,0x397,0x38f,0x397, +0x38f,0x397,0x38f,0x397,0x3bd,0x3c5,0x3cd,0x3d5,0x3dd,0x3e5,0x3e1,0x3e9,0x3f1,0x3f9,0x3f4,0x3fc, +0x38f,0x397,0x38f,0x397,0x404,0x40c,0x38f,0x397,0x38f,0x397,0x38f,0x397,0x412,0x41a,0x422,0x42a, +0x432,0x43a,0x442,0x44a,0x450,0x458,0x460,0x468,0x470,0x478,0x47e,0x486,0x48e,0x496,0x49e,0x4a6, +0x4b2,0x4ae,0x4ba,0x4c2,0x424,0x4d2,0x4da,0x4ca,0x4e2,0x4e4,0x4ec,0x4f4,0x4fc,0x4fd,0x505,0x50d, +0x515,0x4fd,0x51d,0x522,0x515,0x4fd,0x52a,0x532,0x4fc,0x53a,0x542,0x4f4,0x547,0x38f,0x54f,0x553, +0x55b,0x55d,0x565,0x56d,0x4fc,0x575,0x57d,0x4f4,0x406,0x581,0x505,0x4f4,0x38f,0x38f,0x589,0x38f, +0x38f,0x58f,0x597,0x38f,0x38f,0x59b,0x5a3,0x38f,0x5a7,0x5ae,0x38f,0x5b6,0x5be,0x5c5,0x546,0x38f, +0x38f,0x5cd,0x5d5,0x5dd,0x5e5,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x5ed,0x38f,0x5f5,0x38f,0x38f,0x38f, +0x5fd,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x605,0x38f,0x38f,0x38f,0x60d,0x60d,0x509,0x509,0x38f,0x613,0x61b,0x5f5, +0x631,0x623,0x623,0x639,0x640,0x629,0x38f,0x38f,0x38f,0x648,0x650,0x38f,0x38f,0x38f,0x652,0x65a, +0x662,0x38f,0x669,0x671,0x38f,0x679,0x38f,0x38f,0x539,0x681,0x547,0x689,0x406,0x691,0x38f,0x698, +0x38f,0x69d,0x38f,0x38f,0x38f,0x38f,0x6a3,0x6ab,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x3dd,0x6b3, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x6bb,0x6c3,0x6c7, +0x6df,0x6e5,0x6cf,0x6d7,0x6ed,0x6f5,0x6f9,0x5c8,0x701,0x709,0x711,0x38f,0x719,0x65a,0x65a,0x65a, +0x729,0x731,0x739,0x741,0x746,0x74e,0x756,0x721,0x75e,0x766,0x38f,0x76c,0x773,0x65a,0x65a,0x65a, +0x65a,0x573,0x779,0x65a,0x781,0x38f,0x38f,0x657,0x65a,0x65a,0x65a,0x65a,0x65a,0x65a,0x65a,0x65a, +0x65a,0x65a,0x65a,0x65a,0x65a,0x789,0x65a,0x65a,0x65a,0x65a,0x65a,0x78f,0x65a,0x65a,0x797,0x79f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x65a,0x65a,0x65a,0x65a,0x7af,0x7b7,0x7bf,0x7a7, +0x7cf,0x7d7,0x7df,0x7e6,0x7ed,0x7f5,0x7f9,0x7c7,0x65a,0x65a,0x65a,0x801,0x807,0x65a,0x80d,0x810, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x818,0x38f,0x38f,0x38f,0x820,0x38f,0x38f,0x38f,0x3dd, +0x828,0x830,0x835,0x38f,0x83d,0x65a,0x65a,0x65d,0x65a,0x65a,0x65a,0x65a,0x65a,0x65a,0x844,0x84a, +0x85a,0x852,0x38f,0x38f,0x862,0x5fd,0x38f,0x3b6,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x65a,0x81f, +0x3c4,0x38f,0x839,0x86a,0x38f,0x872,0x87a,0x38f,0x38f,0x38f,0x38f,0x87e,0x38f,0x38f,0x652,0x3b5, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x65a,0x65a, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x839,0x65a,0x573,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x885,0x38f,0x38f,0x88a,0x55d,0x38f,0x38f,0x5a9,0x65a,0x651,0x38f,0x38f,0x892,0x38f,0x38f,0x38f, +0x89a,0x8a1,0x623,0x8a9,0x38f,0x38f,0x57f,0x8b1,0x38f,0x8b9,0x8c0,0x38f,0x4e2,0x8c5,0x38f,0x4fb, +0x38f,0x8cd,0x8d5,0x4fd,0x38f,0x8d9,0x4fc,0x8e1,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x8e8, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x8fc,0x8f0,0x8f4,0x48e,0x48e,0x48e,0x48e,0x48e, +0x48e,0x48e,0x48e,0x48e,0x48e,0x48e,0x48e,0x48e,0x48e,0x904,0x48e,0x48e,0x48e,0x48e,0x90c,0x910, +0x918,0x920,0x924,0x92c,0x48e,0x48e,0x48e,0x930,0x938,0x37f,0x940,0x948,0x38f,0x38f,0x38f,0x950, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0xe3c,0xe3c,0xe7c,0xebc,0xe3c,0xe3c,0xe3c,0xe3c,0xe3c,0xe3c,0xef4,0xf34,0xf74,0xf84,0xfc4,0xfd0, +0xe3c,0xe3c,0x1010,0xe3c,0xe3c,0xe3c,0x1048,0x1088,0x10c8,0x1108,0x1140,0x1180,0x11c0,0x11f8,0x1238,0x1278, +0xa40,0xa80,0xac0,0xaff,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0xb37,0x1a0,0x1a0, +0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0xb74,0x1a0,0x1a0,0xba9,0xbe9,0xc29,0xc69,0xca9,0xce9, 0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0, -0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0xd17, +0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0xd29, 0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0, -0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0xd17, +0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0xd29, 0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0, -0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0xd17, +0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0xd29, 0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0, -0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0xd17, +0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0xd29, 0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0, -0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0xd17, +0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0xd29, 0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0, -0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0xd17, +0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0xd29, 0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0, -0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0xd17, +0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0xd29, 0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0, -0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0xd17, +0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0xd29, 0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0, -0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0xd17, +0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0xd29, 0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0, -0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0xd17, +0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0xd29, 0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0, -0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0xd17, +0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0xd29, 0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0, -0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0xd17, -0xd57,0xd67,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0, -0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0xd17, +0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0xd29, +0xd69,0xd79,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0, +0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0xd29, 0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0, -0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0xd17, +0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0xd29, 0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0, -0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0xd17, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x957,0x38a,0x654,0x654,0x95f,0x5f7,0x38a,0x4f0, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x967,0x38a,0x38a,0x38a,0x96e,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x41f,0x41f,0x41f,0x41f,0x41f,0x41f,0x41f,0x41f,0x976,0x41f,0x41f,0x41f,0x41f,0x41f,0x41f,0x41f, -0x97e,0x982,0x41f,0x41f,0x41f,0x41f,0x992,0x98a,0x41f,0x99a,0x41f,0x41f,0x9a2,0x9a8,0x41f,0x41f, -0x41f,0x41f,0x41f,0x41f,0x41f,0x41f,0x41f,0x41f,0x41f,0x41f,0x41f,0x41f,0x41f,0x41f,0x41f,0x41f, -0x41f,0x41f,0x41f,0x9b0,0x41f,0x41f,0x41f,0x41f,0x41f,0x41f,0x41f,0x41f,0x41f,0x41f,0x41f,0x41f, -0x4f7,0x9b8,0x9bf,0x9c6,0x401,0x9c9,0x38a,0x38a,0x4dd,0x9d1,0x38a,0x9d7,0x401,0x9dc,0x609,0x38a, -0x38a,0x9e4,0x38a,0x38a,0x38a,0x38a,0x826,0x9ec,0x401,0x4f8,0x556,0x9f3,0x38a,0x38a,0x38a,0x38a, -0x38a,0x9b8,0x9fb,0x38a,0x38a,0x9ff,0xa07,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0xa0b,0xa13,0x38a, -0x38a,0xa1b,0x556,0xa23,0x38a,0xa29,0x38a,0x38a,0x5e7,0xa31,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0xa39,0xa3d,0xa45,0x38a,0xa4c,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0xa53,0x38a,0x38a,0xa61,0xa5b, -0x38a,0x38a,0x38a,0xa69,0xa71,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0xa75,0x38a,0xa7b,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0xa81,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x511,0xa89,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0xa90,0xa98,0xa9e,0x38a,0x38a,0x654,0x654,0xaa6,0x38a,0x38a,0x38a,0x38a,0x38a,0x654, -0x654,0xaae,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0xab4,0x38a,0xabb, -0x38a,0xab7,0x38a,0xabe,0x38a,0xac6,0xaca,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x3d8,0xad2,0x3d8,0xad9,0xae0,0xae8,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0xaf0,0xaf8,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x41f,0x41f,0x41f,0x41f,0x41f,0x41f,0xb00,0x41f,0xb08, -0xb08,0xb0f,0x41f,0x41f,0x41f,0x41f,0x41f,0x41f,0x41f,0x41f,0x41f,0x41f,0x41f,0x41f,0x41f,0x41f, -0x41f,0x41f,0x41f,0x41f,0x41f,0x41f,0x41f,0x41f,0x41f,0x41f,0x41f,0x41f,0x41f,0x41f,0x41f,0x41f, -0x41f,0x41f,0x41f,0x41f,0x41f,0x41f,0x41f,0x489,0x489,0x489,0x489,0x489,0x489,0x489,0xb17,0x41f, -0x41f,0x41f,0x41f,0x41f,0x41f,0x41f,0x41f,0x654,0xb1f,0x654,0x654,0x657,0xb24,0xb28,0x840,0xb30, -0x38a,0x38a,0xb36,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x764,0x38a,0x38a,0x38a,0x38a,0x654, -0x654,0x654,0x654,0x654,0x654,0x654,0x654,0x654,0x654,0x654,0x654,0x654,0x654,0x654,0x654,0x654, -0x654,0x654,0x654,0x654,0x654,0x654,0x654,0x654,0x654,0x654,0x654,0x654,0x654,0xb3e,0xb46,0x654, -0x654,0x654,0x657,0x654,0x654,0xb3e,0x38a,0xb1f,0x654,0xb4e,0x654,0xb56,0x842,0x38a,0x38a,0xb1f, -0xb5a,0xb62,0x659,0x656,0x38a,0xb6a,0x56d,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0xb72,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0x38a, -0x38a,0x38a,0x38a,0x38a,0x38a,0x38a,0xb72,0xb82,0xb7a,0xb7a,0xb7a,0xb83,0xb83,0xb83,0xb83,0x3d8, -0x3d8,0x3d8,0x3d8,0x3d8,0x3d8,0x3d8,0xb8b,0xb83,0xb83,0xb83,0xb83,0xb83,0xb83,0xb83,0xb83,0xb83, -0xb83,0xb83,0xb83,0xb83,0xb83,0xb83,0xb83,0xb83,0xb83,0xb83,0xb83,0xb83,0xb83,0xb83,0xb83,0xb83, -0xb83,0xb83,0xb83,0xb83,0xb83,0xb83,0xb83,0xb83,0xb83,0xb83,0xb83,0xb83,0xb83,0xb83,0xb83,0xb83, -0xb83,0xb83,0xb83,0xb83,0xb83,0xb83,0xb83,0xb83,0xb83,0xb83,0xb83,0xb83,0xb83,0xb83,0xb83,0xb83, -0xb83,0xb83,0xb83,0xb83,0xb83,0xb83,0xb83,0x369,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, -0x12,8,7,8,9,7,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, -0x12,0x12,0x12,0x12,7,7,7,8,9,0xa,0xa,4,4,4,0xa,0xa, -0x310a,0xf20a,0xa,3,6,3,6,6,2,2,2,2,2,2,2,2, -2,2,6,0xa,0x500a,0xa,0xd00a,0xa,0xa,0,0,0,0,0,0,0, +0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0x1a0,0xd29, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x958,0x38f,0x65a,0x65a,0x960,0x5fd,0x38f,0x4f5, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x968,0x38f,0x38f,0x38f,0x96f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x424,0x424,0x424,0x424,0x424,0x424,0x424,0x424,0x977,0x424,0x424,0x424,0x424,0x424,0x424,0x424, +0x97f,0x983,0x424,0x424,0x424,0x424,0x993,0x98b,0x424,0x99b,0x424,0x424,0x9a3,0x9a9,0x424,0x424, +0x424,0x424,0x424,0x424,0x424,0x424,0x424,0x424,0x9b9,0x9b1,0x424,0x424,0x424,0x424,0x424,0x424, +0x424,0x424,0x424,0x9c1,0x424,0x424,0x424,0x424,0x424,0x9c9,0x9d0,0x9d6,0x424,0x424,0x424,0x424, +0x4fc,0x9de,0x9e5,0x9ec,0x406,0x9ef,0x38f,0x38f,0x4e2,0x9f6,0x38f,0x9fc,0x406,0xa01,0xa09,0x38f, +0x38f,0xa0e,0x38f,0x38f,0x38f,0x38f,0x820,0xa16,0x406,0x581,0x55c,0xa1d,0x38f,0x38f,0x38f,0x38f, +0x38f,0x9de,0xa25,0x38f,0x38f,0xa2d,0xa35,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0xa39,0xa41,0x38f, +0x38f,0xa49,0x55c,0xa51,0x38f,0xa57,0x38f,0x38f,0x5ed,0xa5f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0xa64,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0xa6c, +0xa70,0xa78,0x38f,0xa7f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0xa86,0x38f,0x38f,0xa94,0xa8e,0x38f,0x38f,0x38f,0xa9c,0xaa4,0x38f,0xaa8,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x583,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0xaae,0x38f, +0xab4,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0xaba,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x516,0xac2,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0xac9,0xad1,0xad7,0x38f,0x38f,0x65a,0x65a,0xadf,0x38f,0x38f,0x38f,0x38f, +0x38f,0x65a,0x65a,0x833,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0xae1, +0x38f,0xae8,0x38f,0xae4,0x38f,0xaeb,0x38f,0xaf3,0xaf7,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x3dd,0xaff,0x3dd,0xb06,0xb0d,0xb15,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0xb1d,0xb25,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x424,0x424,0x424,0x424,0x424,0x424,0xb2d, +0x424,0xb35,0xb35,0xb3c,0x424,0x424,0x424,0x424,0x424,0x424,0x424,0x424,0x424,0x424,0x424,0x424, +0x424,0x424,0x424,0x424,0x424,0x424,0x424,0x424,0x424,0x424,0x424,0x424,0x8f4,0x48e,0x48e,0x424, +0x424,0x424,0x424,0x424,0x424,0x424,0x424,0x424,0x424,0x48e,0x48e,0x48e,0x48e,0x48e,0x48e,0x48e, +0xb44,0x424,0x424,0x424,0x424,0x424,0x424,0x424,0x424,0x65a,0xb4c,0x65a,0x65a,0x65d,0xb51,0xb55, +0x844,0xb5d,0x3b1,0x38f,0xb63,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x76a,0x38f,0x38f,0x38f, +0x38f,0x65a,0x65a,0x65a,0x65a,0x65a,0x65a,0x65a,0x65a,0x65a,0x65a,0x65a,0x65a,0x65a,0x65a,0x65a, +0x65a,0x65a,0x65a,0x65a,0x65a,0x65a,0x65a,0x65a,0x65a,0x65a,0x65a,0x65a,0x65a,0x65a,0x65a,0xb6b, +0xb73,0x65a,0x65a,0x65a,0x65d,0x65a,0x65a,0xb7b,0x38f,0xb4c,0x65a,0xb83,0x65a,0xb8b,0x846,0x38f, +0x38f,0xb4c,0xb8f,0x65a,0xb97,0x65a,0xb9f,0xba7,0x65a,0x38f,0x38f,0x38f,0x846,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0xbaf,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f, +0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0x38f,0xbaf,0xbbf,0xbb7,0xbb7,0xbb7,0xbc0,0xbc0,0xbc0, +0xbc0,0x3dd,0x3dd,0x3dd,0x3dd,0x3dd,0x3dd,0x3dd,0xbc8,0xbc0,0xbc0,0xbc0,0xbc0,0xbc0,0xbc0,0xbc0, +0xbc0,0xbc0,0xbc0,0xbc0,0xbc0,0xbc0,0xbc0,0xbc0,0xbc0,0xbc0,0xbc0,0xbc0,0xbc0,0xbc0,0xbc0,0xbc0, +0xbc0,0xbc0,0xbc0,0xbc0,0xbc0,0xbc0,0xbc0,0xbc0,0xbc0,0xbc0,0xbc0,0xbc0,0xbc0,0xbc0,0xbc0,0xbc0, +0xbc0,0xbc0,0xbc0,0xbc0,0xbc0,0xbc0,0xbc0,0xbc0,0xbc0,0xbc0,0xbc0,0xbc0,0xbc0,0xbc0,0xbc0,0xbc0, +0xbc0,0xbc0,0xbc0,0xbc0,0xbc0,0xbc0,0xbc0,0xbc0,0xbc0,0x36e,0x36e,0x36e,0x12,0x12,0x12,0x12, +0x12,0x12,0x12,0x12,0x12,8,7,8,9,7,0x12,0x12,0x12,0x12,0x12,0x12, +0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,7,7,7,8,9,0xa,0xa,4, +4,4,0xa,0xa,0x310a,0xf20a,0xa,3,6,3,6,6,2,2,2,2, +2,2,2,2,2,2,6,0xa,0x500a,0xa,0xd00a,0xa,0xa,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0x510a,0xa,0xd20a,0xa,0xa,0xa,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0x510a,0xa,0xd20a,0xa,0xa,0xa,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0x510a,0xa,0xd20a,0xa,0x12,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0x510a,0xa,0xd20a,0xa,0x12,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0x12,0x12,0x12,0x12,0x12,7,0x12,0x12, -0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, -0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,6,0xa,4,4,4,4,0xa,0xa, -0xa,0xa,0,0x900a,0xa,0xb2,0xa,0xa,4,4,2,2,0xa,0,0xa,0xa, -0xa,2,0,0x900a,0xa,0xa,0xa,0xa,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xa, +0,0,0,0,0,0,0,0,0,0,0,0,0x12,0x12,0x12,0x12, +0x12,7,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, +0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,6,0xa,4,4, +4,4,0xa,0xa,0xa,0xa,0,0x900a,0xa,0xb2,0xa,0xa,4,4,2,2, +0xa,0,0xa,0xa,0xa,2,0,0x900a,0xa,0xa,0xa,0xa,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xa, +0,0,0,0xa,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0xa,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0xa,0xa,0,0,0,0,0, -0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0,0,0,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0xa, -0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, +0,0,0,0,0,0,0,0,0,0,0,0,0,0xa,0xa,0, +0,0,0,0,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, +0xa,0xa,0xa,0xa,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, +0xa,0xa,0xa,0xa,0,0,0,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa, +0xa,0xa,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, +0xa,0xa,0xa,0xa,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, 0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, 0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, 0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, -0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, -0,0,0,0,0xa,0xa,0,0,0,0,0,0,0,0,0xa,0, -0,0,0,0,0xa,0xa,0,0xa,0,0,0,0,0,0,0,0, +0xb1,0xb1,0xb1,0xb1,0,0,0,0,0xa,0xa,0,0,0,0,0,0, +0,0,0xa,0,0,0,0,0,0xa,0xa,0,0xa,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0xa,0,0,0,0,0,0,0,0,0,0,0,0,0xb1, -0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0xa,0,0,0,0,0,0,0,0,0, +0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xa,0, -0,0xa,0xa,4,1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0xa,0,0,0xa,0xa,4,1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, 0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, 0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, -0xb1,0xb1,1,0xb1,1,0xb1,0xb1,1,0xb1,0xb1,1,0xb1,1,1,1,1, +0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,1,0xb1,1,0xb1,0xb1,1,0xb1,0xb1,1,0xb1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,5,5,5,5,5,5,0xa,0xa,0xd,4,4,0xd, -6,0xd,0xa,0xa,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xd, -0x8ad,0xd,0xd,0xd,0x4d,0xd,0x8d,0x8d,0x8d,0x8d,0x4d,0x8d,0x4d,0x8d,0x4d,0x4d, -0x4d,0x4d,0x4d,0x8d,0x8d,0x8d,0x8d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d, -0x4d,0x4d,0x4d,0x4d,0x2d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x8d,0x4d,0x4d,0xb1, -0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, -0xb1,0xb1,0xb1,0xb1,5,5,5,5,5,5,5,5,5,5,4,5, -5,0xd,0x4d,0x4d,0xb1,0x8d,0x8d,0x8d,0xd,0x8d,0x8d,0x8d,0x4d,0x4d,0x4d,0x4d, -0x4d,0x4d,0x4d,0x4d,0x8d,0x8d,0x8d,0x8d,0x8d,0x8d,0x8d,0x8d,0x8d,0x8d,0x8d,0x8d, -0x8d,0x8d,0x8d,0x8d,0x8d,0x8d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d, +1,1,1,1,1,1,1,1,5,5,5,5,5,5,0xa,0xa, +0xd,4,4,0xd,6,0xd,0xa,0xa,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, +0xb1,0xb1,0xb1,0xd,0x8ad,0xd,0xd,0xd,0x4d,0xd,0x8d,0x8d,0x8d,0x8d,0x4d,0x8d, +0x4d,0x8d,0x4d,0x4d,0x4d,0x4d,0x4d,0x8d,0x8d,0x8d,0x8d,0x4d,0x4d,0x4d,0x4d,0x4d, +0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x2d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d, +0x8d,0x4d,0x4d,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, +0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,5,5,5,5,5,5,5,5, +5,5,4,5,5,0xd,0x4d,0x4d,0xb1,0x8d,0x8d,0x8d,0xd,0x8d,0x8d,0x8d, +0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x8d,0x8d,0x8d,0x8d,0x8d,0x8d,0x8d,0x8d, +0x8d,0x8d,0x8d,0x8d,0x8d,0x8d,0x8d,0x8d,0x8d,0x8d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d, 0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d, -0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x8d,0x4d,0x4d,0x8d, -0x8d,0x8d,0x8d,0x8d,0x8d,0x8d,0x8d,0x8d,0x4d,0x8d,0x4d,0x8d,0x4d,0x4d,0x8d,0x8d, -0xd,0x8d,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,5,0xa,0xb1,0xb1,0xb1,0xb1,0xb1, -0xb1,0xd,0xd,0xb1,0xb1,0xa,0xb1,0xb1,0xb1,0xb1,0x8d,0x8d,2,2,2,2, -2,2,2,2,2,2,0x4d,0x4d,0x4d,0xd,0xd,0x4d,0xd,0xd,0xd,0xd, -0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xad,0x8d,0xb1,0x4d,0x4d, -0x4d,0x8d,0x8d,0x8d,0x8d,0x8d,0x4d,0x4d,0x4d,0x4d,0x8d,0x4d,0x4d,0x4d,0x4d,0x4d, -0x4d,0x4d,0x4d,0x4d,0x8d,0x4d,0x8d,0x4d,0x8d,0x4d,0x4d,0x8d,0xb1,0xb1,0xb1,0xb1, -0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xd, -0xd,0x8d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x8d,0x8d,0x8d, -0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x8d, -0x8d,0x4d,0x4d,0x4d,0x4d,0x8d,0x4d,0x8d,0x8d,0x4d,0x4d,0x4d,0x8d,0x8d,0x4d,0x4d, -0x4d,0x4d,0x4d,0x4d,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd, +0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d, +0x8d,0x4d,0x4d,0x8d,0x8d,0x8d,0x8d,0x8d,0x8d,0x8d,0x8d,0x8d,0x4d,0x8d,0x4d,0x8d, +0x4d,0x4d,0x8d,0x8d,0xd,0x8d,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,5,0xa,0xb1, +0xb1,0xb1,0xb1,0xb1,0xb1,0xd,0xd,0xb1,0xb1,0xa,0xb1,0xb1,0xb1,0xb1,0x8d,0x8d, +2,2,2,2,2,2,2,2,2,2,0x4d,0x4d,0x4d,0xd,0xd,0x4d, +0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xad, +0x8d,0xb1,0x4d,0x4d,0x4d,0x8d,0x8d,0x8d,0x8d,0x8d,0x4d,0x4d,0x4d,0x4d,0x8d,0x4d, +0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x8d,0x4d,0x8d,0x4d,0x8d,0x4d,0x4d,0x8d, +0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, +0xb1,0xb1,0xb1,0xd,0xd,0x8d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d, +0x4d,0x8d,0x8d,0x8d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d, +0x4d,0x4d,0x4d,0x8d,0x8d,0x4d,0x4d,0x4d,0x4d,0x8d,0x4d,0x8d,0x8d,0x4d,0x4d,0x4d, +0x8d,0x8d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd, 0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd, -0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, -0xb1,0xb1,0xb1,0xb1,0xb1,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd, -0xd,0xd,0xd,0xd,1,1,1,1,1,1,1,1,1,1,0x41,0x41, +0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xb1,0xb1, +0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xd,0xd,0xd,0xd,0xd,0xd,0xd, +0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,1,1,1,1,1,1,1,1, +1,1,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41, 0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41, -0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0xb1, -0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,1,1,0xa,0xa,0xa,0xa,0x21,1, -1,1,1,1,0xb1,0xb1,0xb1,0xb1,1,0xb1,0xb1,0xb1,1,0xb1,0xb1,0xb1, -0xb1,0xb1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,0xb1,0xb1,0xb1,0xb1,1,0xb1, -0xb1,0xb1,0xb1,0xb1,0x81,0x41,0x41,0x41,0x41,0x41,0x81,0x81,0x41,0x81,0x41,0x41, -0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x81,0x41,1,1,1,0xb1,0xb1,0xb1, -1,1,1,1,0x4d,0xd,0x4d,0x4d,0x4d,0x4d,0xd,0x8d,0x4d,0x8d,0x8d,0xd, -0xd,0xd,0xd,0xd,1,1,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,0xb1,0xb1,5,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, +0x41,0x41,0x41,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,1,1,0xa,0xa, +0xa,0xa,0x21,1,1,0xb1,1,1,0xb1,0xb1,0xb1,0xb1,1,0xb1,0xb1,0xb1, +1,0xb1,0xb1,0xb1,0xb1,0xb1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,0xb1,0xb1, +0xb1,0xb1,1,0xb1,0xb1,0xb1,0xb1,0xb1,0x81,0x41,0x41,0x41,0x41,0x41,0x81,0x81, +0x41,0x81,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x81,0x41,1,1, +1,0xb1,0xb1,0xb1,1,1,1,1,0x4d,0xd,0x4d,0x4d,0x4d,0x4d,0xd,0x8d, +0x4d,0x8d,0x8d,0xd,0xd,0xd,0xd,0xd,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,0xb1,0xb1,5,0xb1,0xb1,0xb1,0xb1,0xb1, 0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, -0xb1,0xb1,0xb1,0xb1,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x8d,0x8d, -0x8d,0xd,0x8d,0x4d,0x4d,0x8d,0x8d,0x4d,0x4d,0xd,0x4d,0x4d,0x4d,0x8d,0x4d,0x4d, -0x4d,0x4d,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd, -0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, -0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0xb1,0,0xb1,0,0,0,0,0xb1,0xb1,0xb1, -0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0,0,0xb1,0,0,0,0xb1,0xb1,0xb1, -0xb1,0xb1,0xb1,0xb1,0,0,0,0,0,0,0,0,0,0,0xb1,0xb1, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0xb1,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0xb1,0,0,0, -0,0xb1,0xb1,0xb1,0xb1,0,0,0,0,0,0,0,0,0xb1,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0xb1,0xb1,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,4,4,0,0,0,0,0,0,0,4,0,0,0,0, -0,0xb1,0xb1,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0xb1,0xb1,0,0,0,0,0xb1,0xb1,0,0,0xb1,0xb1,0xb1,0,0, -0,0xb1,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0xb1,0xb1,0,0,0,0xb1,0,0,0,0,0,0, -0,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0,0xb1,0xb1,0,0,0, -0,0xb1,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0xb1,0xb1,0,0,0,0,0,0,0,0, -0,0,0,0,0,4,0,0,0,0,0,0,0,0,0xb1,0xb1, -0xb1,0xb1,0xb1,0xb1,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0xb1,0,0,0xb1,0,0xb1,0xb1,0xb1,0xb1,0,0,0,0,0,0,0, -0,0xb1,0,0,0,0,0,0,0,0,0xb1,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0xb1,0,0,0,0,0,0,0, -0,0,0,0,0,0xb1,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0xa,0xa,0xa,0xa,0xa, -0xa,4,0xa,0,0,0,0,0,0xb1,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0xb1,0xb1,0xb1,0,0,0, -0,0,0xb1,0xb1,0xb1,0,0xb1,0xb1,0xb1,0xb1,0,0,0,0,0,0, -0,0xb1,0xb1,0,0,0,0,0,0,0,0,0,0,0,0xb1,0xb1, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0xb1,0,0,0xa0,0,0,0,0, -0,0,0xa0,0,0,0,0,0,0xb1,0xb1,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0xb1,0xb1,0,0,0,0,0,0,0, -0,0,0,0,0,0,0xb1,0,0,0,0,0,0,0,0xb1,0xb1, -0xb1,0,0xb1,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0xb1,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0, -0,0,0,4,0,0,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1, -0xb1,0xb1,0xb1,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0xb1,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0xb1, -0xb1,0,0,0,0,0,0,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1, -0xb1,0xb1,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0xb1,0xb1,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0xb1,0,0xb1,0,0xb1,0x310a,0xf20a,0x310a,0xf20a,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0, -0xb1,0xb1,0xb1,0xb1,0xb1,0,0xb1,0xb1,0,0,0,0,0,0xb1,0xb1,0xb1, -0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, -0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, -0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0,0xb1,0xb1, -0xb1,0xb1,0xb1,0xb1,0,0xb1,0xb1,0,0,0xb1,0xb1,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0xb1,0xb1,0,0,0,0,0xb1,0xb1,0xb1,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0xb1,0xb1,0xb1, -0xb1,0,0,0,0,0,0,0,0,0,0,0,0,0,0xb1,0, -0,0xb1,0xb1,0,0,0,0,0,0,0xb1,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0xb1,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0xb1,0xb1,0xb1,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0xa,0xa,0,0,0,0,0,0,0xa,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0x310a,0xf20a,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xb1,0xb1, -0xb1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0xb1,0xb1,0,0xb1,0xb1,0xb1,0xb1,0xb1, -0xb1,0xb1,0,0,0,0,0,0,0,0,0xb1,0,0,0xb1,0xb1,0xb1, -0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0,0,0,0,0,4, -0,0xb1,0,0,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,0x40,0xb1,0x40,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0x4a,0xa,0xa,0x2a,0xb1,0xb1,0xb1,0x12,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0x40,0x40,0x40,0x40, -0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40, -0x40,0x40,0x40,0x40,0,0,0,0,0,0,0,0,0,0xb1,0xb1,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,0xb1,0xb1,0xb1,0,0,0,0,0xb1, -0xb1,0,0,0,0,0,0,0,0,0,0xb1,0,0,0,0,0, -0,0xb1,0xb1,0xb1,0,0,0,0,0xa,0,0,0,0xa,0xa,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xa,0xa, -0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0xb1,0xb1,0,0,0xb1,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0xb1,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0xb1,0,0xb1,0, -0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0,0,0,0,0xb1, -0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0xb1,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1, +0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d, +0x4d,0x4d,0x8d,0x8d,0x8d,0xd,0x8d,0x4d,0x4d,0x8d,0x8d,0x4d,0x4d,0xd,0x4d,0x4d, +0x4d,0x8d,0x4d,0x4d,0x4d,0x4d,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd, +0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xb1,0xb1,0xb1,0xb1,0xb1, 0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0xb1,0,0xb1,0xb1,0xb1,0xb1,0xb1,0,0xb1,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xb1,0xb1, -0xb1,0xb1,0,0,0xb1,0xb1,0,0xb1,0xb1,0xb1,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xb1,0, -0xb1,0xb1,0,0,0,0xb1,0,0xb1,0xb1,0xb1,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, +0,0,0,0,0,0,0,0,0,0,0xb1,0,0xb1,0,0,0, +0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0,0,0xb1,0,0, +0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0,0,0,0,0,0, 0,0,0xb1,0xb1,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0xb1,0xb1,0xb1,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, -0xb1,0xb1,0xb1,0xb1,0xb1,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0, -0,0xb1,0,0,0,0,0,0,0xb1,0,0,0,0xb1,0xb1,0,0, -0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, -0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0xb1, -0xb1,0xb1,0xb1,0xb1,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0xa,0,0xa,0xa,0xa,0,0,0,0,0,0,0,0,0,0, -0,0xa,0xa,0xa,0,0,0,0,0,0,0,0,0,0,0,0, -0,0xa,0xa,0xa,0,0,0,0,0,0,0,0,0,0,0,0, -0,0xa,0xa,0,0xa,0xa,0xa,0xa,6,0x310a,0xf20a,0xa,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,9,0xb2,0xb2,0xb2,0xb2,0xb2,0x12,0x814,0x815,0x813,0x816,0xb2,0xb2, -0xb2,0xb2,0xb2,0xb2,2,0,0,0,2,2,2,2,2,2,3,3, -0xa,0x310a,0xf20a,0,9,9,9,9,9,9,9,9,9,9,9,0xb2, -0x412,0x432,0x8a0,0x8a1,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,9,7,0x8ab,0x8ae,0x8b0,0x8ac,0x8af,6,4,4,4,4, -4,0xa,0xa,0xa,0xa,0x300a,0xf00a,0xa,0xa,0xa,0xa,0xa,2,2,2,2, -2,2,2,2,2,2,3,3,0xa,0x310a,0xf20a,0,0,0,0,0, -0,0,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,4,4,4,4, -4,4,4,4,4,4,4,4,4,4,4,4,0xb1,0xb1,0xb1,0xb1, -0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xa,0xa,0,0xa, -0xa,0xa,0xa,0,0xa,0xa,0,0,0,0,0,0,0,0,0,0, -0xa,0,0xa,0xa,0xa,0,0,0,0,0,0xa,0xa,0xa,0xa,0xa,0xa, -0,0xa,0,0xa,0,0xa,0,0,0,0,4,0,0,0,0,0, -0,0,0,0,0,0,0xa,0xa,0,0,0,0,0x100a,0xa,0xa,0xa, -0xa,0,0,0,0,0,0xa,0xa,0xa,0xa,0,0,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0,0,0, -0,0,0,0,0,0xa,0xa,0xa,0,0,0,0,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0x300a,0xf00a,0x300a,0xf00a, -0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0xa,0xa,0x300a,0xf00a,0x900a,0x900a, -0x900a,0x100a,0x900a,0x900a,0x100a,0x100a,0x900a,0x900a,0x900a,0x900a,0x900a,0x100a,0xa,0x100a,0x100a,0x100a, -0x100a,0xa,0xa,0xa,0x700a,0x700a,0x700a,0xb00a,0xb00a,0xb00a,0xa,0xa,0xa,0x100a,3,4, -0xa,0x900a,0x100a,0xa,0xa,0xa,0x100a,0x100a,0x100a,0x100a,0xa,0x100a,0x100a,0x100a,0x100a,0xa, -0x100a,0xa,0x100a,0xa,0xa,0xa,0xa,0x100a,0x100a,0x100a,0x100a,0x100a,0x100a,0x100a,0x100a,0x100a, -0xa,0xa,0xa,0xa,0xa,0x100a,0xa,0x100a,0x300a,0xf00a,0x100a,0x100a,0x100a,0x100a,0x100a,0x900a, -0x100a,0x100a,0x100a,0x100a,0x100a,0x100a,0x100a,0x100a,0x100a,0xa,0xa,0xa,0xa,0xa,0x300a,0xf00a, -0x300a,0xf00a,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0x100a,0x100a,0xa,0x100a,0xa, -0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0xa,0xa,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a, -0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x100a,0xa,0xa,0x300a, -0xf00a,0x300a,0xf00a,0xa,0xa,0xa,0xa,0xa,0x900a,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0xa,0xa,0x300a,0xf00a,0xa,0xa,0x900a,0x100a,0x900a,0x900a,0x100a,0x900a,0x100a,0x100a,0x100a,0x100a, -0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x100a,0xa,0xa,0xa,0xa,0xa,0x100a,0x100a, -0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0x300a,0xf00a,0x300a,0xf00a,0x900a,0xa,0xa, -0x300a,0xf00a,0xa,0xa,0xa,0xa,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a, -0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0x310a,0xf20a,0x310a,0xf20a,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0x100a,0x100a,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0x310a,0xf20a,0xa,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0xa,0xa,0,0,0,0,0,0,0,0,0,0, +0,0xb1,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0xa,0xa,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0,0,0,0,0,0,0,0, +0xb1,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0,0,0,0,0,0,0, +0,0xb1,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0xb1,0xb1,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,4,4,0,0,0,0,0,0,0,4, +0,0,0xb1,0,0,0xb1,0xb1,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0xb1,0xb1,0,0,0,0,0xb1,0xb1,0,0,0xb1, +0xb1,0xb1,0,0,0,0xb1,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0xb1,0xb1,0,0,0,0xb1,0,0, +0,0,0,0,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0,0xb1, +0xb1,0,0,0,0,0xb1,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0xb1,0xb1,0,0,0,0, +0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0, +0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0xb1,0,0,0xb1,0,0xb1,0xb1,0xb1,0xb1,0,0,0, +0,0,0,0,0,0xb1,0,0,0,0,0,0,0,0,0xb1,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0xb1,0,0,0, +0,0,0,0,0,0,0,0,0,0xb1,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xa, +0xa,0xa,0xa,0xa,0xa,4,0xa,0,0,0,0,0,0xb1,0,0,0, +0xb1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0xb1,0xb1,0xb1,0,0,0,0,0,0xb1,0xb1,0xb1,0,0xb1,0xb1, +0xb1,0xb1,0,0,0,0,0,0,0,0xb1,0xb1,0,0,0,0,0, +0,0,0,0,0,0,0xb1,0xb1,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,2,2,2,2,2,2,2,2,2,2,2,2, -2,2,2,2,2,2,2,2,0,0,0,0,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0x310a,0xf20a,0x310a,0xf20a, -0x310a,0xf20a,0x310a,0xf20a,0x310a,0xf20a,0x310a,0xf20a,0x310a,0xf20a,0xa,0xa,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0x100a,0xa,0xa,0x300a,0xf00a,0x310a,0xf20a,0xa,0x300a,0xf00a,0xa,0x500a, -0x100a,0xd00a,0xa,0xa,0xa,0xa,0xa,0x100a,0x100a,0x300a,0xf00a,0xa,0xa,0xa,0xa,0xa, -0x100a,0x300a,0xf00a,0xa,0xa,0xa,0x300a,0xf00a,0x300a,0xf00a,0x310a,0xf20a,0x310a,0xf20a,0x310a,0xf20a, -0x310a,0xf20a,0x310a,0xf20a,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0xa,0x100a,0xa,0x100a,0x100a,0x100a,0xa,0xa,0x100a,0x100a,0xa,0xa, -0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0x100a,0x900a,0x100a,0x100a,0x300a,0xf00a,0xa,0xa, -0x310a,0xf20a,0xa,0xa,0xa,0xa,0xa,0x310a,0xf20a,0x310a,0xf20a,0x310a,0xf20a,0x310a,0xf20a,0x310a, -0xf20a,0x710a,0x320a,0xf10a,0xb20a,0x310a,0xf20a,0x310a,0xf20a,0x310a,0xf20a,0x310a,0xf20a,0xa,0xa,0x100a, -0x100a,0x100a,0x100a,0x100a,0x100a,0x100a,0x100a,0x100a,0x100a,0x100a,0x100a,0x100a,0x100a,0x100a,0x100a,0x100a, -0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0x900a,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0x300a,0xf00a,0x100a,0x100a,0x300a,0xf00a,0xa,0xa,0xa,0x100a,0xa,0xa,0xa,0xa,0x100a,0x300a, -0xf00a,0x300a,0xf00a,0xa,0x300a,0xf00a,0xa,0xa,0x310a,0xf20a,0x310a,0xf20a,0x100a,0xa,0xa,0xa, -0xa,0xa,0x100a,0x900a,0x900a,0x900a,0x100a,0xa,0xa,0xa,0xa,0xa,0x300a,0xf00a,0x100a,0xa, -0xa,0xa,0xa,0x100a,0xa,0xa,0xa,0x300a,0xf00a,0x300a,0xf00a,0x100a,0xa,0x100a,0xa,0xa, -0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0x100a,0x100a,0x100a,0x100a,0x100a,0x100a, -0x100a,0x100a,0x100a,0x100a,0x100a,0x100a,0x100a,0x100a,0x100a,0x100a,0x100a,0x100a,0x100a,0xa,0x100a,0x100a, -0x100a,0x100a,0xa,0xa,0x100a,0xa,0x100a,0xa,0xa,0x100a,0xa,0x300a,0xf00a,0x300a,0xf00a,0xa, -0xa,0xa,0xa,0xa,0x300a,0xf00a,0xa,0xa,0xa,0xa,0xa,0xa,0x300a,0xf00a,0x100a,0xa, -0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0xa,0xa,0xa,0x100a,0x100a,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0x300a,0xf00a,0xa,0xa,0xa,0xa,0x100a,0x100a,0x100a,0x100a,0xa,0x100a,0x100a,0xa,0xa,0x100a, -0x100a,0xa,0xa,0xa,0xa,0x300a,0xf00a,0x100a,0x100a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a, -0xf00a,0x100a,0x100a,0x100a,0x100a,0x100a,0x100a,0x300a,0xf00a,0x100a,0x100a,0x100a,0x100a,0x300a,0xf00a,0x300a, -0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x100a,0x100a,0x100a,0x100a,0x300a,0xf00a,0x100a, -0xa,0xa,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0xa,0x300a,0xf00a,0x100a,0x100a,0x300a, -0xf00a,0x100a,0x100a,0x100a,0x100a,0x100a,0x100a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x100a, -0x100a,0x100a,0x100a,0x100a,0x100a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0xa, -0xa,0xa,0xa,0xa,0x100a,0xa,0x900a,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0,0xa,0xa, -0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0xa,0xa,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0xa,0xa,0,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0xa,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0,0,0,0, -0,0,0,0,0,0,0,0,0xa,0xa,0xa,0xa,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0xa,0xa,0xa, -0xa,0xa,0xa,0,0,0,0,0xb1,0xb1,0xb1,0,0,0,0,0,0, -0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0,0,0,0,0,0,0, +0xa,0xa,0xa,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0xb1,0xa,0xa,0x300a,0xf00a,0x300a,0xf00a,0xa,0xa, -0xa,0x300a,0xf00a,0xa,0x300a,0xf00a,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0x300a,0xf00a,0xa,0xa,0x300a,0xf00a,0x310a,0xf20a,0x310a,0xf20a,0x310a,0xf20a, -0x310a,0xf20a,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, +0xb1,0,0,0xa0,0,0,0,0,0,0,0xa0,0,0,0,0,0, +0xb1,0xb1,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xb1, +0xb1,0,0,0,0,0,0,0,0,0,0,0,0,0,0xb1,0, +0,0,0,0,0,0,0xb1,0xb1,0xb1,0,0xb1,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0xb1,0,0, +0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0,0,4,0,0,0,0, +0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0xb1,0,0, +0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0xb1,0xb1,0,0,0,0,0,0,0, +0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0xb1,0xb1,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0xb1,0,0xb1, +0,0xb1,0x310a,0xf20a,0x310a,0xf20a,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, +0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0xb1,0xb1,0xb1,0xb1,0xb1,0,0xb1,0xb1, +0,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, +0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, +0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, +0xb1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0xb1,0xb1,0xb1,0xb1,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0xb1,0xb1,0, +0,0xb1,0xb1,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0xb1,0xb1,0,0, +0,0,0xb1,0xb1,0xb1,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0,0,0,0,0,0,0, +0,0,0,0,0,0,0xb1,0,0,0xb1,0xb1,0,0,0,0,0, +0,0xb1,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0xb1,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0xb1,0xb1,0xb1,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0, +0,0,0,0,0xa,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,9,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0x310a, +0xf20a,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0xb1,0xb1,0xb1,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0xb1,0xb1,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0,0,0,0, +0,0,0xb1,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, +0,0,0,0,0,0,0,4,0,0xb1,0,0,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,0x40,0xb1,0x40,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0x4a,0xa,0xa,0x2a,0xb1, +0xb1,0xb1,0x12,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,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,0,0,0, +0,0,0,0,0,0xb1,0xb1,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, +0xb1,0xb1,0xb1,0,0,0,0,0xb1,0xb1,0,0,0,0,0,0,0, +0,0,0xb1,0,0,0,0,0,0,0xb1,0xb1,0xb1,0,0,0,0, +0xa,0,0,0,0xa,0xa,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, +0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, +0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xb1, +0xb1,0,0,0xb1,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0xb1,0,0xb1,0xb1,0xb1,0xb1, +0xb1,0xb1,0xb1,0,0xb1,0,0xb1,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, +0xb1,0,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, +0xb1,0,0,0xb1,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, +0xb1,0xb1,0xb1,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0xb1,0,0xb1,0xb1,0xb1,0xb1,0xb1,0, +0xb1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xb1, +0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0,0,0xb1,0xb1,0,0xb1, +0xb1,0xb1,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0xb1,0,0xb1,0xb1,0,0,0,0xb1,0,0xb1, +0xb1,0xb1,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0xb1,0xb1,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0xb1,0xb1,0xb1,0, +0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0xb1,0xb1, +0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0,0,0xb1,0,0,0,0,0,0, +0xb1,0,0,0,0xb1,0xb1,0,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1, +0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, +0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0xa,0,0xa,0xa,0xa,0,0, +0,0,0,0,0,0,0,0,0,0xa,0xa,0xa,0,0,0,0, +0,0,0,0,0,0,0,0,0,0xa,0xa,0xa,0,0,0,0, +0,0,0,0,0,0,0,0,0,0xa,0xa,0,0xa,0xa,0xa,0xa, +6,0x310a,0xf20a,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, +0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,9,0xb2,0xb2,0xb2,0xb2, +0xb2,0x12,0x814,0x815,0x813,0x816,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,2,0,0,0, +2,2,2,2,2,2,3,3,0xa,0x310a,0xf20a,0,9,9,9,9, +9,9,9,9,9,9,9,0xb2,0x412,0x432,0x8a0,0x8a1,0xa,0xa,0xa,0xa, +0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,9,7,0x8ab,0x8ae, +0x8b0,0x8ac,0x8af,6,4,4,4,4,4,0xa,0xa,0xa,0xa,0x300a,0xf00a,0xa, +0xa,0xa,0xa,0xa,2,2,2,2,2,2,2,2,2,2,3,3, +0xa,0x310a,0xf20a,0,0,0,0,0,0,0,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,4,4,4,4,4,4,4,4,4,4,4,4, +4,4,4,4,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, +0xb1,0xb1,0xb1,0xb1,0xa,0xa,0,0xa,0xa,0xa,0xa,0,0xa,0xa,0,0, +0,0,0,0,0,0,0,0,0xa,0,0xa,0xa,0xa,0,0,0, +0,0,0xa,0xa,0xa,0xa,0xa,0xa,0,0xa,0,0xa,0,0xa,0,0, +0,0,4,0,0,0,0,0,0,0,0,0,0,0,0xa,0xa, +0,0,0,0,0x100a,0xa,0xa,0xa,0xa,0,0,0,0,0,0xa,0xa, +0xa,0xa,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, +0xa,0xa,0xa,0xa,0,0,0,0,0,0,0,0,0,0xa,0xa,0xa, +0,0,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, +0xa,0xa,0xa,0xa,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a, +0x300a,0xf00a,0xa,0xa,0x300a,0xf00a,0x900a,0x900a,0x900a,0x100a,0x900a,0x900a,0x100a,0x100a,0x900a,0x900a, +0x900a,0x900a,0x900a,0x100a,0xa,0x100a,0x100a,0x100a,0x100a,0xa,0xa,0xa,0x700a,0x700a,0x700a,0xb00a, +0xb00a,0xb00a,0xa,0xa,0xa,0x100a,3,4,0xa,0x900a,0x100a,0xa,0xa,0xa,0x100a,0x100a, +0x100a,0x100a,0xa,0x900a,0x900a,0x900a,0x900a,0xa,0x900a,0xa,0x100a,0xa,0xa,0xa,0xa,0x100a, +0x100a,0x100a,0x100a,0x100a,0x100a,0x100a,0x100a,0x100a,0xa,0xa,0xa,0xa,0xa,0x100a,0xa,0x100a, +0x300a,0xf00a,0x100a,0x100a,0x100a,0x100a,0x100a,0x900a,0x100a,0x900a,0x100a,0x100a,0x100a,0x100a,0x100a,0x100a, +0x900a,0xa,0xa,0xa,0xa,0xa,0x300a,0xf00a,0x300a,0xf00a,0xa,0xa,0xa,0xa,0xa,0xa, +0xa,0xa,0xa,0x100a,0x100a,0xa,0x100a,0xa,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a, +0xa,0xa,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a, +0x300a,0xf00a,0x300a,0xf00a,0x100a,0xa,0xa,0x300a,0xf00a,0x300a,0xf00a,0xa,0xa,0xa,0xa,0xa, +0x900a,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0x300a,0xf00a,0xa,0xa,0x900a,0x100a, +0x900a,0x900a,0x100a,0x900a,0x100a,0x100a,0x100a,0x100a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a, +0x900a,0xa,0xa,0xa,0xa,0xa,0x100a,0x100a,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, +0xa,0x300a,0xf00a,0x300a,0xf00a,0x900a,0xa,0xa,0x300a,0xf00a,0xa,0xa,0xa,0xa,0x300a,0xf00a, +0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, +0x310a,0xf20a,0x310a,0xf20a,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, +0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0x100a,0x100a,0xa,0xa,0xa,0xa,0xa,0xa, +0xa,0x310a,0xf20a,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0xa,0xa,0xa,0xa,0xa, +0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, +0xa,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,2,2,2,2, +2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, +0,0,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, +0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, +0xa,0xa,0xa,0xa,0x310a,0xf20a,0x310a,0xf20a,0x310a,0xf20a,0x310a,0xf20a,0x310a,0xf20a,0x310a,0xf20a, +0x310a,0xf20a,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0x100a,0xa,0xa,0x300a, +0xf00a,0x310a,0xf20a,0xa,0x300a,0xf00a,0xa,0x500a,0x100a,0xd00a,0xa,0xa,0xa,0xa,0xa,0x100a, +0x100a,0x300a,0xf00a,0xa,0xa,0xa,0xa,0xa,0x900a,0x300a,0xf00a,0xa,0xa,0xa,0x300a,0xf00a, +0x300a,0xf00a,0x310a,0xf20a,0x310a,0xf20a,0x310a,0xf20a,0x310a,0xf20a,0x310a,0xf20a,0xa,0xa,0xa,0xa, +0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0x100a,0xa,0x100a, +0x100a,0x100a,0xa,0xa,0x300a,0xf00a,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, +0x100a,0x900a,0x100a,0x100a,0x300a,0xf00a,0xa,0xa,0x310a,0xf20a,0xa,0xa,0xa,0xa,0xa,0x310a, +0xf20a,0x310a,0xf20a,0x310a,0xf20a,0x310a,0xf20a,0x310a,0xf20a,0x710a,0x320a,0xf10a,0xb20a,0x310a,0xf20a,0x310a, +0xf20a,0x310a,0xf20a,0x310a,0xf20a,0xa,0xa,0x900a,0x100a,0x100a,0x100a,0x100a,0x900a,0xa,0x100a,0x900a, +0x300a,0xf00a,0x100a,0x100a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0xa,0xa,0xa,0xa, +0xa,0xa,0xa,0xa,0x900a,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0x300a,0xf00a,0x100a,0x100a, +0x300a,0xf00a,0xa,0xa,0xa,0x100a,0xa,0xa,0xa,0xa,0x100a,0x300a,0xf00a,0x300a,0xf00a,0xa, +0x300a,0xf00a,0xa,0xa,0x310a,0xf20a,0x310a,0xf20a,0x100a,0xa,0xa,0xa,0xa,0xa,0x100a,0x900a, +0x900a,0x900a,0x100a,0xa,0xa,0xa,0xa,0xa,0x300a,0xf00a,0x900a,0xa,0xa,0xa,0xa,0x100a, +0xa,0xa,0xa,0x300a,0xf00a,0x300a,0xf00a,0x100a,0xa,0x100a,0xa,0xa,0xa,0xa,0xa,0xa, +0xa,0xa,0xa,0xa,0xa,0xa,0x100a,0x100a,0x100a,0x100a,0x100a,0x100a,0x100a,0x100a,0x100a,0x100a, +0x100a,0x100a,0x100a,0x100a,0x100a,0x100a,0x100a,0x100a,0x100a,0xa,0x100a,0x100a,0x100a,0x100a,0xa,0xa, +0x100a,0xa,0x100a,0xa,0xa,0x100a,0xa,0x300a,0xf00a,0x300a,0xf00a,0xa,0xa,0xa,0xa,0xa, +0x300a,0xf00a,0xa,0xa,0xa,0xa,0xa,0xa,0x300a,0xf00a,0x100a,0xa,0xa,0xa,0xa,0xa, +0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, +0xa,0xa,0xa,0x100a,0x100a,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0x300a,0xf00a,0xa,0xa, +0xa,0xa,0x100a,0x100a,0x100a,0x100a,0xa,0x100a,0x100a,0xa,0xa,0x100a,0x100a,0xa,0xa,0xa, +0xa,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a, +0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a, +0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x100a,0xa,0xa,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a, +0x300a,0xf00a,0xa,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a, +0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0x300a,0xf00a,0xa,0xa,0xa,0xa,0xa, +0x100a,0xa,0x900a,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, +0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0,0xa,0xa,0xa,0xa,0xa,0xa, +0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, +0xa,0xa,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0xa,0xa, +0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, +0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0x900a,0, +0,0,0,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0,0,0,0,0xb1, +0xb1,0xb1,0,0,0,0,0,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xb1, +0xa,0xa,0x300a,0xf00a,0x300a,0xf00a,0xa,0xa,0xa,0x300a,0xf00a,0xa,0x300a,0xf00a,0xa,0xa, +0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0x300a,0xf00a,0xa,0xa, +0x300a,0xf00a,0x310a,0xf20a,0x310a,0xf20a,0x310a,0xf20a,0x310a,0xf20a,0xa,0xa,0xa,0xa,0xa,0xa, +0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, +0xa,0xa,0xa,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, 0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0xa, 0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, 0xa,0xa,0xa,0xa,0xa,0xa,0,0,0,0,0,0,0,0,0,0, @@ -554,12 +555,11 @@ static const uint16_t ubidi_props_trieIndex[11856]={ 0x310a,0xf20a,0x310a,0xf20a,0xa,0xa,0xa,0xa,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0xb1,0xb1,0xa,0xa,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0xa,0xa,0xa,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa, 0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0,0,0,0,0,0,0, +0,0,0,0,0xa,0xa,0xa,0xa,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xa, 0xa,0xa,0xa,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0xa,0xa,0xa,0,0,0,0,0,0,0,0,0,0,0,0, @@ -574,194 +574,211 @@ static const uint16_t ubidi_props_trieIndex[11856]={ 0x40,0x40,0x40,0x40,0x40,0x40,0x60,0,0xa,0xa,0xa,0xa,0,0,0,0, 0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, 0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0, +0,0,0,0xb1,0,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, +0xb1,0xb1,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, +0xb1,0xb1,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0xb1,0,0,0xb1,0xb1,0xb1,0xb1,0,0, +0xb1,0,0,0,0,0,0,0,0,0,0,0,0,0xb1,0xb1,0xb1, +0xb1,0xb1,0xb1,0,0,0xb1,0xb1,0,0,0xb1,0xb1,0,0,0,0,0, +0,0,0,0,0,0,0,0xb1,0,0,0,0,0,0,0,0, +0xb1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0xb1,0,0xb1,0xb1,0xb1,0,0,0xb1,0xb1,0,0,0, +0,0,0xb1,0xb1,0,0,0,0,0,0,0,0,0,0,0,0, +0xb1,0xb1,0,0,0,0,0,0,0,0,0xb1,0,0,0,0,0, +0,0,0,0,0,0xb1,0,0,0xb1,0,0,0,0,0xb1,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0xb1,0,0,0xb1,0xb1,0xb1,0xb1,0,0,0xb1,0,0,0, -0,0,0,0,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0, -0,0xb1,0xb1,0,0,0xb1,0xb1,0,0,0,0,0,0,0,0,0, -0,0,0,0xb1,0,0,0,0,0,0,0,0,0xb1,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0xb1,0,0xb1,0xb1,0xb1,0,0,0xb1,0xb1,0,0,0,0,0,0xb1,0xb1, -0,0,0,0,0,0,0,0,0,0,0,0,0xb1,0xb1,0,0, -0,0,0,0,0,0,0xb1,0,0,0,0,0,0,0,0,0, -0,0xb1,0,0,0xb1,0,0,0,0,0xb1,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1, -1,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,0xd,0xd,0xd,0xd, -0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0,0,0,0, -0,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,0xb1,1,0xd,0xd,0xd,0xd, +1,1,1,1,1,1,1,1,1,3,1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd, -0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xa,0xa,0xd,0xd,0xd,0xd, -0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0x12,0x12,0x12,0x12, -0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0xd,0xd,0xd,0xd, -0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xa,0xd,0xd,0xb1,0xb1,0xb1,0xb1, -0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0xa,0xa,0,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1, -0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,6,0xa,6,0, -0xa,6,0xa,0xa,0xa,0x310a,0xf20a,0x310a,0xf20a,0x310a,0xf20a,4,0xa,0xa,3,3, -0x300a,0xf00a,0xa,0,0xa,4,4,0xa,0,0,0,0,0xd,0xd,0xd,0xd, +0,0,0,0,0,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,0xb1,1, +0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd, +0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xa,0xa, 0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd, -0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xb2,0,0xa,0xa,4, -4,4,0xa,0xa,0x310a,0xf20a,0xa,3,6,3,6,6,2,2,2,2, -2,2,2,2,2,2,6,0xa,0x500a,0xa,0xd00a,0xa,0xa,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0x510a,0xa,0xd20a,0xa,0x310a,0xf20a,0xa,0x310a,0xf20a, -0xa,0xa,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,4,4,0xa,0xa, -0xa,4,4,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0x12,0x12,0x12,0x12, -0x12,0x12,0x12,0x12,0x12,0xaa,0xaa,0xaa,0xa,0xa,0x12,0x12,0,0xa,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0,0,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0,0,0,0xb1,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,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xb1,0xb1, -0xb1,0xb1,0xb1,0,0,0,0,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,0xa,1,0xb1,0xb1,0xb1,1,0xb1,0xb1,1, -1,1,1,1,0xb1,0xb1,0xb1,0xb1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -0xb1,0xb1,0xb1,1,1,1,1,0xb1,0x41,0x81,1,1,0x81,0xb1,0xb1,1, -1,1,1,0x41,0x41,0x41,0x41,0x81,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,0x41,0x41,0x41,0x41,0x41,0x81,1,0x81, -1,0x81,0x81,1,1,0x61,0x81,0x81,0x81,0x81,0x81,0x41,0x41,0x41,0x41,0x61, -0x41,0x41,0x41,0x41,0x41,0x81,0x41,0x41,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -1,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0x41,0x81,0x41,0x81,0x81,0x81,0x41,0x41, -0x41,0x81,0x41,0x41,0x81,0x41,0x81,0x81,0x41,0x81,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,0x81,0x81,0x81,0x81,0x41,0x41,1, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -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,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,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, -0xb1,0xb1,0xb1,0,0,0,0,0,0,0,0,0,0,0,0xa,0xa, -0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0,0,0xb1,0xb1,0, -0,0xa0,0,0,0,0,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1, -0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xb1, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xb1, -0xb1,0xb1,0,0,0xb1,0,0xb1,0xb1,0,0,0,0,0,0,0xb1,0, -0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0,0xb1,0xb1,0xb1,0xb1, -0xb1,0,0,0,0,0,0,0,0,0,0,0,0,0,0xb1,0xb1, -0xb1,0,0xb1,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xb1, -0xb1,0xb1,0xb1,0xb1,0xb1,0,0xb1,0,0,0,0,0xb1,0xb1,0,0xb1,0xb1, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xb1,0xb1, -0xb1,0xb1,0,0,0,0,0,0,0xb1,0xb1,0,0xb1,0xb1,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0xb1,0xb1,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xb1, -0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0xb1,0,0xb1,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xb1, -0,0xb1,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0xb1,0,0,0,0, -0,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0,0xb1,0xb1,0xb1,0xb1,0xb1, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0xb1,0xb1,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0xb1, -0xb1,0xb1,0xb1,0,0,0,0,0,0,0,0,0xb1,0,0,0,0, -0,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0xb1,0xb1,0xb1, -0,0,0,0,0,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, -0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0xb1,0xb1,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1, -0xb1,0xb1,0xb1,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0xa0,0xb1,0xb1,0xb1,0xb1, -0xb1,0xb1,0xb1,0xb1,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0xb1,0xb1, -0,0xb1,0xb1,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, -0xb1,0xb1,0xb1,0xb1,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0,0xb1,0, -0xb1,0xb1,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0xb1,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1, -0xb1,0xb1,0xb1,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0xb1,0xb1,0xb1,0xb1,0,0,0,0,0,0,0,0,0, -0,0,0,0,0xb2,0xb2,0xb2,0xb2,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0xb1,0xb1,0xb1,0,0,0,0,0,0, -0,0,0,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb1,0xb1,0xb1,0xb1,0xb1, -0xb1,0xb1,0xb1,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0xb1,0xb1,0xb1,0xb1,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0xa,0xa,0xb1,0xb1,0xb1,0xa,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0x100a,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0x100a,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0x100a,0,0,0,0, -0,0,0,0,0,0,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,2,2,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, -0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0, -0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, -0xb1,0,0,0,0,0,0,0,0,0xb1,0,0,0,0,0,0, -0,0,0,0,0xb1,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1, -0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, -0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0xb1,0xb1,0xb1,0xb1,0xb1, -0xb1,0xb1,0,0xb1,0xb1,0,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, -0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,1,1,1,1,1,1,1,1,1, -0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41, -0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41, -0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,1,1,1,1,1,1,1,1,1, -1,1,1,1,1,1,1,1,1,1,1,1,0xd,0xd,0xd,0xd, -0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xa,0xa,0xd,0xd, -0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0,0,0,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0, -0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -2,2,2,2,2,2,2,2,2,2,2,0xa,0xa,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0xa,0xa,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0,0, -0,0,0,0,0,0,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0xa,0,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0xa,0,0,0,0,0,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0,0,0,0,0,0,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0xa,0xa,0,0,0,0,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0,0,0,0,0,0,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0xa,0,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, -0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0x12,0x12,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2, -0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2, -0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0x12,0xb2,0x12,0x12,0x12,0x12,0x12,0x12, 0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, -0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0xb1,0xb1,0xb1,0xb1, -0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0x12,0x12,0x12,0x12, -0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0,0,0,0 +0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xa,0xd,0xd, +0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, +0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0,0,0,0,0, +0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, +0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, +6,0xa,6,0,0xa,6,0xa,0xa,0xa,0x310a,0xf20a,0x310a,0xf20a,0x310a,0xf20a,4, +0xa,0xa,3,3,0x300a,0xf00a,0xa,0,0xa,4,4,0xa,0,0,0,0, +0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd, +0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xb2, +0,0xa,0xa,4,4,4,0xa,0xa,0x310a,0xf20a,0xa,3,6,3,6,6, +2,2,2,2,2,2,2,2,2,2,6,0xa,0x500a,0xa,0xd00a,0xa, +0xa,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0x510a,0xa,0xd20a,0xa,0x310a, +0xf20a,0xa,0x310a,0xf20a,0xa,0xa,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +4,4,0xa,0xa,0xa,4,4,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0, +0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0xaa,0xaa,0xaa,0xa,0xa,0x12,0x12, +0,0xa,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0,0, +0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0,0,0, +0xb1,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,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0,0,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,0xa,1,0xb1,0xb1,0xb1, +1,0xb1,0xb1,1,1,1,1,1,0xb1,0xb1,0xb1,0xb1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,0xb1,0xb1,0xb1,1,1,1,1,0xb1,0x41,0x81,1,1, +0x81,0xb1,0xb1,1,1,1,1,0x41,0x41,0x41,0x41,0x81,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,0x41,0x41,0x41,0x41, +0x41,0x81,1,0x81,1,0x81,0x81,1,1,0x61,0x81,0x81,0x81,0x81,0x81,0x41, +0x41,0x41,0x41,0x61,0x41,0x41,0x41,0x41,0x41,0x81,0x41,0x41,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,1,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0x41,0x81,0x41,0x81, +0x81,0x81,0x41,0x41,0x41,0x81,0x41,0x41,0x81,0x41,0x81,0x81,0x41,0x81,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,0x81,0x81,0x81, +0x81,0x41,0x41,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,0x4d,0x4d,0x8d,0x4d,0xb1,0xb1,0xb1,0xb1,0xd,0xd,0xd,0xd, +0xd,0xd,0xd,0xd,5,5,5,5,5,5,5,5,5,5,0xd,0xd, +0xd,0xd,0xd,0xd,0x6d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d, +0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d, +0x4d,0x4d,0x4d,0x4d,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,1,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,0x4d,0x4d,0x4d,0x8d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d,0x4d, +0x4d,0x4d,0x4d,0x4d,0x4d,0xd,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, +0xb1,0x4d,0x4d,0x4d,0x8d,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd, +0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,1,1,1,1,1,1,1,1, +1,1,1,1,1,1,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, +0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0,0,0, +0,0,0,0,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, +0xa,0xa,0xa,0xa,0xa,0xa,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xb1, +0xb1,0xb1,0xb1,0,0,0xb1,0xb1,0,0,0,0,0,0,0,0,0xb1, +0xb1,0xb1,0xb1,0xb1,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0xb1,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, +0xb1,0xb1,0xb1,0,0,0,0,0,0,0,0,0,0,0xb1,0xb1,0xb1, +0xb1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0xb1,0xb1,0xb1,0,0,0xb1,0,0xb1,0xb1, +0,0,0,0,0,0,0xb1,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1, +0xb1,0xb1,0xb1,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, +0xb1,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0,0,0,0,0, +0,0,0,0,0,0,0xb1,0xb1,0xb1,0,0xb1,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0xb1,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0xb1,0, +0,0,0,0xb1,0xb1,0,0xb1,0xb1,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0,0,0,0,0,0, +0xb1,0xb1,0,0xb1,0xb1,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0xb1,0xb1,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0, +0,0xb1,0,0xb1,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, +0xa,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0xb1,0,0xb1,0,0,0xb1,0xb1,0xb1,0xb1, +0xb1,0xb1,0,0xb1,0,0,0,0,0,0,0,0,0,0,0xb1,0xb1, +0xb1,0xb1,0,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xb1, +0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0xb1,0xb1,0,0,0,0,0, +0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xa0,0xa0,0xb1,0xb1,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0xb1,0xb1,0xb1,0xb1,0, +0,0,0,0,0,0,0,0xb1,0,0,0,0,0,0,0,0, +0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0xb1,0xb1,0xb1,0,0,0,0, +0,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, +0xb1,0xb1,0xb1,0,0xb1,0xb1,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0, +0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0xa0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, +0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0xb1,0xb1,0,0xb1,0xb1,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0,0xb1,0,0xb1,0xb1,0,0xb1, +0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0xb1,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0xb1,0xb1,0,0,0,0xb1,0,0xb1,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0,0,0,0,0, +0,0,0,0,0,0,0,0,0xb2,0xb2,0xb2,0xb2,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0xb1,0xb1,0xb1,0,0, +0,0,0,0,0,0,0,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb1, +0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0xa,0xa,0xb1,0xb1, +0xb1,0xa,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0x100a, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0x100a,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0x100a, +0,0,0,0,0,0,0,0,0,0,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,2,2,0xb1,0xb1,0xb1,0xb1, +0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, +0xb1,0xb1,0xb1,0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, +0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0,0,0,0,0,0,0xb1,0,0, +0,0,0,0,0,0,0,0,0xb1,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xb1, +0xb1,0xb1,0xb1,0xb1,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, +0xb1,0xb1,0xb1,0xb1,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0xb1,0xb1,0xb1,0xb1, +0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0,0xb1, +0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0,0xb1,0xb1,0,0xb1,0xb1,0xb1,0xb1,0xb1,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1, +1,1,1,1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,1,1,1,1,1, +1,1,1,1,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41, +0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41, +0x41,0x41,0x41,0x41,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,1,1,1,1,1, +1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, +0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd, +0xa,0xa,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd,0xd, +0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0,0,0, +0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, +0xa,0xa,0xa,0,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, +0xa,0xa,0xa,0xa,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, +0xa,0xa,0xa,0xa,2,2,2,2,2,2,2,2,2,2,2,0xa, +0xa,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0xa,0xa,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0xa,0xa,0xa,0xa, +0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, +0xa,0,0,0,0,0,0,0,0,0,0,0,0xa,0xa,0xa,0xa, +0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0,0,0xa,0xa,0xa,0xa, +0xa,0xa,0xa,0xa,0xa,0xa,0,0,0,0,0,0,0xa,0xa,0xa,0xa, +0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, +0xa,0xa,0xa,0xa,0xa,0,0,0,0,0,0,0,0xa,0xa,0xa,0xa, +0xa,0xa,0xa,0xa,0,0,0,0,0,0,0,0,0xa,0xa,0xa,0xa, +0xa,0xa,0xa,0xa,0xa,0xa,0,0,0,0,0,0,0xa,0xa,0xa,0xa, +0xa,0xa,0xa,0xa,0,0,0,0,0,0,0,0,0xa,0xa,0xa,0xa, +0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa, +0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0xa,0xa,0xa,0xa, +0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0,0xa, +0xa,0xa,0xa,0,0,0,0xa,0,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0, +0,0,0,0,0,0,0,0,0,0,0,0,0xa,0xa,0xa,0xa, +0xa,0xa,0xa,0xa,0xa,0xa,0,0,0,0,0,0,0xa,0xa,0xa,0, +0,0,0,0,0,0,0,0,0,0,0,0,0xa,0xa,0xa,0xa, +0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0xa,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0x12,0x12,0xb2,0xb2,0xb2,0xb2, +0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2, +0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0xb2,0x12,0xb2,0x12,0x12, +0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, +0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, +0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1,0xb1, +0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, +0,0,0,0 }; -static const uint32_t ubidi_props_mirrors[26]={ -0x2000ab,0xbb,0x2a02215,0x1202243,0x2802298,0x2c022a6,0x30022a8,0x2e022a9,0x32022ab,0x6022cd,0x1e022f2,0x20022f3,0x22022f4,0x24022f6,0x26022f7,0x14022fa, -0x16022fb,0x18022fc,0x1a022fd,0x1c022fe,0x8029b8,0x4029f5,0xa02ade,0xe02ae3,0xc02ae4,0x1002ae5 +static const uint32_t ubidi_props_mirrors[40]={ +0x2000ab,0xbb,0x4202215,0x4e0221f,0x3e02220,0x3a02221,0x3c02222,0x4c02224,0x2202243,0x1402245,0x120224c,0x4002298,0x44022a6,0x48022a8,0x46022a9,0x4a022ab, +0x38022b8,0x10022cd,0x2e022f2,0x30022f3,0x32022f4,0x34022f6,0x36022f7,0x24022fa,0x26022fb,0x28022fc,0x2a022fd,0x2c022fe,0x20027dc,0xa0299b,0xc029a0,0x8029a3, +0x16029b8,0x4029f5,0x1802ade,0x1c02ae3,0x1a02ae4,0x1e02ae5,0xe02aee,0x602bfe }; static const uint8_t ubidi_props_jgArray[672]={ @@ -809,10 +826,46 @@ static const uint8_t ubidi_props_jgArray[672]={ 0xb,0x55,0x1f,1,0x13,0,4,4,4,0x1f,0x2d,0x56,0x58,0x57,0,0 }; -static const uint8_t ubidi_props_jgArray2[48]={ +static const uint8_t ubidi_props_jgArray2[612]={ 0x3a,0x3c,0x3c,0x40,0x40,0x3d,0,0x52,0,0x54,0x54,0,0,0x41,0x4f,0x53, 0x43,0x43,0x43,0x44,0x3e,0x50,0x45,0x46,0x4c,0x3b,0x3b,0x48,0x48,0x4b,0x49,0x49, -0x49,0x4a,0,0,0x4d,0,0,0,0,0,0,0x47,0x3f,0x4e,0x51,0x42 +0x49,0x4a,0,0,0x4d,0,0,0,0,0,0,0x47,0x3f,0x4e,0x51,0x42, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0x65,0,0,0,0,0,0,0x65,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0x64,0,0,0x65,0,0x64,0, +0x64,0,0,0x64 }; static const UBiDiProps ubidi_props_singleton={ @@ -823,16 +876,16 @@ static const UBiDiProps ubidi_props_singleton={ ubidi_props_jgArray2, { ubidi_props_trieIndex, - ubidi_props_trieIndex+3496, + ubidi_props_trieIndex+3516, NULL, - 3496, - 8360, + 3516, + 8584, 0x1a0, - 0xe28, + 0xe3c, 0x0, 0x0, 0x110000, - 0x2e4c, + 0x2f40, NULL, 0, FALSE, FALSE, 0, NULL }, { 2,2,0,0 } diff --git a/deps/icu-small/source/common/ucase.cpp b/deps/icu-small/source/common/ucase.cpp index 28d5a4cac62..43c57f896e9 100644 --- a/deps/icu-small/source/common/ucase.cpp +++ b/deps/icu-small/source/common/ucase.cpp @@ -138,6 +138,11 @@ ucase_tolower(UChar32 c) { } else { const uint16_t *pe=GET_EXCEPTIONS(&ucase_props_singleton, props); uint16_t excWord=*pe++; + 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); + return (excWord&UCASE_EXC_DELTA_IS_NEGATIVE)==0 ? c+delta : c-delta; + } if(HAS_SLOT(excWord, UCASE_EXC_LOWER)) { GET_SLOT_VALUE(excWord, UCASE_EXC_LOWER, pe, c); } @@ -155,6 +160,11 @@ ucase_toupper(UChar32 c) { } else { const uint16_t *pe=GET_EXCEPTIONS(&ucase_props_singleton, props); uint16_t excWord=*pe++; + 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); + return (excWord&UCASE_EXC_DELTA_IS_NEGATIVE)==0 ? c+delta : c-delta; + } if(HAS_SLOT(excWord, UCASE_EXC_UPPER)) { GET_SLOT_VALUE(excWord, UCASE_EXC_UPPER, pe, c); } @@ -172,6 +182,11 @@ ucase_totitle(UChar32 c) { } else { const uint16_t *pe=GET_EXCEPTIONS(&ucase_props_singleton, props); uint16_t excWord=*pe++; + 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); + return (excWord&UCASE_EXC_DELTA_IS_NEGATIVE)==0 ? c+delta : c-delta; + } int32_t idx; if(HAS_SLOT(excWord, UCASE_EXC_TITLE)) { idx=UCASE_EXC_TITLE; @@ -254,6 +269,11 @@ ucase_addCaseClosure(UChar32 c, const USetAdder *sa) { sa->add(sa->set, c); } } + if(HAS_SLOT(excWord, UCASE_EXC_DELTA)) { + 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); + } /* get the closure string pointer & length */ if(HAS_SLOT(excWord, UCASE_EXC_CLOSURE)) { @@ -590,7 +610,12 @@ ucase_isSoftDotted(UChar32 c) { U_CAPI UBool U_EXPORT2 ucase_isCaseSensitive(UChar32 c) { uint16_t props=UTRIE2_GET16(&ucase_props_singleton.trie, c); - return (UBool)((props&UCASE_SENSITIVE)!=0); + if(!UCASE_HAS_EXCEPTION(props)) { + return (UBool)((props&UCASE_SENSITIVE)!=0); + } else { + const uint16_t *pe=GET_EXCEPTIONS(&ucase_props_singleton, props); + return (UBool)((*pe&UCASE_EXC_SENSITIVE)!=0); + } } /* string casing ------------------------------------------------------------ */ @@ -1140,6 +1165,11 @@ 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); + return (excWord&UCASE_EXC_DELTA_IS_NEGATIVE)==0 ? c+delta : c-delta; + } if(HAS_SLOT(excWord, UCASE_EXC_LOWER)) { GET_SLOT_VALUE(excWord, UCASE_EXC_LOWER, pe2, result); } @@ -1229,6 +1259,11 @@ 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); + return (excWord&UCASE_EXC_DELTA_IS_NEGATIVE)==0 ? c+delta : c-delta; + } if(!upperNotTitle && HAS_SLOT(excWord, UCASE_EXC_TITLE)) { idx=UCASE_EXC_TITLE; } else if(HAS_SLOT(excWord, UCASE_EXC_UPPER)) { @@ -1334,6 +1369,14 @@ ucase_fold(UChar32 c, uint32_t options) { } } } + if((excWord&UCASE_EXC_NO_SIMPLE_CASE_FOLDING)!=0) { + return 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); + return (excWord&UCASE_EXC_DELTA_IS_NEGATIVE)==0 ? c+delta : c-delta; + } if(HAS_SLOT(excWord, UCASE_EXC_FOLD)) { idx=UCASE_EXC_FOLD; } else if(HAS_SLOT(excWord, UCASE_EXC_LOWER)) { @@ -1421,6 +1464,14 @@ ucase_toFullFolding(UChar32 c, } } + if((excWord&UCASE_EXC_NO_SIMPLE_CASE_FOLDING)!=0) { + return ~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); + return (excWord&UCASE_EXC_DELTA_IS_NEGATIVE)==0 ? c+delta : c-delta; + } if(HAS_SLOT(excWord, UCASE_EXC_FOLD)) { idx=UCASE_EXC_FOLD; } else if(HAS_SLOT(excWord, UCASE_EXC_LOWER)) { diff --git a/deps/icu-small/source/common/ucase.h b/deps/icu-small/source/common/ucase.h index a7a8c9f00d1..b0a453b87e8 100644 --- a/deps/icu-small/source/common/ucase.h +++ b/deps/icu-small/source/common/ucase.h @@ -354,8 +354,8 @@ enum { #define UCASE_IS_UPPER_OR_TITLE(props) ((props)&2) #define UCASE_IGNORABLE 4 -#define UCASE_SENSITIVE 8 -#define UCASE_EXCEPTION 0x10 +#define UCASE_EXCEPTION 8 +#define UCASE_SENSITIVE 0x10 #define UCASE_HAS_EXCEPTION(props) ((props)&UCASE_EXCEPTION) @@ -379,9 +379,9 @@ enum { # define UCASE_GET_DELTA(props) (int16_t)(((props)&0x8000) ? (((props)>>UCASE_DELTA_SHIFT)|0xfe00) : ((uint16_t)(props)>>UCASE_DELTA_SHIFT)) #endif -/* exception: bits 15..5 are an unsigned 11-bit index into the exceptions array */ -#define UCASE_EXC_SHIFT 5 -#define UCASE_EXC_MASK 0xffe0 +/* exception: bits 15..4 are an unsigned 12-bit index into the exceptions array */ +#define UCASE_EXC_SHIFT 4 +#define UCASE_EXC_MASK 0xfff0 #define UCASE_MAX_EXCEPTIONS ((UCASE_EXC_MASK>>UCASE_EXC_SHIFT)+1) /* definitions for 16-bit main exceptions word ------------------------------ */ @@ -392,7 +392,7 @@ enum { UCASE_EXC_FOLD, UCASE_EXC_UPPER, UCASE_EXC_TITLE, - UCASE_EXC_4, /* reserved */ + UCASE_EXC_DELTA, UCASE_EXC_5, /* reserved */ UCASE_EXC_CLOSURE, UCASE_EXC_FULL_MAPPINGS, @@ -402,7 +402,11 @@ enum { /* each slot is 2 uint16_t instead of 1 */ #define UCASE_EXC_DOUBLE_SLOTS 0x100 -/* reserved: exception bits 11..9 */ +enum { + UCASE_EXC_NO_SIMPLE_CASE_FOLDING=0x200, + UCASE_EXC_DELTA_IS_NEGATIVE=0x400, + UCASE_EXC_SENSITIVE=0x800 +}; /* UCASE_EXC_DOT_MASK=UCASE_DOT_MASK< *maxMatchLen && len <= textLen && uprv_memcmp(currencyNames[index].currencyName, text, len * sizeof(UChar)) == 0) { + *partialMatchLen = MAX(*partialMatchLen, len); *maxMatchIndex = index; *maxMatchLen = len; #ifdef UCURR_DEBUG printf("maxMatchIndex = %d, maxMatchLen = %d\n", *maxMatchIndex, *maxMatchLen); #endif + } else { + // Check for partial matches. + for (int32_t i=initialPartialMatchLen; icurrencyNames; - total_currency_name_count = cacheEntry->totalCurrencyNameCount; - currencySymbols = cacheEntry->currencySymbols; - total_currency_symbol_count = cacheEntry->totalCurrencySymbolCount; ++(cacheEntry->refCount); } umtx_unlock(&gCurrencyCacheMutex); if (found == -1) { collectCurrencyNames(locale, ¤cyNames, &total_currency_name_count, ¤cySymbols, &total_currency_symbol_count, ec); if (U_FAILURE(ec)) { - return; + return NULL; } umtx_lock(&gCurrencyCacheMutex); // check again. @@ -1500,20 +1500,50 @@ uprv_parseCurrency(const char* locale, cacheEntry->totalCurrencySymbolCount = total_currency_symbol_count; cacheEntry->refCount = 2; // one for cache, one for reference currentCacheEntryIndex = (currentCacheEntryIndex + 1) % CURRENCY_NAME_CACHE_NUM; - ucln_common_registerCleanup(UCLN_COMMON_CURRENCY, currency_cache_cleanup); + ucln_common_registerCleanup(UCLN_COMMON_CURRENCY, currency_cleanup); } else { deleteCurrencyNames(currencyNames, total_currency_name_count); deleteCurrencyNames(currencySymbols, total_currency_symbol_count); cacheEntry = currCache[found]; - currencyNames = cacheEntry->currencyNames; - total_currency_name_count = cacheEntry->totalCurrencyNameCount; - currencySymbols = cacheEntry->currencySymbols; - total_currency_symbol_count = cacheEntry->totalCurrencySymbolCount; ++(cacheEntry->refCount); } umtx_unlock(&gCurrencyCacheMutex); } + return cacheEntry; +} + +static void releaseCacheEntry(CurrencyNameCacheEntry* cacheEntry) { + umtx_lock(&gCurrencyCacheMutex); + --(cacheEntry->refCount); + if (cacheEntry->refCount == 0) { // remove + deleteCacheEntry(cacheEntry); + } + umtx_unlock(&gCurrencyCacheMutex); +} + +U_CAPI void +uprv_parseCurrency(const char* locale, + const icu::UnicodeString& text, + icu::ParsePosition& pos, + int8_t type, + int32_t* partialMatchLen, + UChar* result, + UErrorCode& ec) { + U_NAMESPACE_USE + if (U_FAILURE(ec)) { + return; + } + CurrencyNameCacheEntry* cacheEntry = getCacheEntry(locale, ec); + if (U_FAILURE(ec)) { + return; + } + + int32_t total_currency_name_count = cacheEntry->totalCurrencyNameCount; + CurrencyNameStruct* currencyNames = cacheEntry->currencyNames; + int32_t total_currency_symbol_count = cacheEntry->totalCurrencySymbolCount; + CurrencyNameStruct* currencySymbols = cacheEntry->currencySymbols; + int32_t start = pos.getIndex(); UChar inputText[MAX_CURRENCY_NAME_LEN]; @@ -1523,11 +1553,14 @@ uprv_parseCurrency(const char* locale, UErrorCode ec1 = U_ZERO_ERROR; textLen = u_strToUpper(upperText, MAX_CURRENCY_NAME_LEN, inputText, textLen, locale, &ec1); + // Make sure partialMatchLen is initialized + *partialMatchLen = 0; + int32_t max = 0; int32_t matchIndex = -1; // case in-sensitive comparision against currency names searchCurrencyName(currencyNames, total_currency_name_count, - upperText, textLen, &max, &matchIndex); + upperText, textLen, partialMatchLen, &max, &matchIndex); #ifdef UCURR_DEBUG printf("search in names, max = %d, matchIndex = %d\n", max, matchIndex); @@ -1539,6 +1572,7 @@ uprv_parseCurrency(const char* locale, // case sensitive comparison against currency symbols and ISO code. searchCurrencyName(currencySymbols, total_currency_symbol_count, inputText, textLen, + partialMatchLen, &maxInSymbol, &matchIndexInSymbol); } @@ -1558,12 +1592,35 @@ uprv_parseCurrency(const char* locale, } // decrease reference count - umtx_lock(&gCurrencyCacheMutex); - --(cacheEntry->refCount); - if (cacheEntry->refCount == 0) { // remove - deleteCacheEntry(cacheEntry); + releaseCacheEntry(cacheEntry); +} + +void uprv_currencyLeads(const char* locale, icu::UnicodeSet& result, UErrorCode& ec) { + U_NAMESPACE_USE + if (U_FAILURE(ec)) { + return; } - umtx_unlock(&gCurrencyCacheMutex); + CurrencyNameCacheEntry* cacheEntry = getCacheEntry(locale, ec); + if (U_FAILURE(ec)) { + return; + } + + for (int32_t i=0; itotalCurrencySymbolCount; i++) { + const CurrencyNameStruct& info = cacheEntry->currencySymbols[i]; + UChar32 cp; + U16_GET(info.currencyName, 0, 0, info.currencyNameLen, cp); + result.add(cp); + } + + for (int32_t i=0; itotalCurrencyNameCount; i++) { + const CurrencyNameStruct& info = cacheEntry->currencyNames[i]; + UChar32 cp; + U16_GET(info.currencyName, 0, 0, info.currencyNameLen, cp); + result.add(cp); + } + + // decrease reference count + releaseCacheEntry(cacheEntry); } @@ -1729,7 +1786,8 @@ static const struct CurrencyList { {"BUK", UCURR_COMMON|UCURR_DEPRECATED}, {"BWP", UCURR_COMMON|UCURR_NON_DEPRECATED}, {"BYB", UCURR_COMMON|UCURR_DEPRECATED}, - {"BYR", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"BYN", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"BYR", UCURR_COMMON|UCURR_DEPRECATED}, {"BZD", UCURR_COMMON|UCURR_NON_DEPRECATED}, {"CAD", UCURR_COMMON|UCURR_NON_DEPRECATED}, {"CDF", UCURR_COMMON|UCURR_NON_DEPRECATED}, @@ -1739,6 +1797,7 @@ static const struct CurrencyList { {"CLE", UCURR_COMMON|UCURR_DEPRECATED}, {"CLF", UCURR_UNCOMMON|UCURR_NON_DEPRECATED}, {"CLP", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"CNH", UCURR_UNCOMMON|UCURR_NON_DEPRECATED}, {"CNX", UCURR_UNCOMMON|UCURR_DEPRECATED}, {"CNY", UCURR_COMMON|UCURR_NON_DEPRECATED}, {"COP", UCURR_COMMON|UCURR_NON_DEPRECATED}, @@ -1761,7 +1820,7 @@ static const struct CurrencyList { {"ECV", UCURR_UNCOMMON|UCURR_DEPRECATED}, {"EEK", UCURR_COMMON|UCURR_DEPRECATED}, {"EGP", UCURR_COMMON|UCURR_NON_DEPRECATED}, - {"EQE", UCURR_COMMON|UCURR_DEPRECATED}, + {"EQE", UCURR_COMMON|UCURR_DEPRECATED}, // questionable, remove? {"ERN", UCURR_COMMON|UCURR_NON_DEPRECATED}, {"ESA", UCURR_UNCOMMON|UCURR_DEPRECATED}, {"ESB", UCURR_UNCOMMON|UCURR_DEPRECATED}, @@ -1785,7 +1844,7 @@ static const struct CurrencyList { {"GRD", UCURR_COMMON|UCURR_DEPRECATED}, {"GTQ", UCURR_COMMON|UCURR_NON_DEPRECATED}, {"GWE", UCURR_COMMON|UCURR_DEPRECATED}, - {"GWP", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"GWP", UCURR_COMMON|UCURR_DEPRECATED}, {"GYD", UCURR_COMMON|UCURR_NON_DEPRECATED}, {"HKD", UCURR_COMMON|UCURR_NON_DEPRECATED}, {"HNL", UCURR_COMMON|UCURR_NON_DEPRECATED}, @@ -1823,13 +1882,13 @@ static const struct CurrencyList { {"LKR", UCURR_COMMON|UCURR_NON_DEPRECATED}, {"LRD", UCURR_COMMON|UCURR_NON_DEPRECATED}, {"LSL", UCURR_COMMON|UCURR_NON_DEPRECATED}, - {"LSM", UCURR_COMMON|UCURR_DEPRECATED}, - {"LTL", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"LSM", UCURR_COMMON|UCURR_DEPRECATED}, // questionable, remove? + {"LTL", UCURR_COMMON|UCURR_DEPRECATED}, {"LTT", UCURR_COMMON|UCURR_DEPRECATED}, {"LUC", UCURR_UNCOMMON|UCURR_DEPRECATED}, {"LUF", UCURR_COMMON|UCURR_DEPRECATED}, {"LUL", UCURR_UNCOMMON|UCURR_DEPRECATED}, - {"LVL", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"LVL", UCURR_COMMON|UCURR_DEPRECATED}, {"LVR", UCURR_COMMON|UCURR_DEPRECATED}, {"LYD", UCURR_COMMON|UCURR_NON_DEPRECATED}, {"MAD", UCURR_COMMON|UCURR_NON_DEPRECATED}, @@ -1845,18 +1904,19 @@ static const struct CurrencyList { {"MMK", UCURR_COMMON|UCURR_NON_DEPRECATED}, {"MNT", UCURR_COMMON|UCURR_NON_DEPRECATED}, {"MOP", UCURR_COMMON|UCURR_NON_DEPRECATED}, - {"MRO", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"MRO", UCURR_COMMON|UCURR_DEPRECATED}, + {"MRU", UCURR_COMMON|UCURR_NON_DEPRECATED}, {"MTL", UCURR_COMMON|UCURR_DEPRECATED}, {"MTP", UCURR_COMMON|UCURR_DEPRECATED}, {"MUR", UCURR_COMMON|UCURR_NON_DEPRECATED}, - {"MVP", UCURR_COMMON|UCURR_DEPRECATED}, + {"MVP", UCURR_COMMON|UCURR_DEPRECATED}, // questionable, remove? {"MVR", UCURR_COMMON|UCURR_NON_DEPRECATED}, {"MWK", UCURR_COMMON|UCURR_NON_DEPRECATED}, {"MXN", UCURR_COMMON|UCURR_NON_DEPRECATED}, {"MXP", UCURR_COMMON|UCURR_DEPRECATED}, {"MXV", UCURR_UNCOMMON|UCURR_NON_DEPRECATED}, {"MYR", UCURR_COMMON|UCURR_NON_DEPRECATED}, - {"MZE", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"MZE", UCURR_COMMON|UCURR_DEPRECATED}, {"MZM", UCURR_COMMON|UCURR_DEPRECATED}, {"MZN", UCURR_COMMON|UCURR_NON_DEPRECATED}, {"NAD", UCURR_COMMON|UCURR_NON_DEPRECATED}, @@ -1897,15 +1957,16 @@ static const struct CurrencyList { {"SGD", UCURR_COMMON|UCURR_NON_DEPRECATED}, {"SHP", UCURR_COMMON|UCURR_NON_DEPRECATED}, {"SIT", UCURR_COMMON|UCURR_DEPRECATED}, - {"SKK", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"SKK", UCURR_COMMON|UCURR_DEPRECATED}, {"SLL", UCURR_COMMON|UCURR_NON_DEPRECATED}, {"SOS", UCURR_COMMON|UCURR_NON_DEPRECATED}, {"SRD", UCURR_COMMON|UCURR_NON_DEPRECATED}, {"SRG", UCURR_COMMON|UCURR_DEPRECATED}, {"SSP", UCURR_COMMON|UCURR_NON_DEPRECATED}, - {"STD", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"STD", UCURR_COMMON|UCURR_DEPRECATED}, + {"STN", UCURR_COMMON|UCURR_NON_DEPRECATED}, {"SUR", UCURR_COMMON|UCURR_DEPRECATED}, - {"SVC", UCURR_COMMON|UCURR_NON_DEPRECATED}, + {"SVC", UCURR_COMMON|UCURR_DEPRECATED}, {"SYP", UCURR_COMMON|UCURR_NON_DEPRECATED}, {"SZL", UCURR_COMMON|UCURR_NON_DEPRECATED}, {"THB", UCURR_COMMON|UCURR_NON_DEPRECATED}, @@ -1954,7 +2015,7 @@ static const struct CurrencyList { {"XPD", UCURR_UNCOMMON|UCURR_NON_DEPRECATED}, {"XPF", UCURR_COMMON|UCURR_NON_DEPRECATED}, {"XPT", UCURR_UNCOMMON|UCURR_NON_DEPRECATED}, - {"XRE", UCURR_UNCOMMON|UCURR_NON_DEPRECATED}, + {"XRE", UCURR_UNCOMMON|UCURR_DEPRECATED}, {"XSU", UCURR_UNCOMMON|UCURR_NON_DEPRECATED}, {"XTS", UCURR_UNCOMMON|UCURR_NON_DEPRECATED}, {"XUA", UCURR_UNCOMMON|UCURR_NON_DEPRECATED}, @@ -1965,15 +2026,15 @@ static const struct CurrencyList { {"YUM", UCURR_COMMON|UCURR_DEPRECATED}, {"YUN", UCURR_COMMON|UCURR_DEPRECATED}, {"YUR", UCURR_COMMON|UCURR_DEPRECATED}, - {"ZAL", UCURR_UNCOMMON|UCURR_NON_DEPRECATED}, + {"ZAL", UCURR_UNCOMMON|UCURR_DEPRECATED}, {"ZAR", UCURR_COMMON|UCURR_NON_DEPRECATED}, {"ZMK", UCURR_COMMON|UCURR_DEPRECATED}, {"ZMW", UCURR_COMMON|UCURR_NON_DEPRECATED}, {"ZRN", UCURR_COMMON|UCURR_DEPRECATED}, {"ZRZ", UCURR_COMMON|UCURR_DEPRECATED}, + {"ZWD", UCURR_COMMON|UCURR_DEPRECATED}, {"ZWL", UCURR_COMMON|UCURR_DEPRECATED}, {"ZWR", UCURR_COMMON|UCURR_DEPRECATED}, - {"ZWD", UCURR_COMMON|UCURR_DEPRECATED}, { NULL, 0 } // Leave here to denote the end of the list. }; @@ -2144,16 +2205,20 @@ static void U_CALLCONV initIsoCodes(UErrorCode &status) { } static void populateCurrSymbolsEquiv(icu::Hashtable *hash, UErrorCode &status) { - if (U_FAILURE(status)) { - return; - } - int32_t length = UPRV_LENGTHOF(EQUIV_CURRENCY_SYMBOLS); - for (int32_t i = 0; i < length; ++i) { - icu::UnicodeString lhs(EQUIV_CURRENCY_SYMBOLS[i][0], -1, US_INV); - icu::UnicodeString rhs(EQUIV_CURRENCY_SYMBOLS[i][1], -1, US_INV); - makeEquivalent(lhs.unescape(), rhs.unescape(), hash, status); - if (U_FAILURE(status)) { - return; + if (U_FAILURE(status)) { return; } + for (auto& entry : unisets::kCurrencyEntries) { + UnicodeString exemplar(entry.exemplar); + const UnicodeSet* set = unisets::get(entry.key); + if (set == nullptr) { return; } + UnicodeSetIterator it(*set); + while (it.next()) { + UnicodeString value = it.getString(); + if (value == exemplar) { + // No need to mark the exemplar character as an equivalent + continue; + } + makeEquivalent(exemplar, value, hash, status); + if (U_FAILURE(status)) { return; } } } } diff --git a/deps/icu-small/source/common/ucurrimp.h b/deps/icu-small/source/common/ucurrimp.h index 6e468fd4c94..6d9588295df 100644 --- a/deps/icu-small/source/common/ucurrimp.h +++ b/deps/icu-small/source/common/ucurrimp.h @@ -13,6 +13,7 @@ #include "unicode/utypes.h" #include "unicode/unistr.h" #include "unicode/parsepos.h" +#include "unicode/uniset.h" /** * Internal method. Given a currency ISO code and a locale, return @@ -36,6 +37,8 @@ uprv_getStaticCurrencyName(const UChar* iso, const char* loc, * match, then the display name is preferred, unless it's length * is less than 3. * + * The parameters must not be NULL. + * * @param locale the locale of the display names to match * @param text the text to parse * @param pos input-output position; on input, the position within @@ -43,6 +46,8 @@ uprv_getStaticCurrencyName(const UChar* iso, const char* loc, * on output, the position after the last matched character. If * the parse fails, the position in unchanged upon output. * @param type currency type to parse against, LONG_NAME only or not + * @param partialMatchLen The length of the longest matching prefix; + * this may be nonzero even if no full currency was matched. * @return the ISO 4217 code, as a string, of the best match, or * null if there is no match * @@ -53,9 +58,21 @@ uprv_parseCurrency(const char* locale, const icu::UnicodeString& text, icu::ParsePosition& pos, int8_t type, + int32_t* partialMatchLen, UChar* result, UErrorCode& ec); +/** + * Puts all possible first-characters of a currency into the + * specified UnicodeSet. + * + * @param locale the locale of the display names of interest + * @param result the UnicodeSet to which to add the starting characters + */ +void uprv_currencyLeads(const char* locale, icu::UnicodeSet& result, UErrorCode& ec); + + + #endif /* #ifndef _UCURR_IMP_H_ */ //eof diff --git a/deps/icu-small/source/common/unicode/brkiter.h b/deps/icu-small/source/common/unicode/brkiter.h index 607f3ec625a..5faeedfa93e 100644 --- a/deps/icu-small/source/common/unicode/brkiter.h +++ b/deps/icu-small/source/common/unicode/brkiter.h @@ -638,7 +638,7 @@ protected: private: - /** @internal */ + /** @internal (private) */ char actualLocale[ULOC_FULLNAME_CAPACITY]; char validLocale[ULOC_FULLNAME_CAPACITY]; }; diff --git a/deps/icu-small/source/common/unicode/bytestriebuilder.h b/deps/icu-small/source/common/unicode/bytestriebuilder.h index 7a806bb7f02..b164e3bbd68 100644 --- a/deps/icu-small/source/common/unicode/bytestriebuilder.h +++ b/deps/icu-small/source/common/unicode/bytestriebuilder.h @@ -143,7 +143,7 @@ private: virtual int32_t getMaxLinearMatchLength() const { return BytesTrie::kMaxLinearMatchLength; } /** - * @internal + * @internal (private) */ class BTLinearMatchNode : public LinearMatchNode { public: diff --git a/deps/icu-small/source/common/unicode/caniter.h b/deps/icu-small/source/common/unicode/caniter.h index 543341f42c5..b47e35da07b 100644 --- a/deps/icu-small/source/common/unicode/caniter.h +++ b/deps/icu-small/source/common/unicode/caniter.h @@ -153,13 +153,13 @@ private: /** * Copy constructor. Private for now. - * @internal + * @internal (private) */ CanonicalIterator(const CanonicalIterator& other); /** * Assignment operator. Private for now. - * @internal + * @internal (private) */ CanonicalIterator& operator=(const CanonicalIterator& other); diff --git a/deps/icu-small/source/common/unicode/docmain.h b/deps/icu-small/source/common/unicode/docmain.h index 3e645aee4a8..91e5ae3fa2e 100644 --- a/deps/icu-small/source/common/unicode/docmain.h +++ b/deps/icu-small/source/common/unicode/docmain.h @@ -139,7 +139,7 @@ * * * Number Formatting - * unum.h + * unumberformatter.h, unum.h * icu::number::NumberFormatter (ICU 60+) or icu::NumberFormat (older versions) * * diff --git a/deps/icu-small/source/common/unicode/edits.h b/deps/icu-small/source/common/unicode/edits.h index 5a72574c140..f767a8d3b49 100644 --- a/deps/icu-small/source/common/unicode/edits.h +++ b/deps/icu-small/source/common/unicode/edits.h @@ -17,10 +17,57 @@ U_NAMESPACE_BEGIN +class UnicodeString; + /** - * Records lengths of string edits but not replacement text. - * Supports replacements, insertions, deletions in linear progression. - * Does not support moving/reordering of text. + * Records lengths of string edits but not replacement text. Supports replacements, insertions, deletions + * 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, + * 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. + * + * After all edits have been added, instances of this class should be considered immutable, and an + * {@link Edits::Iterator} can be used for queries. + * + * There are four flavors of Edits::Iterator: + * + *
    + *
  • {@link #getFineIterator()} retains full granularity of change edits. + *
  • {@link #getFineChangesIterator()} retains full granularity of change edits, and when calling + * next() on the iterator, skips over no-change edits (unchanged regions). + *
  • {@link #getCoarseIterator()} treats adjacent change edits as a single edit. (Adjacent no-change + * edits are automatically merged during the construction phase.) + *
  • {@link #getCoarseChangesIterator()} treats adjacent change edits as a single edit, and when + * calling next() on the iterator, skips over no-change edits (unchanged regions). + *
+ * + * For example, consider the string "abcßDeF", which case-folds to "abcssdef". This string has the + * following fine edits: + *
    + *
  • abc ⇨ abc (no-change) + *
  • ß ⇨ ss (change) + *
  • D ⇨ d (change) + *
  • e ⇨ e (no-change) + *
  • F ⇨ f (change) + *
+ * and the following coarse edits (note how adjacent change edits get merged together): + *
    + *
  • abc ⇨ abc (no-change) + *
  • ßD ⇨ ssd (change) + *
  • e ⇨ e (no-change) + *
  • F ⇨ f (change) + *
+ * + * 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)} + * methods are used to walk through the string. + * + * 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 * (e.g., case mapping functions) merge any such errors into their API's UErrorCode. @@ -91,13 +138,13 @@ public: void reset() U_NOEXCEPT; /** - * Adds a record for an unchanged segment of text. + * Adds a no-change edit: a record for an unchanged segment of text. * Normally called from inside ICU string transformation functions, not user code. * @stable ICU 59 */ void addUnchanged(int32_t unchangedLength); /** - * Adds a record for a text replacement/insertion/deletion. + * Adds a change edit: a record for a text replacement/insertion/deletion. * Normally called from inside ICU string transformation functions, not user code. * @stable ICU 59 */ @@ -136,6 +183,18 @@ public: /** * Access to the list of edits. + * + * At any moment in time, an instance of this class points to a single edit: a "window" into a span + * of the source string and the corresponding span of the destination string. The source string span + * 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. + * + * For more information, see the documentation for {@link Edits}. + * * @see getCoarseIterator * @see getFineIterator * @stable ICU 59 @@ -162,7 +221,7 @@ public: Iterator &operator=(const Iterator &other) = default; /** - * Advances to the next edit. + * Advances the iterator to the next edit. * @param errorCode ICU error code. Its input value must 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.) @@ -172,9 +231,9 @@ public: UBool next(UErrorCode &errorCode) { return next(onlyChanges_, errorCode); } /** - * Finds the edit that contains the source index. - * The source index may be found in a non-change - * even if normal iteration would skip non-changes. + * Moves the iterator to the edit that contains the source index. + * The source index may be found in a no-change edit + * even if normal iteration would skip no-change edits. * Normal iteration can continue from a found edit. * * The iterator state before this search logically does not matter. @@ -196,9 +255,9 @@ public: #ifndef U_HIDE_DRAFT_API /** - * Finds the edit that contains the destination index. - * The destination index may be found in a non-change - * even if normal iteration would skip non-changes. + * Moves the iterator to the edit that contains the destination index. + * The destination index may be found in a no-change edit + * even if normal iteration would skip no-change edits. * Normal iteration can continue from a found edit. * * The iterator state before this search logically does not matter. @@ -219,7 +278,7 @@ public: } /** - * Returns the destination index corresponding to the given source index. + * Computes the destination index corresponding to the given source index. * If the source index is inside a change edit (not at its start), * then the destination index at the end of that edit is returned, * since there is no information about index mapping inside a change edit. @@ -243,7 +302,7 @@ public: int32_t destinationIndexFromSourceIndex(int32_t i, UErrorCode &errorCode); /** - * Returns the source index corresponding to the given destination index. + * Computes the source index corresponding to the given destination index. * If the destination index is inside a change edit (not at its start), * then the source index at the end of that edit is returned, * since there is no information about index mapping inside a change edit. @@ -268,17 +327,27 @@ public: #endif // U_HIDE_DRAFT_API /** + * Returns whether the edit currently represented by the iterator is a change edit. + * * @return TRUE if this edit replaces oldLength() units with newLength() different ones. * FALSE if oldLength units remain unchanged. * @stable ICU 59 */ UBool hasChange() const { return changed; } + /** + * The length of the current span in the source string, which starts at {@link #sourceIndex}. + * * @return the number of units in the original string which are replaced or remain unchanged. * @stable ICU 59 */ int32_t oldLength() const { return oldLength_; } + /** + * The length of the current span in the destination string, which starts at + * {@link #destinationIndex}, or in the replacement string, which starts at + * {@link #replacementIndex}. + * * @return the number of units in the modified string, if hasChange() is TRUE. * Same as oldLength if hasChange() is FALSE. * @stable ICU 59 @@ -286,22 +355,52 @@ public: int32_t newLength() const { return newLength_; } /** + * The start index of the current span in the source string; the span has length + * {@link #oldLength}. + * * @return the current index into the source string * @stable ICU 59 */ int32_t sourceIndex() const { return srcIndex; } + /** + * 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 + * 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. + * * @return the current index into the replacement-characters-only string, * not counting unchanged spans * @stable ICU 59 */ - int32_t replacementIndex() const { return replIndex; } + int32_t replacementIndex() const { + // TODO: Throw an exception if we aren't in a change edit? + return replIndex; + } + /** + * The start index of the current span in the destination string; the span has length + * {@link #newLength}. + * * @return the current index into the full destination string * @stable ICU 59 */ int32_t destinationIndex() const { return destIndex; } +#ifndef U_HIDE_INTERNAL_API + /** + * A string representation of the current edit represented by the iterator for debugging. You + * should not depend on the contents of the return string. + * @internal + */ + UnicodeString& toString(UnicodeString& appendTo) const; +#endif // U_HIDE_INTERNAL_API + private: friend class Edits; @@ -330,8 +429,10 @@ public: }; /** - * Returns an Iterator for coarse-grained changes for simple string updates. - * Skips non-changes. + * Returns an Iterator for coarse-grained change edits + * (adjacent change edits are treated as one). + * Can be used to perform simple string updates. + * Skips no-change edits. * @return an Iterator that merges adjacent changes. * @stable ICU 59 */ @@ -340,7 +441,10 @@ public: } /** - * Returns an Iterator for coarse-grained changes and non-changes for simple string updates. + * Returns an Iterator for coarse-grained change and no-change edits + * (adjacent change edits are treated as one). + * Can be used to perform simple string updates. + * Adjacent change edits are treated as one edit. * @return an Iterator that merges adjacent changes. * @stable ICU 59 */ @@ -349,8 +453,10 @@ public: } /** - * Returns an Iterator for fine-grained changes for modifying styled text. - * Skips non-changes. + * Returns an Iterator for fine-grained change edits + * (full granularity of change edits is retained). + * Can be used for modifying styled text. + * Skips no-change edits. * @return an Iterator that separates adjacent changes. * @stable ICU 59 */ @@ -359,7 +465,9 @@ public: } /** - * Returns an Iterator for fine-grained changes and non-changes for modifying styled text. + * Returns an Iterator for fine-grained change and no-change edits + * (full granularity of change edits is retained). + * Can be used for modifying styled text. * @return an Iterator that separates adjacent changes. * @stable ICU 59 */ diff --git a/deps/icu-small/source/common/unicode/platform.h b/deps/icu-small/source/common/unicode/platform.h index a3f8d32f89d..d9636580c30 100644 --- a/deps/icu-small/source/common/unicode/platform.h +++ b/deps/icu-small/source/common/unicode/platform.h @@ -196,20 +196,6 @@ # define U_PLATFORM U_PF_UNKNOWN #endif -/** - * \def UPRV_INCOMPLETE_CPP11_SUPPORT - * This switch turns off ICU 60 NumberFormatter code. - * By default, this switch is enabled on AIX and z/OS, - * which have poor C++11 support. - * - * NOTE: This switch is intended to be temporary; see #13393. - * - * @internal - */ -#ifndef UPRV_INCOMPLETE_CPP11_SUPPORT -# define UPRV_INCOMPLETE_CPP11_SUPPORT (U_PLATFORM == U_PF_AIX || U_PLATFORM == U_PF_OS390 || U_PLATFORM == U_PF_SOLARIS ) -#endif - /** * \def CYGWINMSVC * Defined if this is Windows with Cygwin, but using MSVC rather than gcc. diff --git a/deps/icu-small/source/common/unicode/rbbi.h b/deps/icu-small/source/common/unicode/rbbi.h index 0c41d69d235..e9b82cd5207 100644 --- a/deps/icu-small/source/common/unicode/rbbi.h +++ b/deps/icu-small/source/common/unicode/rbbi.h @@ -55,7 +55,7 @@ class U_COMMON_API RuleBasedBreakIterator /*U_FINAL*/ : public BreakIterator { private: /** * The UText through which this BreakIterator accesses the text - * @internal + * @internal (private) */ UText fText; @@ -70,13 +70,6 @@ public: RBBIDataWrapper *fData; private: - /** - * The iteration state - current position, rule status for the current position, - * and whether the iterator ran off the end, yielding UBRK_DONE. - * Current position is pinned to be 0 < position <= text.length. - * Current position is always set to a boundary. - * @internal - */ /** * The current position of the iterator. Pinned, 0 < fPosition <= text.length. * Never has the value UBRK_DONE (-1). @@ -628,25 +621,26 @@ private: /** * Dumps caches and performs other actions associated with a complete change * in text or iteration position. - * @internal + * @internal (private) */ void reset(void); /** * Common initialization function, used by constructors and bufferClone. - * @internal + * @internal (private) */ void init(UErrorCode &status); /** - * Iterate backwards from an arbitrary position in the input text using the Safe Reverse rules. + * Iterate backwards from an arbitrary position in the input text using the + * synthesized Safe Reverse rules. * This locates a "Safe Position" from which the forward break rules * will operate correctly. A Safe Position is not necessarily a boundary itself. * * @param fromPosition the position in the input text to begin the iteration. - * @internal + * @internal (private) */ - int32_t handlePrevious(int32_t fromPosition); + int32_t handleSafePrevious(int32_t fromPosition); /** * Find a rule-based boundary by running the state machine. @@ -658,7 +652,7 @@ private: * If > 0, the segment will be further subdivided * fRuleStatusIndex Info from the state table indicating which rules caused the boundary. * - * @internal + * @internal (private) */ int32_t handleNext(); @@ -667,7 +661,7 @@ private: * This function returns the appropriate LanguageBreakEngine for a * given character c. * @param c A character in the dictionary set - * @internal + * @internal (private) */ const LanguageBreakEngine *getLanguageBreakEngine(UChar32 c); diff --git a/deps/icu-small/source/common/unicode/uchar.h b/deps/icu-small/source/common/unicode/uchar.h index 4b72ecfc26b..6d31083e66e 100644 --- a/deps/icu-small/source/common/unicode/uchar.h +++ b/deps/icu-small/source/common/unicode/uchar.h @@ -42,7 +42,7 @@ U_CDECL_BEGIN * @see u_getUnicodeVersion * @stable ICU 2.0 */ -#define U_UNICODE_VERSION "10.0" +#define U_UNICODE_VERSION "11.0" /** * \file @@ -446,6 +446,13 @@ typedef enum UProperty { * @stable ICU 60 */ UCHAR_PREPENDED_CONCATENATION_MARK=63, + /** + * Binary property Extended_Pictographic. + * See http://www.unicode.org/reports/tr51/#Emoji_Properties + * + * @stable ICU 62 + */ + UCHAR_EXTENDED_PICTOGRAPHIC=64, #ifndef U_HIDE_DEPRECATED_API /** * One more than the last constant for binary Unicode properties. @@ -1683,6 +1690,31 @@ enum UBlockCode { /** @stable ICU 60 */ UBLOCK_ZANABAZAR_SQUARE = 280, /*[11A00]*/ + // New blocks in Unicode 11.0 + + /** @stable ICU 62 */ + UBLOCK_CHESS_SYMBOLS = 281, /*[1FA00]*/ + /** @stable ICU 62 */ + UBLOCK_DOGRA = 282, /*[11800]*/ + /** @stable ICU 62 */ + UBLOCK_GEORGIAN_EXTENDED = 283, /*[1C90]*/ + /** @stable ICU 62 */ + UBLOCK_GUNJALA_GONDI = 284, /*[11D60]*/ + /** @stable ICU 62 */ + UBLOCK_HANIFI_ROHINGYA = 285, /*[10D00]*/ + /** @stable ICU 62 */ + UBLOCK_INDIC_SIYAQ_NUMBERS = 286, /*[1EC70]*/ + /** @stable ICU 62 */ + UBLOCK_MAKASAR = 287, /*[11EE0]*/ + /** @stable ICU 62 */ + UBLOCK_MAYAN_NUMERALS = 288, /*[1D2E0]*/ + /** @stable ICU 62 */ + UBLOCK_MEDEFAIDRIN = 289, /*[16E40]*/ + /** @stable ICU 62 */ + UBLOCK_OLD_SOGDIAN = 290, /*[10F00]*/ + /** @stable ICU 62 */ + UBLOCK_SOGDIAN = 291, /*[10F30]*/ + #ifndef U_HIDE_DEPRECATED_API /** * One more than the highest normal UBlockCode value. @@ -1690,7 +1722,7 @@ enum UBlockCode { * * @deprecated ICU 58 The numeric value may change over time, see ICU ticket #12420. */ - UBLOCK_COUNT = 281, + UBLOCK_COUNT = 292, #endif // U_HIDE_DEPRECATED_API /** @stable ICU 2.0 */ @@ -1979,6 +2011,9 @@ typedef enum UJoiningGroup { U_JG_MALAYALAM_SSA, /**< @stable ICU 60 */ U_JG_MALAYALAM_TTA, /**< @stable ICU 60 */ + U_JG_HANIFI_ROHINGYA_KINNA_YA, /**< @stable ICU 62 */ + U_JG_HANIFI_ROHINGYA_PA, /**< @stable ICU 62 */ + #ifndef U_HIDE_DEPRECATED_API /** * One more than the highest normal UJoiningGroup value. @@ -2029,6 +2064,7 @@ typedef enum UGraphemeClusterBreak { U_GCB_GLUE_AFTER_ZWJ = 16, /*[GAZ]*/ /** @stable ICU 58 */ U_GCB_ZWJ = 17, /*[ZWJ]*/ + #ifndef U_HIDE_DEPRECATED_API /** * One more than the highest normal UGraphemeClusterBreak value. @@ -2090,6 +2126,9 @@ typedef enum UWordBreakValues { U_WB_GLUE_AFTER_ZWJ = 20, /*[GAZ]*/ /** @stable ICU 58 */ U_WB_ZWJ = 21, /*[ZWJ]*/ + /** @stable ICU 62 */ + U_WB_WSEGSPACE = 22, /*[WSEGSPACE]*/ + #ifndef U_HIDE_DEPRECATED_API /** * One more than the highest normal UWordBreakValues value. @@ -2097,7 +2136,7 @@ typedef enum UWordBreakValues { * * @deprecated ICU 58 The numeric value may change over time, see ICU ticket #12420. */ - U_WB_COUNT = 22 + U_WB_COUNT = 23 #endif // U_HIDE_DEPRECATED_API } UWordBreakValues; diff --git a/deps/icu-small/source/common/unicode/unistr.h b/deps/icu-small/source/common/unicode/unistr.h index d0b271754b6..b84f40bd449 100644 --- a/deps/icu-small/source/common/unicode/unistr.h +++ b/deps/icu-small/source/common/unicode/unistr.h @@ -1892,7 +1892,7 @@ public: UnicodeString &fastCopyFrom(const UnicodeString &src); /** - * Move assignment operator, might leave src in bogus state. + * Move assignment operator; might leave src in bogus state. * This string will have the same contents and state that the source string had. * The behavior is undefined if *this and src are the same object. * @param src source string @@ -1905,7 +1905,7 @@ public: // do not use #ifndef U_HIDE_DRAFT_API for moveFrom, needed by non-draft API /** - * Move assignment, might leave src in bogus state. + * Move assignment; might leave src in bogus state. * This string will have the same contents and state that the source string had. * The behavior is undefined if *this and src are the same object. * @@ -3314,7 +3314,7 @@ public: UnicodeString(const UnicodeString& that); /** - * Move constructor, might leave src in bogus state. + * Move constructor; might leave src in bogus state. * This string will have the same contents and state that the source string had. * @param src source string * @stable ICU 56 diff --git a/deps/icu-small/source/common/unicode/urename.h b/deps/icu-small/source/common/unicode/urename.h index d8ab85091f5..4175e527f40 100644 --- a/deps/icu-small/source/common/unicode/urename.h +++ b/deps/icu-small/source/common/unicode/urename.h @@ -613,6 +613,7 @@ #define ucnv_createConverterFromPackage U_ICU_ENTRY_POINT_RENAME(ucnv_createConverterFromPackage) #define ucnv_createConverterFromSharedData U_ICU_ENTRY_POINT_RENAME(ucnv_createConverterFromSharedData) #define ucnv_detectUnicodeSignature U_ICU_ENTRY_POINT_RENAME(ucnv_detectUnicodeSignature) +#define ucnv_enableCleanup U_ICU_ENTRY_POINT_RENAME(ucnv_enableCleanup) #define ucnv_extContinueMatchFromU U_ICU_ENTRY_POINT_RENAME(ucnv_extContinueMatchFromU) #define ucnv_extContinueMatchToU U_ICU_ENTRY_POINT_RENAME(ucnv_extContinueMatchToU) #define ucnv_extGetUnicodeSet U_ICU_ENTRY_POINT_RENAME(ucnv_extGetUnicodeSet) @@ -1170,6 +1171,16 @@ #define unum_setSymbol U_ICU_ENTRY_POINT_RENAME(unum_setSymbol) #define unum_setTextAttribute U_ICU_ENTRY_POINT_RENAME(unum_setTextAttribute) #define unum_toPattern U_ICU_ENTRY_POINT_RENAME(unum_toPattern) +#define unumf_close U_ICU_ENTRY_POINT_RENAME(unumf_close) +#define unumf_closeResult U_ICU_ENTRY_POINT_RENAME(unumf_closeResult) +#define unumf_formatDecimal U_ICU_ENTRY_POINT_RENAME(unumf_formatDecimal) +#define unumf_formatDouble U_ICU_ENTRY_POINT_RENAME(unumf_formatDouble) +#define unumf_formatInt U_ICU_ENTRY_POINT_RENAME(unumf_formatInt) +#define unumf_openForSkeletonAndLocale U_ICU_ENTRY_POINT_RENAME(unumf_openForSkeletonAndLocale) +#define unumf_openResult U_ICU_ENTRY_POINT_RENAME(unumf_openResult) +#define unumf_resultGetAllFieldPositions U_ICU_ENTRY_POINT_RENAME(unumf_resultGetAllFieldPositions) +#define unumf_resultNextFieldPosition U_ICU_ENTRY_POINT_RENAME(unumf_resultNextFieldPosition) +#define unumf_resultToString U_ICU_ENTRY_POINT_RENAME(unumf_resultToString) #define unumsys_close U_ICU_ENTRY_POINT_RENAME(unumsys_close) #define unumsys_getDescription U_ICU_ENTRY_POINT_RENAME(unumsys_getDescription) #define unumsys_getName U_ICU_ENTRY_POINT_RENAME(unumsys_getName) @@ -1209,6 +1220,7 @@ #define uplug_setPlugNoUnload U_ICU_ENTRY_POINT_RENAME(uplug_setPlugNoUnload) #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) #define uprv_aestrncpy U_ICU_ENTRY_POINT_RENAME(uprv_aestrncpy) #define uprv_asciiFromEbcdic U_ICU_ENTRY_POINT_RENAME(uprv_asciiFromEbcdic) #define uprv_asciitolower U_ICU_ENTRY_POINT_RENAME(uprv_asciitolower) @@ -1343,6 +1355,7 @@ #define uprv_maximumPtr U_ICU_ENTRY_POINT_RENAME(uprv_maximumPtr) #define uprv_min U_ICU_ENTRY_POINT_RENAME(uprv_min) #define uprv_modf U_ICU_ENTRY_POINT_RENAME(uprv_modf) +#define uprv_mul32_overflow U_ICU_ENTRY_POINT_RENAME(uprv_mul32_overflow) #define uprv_parseCurrency U_ICU_ENTRY_POINT_RENAME(uprv_parseCurrency) #define uprv_pathIsAbsolute U_ICU_ENTRY_POINT_RENAME(uprv_pathIsAbsolute) #define uprv_pow U_ICU_ENTRY_POINT_RENAME(uprv_pow) diff --git a/deps/icu-small/source/common/unicode/uscript.h b/deps/icu-small/source/common/unicode/uscript.h index 0befa1cd422..faf9edf8ae2 100644 --- a/deps/icu-small/source/common/unicode/uscript.h +++ b/deps/icu-small/source/common/unicode/uscript.h @@ -451,6 +451,21 @@ typedef enum UScriptCode { /** @stable ICU 60 */ USCRIPT_ZANABAZAR_SQUARE = 177,/* Zanb */ + /** @stable ICU 62 */ + USCRIPT_DOGRA = 178,/* Dogr */ + /** @stable ICU 62 */ + USCRIPT_GUNJALA_GONDI = 179,/* Gong */ + /** @stable ICU 62 */ + USCRIPT_MAKASAR = 180,/* Maka */ + /** @stable ICU 62 */ + USCRIPT_MEDEFAIDRIN = 181,/* Medf */ + /** @stable ICU 62 */ + USCRIPT_HANIFI_ROHINGYA = 182,/* Rohg */ + /** @stable ICU 62 */ + USCRIPT_SOGDIAN = 183,/* Sogd */ + /** @stable ICU 62 */ + USCRIPT_OLD_SOGDIAN = 184,/* Sogo */ + #ifndef U_HIDE_DEPRECATED_API /** * One more than the highest normal UScriptCode value. @@ -458,7 +473,7 @@ typedef enum UScriptCode { * * @deprecated ICU 58 The numeric value may change over time, see ICU ticket #12420. */ - USCRIPT_CODE_LIMIT = 178 + USCRIPT_CODE_LIMIT = 185 #endif // U_HIDE_DEPRECATED_API } UScriptCode; diff --git a/deps/icu-small/source/common/unicode/utypes.h b/deps/icu-small/source/common/unicode/utypes.h index b6cf4965112..f43056b6f2f 100644 --- a/deps/icu-small/source/common/unicode/utypes.h +++ b/deps/icu-small/source/common/unicode/utypes.h @@ -542,12 +542,15 @@ typedef enum UErrorCode { #ifndef U_HIDE_DRAFT_API U_NUMBER_ARG_OUTOFBOUNDS_ERROR, /**< The argument to a NumberFormatter helper method was out of bounds; the bounds are usually 0 to 999. @draft ICU 61 */ #endif // U_HIDE_DRAFT_API +#ifndef U_HIDE_DRAFT_API + U_NUMBER_SKELETON_SYNTAX_ERROR, /**< The number skeleton passed to C++ NumberFormatter or C UNumberFormatter was invalid or contained a syntax error. @draft ICU 62 */ +#endif // U_HIDE_DRAFT_API #ifndef U_HIDE_DEPRECATED_API /** * One more than the highest normal formatting API error code. * @deprecated ICU 58 The numeric value may change over time, see ICU ticket #12420. */ - U_FMT_PARSE_ERROR_LIMIT = 0x10113, + U_FMT_PARSE_ERROR_LIMIT = 0x10114, #endif // U_HIDE_DEPRECATED_API /* diff --git a/deps/icu-small/source/common/unicode/uvernum.h b/deps/icu-small/source/common/unicode/uvernum.h index 0427bcb03db..2240661112c 100644 --- a/deps/icu-small/source/common/unicode/uvernum.h +++ b/deps/icu-small/source/common/unicode/uvernum.h @@ -58,7 +58,7 @@ * This value will change in the subsequent releases of ICU * @stable ICU 2.4 */ -#define U_ICU_VERSION_MAJOR_NUM 61 +#define U_ICU_VERSION_MAJOR_NUM 62 /** The current ICU minor version as an integer. * This value will change in the subsequent releases of ICU @@ -84,7 +84,7 @@ * This value will change in the subsequent releases of ICU * @stable ICU 2.6 */ -#define U_ICU_VERSION_SUFFIX _61 +#define U_ICU_VERSION_SUFFIX _62 /** * \def U_DEF2_ICU_ENTRY_POINT_RENAME @@ -119,7 +119,7 @@ * This value will change in the subsequent releases of ICU * @stable ICU 2.4 */ -#define U_ICU_VERSION "61.1" +#define U_ICU_VERSION "62.1" /** * The current ICU library major version number as a string, for library name suffixes. @@ -132,13 +132,13 @@ * * @stable ICU 2.6 */ -#define U_ICU_VERSION_SHORT "61" +#define U_ICU_VERSION_SHORT "62" #ifndef U_HIDE_INTERNAL_API /** Data version in ICU4C. * @internal ICU 4.4 Internal Use Only **/ -#define U_ICU_DATA_VERSION "61.1" +#define U_ICU_DATA_VERSION "62.1" #endif /* U_HIDE_INTERNAL_API */ /*=========================================================================== diff --git a/deps/icu-small/source/common/uprops.cpp b/deps/icu-small/source/common/uprops.cpp index b76896db1b7..21723b32aa7 100644 --- a/deps/icu-small/source/common/uprops.cpp +++ b/deps/icu-small/source/common/uprops.cpp @@ -282,6 +282,7 @@ static const BinaryProperty binProps[UCHAR_BINARY_LIMIT]={ { 2, U_MASK(UPROPS_2_EMOJI_COMPONENT), defaultContains }, { 2, 0, isRegionalIndicator }, { 1, U_MASK(UPROPS_PREPENDED_CONCATENATION_MARK), defaultContains }, + { 2, U_MASK(UPROPS_2_EXTENDED_PICTOGRAPHIC), defaultContains }, }; U_CAPI UBool U_EXPORT2 diff --git a/deps/icu-small/source/common/uprops.h b/deps/icu-small/source/common/uprops.h index 6f67756cd91..2078384c3e4 100644 --- a/deps/icu-small/source/common/uprops.h +++ b/deps/icu-small/source/common/uprops.h @@ -196,8 +196,7 @@ enum { /* * Properties in vector word 2 * Bits - * 31..27 http://www.unicode.org/reports/tr51/#Emoji_Properties - * 26 reserved + * 31..26 http://www.unicode.org/reports/tr51/#Emoji_Properties * 25..20 Line Break * 19..15 Sentence Break * 14..10 Word Break @@ -205,7 +204,8 @@ enum { * 4.. 0 Decomposition Type */ enum { - UPROPS_2_EMOJI_COMPONENT=27, + UPROPS_2_EXTENDED_PICTOGRAPHIC=26, + UPROPS_2_EMOJI_COMPONENT, UPROPS_2_EMOJI, UPROPS_2_EMOJI_PRESENTATION, UPROPS_2_EMOJI_MODIFIER, diff --git a/deps/icu-small/source/common/uscript_props.cpp b/deps/icu-small/source/common/uscript_props.cpp index 7998c52c7f0..bfdb68c7a9c 100644 --- a/deps/icu-small/source/common/uscript_props.cpp +++ b/deps/icu-small/source/common/uscript_props.cpp @@ -71,7 +71,7 @@ const int32_t SCRIPT_PROPS[] = { 0x0EA5 | RECOMMENDED | LB_LETTERS, // Laoo 0x004C | RECOMMENDED | CASED, // Latn 0x0D15 | RECOMMENDED, // Mlym - 0x1826 | LIMITED_USE, // Mong + 0x1826 | EXCLUSION, // Mong 0x1000 | RECOMMENDED | LB_LETTERS, // Mymr 0x168F | EXCLUSION, // Ogam 0x10300 | EXCLUSION, // Ital @@ -222,6 +222,13 @@ const int32_t SCRIPT_PROPS[] = { 0x11D10 | EXCLUSION, // Gonm 0x11A5C | EXCLUSION, // Soyo 0x11A0B | EXCLUSION, // Zanb + 0x1180B | EXCLUSION, // Dogr + 0x11D71 | LIMITED_USE, // Gong + 0x11EE5 | EXCLUSION, // Maka + 0x16E40 | EXCLUSION | CASED, // Medf + 0x10D12 | LIMITED_USE | RTL, // Rohg + 0x10F42 | EXCLUSION | RTL, // Sogd + 0x10F19 | EXCLUSION | RTL, // Sogo // End copy-paste from parsescriptmetadata.py }; diff --git a/deps/icu-small/source/common/ustr_cnv.cpp b/deps/icu-small/source/common/ustr_cnv.cpp index 951864f4a6c..eb37232c25d 100644 --- a/deps/icu-small/source/common/ustr_cnv.cpp +++ b/deps/icu-small/source/common/ustr_cnv.cpp @@ -28,6 +28,7 @@ #include "cmemory.h" #include "umutex.h" #include "ustr_cnv.h" +#include "ucnv_bld.h" /* mutexed access to a shared default converter ----------------------------- */ @@ -68,8 +69,8 @@ u_releaseDefaultConverter(UConverter *converter) if (converter != NULL) { ucnv_reset(converter); } + ucnv_enableCleanup(); umtx_lock(NULL); - if(gDefaultConverter == NULL) { gDefaultConverter = converter; converter = NULL; diff --git a/deps/icu-small/source/common/util.h b/deps/icu-small/source/common/util.h index 7af9a32d8ff..92cdc9ef69a 100644 --- a/deps/icu-small/source/common/util.h +++ b/deps/icu-small/source/common/util.h @@ -46,6 +46,13 @@ class U_COMMON_API ICU_Utility /* not : public UObject because all methods are s int32_t radix = 10, int32_t minDigits = 1); + /** Returns a bogus UnicodeString by value. */ + static inline UnicodeString makeBogusString() { + UnicodeString result; + result.setToBogus(); + return result; + } + /** * Return true if the character is NOT printable ASCII. * diff --git a/deps/icu-small/source/common/utypes.cpp b/deps/icu-small/source/common/utypes.cpp index 5d6a0504ba6..7531e465683 100644 --- a/deps/icu-small/source/common/utypes.cpp +++ b/deps/icu-small/source/common/utypes.cpp @@ -126,7 +126,8 @@ _uFmtErrorName[U_FMT_PARSE_ERROR_LIMIT - U_FMT_PARSE_ERROR_START] = { "U_DEFAULT_KEYWORD_MISSING", "U_DECIMAL_NUMBER_SYNTAX_ERROR", "U_FORMAT_INEXACT_ERROR", - "U_NUMBER_ARG_OUTOFBOUNDS_ERROR" + "U_NUMBER_ARG_OUTOFBOUNDS_ERROR", + "U_NUMBER_SKELETON_SYNTAX_ERROR", }; static const char * const diff --git a/deps/icu-small/source/common/wintz.cpp b/deps/icu-small/source/common/wintz.cpp index c30a5dbc606..3708925b38f 100644 --- a/deps/icu-small/source/common/wintz.cpp +++ b/deps/icu-small/source/common/wintz.cpp @@ -49,7 +49,7 @@ typedef struct /** * Various registry keys and key fragments. */ -static const char CURRENT_ZONE_REGKEY[] = "SYSTEM\\CurrentControlSet\\Control\\TimeZoneInformation\\"; +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"; @@ -121,27 +121,39 @@ static LONG getSTDName(const char *winid, char *regStdName, int32_t length) return result; } -static LONG getTZKeyName(char* tzKeyName, int32_t length) +static LONG getTZKeyName(char* tzKeyName, int32_t tzKeyNamelength) { HKEY hkey; LONG result = FALSE; - DWORD cbData = length; + WCHAR timeZoneKeyNameData[128]; + DWORD timeZoneKeyNameLength = static_cast(sizeof(timeZoneKeyNameData)); - if(ERROR_SUCCESS == RegOpenKeyExA( + if(ERROR_SUCCESS == RegOpenKeyExW( HKEY_LOCAL_MACHINE, CURRENT_ZONE_REGKEY, 0, KEY_QUERY_VALUE, &hkey)) { - result = RegQueryValueExA( + if (ERROR_SUCCESS == RegQueryValueExW( hkey, - "TimeZoneKeyName", + L"TimeZoneKeyName", NULL, NULL, - (LPBYTE)tzKeyName, - &cbData); + (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); } diff --git a/deps/icu-small/source/data/in/icudt61l.dat b/deps/icu-small/source/data/in/icudt62l.dat similarity index 65% rename from deps/icu-small/source/data/in/icudt61l.dat rename to deps/icu-small/source/data/in/icudt62l.dat index e9c24d8d1a78822c99efda00d11bed8a45d9eb24..a6ac7ebb374980af350e400719adeeefdb78fa70 100644 GIT binary patch delta 459320 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

mZ`3(p{c3qQTPX@R;JL%cBT%d&Ze%WC$=7@ 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 delta 443800 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 >3J_OS#J(iMmU*xYy|yb)9&R&-IxWX|S3drN;|V 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 v%<}i;< zY{8(F&lhsPS&+(OZ>@Z~Qp!k~41Yr0 zVUL<`9N4f+@N31jmvUdHe)VHMhyxK_B|Dge~mCigww; z4S|S9F)C4oYSf?}jc9@kD>@$qC`1v8F$QZ^v<SS0AUVooHHgcPJA6IsYc4swx)GL)kN zwWvcgTG57fbf62}=s_R)F^C}yV+3QE#MDX4r!j+BEMO5!SjGxgv4(XV$g%$|0vn3O zrBkk~Q8$!I_hNC2-8jh!OkxVQihQ_O7qvZYu&S(3+8D@G^aBv_M3 zKpjT0j~LzwNI)Xek%>ZdVH^t(mh1~yz#^8gd@|1OWh`O|_BXI^!4XbyzQJs4E#cYN znKEiGM+GV|BX>&0xd+pzJRKRxL>8togChh|aRyqk3`;7sg)icffJ7vr8$IZi$v+h5 zbV~}qHvB`Lgm}rVABtERQpQ^rj>L?|9y*CPhE*Iv&%Ak$mJd%-uRHRw3Ub0AJBL}(2M*)gZj8c@L z2DNBFBihi84h&)l!x+IR=CO?x>|huBIKUyaY&5HrANsb2JsjW!16<$%Klmd6$w-lH zPl+o^D9JE>2voQ>RPZgY(-mBVJy;>KEc%$xZ)ujJ6(?UCs1#q6_x(t$TIA3fa!+w0 zspOrCYAY7TN`8s7EUo0h<4-D?{g;(uQx|jtzhnPn5hq)JEc7?1QJHjZN*7tlfBcwZ zOt7@65+7T*(WTsPFgH9cZWRsm@kVQT$I}E$d78WaoTr7}QVpRU=c;(=(A?&(I~!bSHo`z6%(lxO-yJ$D}U5T&**(# zcuMUvqQt_L0B!^*eTJ`M^*+Np7o*RdZ2v>%v~-{@2YF)?Z>|Lxy_>|t8eJrzYoDd( zy!_Z04!HPb>9aeNK2-G&^#1 zaO4-mpA(-yHSEN0gHhS@ocJ%@82LVvikGDt!Tgbg_GuC2viFxF&r+==tL`N0dAjlh zZ>~+Amk&QLLQl2u23srIj6Kiufs55P=~QY-bCj>Oio{FNR8YrwJsQx681iCKj|S=e zOYu3UCbIh(9l#)V2(ybJCwXHB-&%b2m!jNil?ip!U4LHQ)h1%?Vx3t4#z!%R@$>S= zUx{pa<^{Uc0CNvspv5oH;&n=HILn7$5Kd@a+1ZNz|nis^K7SoiUq5S9zBEWIR z#hcfW{zHwU>Ubx5T)X&zGRDZbtZ5f_34a0yILo)&h3~2On>j%uQQG`UJZaHRzzzb| z{z{w|GnAWkmaqIuxL>uTQY%=)2DY$+J+`oo9qeKc`_iUEeC3=!NiV{9!w0_bbEZk1 zd`k1P4pCs0M&(oFPCLsRe=WWzeO?r&pZ%k|>&t6r>`H z0@()ne5Y{wa@0k-F=7ylIK*QK%UHoG*07EZWV#Ro-RMCtw!wdy@N4mXry|0yP|YgV zP|Wx`!;PDz{I$48)^_nS(U~reLGA?exM-G9jGSbD@Zb?;%{YdZsd{vw8$IYnANmna zl@W+U6Ph6|u{$9aNm#+E9C=BcJ5%Y(;SJTOL9N_*N!;l$K%_woVHi8 zEu>q~1}h?2!v?lUKqexXClVtVmHFM`w$Hnfy};-q5}7p#$w)ye(vXe}w4(!^=)xM- zu_1T5#gpmngy=vgg2)a=2tpBt1~g&?tI$(*1{Se|WfZcoMJPro%2199WZuH2yhXnA zGPgLpFN+^r^bw@r#ViYY!~+j*GO`6bqS(V79`HmEf)R&!q#zY($U-)9kc&LzqY+Kg z@QS!i>=Jg*MSkTKVYuW#wj-S23*S=t@!Vh{T`z_uIt*u@_9aezZ45;hs>C`PGF>=m~tgCvJ! zS+DqZYR$=iVVZtyfY>y+ETCblp` z-Yn)Yj|D7Z2}evf!_}R$sJoO#;VA~Lu;X5lzc-3tE6-cm=9CM#EN>hXKa{IOqM$^r zB4>vw{eEn#0J>iwCGKTc4Pl`}X?z%~@ADi;zQk@F&F&q`N_mhP9-^isc5AplLf1{9 zXMK&bdE7(bD4&h`12*~-95+koluy#l;apDqr|EV0f5^K3xUSOsK=cjO?{OH0A%r0e zV;F`p48t%C!&pO%F^n;k7(yIMEg^&uLI@#*5JCtc1Qsr^k)EHu2>Wf&yHP&@qhV0vYz3!&>?jLW?=bZCA&*wSM`SJaA_R#A~BCor`n1ky&rxd{KHdr?5zw(@eAR{eiTUze|jo% zDd@FeZ^mjk@o(H>ddU`Celh$9@&DXKnZwqOaFkJwF~)JmnP5ewyDx^HJMEuly;eOP zc_Emz_=HB!pY{|c_1{K*&sR{7|J%q<+!i@-Ci2191?z7T<7bLuGsC|<6WJcgdC8W) z6h8B#NZMmPSuPvw4U2yi`EGQ&3=!-Cp7p3)uWUnR__MQ)oI%YVdMSK-I+DKriYBl6#@Wb6e!V?&HQaqBviX(iJ8H%& zlt3a$B(sqeQc0sy<*KakADmN>{Fm*Cm%}H|`LEDB;$>F2OYUFzUo=XoqMCXd=%ABs z_R_~a)=l`oHqxo0hh7Fb&NvfHa)KHgc+GTv;;q=}>w+6Bu+BHqMqY?MuD|2TOk{@t za4u5vj;z0NY@0vu1^-KDdc)Qi{a=w!ca1AJ!6fNqkVzKVG~4JFT4|%54m#;(w+$|# zls(+%0S{@)R-YDHX=9D3S6rKjys{cSy+Lq<*>L;$NLTc*Hc!Yq^-}nw^O1+^`^@); zXa34nyiAkjFNZ(>t4MCjs(6hk&8;KC21XP=niYOvCi3xccqa1POIJIs9CI{GdIrPb zzfxhwBgaqWsrLVMep+Vvh~L=q(-D5Mtkk`anwaN0H`pi50Gl+Q&H*ww$RLMEv;n(m zrHzZk_(_#mY8Yqtt44@Q8tCLA(Ye~>AZK&K5BzncC)h9FftMZ3e;uhynj3!A7w7!S zbgYbV*}ju|Hu6+`ruPCw z>E-Z8v#tsg7b1DZ)1%Wa0gN-jBqx~SBui?XGd<4?vs~gb7r4Szt}!1r{=3NYT`R(S z+~>igSQ8C8+Qg#N{|3;spsLl0-5a$s~(xE~s>qTda^`St`3Iqnsw1 z8DKw08RZnGxyC$;+-99IioEKvK3R}KCV3Rl!coS!$`KWYm|&6k`qjElCzxSJab&)GFKj5 z5N--?vB+(fUR|AAa2@{tnLcCP1s2G3;mBn>73^g{qa0(2J1mpafjv2|J!bvj!`!@*F)rgbn9J~nQU^{%og(4NoD%{3)^4Y;oiYN}}{>F{2Ey7mXXs3f7df7`K z103KmM;PH4V@xo~6el^wY0hz;SuSvi>)c?0d)$A`aq&R#@U_*sU(5Zqe{Oow^4lzN zhh?IS$T}iyAetCriKChtYN?~11{!IinX{bZJTse<^iXh*`#j(wtDD1D{!?T$xGcW1 zc{RN9pL_}s_qUOR*y)`{e$CB4I;30>dwnrGE_EA- zRMObQZN*|uA9?1zRl;g&sHKhuTIr;l9(vhJA4eDp56nk$!%Opz{{8vy zeB_a52)E{~hMWH`@qnAYZnKlr;y+8cMp_qfjk9hg z9A%ValsOp7-xt2`$B~rCMQzXJg`fKIqdUib>_y;@e;la`hP62I-qmpD4RKl>I$KO$KnH4InsM;ES;U|$#7R;rp@y|>bSXsyz z#~EjWNlq}uNgn-hY!Rn89mX#BQkMq(Z={K4T4<$0k!#Fzof|B0lYZ;>F~EKfaF9U~ zw>geUW+N%2GR_2(oM4KR+g#jp-tW+4Gu`yi%Rz|-DbQ#kyC`CXyR>Q`R=E+b@_@bD zoz)+35|K>~xol<&cUb1QHyg*9$PYj8(@64fv}y0ETR;sRl~|=miC*^7M?d>W(91-UNM<8VjB<>5t`l!dHc?C; zJN3GNLUvI^@dsAtx;OvYKNl|CjC{5$O`=VtlR+j~Wb;tx+DzN&pp$Om9wnuo1{yia zHR5!jkZR6wmaRIljqT*KgB9+6VD;f)fBa3iB3}-F zd@GXl`4nkVNn;b~WROV~*)-EaD{ZvXK__DzXPgOcu)s|ovPyz(Cx(^(CGy>1ui3u$ zuZFk(i~9vq7bCBJXws5fEV4$F!t02zoi^I(ppzkn8R00)tb_xLk#|P++u8#k2>*OB zlKi&PaL%Hx+ge=W4$G`?mwVi2gWA!=5K9utY$SzL(#Rl_EV9``9$VQ)KI!C;%Vu_O zU)?%gDk!6z3TmjQmIfMWqL~(2>1SU!_z#h^U30(YIQwU&cUZTR0(MbE345rdiaNUK zp_fsPg;BSC{C??n*1+ zJqnkWA|HMG4J8-2$t{M%?4NlLw?r7NUd-#^@BA#1wthr>H0=CYH{lEq!_g?E1zdFip}4{DXzF#AsATiNHeGQ%tvxJa+kd+DQ} zee9R@z>e^5?|1|Jgz8ft41aki@>E#$3tz>O^N*1?Q`(ejr-M$q>7hl<)*azr|6?RO za!}2|4~GB!QGC+6Q?G}wEJqq2JEzQfX2S91$lt`D5}xJ^=TtfW!SK63k0j?F@Hxss z2028D&s0j;LmA~%P)S086Qdyf+n?+3tadK!2!HwWNc;LY?ZtG$n^8AbaTG+<``#Hct206qotrt-ouB}A=K7L%I6HHRAm71O5&;B3VxJA*t4~5U( z^-^V7yb^A`8+kTzS+Of03_o?(e`GEE!l!IMy&E~0QlLQLqqZrcnBAoN+c38inx2FCyuB}2x&rhR0JvkJnm{8MD>`qSbw;p9KLrDEZq zB5!s@nIGg3hdII!!zAfhG7U7+#0WQDRzXrHytbxXcw6xy=%JlI&)jQ(Wf;SrYAIfXfnH z;VPNxWRXn{xorN;)v)71R&bxXCS6xXV56 z^MHq}vQ94^jyir!qlqDwIO0hrg-v9UO%AziW(PYdps>&}vP)1#ITch=MGdvoQBMPn zB(jkrin+}y8FoP?z3iorepXpyyMwZxn^b;8+Z_8yl@n5Mo_SWd%RSbJDze4wU?;~Y zk*t|fPII0)=2>8gJFF4);V}5`zBf2q2Xe?|4`q~dkUijBu3WOmKoJPI88`oMVPrE^v`cT;VF$xWyuOxyOAT zkf_s19}b^fb(P&N&JQzJ9bt9CdbUwPB~?^YLoG)bVwe%;xWr|yaFuJ!6Ke;?5l;e% zBvC*iyJ(}Gj$NxyPIn3p)1Y$Whr^$&`fC28;?XenE&o_qwH8V6Z&wx^;2cqp3Uh_4 z++mp*M?@xB?52u3>S^Wx2N`6X>m)j2k|>~vQp%~Ohmwz4_R%h*E%8OxNfcoN(T|dn z&klCdNE6Mp(8>W0GRPrLahfw+V}*2`$z~fx6tjmidc(@K$g@GRVjFk4O07lS{meam z$*~}p&1@l$tqNQ+WZ}Y^FMj)f|Ezzb+qxcl*-Ib&>|=oa9Ak{*j5EO`Cz#^CoF`4s zGZSY2GV)B<5#bQSjBu1u&T@`D`dsH2_+8foGZm$^dZV>(SfJ80_i=a6J$ zOfbm|vs~al89IlW`;>?Eg%GvM(g&`b-hv~iW4 z#=hWV;V+|t#8+FzZJgi|m)X4A_%X^|?$Pju@un#({`KIspj(=rkGc!_*MkqQ-(#jM zocs0Qoyn(#XE@6_&XXu*QgQgpUk{Skw~IT%ly!lhR1(f}of|Chpv+OA$}AVS$Q+lr zO!*HSPNwO~W{^o1+2nB5x|^oCY-S66^s|ov_H*FT33yAe$ZZmAb|PEF2N~oLhgl-Y zx@0y|!2oAC%XRLPWtcjdJ-w z`uZRvZ2E(BsqXb&w=QiuT86#LrQQimMpnW6KyosdlKu{&t_9lO%;b%(T% zJACQ=_-fbOuf50H1ivzUPAASY!z>rL!2&nA#Ui&^;tmg3<{_)B5vB9%h!9I0@g$H) z5}O{~_LnZmAe$U=$zvK*w4W(f0}4! zFZ&qa04;{Qm1M)bk%J6!h{F^c_T7|F${scv`V>-0V~$H)<_cH2#yorNp63$mn?cDA zahM^7Im#3#!-B_xXV>2p-U{m<3zEZ}=wMUy^fe3a^B|mjEO^iQHvROg9*+gjMf$#FIcGN%YarJ_gv&0e0Gs0t(qh5efR6ND|4+a)FEV+KxDz z5ziDS$#l3~{T=^F@ObcIkfPDl68}N*c#svwJrQi$Fg>APlW({+^YP%hNS^guOZ@y$ zkg|S8JR3fIJjf1nVuJrOxMhA(-CHrirbl((%wDkMCIh;)p936ZkV72i2t~S9TpIrH z2@f4>;;7#a|KW)sE%H#^)spbZ*x=1@I5zll_%CCF4dL6L3^oRv6iY8%4YQsMUVr+! znHwx{lUpoO7!Eucd@HyuTv9eJE_mwcU1sj{fQPKoXIT2f?Qy{_za

v@5}UB9ok8 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 N3~sR8nCX7S{(lXxFGc_W diff --git a/deps/icu-small/source/i18n/affixpatternparser.cpp b/deps/icu-small/source/i18n/affixpatternparser.cpp deleted file mode 100644 index d9e122953af..00000000000 --- a/deps/icu-small/source/i18n/affixpatternparser.cpp +++ /dev/null @@ -1,698 +0,0 @@ -// © 2016 and later: Unicode, Inc. and others. -// License & terms of use: http://www.unicode.org/copyright.html -/* - * Copyright (C) 2015, International Business Machines - * Corporation and others. All Rights Reserved. - * - * file name: affixpatternparser.cpp - */ - -#include "unicode/utypes.h" - -#if !UCONFIG_NO_FORMATTING - -#include "unicode/dcfmtsym.h" -#include "unicode/plurrule.h" -#include "unicode/strenum.h" -#include "unicode/ucurr.h" -#include "unicode/ustring.h" -#include "affixpatternparser.h" -#include "charstr.h" -#include "precision.h" -#include "uassert.h" -#include "unistrappender.h" - -static const UChar gDefaultSymbols[] = {0xa4, 0xa4, 0xa4}; - -static const UChar gPercent = 0x25; -static const UChar gPerMill = 0x2030; -static const UChar gNegative = 0x2D; -static const UChar gPositive = 0x2B; - -#define PACK_TOKEN_AND_LENGTH(t, l) ((UChar) (((t) << 8) | (l & 0xFF))) - -#define UNPACK_TOKEN(c) ((AffixPattern::ETokenType) (((c) >> 8) & 0x7F)) - -#define UNPACK_LONG(c) (((c) >> 8) & 0x80) - -#define UNPACK_LENGTH(c) ((c) & 0xFF) - -U_NAMESPACE_BEGIN - -static int32_t -nextToken(const UChar *buffer, int32_t idx, int32_t len, UChar *token) { - if (buffer[idx] != 0x27 || idx + 1 == len) { - *token = buffer[idx]; - return 1; - } - *token = buffer[idx + 1]; - if (buffer[idx + 1] == 0xA4) { - int32_t i = 2; - for (; idx + i < len && i < 4 && buffer[idx + i] == buffer[idx + 1]; ++i) - ; - return i; - } - return 2; -} - -static int32_t -nextUserToken(const UChar *buffer, int32_t idx, int32_t len, UChar *token) { - *token = buffer[idx]; - int32_t max; - switch (buffer[idx]) { - case 0x27: - max = 2; - break; - case 0xA4: - max = 3; - break; - default: - max = 1; - break; - } - int32_t i = 1; - for (; idx + i < len && i < max && buffer[idx + i] == buffer[idx]; ++i) - ; - return i; -} - -CurrencyAffixInfo::CurrencyAffixInfo() - : fSymbol(gDefaultSymbols, 1), - fISO(gDefaultSymbols, 2), - fLong(DigitAffix(gDefaultSymbols, 3)), - fIsDefault(TRUE) { -} - -void -CurrencyAffixInfo::set( - const char *locale, - const PluralRules *rules, - const UChar *currency, - UErrorCode &status) { - if (U_FAILURE(status)) { - return; - } - fIsDefault = FALSE; - if (currency == NULL) { - fSymbol.setTo(gDefaultSymbols, 1); - fISO.setTo(gDefaultSymbols, 2); - fLong.remove(); - fLong.append(gDefaultSymbols, 3); - fIsDefault = TRUE; - return; - } - int32_t len; - UBool unusedIsChoice; - const UChar *symbol = ucurr_getName( - currency, locale, UCURR_SYMBOL_NAME, &unusedIsChoice, - &len, &status); - if (U_FAILURE(status)) { - return; - } - fSymbol.setTo(symbol, len); - fISO.setTo(currency, u_strlen(currency)); - fLong.remove(); - StringEnumeration* keywords = rules->getKeywords(status); - if (U_FAILURE(status)) { - return; - } - const UnicodeString* pluralCount; - while ((pluralCount = keywords->snext(status)) != NULL) { - CharString pCount; - pCount.appendInvariantChars(*pluralCount, status); - const UChar *pluralName = ucurr_getPluralName( - currency, locale, &unusedIsChoice, pCount.data(), - &len, &status); - fLong.setVariant(pCount.data(), UnicodeString(pluralName, len), status); - } - delete keywords; -} - -void -CurrencyAffixInfo::adjustPrecision( - const UChar *currency, const UCurrencyUsage usage, - FixedPrecision &precision, UErrorCode &status) { - if (U_FAILURE(status)) { - return; - } - - int32_t digitCount = ucurr_getDefaultFractionDigitsForUsage( - currency, usage, &status); - precision.fMin.setFracDigitCount(digitCount); - precision.fMax.setFracDigitCount(digitCount); - double increment = ucurr_getRoundingIncrementForUsage( - currency, usage, &status); - if (increment == 0.0) { - precision.fRoundingIncrement.clear(); - } else { - precision.fRoundingIncrement.set(increment); - // guard against round-off error - precision.fRoundingIncrement.round(6); - } -} - -void -AffixPattern::addLiteral( - const UChar *literal, int32_t start, int32_t len) { - char32Count += u_countChar32(literal + start, len); - literals.append(literal, start, len); - int32_t tlen = tokens.length(); - // Takes 4 UChars to encode maximum literal length. - UChar *tokenChars = tokens.getBuffer(tlen + 4); - - // find start of literal size. May be tlen if there is no literal. - // While finding start of literal size, compute literal length - int32_t literalLength = 0; - int32_t tLiteralStart = tlen; - while (tLiteralStart > 0 && UNPACK_TOKEN(tokenChars[tLiteralStart - 1]) == kLiteral) { - tLiteralStart--; - literalLength <<= 8; - literalLength |= UNPACK_LENGTH(tokenChars[tLiteralStart]); - } - // Add number of chars we just added to literal - literalLength += len; - - // Now encode the new length starting at tLiteralStart - tlen = tLiteralStart; - tokenChars[tlen++] = PACK_TOKEN_AND_LENGTH(kLiteral, literalLength & 0xFF); - literalLength >>= 8; - while (literalLength) { - tokenChars[tlen++] = PACK_TOKEN_AND_LENGTH(kLiteral | 0x80, literalLength & 0xFF); - literalLength >>= 8; - } - tokens.releaseBuffer(tlen); -} - -void -AffixPattern::add(ETokenType t) { - add(t, 1); -} - -void -AffixPattern::addCurrency(uint8_t count) { - add(kCurrency, count); -} - -void -AffixPattern::add(ETokenType t, uint8_t count) { - U_ASSERT(t != kLiteral); - char32Count += count; - switch (t) { - case kCurrency: - hasCurrencyToken = TRUE; - break; - case kPercent: - hasPercentToken = TRUE; - break; - case kPerMill: - hasPermillToken = TRUE; - break; - default: - // Do nothing - break; - } - tokens.append(PACK_TOKEN_AND_LENGTH(t, count)); -} - -AffixPattern & -AffixPattern::append(const AffixPattern &other) { - AffixPatternIterator iter; - other.iterator(iter); - UnicodeString literal; - while (iter.nextToken()) { - switch (iter.getTokenType()) { - case kLiteral: - iter.getLiteral(literal); - addLiteral(literal.getBuffer(), 0, literal.length()); - break; - case kCurrency: - addCurrency(static_cast(iter.getTokenLength())); - break; - default: - add(iter.getTokenType()); - break; - } - } - return *this; -} - -void -AffixPattern::remove() { - tokens.remove(); - literals.remove(); - hasCurrencyToken = FALSE; - hasPercentToken = FALSE; - hasPermillToken = FALSE; - char32Count = 0; -} - -// escapes literals for strings where special characters are NOT escaped -// except for apostrophe. -static void escapeApostropheInLiteral( - const UnicodeString &literal, UnicodeStringAppender &appender) { - int32_t len = literal.length(); - const UChar *buffer = literal.getBuffer(); - for (int32_t i = 0; i < len; ++i) { - UChar ch = buffer[i]; - switch (ch) { - case 0x27: - appender.append((UChar) 0x27); - appender.append((UChar) 0x27); - break; - default: - appender.append(ch); - break; - } - } -} - - -// escapes literals for user strings where special characters in literals -// are escaped with apostrophe. -static void escapeLiteral( - const UnicodeString &literal, UnicodeStringAppender &appender) { - int32_t len = literal.length(); - const UChar *buffer = literal.getBuffer(); - for (int32_t i = 0; i < len; ++i) { - UChar ch = buffer[i]; - switch (ch) { - case 0x27: - appender.append((UChar) 0x27); - appender.append((UChar) 0x27); - break; - case 0x25: - appender.append((UChar) 0x27); - appender.append((UChar) 0x25); - appender.append((UChar) 0x27); - break; - case 0x2030: - appender.append((UChar) 0x27); - appender.append((UChar) 0x2030); - appender.append((UChar) 0x27); - break; - case 0xA4: - appender.append((UChar) 0x27); - appender.append((UChar) 0xA4); - appender.append((UChar) 0x27); - break; - case 0x2D: - appender.append((UChar) 0x27); - appender.append((UChar) 0x2D); - appender.append((UChar) 0x27); - break; - case 0x2B: - appender.append((UChar) 0x27); - appender.append((UChar) 0x2B); - appender.append((UChar) 0x27); - break; - default: - appender.append(ch); - break; - } - } -} - -UnicodeString & -AffixPattern::toString(UnicodeString &appendTo) const { - AffixPatternIterator iter; - iterator(iter); - UnicodeStringAppender appender(appendTo); - UnicodeString literal; - while (iter.nextToken()) { - switch (iter.getTokenType()) { - case kLiteral: - escapeApostropheInLiteral(iter.getLiteral(literal), appender); - break; - case kPercent: - appender.append((UChar) 0x27); - appender.append((UChar) 0x25); - break; - case kPerMill: - appender.append((UChar) 0x27); - appender.append((UChar) 0x2030); - break; - case kCurrency: - { - appender.append((UChar) 0x27); - int32_t cl = iter.getTokenLength(); - for (int32_t i = 0; i < cl; ++i) { - appender.append((UChar) 0xA4); - } - } - break; - case kNegative: - appender.append((UChar) 0x27); - appender.append((UChar) 0x2D); - break; - case kPositive: - appender.append((UChar) 0x27); - appender.append((UChar) 0x2B); - break; - default: - U_ASSERT(FALSE); - break; - } - } - return appendTo; -} - -UnicodeString & -AffixPattern::toUserString(UnicodeString &appendTo) const { - AffixPatternIterator iter; - iterator(iter); - UnicodeStringAppender appender(appendTo); - UnicodeString literal; - while (iter.nextToken()) { - switch (iter.getTokenType()) { - case kLiteral: - escapeLiteral(iter.getLiteral(literal), appender); - break; - case kPercent: - appender.append((UChar) 0x25); - break; - case kPerMill: - appender.append((UChar) 0x2030); - break; - case kCurrency: - { - int32_t cl = iter.getTokenLength(); - for (int32_t i = 0; i < cl; ++i) { - appender.append((UChar) 0xA4); - } - } - break; - case kNegative: - appender.append((UChar) 0x2D); - break; - case kPositive: - appender.append((UChar) 0x2B); - break; - default: - U_ASSERT(FALSE); - break; - } - } - return appendTo; -} - -class AffixPatternAppender : public UMemory { -public: - AffixPatternAppender(AffixPattern &dest) : fDest(&dest), fIdx(0) { } - - inline void append(UChar x) { - if (fIdx == UPRV_LENGTHOF(fBuffer)) { - fDest->addLiteral(fBuffer, 0, fIdx); - fIdx = 0; - } - fBuffer[fIdx++] = x; - } - - inline void append(UChar32 x) { - if (fIdx >= UPRV_LENGTHOF(fBuffer) - 1) { - fDest->addLiteral(fBuffer, 0, fIdx); - fIdx = 0; - } - U16_APPEND_UNSAFE(fBuffer, fIdx, x); - } - - inline void flush() { - if (fIdx) { - fDest->addLiteral(fBuffer, 0, fIdx); - } - fIdx = 0; - } - - /** - * flush the buffer when we go out of scope. - */ - ~AffixPatternAppender() { - flush(); - } -private: - AffixPattern *fDest; - int32_t fIdx; - UChar fBuffer[32]; - AffixPatternAppender(const AffixPatternAppender &other); - AffixPatternAppender &operator=(const AffixPatternAppender &other); -}; - - -AffixPattern & -AffixPattern::parseUserAffixString( - const UnicodeString &affixStr, - AffixPattern &appendTo, - UErrorCode &status) { - if (U_FAILURE(status)) { - return appendTo; - } - int32_t len = affixStr.length(); - const UChar *buffer = affixStr.getBuffer(); - // 0 = not quoted; 1 = quoted. - int32_t state = 0; - AffixPatternAppender appender(appendTo); - for (int32_t i = 0; i < len; ) { - UChar token; - int32_t tokenSize = nextUserToken(buffer, i, len, &token); - i += tokenSize; - if (token == 0x27 && tokenSize == 1) { // quote - state = 1 - state; - continue; - } - if (state == 0) { - switch (token) { - case 0x25: - appender.flush(); - appendTo.add(kPercent, 1); - break; - case 0x27: // double quote - appender.append((UChar) 0x27); - break; - case 0x2030: - appender.flush(); - appendTo.add(kPerMill, 1); - break; - case 0x2D: - appender.flush(); - appendTo.add(kNegative, 1); - break; - case 0x2B: - appender.flush(); - appendTo.add(kPositive, 1); - break; - case 0xA4: - appender.flush(); - appendTo.add(kCurrency, static_cast(tokenSize)); - break; - default: - appender.append(token); - break; - } - } else { - switch (token) { - case 0x27: // double quote - appender.append((UChar) 0x27); - break; - case 0xA4: // included b/c tokenSize can be > 1 - for (int32_t j = 0; j < tokenSize; ++j) { - appender.append((UChar) 0xA4); - } - break; - default: - appender.append(token); - break; - } - } - } - return appendTo; -} - -AffixPattern & -AffixPattern::parseAffixString( - const UnicodeString &affixStr, - AffixPattern &appendTo, - UErrorCode &status) { - if (U_FAILURE(status)) { - return appendTo; - } - int32_t len = affixStr.length(); - const UChar *buffer = affixStr.getBuffer(); - for (int32_t i = 0; i < len; ) { - UChar token; - int32_t tokenSize = nextToken(buffer, i, len, &token); - if (tokenSize == 1) { - int32_t literalStart = i; - ++i; - while (i < len && (tokenSize = nextToken(buffer, i, len, &token)) == 1) { - ++i; - } - appendTo.addLiteral(buffer, literalStart, i - literalStart); - - // If we reached end of string, we are done - if (i == len) { - return appendTo; - } - } - i += tokenSize; - switch (token) { - case 0x25: - appendTo.add(kPercent, 1); - break; - case 0x2030: - appendTo.add(kPerMill, 1); - break; - case 0x2D: - appendTo.add(kNegative, 1); - break; - case 0x2B: - appendTo.add(kPositive, 1); - break; - case 0xA4: - { - if (tokenSize - 1 > 3) { - status = U_PARSE_ERROR; - return appendTo; - } - appendTo.add(kCurrency, tokenSize - 1); - } - break; - default: - appendTo.addLiteral(&token, 0, 1); - break; - } - } - return appendTo; -} - -AffixPatternIterator & -AffixPattern::iterator(AffixPatternIterator &result) const { - result.nextLiteralIndex = 0; - result.lastLiteralLength = 0; - result.nextTokenIndex = 0; - result.tokens = &tokens; - result.literals = &literals; - return result; -} - -UBool -AffixPatternIterator::nextToken() { - int32_t tlen = tokens->length(); - if (nextTokenIndex == tlen) { - return FALSE; - } - ++nextTokenIndex; - const UChar *tokenBuffer = tokens->getBuffer(); - if (UNPACK_TOKEN(tokenBuffer[nextTokenIndex - 1]) == - AffixPattern::kLiteral) { - while (nextTokenIndex < tlen && - UNPACK_LONG(tokenBuffer[nextTokenIndex])) { - ++nextTokenIndex; - } - lastLiteralLength = 0; - int32_t i = nextTokenIndex - 1; - for (; UNPACK_LONG(tokenBuffer[i]); --i) { - lastLiteralLength <<= 8; - lastLiteralLength |= UNPACK_LENGTH(tokenBuffer[i]); - } - lastLiteralLength <<= 8; - lastLiteralLength |= UNPACK_LENGTH(tokenBuffer[i]); - nextLiteralIndex += lastLiteralLength; - } - return TRUE; -} - -AffixPattern::ETokenType -AffixPatternIterator::getTokenType() const { - return UNPACK_TOKEN(tokens->charAt(nextTokenIndex - 1)); -} - -UnicodeString & -AffixPatternIterator::getLiteral(UnicodeString &result) const { - const UChar *buffer = literals->getBuffer(); - result.setTo(buffer + (nextLiteralIndex - lastLiteralLength), lastLiteralLength); - return result; -} - -int32_t -AffixPatternIterator::getTokenLength() const { - const UChar *tokenBuffer = tokens->getBuffer(); - AffixPattern::ETokenType type = UNPACK_TOKEN(tokenBuffer[nextTokenIndex - 1]); - return type == AffixPattern::kLiteral ? lastLiteralLength : UNPACK_LENGTH(tokenBuffer[nextTokenIndex - 1]); -} - -AffixPatternParser::AffixPatternParser() - : fPercent(gPercent), fPermill(gPerMill), fNegative(gNegative), fPositive(gPositive) { -} - -AffixPatternParser::AffixPatternParser( - const DecimalFormatSymbols &symbols) { - setDecimalFormatSymbols(symbols); -} - -void -AffixPatternParser::setDecimalFormatSymbols( - const DecimalFormatSymbols &symbols) { - fPercent = symbols.getConstSymbol(DecimalFormatSymbols::kPercentSymbol); - fPermill = symbols.getConstSymbol(DecimalFormatSymbols::kPerMillSymbol); - fNegative = symbols.getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol); - fPositive = symbols.getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol); -} - -PluralAffix & -AffixPatternParser::parse( - const AffixPattern &affixPattern, - const CurrencyAffixInfo ¤cyAffixInfo, - PluralAffix &appendTo, - UErrorCode &status) const { - if (U_FAILURE(status)) { - return appendTo; - } - AffixPatternIterator iter; - affixPattern.iterator(iter); - UnicodeString literal; - while (iter.nextToken()) { - switch (iter.getTokenType()) { - case AffixPattern::kPercent: - appendTo.append(fPercent, UNUM_PERCENT_FIELD); - break; - case AffixPattern::kPerMill: - appendTo.append(fPermill, UNUM_PERMILL_FIELD); - break; - case AffixPattern::kNegative: - appendTo.append(fNegative, UNUM_SIGN_FIELD); - break; - case AffixPattern::kPositive: - appendTo.append(fPositive, UNUM_SIGN_FIELD); - break; - case AffixPattern::kCurrency: - switch (iter.getTokenLength()) { - case 1: - appendTo.append( - currencyAffixInfo.getSymbol(), UNUM_CURRENCY_FIELD); - break; - case 2: - appendTo.append( - currencyAffixInfo.getISO(), UNUM_CURRENCY_FIELD); - break; - case 3: - appendTo.append( - currencyAffixInfo.getLong(), UNUM_CURRENCY_FIELD, status); - break; - default: - U_ASSERT(FALSE); - break; - } - break; - case AffixPattern::kLiteral: - appendTo.append(iter.getLiteral(literal)); - break; - default: - U_ASSERT(FALSE); - break; - } - } - return appendTo; -} - - -U_NAMESPACE_END -#endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/deps/icu-small/source/i18n/affixpatternparser.h b/deps/icu-small/source/i18n/affixpatternparser.h deleted file mode 100644 index b54c749c700..00000000000 --- a/deps/icu-small/source/i18n/affixpatternparser.h +++ /dev/null @@ -1,402 +0,0 @@ -// © 2016 and later: Unicode, Inc. and others. -// License & terms of use: http://www.unicode.org/copyright.html -/* -******************************************************************************* -* Copyright (C) 2015, International Business Machines -* Corporation and others. All Rights Reserved. -******************************************************************************* -* affixpatternparser.h -* -* created on: 2015jan06 -* created by: Travis Keep -*/ - -#ifndef __AFFIX_PATTERN_PARSER_H__ -#define __AFFIX_PATTERN_PARSER_H__ - -#include "unicode/utypes.h" - -#if !UCONFIG_NO_FORMATTING - -#include "unicode/unistr.h" -#include "unicode/uobject.h" -#include "pluralaffix.h" - -U_NAMESPACE_BEGIN - -class PluralRules; -class FixedPrecision; -class DecimalFormatSymbols; - -/** - * A representation of the various forms of a particular currency according - * to some locale and usage context. - * - * Includes the symbol, ISO code form, and long form(s) of the currency name - * for each plural variation. - */ -class U_I18N_API CurrencyAffixInfo : public UMemory { -public: - /** - * Symbol is \u00a4; ISO form is \u00a4\u00a4; - * long form is \u00a4\u00a4\u00a4. - */ - CurrencyAffixInfo(); - - const UnicodeString &getSymbol() const { return fSymbol; } - const UnicodeString &getISO() const { return fISO; } - const PluralAffix &getLong() const { return fLong; } - void setSymbol(const UnicodeString &symbol) { - fSymbol = symbol; - fIsDefault = FALSE; - } - void setISO(const UnicodeString &iso) { - fISO = iso; - fIsDefault = FALSE; - } - UBool - equals(const CurrencyAffixInfo &other) const { - return (fSymbol == other.fSymbol) - && (fISO == other.fISO) - && (fLong.equals(other.fLong)) - && (fIsDefault == other.fIsDefault); - } - - /** - * Intializes this instance. - * - * @param locale the locale for the currency forms. - * @param rules The plural rules for the locale. - * @param currency the null terminated, 3 character ISO code of the - * currency. If NULL, resets this instance as if it were just created. - * In this case, the first 2 parameters may be NULL as well. - * @param status any error returned here. - */ - void set( - const char *locale, const PluralRules *rules, - const UChar *currency, UErrorCode &status); - - /** - * Returns true if this instance is the default. That is has no real - * currency. For instance never initialized with set() - * or reset with set(NULL, NULL, NULL, status). - */ - UBool isDefault() const { return fIsDefault; } - - /** - * Adjusts the precision used for a particular currency. - * @param currency the null terminated, 3 character ISO code of the - * currency. - * @param usage the usage of the currency - * @param precision min/max fraction digits and rounding increment - * adjusted. - * @params status any error reported here. - */ - static void adjustPrecision( - const UChar *currency, const UCurrencyUsage usage, - FixedPrecision &precision, UErrorCode &status); - -private: - /** - * The symbol form of the currency. - */ - UnicodeString fSymbol; - - /** - * The ISO form of the currency, usually three letter abbreviation. - */ - UnicodeString fISO; - - /** - * The long forms of the currency keyed by plural variation. - */ - PluralAffix fLong; - - UBool fIsDefault; - -}; - -class AffixPatternIterator; - -/** - * A locale agnostic representation of an affix pattern. - */ -class U_I18N_API AffixPattern : public UMemory { -public: - - /** - * The token types that can appear in an affix pattern. - */ - enum ETokenType { - kLiteral, - kPercent, - kPerMill, - kCurrency, - kNegative, - kPositive - }; - - /** - * An empty affix pattern. - */ - AffixPattern() - : tokens(), literals(), hasCurrencyToken(FALSE), - hasPercentToken(FALSE), hasPermillToken(FALSE), char32Count(0) { - } - - /** - * Adds a string literal to this affix pattern. - */ - void addLiteral(const UChar *, int32_t start, int32_t len); - - /** - * Adds a token to this affix pattern. t must not be kLiteral as - * the addLiteral() method adds literals. - * @param t the token type to add - */ - void add(ETokenType t); - - /** - * Adds a currency token with specific count to this affix pattern. - * @param count the token count. Used to distinguish between - * one, two, or three currency symbols. Note that adding a currency - * token with count=2 (Use ISO code) is different than adding two - * currency tokens each with count=1 (two currency symbols). - */ - void addCurrency(uint8_t count); - - /** - * Makes this instance be an empty affix pattern. - */ - void remove(); - - /** - * Provides an iterator over the tokens in this instance. - * @param result this is initialized to point just before the - * first token of this instance. Caller must call nextToken() - * on the iterator once it is set up to have it actually point - * to the first token. This first call to nextToken() will return - * FALSE if the AffixPattern being iterated over is empty. - * @return result - */ - AffixPatternIterator &iterator(AffixPatternIterator &result) const; - - /** - * Returns TRUE if this instance has currency tokens in it. - */ - UBool usesCurrency() const { - return hasCurrencyToken; - } - - UBool usesPercent() const { - return hasPercentToken; - } - - UBool usesPermill() const { - return hasPermillToken; - } - - /** - * Returns the number of code points a string of this instance - * would have if none of the special tokens were escaped. - * Used to compute the padding size. - */ - int32_t countChar32() const { - return char32Count; - } - - /** - * Appends other to this instance mutating this instance in place. - * @param other The pattern appended to the end of this one. - * @return a reference to this instance for chaining. - */ - AffixPattern &append(const AffixPattern &other); - - /** - * Converts this AffixPattern back into a user string. - * It is the inverse of parseUserAffixString. - */ - UnicodeString &toUserString(UnicodeString &appendTo) const; - - /** - * Converts this AffixPattern back into a string. - * It is the inverse of parseAffixString. - */ - UnicodeString &toString(UnicodeString &appendTo) const; - - /** - * Parses an affix pattern string appending it to an AffixPattern. - * Parses affix pattern strings produced from using - * DecimalFormatPatternParser to parse a format pattern. Affix patterns - * include the positive prefix and suffix and the negative prefix - * and suffix. This method expects affix patterns strings to be in the - * same format that DecimalFormatPatternParser produces. Namely special - * characters in the affix that correspond to a field type must be - * prefixed with an apostrophe ('). These special character sequences - * inluce minus (-), percent (%), permile (U+2030), plus (+), - * short currency (U+00a4), medium currency (u+00a4 * 2), - * long currency (u+a4 * 3), and apostrophe (') - * (apostrophe does not correspond to a field type but has to be escaped - * because it itself is the escape character). - * Since the expansion of these special character - * sequences is locale dependent, these sequences are not expanded in - * an AffixPattern instance. - * If these special characters are not prefixed with an apostrophe in - * the affix pattern string, then they are treated verbatim just as - * any other character. If an apostrophe prefixes a non special - * character in the affix pattern, the apostrophe is simply ignored. - * - * @param affixStr the string from DecimalFormatPatternParser - * @param appendTo parsed result appended here. - * @param status any error parsing returned here. - */ - static AffixPattern &parseAffixString( - const UnicodeString &affixStr, - AffixPattern &appendTo, - UErrorCode &status); - - /** - * Parses an affix pattern string appending it to an AffixPattern. - * Parses affix pattern strings as the user would supply them. - * In this function, quoting makes special characters like normal - * characters whereas in parseAffixString, quoting makes special - * characters special. - * - * @param affixStr the string from the user - * @param appendTo parsed result appended here. - * @param status any error parsing returned here. - */ - static AffixPattern &parseUserAffixString( - const UnicodeString &affixStr, - AffixPattern &appendTo, - UErrorCode &status); - - UBool equals(const AffixPattern &other) const { - return (tokens == other.tokens) - && (literals == other.literals) - && (hasCurrencyToken == other.hasCurrencyToken) - && (hasPercentToken == other.hasPercentToken) - && (hasPermillToken == other.hasPermillToken) - && (char32Count == other.char32Count); - } - -private: - /* - * Tokens stored here. Each UChar generally stands for one token. A - * Each token is of form 'etttttttllllllll' llllllll is the length of - * the token and ranges from 0-255. ttttttt is the token type and ranges - * from 0-127. If e is set it means this is an extendo token (to be - * described later). To accomodate token lengths above 255, each normal - * token (e=0) can be followed by 0 or more extendo tokens (e=1) with - * the same type. Right now only kLiteral Tokens have extendo tokens. - * Each extendo token provides the next 8 higher bits for the length. - * If a kLiteral token is followed by 2 extendo tokens then, then the - * llllllll of the next extendo token contains bits 8-15 of the length - * and the last extendo token contains bits 16-23 of the length. - */ - UnicodeString tokens; - - /* - * The characters of the kLiteral tokens are concatenated together here. - * The first characters go with the first kLiteral token, the next - * characters go with the next kLiteral token etc. - */ - UnicodeString literals; - UBool hasCurrencyToken; - UBool hasPercentToken; - UBool hasPermillToken; - int32_t char32Count; - void add(ETokenType t, uint8_t count); - -}; - -/** - * An iterator over the tokens in an AffixPattern instance. - */ -class U_I18N_API AffixPatternIterator : public UMemory { -public: - - /** - * Using an iterator without first calling iterator on an AffixPattern - * instance to initialize the iterator results in - * undefined behavior. - */ - AffixPatternIterator() : nextLiteralIndex(0), lastLiteralLength(0), nextTokenIndex(0), tokens(NULL), literals(NULL) { } - /** - * Advances this iterator to the next token. Returns FALSE when there - * are no more tokens. Calling the other methods after nextToken() - * returns FALSE results in undefined behavior. - */ - UBool nextToken(); - - /** - * Returns the type of token. - */ - AffixPattern::ETokenType getTokenType() const; - - /** - * For literal tokens, returns the literal string. Calling this for - * other token types results in undefined behavior. - * @param result replaced with a read-only alias to the literal string. - * @return result - */ - UnicodeString &getLiteral(UnicodeString &result) const; - - /** - * Returns the token length. Usually 1, but for currency tokens may - * be 2 for ISO code and 3 for long form. - */ - int32_t getTokenLength() const; -private: - int32_t nextLiteralIndex; - int32_t lastLiteralLength; - int32_t nextTokenIndex; - const UnicodeString *tokens; - const UnicodeString *literals; - friend class AffixPattern; - AffixPatternIterator(const AffixPatternIterator &); - AffixPatternIterator &operator=(const AffixPatternIterator &); -}; - -/** - * A locale aware class that converts locale independent AffixPattern - * instances into locale dependent PluralAffix instances. - */ -class U_I18N_API AffixPatternParser : public UMemory { -public: -AffixPatternParser(); -AffixPatternParser(const DecimalFormatSymbols &symbols); -void setDecimalFormatSymbols(const DecimalFormatSymbols &symbols); - -/** - * Parses affixPattern appending the result to appendTo. - * @param affixPattern The affix pattern. - * @param currencyAffixInfo contains the currency forms. - * @param appendTo The result of parsing affixPattern is appended here. - * @param status any error returned here. - * @return appendTo. - */ -PluralAffix &parse( - const AffixPattern &affixPattern, - const CurrencyAffixInfo ¤cyAffixInfo, - PluralAffix &appendTo, - UErrorCode &status) const; - -UBool equals(const AffixPatternParser &other) const { - return (fPercent == other.fPercent) - && (fPermill == other.fPermill) - && (fNegative == other.fNegative) - && (fPositive == other.fPositive); -} - -private: -UnicodeString fPercent; -UnicodeString fPermill; -UnicodeString fNegative; -UnicodeString fPositive; -}; - - -U_NAMESPACE_END -#endif /* #if !UCONFIG_NO_FORMATTING */ -#endif // __AFFIX_PATTERN_PARSER_H__ diff --git a/deps/icu-small/source/i18n/collationfcd.cpp b/deps/icu-small/source/i18n/collationfcd.cpp index 19841ee6487..1aff936dee1 100644 --- a/deps/icu-small/source/i18n/collationfcd.cpp +++ b/deps/icu-small/source/i18n/collationfcd.cpp @@ -22,27 +22,27 @@ const uint8_t CollationFCD::lcccIndex[2048]={ 0,0,0,0,0,0,0,0,1,1,2,3,0,0,0,0, 0,0,0,0,4,0,0,0,0,0,0,0,5,6,7,0, 8,0,9,0xa,0,0,0xb,0xc,0xd,0xe,0xf,0,0,0,0,0x10, -0x11,0x12,0x13,0,0,0,0x14,0x15,0,0x16,0x17,0,0,0x16,0x18,0, +0x11,0x12,0x13,0,0,0,0x14,0x15,0,0x16,0x17,0,0,0x16,0x18,0x19, 0,0x16,0x18,0,0,0x16,0x18,0,0,0x16,0x18,0,0,0,0x18,0, -0,0,0x19,0,0,0x16,0x18,0,0,0x1a,0x18,0,0,0,0x1b,0, -0,0x1c,0x1d,0,0,0x1e,0x1d,0,0x1e,0x1f,0,0x20,0x21,0,0x22,0, -0,0x23,0,0,0x18,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0x24,0,0,0,0,0, +0,0,0x1a,0,0,0x16,0x18,0,0,0x1b,0x18,0,0,0,0x1c,0, +0,0x1d,0x1e,0,0,0x1f,0x1e,0,0x1f,0x20,0,0x21,0x22,0,0x23,0, +0,0x24,0,0,0x18,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0x25,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0x25,0x25,0,0,0,0,0x26,0, -0,0,0,0,0,0x27,0,0,0,0x13,0,0,0,0,0,0, -0x28,0,0,0x29,0,0x2a,0,0,0,0x25,0x2b,0x10,0,0x2c,0,0x2d, -0,0x2e,0,0,0,0,0x2f,0x30,0,0,0,0,0,0,1,0x31, +0,0,0,0,0,0,0,0,0x26,0x26,0,0,0,0,0x27,0, +0,0,0,0,0,0x28,0,0,0,0x13,0,0,0,0,0,0, +0x29,0,0,0x2a,0,0x2b,0,0,0,0x26,0x2c,0x2d,0,0x2e,0,0x2f, +0,0x30,0,0,0,0,0x31,0x32,0,0,0,0,0,0,1,0x33, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0x32,0x33,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0x34,0x35,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0x34,0,0,0,0x35,0,0,0,1, +0,0,0,0,0,0,0,0x36,0,0,0,0x37,0,0,0,1, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0x36,0,0,0x37,0,0,0,0,0,0,0,0,0,0,0, +0,0x38,0,0,0x39,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, @@ -101,9 +101,9 @@ const uint8_t CollationFCD::lcccIndex[2048]={ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0x38,0x39,0,0,0x3a,0,0,0,0,0,0,0,0, -0x22,0,0,0,0,0,0x2b,0x3b,0,0x3c,0x3d,0,0,0x3d,0x3e,0, -0,0,0,0,0,0x3f,0x40,0x41,0,0,0,0,0,0,0,0x18, +0,0,0,0x3a,0x3b,0,0,0x3c,0,0,0,0,0,0,0,0, +0x23,0,0,0,0,0,0x2c,0x3d,0,0x3e,0x3f,0,0,0x3f,0x40,0, +0,0,0,0,0,0x41,0x42,0x43,0,0,0,0,0,0,0,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, @@ -126,7 +126,7 @@ const uint8_t CollationFCD::lcccIndex[2048]={ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0x42,0x43,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0x44,0x45,0,0,0,0,0,0,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,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, @@ -143,17 +143,17 @@ const uint8_t CollationFCD::lcccIndex[2048]={ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0x44,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0x19,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 }; -const uint32_t CollationFCD::lcccBits[69]={ +const uint32_t CollationFCD::lcccBits[70]={ 0,0xffffffff,0xffff7fff,0xffff,0xf8,0xfffe0000,0xbfffffff,0xb6,0x7ff0000,0xfffff800,0x10000,0x9fc00000,0x3d9f,0x20000,0xffff0000,0x7ff, -0xff800,0xfbc00000,0x3eef,0xe000000,0xfff00000,0xfffffffb,0x10000000,0x1e2000,0x2000,0x602000,0x18000000,0x400,0x7000000,0xf00,0x3000000,0x2a00000, -0x3c3e0000,0xdf,0x40,0x6800000,0xe0000000,0x100000,0x20040000,0x200,0x1800000,0x9fe00001,0x3fff0000,0x10,0xc00,0xc0040,0x800000,0xfff70000, -0x31021fd,0xfbffffff,0x1fff0000,0x1ffe2,0x38000,0x80000000,0xfc00,0x6000000,0x3ff08000,0xc0000000,0x30000,0x3ffff,0x3800,0x80000,1,0xc19d0000, -2,0x400000,0x40000f5,0x5108000,0x40000000 +0x200ff800,0xfbc00000,0x3eef,0xe000000,0xfff80000,0xfffffffb,0x10000000,0x1e2000,0x2000,0x40000000,0x602000,0x18000000,0x400,0x7000000,0xf00,0x3000000, +0x2a00000,0x3c3e0000,0xdf,0x40,0x6800000,0xe0000000,0x100000,0x20040000,0x200,0x1800000,0x9fe00001,0x3fff0000,0x10,0xff800,0xc00,0xc0040, +0x800000,0xfff70000,0x31021fd,0xfbffffff,0x1fff0000,0x1ffe2,0x38000,0x80000000,0xfc00,0x6000000,0x3ff08000,0xc0000000,0x30000,0x3ffff,0x3800,0x80000, +1,0xc19d0000,2,0x400000,0x40000fd,0x5108000 }; const uint8_t CollationFCD::tcccIndex[2048]={ @@ -161,27 +161,27 @@ const uint8_t CollationFCD::tcccIndex[2048]={ 0xb,0xc,0,0,0,0,0,0,1,1,0xd,0xe,0xf,0x10,0x11,0, 0x12,0x13,0x14,0x15,0x16,0,0x17,0x18,0,0,0,0,0x19,0x1a,0x1b,0, 0x1c,0x1d,0x1e,0x1f,0,0,0x20,0x21,0x22,0x23,0x24,0,0,0,0,0x25, -0x26,0x27,0x28,0,0,0,0x29,0x2a,0,0x2b,0x2c,0,0,0x2d,0x2e,0, -0,0x2f,0x30,0,0,0x2d,0x31,0,0,0x2d,0x32,0,0,0,0x31,0, -0,0,0x33,0,0,0x2d,0x31,0,0,0x34,0x31,0,0,0,0x35,0, -0,0x36,0x37,0,0,0x38,0x37,0,0x38,0x39,0,0x3a,0x3b,0,0x3c,0, -0,0x3d,0,0,0x31,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0x3e,0,0,0,0,0, +0x26,0x27,0x28,0,0,0,0x29,0x2a,0,0x2b,0x2c,0,0,0x2d,0x2e,0x2f, +0,0x30,0x31,0,0,0x2d,0x32,0,0,0x2d,0x33,0,0,0,0x32,0, +0,0,0x34,0,0,0x2d,0x32,0,0,0x35,0x32,0,0,0,0x36,0, +0,0x37,0x38,0,0,0x39,0x38,0,0x39,0x3a,0,0x3b,0x3c,0,0x3d,0, +0,0x3e,0,0,0x32,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0x3f,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0x3f,0x3f,0,0,0,0,0x40,0, -0,0,0,0,0,0x41,0,0,0,0x28,0,0,0,0,0,0, -0x42,0,0,0x43,0,0x44,0,0,0,0x3f,0x45,0x25,0,0x46,0,0x47, -0,0x48,0,0,0,0,0x49,0x4a,0,0,0,0,0,0,1,0x4b, -1,1,1,1,0x4c,1,1,0x4d,0x4e,1,0x4f,0x50,1,0x51,0x52,0x53, -0,0,0,0,0,0,0x54,0x55,0,0x56,0,0,0x57,0x58,0x59,0, -0x5a,0x5b,0x5c,0x5d,0x5e,0x5f,0,0x60,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0x40,0x40,0,0,0,0,0x41,0, +0,0,0,0,0,0x42,0,0,0,0x28,0,0,0,0,0,0, +0x43,0,0,0x44,0,0x45,0,0,0,0x40,0x46,0x47,0,0x48,0,0x49, +0,0x4a,0,0,0,0,0x4b,0x4c,0,0,0,0,0,0,1,0x4d, +1,1,1,1,0x4e,1,1,0x4f,0x50,1,0x51,0x52,1,0x53,0x54,0x55, +0,0,0,0,0,0,0x56,0x57,0,0x58,0,0,0x59,0x5a,0x5b,0, +0x5c,0x5d,0x5e,0x5f,0x60,0x61,0,0x62,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0x2d,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0x61,0,0,0,0x62,0,0,0,1, +0,0,0,0,0,0,0,0x63,0,0,0,0x64,0,0,0,1, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0x63,0x64,0x65,0x66,0x64,0x65,0x67,0,0,0,0,0,0,0,0, +0,0x65,0x66,0x67,0x68,0x66,0x67,0x69,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, @@ -240,9 +240,9 @@ const uint8_t CollationFCD::tcccIndex[2048]={ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0x68,0x69,0,0,0x6a,0,0,0,0,0,0,0,0, -0x3c,0,0,0,0,0,0x45,0x6b,0,0x6c,0x6d,0,0,0x6d,0x6e,0, -0,0,0,0,0,0x6f,0x70,0x71,0,0,0,0,0,0,0,0x31, +0,0,0,0x6a,0x6b,0,0,0x6c,0,0,0,0,0,0,0,0, +0x3d,0,0,0,0,0,0x46,0x6d,0,0x6e,0x6f,0,0,0x6f,0x70,0, +0,0,0,0,0,0x71,0x72,0x73,0,0,0,0,0,0,0,0x32, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, @@ -265,7 +265,7 @@ const uint8_t CollationFCD::tcccIndex[2048]={ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0x72,0x73,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0x74,0x75,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, @@ -282,20 +282,20 @@ const uint8_t CollationFCD::tcccIndex[2048]={ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0x3e,0x74,0x75,0,0,0,0,0, +0,0,0,0,0,0,0,0,0x3f,0x76,0x77,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0xe,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }; -const uint32_t CollationFCD::tcccBits[118]={ +const uint32_t CollationFCD::tcccBits[120]={ 0,0xffffffff,0x3e7effbf,0xbe7effbf,0xfffcffff,0x7ef1ff3f,0xfff3f1f8,0x7fffff3f,0x18003,0xdfffe000,0xff31ffcf,0xcfffffff,0xfffc0,0xffff7fff,0xffff,0x1d760, 0x1fc00,0x187c00,0x200708b,0x2000000,0x708b0000,0xc00000,0xf8,0xfccf0006,0x33ffcfc,0xfffe0000,0xbfffffff,0xb6,0x7ff0000,0x7c,0xfffff800,0x10000, -0x9fc80005,0x3d9f,0x20000,0xffff0000,0x7ff,0xff800,0xfbc00000,0x3eef,0xe000000,0xfff00000,0xfffffffb,0x10120200,0xff1e2000,0x10000000,0xb0002000,0x10480000, -0x4e002000,0x2000,0x30002000,0x602100,0x18000000,0x24000400,0x7000000,0xf00,0x3000000,0x2a00000,0x3d7e0000,0xdf,0x40,0x6800000,0xe0000000,0x100000, -0x20040000,0x200,0x1800000,0x9fe00001,0x3fff0000,0x10,0xc00,0xc0040,0x800000,0xfff70000,0x31021fd,0xfbffffff,0xbffffff,0x3ffffff,0x3f3fffff,0xaaff3f3f, -0x3fffffff,0x1fdfffff,0xefcfffde,0x1fdc7fff,0x1fff0000,0x1ffe2,0x800,0xc000000,0x4000,0xe000,0x1210,0x50,0x292,0x333e005,0x333,0xf000, -0x3c0f,0x38000,0x80000000,0xfc00,0x55555000,0x36db02a5,0x46100000,0x47900000,0x3ff08000,0xc0000000,0x30000,0x3ffff,0x3800,0x80000,1,0xc19d0000, -2,0x400000,0x40000f5,0x5108000,0x5f7ffc00,0x7fdb +0x9fc80005,0x3d9f,0x20000,0xffff0000,0x7ff,0x200ff800,0xfbc00000,0x3eef,0xe000000,0xfff80000,0xfffffffb,0x10120200,0xff1e2000,0x10000000,0xb0002000,0x40000000, +0x10480000,0x4e002000,0x2000,0x30002000,0x602100,0x18000000,0x24000400,0x7000000,0xf00,0x3000000,0x2a00000,0x3d7e0000,0xdf,0x40,0x6800000,0xe0000000, +0x100000,0x20040000,0x200,0x1800000,0x9fe00001,0x3fff0000,0x10,0xff800,0xc00,0xc0040,0x800000,0xfff70000,0x31021fd,0xfbffffff,0xbffffff,0x3ffffff, +0x3f3fffff,0xaaff3f3f,0x3fffffff,0x1fdfffff,0xefcfffde,0x1fdc7fff,0x1fff0000,0x1ffe2,0x800,0xc000000,0x4000,0xe000,0x1210,0x50,0x292,0x333e005, +0x333,0xf000,0x3c0f,0x38000,0x80000000,0xfc00,0x55555000,0x36db02a5,0x46100000,0x47900000,0x3ff08000,0xc0000000,0x30000,0x3ffff,0x3800,0x80000, +1,0xc19d0000,2,0x400000,0x40000fd,0x5108000,0x5f7ffc00,0x7fdb }; U_NAMESPACE_END diff --git a/deps/icu-small/source/i18n/compactdecimalformat.cpp b/deps/icu-small/source/i18n/compactdecimalformat.cpp index b2aacc45cda..4dd2241b23d 100644 --- a/deps/icu-small/source/i18n/compactdecimalformat.cpp +++ b/deps/icu-small/source/i18n/compactdecimalformat.cpp @@ -1,1013 +1,75 @@ -// © 2016 and later: Unicode, Inc. and others. +// © 2018 and later: Unicode, Inc. and others. // License & terms of use: http://www.unicode.org/copyright.html -/* -******************************************************************************* -* Copyright (C) 1997-2015, International Business Machines Corporation and * -* others. All Rights Reserved. * -******************************************************************************* -* -* File COMPACTDECIMALFORMAT.CPP -* -******************************************************************************** -*/ + #include "unicode/utypes.h" #if !UCONFIG_NO_FORMATTING -#include "charstr.h" -#include "cstring.h" -#include "digitlst.h" -#include "mutex.h" +// Allow implicit conversion from char16_t* to UnicodeString for this file: +// Helpful in toString methods and elsewhere. +#define UNISTR_FROM_STRING_EXPLICIT + #include "unicode/compactdecimalformat.h" -#include "unicode/numsys.h" -#include "unicode/plurrule.h" -#include "unicode/ures.h" -#include "ucln_in.h" -#include "uhash.h" -#include "umutex.h" -#include "unicode/ures.h" -#include "uresimp.h" +#include "number_mapper.h" +#include "number_decimfmtprops.h" -// Maps locale name to CDFLocaleData struct. -static UHashtable* gCompactDecimalData = NULL; -static UMutex gCompactDecimalMetaLock = U_MUTEX_INITIALIZER; +using namespace icu; -U_NAMESPACE_BEGIN - -static const int32_t MAX_DIGITS = 15; -static const char gOther[] = "other"; -static const char gLatnTag[] = "latn"; -static const char gNumberElementsTag[] = "NumberElements"; -static const char gDecimalFormatTag[] = "decimalFormat"; -static const char gPatternsShort[] = "patternsShort"; -static const char gPatternsLong[] = "patternsLong"; -static const char gLatnPath[] = "NumberElements/latn"; - -static const UChar u_0 = 0x30; -static const UChar u_apos = 0x27; - -static const UChar kZero[] = {u_0}; - -// Used to unescape single quotes. -enum QuoteState { - OUTSIDE, - INSIDE_EMPTY, - INSIDE_FULL -}; - -enum FallbackFlags { - ANY = 0, - MUST = 1, - NOT_ROOT = 2 - // Next one will be 4 then 6 etc. -}; - - -// CDFUnit represents a prefix-suffix pair for a particular variant -// and log10 value. -struct CDFUnit : public UMemory { - UnicodeString prefix; - UnicodeString suffix; - inline CDFUnit() : prefix(), suffix() { - prefix.setToBogus(); - } - inline ~CDFUnit() {} - inline UBool isSet() const { - return !prefix.isBogus(); - } - inline void markAsSet() { - prefix.remove(); - } -}; - -// CDFLocaleStyleData contains formatting data for a particular locale -// and style. -class CDFLocaleStyleData : public UMemory { - public: - // What to divide by for each log10 value when formatting. These values - // will be powers of 10. For English, would be: - // 1, 1, 1, 1000, 1000, 1000, 1000000, 1000000, 1000000, 1000000000 ... - double divisors[MAX_DIGITS]; - // Maps plural variants to CDFUnit[MAX_DIGITS] arrays. - // To format a number x, - // first compute log10(x). Compute displayNum = (x / divisors[log10(x)]). - // Compute the plural variant for displayNum - // (e.g zero, one, two, few, many, other). - // Compute cdfUnits = unitsByVariant[pluralVariant]. - // Prefix and suffix to use at cdfUnits[log10(x)] - UHashtable* unitsByVariant; - // A flag for whether or not this CDFLocaleStyleData was loaded from the - // Latin numbering system as a fallback from the locale numbering system. - // This value is meaningless if the object is bogus or empty. - UBool fromFallback; - inline CDFLocaleStyleData() : unitsByVariant(NULL), fromFallback(FALSE) { - uprv_memset(divisors, 0, sizeof(divisors)); - } - ~CDFLocaleStyleData(); - // Init initializes this object. - void Init(UErrorCode& status); - inline UBool isBogus() const { - return unitsByVariant == NULL; - } - void setToBogus(); - UBool isEmpty() { - return unitsByVariant == NULL || unitsByVariant->count == 0; - } - private: - CDFLocaleStyleData(const CDFLocaleStyleData&); - CDFLocaleStyleData& operator=(const CDFLocaleStyleData&); -}; - -// CDFLocaleData contains formatting data for a particular locale. -struct CDFLocaleData : public UMemory { - CDFLocaleStyleData shortData; - CDFLocaleStyleData longData; - inline CDFLocaleData() : shortData(), longData() { } - inline ~CDFLocaleData() { } - // Init initializes this object. - void Init(UErrorCode& status); -}; - -U_NAMESPACE_END - -U_CDECL_BEGIN - -static UBool U_CALLCONV cdf_cleanup(void) { - if (gCompactDecimalData != NULL) { - uhash_close(gCompactDecimalData); - gCompactDecimalData = NULL; - } - return TRUE; -} - -static void U_CALLCONV deleteCDFUnits(void* ptr) { - delete [] (icu::CDFUnit*) ptr; -} - -static void U_CALLCONV deleteCDFLocaleData(void* ptr) { - delete (icu::CDFLocaleData*) ptr; -} - -U_CDECL_END - -U_NAMESPACE_BEGIN - -static UBool divisors_equal(const double* lhs, const double* rhs); -static const CDFLocaleStyleData* getCDFLocaleStyleData(const Locale& inLocale, UNumberCompactStyle style, UErrorCode& status); - -static const CDFLocaleStyleData* extractDataByStyleEnum(const CDFLocaleData& data, UNumberCompactStyle style, UErrorCode& status); -static CDFLocaleData* loadCDFLocaleData(const Locale& inLocale, UErrorCode& status); -static void load(const Locale& inLocale, CDFLocaleData* result, UErrorCode& status); -static int32_t populatePrefixSuffix(const char* variant, int32_t log10Value, const UnicodeString& formatStr, UHashtable* result, UBool overwrite, UErrorCode& status); -static double calculateDivisor(double power10, int32_t numZeros); -static UBool onlySpaces(UnicodeString u); -static void fixQuotes(UnicodeString& s); -static void checkForOtherVariants(CDFLocaleStyleData* result, UErrorCode& status); -static void fillInMissing(CDFLocaleStyleData* result); -static int32_t computeLog10(double x, UBool inRange); -static CDFUnit* createCDFUnit(const char* variant, int32_t log10Value, UHashtable* table, UErrorCode& status); -static const CDFUnit* getCDFUnitFallback(const UHashtable* table, const UnicodeString& variant, int32_t log10Value); UOBJECT_DEFINE_RTTI_IMPLEMENTATION(CompactDecimalFormat) -CompactDecimalFormat::CompactDecimalFormat( - const DecimalFormat& decimalFormat, - const UHashtable* unitsByVariant, - const double* divisors, - PluralRules* pluralRules) - : DecimalFormat(decimalFormat), _unitsByVariant(unitsByVariant), _divisors(divisors), _pluralRules(pluralRules) { + +CompactDecimalFormat* +CompactDecimalFormat::createInstance(const Locale& inLocale, UNumberCompactStyle style, + UErrorCode& status) { + return new CompactDecimalFormat(inLocale, style, status); } -CompactDecimalFormat::CompactDecimalFormat(const CompactDecimalFormat& source) - : DecimalFormat(source), _unitsByVariant(source._unitsByVariant), _divisors(source._divisors), _pluralRules(source._pluralRules->clone()) { +CompactDecimalFormat::CompactDecimalFormat(const Locale& inLocale, UNumberCompactStyle style, + UErrorCode& status) + : DecimalFormat(new DecimalFormatSymbols(inLocale, status), status) { + if (U_FAILURE(status)) return; + // Minimal properties: let the non-shim code path do most of the logic for us. + fields->properties->compactStyle = style; + fields->properties->groupingSize = -2; // do not forward grouping information + fields->properties->minimumGroupingDigits = 2; + touch(status); } -CompactDecimalFormat* U_EXPORT2 -CompactDecimalFormat::createInstance( - const Locale& inLocale, UNumberCompactStyle style, UErrorCode& status) { - LocalPointer decfmt((DecimalFormat*) NumberFormat::makeInstance(inLocale, UNUM_DECIMAL, TRUE, status)); - if (U_FAILURE(status)) { - return NULL; - } - LocalPointer pluralRules(PluralRules::forLocale(inLocale, status)); - if (U_FAILURE(status)) { - return NULL; - } - const CDFLocaleStyleData* data = getCDFLocaleStyleData(inLocale, style, status); - if (U_FAILURE(status)) { - return NULL; - } - CompactDecimalFormat* result = - new CompactDecimalFormat(*decfmt, data->unitsByVariant, data->divisors, pluralRules.getAlias()); - if (result == NULL) { - status = U_MEMORY_ALLOCATION_ERROR; - return NULL; - } - pluralRules.orphan(); - result->setMaximumSignificantDigits(3); - result->setSignificantDigitsUsed(TRUE); - result->setGroupingUsed(FALSE); - return result; -} +CompactDecimalFormat::CompactDecimalFormat(const CompactDecimalFormat& source) = default; -CompactDecimalFormat& -CompactDecimalFormat::operator=(const CompactDecimalFormat& rhs) { - if (this != &rhs) { +CompactDecimalFormat::~CompactDecimalFormat() = default; + +CompactDecimalFormat& CompactDecimalFormat::operator=(const CompactDecimalFormat& rhs) { DecimalFormat::operator=(rhs); - _unitsByVariant = rhs._unitsByVariant; - _divisors = rhs._divisors; - delete _pluralRules; - _pluralRules = rhs._pluralRules->clone(); - } - return *this; + return *this; } -CompactDecimalFormat::~CompactDecimalFormat() { - delete _pluralRules; -} - - -Format* -CompactDecimalFormat::clone(void) const { - return new CompactDecimalFormat(*this); -} - -UBool -CompactDecimalFormat::operator==(const Format& that) const { - if (this == &that) { - return TRUE; - } - return (DecimalFormat::operator==(that) && eqHelper((const CompactDecimalFormat&) that)); -} - -UBool -CompactDecimalFormat::eqHelper(const CompactDecimalFormat& that) const { - return uhash_equals(_unitsByVariant, that._unitsByVariant) && divisors_equal(_divisors, that._divisors) && (*_pluralRules == *that._pluralRules); -} - -UnicodeString& -CompactDecimalFormat::format( - double number, - UnicodeString& appendTo, - FieldPosition& pos) const { - UErrorCode status = U_ZERO_ERROR; - return format(number, appendTo, pos, status); -} - -UnicodeString& -CompactDecimalFormat::format( - double number, - UnicodeString& appendTo, - FieldPosition& pos, - UErrorCode &status) const { - if (U_FAILURE(status)) { - return appendTo; - } - DigitList orig, rounded; - orig.set(number); - UBool isNegative; - _round(orig, rounded, isNegative, status); - if (U_FAILURE(status)) { - return appendTo; - } - double roundedDouble = rounded.getDouble(); - if (isNegative) { - roundedDouble = -roundedDouble; - } - int32_t baseIdx = computeLog10(roundedDouble, TRUE); - double numberToFormat = roundedDouble / _divisors[baseIdx]; - UnicodeString variant = _pluralRules->select(numberToFormat); - if (isNegative) { - numberToFormat = -numberToFormat; - } - const CDFUnit* unit = getCDFUnitFallback(_unitsByVariant, variant, baseIdx); - appendTo += unit->prefix; - DecimalFormat::format(numberToFormat, appendTo, pos); - appendTo += unit->suffix; - return appendTo; -} - -UnicodeString& -CompactDecimalFormat::format( - double /* number */, - UnicodeString& appendTo, - FieldPositionIterator* /* posIter */, - UErrorCode& status) const { - status = U_UNSUPPORTED_ERROR; - return appendTo; -} - -UnicodeString& -CompactDecimalFormat::format( - int32_t number, - UnicodeString& appendTo, - FieldPosition& pos) const { - return format((double) number, appendTo, pos); -} - -UnicodeString& -CompactDecimalFormat::format( - int32_t number, - UnicodeString& appendTo, - FieldPosition& pos, - UErrorCode &status) const { - return format((double) number, appendTo, pos, status); -} - -UnicodeString& -CompactDecimalFormat::format( - int32_t /* number */, - UnicodeString& appendTo, - FieldPositionIterator* /* posIter */, - UErrorCode& status) const { - status = U_UNSUPPORTED_ERROR; - return appendTo; -} - -UnicodeString& -CompactDecimalFormat::format( - int64_t number, - UnicodeString& appendTo, - FieldPosition& pos) const { - return format((double) number, appendTo, pos); -} - -UnicodeString& -CompactDecimalFormat::format( - int64_t number, - UnicodeString& appendTo, - FieldPosition& pos, - UErrorCode &status) const { - return format((double) number, appendTo, pos, status); -} - -UnicodeString& -CompactDecimalFormat::format( - int64_t /* number */, - UnicodeString& appendTo, - FieldPositionIterator* /* posIter */, - UErrorCode& status) const { - status = U_UNSUPPORTED_ERROR; - return appendTo; -} - -UnicodeString& -CompactDecimalFormat::format( - StringPiece /* number */, - UnicodeString& appendTo, - FieldPositionIterator* /* posIter */, - UErrorCode& status) const { - status = U_UNSUPPORTED_ERROR; - return appendTo; -} - -UnicodeString& -CompactDecimalFormat::format( - const DigitList& /* number */, - UnicodeString& appendTo, - FieldPositionIterator* /* posIter */, - UErrorCode& status) const { - status = U_UNSUPPORTED_ERROR; - return appendTo; -} - -UnicodeString& -CompactDecimalFormat::format(const DigitList& /* number */, - UnicodeString& appendTo, - FieldPosition& /* pos */, - UErrorCode& status) const { - status = U_UNSUPPORTED_ERROR; - return appendTo; +Format* CompactDecimalFormat::clone() const { + return new CompactDecimalFormat(*this); } void CompactDecimalFormat::parse( - const UnicodeString& /* text */, - Formattable& /* result */, - ParsePosition& /* parsePosition */) const { + const UnicodeString& /* text */, + Formattable& /* result */, + ParsePosition& /* parsePosition */) const { } void CompactDecimalFormat::parse( - const UnicodeString& /* text */, - Formattable& /* result */, - UErrorCode& status) const { - status = U_UNSUPPORTED_ERROR; + const UnicodeString& /* text */, + Formattable& /* result */, + UErrorCode& status) const { + status = U_UNSUPPORTED_ERROR; } CurrencyAmount* CompactDecimalFormat::parseCurrency( - const UnicodeString& /* text */, - ParsePosition& /* pos */) const { - return NULL; + const UnicodeString& /* text */, + ParsePosition& /* pos */) const { + return nullptr; } -void CDFLocaleStyleData::Init(UErrorCode& status) { - if (unitsByVariant != NULL) { - return; - } - unitsByVariant = uhash_open(uhash_hashChars, uhash_compareChars, NULL, &status); - if (U_FAILURE(status)) { - return; - } - uhash_setKeyDeleter(unitsByVariant, uprv_free); - uhash_setValueDeleter(unitsByVariant, deleteCDFUnits); -} -CDFLocaleStyleData::~CDFLocaleStyleData() { - setToBogus(); -} - -void CDFLocaleStyleData::setToBogus() { - if (unitsByVariant != NULL) { - uhash_close(unitsByVariant); - unitsByVariant = NULL; - } -} - -void CDFLocaleData::Init(UErrorCode& status) { - shortData.Init(status); - if (U_FAILURE(status)) { - return; - } - longData.Init(status); -} - -// Helper method for operator= -static UBool divisors_equal(const double* lhs, const double* rhs) { - for (int32_t i = 0; i < MAX_DIGITS; ++i) { - if (lhs[i] != rhs[i]) { - return FALSE; - } - } - return TRUE; -} - -// getCDFLocaleStyleData returns pointer to formatting data for given locale and -// style within the global cache. On cache miss, getCDFLocaleStyleData loads -// the data from CLDR into the global cache before returning the pointer. If a -// UNUM_LONG data is requested for a locale, and that locale does not have -// UNUM_LONG data, getCDFLocaleStyleData will fall back to UNUM_SHORT data for -// that locale. -static const CDFLocaleStyleData* getCDFLocaleStyleData(const Locale& inLocale, UNumberCompactStyle style, UErrorCode& status) { - if (U_FAILURE(status)) { - return NULL; - } - CDFLocaleData* result = NULL; - const char* key = inLocale.getName(); - { - Mutex lock(&gCompactDecimalMetaLock); - if (gCompactDecimalData == NULL) { - gCompactDecimalData = uhash_open(uhash_hashChars, uhash_compareChars, NULL, &status); - if (U_FAILURE(status)) { - return NULL; - } - uhash_setKeyDeleter(gCompactDecimalData, uprv_free); - uhash_setValueDeleter(gCompactDecimalData, deleteCDFLocaleData); - ucln_i18n_registerCleanup(UCLN_I18N_CDFINFO, cdf_cleanup); - } else { - result = (CDFLocaleData*) uhash_get(gCompactDecimalData, key); - } - } - if (result != NULL) { - return extractDataByStyleEnum(*result, style, status); - } - - result = loadCDFLocaleData(inLocale, status); - if (U_FAILURE(status)) { - return NULL; - } - - { - Mutex lock(&gCompactDecimalMetaLock); - CDFLocaleData* temp = (CDFLocaleData*) uhash_get(gCompactDecimalData, key); - if (temp != NULL) { - delete result; - result = temp; - } else { - uhash_put(gCompactDecimalData, uprv_strdup(key), (void*) result, &status); - if (U_FAILURE(status)) { - return NULL; - } - } - } - return extractDataByStyleEnum(*result, style, status); -} - -static const CDFLocaleStyleData* extractDataByStyleEnum(const CDFLocaleData& data, UNumberCompactStyle style, UErrorCode& status) { - switch (style) { - case UNUM_SHORT: - return &data.shortData; - case UNUM_LONG: - if (!data.longData.isBogus()) { - return &data.longData; - } - return &data.shortData; - default: - status = U_ILLEGAL_ARGUMENT_ERROR; - return NULL; - } -} - -// loadCDFLocaleData loads formatting data from CLDR for a given locale. The -// caller owns the returned pointer. -static CDFLocaleData* loadCDFLocaleData(const Locale& inLocale, UErrorCode& status) { - if (U_FAILURE(status)) { - return NULL; - } - CDFLocaleData* result = new CDFLocaleData; - if (result == NULL) { - status = U_MEMORY_ALLOCATION_ERROR; - return NULL; - } - result->Init(status); - if (U_FAILURE(status)) { - delete result; - return NULL; - } - - load(inLocale, result, status); - - if (U_FAILURE(status)) { - delete result; - return NULL; - } - return result; -} - -namespace { - -struct CmptDecDataSink : public ResourceSink { - - CDFLocaleData& dataBundle; // Where to save values when they are read - UBool isLatin; // Whether or not we are traversing the Latin tree - UBool isFallback; // Whether or not we are traversing the Latin tree as fallback - - enum EPatternsTableKey { PATTERNS_SHORT, PATTERNS_LONG }; - enum EFormatsTableKey { DECIMAL_FORMAT, CURRENCY_FORMAT }; - - /* - * NumberElements{ <-- top (numbering system table) - * latn{ <-- patternsTable (one per numbering system) - * patternsLong{ <-- formatsTable (one per pattern) - * decimalFormat{ <-- powersOfTenTable (one per format) - * 1000{ <-- pluralVariantsTable (one per power of ten) - * one{"0 thousand"} <-- plural variant and template - */ - - CmptDecDataSink(CDFLocaleData& _dataBundle) - : dataBundle(_dataBundle), isLatin(FALSE), isFallback(FALSE) {} - virtual ~CmptDecDataSink(); - - virtual void put(const char *key, ResourceValue &value, UBool isRoot, UErrorCode &errorCode) { - // SPECIAL CASE: Don't consume root in the non-Latin numbering system - if (isRoot && !isLatin) { return; } - - ResourceTable patternsTable = value.getTable(errorCode); - if (U_FAILURE(errorCode)) { return; } - for (int i1 = 0; patternsTable.getKeyAndValue(i1, key, value); ++i1) { - - // Check for patternsShort or patternsLong - EPatternsTableKey patternsTableKey; - if (uprv_strcmp(key, gPatternsShort) == 0) { - patternsTableKey = PATTERNS_SHORT; - } else if (uprv_strcmp(key, gPatternsLong) == 0) { - patternsTableKey = PATTERNS_LONG; - } else { - continue; - } - - // Traverse into the formats table - ResourceTable formatsTable = value.getTable(errorCode); - if (U_FAILURE(errorCode)) { return; } - for (int i2 = 0; formatsTable.getKeyAndValue(i2, key, value); ++i2) { - - // Check for decimalFormat or currencyFormat - EFormatsTableKey formatsTableKey; - if (uprv_strcmp(key, gDecimalFormatTag) == 0) { - formatsTableKey = DECIMAL_FORMAT; - // TODO: Enable this statement when currency support is added - // } else if (uprv_strcmp(key, gCurrencyFormat) == 0) { - // formatsTableKey = CURRENCY_FORMAT; - } else { - continue; - } - - // Set the current style and destination based on the two keys - UNumberCompactStyle style; - CDFLocaleStyleData* destination = NULL; - if (patternsTableKey == PATTERNS_LONG - && formatsTableKey == DECIMAL_FORMAT) { - style = UNUM_LONG; - destination = &dataBundle.longData; - } else if (patternsTableKey == PATTERNS_SHORT - && formatsTableKey == DECIMAL_FORMAT) { - style = UNUM_SHORT; - destination = &dataBundle.shortData; - // TODO: Enable the following statements when currency support is added - // } else if (patternsTableKey == PATTERNS_SHORT - // && formatsTableKey == CURRENCY_FORMAT) { - // style = UNUM_SHORT_CURRENCY; // or whatever the enum gets named - // destination = &dataBundle.shortCurrencyData; - // } else { - // // Silently ignore this case - // continue; - } - - // SPECIAL CASE: RULES FOR WHETHER OR NOT TO CONSUME THIS TABLE: - // 1) Don't consume longData if shortData was consumed from the non-Latin - // locale numbering system - // 2) Don't consume longData for the first time if this is the root bundle and - // shortData is already populated from a more specific locale. Note that if - // both longData and shortData are both only in root, longData will be - // consumed since it is alphabetically before shortData in the bundle. - if (isFallback - && style == UNUM_LONG - && !dataBundle.shortData.isEmpty() - && !dataBundle.shortData.fromFallback) { - continue; - } - if (isRoot - && style == UNUM_LONG - && dataBundle.longData.isEmpty() - && !dataBundle.shortData.isEmpty()) { - continue; - } - - // Set the "fromFallback" flag on the data object - destination->fromFallback = isFallback; - - // Traverse into the powers of ten table - ResourceTable powersOfTenTable = value.getTable(errorCode); - if (U_FAILURE(errorCode)) { return; } - for (int i3 = 0; powersOfTenTable.getKeyAndValue(i3, key, value); ++i3) { - - // The key will always be some even power of 10. e.g 10000. - char* endPtr = NULL; - double power10 = uprv_strtod(key, &endPtr); - if (*endPtr != 0) { - errorCode = U_INTERNAL_PROGRAM_ERROR; - return; - } - int32_t log10Value = computeLog10(power10, FALSE); - - // Silently ignore divisors that are too big. - if (log10Value >= MAX_DIGITS) continue; - - // Iterate over the plural variants ("one", "other", etc) - ResourceTable pluralVariantsTable = value.getTable(errorCode); - if (U_FAILURE(errorCode)) { return; } - for (int i4 = 0; pluralVariantsTable.getKeyAndValue(i4, key, value); ++i4) { - const char* pluralVariant = key; - const UnicodeString formatStr = value.getUnicodeString(errorCode); - - // Copy the data into the in-memory data bundle (do not overwrite - // existing values) - int32_t numZeros = populatePrefixSuffix( - pluralVariant, log10Value, formatStr, - destination->unitsByVariant, FALSE, errorCode); - - // If populatePrefixSuffix returns -1, it means that this key has been - // encountered already. - if (numZeros < 0) { - continue; - } - - // Set the divisor, which is based on the number of zeros in the template - // string. If the divisor from here is different from the one previously - // stored, it means that the number of zeros in different plural variants - // differs; throw an exception. - // TODO: How should I check for floating-point errors here? - // Is there a good reason why "divisor" is double and not long like Java? - double divisor = calculateDivisor(power10, numZeros); - if (destination->divisors[log10Value] != 0.0 - && destination->divisors[log10Value] != divisor) { - errorCode = U_INTERNAL_PROGRAM_ERROR; - return; - } - destination->divisors[log10Value] = divisor; - } - } - } - } - } -}; - -// Virtual destructors must be defined out of line. -CmptDecDataSink::~CmptDecDataSink() {} - -} // namespace - -static void load(const Locale& inLocale, CDFLocaleData* result, UErrorCode& status) { - LocalPointer ns(NumberingSystem::createInstance(inLocale, status)); - if (U_FAILURE(status)) { - return; - } - const char* nsName = ns->getName(); - - LocalUResourceBundlePointer resource(ures_open(NULL, inLocale.getName(), &status)); - if (U_FAILURE(status)) { - return; - } - CmptDecDataSink sink(*result); - sink.isFallback = FALSE; - - // First load the number elements data if nsName is not Latin. - if (uprv_strcmp(nsName, gLatnTag) != 0) { - sink.isLatin = FALSE; - CharString path; - path.append(gNumberElementsTag, status) - .append('/', status) - .append(nsName, status); - ures_getAllItemsWithFallback(resource.getAlias(), path.data(), sink, status); - if (status == U_MISSING_RESOURCE_ERROR) { - // Silently ignore and use Latin - status = U_ZERO_ERROR; - } else if (U_FAILURE(status)) { - return; - } - sink.isFallback = TRUE; - } - - // Now load Latin. - sink.isLatin = TRUE; - ures_getAllItemsWithFallback(resource.getAlias(), gLatnPath, sink, status); - if (U_FAILURE(status)) return; - - // If longData is empty, default it to be equal to shortData - if (result->longData.isEmpty()) { - result->longData.setToBogus(); - } - - // Check for "other" variants in each of the three data classes, and resolve missing elements. - - if (!result->longData.isBogus()) { - checkForOtherVariants(&result->longData, status); - if (U_FAILURE(status)) return; - fillInMissing(&result->longData); - } - - checkForOtherVariants(&result->shortData, status); - if (U_FAILURE(status)) return; - fillInMissing(&result->shortData); - - // TODO: Enable this statement when currency support is added - // checkForOtherVariants(&result->shortCurrencyData, status); - // if (U_FAILURE(status)) return; - // fillInMissing(&result->shortCurrencyData); -} - -// populatePrefixSuffix Adds a specific prefix-suffix pair to result for a -// given variant and log10 value. -// variant is 'zero', 'one', 'two', 'few', 'many', or 'other'. -// formatStr is the format string from which the prefix and suffix are -// extracted. It is usually of form 'Pefix 000 suffix'. -// populatePrefixSuffix returns the number of 0's found in formatStr -// before the decimal point. -// In the special case that formatStr contains only spaces for prefix -// and suffix, populatePrefixSuffix returns log10Value + 1. -static int32_t populatePrefixSuffix( - const char* variant, int32_t log10Value, const UnicodeString& formatStr, UHashtable* result, UBool overwrite, UErrorCode& status) { - if (U_FAILURE(status)) { - return 0; - } - - // ICU 59 HACK: Ignore negative part of format string, mimicking ICU 58 behavior. - // TODO(sffc): Make sure this is fixed during the overhaul port in ICU 60. - int32_t semiPos = formatStr.indexOf(';', 0); - if (semiPos == -1) { - semiPos = formatStr.length(); - } - UnicodeString positivePart = formatStr.tempSubString(0, semiPos); - - int32_t firstIdx = positivePart.indexOf(kZero, UPRV_LENGTHOF(kZero), 0); - // We must have 0's in format string. - if (firstIdx == -1) { - status = U_INTERNAL_PROGRAM_ERROR; - return 0; - } - int32_t lastIdx = positivePart.lastIndexOf(kZero, UPRV_LENGTHOF(kZero), firstIdx); - CDFUnit* unit = createCDFUnit(variant, log10Value, result, status); - if (U_FAILURE(status)) { - return 0; - } - - // Return -1 if we are not overwriting an existing value - if (unit->isSet() && !overwrite) { - return -1; - } - unit->markAsSet(); - - // Everything up to first 0 is the prefix - unit->prefix = positivePart.tempSubString(0, firstIdx); - fixQuotes(unit->prefix); - // Everything beyond the last 0 is the suffix - unit->suffix = positivePart.tempSubString(lastIdx + 1); - fixQuotes(unit->suffix); - - // If there is effectively no prefix or suffix, ignore the actual number of - // 0's and act as if the number of 0's matches the size of the number. - if (onlySpaces(unit->prefix) && onlySpaces(unit->suffix)) { - return log10Value + 1; - } - - // Calculate number of zeros before decimal point - int32_t idx = firstIdx + 1; - while (idx <= lastIdx && positivePart.charAt(idx) == u_0) { - ++idx; - } - return (idx - firstIdx); -} - -// Calculate a divisor based on the magnitude and number of zeros in the -// template string. -static double calculateDivisor(double power10, int32_t numZeros) { - double divisor = power10; - for (int32_t i = 1; i < numZeros; ++i) { - divisor /= 10.0; - } - return divisor; -} - -static UBool onlySpaces(UnicodeString u) { - return u.trim().length() == 0; -} - -// fixQuotes unescapes single quotes. Don''t -> Don't. Letter 'j' -> Letter j. -// Modifies s in place. -static void fixQuotes(UnicodeString& s) { - QuoteState state = OUTSIDE; - int32_t len = s.length(); - int32_t dest = 0; - for (int32_t i = 0; i < len; ++i) { - UChar ch = s.charAt(i); - if (ch == u_apos) { - if (state == INSIDE_EMPTY) { - s.setCharAt(dest, ch); - ++dest; - } - } else { - s.setCharAt(dest, ch); - ++dest; - } - - // Update state - switch (state) { - case OUTSIDE: - state = ch == u_apos ? INSIDE_EMPTY : OUTSIDE; - break; - case INSIDE_EMPTY: - case INSIDE_FULL: - state = ch == u_apos ? OUTSIDE : INSIDE_FULL; - break; - default: - break; - } - } - s.truncate(dest); -} - -// Checks to make sure that an "other" variant is present in all -// powers of 10. -static void checkForOtherVariants(CDFLocaleStyleData* result, - UErrorCode& status) { - if (result == NULL || result->unitsByVariant == NULL) { - return; - } - - const CDFUnit* otherByBase = - (const CDFUnit*) uhash_get(result->unitsByVariant, gOther); - if (otherByBase == NULL) { - status = U_INTERNAL_PROGRAM_ERROR; - return; - } - - // Check all other plural variants, and make sure that if - // any of them are populated, then other is also populated - int32_t pos = UHASH_FIRST; - const UHashElement* element; - while ((element = uhash_nextElement(result->unitsByVariant, &pos)) != NULL) { - CDFUnit* variantsByBase = (CDFUnit*) element->value.pointer; - if (variantsByBase == otherByBase) continue; - for (int32_t log10Value = 0; log10Value < MAX_DIGITS; ++log10Value) { - if (variantsByBase[log10Value].isSet() - && !otherByBase[log10Value].isSet()) { - status = U_INTERNAL_PROGRAM_ERROR; - return; - } - } - } -} - -// fillInMissing ensures that the data in result is complete. -// result data is complete if for each variant in result, there exists -// a prefix-suffix pair for each log10 value and there also exists -// a divisor for each log10 value. -// -// First this function figures out for which log10 values, the other -// variant already had data. These are the same log10 values defined -// in CLDR. -// -// For each log10 value not defined in CLDR, it uses the divisor for -// the last defined log10 value or 1. -// -// Then for each variant, it does the following. For each log10 -// value not defined in CLDR, copy the prefix-suffix pair from the -// previous log10 value. If log10 value is defined in CLDR but is -// missing from given variant, copy the prefix-suffix pair for that -// log10 value from the 'other' variant. -static void fillInMissing(CDFLocaleStyleData* result) { - const CDFUnit* otherUnits = - (const CDFUnit*) uhash_get(result->unitsByVariant, gOther); - UBool definedInCLDR[MAX_DIGITS]; - double lastDivisor = 1.0; - for (int32_t i = 0; i < MAX_DIGITS; ++i) { - if (!otherUnits[i].isSet()) { - result->divisors[i] = lastDivisor; - definedInCLDR[i] = FALSE; - } else { - lastDivisor = result->divisors[i]; - definedInCLDR[i] = TRUE; - } - } - // Iterate over each variant. - int32_t pos = UHASH_FIRST; - const UHashElement* element = uhash_nextElement(result->unitsByVariant, &pos); - for (;element != NULL; element = uhash_nextElement(result->unitsByVariant, &pos)) { - CDFUnit* units = (CDFUnit*) element->value.pointer; - for (int32_t i = 0; i < MAX_DIGITS; ++i) { - if (definedInCLDR[i]) { - if (!units[i].isSet()) { - units[i] = otherUnits[i]; - } - } else { - if (i == 0) { - units[0].markAsSet(); - } else { - units[i] = units[i - 1]; - } - } - } - } -} - -// computeLog10 computes floor(log10(x)). If inRange is TRUE, the biggest -// value computeLog10 will return MAX_DIGITS -1 even for -// numbers > 10^MAX_DIGITS. If inRange is FALSE, computeLog10 will return -// up to MAX_DIGITS. -static int32_t computeLog10(double x, UBool inRange) { - int32_t result = 0; - int32_t max = inRange ? MAX_DIGITS - 1 : MAX_DIGITS; - while (x >= 10.0) { - x /= 10.0; - ++result; - if (result == max) { - break; - } - } - return result; -} - -// createCDFUnit returns a pointer to the prefix-suffix pair for a given -// variant and log10 value within table. If no such prefix-suffix pair is -// stored in table, one is created within table before returning pointer. -static CDFUnit* createCDFUnit(const char* variant, int32_t log10Value, UHashtable* table, UErrorCode& status) { - if (U_FAILURE(status)) { - return NULL; - } - CDFUnit *cdfUnit = (CDFUnit*) uhash_get(table, variant); - if (cdfUnit == NULL) { - cdfUnit = new CDFUnit[MAX_DIGITS]; - if (cdfUnit == NULL) { - status = U_MEMORY_ALLOCATION_ERROR; - return NULL; - } - uhash_put(table, uprv_strdup(variant), cdfUnit, &status); - if (U_FAILURE(status)) { - return NULL; - } - } - CDFUnit* result = &cdfUnit[log10Value]; - return result; -} - -// getCDFUnitFallback returns a pointer to the prefix-suffix pair for a given -// variant and log10 value within table. If the given variant doesn't exist, it -// falls back to the OTHER variant. Therefore, this method will always return -// some non-NULL value. -static const CDFUnit* getCDFUnitFallback(const UHashtable* table, const UnicodeString& variant, int32_t log10Value) { - CharString cvariant; - UErrorCode status = U_ZERO_ERROR; - const CDFUnit *cdfUnit = NULL; - cvariant.appendInvariantChars(variant, status); - if (!U_FAILURE(status)) { - cdfUnit = (const CDFUnit*) uhash_get(table, cvariant.data()); - } - if (cdfUnit == NULL) { - cdfUnit = (const CDFUnit*) uhash_get(table, gOther); - } - return &cdfUnit[log10Value]; -} - -U_NAMESPACE_END -#endif +#endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/deps/icu-small/source/i18n/currpinf.cpp b/deps/icu-small/source/i18n/currpinf.cpp index 5d3ca620891..6b1efd5f4da 100644 --- a/deps/icu-small/source/i18n/currpinf.cpp +++ b/deps/icu-small/source/i18n/currpinf.cpp @@ -203,6 +203,9 @@ CurrencyPluralInfo::setCurrencyPluralPattern(const UnicodeString& pluralCount, const UnicodeString& pattern, UErrorCode& status) { if (U_SUCCESS(status)) { + UnicodeString* oldValue = static_cast( + fPluralCountToCurrencyUnitPattern->get(pluralCount)); + delete oldValue; fPluralCountToCurrencyUnitPattern->put(pluralCount, new UnicodeString(pattern), status); } } diff --git a/deps/icu-small/source/i18n/currunit.cpp b/deps/icu-small/source/i18n/currunit.cpp index 83429c01694..6d8d1cd6c6f 100644 --- a/deps/icu-small/source/i18n/currunit.cpp +++ b/deps/icu-small/source/i18n/currunit.cpp @@ -17,21 +17,32 @@ #include "unicode/currunit.h" #include "unicode/ustring.h" #include "cstring.h" +#include "uinvchar.h" + +static constexpr char16_t kDefaultCurrency[] = u"XXX"; U_NAMESPACE_BEGIN CurrencyUnit::CurrencyUnit(ConstChar16Ptr _isoCode, UErrorCode& ec) { - *isoCode = 0; - if (U_SUCCESS(ec)) { - if (_isoCode != nullptr && u_strlen(_isoCode)==3) { - u_strcpy(isoCode, _isoCode); - char simpleIsoCode[4]; - u_UCharsToChars(isoCode, simpleIsoCode, 4); - initCurrency(simpleIsoCode); - } else { - ec = U_ILLEGAL_ARGUMENT_ERROR; - } + // 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. + const char16_t* isoCodeToUse; + if (U_FAILURE(ec) || _isoCode == nullptr) { + isoCodeToUse = kDefaultCurrency; + } else if (!uprv_isInvariantUString(_isoCode, 3)) { + // TODO: Perform a more strict ASCII check like in ICU4J isAlpha3Code? + isoCodeToUse = kDefaultCurrency; + ec = U_INVARIANT_CONVERSION_ERROR; + } else { + isoCodeToUse = _isoCode; } + // TODO: Perform uppercasing here like in ICU4J Currency.getInstance()? + uprv_memcpy(isoCode, isoCodeToUse, sizeof(UChar) * 3); + isoCode[3] = 0; + char simpleIsoCode[4]; + u_UCharsToChars(isoCode, simpleIsoCode, 4); + initCurrency(simpleIsoCode); } CurrencyUnit::CurrencyUnit(const CurrencyUnit& other) : MeasureUnit(other) { @@ -52,7 +63,7 @@ CurrencyUnit::CurrencyUnit(const MeasureUnit& other, UErrorCode& ec) : MeasureUn } CurrencyUnit::CurrencyUnit() : MeasureUnit() { - u_strcpy(isoCode, u"XXX"); + u_strcpy(isoCode, kDefaultCurrency); char simpleIsoCode[4]; u_UCharsToChars(isoCode, simpleIsoCode, 4); initCurrency(simpleIsoCode); diff --git a/deps/icu-small/source/i18n/dcfmtimp.h b/deps/icu-small/source/i18n/dcfmtimp.h deleted file mode 100644 index e582efb344b..00000000000 --- a/deps/icu-small/source/i18n/dcfmtimp.h +++ /dev/null @@ -1,54 +0,0 @@ -// © 2016 and later: Unicode, Inc. and others. -// License & terms of use: http://www.unicode.org/copyright.html -/* -******************************************************************************** -* Copyright (C) 2012-2014, International Business Machines -* Corporation and others. All Rights Reserved. -********************************************************************************/ - -#ifndef DCFMTIMP_H -#define DCFMTIMP_H - -#include "unicode/utypes.h" - - -#if UCONFIG_FORMAT_FASTPATHS_49 - -U_NAMESPACE_BEGIN - -enum EDecimalFormatFastpathStatus { - kFastpathNO = 0, - kFastpathYES = 1, - kFastpathUNKNOWN = 2, /* not yet set */ - kFastpathMAYBE = 3 /* depends on value being formatted. */ -}; - -/** - * Must be smaller than DecimalFormat::fReserved - */ -struct DecimalFormatInternal { - uint8_t fFastFormatStatus; - uint8_t fFastParseStatus; - - DecimalFormatInternal &operator=(const DecimalFormatInternal& rhs) { - fFastParseStatus = rhs.fFastParseStatus; - fFastFormatStatus = rhs.fFastFormatStatus; - return *this; - } -#ifdef FMT_DEBUG - void dump() const { - printf("DecimalFormatInternal: fFastFormatStatus=%c, fFastParseStatus=%c\n", - "NY?"[(int)fFastFormatStatus&3], - "NY?"[(int)fFastParseStatus&3] - ); - } -#endif -}; - - - -U_NAMESPACE_END - -#endif - -#endif diff --git a/deps/icu-small/source/i18n/dcfmtsym.cpp b/deps/icu-small/source/i18n/dcfmtsym.cpp index 680c3120a1e..5a432aec8e4 100644 --- a/deps/icu-small/source/i18n/dcfmtsym.cpp +++ b/deps/icu-small/source/i18n/dcfmtsym.cpp @@ -66,7 +66,7 @@ static const UChar INTL_CURRENCY_SYMBOL_STR[] = {0xa4, 0xa4, 0}; static const char *gNumberElementKeys[DecimalFormatSymbols::kFormatSymbolCount] = { "decimal", "group", - "list", + NULL, /* #11897: the symbol is NOT the pattern separator symbol */ "percentSign", NULL, /* Native zero digit is deprecated from CLDR - get it from the numbering system */ NULL, /* Pattern digit character is deprecated from CLDR - use # by default always */ @@ -98,7 +98,7 @@ static const char *gNumberElementKeys[DecimalFormatSymbols::kFormatSymbolCount] // Initializes this with the decimal format symbols in the default locale. DecimalFormatSymbols::DecimalFormatSymbols(UErrorCode& status) - : UObject(), locale() { + : UObject(), locale(), currPattern(NULL) { initialize(locale, status, TRUE); } @@ -106,12 +106,12 @@ DecimalFormatSymbols::DecimalFormatSymbols(UErrorCode& status) // Initializes this with the decimal format symbols in the desired locale. DecimalFormatSymbols::DecimalFormatSymbols(const Locale& loc, UErrorCode& status) - : UObject(), locale(loc) { + : UObject(), locale(loc), currPattern(NULL) { initialize(locale, status); } DecimalFormatSymbols::DecimalFormatSymbols(const Locale& loc, const NumberingSystem& ns, UErrorCode& status) - : UObject(), locale(loc) { + : UObject(), locale(loc), currPattern(NULL) { initialize(locale, status, FALSE, &ns); } @@ -349,7 +349,6 @@ DecimalFormatSymbols::initialize(const Locale& loc, UErrorCode& status, { if (U_FAILURE(status)) { return; } *validLocale = *actualLocale = 0; - currPattern = NULL; // First initialize all the symbols to the fallbacks for anything we can't find initialize(); @@ -477,6 +476,7 @@ DecimalFormatSymbols::initialize(const Locale& loc, UErrorCode& status, UErrorCode localStatus = U_ZERO_ERROR; uccLen = ucurr_forLocale(locName, ucc, uccLen, &localStatus); + // TODO: Currency pattern data loading is duplicated in number_formatimpl.cpp if(U_SUCCESS(localStatus) && uccLen > 0) { char cc[4]={0}; u_UCharsToChars(ucc, cc, uccLen); diff --git a/deps/icu-small/source/i18n/decfmtst.cpp b/deps/icu-small/source/i18n/decfmtst.cpp deleted file mode 100644 index 5943affad4e..00000000000 --- a/deps/icu-small/source/i18n/decfmtst.cpp +++ /dev/null @@ -1,251 +0,0 @@ -// © 2016 and later: Unicode, Inc. and others. -// License & terms of use: http://www.unicode.org/copyright.html -/* -******************************************************************************* -* Copyright (C) 2009-2016, International Business Machines Corporation and -* others. All Rights Reserved. -******************************************************************************* -* -* This file contains the class DecimalFormatStaticSets -* -* DecimalFormatStaticSets holds the UnicodeSets that are needed for lenient -* parsing of decimal and group separators. -******************************************************************************** -*/ - -#include "unicode/utypes.h" - -#if !UCONFIG_NO_FORMATTING - -#include "unicode/unistr.h" -#include "unicode/uniset.h" -#include "unicode/uchar.h" -#include "cmemory.h" -#include "cstring.h" -#include "uassert.h" -#include "ucln_in.h" -#include "umutex.h" - -#include "decfmtst.h" - -U_NAMESPACE_BEGIN - - -//------------------------------------------------------------------------------ -// -// Unicode Set pattern strings for all of the required constant sets. -// Initialized with hex values for portability to EBCDIC based machines. -// Really ugly, but there's no good way to avoid it. -// -//------------------------------------------------------------------------------ - -static const UChar gDotEquivalentsPattern[] = { - // [ . \u2024 \u3002 \uFE12 \uFE52 \uFF0E \uFF61 ] - 0x005B, 0x002E, 0x2024, 0x3002, 0xFE12, 0xFE52, 0xFF0E, 0xFF61, 0x005D, 0x0000}; - -static const UChar gCommaEquivalentsPattern[] = { - // [ , \u060C \u066B \u3001 \uFE10 \uFE11 \uFE50 \uFE51 \uFF0C \uFF64 ] - 0x005B, 0x002C, 0x060C, 0x066B, 0x3001, 0xFE10, 0xFE11, 0xFE50, 0xFE51, 0xFF0C, 0xFF64, 0x005D, 0x0000}; - -static const UChar gOtherGroupingSeparatorsPattern[] = { - // [ \ SPACE ' NBSP \u066C \u2000 - \u200A \u2018 \u2019 \u202F \u205F \u3000 \uFF07 ] - 0x005B, 0x005C, 0x0020, 0x0027, 0x00A0, 0x066C, 0x2000, 0x002D, 0x200A, 0x2018, 0x2019, 0x202F, 0x205F, 0x3000, 0xFF07, 0x005D, 0x0000}; - -static const UChar gDashEquivalentsPattern[] = { - // [ \ - HYPHEN F_DASH N_DASH MINUS ] - 0x005B, 0x005C, 0x002D, 0x2010, 0x2012, 0x2013, 0x2212, 0x005D, 0x0000}; - -static const UChar gStrictDotEquivalentsPattern[] = { - // [ . \u2024 \uFE52 \uFF0E \uFF61 ] - 0x005B, 0x002E, 0x2024, 0xFE52, 0xFF0E, 0xFF61, 0x005D, 0x0000}; - -static const UChar gStrictCommaEquivalentsPattern[] = { - // [ , \u066B \uFE10 \uFE50 \uFF0C ] - 0x005B, 0x002C, 0x066B, 0xFE10, 0xFE50, 0xFF0C, 0x005D, 0x0000}; - -static const UChar gStrictOtherGroupingSeparatorsPattern[] = { - // [ \ SPACE ' NBSP \u066C \u2000 - \u200A \u2018 \u2019 \u202F \u205F \u3000 \uFF07 ] - 0x005B, 0x005C, 0x0020, 0x0027, 0x00A0, 0x066C, 0x2000, 0x002D, 0x200A, 0x2018, 0x2019, 0x202F, 0x205F, 0x3000, 0xFF07, 0x005D, 0x0000}; - -static const UChar gStrictDashEquivalentsPattern[] = { - // [ \ - MINUS ] - 0x005B, 0x005C, 0x002D, 0x2212, 0x005D, 0x0000}; - -static const UChar32 gMinusSigns[] = { - 0x002D, - 0x207B, - 0x208B, - 0x2212, - 0x2796, - 0xFE63, - 0xFF0D}; - -static const UChar32 gPlusSigns[] = { - 0x002B, - 0x207A, - 0x208A, - 0x2795, - 0xfB29, - 0xFE62, - 0xFF0B}; - -static void initUnicodeSet(const UChar32 *raw, int32_t len, UnicodeSet *s) { - for (int32_t i = 0; i < len; ++i) { - s->add(raw[i]); - } -} - -DecimalFormatStaticSets::DecimalFormatStaticSets(UErrorCode &status) -: fDotEquivalents(NULL), - fCommaEquivalents(NULL), - fOtherGroupingSeparators(NULL), - fDashEquivalents(NULL), - fStrictDotEquivalents(NULL), - fStrictCommaEquivalents(NULL), - fStrictOtherGroupingSeparators(NULL), - fStrictDashEquivalents(NULL), - fDefaultGroupingSeparators(NULL), - fStrictDefaultGroupingSeparators(NULL), - fMinusSigns(NULL), - fPlusSigns(NULL) -{ - fDotEquivalents = new UnicodeSet(UnicodeString(TRUE, gDotEquivalentsPattern, -1), status); - fCommaEquivalents = new UnicodeSet(UnicodeString(TRUE, gCommaEquivalentsPattern, -1), status); - fOtherGroupingSeparators = new UnicodeSet(UnicodeString(TRUE, gOtherGroupingSeparatorsPattern, -1), status); - fDashEquivalents = new UnicodeSet(UnicodeString(TRUE, gDashEquivalentsPattern, -1), status); - - fStrictDotEquivalents = new UnicodeSet(UnicodeString(TRUE, gStrictDotEquivalentsPattern, -1), status); - fStrictCommaEquivalents = new UnicodeSet(UnicodeString(TRUE, gStrictCommaEquivalentsPattern, -1), status); - fStrictOtherGroupingSeparators = new UnicodeSet(UnicodeString(TRUE, gStrictOtherGroupingSeparatorsPattern, -1), status); - fStrictDashEquivalents = new UnicodeSet(UnicodeString(TRUE, gStrictDashEquivalentsPattern, -1), status); - - - fDefaultGroupingSeparators = new UnicodeSet(*fDotEquivalents); - fDefaultGroupingSeparators->addAll(*fCommaEquivalents); - fDefaultGroupingSeparators->addAll(*fOtherGroupingSeparators); - - fStrictDefaultGroupingSeparators = new UnicodeSet(*fStrictDotEquivalents); - fStrictDefaultGroupingSeparators->addAll(*fStrictCommaEquivalents); - fStrictDefaultGroupingSeparators->addAll(*fStrictOtherGroupingSeparators); - - fMinusSigns = new UnicodeSet(); - fPlusSigns = new UnicodeSet(); - - // Check for null pointers - if (fDotEquivalents == NULL || fCommaEquivalents == NULL || fOtherGroupingSeparators == NULL || fDashEquivalents == NULL || - fStrictDotEquivalents == NULL || fStrictCommaEquivalents == NULL || fStrictOtherGroupingSeparators == NULL || fStrictDashEquivalents == NULL || - fDefaultGroupingSeparators == NULL || fStrictOtherGroupingSeparators == NULL || - fMinusSigns == NULL || fPlusSigns == NULL) { - cleanup(); - status = U_MEMORY_ALLOCATION_ERROR; - return; - } - - initUnicodeSet( - gMinusSigns, - UPRV_LENGTHOF(gMinusSigns), - fMinusSigns); - initUnicodeSet( - gPlusSigns, - UPRV_LENGTHOF(gPlusSigns), - fPlusSigns); - - // Freeze all the sets - fDotEquivalents->freeze(); - fCommaEquivalents->freeze(); - fOtherGroupingSeparators->freeze(); - fDashEquivalents->freeze(); - fStrictDotEquivalents->freeze(); - fStrictCommaEquivalents->freeze(); - fStrictOtherGroupingSeparators->freeze(); - fStrictDashEquivalents->freeze(); - fDefaultGroupingSeparators->freeze(); - fStrictDefaultGroupingSeparators->freeze(); - fMinusSigns->freeze(); - fPlusSigns->freeze(); -} - -DecimalFormatStaticSets::~DecimalFormatStaticSets() { - cleanup(); -} - -void DecimalFormatStaticSets::cleanup() { // Be sure to clean up newly added fields! - delete fDotEquivalents; fDotEquivalents = NULL; - delete fCommaEquivalents; fCommaEquivalents = NULL; - delete fOtherGroupingSeparators; fOtherGroupingSeparators = NULL; - delete fDashEquivalents; fDashEquivalents = NULL; - delete fStrictDotEquivalents; fStrictDotEquivalents = NULL; - delete fStrictCommaEquivalents; fStrictCommaEquivalents = NULL; - delete fStrictOtherGroupingSeparators; fStrictOtherGroupingSeparators = NULL; - delete fStrictDashEquivalents; fStrictDashEquivalents = NULL; - delete fDefaultGroupingSeparators; fDefaultGroupingSeparators = NULL; - delete fStrictDefaultGroupingSeparators; fStrictDefaultGroupingSeparators = NULL; - delete fStrictOtherGroupingSeparators; fStrictOtherGroupingSeparators = NULL; - delete fMinusSigns; fMinusSigns = NULL; - delete fPlusSigns; fPlusSigns = NULL; -} - -static DecimalFormatStaticSets *gStaticSets; -static icu::UInitOnce gStaticSetsInitOnce = U_INITONCE_INITIALIZER; - - -//------------------------------------------------------------------------------ -// -// decfmt_cleanup Memory cleanup function, free/delete all -// cached memory. Called by ICU's u_cleanup() function. -// -//------------------------------------------------------------------------------ -U_CDECL_BEGIN -static UBool U_CALLCONV -decimfmt_cleanup(void) -{ - delete gStaticSets; - gStaticSets = NULL; - gStaticSetsInitOnce.reset(); - return TRUE; -} - -static void U_CALLCONV initSets(UErrorCode &status) { - U_ASSERT(gStaticSets == NULL); - ucln_i18n_registerCleanup(UCLN_I18N_DECFMT, decimfmt_cleanup); - gStaticSets = new DecimalFormatStaticSets(status); - if (U_FAILURE(status)) { - delete gStaticSets; - gStaticSets = NULL; - return; - } - if (gStaticSets == NULL) { - status = U_MEMORY_ALLOCATION_ERROR; - } -} -U_CDECL_END - -const DecimalFormatStaticSets *DecimalFormatStaticSets::getStaticSets(UErrorCode &status) { - umtx_initOnce(gStaticSetsInitOnce, initSets, status); - return gStaticSets; -} - - -const UnicodeSet *DecimalFormatStaticSets::getSimilarDecimals(UChar32 decimal, UBool strictParse) -{ - UErrorCode status = U_ZERO_ERROR; - umtx_initOnce(gStaticSetsInitOnce, initSets, status); - if (U_FAILURE(status)) { - return NULL; - } - - if (gStaticSets->fDotEquivalents->contains(decimal)) { - return strictParse ? gStaticSets->fStrictDotEquivalents : gStaticSets->fDotEquivalents; - } - - if (gStaticSets->fCommaEquivalents->contains(decimal)) { - return strictParse ? gStaticSets->fStrictCommaEquivalents : gStaticSets->fCommaEquivalents; - } - - // if there is no match, return NULL - return NULL; -} - - -U_NAMESPACE_END -#endif // !UCONFIG_NO_FORMATTING diff --git a/deps/icu-small/source/i18n/decfmtst.h b/deps/icu-small/source/i18n/decfmtst.h deleted file mode 100644 index 63ae50c6df9..00000000000 --- a/deps/icu-small/source/i18n/decfmtst.h +++ /dev/null @@ -1,69 +0,0 @@ -// © 2016 and later: Unicode, Inc. and others. -// License & terms of use: http://www.unicode.org/copyright.html -/* -******************************************************************************* -* Copyright (C) 2009-2016, International Business Machines Corporation and -* others. All Rights Reserved. -******************************************************************************* -* -* This file contains declarations for the class DecimalFormatStaticSets -* -* DecimalFormatStaticSets holds the UnicodeSets that are needed for lenient -* parsing of decimal and group separators. -******************************************************************************** -*/ - -#ifndef DECFMTST_H -#define DECFMTST_H - -#include "unicode/utypes.h" - -#if !UCONFIG_NO_FORMATTING - -#include "unicode/uobject.h" - -U_NAMESPACE_BEGIN - -class UnicodeSet; - - -class DecimalFormatStaticSets : public UMemory -{ -public: - // Constructor and Destructor not for general use. - // Public to permit access from plain C implementation functions. - DecimalFormatStaticSets(UErrorCode &status); - ~DecimalFormatStaticSets(); - - /** - * Return a pointer to a lazy-initialized singleton instance of this class. - */ - static const DecimalFormatStaticSets *getStaticSets(UErrorCode &status); - - static const UnicodeSet *getSimilarDecimals(UChar32 decimal, UBool strictParse); - - UnicodeSet *fDotEquivalents; - UnicodeSet *fCommaEquivalents; - UnicodeSet *fOtherGroupingSeparators; - UnicodeSet *fDashEquivalents; - - UnicodeSet *fStrictDotEquivalents; - UnicodeSet *fStrictCommaEquivalents; - UnicodeSet *fStrictOtherGroupingSeparators; - UnicodeSet *fStrictDashEquivalents; - - UnicodeSet *fDefaultGroupingSeparators; - UnicodeSet *fStrictDefaultGroupingSeparators; - - UnicodeSet *fMinusSigns; - UnicodeSet *fPlusSigns; -private: - void cleanup(); - -}; - - -U_NAMESPACE_END - -#endif // !UCONFIG_NO_FORMATTING -#endif // DECFMTST_H diff --git a/deps/icu-small/source/i18n/decimalformatpattern.cpp b/deps/icu-small/source/i18n/decimalformatpattern.cpp deleted file mode 100644 index 80a1870f33e..00000000000 --- a/deps/icu-small/source/i18n/decimalformatpattern.cpp +++ /dev/null @@ -1,656 +0,0 @@ -// © 2016 and later: Unicode, Inc. and others. -// License & terms of use: http://www.unicode.org/copyright.html -/* -******************************************************************************* -* Copyright (C) 1997-2015, International Business Machines Corporation and * -* others. All Rights Reserved. * -******************************************************************************* -*/ - -#include "uassert.h" -#include "decimalformatpattern.h" - -#if !UCONFIG_NO_FORMATTING - -#include "unicode/dcfmtsym.h" -#include "unicode/format.h" -#include "unicode/utf16.h" -#include "decimalformatpatternimpl.h" - - -#ifdef FMT_DEBUG -#define debug(x) printf("%s:%d: %s\n", __FILE__,__LINE__, x); -#else -#define debug(x) -#endif - -U_NAMESPACE_BEGIN - -// TODO: Travis Keep: Copied from numfmt.cpp -static int32_t kDoubleIntegerDigits = 309; -static int32_t kDoubleFractionDigits = 340; - - -// TODO: Travis Keep: Copied from numfmt.cpp -static int32_t gDefaultMaxIntegerDigits = 2000000000; - -// TODO: Travis Keep: This function was copied from format.cpp -static void syntaxError(const UnicodeString& pattern, - int32_t pos, - UParseError& parseError) { - parseError.offset = pos; - parseError.line=0; // we are not using line number - - // for pre-context - int32_t start = (pos < U_PARSE_CONTEXT_LEN)? 0 : (pos - (U_PARSE_CONTEXT_LEN-1 - /* subtract 1 so that we have room for null*/)); - int32_t stop = pos; - pattern.extract(start,stop-start,parseError.preContext,0); - //null terminate the buffer - parseError.preContext[stop-start] = 0; - - //for post-context - start = pattern.moveIndex32(pos, 1); - stop = pos + U_PARSE_CONTEXT_LEN - 1; - if (stop > pattern.length()) { - stop = pattern.length(); - } - pattern.extract(start, stop - start, parseError.postContext, 0); - //null terminate the buffer - parseError.postContext[stop-start]= 0; -} - -DecimalFormatPattern::DecimalFormatPattern() - : fMinimumIntegerDigits(1), - fMaximumIntegerDigits(gDefaultMaxIntegerDigits), - fMinimumFractionDigits(0), - fMaximumFractionDigits(3), - fUseSignificantDigits(FALSE), - fMinimumSignificantDigits(1), - fMaximumSignificantDigits(6), - fUseExponentialNotation(FALSE), - fMinExponentDigits(0), - fExponentSignAlwaysShown(FALSE), - fCurrencySignCount(fgCurrencySignCountZero), - fGroupingUsed(TRUE), - fGroupingSize(0), - fGroupingSize2(0), - fMultiplier(1), - fDecimalSeparatorAlwaysShown(FALSE), - fFormatWidth(0), - fRoundingIncrementUsed(FALSE), - fRoundingIncrement(), - fPad(kDefaultPad), - fNegPatternsBogus(TRUE), - fPosPatternsBogus(TRUE), - fNegPrefixPattern(), - fNegSuffixPattern(), - fPosPrefixPattern(), - fPosSuffixPattern(), - fPadPosition(DecimalFormatPattern::kPadBeforePrefix) { -} - - -DecimalFormatPatternParser::DecimalFormatPatternParser() : - fZeroDigit(kPatternZeroDigit), - fSigDigit(kPatternSignificantDigit), - fGroupingSeparator((UChar)kPatternGroupingSeparator), - fDecimalSeparator((UChar)kPatternDecimalSeparator), - fPercent((UChar)kPatternPercent), - fPerMill((UChar)kPatternPerMill), - fDigit((UChar)kPatternDigit), - fSeparator((UChar)kPatternSeparator), - fExponent((UChar)kPatternExponent), - fPlus((UChar)kPatternPlus), - fMinus((UChar)kPatternMinus), - fPadEscape((UChar)kPatternPadEscape) { -} - -void DecimalFormatPatternParser::useSymbols( - const DecimalFormatSymbols& symbols) { - fZeroDigit = symbols.getConstSymbol( - DecimalFormatSymbols::kZeroDigitSymbol).char32At(0); - fSigDigit = symbols.getConstSymbol( - DecimalFormatSymbols::kSignificantDigitSymbol).char32At(0); - fGroupingSeparator = symbols.getConstSymbol( - DecimalFormatSymbols::kGroupingSeparatorSymbol); - fDecimalSeparator = symbols.getConstSymbol( - DecimalFormatSymbols::kDecimalSeparatorSymbol); - fPercent = symbols.getConstSymbol( - DecimalFormatSymbols::kPercentSymbol); - fPerMill = symbols.getConstSymbol( - DecimalFormatSymbols::kPerMillSymbol); - fDigit = symbols.getConstSymbol( - DecimalFormatSymbols::kDigitSymbol); - fSeparator = symbols.getConstSymbol( - DecimalFormatSymbols::kPatternSeparatorSymbol); - fExponent = symbols.getConstSymbol( - DecimalFormatSymbols::kExponentialSymbol); - fPlus = symbols.getConstSymbol( - DecimalFormatSymbols::kPlusSignSymbol); - fMinus = symbols.getConstSymbol( - DecimalFormatSymbols::kMinusSignSymbol); - fPadEscape = symbols.getConstSymbol( - DecimalFormatSymbols::kPadEscapeSymbol); -} - -void -DecimalFormatPatternParser::applyPatternWithoutExpandAffix( - const UnicodeString& pattern, - DecimalFormatPattern& out, - UParseError& parseError, - UErrorCode& status) { - if (U_FAILURE(status)) - { - return; - } - out = DecimalFormatPattern(); - - // Clear error struct - parseError.offset = -1; - parseError.preContext[0] = parseError.postContext[0] = (UChar)0; - - // TODO: Travis Keep: This won't always work. - UChar nineDigit = (UChar)(fZeroDigit + 9); - int32_t digitLen = fDigit.length(); - int32_t groupSepLen = fGroupingSeparator.length(); - int32_t decimalSepLen = fDecimalSeparator.length(); - - int32_t pos = 0; - int32_t patLen = pattern.length(); - // Part 0 is the positive pattern. Part 1, if present, is the negative - // pattern. - for (int32_t part=0; part<2 && pos 0 || sigDigitCount > 0) { - ++digitRightCount; - } else { - ++digitLeftCount; - } - if (groupingCount >= 0 && decimalPos < 0) { - ++groupingCount; - } - pos += digitLen; - } else if ((ch >= fZeroDigit && ch <= nineDigit) || - ch == fSigDigit) { - if (digitRightCount > 0) { - // Unexpected '0' - debug("Unexpected '0'") - status = U_UNEXPECTED_TOKEN; - syntaxError(pattern,pos,parseError); - return; - } - if (ch == fSigDigit) { - ++sigDigitCount; - } else { - if (ch != fZeroDigit && roundingPos < 0) { - roundingPos = digitLeftCount + zeroDigitCount; - } - if (roundingPos >= 0) { - roundingInc.append((char)(ch - fZeroDigit + '0')); - } - ++zeroDigitCount; - } - if (groupingCount >= 0 && decimalPos < 0) { - ++groupingCount; - } - pos += U16_LENGTH(ch); - } else if (pattern.compare(pos, groupSepLen, fGroupingSeparator) == 0) { - if (decimalPos >= 0) { - // Grouping separator after decimal - debug("Grouping separator after decimal") - status = U_UNEXPECTED_TOKEN; - syntaxError(pattern,pos,parseError); - return; - } - groupingCount2 = groupingCount; - groupingCount = 0; - pos += groupSepLen; - } else if (pattern.compare(pos, decimalSepLen, fDecimalSeparator) == 0) { - if (decimalPos >= 0) { - // Multiple decimal separators - debug("Multiple decimal separators") - status = U_MULTIPLE_DECIMAL_SEPARATORS; - syntaxError(pattern,pos,parseError); - return; - } - // Intentionally incorporate the digitRightCount, - // even though it is illegal for this to be > 0 - // at this point. We check pattern syntax below. - decimalPos = digitLeftCount + zeroDigitCount + digitRightCount; - pos += decimalSepLen; - } else { - if (pattern.compare(pos, fExponent.length(), fExponent) == 0) { - if (expDigits >= 0) { - // Multiple exponential symbols - debug("Multiple exponential symbols") - status = U_MULTIPLE_EXPONENTIAL_SYMBOLS; - syntaxError(pattern,pos,parseError); - return; - } - if (groupingCount >= 0) { - // Grouping separator in exponential pattern - debug("Grouping separator in exponential pattern") - status = U_MALFORMED_EXPONENTIAL_PATTERN; - syntaxError(pattern,pos,parseError); - return; - } - pos += fExponent.length(); - // Check for positive prefix - if (pos < patLen - && pattern.compare(pos, fPlus.length(), fPlus) == 0) { - expSignAlways = TRUE; - pos += fPlus.length(); - } - // Use lookahead to parse out the exponential part of the - // pattern, then jump into suffix subpart. - expDigits = 0; - while (pos < patLen && - pattern.char32At(pos) == fZeroDigit) { - ++expDigits; - pos += U16_LENGTH(fZeroDigit); - } - - // 1. Require at least one mantissa pattern digit - // 2. Disallow "#+ @" in mantissa - // 3. Require at least one exponent pattern digit - if (((digitLeftCount + zeroDigitCount) < 1 && - (sigDigitCount + digitRightCount) < 1) || - (sigDigitCount > 0 && digitLeftCount > 0) || - expDigits < 1) { - // Malformed exponential pattern - debug("Malformed exponential pattern") - status = U_MALFORMED_EXPONENTIAL_PATTERN; - syntaxError(pattern,pos,parseError); - return; - } - } - // Transition to suffix subpart - subpart = 2; // suffix subpart - affix = &suffix; - sub0Limit = pos; - continue; - } - break; - case 1: // Prefix subpart - case 2: // Suffix subpart - // Process the prefix / suffix characters - // Process unquoted characters seen in prefix or suffix - // subpart. - - // Several syntax characters implicitly begins the - // next subpart if we are in the prefix; otherwise - // they are illegal if unquoted. - if (!pattern.compare(pos, digitLen, fDigit) || - !pattern.compare(pos, groupSepLen, fGroupingSeparator) || - !pattern.compare(pos, decimalSepLen, fDecimalSeparator) || - (ch >= fZeroDigit && ch <= nineDigit) || - ch == fSigDigit) { - if (subpart == 1) { // prefix subpart - subpart = 0; // pattern proper subpart - sub0Start = pos; // Reprocess this character - continue; - } else { - status = U_UNQUOTED_SPECIAL; - syntaxError(pattern,pos,parseError); - return; - } - } else if (ch == kCurrencySign) { - affix->append(kQuote); // Encode currency - // Use lookahead to determine if the currency sign is - // doubled or not. - U_ASSERT(U16_LENGTH(kCurrencySign) == 1); - if ((pos+1) < pattern.length() && pattern[pos+1] == kCurrencySign) { - affix->append(kCurrencySign); - ++pos; // Skip over the doubled character - if ((pos+1) < pattern.length() && - pattern[pos+1] == kCurrencySign) { - affix->append(kCurrencySign); - ++pos; // Skip over the doubled character - out.fCurrencySignCount = fgCurrencySignCountInPluralFormat; - } else { - out.fCurrencySignCount = fgCurrencySignCountInISOFormat; - } - } else { - out.fCurrencySignCount = fgCurrencySignCountInSymbolFormat; - } - // Fall through to append(ch) - } else if (ch == kQuote) { - // A quote outside quotes indicates either the opening - // quote or two quotes, which is a quote literal. That is, - // we have the first quote in 'do' or o''clock. - U_ASSERT(U16_LENGTH(kQuote) == 1); - ++pos; - if (pos < pattern.length() && pattern[pos] == kQuote) { - affix->append(kQuote); // Encode quote - // Fall through to append(ch) - } else { - subpart += 2; // open quote - continue; - } - } else if (pattern.compare(pos, fSeparator.length(), fSeparator) == 0) { - // Don't allow separators in the prefix, and don't allow - // separators in the second pattern (part == 1). - if (subpart == 1 || part == 1) { - // Unexpected separator - debug("Unexpected separator") - status = U_UNEXPECTED_TOKEN; - syntaxError(pattern,pos,parseError); - return; - } - sub2Limit = pos; - isPartDone = TRUE; // Go to next part - pos += fSeparator.length(); - break; - } else if (pattern.compare(pos, fPercent.length(), fPercent) == 0) { - // Next handle characters which are appended directly. - if (multiplier != 1) { - // Too many percent/perMill characters - debug("Too many percent characters") - status = U_MULTIPLE_PERCENT_SYMBOLS; - syntaxError(pattern,pos,parseError); - return; - } - affix->append(kQuote); // Encode percent/perMill - affix->append(kPatternPercent); // Use unlocalized pattern char - multiplier = 100; - pos += fPercent.length(); - break; - } else if (pattern.compare(pos, fPerMill.length(), fPerMill) == 0) { - // Next handle characters which are appended directly. - if (multiplier != 1) { - // Too many percent/perMill characters - debug("Too many perMill characters") - status = U_MULTIPLE_PERMILL_SYMBOLS; - syntaxError(pattern,pos,parseError); - return; - } - affix->append(kQuote); // Encode percent/perMill - affix->append(kPatternPerMill); // Use unlocalized pattern char - multiplier = 1000; - pos += fPerMill.length(); - break; - } else if (pattern.compare(pos, fPadEscape.length(), fPadEscape) == 0) { - if (padPos >= 0 || // Multiple pad specifiers - (pos+1) == pattern.length()) { // Nothing after padEscape - debug("Multiple pad specifiers") - status = U_MULTIPLE_PAD_SPECIFIERS; - syntaxError(pattern,pos,parseError); - return; - } - padPos = pos; - pos += fPadEscape.length(); - padChar = pattern.char32At(pos); - pos += U16_LENGTH(padChar); - break; - } else if (pattern.compare(pos, fMinus.length(), fMinus) == 0) { - affix->append(kQuote); // Encode minus - affix->append(kPatternMinus); - pos += fMinus.length(); - break; - } else if (pattern.compare(pos, fPlus.length(), fPlus) == 0) { - affix->append(kQuote); // Encode plus - affix->append(kPatternPlus); - pos += fPlus.length(); - break; - } - // Unquoted, non-special characters fall through to here, as - // well as other code which needs to append something to the - // affix. - affix->append(ch); - pos += U16_LENGTH(ch); - break; - case 3: // Prefix subpart, in quote - case 4: // Suffix subpart, in quote - // A quote within quotes indicates either the closing - // quote or two quotes, which is a quote literal. That is, - // we have the second quote in 'do' or 'don''t'. - if (ch == kQuote) { - ++pos; - if (pos < pattern.length() && pattern[pos] == kQuote) { - affix->append(kQuote); // Encode quote - // Fall through to append(ch) - } else { - subpart -= 2; // close quote - continue; - } - } - affix->append(ch); - pos += U16_LENGTH(ch); - break; - } - } - - if (sub0Limit == 0) { - sub0Limit = pattern.length(); - } - - if (sub2Limit == 0) { - sub2Limit = pattern.length(); - } - - /* Handle patterns with no '0' pattern character. These patterns - * are legal, but must be recodified to make sense. "##.###" -> - * "#0.###". ".###" -> ".0##". - * - * We allow patterns of the form "####" to produce a zeroDigitCount - * of zero (got that?); although this seems like it might make it - * possible for format() to produce empty strings, format() checks - * for this condition and outputs a zero digit in this situation. - * Having a zeroDigitCount of zero yields a minimum integer digits - * of zero, which allows proper round-trip patterns. We don't want - * "#" to become "#0" when toPattern() is called (even though that's - * what it really is, semantically). - */ - if (zeroDigitCount == 0 && sigDigitCount == 0 && - digitLeftCount > 0 && decimalPos >= 0) { - // Handle "###.###" and "###." and ".###" - int n = decimalPos; - if (n == 0) - ++n; // Handle ".###" - digitRightCount = digitLeftCount - n; - digitLeftCount = n - 1; - zeroDigitCount = 1; - } - - // Do syntax checking on the digits, decimal points, and quotes. - if ((decimalPos < 0 && digitRightCount > 0 && sigDigitCount == 0) || - (decimalPos >= 0 && - (sigDigitCount > 0 || - decimalPos < digitLeftCount || - decimalPos > (digitLeftCount + zeroDigitCount))) || - groupingCount == 0 || groupingCount2 == 0 || - (sigDigitCount > 0 && zeroDigitCount > 0) || - subpart > 2) - { // subpart > 2 == unmatched quote - debug("Syntax error") - status = U_PATTERN_SYNTAX_ERROR; - syntaxError(pattern,pos,parseError); - return; - } - - // Make sure pad is at legal position before or after affix. - if (padPos >= 0) { - if (padPos == start) { - padPos = DecimalFormatPattern::kPadBeforePrefix; - } else if (padPos+2 == sub0Start) { - padPos = DecimalFormatPattern::kPadAfterPrefix; - } else if (padPos == sub0Limit) { - padPos = DecimalFormatPattern::kPadBeforeSuffix; - } else if (padPos+2 == sub2Limit) { - padPos = DecimalFormatPattern::kPadAfterSuffix; - } else { - // Illegal pad position - debug("Illegal pad position") - status = U_ILLEGAL_PAD_POSITION; - syntaxError(pattern,pos,parseError); - return; - } - } - - if (part == 0) { - out.fPosPatternsBogus = FALSE; - out.fPosPrefixPattern = prefix; - out.fPosSuffixPattern = suffix; - out.fNegPatternsBogus = TRUE; - out.fNegPrefixPattern.remove(); - out.fNegSuffixPattern.remove(); - - out.fUseExponentialNotation = (expDigits >= 0); - if (out.fUseExponentialNotation) { - out.fMinExponentDigits = expDigits; - } - out.fExponentSignAlwaysShown = expSignAlways; - int32_t digitTotalCount = digitLeftCount + zeroDigitCount + digitRightCount; - // The effectiveDecimalPos is the position the decimal is at or - // would be at if there is no decimal. Note that if - // decimalPos<0, then digitTotalCount == digitLeftCount + - // zeroDigitCount. - int32_t effectiveDecimalPos = decimalPos >= 0 ? decimalPos : digitTotalCount; - UBool isSigDig = (sigDigitCount > 0); - out.fUseSignificantDigits = isSigDig; - if (isSigDig) { - out.fMinimumSignificantDigits = sigDigitCount; - out.fMaximumSignificantDigits = sigDigitCount + digitRightCount; - } else { - int32_t minInt = effectiveDecimalPos - digitLeftCount; - out.fMinimumIntegerDigits = minInt; - out.fMaximumIntegerDigits = out.fUseExponentialNotation - ? digitLeftCount + out.fMinimumIntegerDigits - : gDefaultMaxIntegerDigits; - out.fMaximumFractionDigits = decimalPos >= 0 - ? (digitTotalCount - decimalPos) : 0; - out.fMinimumFractionDigits = decimalPos >= 0 - ? (digitLeftCount + zeroDigitCount - decimalPos) : 0; - } - out.fGroupingUsed = groupingCount > 0; - out.fGroupingSize = (groupingCount > 0) ? groupingCount : 0; - out.fGroupingSize2 = (groupingCount2 > 0 && groupingCount2 != groupingCount) - ? groupingCount2 : 0; - out.fMultiplier = multiplier; - out.fDecimalSeparatorAlwaysShown = decimalPos == 0 - || decimalPos == digitTotalCount; - if (padPos >= 0) { - out.fPadPosition = (DecimalFormatPattern::EPadPosition) padPos; - // To compute the format width, first set up sub0Limit - - // sub0Start. Add in prefix/suffix length later. - - // fFormatWidth = prefix.length() + suffix.length() + - // sub0Limit - sub0Start; - out.fFormatWidth = sub0Limit - sub0Start; - out.fPad = padChar; - } else { - out.fFormatWidth = 0; - } - if (roundingPos >= 0) { - out.fRoundingIncrementUsed = TRUE; - roundingInc.setDecimalAt(effectiveDecimalPos - roundingPos); - out.fRoundingIncrement = roundingInc; - } else { - out.fRoundingIncrementUsed = FALSE; - } - } else { - out.fNegPatternsBogus = FALSE; - out.fNegPrefixPattern = prefix; - out.fNegSuffixPattern = suffix; - } - } - - if (pattern.length() == 0) { - out.fNegPatternsBogus = TRUE; - out.fNegPrefixPattern.remove(); - out.fNegSuffixPattern.remove(); - out.fPosPatternsBogus = FALSE; - out.fPosPrefixPattern.remove(); - out.fPosSuffixPattern.remove(); - - out.fMinimumIntegerDigits = 0; - out.fMaximumIntegerDigits = kDoubleIntegerDigits; - out.fMinimumFractionDigits = 0; - out.fMaximumFractionDigits = kDoubleFractionDigits; - - out.fUseExponentialNotation = FALSE; - out.fCurrencySignCount = fgCurrencySignCountZero; - out.fGroupingUsed = FALSE; - out.fGroupingSize = 0; - out.fGroupingSize2 = 0; - out.fMultiplier = 1; - out.fDecimalSeparatorAlwaysShown = FALSE; - out.fFormatWidth = 0; - out.fRoundingIncrementUsed = FALSE; - } - - // If there was no negative pattern, or if the negative pattern is - // identical to the positive pattern, then prepend the minus sign to the - // positive pattern to form the negative pattern. - if (out.fNegPatternsBogus || - (out.fNegPrefixPattern == out.fPosPrefixPattern - && out.fNegSuffixPattern == out.fPosSuffixPattern)) { - out.fNegPatternsBogus = FALSE; - out.fNegSuffixPattern = out.fPosSuffixPattern; - out.fNegPrefixPattern.remove(); - out.fNegPrefixPattern.append(kQuote).append(kPatternMinus) - .append(out.fPosPrefixPattern); - } - // TODO: Deprecate/Remove out.fNegSuffixPattern and 3 other fields. - AffixPattern::parseAffixString( - out.fNegSuffixPattern, out.fNegSuffixAffix, status); - AffixPattern::parseAffixString( - out.fPosSuffixPattern, out.fPosSuffixAffix, status); - AffixPattern::parseAffixString( - out.fNegPrefixPattern, out.fNegPrefixAffix, status); - AffixPattern::parseAffixString( - out.fPosPrefixPattern, out.fPosPrefixAffix, status); -} - -U_NAMESPACE_END - -#endif /* !UCONFIG_NO_FORMATTING */ diff --git a/deps/icu-small/source/i18n/decimalformatpattern.h b/deps/icu-small/source/i18n/decimalformatpattern.h deleted file mode 100644 index 1c297575ead..00000000000 --- a/deps/icu-small/source/i18n/decimalformatpattern.h +++ /dev/null @@ -1,106 +0,0 @@ -// © 2016 and later: Unicode, Inc. and others. -// License & terms of use: http://www.unicode.org/copyright.html -/* -******************************************************************************* -* Copyright (C) 1997-2015, International Business Machines Corporation and * -* others. All Rights Reserved. * -******************************************************************************* -*/ -#ifndef _DECIMAL_FORMAT_PATTERN -#define _DECIMAL_FORMAT_PATTERN - -#include "unicode/utypes.h" - -#if !UCONFIG_NO_FORMATTING - -#include "unicode/uobject.h" -#include "unicode/unistr.h" -#include "digitlst.h" -#include "affixpatternparser.h" - -U_NAMESPACE_BEGIN - -// currency sign count -enum CurrencySignCount { - fgCurrencySignCountZero, - fgCurrencySignCountInSymbolFormat, - fgCurrencySignCountInISOFormat, - fgCurrencySignCountInPluralFormat -}; - -class DecimalFormatSymbols; - -struct DecimalFormatPattern : public UMemory { - enum EPadPosition { - kPadBeforePrefix, - kPadAfterPrefix, - kPadBeforeSuffix, - kPadAfterSuffix - }; - - DecimalFormatPattern(); - - int32_t fMinimumIntegerDigits; - int32_t fMaximumIntegerDigits; - int32_t fMinimumFractionDigits; - int32_t fMaximumFractionDigits; - UBool fUseSignificantDigits; - int32_t fMinimumSignificantDigits; - int32_t fMaximumSignificantDigits; - UBool fUseExponentialNotation; - int32_t fMinExponentDigits; - UBool fExponentSignAlwaysShown; - int32_t fCurrencySignCount; - UBool fGroupingUsed; - int32_t fGroupingSize; - int32_t fGroupingSize2; - int32_t fMultiplier; - UBool fDecimalSeparatorAlwaysShown; - int32_t fFormatWidth; - UBool fRoundingIncrementUsed; - DigitList fRoundingIncrement; - UChar32 fPad; - UBool fNegPatternsBogus; - UBool fPosPatternsBogus; - UnicodeString fNegPrefixPattern; - UnicodeString fNegSuffixPattern; - UnicodeString fPosPrefixPattern; - UnicodeString fPosSuffixPattern; - AffixPattern fNegPrefixAffix; - AffixPattern fNegSuffixAffix; - AffixPattern fPosPrefixAffix; - AffixPattern fPosSuffixAffix; - EPadPosition fPadPosition; -}; - -class DecimalFormatPatternParser : public UMemory { - public: - DecimalFormatPatternParser(); - void useSymbols(const DecimalFormatSymbols& symbols); - - void applyPatternWithoutExpandAffix( - const UnicodeString& pattern, - DecimalFormatPattern& out, - UParseError& parseError, - UErrorCode& status); - private: - DecimalFormatPatternParser(const DecimalFormatPatternParser&); - DecimalFormatPatternParser& operator=(DecimalFormatPatternParser& rhs); - UChar32 fZeroDigit; - UChar32 fSigDigit; - UnicodeString fGroupingSeparator; - UnicodeString fDecimalSeparator; - UnicodeString fPercent; - UnicodeString fPerMill; - UnicodeString fDigit; - UnicodeString fSeparator; - UnicodeString fExponent; - UnicodeString fPlus; - UnicodeString fMinus; - UnicodeString fPadEscape; -}; - -U_NAMESPACE_END - -#endif /* !UCONFIG_NO_FORMATTING */ -#endif diff --git a/deps/icu-small/source/i18n/decimalformatpatternimpl.h b/deps/icu-small/source/i18n/decimalformatpatternimpl.h deleted file mode 100644 index 8cecc8cca02..00000000000 --- a/deps/icu-small/source/i18n/decimalformatpatternimpl.h +++ /dev/null @@ -1,35 +0,0 @@ -// © 2016 and later: Unicode, Inc. and others. -// License & terms of use: http://www.unicode.org/copyright.html -/* -******************************************************************************** -* Copyright (C) 2015, International Business Machines -* Corporation and others. All Rights Reserved. -******************************************************************************** -* -* File decimalformatpatternimpl.h -******************************************************************************** -*/ - -#ifndef DECIMALFORMATPATTERNIMPL_H -#define DECIMALFORMATPATTERNIMPL_H - -#include "unicode/utypes.h" - -#define kPatternZeroDigit ((UChar)0x0030) /*'0'*/ -#define kPatternSignificantDigit ((UChar)0x0040) /*'@'*/ -#define kPatternGroupingSeparator ((UChar)0x002C) /*','*/ -#define kPatternDecimalSeparator ((UChar)0x002E) /*'.'*/ -#define kPatternPerMill ((UChar)0x2030) -#define kPatternPercent ((UChar)0x0025) /*'%'*/ -#define kPatternDigit ((UChar)0x0023) /*'#'*/ -#define kPatternSeparator ((UChar)0x003B) /*';'*/ -#define kPatternExponent ((UChar)0x0045) /*'E'*/ -#define kPatternPlus ((UChar)0x002B) /*'+'*/ -#define kPatternMinus ((UChar)0x002D) /*'-'*/ -#define kPatternPadEscape ((UChar)0x002A) /*'*'*/ -#define kQuote ((UChar)0x0027) /*'\''*/ - -#define kCurrencySign ((UChar)0x00A4) -#define kDefaultPad ((UChar)0x0020) /* */ - -#endif diff --git a/deps/icu-small/source/i18n/decimfmt.cpp b/deps/icu-small/source/i18n/decimfmt.cpp index 80a9446e146..a2638bb7429 100644 --- a/deps/icu-small/source/i18n/decimfmt.cpp +++ b/deps/icu-small/source/i18n/decimfmt.cpp @@ -1,3295 +1,1383 @@ -// © 2016 and later: Unicode, Inc. and others. +// © 2018 and later: Unicode, Inc. and others. // License & terms of use: http://www.unicode.org/copyright.html -/* -******************************************************************************* -* Copyright (C) 1997-2015, International Business Machines Corporation and * -* others. All Rights Reserved. * -******************************************************************************* -* -* File DECIMFMT.CPP -* -* Modification History: -* -* Date Name Description -* 02/19/97 aliu Converted from java. -* 03/20/97 clhuang Implemented with new APIs. -* 03/31/97 aliu Moved isLONG_MIN to DigitList, and fixed it. -* 04/3/97 aliu Rewrote parsing and formatting completely, and -* cleaned up and debugged. Actually works now. -* Implemented NAN and INF handling, for both parsing -* and formatting. Extensive testing & debugging. -* 04/10/97 aliu Modified to compile on AIX. -* 04/16/97 aliu Rewrote to use DigitList, which has been resurrected. -* Changed DigitCount to int per code review. -* 07/09/97 helena Made ParsePosition into a class. -* 08/26/97 aliu Extensive changes to applyPattern; completely -* rewritten from the Java. -* 09/09/97 aliu Ported over support for exponential formats. -* 07/20/98 stephen JDK 1.2 sync up. -* Various instances of '0' replaced with 'NULL' -* Check for grouping size in subFormat() -* Brought subParse() in line with Java 1.2 -* Added method appendAffix() -* 08/24/1998 srl Removed Mutex calls. This is not a thread safe class! -* 02/22/99 stephen Removed character literals for EBCDIC safety -* 06/24/99 helena Integrated Alan's NF enhancements and Java2 bug fixes -* 06/28/99 stephen Fixed bugs in toPattern(). -* 06/29/99 stephen Fixed operator= to copy fFormatWidth, fPad, -* fPadPosition -******************************************************************************** -*/ #include "unicode/utypes.h" #if !UCONFIG_NO_FORMATTING -#include "unicode/uniset.h" -#include "unicode/currpinf.h" -#include "unicode/plurrule.h" -#include "unicode/utf16.h" -#include "unicode/numsys.h" -#include "unicode/localpointer.h" -#include "unicode/ustring.h" -#include "uresimp.h" -#include "ucurrimp.h" -#include "charstr.h" -#include "patternprops.h" -#include "cstring.h" -#include "uassert.h" -#include "hash.h" -#include "decfmtst.h" -#include "plurrule_impl.h" -#include "decimalformatpattern.h" -#include "fmtableimp.h" -#include "decimfmtimpl.h" -#include "visibledigits.h" +// Allow implicit conversion from char16_t* to UnicodeString for this file: +// Helpful in toString methods and elsewhere. +#define UNISTR_FROM_STRING_EXPLICIT -/* - * On certain platforms, round is a macro defined in math.h - * This undefine is to avoid conflict between the macro and - * the function defined below. - */ -#ifdef round -#undef round -#endif +#include +#include +#include +#include "unicode/errorcode.h" +#include "unicode/decimfmt.h" +#include "number_decimalquantity.h" +#include "number_types.h" +#include "numparse_impl.h" +#include "number_mapper.h" +#include "number_patternstring.h" +#include "putilimp.h" +#include "number_utils.h" +#include "number_utypes.h" +using namespace icu; +using namespace icu::number; +using namespace icu::number::impl; +using namespace icu::numparse; +using namespace icu::numparse::impl; +using ERoundingMode = icu::DecimalFormat::ERoundingMode; +using EPadPosition = icu::DecimalFormat::EPadPosition; -U_NAMESPACE_BEGIN - -#ifdef FMT_DEBUG -#include -static void _debugout(const char *f, int l, const UnicodeString& s) { - char buf[2000]; - s.extract((int32_t) 0, s.length(), buf, "utf-8"); - printf("%s:%d: %s\n", f,l, buf); -} -#define debugout(x) _debugout(__FILE__,__LINE__,x) -#define debug(x) printf("%s:%d: %s\n", __FILE__,__LINE__, x); -static const UnicodeString dbg_null("",""); -#define DEREFSTR(x) ((x!=NULL)?(*x):(dbg_null)) +// MSVC warns C4805 when comparing bool with UBool +// TODO: Move this macro into a better place? +#if U_PF_WINDOWS <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN +#define UBOOL_TO_BOOL(b) static_cast(b) #else -#define debugout(x) -#define debug(x) +#define UBOOL_TO_BOOL(b) b #endif -/* For currency parsing purose, - * Need to remember all prefix patterns and suffix patterns of - * every currency format pattern, - * including the pattern of default currecny style - * and plural currency style. And the patterns are set through applyPattern. - */ -struct AffixPatternsForCurrency : public UMemory { - // negative prefix pattern - UnicodeString negPrefixPatternForCurrency; - // negative suffix pattern - UnicodeString negSuffixPatternForCurrency; - // positive prefix pattern - UnicodeString posPrefixPatternForCurrency; - // positive suffix pattern - UnicodeString posSuffixPatternForCurrency; - int8_t patternType; - - AffixPatternsForCurrency(const UnicodeString& negPrefix, - const UnicodeString& negSuffix, - const UnicodeString& posPrefix, - const UnicodeString& posSuffix, - int8_t type) { - negPrefixPatternForCurrency = negPrefix; - negSuffixPatternForCurrency = negSuffix; - posPrefixPatternForCurrency = posPrefix; - posSuffixPatternForCurrency = posSuffix; - patternType = type; - } -#ifdef FMT_DEBUG - void dump() const { - debugout( UnicodeString("AffixPatternsForCurrency( -=\"") + - negPrefixPatternForCurrency + (UnicodeString)"\"/\"" + - negSuffixPatternForCurrency + (UnicodeString)"\" +=\"" + - posPrefixPatternForCurrency + (UnicodeString)"\"/\"" + - posSuffixPatternForCurrency + (UnicodeString)"\" )"); - } -#endif -}; - -/* affix for currency formatting when the currency sign in the pattern - * equals to 3, such as the pattern contains 3 currency sign or - * the formatter style is currency plural format style. - */ -struct AffixesForCurrency : public UMemory { - // negative prefix - UnicodeString negPrefixForCurrency; - // negative suffix - UnicodeString negSuffixForCurrency; - // positive prefix - UnicodeString posPrefixForCurrency; - // positive suffix - UnicodeString posSuffixForCurrency; - - int32_t formatWidth; - - AffixesForCurrency(const UnicodeString& negPrefix, - const UnicodeString& negSuffix, - const UnicodeString& posPrefix, - const UnicodeString& posSuffix) { - negPrefixForCurrency = negPrefix; - negSuffixForCurrency = negSuffix; - posPrefixForCurrency = posPrefix; - posSuffixForCurrency = posSuffix; - } -#ifdef FMT_DEBUG - void dump() const { - debugout( UnicodeString("AffixesForCurrency( -=\"") + - negPrefixForCurrency + (UnicodeString)"\"/\"" + - negSuffixForCurrency + (UnicodeString)"\" +=\"" + - posPrefixForCurrency + (UnicodeString)"\"/\"" + - posSuffixForCurrency + (UnicodeString)"\" )"); - } -#endif -}; - -U_CDECL_BEGIN - -/** - * @internal ICU 4.2 - */ -static UBool U_CALLCONV decimfmtAffixPatternValueComparator(UHashTok val1, UHashTok val2); - - -static UBool -U_CALLCONV decimfmtAffixPatternValueComparator(UHashTok val1, UHashTok val2) { - const AffixPatternsForCurrency* affix_1 = - (AffixPatternsForCurrency*)val1.pointer; - const AffixPatternsForCurrency* affix_2 = - (AffixPatternsForCurrency*)val2.pointer; - return affix_1->negPrefixPatternForCurrency == - affix_2->negPrefixPatternForCurrency && - affix_1->negSuffixPatternForCurrency == - affix_2->negSuffixPatternForCurrency && - affix_1->posPrefixPatternForCurrency == - affix_2->posPrefixPatternForCurrency && - affix_1->posSuffixPatternForCurrency == - affix_2->posSuffixPatternForCurrency && - affix_1->patternType == affix_2->patternType; -} - -U_CDECL_END - - - - -// ***************************************************************************** -// class DecimalFormat -// ***************************************************************************** - UOBJECT_DEFINE_RTTI_IMPLEMENTATION(DecimalFormat) -// Constants for characters used in programmatic (unlocalized) patterns. -#define kPatternZeroDigit ((UChar)0x0030) /*'0'*/ -#define kPatternSignificantDigit ((UChar)0x0040) /*'@'*/ -#define kPatternGroupingSeparator ((UChar)0x002C) /*','*/ -#define kPatternDecimalSeparator ((UChar)0x002E) /*'.'*/ -#define kPatternPerMill ((UChar)0x2030) -#define kPatternPercent ((UChar)0x0025) /*'%'*/ -#define kPatternDigit ((UChar)0x0023) /*'#'*/ -#define kPatternSeparator ((UChar)0x003B) /*';'*/ -#define kPatternExponent ((UChar)0x0045) /*'E'*/ -#define kPatternPlus ((UChar)0x002B) /*'+'*/ -#define kPatternMinus ((UChar)0x002D) /*'-'*/ -#define kPatternPadEscape ((UChar)0x002A) /*'*'*/ -#define kQuote ((UChar)0x0027) /*'\''*/ -/** - * The CURRENCY_SIGN is the standard Unicode symbol for currency. It - * is used in patterns and substitued with either the currency symbol, - * or if it is doubled, with the international currency symbol. If the - * CURRENCY_SIGN is seen in a pattern, then the decimal separator is - * replaced with the monetary decimal separator. - */ -#define kCurrencySign ((UChar)0x00A4) -#define kDefaultPad ((UChar)0x0020) /* */ -const int32_t DecimalFormat::kDoubleIntegerDigits = 309; -const int32_t DecimalFormat::kDoubleFractionDigits = 340; - -const int32_t DecimalFormat::kMaxScientificIntegerDigits = 8; - -/** - * These are the tags we expect to see in normal resource bundle files associated - * with a locale. - */ -const char DecimalFormat::fgNumberPatterns[]="NumberPatterns"; // Deprecated - not used -static const char fgNumberElements[]="NumberElements"; -static const char fgLatn[]="latn"; -static const char fgPatterns[]="patterns"; -static const char fgDecimalFormat[]="decimalFormat"; -static const char fgCurrencyFormat[]="currencyFormat"; - -inline int32_t _min(int32_t a, int32_t b) { return (a ns(NumberingSystem::createInstance(status)); + UnicodeString patternString = utils::getPatternForStyle( + localeName, + ns->getName(), + CLDR_PATTERN_STYLE_DECIMAL, + status); + setPropertiesFromPattern(patternString, IGNORE_ROUNDING_IF_CURRENCY, status); + touch(status); } -//------------------------------------------------------------------------------ -// Constructs a DecimalFormat instance with the specified number format -// pattern in the default locale. - -DecimalFormat::DecimalFormat(const UnicodeString& pattern, - UErrorCode& status) { - init(); - UParseError parseError; - construct(status, parseError, &pattern); +DecimalFormat::DecimalFormat(const UnicodeString& pattern, UErrorCode& status) + : DecimalFormat(nullptr, status) { + setPropertiesFromPattern(pattern, IGNORE_ROUNDING_IF_CURRENCY, status); + touch(status); } -//------------------------------------------------------------------------------ -// Constructs a DecimalFormat instance with the specified number format -// pattern and the number format symbols in the default locale. The -// created instance owns the symbols. - -DecimalFormat::DecimalFormat(const UnicodeString& pattern, - DecimalFormatSymbols* symbolsToAdopt, - UErrorCode& status) { - init(); - UParseError parseError; - if (symbolsToAdopt == NULL) - status = U_ILLEGAL_ARGUMENT_ERROR; - construct(status, parseError, &pattern, symbolsToAdopt); +DecimalFormat::DecimalFormat(const UnicodeString& pattern, DecimalFormatSymbols* symbolsToAdopt, + UErrorCode& status) + : DecimalFormat(symbolsToAdopt, status) { + setPropertiesFromPattern(pattern, IGNORE_ROUNDING_IF_CURRENCY, status); + touch(status); } -DecimalFormat::DecimalFormat( const UnicodeString& pattern, - DecimalFormatSymbols* symbolsToAdopt, - UParseError& parseErr, - UErrorCode& status) { - init(); - if (symbolsToAdopt == NULL) - status = U_ILLEGAL_ARGUMENT_ERROR; - construct(status,parseErr, &pattern, symbolsToAdopt); +DecimalFormat::DecimalFormat(const UnicodeString& pattern, DecimalFormatSymbols* symbolsToAdopt, + UNumberFormatStyle style, UErrorCode& status) + : DecimalFormat(symbolsToAdopt, status) { + // If choice is a currency type, ignore the rounding information. + if (style == UNumberFormatStyle::UNUM_CURRENCY || style == UNumberFormatStyle::UNUM_CURRENCY_ISO || + style == UNumberFormatStyle::UNUM_CURRENCY_ACCOUNTING || + style == UNumberFormatStyle::UNUM_CASH_CURRENCY || + style == UNumberFormatStyle::UNUM_CURRENCY_STANDARD || + style == UNumberFormatStyle::UNUM_CURRENCY_PLURAL) { + setPropertiesFromPattern(pattern, IGNORE_ROUNDING_ALWAYS, status); + } else { + setPropertiesFromPattern(pattern, IGNORE_ROUNDING_IF_CURRENCY, status); + } + // Note: in Java, CurrencyPluralInfo is set in NumberFormat.java, but in C++, it is not set there, + // so we have to set it here. + if (style == UNumberFormatStyle::UNUM_CURRENCY_PLURAL) { + LocalPointer cpi( + new CurrencyPluralInfo(fields->symbols->getLocale(), status), + status); + if (U_FAILURE(status)) { return; } + fields->properties->currencyPluralInfo.fPtr.adoptInstead(cpi.orphan()); + } + touch(status); } -//------------------------------------------------------------------------------ -// Constructs a DecimalFormat instance with the specified number format -// pattern and the number format symbols in the default locale. The -// created instance owns the clone of the symbols. - -DecimalFormat::DecimalFormat(const UnicodeString& pattern, - const DecimalFormatSymbols& symbols, - UErrorCode& status) { - init(); - UParseError parseError; - construct(status, parseError, &pattern, new DecimalFormatSymbols(symbols)); +DecimalFormat::DecimalFormat(const DecimalFormatSymbols* symbolsToAdopt, UErrorCode& status) { + LocalPointer adoptedSymbols(symbolsToAdopt); + fields = new DecimalFormatFields(); + if (U_FAILURE(status)) { + return; + } + if (fields == nullptr) { + status = U_MEMORY_ALLOCATION_ERROR; + return; + } + fields->properties.adoptInsteadAndCheckErrorCode(new DecimalFormatProperties(), status); + fields->exportedProperties.adoptInsteadAndCheckErrorCode(new DecimalFormatProperties(), status); + if (adoptedSymbols.isNull()) { + fields->symbols.adoptInsteadAndCheckErrorCode(new DecimalFormatSymbols(status), status); + } else { + fields->symbols.adoptInsteadAndCheckErrorCode(adoptedSymbols.orphan(), status); + } } -//------------------------------------------------------------------------------ -// Constructs a DecimalFormat instance with the specified number format -// pattern, the number format symbols, and the number format style. -// The created instance owns the clone of the symbols. - -DecimalFormat::DecimalFormat(const UnicodeString& pattern, - DecimalFormatSymbols* symbolsToAdopt, - UNumberFormatStyle style, - UErrorCode& status) { - init(); - fStyle = style; - UParseError parseError; - construct(status, parseError, &pattern, symbolsToAdopt); -} - -//----------------------------------------------------------------------------- -// Common DecimalFormat initialization. -// Put all fields of an uninitialized object into a known state. -// Common code, shared by all constructors. -// Can not fail. Leave the object in good enough shape that the destructor -// or assignment operator can run successfully. -void -DecimalFormat::init() { - fBoolFlags.clear(); - fStyle = UNUM_DECIMAL; - fAffixPatternsForCurrency = NULL; - fCurrencyPluralInfo = NULL; #if UCONFIG_HAVE_PARSEALLINPUT - fParseAllInput = UNUM_MAYBE; + +void DecimalFormat::setParseAllInput(UNumberFormatAttributeValue value) { + if (value == fields->properties->parseAllInput) { return; } + fields->properties->parseAllInput = value; +} + #endif - fStaticSets = NULL; - fImpl = NULL; -} - -//------------------------------------------------------------------------------ -// Constructs a DecimalFormat instance with the specified number format -// pattern and the number format symbols in the desired locale. The -// created instance owns the symbols. - -void -DecimalFormat::construct(UErrorCode& status, - UParseError& parseErr, - const UnicodeString* pattern, - DecimalFormatSymbols* symbolsToAdopt) -{ - LocalPointer adoptedSymbols(symbolsToAdopt); - if (U_FAILURE(status)) - return; - - if (adoptedSymbols.isNull()) - { - adoptedSymbols.adoptInstead( - new DecimalFormatSymbols(Locale::getDefault(), status)); - if (adoptedSymbols.isNull() && U_SUCCESS(status)) { - status = U_MEMORY_ALLOCATION_ERROR; - } - if (U_FAILURE(status)) { - return; - } - } - fStaticSets = DecimalFormatStaticSets::getStaticSets(status); - if (U_FAILURE(status)) { - return; - } - - UnicodeString str; - // Uses the default locale's number format pattern if there isn't - // one specified. - if (pattern == NULL) - { - UErrorCode nsStatus = U_ZERO_ERROR; - LocalPointer ns( - NumberingSystem::createInstance(nsStatus)); - if (U_FAILURE(nsStatus)) { - status = nsStatus; - return; - } - - int32_t len = 0; - UResourceBundle *top = ures_open(NULL, Locale::getDefault().getName(), &status); - - UResourceBundle *resource = ures_getByKeyWithFallback(top, fgNumberElements, NULL, &status); - resource = ures_getByKeyWithFallback(resource, ns->getName(), resource, &status); - resource = ures_getByKeyWithFallback(resource, fgPatterns, resource, &status); - const UChar *resStr = ures_getStringByKeyWithFallback(resource, fgDecimalFormat, &len, &status); - if ( status == U_MISSING_RESOURCE_ERROR && uprv_strcmp(fgLatn,ns->getName())) { - status = U_ZERO_ERROR; - resource = ures_getByKeyWithFallback(top, fgNumberElements, resource, &status); - resource = ures_getByKeyWithFallback(resource, fgLatn, resource, &status); - resource = ures_getByKeyWithFallback(resource, fgPatterns, resource, &status); - resStr = ures_getStringByKeyWithFallback(resource, fgDecimalFormat, &len, &status); - } - str.setTo(TRUE, resStr, len); - pattern = &str; - ures_close(resource); - ures_close(top); - } - - fImpl = new DecimalFormatImpl(this, *pattern, adoptedSymbols.getAlias(), parseErr, status); - if (fImpl) { - adoptedSymbols.orphan(); - } else if (U_SUCCESS(status)) { - status = U_MEMORY_ALLOCATION_ERROR; - } - if (U_FAILURE(status)) { - return; - } - - if (U_FAILURE(status)) - { - return; - } - - const UnicodeString* patternUsed; - UnicodeString currencyPluralPatternForOther; - // apply pattern - if (fStyle == UNUM_CURRENCY_PLURAL) { - fCurrencyPluralInfo = new CurrencyPluralInfo(fImpl->fSymbols->getLocale(), status); - if (U_FAILURE(status)) { - return; - } - - // the pattern used in format is not fixed until formatting, - // in which, the number is known and - // will be used to pick the right pattern based on plural count. - // Here, set the pattern as the pattern of plural count == "other". - // For most locale, the patterns are probably the same for all - // plural count. If not, the right pattern need to be re-applied - // during format. - fCurrencyPluralInfo->getCurrencyPluralPattern(UNICODE_STRING("other", 5), currencyPluralPatternForOther); - // TODO(refactor): Revisit, we are setting the pattern twice. - fImpl->applyPatternFavorCurrencyPrecision( - currencyPluralPatternForOther, status); - patternUsed = ¤cyPluralPatternForOther; - - } else { - patternUsed = pattern; - } - - if (patternUsed->indexOf(kCurrencySign) != -1) { - // initialize for currency, not only for plural format, - // but also for mix parsing - handleCurrencySignInPattern(status); - } -} - -void -DecimalFormat::handleCurrencySignInPattern(UErrorCode& status) { - // initialize for currency, not only for plural format, - // but also for mix parsing - if (U_FAILURE(status)) { - return; - } - if (fCurrencyPluralInfo == NULL) { - fCurrencyPluralInfo = new CurrencyPluralInfo(fImpl->fSymbols->getLocale(), status); - if (U_FAILURE(status)) { - return; - } - } - // need it for mix parsing - if (fAffixPatternsForCurrency == NULL) { - setupCurrencyAffixPatterns(status); - } -} - -static void -applyPatternWithNoSideEffects( - const UnicodeString& pattern, - UParseError& parseError, - UnicodeString &negPrefix, - UnicodeString &negSuffix, - UnicodeString &posPrefix, - UnicodeString &posSuffix, - UErrorCode& status) { - if (U_FAILURE(status)) - { - return; - } - DecimalFormatPatternParser patternParser; - DecimalFormatPattern out; - patternParser.applyPatternWithoutExpandAffix( - pattern, - out, - parseError, - status); - if (U_FAILURE(status)) { - return; - } - negPrefix = out.fNegPrefixPattern; - negSuffix = out.fNegSuffixPattern; - posPrefix = out.fPosPrefixPattern; - posSuffix = out.fPosSuffixPattern; -} - -void -DecimalFormat::setupCurrencyAffixPatterns(UErrorCode& status) { - if (U_FAILURE(status)) { - return; - } - UParseError parseErr; - fAffixPatternsForCurrency = initHashForAffixPattern(status); - if (U_FAILURE(status)) { - return; - } - - NumberingSystem *ns = NumberingSystem::createInstance(fImpl->fSymbols->getLocale(),status); - if (U_FAILURE(status)) { - return; - } - - // Save the default currency patterns of this locale. - // Here, chose onlyApplyPatternWithoutExpandAffix without - // expanding the affix patterns into affixes. - UnicodeString currencyPattern; - UErrorCode error = U_ZERO_ERROR; - - UResourceBundle *resource = ures_open(NULL, fImpl->fSymbols->getLocale().getName(), &error); - UResourceBundle *numElements = ures_getByKeyWithFallback(resource, fgNumberElements, NULL, &error); - resource = ures_getByKeyWithFallback(numElements, ns->getName(), resource, &error); - resource = ures_getByKeyWithFallback(resource, fgPatterns, resource, &error); - int32_t patLen = 0; - const UChar *patResStr = ures_getStringByKeyWithFallback(resource, fgCurrencyFormat, &patLen, &error); - if ( error == U_MISSING_RESOURCE_ERROR && uprv_strcmp(ns->getName(),fgLatn)) { - error = U_ZERO_ERROR; - resource = ures_getByKeyWithFallback(numElements, fgLatn, resource, &error); - resource = ures_getByKeyWithFallback(resource, fgPatterns, resource, &error); - patResStr = ures_getStringByKeyWithFallback(resource, fgCurrencyFormat, &patLen, &error); - } - ures_close(numElements); - ures_close(resource); - delete ns; - - if (U_SUCCESS(error)) { - UnicodeString negPrefix; - UnicodeString negSuffix; - UnicodeString posPrefix; - UnicodeString posSuffix; - applyPatternWithNoSideEffects(UnicodeString(patResStr, patLen), - parseErr, - negPrefix, negSuffix, posPrefix, posSuffix, status); - AffixPatternsForCurrency* affixPtn = new AffixPatternsForCurrency( - negPrefix, - negSuffix, - posPrefix, - posSuffix, - UCURR_SYMBOL_NAME); - fAffixPatternsForCurrency->put(UNICODE_STRING("default", 7), affixPtn, status); - } - - // save the unique currency plural patterns of this locale. - Hashtable* pluralPtn = fCurrencyPluralInfo->fPluralCountToCurrencyUnitPattern; - const UHashElement* element = NULL; - int32_t pos = UHASH_FIRST; - Hashtable pluralPatternSet; - while ((element = pluralPtn->nextElement(pos)) != NULL) { - const UHashTok valueTok = element->value; - const UnicodeString* value = (UnicodeString*)valueTok.pointer; - const UHashTok keyTok = element->key; - const UnicodeString* key = (UnicodeString*)keyTok.pointer; - if (pluralPatternSet.geti(*value) != 1) { - UnicodeString negPrefix; - UnicodeString negSuffix; - UnicodeString posPrefix; - UnicodeString posSuffix; - pluralPatternSet.puti(*value, 1, status); - applyPatternWithNoSideEffects( - *value, parseErr, - negPrefix, negSuffix, posPrefix, posSuffix, status); - AffixPatternsForCurrency* affixPtn = new AffixPatternsForCurrency( - negPrefix, - negSuffix, - posPrefix, - posSuffix, - UCURR_LONG_NAME); - fAffixPatternsForCurrency->put(*key, affixPtn, status); - } - } -} - - -//------------------------------------------------------------------------------ - -DecimalFormat::~DecimalFormat() -{ - deleteHashForAffixPattern(); - delete fCurrencyPluralInfo; - delete fImpl; -} - -//------------------------------------------------------------------------------ -// copy constructor - -DecimalFormat::DecimalFormat(const DecimalFormat &source) : - NumberFormat(source) { - init(); - *this = source; -} - -//------------------------------------------------------------------------------ -// assignment operator - -template -static void _clone_ptr(T** pdest, const T* source) { - delete *pdest; - if (source == NULL) { - *pdest = NULL; - } else { - *pdest = static_cast(source->clone()); - } -} - DecimalFormat& -DecimalFormat::operator=(const DecimalFormat& rhs) -{ - if(this != &rhs) { - UErrorCode status = U_ZERO_ERROR; - NumberFormat::operator=(rhs); - if (fImpl == NULL) { - fImpl = new DecimalFormatImpl(this, *rhs.fImpl, status); - } else { - fImpl->assign(*rhs.fImpl, status); - } - fStaticSets = DecimalFormatStaticSets::getStaticSets(status); - fStyle = rhs.fStyle; - _clone_ptr(&fCurrencyPluralInfo, rhs.fCurrencyPluralInfo); - deleteHashForAffixPattern(); - if (rhs.fAffixPatternsForCurrency) { - UErrorCode status = U_ZERO_ERROR; - fAffixPatternsForCurrency = initHashForAffixPattern(status); - copyHashForAffixPattern(rhs.fAffixPatternsForCurrency, - fAffixPatternsForCurrency, status); - } - } +DecimalFormat::setAttribute(UNumberFormatAttribute attr, int32_t newValue, UErrorCode& status) { + if (U_FAILURE(status)) { return *this; } + switch (attr) { + case UNUM_LENIENT_PARSE: + setLenient(newValue != 0); + break; + + case UNUM_PARSE_INT_ONLY: + setParseIntegerOnly(newValue != 0); + break; + + case UNUM_GROUPING_USED: + setGroupingUsed(newValue != 0); + break; + + case UNUM_DECIMAL_ALWAYS_SHOWN: + setDecimalSeparatorAlwaysShown(newValue != 0); + break; + + case UNUM_MAX_INTEGER_DIGITS: + setMaximumIntegerDigits(newValue); + break; + + case UNUM_MIN_INTEGER_DIGITS: + setMinimumIntegerDigits(newValue); + break; + + case UNUM_INTEGER_DIGITS: + setMinimumIntegerDigits(newValue); + setMaximumIntegerDigits(newValue); + break; + + case UNUM_MAX_FRACTION_DIGITS: + setMaximumFractionDigits(newValue); + break; + + case UNUM_MIN_FRACTION_DIGITS: + setMinimumFractionDigits(newValue); + break; + + case UNUM_FRACTION_DIGITS: + setMinimumFractionDigits(newValue); + setMaximumFractionDigits(newValue); + break; + + case UNUM_SIGNIFICANT_DIGITS_USED: + setSignificantDigitsUsed(newValue != 0); + break; + + case UNUM_MAX_SIGNIFICANT_DIGITS: + setMaximumSignificantDigits(newValue); + break; + + case UNUM_MIN_SIGNIFICANT_DIGITS: + setMinimumSignificantDigits(newValue); + break; + + case UNUM_MULTIPLIER: + setMultiplier(newValue); + break; + + case UNUM_SCALE: + setMultiplierScale(newValue); + break; + + case UNUM_GROUPING_SIZE: + setGroupingSize(newValue); + break; + + case UNUM_ROUNDING_MODE: + setRoundingMode((DecimalFormat::ERoundingMode) newValue); + break; + + case UNUM_FORMAT_WIDTH: + setFormatWidth(newValue); + break; + + case UNUM_PADDING_POSITION: + /** The position at which padding will take place. */ + setPadPosition((DecimalFormat::EPadPosition) newValue); + break; + + case UNUM_SECONDARY_GROUPING_SIZE: + setSecondaryGroupingSize(newValue); + break; + +#if UCONFIG_HAVE_PARSEALLINPUT + case UNUM_PARSE_ALL_INPUT: + setParseAllInput((UNumberFormatAttributeValue) newValue); + break; +#endif + + case UNUM_PARSE_NO_EXPONENT: + setParseNoExponent((UBool) newValue); + break; + + case UNUM_PARSE_DECIMAL_MARK_REQUIRED: + setDecimalPatternMatchRequired((UBool) newValue); + break; + + case UNUM_CURRENCY_USAGE: + setCurrencyUsage((UCurrencyUsage) newValue, &status); + break; + + case UNUM_MINIMUM_GROUPING_DIGITS: + setMinimumGroupingDigits(newValue); + break; + + case UNUM_PARSE_CASE_SENSITIVE: + setParseCaseSensitive(static_cast(newValue)); + break; + + case UNUM_SIGN_ALWAYS_SHOWN: + setSignAlwaysShown(static_cast(newValue)); + break; + + case UNUM_FORMAT_FAIL_IF_MORE_THAN_MAX_DIGITS: + setFormatFailIfMoreThanMaxDigits(static_cast(newValue)); + break; + + default: + status = U_UNSUPPORTED_ERROR; + break; + } return *this; } -//------------------------------------------------------------------------------ +int32_t DecimalFormat::getAttribute(UNumberFormatAttribute attr, UErrorCode& status) const { + if (U_FAILURE(status)) { return -1; } + switch (attr) { + case UNUM_LENIENT_PARSE: + return isLenient(); -UBool -DecimalFormat::operator==(const Format& that) const -{ - if (this == &that) - return TRUE; + case UNUM_PARSE_INT_ONLY: + return isParseIntegerOnly(); - // NumberFormat::operator== guarantees this cast is safe - const DecimalFormat* other = (DecimalFormat*)&that; + case UNUM_GROUPING_USED: + return isGroupingUsed(); - return ( - NumberFormat::operator==(that) && - fBoolFlags.getAll() == other->fBoolFlags.getAll() && - *fImpl == *other->fImpl); + case UNUM_DECIMAL_ALWAYS_SHOWN: + return isDecimalSeparatorAlwaysShown(); + case UNUM_MAX_INTEGER_DIGITS: + return getMaximumIntegerDigits(); + + case UNUM_MIN_INTEGER_DIGITS: + return getMinimumIntegerDigits(); + + case UNUM_INTEGER_DIGITS: + // TBD: what should this return? + return getMinimumIntegerDigits(); + + case UNUM_MAX_FRACTION_DIGITS: + return getMaximumFractionDigits(); + + case UNUM_MIN_FRACTION_DIGITS: + return getMinimumFractionDigits(); + + case UNUM_FRACTION_DIGITS: + // TBD: what should this return? + return getMinimumFractionDigits(); + + case UNUM_SIGNIFICANT_DIGITS_USED: + return areSignificantDigitsUsed(); + + case UNUM_MAX_SIGNIFICANT_DIGITS: + return getMaximumSignificantDigits(); + + case UNUM_MIN_SIGNIFICANT_DIGITS: + return getMinimumSignificantDigits(); + + case UNUM_MULTIPLIER: + return getMultiplier(); + + case UNUM_SCALE: + return getMultiplierScale(); + + case UNUM_GROUPING_SIZE: + return getGroupingSize(); + + case UNUM_ROUNDING_MODE: + return getRoundingMode(); + + case UNUM_FORMAT_WIDTH: + return getFormatWidth(); + + case UNUM_PADDING_POSITION: + return getPadPosition(); + + case UNUM_SECONDARY_GROUPING_SIZE: + return getSecondaryGroupingSize(); + + case UNUM_PARSE_NO_EXPONENT: + return isParseNoExponent(); + + case UNUM_PARSE_DECIMAL_MARK_REQUIRED: + return isDecimalPatternMatchRequired(); + + case UNUM_CURRENCY_USAGE: + return getCurrencyUsage(); + + case UNUM_MINIMUM_GROUPING_DIGITS: + return getMinimumGroupingDigits(); + + case UNUM_PARSE_CASE_SENSITIVE: + return isParseCaseSensitive(); + + case UNUM_SIGN_ALWAYS_SHOWN: + return isSignAlwaysShown(); + + case UNUM_FORMAT_FAIL_IF_MORE_THAN_MAX_DIGITS: + return isFormatFailIfMoreThanMaxDigits(); + + default: + status = U_UNSUPPORTED_ERROR; + break; + } + + return -1; /* undefined */ } -//------------------------------------------------------------------------------ +void DecimalFormat::setGroupingUsed(UBool enabled) { + if (UBOOL_TO_BOOL(enabled) == fields->properties->groupingUsed) { return; } + NumberFormat::setGroupingUsed(enabled); // to set field for compatibility + fields->properties->groupingUsed = enabled; + touchNoError(); +} -Format* -DecimalFormat::clone() const -{ +void DecimalFormat::setParseIntegerOnly(UBool value) { + if (UBOOL_TO_BOOL(value) == fields->properties->parseIntegerOnly) { return; } + NumberFormat::setParseIntegerOnly(value); // to set field for compatibility + fields->properties->parseIntegerOnly = value; + touchNoError(); +} + +void DecimalFormat::setLenient(UBool enable) { + ParseMode mode = enable ? PARSE_MODE_LENIENT : PARSE_MODE_STRICT; + if (!fields->properties->parseMode.isNull() && mode == fields->properties->parseMode.getNoError()) { return; } + NumberFormat::setLenient(enable); // to set field for compatibility + fields->properties->parseMode = mode; + touchNoError(); +} + +DecimalFormat::DecimalFormat(const UnicodeString& pattern, DecimalFormatSymbols* symbolsToAdopt, + UParseError&, UErrorCode& status) + : DecimalFormat(symbolsToAdopt, status) { + // TODO: What is parseError for? + setPropertiesFromPattern(pattern, IGNORE_ROUNDING_IF_CURRENCY, status); + touch(status); +} + +DecimalFormat::DecimalFormat(const UnicodeString& pattern, const DecimalFormatSymbols& symbols, + UErrorCode& status) + : DecimalFormat(new DecimalFormatSymbols(symbols), status) { + setPropertiesFromPattern(pattern, IGNORE_ROUNDING_IF_CURRENCY, status); + touch(status); +} + +DecimalFormat::DecimalFormat(const DecimalFormat& source) : NumberFormat(source) { + // Note: it is not safe to copy fields->formatter or fWarehouse directly because fields->formatter might have + // dangling pointers to fields inside fWarehouse. The safe thing is to re-construct fields->formatter from + // the property bag, despite being somewhat slower. + fields = new DecimalFormatFields(); + if (fields == nullptr) { + return; + } + fields->properties.adoptInstead(new DecimalFormatProperties(*source.fields->properties)); + fields->symbols.adoptInstead(new DecimalFormatSymbols(*source.fields->symbols)); + fields->exportedProperties.adoptInstead(new DecimalFormatProperties()); + if (fields->properties == nullptr || fields->symbols == nullptr || fields->exportedProperties == nullptr) { + return; + } + touchNoError(); +} + +DecimalFormat& DecimalFormat::operator=(const DecimalFormat& rhs) { + *fields->properties = *rhs.fields->properties; + fields->exportedProperties->clear(); + fields->symbols.adoptInstead(new DecimalFormatSymbols(*rhs.fields->symbols)); + touchNoError(); + return *this; +} + +DecimalFormat::~DecimalFormat() { + delete fields->atomicParser.exchange(nullptr); + delete fields->atomicCurrencyParser.exchange(nullptr); + delete fields; +} + +Format* DecimalFormat::clone() const { return new DecimalFormat(*this); } - -FixedDecimal -DecimalFormat::getFixedDecimal(double number, UErrorCode &status) const { - VisibleDigitsWithExponent digits; - initVisibleDigitsWithExponent(number, digits, status); - if (U_FAILURE(status)) { - return FixedDecimal(); +UBool DecimalFormat::operator==(const Format& other) const { + auto* otherDF = dynamic_cast(&other); + if (otherDF == nullptr) { + return false; } - return FixedDecimal(digits.getMantissa()); + return *fields->properties == *otherDF->fields->properties && *fields->symbols == *otherDF->fields->symbols; } -VisibleDigitsWithExponent & -DecimalFormat::initVisibleDigitsWithExponent( - double number, - VisibleDigitsWithExponent &digits, - UErrorCode &status) const { - return fImpl->initVisibleDigitsWithExponent(number, digits, status); -} - -FixedDecimal -DecimalFormat::getFixedDecimal(const Formattable &number, UErrorCode &status) const { - VisibleDigitsWithExponent digits; - initVisibleDigitsWithExponent(number, digits, status); - if (U_FAILURE(status)) { - return FixedDecimal(); +UnicodeString& DecimalFormat::format(double number, UnicodeString& appendTo, FieldPosition& pos) const { + if (pos.getField() == FieldPosition::DONT_CARE && fastFormatDouble(number, appendTo)) { + return appendTo; } - return FixedDecimal(digits.getMantissa()); + UErrorCode localStatus = U_ZERO_ERROR; + FormattedNumber output = fields->formatter->formatDouble(number, localStatus); + fieldPositionHelper(output, pos, appendTo.length(), localStatus); + auto appendable = UnicodeStringAppendable(appendTo); + output.appendTo(appendable); + return appendTo; } -VisibleDigitsWithExponent & -DecimalFormat::initVisibleDigitsWithExponent( - const Formattable &number, - VisibleDigitsWithExponent &digits, - UErrorCode &status) const { - if (U_FAILURE(status)) { - return digits; +UnicodeString& DecimalFormat::format(double number, UnicodeString& appendTo, FieldPosition& pos, + UErrorCode& status) const { + if (pos.getField() == FieldPosition::DONT_CARE && fastFormatDouble(number, appendTo)) { + return appendTo; } - if (!number.isNumeric()) { - status = U_ILLEGAL_ARGUMENT_ERROR; - return digits; + FormattedNumber output = fields->formatter->formatDouble(number, status); + fieldPositionHelper(output, pos, appendTo.length(), status); + auto appendable = UnicodeStringAppendable(appendTo); + output.appendTo(appendable); + return appendTo; +} + +UnicodeString& +DecimalFormat::format(double number, UnicodeString& appendTo, FieldPositionIterator* posIter, + UErrorCode& status) const { + if (posIter == nullptr && fastFormatDouble(number, appendTo)) { + return appendTo; } + FormattedNumber output = fields->formatter->formatDouble(number, status); + fieldPositionIteratorHelper(output, posIter, appendTo.length(), status); + auto appendable = UnicodeStringAppendable(appendTo); + output.appendTo(appendable); + return appendTo; +} - DigitList *dl = number.getDigitList(); - if (dl != NULL) { - DigitList dlCopy(*dl); - return fImpl->initVisibleDigitsWithExponent( - dlCopy, digits, status); +UnicodeString& DecimalFormat::format(int32_t number, UnicodeString& appendTo, FieldPosition& pos) const { + return format(static_cast (number), appendTo, pos); +} + +UnicodeString& DecimalFormat::format(int32_t number, UnicodeString& appendTo, FieldPosition& pos, + UErrorCode& status) const { + return format(static_cast (number), appendTo, pos, status); +} + +UnicodeString& +DecimalFormat::format(int32_t number, UnicodeString& appendTo, FieldPositionIterator* posIter, + UErrorCode& status) const { + return format(static_cast (number), appendTo, posIter, status); +} + +UnicodeString& DecimalFormat::format(int64_t number, UnicodeString& appendTo, FieldPosition& pos) const { + if (pos.getField() == FieldPosition::DONT_CARE && fastFormatInt64(number, appendTo)) { + return appendTo; } + UErrorCode localStatus = U_ZERO_ERROR; + FormattedNumber output = fields->formatter->formatInt(number, localStatus); + fieldPositionHelper(output, pos, appendTo.length(), localStatus); + auto appendable = UnicodeStringAppendable(appendTo); + output.appendTo(appendable); + return appendTo; +} - Formattable::Type type = number.getType(); - if (type == Formattable::kDouble || type == Formattable::kLong) { - return fImpl->initVisibleDigitsWithExponent( - number.getDouble(status), digits, status); +UnicodeString& DecimalFormat::format(int64_t number, UnicodeString& appendTo, FieldPosition& pos, + UErrorCode& status) const { + if (pos.getField() == FieldPosition::DONT_CARE && fastFormatInt64(number, appendTo)) { + return appendTo; } - return fImpl->initVisibleDigitsWithExponent( - number.getInt64(), digits, status); + FormattedNumber output = fields->formatter->formatInt(number, status); + fieldPositionHelper(output, pos, appendTo.length(), status); + auto appendable = UnicodeStringAppendable(appendTo); + output.appendTo(appendable); + return appendTo; } - -// Create a fixed decimal from a DigitList. -// The digit list may be modified. -// Internal function only. -FixedDecimal -DecimalFormat::getFixedDecimal(DigitList &number, UErrorCode &status) const { - VisibleDigitsWithExponent digits; - initVisibleDigitsWithExponent(number, digits, status); - if (U_FAILURE(status)) { - return FixedDecimal(); +UnicodeString& +DecimalFormat::format(int64_t number, UnicodeString& appendTo, FieldPositionIterator* posIter, + UErrorCode& status) const { + if (posIter == nullptr && fastFormatInt64(number, appendTo)) { + return appendTo; } - return FixedDecimal(digits.getMantissa()); -} - -VisibleDigitsWithExponent & -DecimalFormat::initVisibleDigitsWithExponent( - DigitList &number, - VisibleDigitsWithExponent &digits, - UErrorCode &status) const { - return fImpl->initVisibleDigitsWithExponent( - number, digits, status); -} - - -//------------------------------------------------------------------------------ - -UnicodeString& -DecimalFormat::format(int32_t number, - UnicodeString& appendTo, - FieldPosition& fieldPosition) const -{ - UErrorCode status = U_ZERO_ERROR; - return fImpl->format(number, appendTo, fieldPosition, status); + FormattedNumber output = fields->formatter->formatInt(number, status); + fieldPositionIteratorHelper(output, posIter, appendTo.length(), status); + auto appendable = UnicodeStringAppendable(appendTo); + output.appendTo(appendable); + return appendTo; } UnicodeString& -DecimalFormat::format(int32_t number, - UnicodeString& appendTo, - FieldPosition& fieldPosition, - UErrorCode& status) const -{ - return fImpl->format(number, appendTo, fieldPosition, status); +DecimalFormat::format(StringPiece number, UnicodeString& appendTo, FieldPositionIterator* posIter, + UErrorCode& status) const { + FormattedNumber output = fields->formatter->formatDecimal(number, status); + fieldPositionIteratorHelper(output, posIter, appendTo.length(), status); + auto appendable = UnicodeStringAppendable(appendTo); + output.appendTo(appendable); + return appendTo; +} + +UnicodeString& DecimalFormat::format(const DecimalQuantity& number, UnicodeString& appendTo, + FieldPositionIterator* posIter, UErrorCode& status) const { + FormattedNumber output = fields->formatter->formatDecimalQuantity(number, status); + fieldPositionIteratorHelper(output, posIter, appendTo.length(), status); + auto appendable = UnicodeStringAppendable(appendTo); + output.appendTo(appendable); + return appendTo; } UnicodeString& -DecimalFormat::format(int32_t number, - UnicodeString& appendTo, - FieldPositionIterator* posIter, - UErrorCode& status) const -{ - return fImpl->format(number, appendTo, posIter, status); +DecimalFormat::format(const DecimalQuantity& number, UnicodeString& appendTo, FieldPosition& pos, + UErrorCode& status) const { + FormattedNumber output = fields->formatter->formatDecimalQuantity(number, status); + fieldPositionHelper(output, pos, appendTo.length(), status); + auto appendable = UnicodeStringAppendable(appendTo); + output.appendTo(appendable); + return appendTo; } - -//------------------------------------------------------------------------------ - -UnicodeString& -DecimalFormat::format(int64_t number, - UnicodeString& appendTo, - FieldPosition& fieldPosition) const -{ - UErrorCode status = U_ZERO_ERROR; /* ignored */ - return fImpl->format(number, appendTo, fieldPosition, status); -} - -UnicodeString& -DecimalFormat::format(int64_t number, - UnicodeString& appendTo, - FieldPosition& fieldPosition, - UErrorCode& status) const -{ - return fImpl->format(number, appendTo, fieldPosition, status); -} - -UnicodeString& -DecimalFormat::format(int64_t number, - UnicodeString& appendTo, - FieldPositionIterator* posIter, - UErrorCode& status) const -{ - return fImpl->format(number, appendTo, posIter, status); -} - -//------------------------------------------------------------------------------ - -UnicodeString& -DecimalFormat::format( double number, - UnicodeString& appendTo, - FieldPosition& fieldPosition) const -{ - UErrorCode status = U_ZERO_ERROR; /* ignored */ - return fImpl->format(number, appendTo, fieldPosition, status); -} - -UnicodeString& -DecimalFormat::format( double number, - UnicodeString& appendTo, - FieldPosition& fieldPosition, - UErrorCode& status) const -{ - return fImpl->format(number, appendTo, fieldPosition, status); -} - -UnicodeString& -DecimalFormat::format( double number, - UnicodeString& appendTo, - FieldPositionIterator* posIter, - UErrorCode& status) const -{ - return fImpl->format(number, appendTo, posIter, status); -} - -//------------------------------------------------------------------------------ - - -UnicodeString& -DecimalFormat::format(StringPiece number, - UnicodeString &toAppendTo, - FieldPositionIterator *posIter, - UErrorCode &status) const -{ - return fImpl->format(number, toAppendTo, posIter, status); -} - - -UnicodeString& -DecimalFormat::format(const DigitList &number, - UnicodeString &appendTo, - FieldPositionIterator *posIter, - UErrorCode &status) const { - return fImpl->format(number, appendTo, posIter, status); -} - - -UnicodeString& -DecimalFormat::format(const DigitList &number, - UnicodeString& appendTo, - FieldPosition& pos, - UErrorCode &status) const { - return fImpl->format(number, appendTo, pos, status); -} - -UnicodeString& -DecimalFormat::format(const VisibleDigitsWithExponent &number, - UnicodeString &appendTo, - FieldPositionIterator *posIter, - UErrorCode &status) const { - return fImpl->format(number, appendTo, posIter, status); -} - - -UnicodeString& -DecimalFormat::format(const VisibleDigitsWithExponent &number, - UnicodeString& appendTo, - FieldPosition& pos, - UErrorCode &status) const { - return fImpl->format(number, appendTo, pos, status); -} - -DigitList& -DecimalFormat::_round(const DigitList& number, DigitList& adjustedNum, UBool& isNegative, UErrorCode& status) const { - adjustedNum = number; - fImpl->round(adjustedNum, status); - isNegative = !adjustedNum.isPositive(); - return adjustedNum; -} - -void -DecimalFormat::parse(const UnicodeString& text, - Formattable& result, - ParsePosition& parsePosition) const { - parse(text, result, parsePosition, NULL); -} - -CurrencyAmount* DecimalFormat::parseCurrency(const UnicodeString& text, - ParsePosition& pos) const { - Formattable parseResult; - int32_t start = pos.getIndex(); - UChar curbuf[4] = {}; - parse(text, parseResult, pos, curbuf); - if (pos.getIndex() != start) { - UErrorCode ec = U_ZERO_ERROR; - LocalPointer currAmt(new CurrencyAmount(parseResult, curbuf, ec), ec); - if (U_FAILURE(ec)) { - pos.setIndex(start); // indicate failure - } else { - return currAmt.orphan(); - } - } - return NULL; -} - -/** - * Parses the given text as a number, optionally providing a currency amount. - * @param text the string to parse - * @param result output parameter for the numeric result. - * @param parsePosition input-output position; on input, the - * position within text to match; must have 0 <= pos.getIndex() < - * text.length(); on output, the position after the last matched - * character. If the parse fails, the position in unchanged upon - * output. - * @param currency if non-NULL, it should point to a 4-UChar buffer. - * In this case the text is parsed as a currency format, and the - * ISO 4217 code for the parsed currency is put into the buffer. - * Otherwise the text is parsed as a non-currency format. - */ -void DecimalFormat::parse(const UnicodeString& text, - Formattable& result, - ParsePosition& parsePosition, - UChar* currency) const { - int32_t startIdx, backup; - int32_t i = startIdx = backup = parsePosition.getIndex(); - - // clear any old contents in the result. In particular, clears any DigitList - // that it may be holding. - result.setLong(0); - if (currency != NULL) { - for (int32_t ci=0; ci<4; ci++) { - currency[ci] = 0; - } - } - - // Handle NaN as a special case: - int32_t formatWidth = fImpl->getOldFormatWidth(); - - // Skip padding characters, if around prefix - if (formatWidth > 0 && ( - fImpl->fAffixes.fPadPosition == DigitAffixesAndPadding::kPadBeforePrefix || - fImpl->fAffixes.fPadPosition == DigitAffixesAndPadding::kPadAfterPrefix)) { - i = skipPadding(text, i); - } - - if (isLenient()) { - // skip any leading whitespace - i = backup = skipUWhiteSpace(text, i); - } - - // If the text is composed of the representation of NaN, returns NaN.length - const UnicodeString *nan = &fImpl->getConstSymbol(DecimalFormatSymbols::kNaNSymbol); - int32_t nanLen = (text.compare(i, nan->length(), *nan) - ? 0 : nan->length()); - if (nanLen) { - i += nanLen; - if (formatWidth > 0 && (fImpl->fAffixes.fPadPosition == DigitAffixesAndPadding::kPadBeforeSuffix || fImpl->fAffixes.fPadPosition == DigitAffixesAndPadding::kPadAfterSuffix)) { - i = skipPadding(text, i); - } - parsePosition.setIndex(i); - result.setDouble(uprv_getNaN()); +void DecimalFormat::parse(const UnicodeString& text, Formattable& output, + ParsePosition& parsePosition) const { + if (parsePosition.getIndex() < 0 || parsePosition.getIndex() >= text.length()) { return; } - // NaN parse failed; start over - i = backup; - parsePosition.setIndex(i); - - // status is used to record whether a number is infinite. - UBool status[fgStatusLength]; - - DigitList *digits = result.getInternalDigitList(); // get one from the stack buffer - if (digits == NULL) { - return; // no way to report error from here. - } - - if (fImpl->fMonetary) { - if (!parseForCurrency(text, parsePosition, *digits, - status, currency)) { - return; - } + ErrorCode status; + ParsedNumber result; + // Note: if this is a currency instance, currencies will be matched despite the fact that we are not in the + // parseCurrency method (backwards compatibility) + int32_t startIndex = parsePosition.getIndex(); + const NumberParserImpl* parser = getParser(status); + if (U_FAILURE(status)) { return; } + parser->parse(text, startIndex, true, result, status); + // TODO: Do we need to check for fImpl->properties->parseAllInput (UCONFIG_HAVE_PARSEALLINPUT) here? + if (result.success()) { + parsePosition.setIndex(result.charEnd); + result.populateFormattable(output, parser->getParseFlags()); } else { - if (!subparse(text, - &fImpl->fAffixes.fNegativePrefix.getOtherVariant().toString(), - &fImpl->fAffixes.fNegativeSuffix.getOtherVariant().toString(), - &fImpl->fAffixes.fPositivePrefix.getOtherVariant().toString(), - &fImpl->fAffixes.fPositiveSuffix.getOtherVariant().toString(), - FALSE, UCURR_SYMBOL_NAME, - parsePosition, *digits, status, currency)) { - debug("!subparse(...) - rewind"); - parsePosition.setIndex(startIdx); - return; - } - } - - // Handle infinity - if (status[fgStatusInfinite]) { - double inf = uprv_getInfinity(); - result.setDouble(digits->isPositive() ? inf : -inf); - // TODO: set the dl to infinity, and let it fall into the code below. - } - - else { - - if (!fImpl->fMultiplier.isZero()) { - UErrorCode ec = U_ZERO_ERROR; - digits->div(fImpl->fMultiplier, ec); - } - - if (fImpl->fScale != 0) { - DigitList ten; - ten.set((int32_t)10); - if (fImpl->fScale > 0) { - for (int32_t i = fImpl->fScale; i > 0; i--) { - UErrorCode ec = U_ZERO_ERROR; - digits->div(ten,ec); - } - } else { - for (int32_t i = fImpl->fScale; i < 0; i++) { - UErrorCode ec = U_ZERO_ERROR; - digits->mult(ten,ec); - } - } - } - - // Negative zero special case: - // if parsing integerOnly, change to +0, which goes into an int32 in a Formattable. - // if not parsing integerOnly, leave as -0, which a double can represent. - if (digits->isZero() && !digits->isPositive() && isParseIntegerOnly()) { - digits->setPositive(TRUE); - } - result.adoptDigitList(digits); + parsePosition.setErrorIndex(startIndex + result.charEnd); } } +CurrencyAmount* DecimalFormat::parseCurrency(const UnicodeString& text, ParsePosition& parsePosition) const { + if (parsePosition.getIndex() < 0 || parsePosition.getIndex() >= text.length()) { + return nullptr; + } - -UBool -DecimalFormat::parseForCurrency(const UnicodeString& text, - ParsePosition& parsePosition, - DigitList& digits, - UBool* status, - UChar* currency) const { - UnicodeString positivePrefix; - UnicodeString positiveSuffix; - UnicodeString negativePrefix; - UnicodeString negativeSuffix; - fImpl->fPositivePrefixPattern.toString(positivePrefix); - fImpl->fPositiveSuffixPattern.toString(positiveSuffix); - fImpl->fNegativePrefixPattern.toString(negativePrefix); - fImpl->fNegativeSuffixPattern.toString(negativeSuffix); - - int origPos = parsePosition.getIndex(); - int maxPosIndex = origPos; - int maxErrorPos = -1; - // First, parse against current pattern. - // Since current pattern could be set by applyPattern(), - // it could be an arbitrary pattern, and it may not be the one - // defined in current locale. - UBool tmpStatus[fgStatusLength]; - ParsePosition tmpPos(origPos); - DigitList tmpDigitList; - UBool found; - if (fStyle == UNUM_CURRENCY_PLURAL) { - found = subparse(text, - &negativePrefix, &negativeSuffix, - &positivePrefix, &positiveSuffix, - TRUE, UCURR_LONG_NAME, - tmpPos, tmpDigitList, tmpStatus, currency); + ErrorCode status; + ParsedNumber result; + // Note: if this is a currency instance, currencies will be matched despite the fact that we are not in the + // parseCurrency method (backwards compatibility) + int32_t startIndex = parsePosition.getIndex(); + const NumberParserImpl* parser = getCurrencyParser(status); + if (U_FAILURE(status)) { return nullptr; } + parser->parse(text, startIndex, true, result, status); + // TODO: Do we need to check for fImpl->properties->parseAllInput (UCONFIG_HAVE_PARSEALLINPUT) here? + if (result.success()) { + parsePosition.setIndex(result.charEnd); + Formattable formattable; + result.populateFormattable(formattable, parser->getParseFlags()); + return new CurrencyAmount(formattable, result.currencyCode, status); } else { - found = subparse(text, - &negativePrefix, &negativeSuffix, - &positivePrefix, &positiveSuffix, - TRUE, UCURR_SYMBOL_NAME, - tmpPos, tmpDigitList, tmpStatus, currency); + parsePosition.setErrorIndex(startIndex + result.charEnd); + return nullptr; } - if (found) { - if (tmpPos.getIndex() > maxPosIndex) { - maxPosIndex = tmpPos.getIndex(); - for (int32_t i = 0; i < fgStatusLength; ++i) { - status[i] = tmpStatus[i]; - } - digits = tmpDigitList; - } - } else { - maxErrorPos = tmpPos.getErrorIndex(); - } - // Then, parse against affix patterns. - // Those are currency patterns and currency plural patterns. - int32_t pos = UHASH_FIRST; - const UHashElement* element = NULL; - while ( (element = fAffixPatternsForCurrency->nextElement(pos)) != NULL ) { - const UHashTok valueTok = element->value; - const AffixPatternsForCurrency* affixPtn = (AffixPatternsForCurrency*)valueTok.pointer; - UBool tmpStatus[fgStatusLength]; - ParsePosition tmpPos(origPos); - DigitList tmpDigitList; - -#ifdef FMT_DEBUG - debug("trying affix for currency.."); - affixPtn->dump(); -#endif - - UBool result = subparse(text, - &affixPtn->negPrefixPatternForCurrency, - &affixPtn->negSuffixPatternForCurrency, - &affixPtn->posPrefixPatternForCurrency, - &affixPtn->posSuffixPatternForCurrency, - TRUE, affixPtn->patternType, - tmpPos, tmpDigitList, tmpStatus, currency); - if (result) { - found = true; - if (tmpPos.getIndex() > maxPosIndex) { - maxPosIndex = tmpPos.getIndex(); - for (int32_t i = 0; i < fgStatusLength; ++i) { - status[i] = tmpStatus[i]; - } - digits = tmpDigitList; - } - } else { - maxErrorPos = (tmpPos.getErrorIndex() > maxErrorPos) ? - tmpPos.getErrorIndex() : maxErrorPos; - } - } - // Finally, parse against simple affix to find the match. - // For example, in TestMonster suite, - // if the to-be-parsed text is "-\u00A40,00". - // complexAffixCompare will not find match, - // since there is no ISO code matches "\u00A4", - // and the parse stops at "\u00A4". - // We will just use simple affix comparison (look for exact match) - // to pass it. - // - // TODO: We should parse against simple affix first when - // output currency is not requested. After the complex currency - // parsing implementation was introduced, the default currency - // instance parsing slowed down because of the new code flow. - // I filed #10312 - Yoshito - UBool tmpStatus_2[fgStatusLength]; - ParsePosition tmpPos_2(origPos); - DigitList tmpDigitList_2; - - // Disable complex currency parsing and try it again. - UBool result = subparse(text, - &fImpl->fAffixes.fNegativePrefix.getOtherVariant().toString(), - &fImpl->fAffixes.fNegativeSuffix.getOtherVariant().toString(), - &fImpl->fAffixes.fPositivePrefix.getOtherVariant().toString(), - &fImpl->fAffixes.fPositiveSuffix.getOtherVariant().toString(), - FALSE /* disable complex currency parsing */, UCURR_SYMBOL_NAME, - tmpPos_2, tmpDigitList_2, tmpStatus_2, - currency); - if (result) { - if (tmpPos_2.getIndex() > maxPosIndex) { - maxPosIndex = tmpPos_2.getIndex(); - for (int32_t i = 0; i < fgStatusLength; ++i) { - status[i] = tmpStatus_2[i]; - } - digits = tmpDigitList_2; - } - found = true; - } else { - maxErrorPos = (tmpPos_2.getErrorIndex() > maxErrorPos) ? - tmpPos_2.getErrorIndex() : maxErrorPos; - } - - if (!found) { - //parsePosition.setIndex(origPos); - parsePosition.setErrorIndex(maxErrorPos); - } else { - parsePosition.setIndex(maxPosIndex); - parsePosition.setErrorIndex(-1); - } - return found; } +const DecimalFormatSymbols* DecimalFormat::getDecimalFormatSymbols(void) const { + return fields->symbols.getAlias(); +} -/** - * Parse the given text into a number. The text is parsed beginning at - * parsePosition, until an unparseable character is seen. - * @param text the string to parse. - * @param negPrefix negative prefix. - * @param negSuffix negative suffix. - * @param posPrefix positive prefix. - * @param posSuffix positive suffix. - * @param complexCurrencyParsing whether it is complex currency parsing or not. - * @param type the currency type to parse against, LONG_NAME only or not. - * @param parsePosition The position at which to being parsing. Upon - * return, the first unparsed character. - * @param digits the DigitList to set to the parsed value. - * @param status output param containing boolean status flags indicating - * whether the value was infinite and whether it was positive. - * @param currency return value for parsed currency, for generic - * currency parsing mode, or NULL for normal parsing. In generic - * currency parsing mode, any currency is parsed, not just the - * currency that this formatter is set to. - */ -UBool DecimalFormat::subparse(const UnicodeString& text, - const UnicodeString* negPrefix, - const UnicodeString* negSuffix, - const UnicodeString* posPrefix, - const UnicodeString* posSuffix, - UBool complexCurrencyParsing, - int8_t type, - ParsePosition& parsePosition, - DigitList& digits, UBool* status, - UChar* currency) const -{ - // The parsing process builds up the number as char string, in the neutral format that - // will be acceptable to the decNumber library, then at the end passes that string - // off for conversion to a decNumber. - UErrorCode err = U_ZERO_ERROR; - CharString parsedNum; - digits.setToZero(); +void DecimalFormat::adoptDecimalFormatSymbols(DecimalFormatSymbols* symbolsToAdopt) { + if (symbolsToAdopt == nullptr) { + return; // do not allow caller to set fields->symbols to NULL + } + fields->symbols.adoptInstead(symbolsToAdopt); + touchNoError(); +} - int32_t position = parsePosition.getIndex(); - int32_t oldStart = position; - int32_t textLength = text.length(); // One less pointer to follow - UBool strictParse = !isLenient(); - UChar32 zero = fImpl->getConstSymbol(DecimalFormatSymbols::kZeroDigitSymbol).char32At(0); - const UnicodeString *groupingString = &fImpl->getConstSymbol( - !fImpl->fMonetary ? - DecimalFormatSymbols::kGroupingSeparatorSymbol : DecimalFormatSymbols::kMonetaryGroupingSeparatorSymbol); - UChar32 groupingChar = groupingString->char32At(0); - int32_t groupingStringLength = groupingString->length(); - int32_t groupingCharLength = U16_LENGTH(groupingChar); - UBool groupingUsed = isGroupingUsed(); -#ifdef FMT_DEBUG - UChar dbgbuf[300]; - UnicodeString s(dbgbuf,0,300);; - s.append((UnicodeString)"PARSE \"").append(text.tempSubString(position)).append((UnicodeString)"\" " ); -#define DBGAPPD(x) if(x) { s.append(UnicodeString(#x "=")); if(x->isEmpty()) { s.append(UnicodeString("")); } else { s.append(*x); } s.append(UnicodeString(" ")); } else { s.append(UnicodeString(#x "=NULL ")); } - DBGAPPD(negPrefix); - DBGAPPD(negSuffix); - DBGAPPD(posPrefix); - DBGAPPD(posSuffix); - debugout(s); -#endif +void DecimalFormat::setDecimalFormatSymbols(const DecimalFormatSymbols& symbols) { + fields->symbols.adoptInstead(new DecimalFormatSymbols(symbols)); + touchNoError(); +} - UBool fastParseOk = false; /* TRUE iff fast parse is OK */ - // UBool fastParseHadDecimal = FALSE; /* true if fast parse saw a decimal point. */ - if((fImpl->isParseFastpath()) && !fImpl->fMonetary && - text.length()>0 && - text.length()<32 && - (posPrefix==NULL||posPrefix->isEmpty()) && - (posSuffix==NULL||posSuffix->isEmpty()) && - // (negPrefix==NULL||negPrefix->isEmpty()) && - // (negSuffix==NULL||(negSuffix->isEmpty()) ) && - TRUE) { // optimized path - int j=position; - int l=text.length(); - int digitCount=0; - UChar32 ch = text.char32At(j); - const UnicodeString *decimalString = &fImpl->getConstSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol); - UChar32 decimalChar = 0; - UBool intOnly = FALSE; - UChar32 lookForGroup = (groupingUsed&&intOnly&&strictParse)?groupingChar:0; +const CurrencyPluralInfo* DecimalFormat::getCurrencyPluralInfo(void) const { + return fields->properties->currencyPluralInfo.fPtr.getAlias(); +} - int32_t decimalCount = decimalString->countChar32(0,3); - if(isParseIntegerOnly()) { - decimalChar = 0; // not allowed - intOnly = TRUE; // Don't look for decimals. - } else if(decimalCount==1) { - decimalChar = decimalString->char32At(0); // Look for this decimal - } else if(decimalCount==0) { - decimalChar=0; // NO decimal set - } else { - j=l+1;//Set counter to end of line, so that we break. Unknown decimal situation. - } +void DecimalFormat::adoptCurrencyPluralInfo(CurrencyPluralInfo* toAdopt) { + fields->properties->currencyPluralInfo.fPtr.adoptInstead(toAdopt); + touchNoError(); +} -#ifdef FMT_DEBUG - printf("Preparing to do fastpath parse: decimalChar=U+%04X, groupingChar=U+%04X, first ch=U+%04X intOnly=%c strictParse=%c\n", - decimalChar, groupingChar, ch, - (intOnly)?'y':'n', - (strictParse)?'y':'n'); -#endif - if(ch==0x002D) { // '-' - j=l+1;//=break - negative number. - - /* - parsedNum.append('-',err); - j+=U16_LENGTH(ch); - if(j=0 && digit <= 9) { - parsedNum.append((char)(digit + '0'), err); - if((digitCount>0) || digit!=0 || j==(l-1)) { - digitCount++; - } - } else if(ch == 0) { // break out - digitCount=-1; - break; - } else if(ch == decimalChar) { - parsedNum.append((char)('.'), err); - decimalChar=0; // no more decimals. - // fastParseHadDecimal=TRUE; - } else if(ch == lookForGroup) { - // ignore grouping char. No decimals, so it has to be an ignorable grouping sep - } else if(intOnly && (lookForGroup!=0) && !u_isdigit(ch)) { - // parsing integer only and can fall through - } else { - digitCount=-1; // fail - fall through to slow parse - break; - } - j+=U16_LENGTH(ch); - ch = text.char32At(j); // for next - } - if( - ((j==l)||intOnly) // end OR only parsing integer - && (digitCount>0)) { // and have at least one digit - fastParseOk=true; // Fast parse OK! - -#ifdef SKIP_OPT - debug("SKIP_OPT"); - /* for testing, try it the slow way. also */ - fastParseOk=false; - parsedNum.clear(); -#else - parsePosition.setIndex(position=j); - status[fgStatusInfinite]=false; -#endif - } else { - // was not OK. reset, retry -#ifdef FMT_DEBUG - printf("Fall through: j=%d, l=%d, digitCount=%d\n", j, l, digitCount); -#endif - parsedNum.clear(); - } +void DecimalFormat::setCurrencyPluralInfo(const CurrencyPluralInfo& info) { + if (fields->properties->currencyPluralInfo.fPtr.isNull()) { + fields->properties->currencyPluralInfo.fPtr.adoptInstead(info.clone()); } else { -#ifdef FMT_DEBUG - printf("Could not fastpath parse. "); - printf("text.length()=%d ", text.length()); - printf("posPrefix=%p posSuffix=%p ", posPrefix, posSuffix); - - printf("\n"); -#endif + *fields->properties->currencyPluralInfo.fPtr = info; // copy-assignment operator } + touchNoError(); +} - UnicodeString formatPattern; - toPattern(formatPattern); +UnicodeString& DecimalFormat::getPositivePrefix(UnicodeString& result) const { + ErrorCode localStatus; + fields->formatter->getAffixImpl(true, false, result, localStatus); + return result; +} - if(!fastParseOk -#if UCONFIG_HAVE_PARSEALLINPUT - && fParseAllInput!=UNUM_YES -#endif - ) - { - int32_t formatWidth = fImpl->getOldFormatWidth(); - // Match padding before prefix - if (formatWidth > 0 && fImpl->fAffixes.fPadPosition == DigitAffixesAndPadding::kPadBeforePrefix) { - position = skipPadding(text, position); - } +void DecimalFormat::setPositivePrefix(const UnicodeString& newValue) { + if (newValue == fields->properties->positivePrefix) { return; } + fields->properties->positivePrefix = newValue; + touchNoError(); +} - // Match positive and negative prefixes; prefer longest match. - int32_t posMatch = compareAffix(text, position, FALSE, TRUE, posPrefix, complexCurrencyParsing, type, currency); - int32_t negMatch = compareAffix(text, position, TRUE, TRUE, negPrefix, complexCurrencyParsing, type, currency); - if (posMatch >= 0 && negMatch >= 0) { - if (posMatch > negMatch) { - negMatch = -1; - } else if (negMatch > posMatch) { - posMatch = -1; - } - } - if (posMatch >= 0) { - position += posMatch; - parsedNum.append('+', err); - } else if (negMatch >= 0) { - position += negMatch; - parsedNum.append('-', err); - } else if (strictParse){ - parsePosition.setErrorIndex(position); - return FALSE; +UnicodeString& DecimalFormat::getNegativePrefix(UnicodeString& result) const { + ErrorCode localStatus; + fields->formatter->getAffixImpl(true, true, result, localStatus); + return result; +} + +void DecimalFormat::setNegativePrefix(const UnicodeString& newValue) { + if (newValue == fields->properties->negativePrefix) { return; } + fields->properties->negativePrefix = newValue; + touchNoError(); +} + +UnicodeString& DecimalFormat::getPositiveSuffix(UnicodeString& result) const { + ErrorCode localStatus; + fields->formatter->getAffixImpl(false, false, result, localStatus); + return result; +} + +void DecimalFormat::setPositiveSuffix(const UnicodeString& newValue) { + if (newValue == fields->properties->positiveSuffix) { return; } + fields->properties->positiveSuffix = newValue; + touchNoError(); +} + +UnicodeString& DecimalFormat::getNegativeSuffix(UnicodeString& result) const { + ErrorCode localStatus; + fields->formatter->getAffixImpl(false, true, result, localStatus); + return result; +} + +void DecimalFormat::setNegativeSuffix(const UnicodeString& newValue) { + if (newValue == fields->properties->negativeSuffix) { return; } + fields->properties->negativeSuffix = newValue; + touchNoError(); +} + +UBool DecimalFormat::isSignAlwaysShown() const { + return fields->properties->signAlwaysShown; +} + +void DecimalFormat::setSignAlwaysShown(UBool value) { + if (UBOOL_TO_BOOL(value) == fields->properties->signAlwaysShown) { return; } + fields->properties->signAlwaysShown = value; + touchNoError(); +} + +int32_t DecimalFormat::getMultiplier(void) const { + if (fields->properties->multiplier != 1) { + return fields->properties->multiplier; + } else if (fields->properties->magnitudeMultiplier != 0) { + return static_cast(uprv_pow10(fields->properties->magnitudeMultiplier)); } else { - // Temporary set positive. This might be changed after checking suffix - parsedNum.append('+', err); + return 1; } - - // Match padding before prefix - if (formatWidth > 0 && fImpl->fAffixes.fPadPosition == DigitAffixesAndPadding::kPadAfterPrefix) { - position = skipPadding(text, position); - } - - if (! strictParse) { - position = skipUWhiteSpace(text, position); - } - - // process digits or Inf, find decimal position - const UnicodeString *inf = &fImpl->getConstSymbol(DecimalFormatSymbols::kInfinitySymbol); - int32_t infLen = (text.compare(position, inf->length(), *inf) - ? 0 : inf->length()); - position += infLen; // infLen is non-zero when it does equal to infinity - status[fgStatusInfinite] = infLen != 0; - - if (infLen != 0) { - parsedNum.append("Infinity", err); - } else { - // We now have a string of digits, possibly with grouping symbols, - // and decimal points. We want to process these into a DigitList. - // We don't want to put a bunch of leading zeros into the DigitList - // though, so we keep track of the location of the decimal point, - // put only significant digits into the DigitList, and adjust the - // exponent as needed. - - - UBool strictFail = FALSE; // did we exit with a strict parse failure? - int32_t lastGroup = -1; // after which digit index did we last see a grouping separator? - int32_t currGroup = -1; // for temporary storage the digit index of the current grouping separator - int32_t gs2 = fImpl->fEffGrouping.fGrouping2 == 0 ? fImpl->fEffGrouping.fGrouping : fImpl->fEffGrouping.fGrouping2; - - const UnicodeString *decimalString; - if (fImpl->fMonetary) { - decimalString = &fImpl->getConstSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol); - } else { - decimalString = &fImpl->getConstSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol); - } - UChar32 decimalChar = decimalString->char32At(0); - int32_t decimalStringLength = decimalString->length(); - int32_t decimalCharLength = U16_LENGTH(decimalChar); - - UBool sawDecimal = FALSE; - UChar32 sawDecimalChar = 0xFFFF; - UBool sawGrouping = FALSE; - UChar32 sawGroupingChar = 0xFFFF; - UBool sawDigit = FALSE; - int32_t backup = -1; - int32_t digit; - - // equivalent grouping and decimal support - const UnicodeSet *decimalSet = NULL; - const UnicodeSet *groupingSet = NULL; - - if (decimalCharLength == decimalStringLength) { - decimalSet = DecimalFormatStaticSets::getSimilarDecimals(decimalChar, strictParse); - } - - if (groupingCharLength == groupingStringLength) { - if (strictParse) { - groupingSet = fStaticSets->fStrictDefaultGroupingSeparators; - } else { - groupingSet = fStaticSets->fDefaultGroupingSeparators; - } - } - - // We need to test groupingChar and decimalChar separately from groupingSet and decimalSet, if the sets are even initialized. - // If sawDecimal is TRUE, only consider sawDecimalChar and NOT decimalSet - // If a character matches decimalSet, don't consider it to be a member of the groupingSet. - - // We have to track digitCount ourselves, because digits.fCount will - // pin when the maximum allowable digits is reached. - int32_t digitCount = 0; - int32_t integerDigitCount = 0; - - for (; position < textLength; ) - { - UChar32 ch = text.char32At(position); - - /* We recognize all digit ranges, not only the Latin digit range - * '0'..'9'. We do so by using the Character.digit() method, - * which converts a valid Unicode digit to the range 0..9. - * - * The character 'ch' may be a digit. If so, place its value - * from 0 to 9 in 'digit'. First try using the locale digit, - * which may or MAY NOT be a standard Unicode digit range. If - * this fails, try using the standard Unicode digit ranges by - * calling Character.digit(). If this also fails, digit will - * have a value outside the range 0..9. - */ - digit = ch - zero; - if (digit < 0 || digit > 9) - { - digit = u_charDigitValue(ch); - } - - // As a last resort, look through the localized digits if the zero digit - // is not a "standard" Unicode digit. - if ( (digit < 0 || digit > 9) && u_charDigitValue(zero) != 0) { - digit = 0; - if ( fImpl->getConstSymbol((DecimalFormatSymbols::ENumberFormatSymbol)(DecimalFormatSymbols::kZeroDigitSymbol)).char32At(0) == ch ) { - break; - } - for (digit = 1 ; digit < 10 ; digit++ ) { - if ( fImpl->getConstSymbol((DecimalFormatSymbols::ENumberFormatSymbol)(DecimalFormatSymbols::kOneDigitSymbol+digit-1)).char32At(0) == ch ) { - break; - } - } - } - - if (digit >= 0 && digit <= 9) - { - if (strictParse && backup != -1) { - // comma followed by digit, so group before comma is a - // secondary group. If there was a group separator - // before that, the group must == the secondary group - // length, else it can be <= the the secondary group - // length. - if ((lastGroup != -1 && currGroup - lastGroup != gs2) || - (lastGroup == -1 && digitCount - 1 > gs2)) { - strictFail = TRUE; - break; - } - - lastGroup = currGroup; - } - - // Cancel out backup setting (see grouping handler below) - currGroup = -1; - backup = -1; - sawDigit = TRUE; - - // Note: this will append leading zeros - parsedNum.append((char)(digit + '0'), err); - - // count any digit that's not a leading zero - if (digit > 0 || digitCount > 0 || sawDecimal) { - digitCount += 1; - - // count any integer digit that's not a leading zero - if (! sawDecimal) { - integerDigitCount += 1; - } - } - - position += U16_LENGTH(ch); - } - else if (groupingStringLength > 0 && - matchGrouping(groupingChar, sawGrouping, sawGroupingChar, groupingSet, - decimalChar, decimalSet, - ch) && groupingUsed) - { - if (sawDecimal) { - break; - } - - if (strictParse) { - if ((!sawDigit || backup != -1)) { - // leading group, or two group separators in a row - strictFail = TRUE; - break; - } - } - - // Ignore grouping characters, if we are using them, but require - // that they be followed by a digit. Otherwise we backup and - // reprocess them. - currGroup = digitCount; - backup = position; - position += groupingStringLength; - sawGrouping=TRUE; - // Once we see a grouping character, we only accept that grouping character from then on. - sawGroupingChar=ch; - } - else if (matchDecimal(decimalChar,sawDecimal,sawDecimalChar, decimalSet, ch)) - { - if (strictParse) { - if (backup != -1 || - (lastGroup != -1 && digitCount - lastGroup != fImpl->fEffGrouping.fGrouping)) { - strictFail = TRUE; - break; - } - } - - // If we're only parsing integers, or if we ALREADY saw the - // decimal, then don't parse this one. - if (isParseIntegerOnly() || sawDecimal) { - break; - } - - parsedNum.append('.', err); - position += decimalStringLength; - sawDecimal = TRUE; - // Once we see a decimal character, we only accept that decimal character from then on. - sawDecimalChar=ch; - // decimalSet is considered to consist of (ch,ch) - } - else { - - if(!fBoolFlags.contains(UNUM_PARSE_NO_EXPONENT) || // don't parse if this is set unless.. - isScientificNotation()) { // .. it's an exponent format - ignore setting and parse anyways - const UnicodeString *tmp; - tmp = &fImpl->getConstSymbol(DecimalFormatSymbols::kExponentialSymbol); - // TODO: CASE - if (!text.caseCompare(position, tmp->length(), *tmp, U_FOLD_CASE_DEFAULT)) // error code is set below if !sawDigit - { - // Parse sign, if present - int32_t pos = position + tmp->length(); - char exponentSign = '+'; - - if (pos < textLength) - { - tmp = &fImpl->getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol); - if (!text.compare(pos, tmp->length(), *tmp)) - { - pos += tmp->length(); - } - else { - tmp = &fImpl->getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol); - if (!text.compare(pos, tmp->length(), *tmp)) - { - exponentSign = '-'; - pos += tmp->length(); - } - } - } - - UBool sawExponentDigit = FALSE; - while (pos < textLength) { - ch = text.char32At(pos); - digit = ch - zero; - - if (digit < 0 || digit > 9) { - digit = u_charDigitValue(ch); - } - if (0 <= digit && digit <= 9) { - if (!sawExponentDigit) { - parsedNum.append('E', err); - parsedNum.append(exponentSign, err); - sawExponentDigit = TRUE; - } - pos += U16_LENGTH(ch); - parsedNum.append((char)(digit + '0'), err); - } else { - break; - } - } - - if (sawExponentDigit) { - position = pos; // Advance past the exponent - } - - break; // Whether we fail or succeed, we exit this loop - } else { - break; - } - } else { // not parsing exponent - break; - } - } - } - - // if we didn't see a decimal and it is required, check to see if the pattern had one - if(!sawDecimal && isDecimalPatternMatchRequired()) - { - if(formatPattern.indexOf(kPatternDecimalSeparator) != -1) - { - parsePosition.setIndex(oldStart); - parsePosition.setErrorIndex(position); - debug("decimal point match required fail!"); - return FALSE; - } - } - - if (backup != -1) - { - position = backup; - } - - if (strictParse && !sawDecimal) { - if (lastGroup != -1 && digitCount - lastGroup != fImpl->fEffGrouping.fGrouping) { - strictFail = TRUE; - } - } - - if (strictFail) { - // only set with strictParse and a grouping separator error - - parsePosition.setIndex(oldStart); - parsePosition.setErrorIndex(position); - debug("strictFail!"); - return FALSE; - } - - // If there was no decimal point we have an integer - - // If none of the text string was recognized. For example, parse - // "x" with pattern "#0.00" (return index and error index both 0) - // parse "$" with pattern "$#0.00". (return index 0 and error index - // 1). - if (!sawDigit && digitCount == 0) { -#ifdef FMT_DEBUG - debug("none of text rec"); - printf("position=%d\n",position); -#endif - parsePosition.setIndex(oldStart); - parsePosition.setErrorIndex(oldStart); - return FALSE; - } - } - - // Match padding before suffix - if (formatWidth > 0 && fImpl->fAffixes.fPadPosition == DigitAffixesAndPadding::kPadBeforeSuffix) { - position = skipPadding(text, position); - } - - int32_t posSuffixMatch = -1, negSuffixMatch = -1; - - // Match positive and negative suffixes; prefer longest match. - if (posMatch >= 0 || (!strictParse && negMatch < 0)) { - posSuffixMatch = compareAffix(text, position, FALSE, FALSE, posSuffix, complexCurrencyParsing, type, currency); - } - if (negMatch >= 0) { - negSuffixMatch = compareAffix(text, position, TRUE, FALSE, negSuffix, complexCurrencyParsing, type, currency); - } - if (posSuffixMatch >= 0 && negSuffixMatch >= 0) { - if (posSuffixMatch > negSuffixMatch) { - negSuffixMatch = -1; - } else if (negSuffixMatch > posSuffixMatch) { - posSuffixMatch = -1; - } - } - - // Fail if neither or both - if (strictParse && ((posSuffixMatch >= 0) == (negSuffixMatch >= 0))) { - parsePosition.setErrorIndex(position); - debug("neither or both"); - return FALSE; - } - - position += (posSuffixMatch >= 0 ? posSuffixMatch : (negSuffixMatch >= 0 ? negSuffixMatch : 0)); - - // Match padding before suffix - if (formatWidth > 0 && fImpl->fAffixes.fPadPosition == DigitAffixesAndPadding::kPadAfterSuffix) { - position = skipPadding(text, position); - } - - parsePosition.setIndex(position); - - parsedNum.data()[0] = (posSuffixMatch >= 0 || (!strictParse && negMatch < 0 && negSuffixMatch < 0)) ? '+' : '-'; -#ifdef FMT_DEBUG -printf("PP -> %d, SLOW = [%s]! pp=%d, os=%d, err=%s\n", position, parsedNum.data(), parsePosition.getIndex(),oldStart,u_errorName(err)); -#endif - } /* end SLOW parse */ - if(parsePosition.getIndex() == oldStart) - { -#ifdef FMT_DEBUG - printf(" PP didnt move, err\n"); -#endif - parsePosition.setErrorIndex(position); - return FALSE; - } -#if UCONFIG_HAVE_PARSEALLINPUT - else if (fParseAllInput==UNUM_YES&&parsePosition.getIndex()!=textLength) - { -#ifdef FMT_DEBUG - printf(" PP didnt consume all (UNUM_YES), err\n"); -#endif - parsePosition.setErrorIndex(position); - return FALSE; - } -#endif - // uint32_t bits = (fastParseOk?kFastpathOk:0) | - // (fastParseHadDecimal?0:kNoDecimal); - //printf("FPOK=%d, FPHD=%d, bits=%08X\n", fastParseOk, fastParseHadDecimal, bits); - digits.set(parsedNum.toStringPiece(), - err, - 0//bits - ); - - if (U_FAILURE(err)) { -#ifdef FMT_DEBUG - printf(" err setting %s\n", u_errorName(err)); -#endif - parsePosition.setErrorIndex(position); - return FALSE; - } - - // check if we missed a required decimal point - if(fastParseOk && isDecimalPatternMatchRequired()) - { - if(formatPattern.indexOf(kPatternDecimalSeparator) != -1) - { - parsePosition.setIndex(oldStart); - parsePosition.setErrorIndex(position); - debug("decimal point match required fail!"); - return FALSE; - } - } - - - return TRUE; } -/** - * Starting at position, advance past a run of pad characters, if any. - * Return the index of the first character after position that is not a pad - * character. Result is >= position. - */ -int32_t DecimalFormat::skipPadding(const UnicodeString& text, int32_t position) const { - int32_t padLen = U16_LENGTH(fImpl->fAffixes.fPadChar); - while (position < text.length() && - text.char32At(position) == fImpl->fAffixes.fPadChar) { - position += padLen; - } - return position; -} - -/** - * Return the length matched by the given affix, or -1 if none. - * Runs of white space in the affix, match runs of white space in - * the input. Pattern white space and input white space are - * determined differently; see code. - * @param text input text - * @param pos offset into input at which to begin matching - * @param isNegative - * @param isPrefix - * @param affixPat affix pattern used for currency affix comparison. - * @param complexCurrencyParsing whether it is currency parsing or not - * @param type the currency type to parse against, LONG_NAME only or not. - * @param currency return value for parsed currency, for generic - * currency parsing mode, or null for normal parsing. In generic - * currency parsing mode, any currency is parsed, not just the - * currency that this formatter is set to. - * @return length of input that matches, or -1 if match failure - */ -int32_t DecimalFormat::compareAffix(const UnicodeString& text, - int32_t pos, - UBool isNegative, - UBool isPrefix, - const UnicodeString* affixPat, - UBool complexCurrencyParsing, - int8_t type, - UChar* currency) const -{ - const UnicodeString *patternToCompare; - if (currency != NULL || - (fImpl->fMonetary && complexCurrencyParsing)) { - - if (affixPat != NULL) { - return compareComplexAffix(*affixPat, text, pos, type, currency); - } +void DecimalFormat::setMultiplier(int32_t multiplier) { + if (multiplier == 0) { + multiplier = 1; // one being the benign default value for a multiplier. } - if (isNegative) { - if (isPrefix) { - patternToCompare = &fImpl->fAffixes.fNegativePrefix.getOtherVariant().toString(); - } - else { - patternToCompare = &fImpl->fAffixes.fNegativeSuffix.getOtherVariant().toString(); - } - } - else { - if (isPrefix) { - patternToCompare = &fImpl->fAffixes.fPositivePrefix.getOtherVariant().toString(); - } - else { - patternToCompare = &fImpl->fAffixes.fPositiveSuffix.getOtherVariant().toString(); - } - } - return compareSimpleAffix(*patternToCompare, text, pos, isLenient()); -} - -UBool DecimalFormat::equalWithSignCompatibility(UChar32 lhs, UChar32 rhs) const { - if (lhs == rhs) { - return TRUE; - } - U_ASSERT(fStaticSets != NULL); // should already be loaded - const UnicodeSet *minusSigns = fStaticSets->fMinusSigns; - const UnicodeSet *plusSigns = fStaticSets->fPlusSigns; - return (minusSigns->contains(lhs) && minusSigns->contains(rhs)) || - (plusSigns->contains(lhs) && plusSigns->contains(rhs)); -} - -// check for LRM 0x200E, RLM 0x200F, ALM 0x061C -#define IS_BIDI_MARK(c) (c==0x200E || c==0x200F || c==0x061C) - -#define TRIM_BUFLEN 32 -UnicodeString& DecimalFormat::trimMarksFromAffix(const UnicodeString& affix, UnicodeString& trimmedAffix) { - UChar trimBuf[TRIM_BUFLEN]; - int32_t affixLen = affix.length(); - int32_t affixPos, trimLen = 0; - - for (affixPos = 0; affixPos < affixLen; affixPos++) { - UChar c = affix.charAt(affixPos); - if (!IS_BIDI_MARK(c)) { - if (trimLen < TRIM_BUFLEN) { - trimBuf[trimLen++] = c; - } else { - trimLen = 0; - break; - } - } - } - return (trimLen > 0)? trimmedAffix.setTo(trimBuf, trimLen): trimmedAffix.setTo(affix); -} - -/** - * Return the length matched by the given affix, or -1 if none. - * Runs of white space in the affix, match runs of white space in - * the input. Pattern white space and input white space are - * determined differently; see code. - * @param affix pattern string, taken as a literal - * @param input input text - * @param pos offset into input at which to begin matching - * @return length of input that matches, or -1 if match failure - */ -int32_t DecimalFormat::compareSimpleAffix(const UnicodeString& affix, - const UnicodeString& input, - int32_t pos, - UBool lenient) const { - int32_t start = pos; - UnicodeString trimmedAffix; - // For more efficiency we should keep lazily-created trimmed affixes around in - // instance variables instead of trimming each time they are used (the next step) - trimMarksFromAffix(affix, trimmedAffix); - UChar32 affixChar = trimmedAffix.char32At(0); - int32_t affixLength = trimmedAffix.length(); - int32_t inputLength = input.length(); - int32_t affixCharLength = U16_LENGTH(affixChar); - UnicodeSet *affixSet; - UErrorCode status = U_ZERO_ERROR; - - U_ASSERT(fStaticSets != NULL); // should already be loaded - - if (U_FAILURE(status)) { - return -1; - } - if (!lenient) { - affixSet = fStaticSets->fStrictDashEquivalents; - - // If the trimmedAffix is exactly one character long and that character - // is in the dash set and the very next input character is also - // in the dash set, return a match. - if (affixCharLength == affixLength && affixSet->contains(affixChar)) { - UChar32 ic = input.char32At(pos); - if (affixSet->contains(ic)) { - pos += U16_LENGTH(ic); - pos = skipBidiMarks(input, pos); // skip any trailing bidi marks - return pos - start; - } - } - - for (int32_t i = 0; i < affixLength; ) { - UChar32 c = trimmedAffix.char32At(i); - int32_t len = U16_LENGTH(c); - if (PatternProps::isWhiteSpace(c)) { - // We may have a pattern like: \u200F \u0020 - // and input text like: \u200F \u0020 - // Note that U+200F and U+0020 are Pattern_White_Space but only - // U+0020 is UWhiteSpace. So we have to first do a direct - // match of the run of Pattern_White_Space in the pattern, - // then match any extra characters. - UBool literalMatch = FALSE; - while (pos < inputLength) { - UChar32 ic = input.char32At(pos); - if (ic == c) { - literalMatch = TRUE; - i += len; - pos += len; - if (i == affixLength) { - break; - } - c = trimmedAffix.char32At(i); - len = U16_LENGTH(c); - if (!PatternProps::isWhiteSpace(c)) { - break; - } - } else if (IS_BIDI_MARK(ic)) { - pos ++; // just skip over this input text - } else { - break; - } - } - - // Advance over run in pattern - i = skipPatternWhiteSpace(trimmedAffix, i); - - // Advance over run in input text - // Must see at least one white space char in input, - // unless we've already matched some characters literally. - int32_t s = pos; - pos = skipUWhiteSpace(input, pos); - if (pos == s && !literalMatch) { - return -1; - } - - // If we skip UWhiteSpace in the input text, we need to skip it in the pattern. - // Otherwise, the previous lines may have skipped over text (such as U+00A0) that - // is also in the trimmedAffix. - i = skipUWhiteSpace(trimmedAffix, i); - } else { - UBool match = FALSE; - while (pos < inputLength) { - UChar32 ic = input.char32At(pos); - if (!match && ic == c) { - i += len; - pos += len; - match = TRUE; - } else if (IS_BIDI_MARK(ic)) { - pos++; // just skip over this input text - } else { - break; - } - } - if (!match) { - return -1; - } - } - } - } else { - UBool match = FALSE; - - affixSet = fStaticSets->fDashEquivalents; - - if (affixCharLength == affixLength && affixSet->contains(affixChar)) { - pos = skipUWhiteSpaceAndMarks(input, pos); - UChar32 ic = input.char32At(pos); - - if (affixSet->contains(ic)) { - pos += U16_LENGTH(ic); - pos = skipBidiMarks(input, pos); - return pos - start; - } - } - - for (int32_t i = 0; i < affixLength; ) - { - //i = skipRuleWhiteSpace(trimmedAffix, i); - i = skipUWhiteSpace(trimmedAffix, i); - pos = skipUWhiteSpaceAndMarks(input, pos); - - if (i >= affixLength || pos >= inputLength) { - break; - } - - UChar32 c = trimmedAffix.char32At(i); - UChar32 ic = input.char32At(pos); - - if (!equalWithSignCompatibility(ic, c)) { - return -1; - } - - match = TRUE; - i += U16_LENGTH(c); - pos += U16_LENGTH(ic); - pos = skipBidiMarks(input, pos); - } - - if (affixLength > 0 && ! match) { - return -1; - } - } - return pos - start; -} - -/** - * Skip over a run of zero or more Pattern_White_Space characters at - * pos in text. - */ -int32_t DecimalFormat::skipPatternWhiteSpace(const UnicodeString& text, int32_t pos) { - const UChar* s = text.getBuffer(); - return (int32_t)(PatternProps::skipWhiteSpace(s + pos, text.length() - pos) - s); -} - -/** - * Skip over a run of zero or more isUWhiteSpace() characters at pos - * in text. - */ -int32_t DecimalFormat::skipUWhiteSpace(const UnicodeString& text, int32_t pos) { - while (pos < text.length()) { - UChar32 c = text.char32At(pos); - if (!u_isUWhiteSpace(c)) { + // Try to convert to a magnitude multiplier first + int delta = 0; + int value = multiplier; + while (value != 1) { + delta++; + int temp = value / 10; + if (temp * 10 != value) { + delta = -1; break; } - pos += U16_LENGTH(c); + value = temp; } - return pos; -} - -/** - * Skip over a run of zero or more isUWhiteSpace() characters or bidi marks at pos - * in text. - */ -int32_t DecimalFormat::skipUWhiteSpaceAndMarks(const UnicodeString& text, int32_t pos) { - while (pos < text.length()) { - UChar32 c = text.char32At(pos); - if (!u_isUWhiteSpace(c) && !IS_BIDI_MARK(c)) { // u_isUWhiteSpace doesn't include LRM,RLM,ALM - break; - } - pos += U16_LENGTH(c); - } - return pos; -} - -/** - * Skip over a run of zero or more bidi marks at pos in text. - */ -int32_t DecimalFormat::skipBidiMarks(const UnicodeString& text, int32_t pos) { - while (pos < text.length()) { - UChar c = text.charAt(pos); - if (!IS_BIDI_MARK(c)) { - break; - } - pos++; - } - return pos; -} - -/** - * Return the length matched by the given affix, or -1 if none. - * @param affixPat pattern string - * @param input input text - * @param pos offset into input at which to begin matching - * @param type the currency type to parse against, LONG_NAME only or not. - * @param currency return value for parsed currency, for generic - * currency parsing mode, or null for normal parsing. In generic - * currency parsing mode, any currency is parsed, not just the - * currency that this formatter is set to. - * @return length of input that matches, or -1 if match failure - */ -int32_t DecimalFormat::compareComplexAffix(const UnicodeString& affixPat, - const UnicodeString& text, - int32_t pos, - int8_t type, - UChar* currency) const -{ - int32_t start = pos; - U_ASSERT(currency != NULL || fImpl->fMonetary); - - for (int32_t i=0; - i= 0; ) { - UChar32 c = affixPat.char32At(i); - i += U16_LENGTH(c); - - if (c == kQuote) { - U_ASSERT(i <= affixPat.length()); - c = affixPat.char32At(i); - i += U16_LENGTH(c); - - const UnicodeString* affix = NULL; - - switch (c) { - case kCurrencySign: { - // since the currency names in choice format is saved - // the same way as other currency names, - // do not need to do currency choice parsing here. - // the general currency parsing parse against all names, - // including names in choice format. - UBool intl = igetLocale().getName(); - ParsePosition ppos(pos); - UChar curr[4]; - UErrorCode ec = U_ZERO_ERROR; - // Delegate parse of display name => ISO code to Currency - uprv_parseCurrency(loc, text, ppos, type, curr, ec); - - // If parse succeeds, populate currency[0] - if (U_SUCCESS(ec) && ppos.getIndex() != pos) { - if (currency) { - u_strcpy(currency, curr); - } else { - // The formatter is currency-style but the client has not requested - // the value of the parsed currency. In this case, if that value does - // not match the formatter's current value, then the parse fails. - UChar effectiveCurr[4]; - getEffectiveCurrency(effectiveCurr, ec); - if ( U_FAILURE(ec) || u_strncmp(curr,effectiveCurr,4) != 0 ) { - pos = -1; - continue; - } - } - pos = ppos.getIndex(); - } else if (!isLenient()){ - pos = -1; - } - continue; - } - case kPatternPercent: - affix = &fImpl->getConstSymbol(DecimalFormatSymbols::kPercentSymbol); - break; - case kPatternPerMill: - affix = &fImpl->getConstSymbol(DecimalFormatSymbols::kPerMillSymbol); - break; - case kPatternPlus: - affix = &fImpl->getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol); - break; - case kPatternMinus: - affix = &fImpl->getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol); - break; - default: - // fall through to affix!=0 test, which will fail - break; - } - - if (affix != NULL) { - pos = match(text, pos, *affix); - continue; - } - } - - pos = match(text, pos, c); - if (PatternProps::isWhiteSpace(c)) { - i = skipPatternWhiteSpace(affixPat, i); - } - } - return pos - start; -} - -/** - * Match a single character at text[pos] and return the index of the - * next character upon success. Return -1 on failure. If - * ch is a Pattern_White_Space then match a run of white space in text. - */ -int32_t DecimalFormat::match(const UnicodeString& text, int32_t pos, UChar32 ch) { - if (PatternProps::isWhiteSpace(ch)) { - // Advance over run of white space in input text - // Must see at least one white space char in input - int32_t s = pos; - pos = skipPatternWhiteSpace(text, pos); - if (pos == s) { - return -1; - } - return pos; - } - return (pos >= 0 && text.char32At(pos) == ch) ? - (pos + U16_LENGTH(ch)) : -1; -} - -/** - * Match a string at text[pos] and return the index of the next - * character upon success. Return -1 on failure. Match a run of - * white space in str with a run of white space in text. - */ -int32_t DecimalFormat::match(const UnicodeString& text, int32_t pos, const UnicodeString& str) { - for (int32_t i=0; i= 0; ) { - UChar32 ch = str.char32At(i); - i += U16_LENGTH(ch); - if (PatternProps::isWhiteSpace(ch)) { - i = skipPatternWhiteSpace(str, i); - } - pos = match(text, pos, ch); - } - return pos; -} - -UBool DecimalFormat::matchSymbol(const UnicodeString &text, int32_t position, int32_t length, const UnicodeString &symbol, - UnicodeSet *sset, UChar32 schar) -{ - if (sset != NULL) { - return sset->contains(schar); - } - - return text.compare(position, length, symbol) == 0; -} - -UBool DecimalFormat::matchDecimal(UChar32 symbolChar, - UBool sawDecimal, UChar32 sawDecimalChar, - const UnicodeSet *sset, UChar32 schar) { - if(sawDecimal) { - return schar==sawDecimalChar; - } else if(schar==symbolChar) { - return TRUE; - } else if(sset!=NULL) { - return sset->contains(schar); - } else { - return FALSE; - } -} - -UBool DecimalFormat::matchGrouping(UChar32 groupingChar, - UBool sawGrouping, UChar32 sawGroupingChar, - const UnicodeSet *sset, - UChar32 /*decimalChar*/, const UnicodeSet *decimalSet, - UChar32 schar) { - if(sawGrouping) { - return schar==sawGroupingChar; // previously found - } else if(schar==groupingChar) { - return TRUE; // char from symbols - } else if(sset!=NULL) { - return sset->contains(schar) && // in groupingSet but... - ((decimalSet==NULL) || !decimalSet->contains(schar)); // Exclude decimalSet from groupingSet + if (delta != -1) { + fields->properties->magnitudeMultiplier = delta; + fields->properties->multiplier = 1; } else { - return FALSE; + fields->properties->magnitudeMultiplier = 0; + fields->properties->multiplier = multiplier; } + touchNoError(); } - - -//------------------------------------------------------------------------------ -// Gets the pointer to the localized decimal format symbols - -const DecimalFormatSymbols* -DecimalFormat::getDecimalFormatSymbols() const -{ - return &fImpl->getDecimalFormatSymbols(); +int32_t DecimalFormat::getMultiplierScale() const { + return fields->properties->multiplierScale; } -//------------------------------------------------------------------------------ -// De-owning the current localized symbols and adopt the new symbols. - -void -DecimalFormat::adoptDecimalFormatSymbols(DecimalFormatSymbols* symbolsToAdopt) -{ - if (symbolsToAdopt == NULL) { - return; // do not allow caller to set fSymbols to NULL - } - fImpl->adoptDecimalFormatSymbols(symbolsToAdopt); -} -//------------------------------------------------------------------------------ -// Setting the symbols is equlivalent to adopting a newly created localized -// symbols. - -void -DecimalFormat::setDecimalFormatSymbols(const DecimalFormatSymbols& symbols) -{ - adoptDecimalFormatSymbols(new DecimalFormatSymbols(symbols)); +void DecimalFormat::setMultiplierScale(int32_t newValue) { + if (newValue == fields->properties->multiplierScale) { return; } + fields->properties->multiplierScale = newValue; + touchNoError(); } - -const CurrencyPluralInfo* -DecimalFormat::getCurrencyPluralInfo(void) const -{ - return fCurrencyPluralInfo; +double DecimalFormat::getRoundingIncrement(void) const { + return fields->exportedProperties->roundingIncrement; } - -void -DecimalFormat::adoptCurrencyPluralInfo(CurrencyPluralInfo* toAdopt) -{ - if (toAdopt != NULL) { - delete fCurrencyPluralInfo; - fCurrencyPluralInfo = toAdopt; - // re-set currency affix patterns and currency affixes. - if (fImpl->fMonetary) { - UErrorCode status = U_ZERO_ERROR; - if (fAffixPatternsForCurrency) { - deleteHashForAffixPattern(); - } - setupCurrencyAffixPatterns(status); - } - } -} - -void -DecimalFormat::setCurrencyPluralInfo(const CurrencyPluralInfo& info) -{ - adoptCurrencyPluralInfo(info.clone()); -} - - -//------------------------------------------------------------------------------ -// Gets the positive prefix of the number pattern. - -UnicodeString& -DecimalFormat::getPositivePrefix(UnicodeString& result) const -{ - return fImpl->getPositivePrefix(result); -} - -//------------------------------------------------------------------------------ -// Sets the positive prefix of the number pattern. - -void -DecimalFormat::setPositivePrefix(const UnicodeString& newValue) -{ - fImpl->setPositivePrefix(newValue); -} - -//------------------------------------------------------------------------------ -// Gets the negative prefix of the number pattern. - -UnicodeString& -DecimalFormat::getNegativePrefix(UnicodeString& result) const -{ - return fImpl->getNegativePrefix(result); -} - -//------------------------------------------------------------------------------ -// Gets the negative prefix of the number pattern. - -void -DecimalFormat::setNegativePrefix(const UnicodeString& newValue) -{ - fImpl->setNegativePrefix(newValue); -} - -//------------------------------------------------------------------------------ -// Gets the positive suffix of the number pattern. - -UnicodeString& -DecimalFormat::getPositiveSuffix(UnicodeString& result) const -{ - return fImpl->getPositiveSuffix(result); -} - -//------------------------------------------------------------------------------ -// Sets the positive suffix of the number pattern. - -void -DecimalFormat::setPositiveSuffix(const UnicodeString& newValue) -{ - fImpl->setPositiveSuffix(newValue); -} - -//------------------------------------------------------------------------------ -// Gets the negative suffix of the number pattern. - -UnicodeString& -DecimalFormat::getNegativeSuffix(UnicodeString& result) const -{ - return fImpl->getNegativeSuffix(result); -} - -//------------------------------------------------------------------------------ -// Sets the negative suffix of the number pattern. - -void -DecimalFormat::setNegativeSuffix(const UnicodeString& newValue) -{ - fImpl->setNegativeSuffix(newValue); -} - -//------------------------------------------------------------------------------ -// Gets the multiplier of the number pattern. -// Multipliers are stored as decimal numbers (DigitLists) because that -// is the most convenient for muliplying or dividing the numbers to be formatted. -// A NULL multiplier implies one, and the scaling operations are skipped. - -int32_t -DecimalFormat::getMultiplier() const -{ - return fImpl->getMultiplier(); -} - -//------------------------------------------------------------------------------ -// Sets the multiplier of the number pattern. -void -DecimalFormat::setMultiplier(int32_t newValue) -{ - fImpl->setMultiplier(newValue); -} - -/** - * Get the rounding increment. - * @return A positive rounding increment, or 0.0 if rounding - * is not in effect. - * @see #setRoundingIncrement - * @see #getRoundingMode - * @see #setRoundingMode - */ -double DecimalFormat::getRoundingIncrement() const { - return fImpl->getRoundingIncrement(); -} - -/** - * Set the rounding increment. This method also controls whether - * rounding is enabled. - * @param newValue A positive rounding increment, or 0.0 to disable rounding. - * Negative increments are equivalent to 0.0. - * @see #getRoundingIncrement - * @see #getRoundingMode - * @see #setRoundingMode - */ void DecimalFormat::setRoundingIncrement(double newValue) { - fImpl->setRoundingIncrement(newValue); + if (newValue == fields->properties->roundingIncrement) { return; } + fields->properties->roundingIncrement = newValue; + touchNoError(); } -/** - * Get the rounding mode. - * @return A rounding mode - * @see #setRoundingIncrement - * @see #getRoundingIncrement - * @see #setRoundingMode - */ -DecimalFormat::ERoundingMode DecimalFormat::getRoundingMode() const { - return fImpl->getRoundingMode(); +ERoundingMode DecimalFormat::getRoundingMode(void) const { + // UNumberFormatRoundingMode and ERoundingMode have the same values. + return static_cast(fields->exportedProperties->roundingMode.getNoError()); } -/** - * Set the rounding mode. This has no effect unless the rounding - * increment is greater than zero. - * @param roundingMode A rounding mode - * @see #setRoundingIncrement - * @see #getRoundingIncrement - * @see #getRoundingMode - */ void DecimalFormat::setRoundingMode(ERoundingMode roundingMode) { - fImpl->setRoundingMode(roundingMode); + auto uRoundingMode = static_cast(roundingMode); + if (!fields->properties->roundingMode.isNull() && uRoundingMode == fields->properties->roundingMode.getNoError()) { + return; + } + NumberFormat::setMaximumIntegerDigits(roundingMode); // to set field for compatibility + fields->properties->roundingMode = uRoundingMode; + touchNoError(); } -/** - * Get the width to which the output of format() is padded. - * @return the format width, or zero if no padding is in effect - * @see #setFormatWidth - * @see #getPadCharacter - * @see #setPadCharacter - * @see #getPadPosition - * @see #setPadPosition - */ -int32_t DecimalFormat::getFormatWidth() const { - return fImpl->getFormatWidth(); +int32_t DecimalFormat::getFormatWidth(void) const { + return fields->properties->formatWidth; } -/** - * Set the width to which the output of format() is padded. - * This method also controls whether padding is enabled. - * @param width the width to which to pad the result of - * format(), or zero to disable padding. A negative - * width is equivalent to 0. - * @see #getFormatWidth - * @see #getPadCharacter - * @see #setPadCharacter - * @see #getPadPosition - * @see #setPadPosition - */ void DecimalFormat::setFormatWidth(int32_t width) { - int32_t formatWidth = (width > 0) ? width : 0; - fImpl->setFormatWidth(formatWidth); + if (width == fields->properties->formatWidth) { return; } + fields->properties->formatWidth = width; + touchNoError(); } UnicodeString DecimalFormat::getPadCharacterString() const { - return UnicodeString(fImpl->getPadCharacter()); + if (fields->properties->padString.isBogus()) { + // Readonly-alias the static string kFallbackPaddingString + return {TRUE, kFallbackPaddingString, -1}; + } else { + return fields->properties->padString; + } } -void DecimalFormat::setPadCharacter(const UnicodeString &padChar) { - UChar32 pad; +void DecimalFormat::setPadCharacter(const UnicodeString& padChar) { + if (padChar == fields->properties->padString) { return; } if (padChar.length() > 0) { - pad = padChar.char32At(0); + fields->properties->padString = UnicodeString(padChar.char32At(0)); + } else { + fields->properties->padString.setToBogus(); } - else { - pad = kDefaultPad; - } - fImpl->setPadCharacter(pad); + touchNoError(); } -static DecimalFormat::EPadPosition fromPadPosition(DigitAffixesAndPadding::EPadPosition padPos) { - switch (padPos) { - case DigitAffixesAndPadding::kPadBeforePrefix: - return DecimalFormat::kPadBeforePrefix; - case DigitAffixesAndPadding::kPadAfterPrefix: - return DecimalFormat::kPadAfterPrefix; - case DigitAffixesAndPadding::kPadBeforeSuffix: - return DecimalFormat::kPadBeforeSuffix; - case DigitAffixesAndPadding::kPadAfterSuffix: - return DecimalFormat::kPadAfterSuffix; - default: - U_ASSERT(FALSE); - break; +EPadPosition DecimalFormat::getPadPosition(void) const { + if (fields->properties->padPosition.isNull()) { + return EPadPosition::kPadBeforePrefix; + } else { + // UNumberFormatPadPosition and EPadPosition have the same values. + return static_cast(fields->properties->padPosition.getNoError()); } - return DecimalFormat::kPadBeforePrefix; } -/** - * Get the position at which padding will take place. This is the location - * at which padding will be inserted if the result of format() - * is shorter than the format width. - * @return the pad position, one of kPadBeforePrefix, - * kPadAfterPrefix, kPadBeforeSuffix, or - * kPadAfterSuffix. - * @see #setFormatWidth - * @see #getFormatWidth - * @see #setPadCharacter - * @see #getPadCharacter - * @see #setPadPosition - * @see #kPadBeforePrefix - * @see #kPadAfterPrefix - * @see #kPadBeforeSuffix - * @see #kPadAfterSuffix - */ -DecimalFormat::EPadPosition DecimalFormat::getPadPosition() const { - return fromPadPosition(fImpl->getPadPosition()); -} - -static DigitAffixesAndPadding::EPadPosition toPadPosition(DecimalFormat::EPadPosition padPos) { - switch (padPos) { - case DecimalFormat::kPadBeforePrefix: - return DigitAffixesAndPadding::kPadBeforePrefix; - case DecimalFormat::kPadAfterPrefix: - return DigitAffixesAndPadding::kPadAfterPrefix; - case DecimalFormat::kPadBeforeSuffix: - return DigitAffixesAndPadding::kPadBeforeSuffix; - case DecimalFormat::kPadAfterSuffix: - return DigitAffixesAndPadding::kPadAfterSuffix; - default: - U_ASSERT(FALSE); - break; - } - return DigitAffixesAndPadding::kPadBeforePrefix; -} - -/** - * NEW - * Set the position at which padding will take place. This is the location - * at which padding will be inserted if the result of format() - * is shorter than the format width. This has no effect unless padding is - * enabled. - * @param padPos the pad position, one of kPadBeforePrefix, - * kPadAfterPrefix, kPadBeforeSuffix, or - * kPadAfterSuffix. - * @see #setFormatWidth - * @see #getFormatWidth - * @see #setPadCharacter - * @see #getPadCharacter - * @see #getPadPosition - * @see #kPadBeforePrefix - * @see #kPadAfterPrefix - * @see #kPadBeforeSuffix - * @see #kPadAfterSuffix - */ void DecimalFormat::setPadPosition(EPadPosition padPos) { - fImpl->setPadPosition(toPadPosition(padPos)); + auto uPadPos = static_cast(padPos); + if (!fields->properties->padPosition.isNull() && uPadPos == fields->properties->padPosition.getNoError()) { + return; + } + fields->properties->padPosition = uPadPos; + touchNoError(); } -/** - * Return whether or not scientific notation is used. - * @return TRUE if this object formats and parses scientific notation - * @see #setScientificNotation - * @see #getMinimumExponentDigits - * @see #setMinimumExponentDigits - * @see #isExponentSignAlwaysShown - * @see #setExponentSignAlwaysShown - */ -UBool DecimalFormat::isScientificNotation() const { - return fImpl->isScientificNotation(); +UBool DecimalFormat::isScientificNotation(void) const { + return fields->properties->minimumExponentDigits != -1; } -/** - * Set whether or not scientific notation is used. - * @param useScientific TRUE if this object formats and parses scientific - * notation - * @see #isScientificNotation - * @see #getMinimumExponentDigits - * @see #setMinimumExponentDigits - * @see #isExponentSignAlwaysShown - * @see #setExponentSignAlwaysShown - */ void DecimalFormat::setScientificNotation(UBool useScientific) { - fImpl->setScientificNotation(useScientific); + int32_t minExp = useScientific ? 1 : -1; + if (fields->properties->minimumExponentDigits == minExp) { return; } + if (useScientific) { + fields->properties->minimumExponentDigits = 1; + } else { + fields->properties->minimumExponentDigits = -1; + } + touchNoError(); } -/** - * Return the minimum exponent digits that will be shown. - * @return the minimum exponent digits that will be shown - * @see #setScientificNotation - * @see #isScientificNotation - * @see #setMinimumExponentDigits - * @see #isExponentSignAlwaysShown - * @see #setExponentSignAlwaysShown - */ -int8_t DecimalFormat::getMinimumExponentDigits() const { - return fImpl->getMinimumExponentDigits(); +int8_t DecimalFormat::getMinimumExponentDigits(void) const { + return static_cast(fields->properties->minimumExponentDigits); } -/** - * Set the minimum exponent digits that will be shown. This has no - * effect unless scientific notation is in use. - * @param minExpDig a value >= 1 indicating the fewest exponent digits - * that will be shown. Values less than 1 will be treated as 1. - * @see #setScientificNotation - * @see #isScientificNotation - * @see #getMinimumExponentDigits - * @see #isExponentSignAlwaysShown - * @see #setExponentSignAlwaysShown - */ void DecimalFormat::setMinimumExponentDigits(int8_t minExpDig) { - int32_t minExponentDigits = (int8_t)((minExpDig > 0) ? minExpDig : 1); - fImpl->setMinimumExponentDigits(minExponentDigits); + if (minExpDig == fields->properties->minimumExponentDigits) { return; } + fields->properties->minimumExponentDigits = minExpDig; + touchNoError(); } -/** - * Return whether the exponent sign is always shown. - * @return TRUE if the exponent is always prefixed with either the - * localized minus sign or the localized plus sign, false if only negative - * exponents are prefixed with the localized minus sign. - * @see #setScientificNotation - * @see #isScientificNotation - * @see #setMinimumExponentDigits - * @see #getMinimumExponentDigits - * @see #setExponentSignAlwaysShown - */ -UBool DecimalFormat::isExponentSignAlwaysShown() const { - return fImpl->isExponentSignAlwaysShown(); +UBool DecimalFormat::isExponentSignAlwaysShown(void) const { + return fields->properties->exponentSignAlwaysShown; } -/** - * Set whether the exponent sign is always shown. This has no effect - * unless scientific notation is in use. - * @param expSignAlways TRUE if the exponent is always prefixed with either - * the localized minus sign or the localized plus sign, false if only - * negative exponents are prefixed with the localized minus sign. - * @see #setScientificNotation - * @see #isScientificNotation - * @see #setMinimumExponentDigits - * @see #getMinimumExponentDigits - * @see #isExponentSignAlwaysShown - */ void DecimalFormat::setExponentSignAlwaysShown(UBool expSignAlways) { - fImpl->setExponentSignAlwaysShown(expSignAlways); + if (UBOOL_TO_BOOL(expSignAlways) == fields->properties->exponentSignAlwaysShown) { return; } + fields->properties->exponentSignAlwaysShown = expSignAlways; + touchNoError(); } -//------------------------------------------------------------------------------ -// Gets the grouping size of the number pattern. For example, thousand or 10 -// thousand groupings. - -int32_t -DecimalFormat::getGroupingSize() const -{ - return fImpl->getGroupingSize(); -} - -//------------------------------------------------------------------------------ -// Gets the grouping size of the number pattern. - -void -DecimalFormat::setGroupingSize(int32_t newValue) -{ - fImpl->setGroupingSize(newValue); -} - -//------------------------------------------------------------------------------ - -int32_t -DecimalFormat::getSecondaryGroupingSize() const -{ - return fImpl->getSecondaryGroupingSize(); -} - -//------------------------------------------------------------------------------ - -void -DecimalFormat::setSecondaryGroupingSize(int32_t newValue) -{ - fImpl->setSecondaryGroupingSize(newValue); -} - -//------------------------------------------------------------------------------ - -int32_t -DecimalFormat::getMinimumGroupingDigits() const -{ - return fImpl->getMinimumGroupingDigits(); -} - -//------------------------------------------------------------------------------ - -void -DecimalFormat::setMinimumGroupingDigits(int32_t newValue) -{ - fImpl->setMinimumGroupingDigits(newValue); -} - -//------------------------------------------------------------------------------ -// Checks if to show the decimal separator. - -UBool -DecimalFormat::isDecimalSeparatorAlwaysShown() const -{ - return fImpl->isDecimalSeparatorAlwaysShown(); -} - -//------------------------------------------------------------------------------ -// Sets to always show the decimal separator. - -void -DecimalFormat::setDecimalSeparatorAlwaysShown(UBool newValue) -{ - fImpl->setDecimalSeparatorAlwaysShown(newValue); -} - -//------------------------------------------------------------------------------ -// Checks if decimal point pattern match is required -UBool -DecimalFormat::isDecimalPatternMatchRequired(void) const -{ - return static_cast(fBoolFlags.contains(UNUM_PARSE_DECIMAL_MARK_REQUIRED)); -} - -//------------------------------------------------------------------------------ -// Checks if decimal point pattern match is required - -void -DecimalFormat::setDecimalPatternMatchRequired(UBool newValue) -{ - fBoolFlags.set(UNUM_PARSE_DECIMAL_MARK_REQUIRED, newValue); -} - - -//------------------------------------------------------------------------------ -// Emits the pattern of this DecimalFormat instance. - -UnicodeString& -DecimalFormat::toPattern(UnicodeString& result) const -{ - return fImpl->toPattern(result); -} - -//------------------------------------------------------------------------------ -// Emits the localized pattern this DecimalFormat instance. - -UnicodeString& -DecimalFormat::toLocalizedPattern(UnicodeString& result) const -{ - // toLocalizedPattern is deprecated, so we just make it the same as - // toPattern. - return fImpl->toPattern(result); -} - -//------------------------------------------------------------------------------ - -void -DecimalFormat::applyPattern(const UnicodeString& pattern, UErrorCode& status) -{ - if (pattern.indexOf(kCurrencySign) != -1) { - handleCurrencySignInPattern(status); +int32_t DecimalFormat::getGroupingSize(void) const { + if (fields->properties->groupingSize < 0) { + return 0; } - fImpl->applyPattern(pattern, status); + return fields->properties->groupingSize; } -//------------------------------------------------------------------------------ +void DecimalFormat::setGroupingSize(int32_t newValue) { + if (newValue == fields->properties->groupingSize) { return; } + fields->properties->groupingSize = newValue; + touchNoError(); +} -void -DecimalFormat::applyPattern(const UnicodeString& pattern, - UParseError& parseError, - UErrorCode& status) -{ - if (pattern.indexOf(kCurrencySign) != -1) { - handleCurrencySignInPattern(status); +int32_t DecimalFormat::getSecondaryGroupingSize(void) const { + int grouping2 = fields->properties->secondaryGroupingSize; + if (grouping2 < 0) { + return 0; } - fImpl->applyPattern(pattern, parseError, status); + return grouping2; } -//------------------------------------------------------------------------------ -void -DecimalFormat::applyLocalizedPattern(const UnicodeString& pattern, UErrorCode& status) -{ - if (pattern.indexOf(kCurrencySign) != -1) { - handleCurrencySignInPattern(status); +void DecimalFormat::setSecondaryGroupingSize(int32_t newValue) { + if (newValue == fields->properties->secondaryGroupingSize) { return; } + fields->properties->secondaryGroupingSize = newValue; + touchNoError(); +} + +int32_t DecimalFormat::getMinimumGroupingDigits() const { + return fields->properties->minimumGroupingDigits; +} + +void DecimalFormat::setMinimumGroupingDigits(int32_t newValue) { + if (newValue == fields->properties->minimumGroupingDigits) { return; } + fields->properties->minimumGroupingDigits = newValue; + touchNoError(); +} + +UBool DecimalFormat::isDecimalSeparatorAlwaysShown(void) const { + return fields->properties->decimalSeparatorAlwaysShown; +} + +void DecimalFormat::setDecimalSeparatorAlwaysShown(UBool newValue) { + if (UBOOL_TO_BOOL(newValue) == fields->properties->decimalSeparatorAlwaysShown) { return; } + fields->properties->decimalSeparatorAlwaysShown = newValue; + touchNoError(); +} + +UBool DecimalFormat::isDecimalPatternMatchRequired(void) const { + return fields->properties->decimalPatternMatchRequired; +} + +void DecimalFormat::setDecimalPatternMatchRequired(UBool newValue) { + if (UBOOL_TO_BOOL(newValue) == fields->properties->decimalPatternMatchRequired) { return; } + fields->properties->decimalPatternMatchRequired = newValue; + touchNoError(); +} + +UBool DecimalFormat::isParseNoExponent() const { + return fields->properties->parseNoExponent; +} + +void DecimalFormat::setParseNoExponent(UBool value) { + if (UBOOL_TO_BOOL(value) == fields->properties->parseNoExponent) { return; } + fields->properties->parseNoExponent = value; + touchNoError(); +} + +UBool DecimalFormat::isParseCaseSensitive() const { + return fields->properties->parseCaseSensitive; +} + +void DecimalFormat::setParseCaseSensitive(UBool value) { + if (UBOOL_TO_BOOL(value) == fields->properties->parseCaseSensitive) { return; } + fields->properties->parseCaseSensitive = value; + touchNoError(); +} + +UBool DecimalFormat::isFormatFailIfMoreThanMaxDigits() const { + return fields->properties->formatFailIfMoreThanMaxDigits; +} + +void DecimalFormat::setFormatFailIfMoreThanMaxDigits(UBool value) { + if (UBOOL_TO_BOOL(value) == fields->properties->formatFailIfMoreThanMaxDigits) { return; } + fields->properties->formatFailIfMoreThanMaxDigits = value; + touchNoError(); +} + +UnicodeString& DecimalFormat::toPattern(UnicodeString& result) const { + // Pull some properties from exportedProperties and others from properties + // to keep affix patterns intact. In particular, pull rounding properties + // so that CurrencyUsage is reflected properly. + // TODO: Consider putting this logic in number_patternstring.cpp instead. + ErrorCode localStatus; + DecimalFormatProperties tprops(*fields->properties); + bool useCurrency = ((!tprops.currency.isNull()) || !tprops.currencyPluralInfo.fPtr.isNull() || + !tprops.currencyUsage.isNull() || AffixUtils::hasCurrencySymbols( + tprops.positivePrefixPattern, localStatus) || AffixUtils::hasCurrencySymbols( + tprops.positiveSuffixPattern, localStatus) || AffixUtils::hasCurrencySymbols( + tprops.negativePrefixPattern, localStatus) || AffixUtils::hasCurrencySymbols( + tprops.negativeSuffixPattern, localStatus)); + if (useCurrency) { + tprops.minimumFractionDigits = fields->exportedProperties->minimumFractionDigits; + tprops.maximumFractionDigits = fields->exportedProperties->maximumFractionDigits; + tprops.roundingIncrement = fields->exportedProperties->roundingIncrement; } - fImpl->applyLocalizedPattern(pattern, status); + result = PatternStringUtils::propertiesToPatternString(tprops, localStatus); + return result; } -//------------------------------------------------------------------------------ +UnicodeString& DecimalFormat::toLocalizedPattern(UnicodeString& result) const { + ErrorCode localStatus; + result = toPattern(result); + result = PatternStringUtils::convertLocalized(result, *fields->symbols, true, localStatus); + return result; +} -void -DecimalFormat::applyLocalizedPattern(const UnicodeString& pattern, - UParseError& parseError, - UErrorCode& status) -{ - if (pattern.indexOf(kCurrencySign) != -1) { - handleCurrencySignInPattern(status); +void DecimalFormat::applyPattern(const UnicodeString& pattern, UParseError&, UErrorCode& status) { + // TODO: What is parseError for? + applyPattern(pattern, status); +} + +void DecimalFormat::applyPattern(const UnicodeString& pattern, UErrorCode& status) { + setPropertiesFromPattern(pattern, IGNORE_ROUNDING_NEVER, status); + touch(status); +} + +void DecimalFormat::applyLocalizedPattern(const UnicodeString& localizedPattern, UParseError&, + UErrorCode& status) { + // TODO: What is parseError for? + applyLocalizedPattern(localizedPattern, status); +} + +void DecimalFormat::applyLocalizedPattern(const UnicodeString& localizedPattern, UErrorCode& status) { + if (U_SUCCESS(status)) { + UnicodeString pattern = PatternStringUtils::convertLocalized( + localizedPattern, *fields->symbols, false, status); + applyPattern(pattern, status); } - fImpl->applyLocalizedPattern(pattern, parseError, status); } -//------------------------------------------------------------------------------ - -/** - * Sets the maximum number of digits allowed in the integer portion of a - * number. - * @see NumberFormat#setMaximumIntegerDigits - */ void DecimalFormat::setMaximumIntegerDigits(int32_t newValue) { - newValue = _min(newValue, gDefaultMaxIntegerDigits); - NumberFormat::setMaximumIntegerDigits(newValue); - fImpl->updatePrecision(); + if (newValue == fields->properties->maximumIntegerDigits) { return; } + // For backwards compatibility, conflicting min/max need to keep the most recent setting. + int32_t min = fields->properties->minimumIntegerDigits; + if (min >= 0 && min > newValue) { + fields->properties->minimumIntegerDigits = newValue; + } + fields->properties->maximumIntegerDigits = newValue; + touchNoError(); } -/** - * Sets the minimum number of digits allowed in the integer portion of a - * number. This override limits the integer digit count to 309. - * @see NumberFormat#setMinimumIntegerDigits - */ void DecimalFormat::setMinimumIntegerDigits(int32_t newValue) { - newValue = _min(newValue, kDoubleIntegerDigits); - NumberFormat::setMinimumIntegerDigits(newValue); - fImpl->updatePrecision(); + if (newValue == fields->properties->minimumIntegerDigits) { return; } + // For backwards compatibility, conflicting min/max need to keep the most recent setting. + int32_t max = fields->properties->maximumIntegerDigits; + if (max >= 0 && max < newValue) { + fields->properties->maximumIntegerDigits = newValue; + } + fields->properties->minimumIntegerDigits = newValue; + touchNoError(); } -/** - * Sets the maximum number of digits allowed in the fraction portion of a - * number. This override limits the fraction digit count to 340. - * @see NumberFormat#setMaximumFractionDigits - */ void DecimalFormat::setMaximumFractionDigits(int32_t newValue) { - newValue = _min(newValue, kDoubleFractionDigits); - NumberFormat::setMaximumFractionDigits(newValue); - fImpl->updatePrecision(); + if (newValue == fields->properties->maximumFractionDigits) { return; } + // For backwards compatibility, conflicting min/max need to keep the most recent setting. + int32_t min = fields->properties->minimumFractionDigits; + if (min >= 0 && min > newValue) { + fields->properties->minimumFractionDigits = newValue; + } + fields->properties->maximumFractionDigits = newValue; + touchNoError(); } -/** - * Sets the minimum number of digits allowed in the fraction portion of a - * number. This override limits the fraction digit count to 340. - * @see NumberFormat#setMinimumFractionDigits - */ void DecimalFormat::setMinimumFractionDigits(int32_t newValue) { - newValue = _min(newValue, kDoubleFractionDigits); - NumberFormat::setMinimumFractionDigits(newValue); - fImpl->updatePrecision(); + if (newValue == fields->properties->minimumFractionDigits) { return; } + // For backwards compatibility, conflicting min/max need to keep the most recent setting. + int32_t max = fields->properties->maximumFractionDigits; + if (max >= 0 && max < newValue) { + fields->properties->maximumFractionDigits = newValue; + } + fields->properties->minimumFractionDigits = newValue; + touchNoError(); } int32_t DecimalFormat::getMinimumSignificantDigits() const { - return fImpl->getMinimumSignificantDigits(); + return fields->exportedProperties->minimumSignificantDigits; } int32_t DecimalFormat::getMaximumSignificantDigits() const { - return fImpl->getMaximumSignificantDigits(); + return fields->exportedProperties->maximumSignificantDigits; } -void DecimalFormat::setMinimumSignificantDigits(int32_t min) { - if (min < 1) { - min = 1; +void DecimalFormat::setMinimumSignificantDigits(int32_t value) { + if (value == fields->properties->minimumSignificantDigits) { return; } + int32_t max = fields->properties->maximumSignificantDigits; + if (max >= 0 && max < value) { + fields->properties->maximumSignificantDigits = value; } - // pin max sig dig to >= min - int32_t max = _max(fImpl->fMaxSigDigits, min); - fImpl->setMinMaxSignificantDigits(min, max); + fields->properties->minimumSignificantDigits = value; + touchNoError(); } -void DecimalFormat::setMaximumSignificantDigits(int32_t max) { - if (max < 1) { - max = 1; +void DecimalFormat::setMaximumSignificantDigits(int32_t value) { + if (value == fields->properties->maximumSignificantDigits) { return; } + int32_t min = fields->properties->minimumSignificantDigits; + if (min >= 0 && min > value) { + fields->properties->minimumSignificantDigits = value; } - // pin min sig dig to 1..max - U_ASSERT(fImpl->fMinSigDigits >= 1); - int32_t min = _min(fImpl->fMinSigDigits, max); - fImpl->setMinMaxSignificantDigits(min, max); + fields->properties->maximumSignificantDigits = value; + touchNoError(); } UBool DecimalFormat::areSignificantDigitsUsed() const { - return fImpl->areSignificantDigitsUsed(); + return fields->properties->minimumSignificantDigits != -1 || fields->properties->maximumSignificantDigits != -1; } void DecimalFormat::setSignificantDigitsUsed(UBool useSignificantDigits) { - fImpl->setSignificantDigitsUsed(useSignificantDigits); + // These are the default values from the old implementation. + 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(); } -void DecimalFormat::setCurrency(const UChar* theCurrency, UErrorCode& ec) { - // set the currency before compute affixes to get the right currency names - NumberFormat::setCurrency(theCurrency, ec); - fImpl->updateCurrency(ec); +void DecimalFormat::setCurrency(const char16_t* theCurrency, UErrorCode& ec) { + CurrencyUnit currencyUnit(theCurrency, ec); + if (U_FAILURE(ec)) { return; } + if (!fields->properties->currency.isNull() && fields->properties->currency.getNoError() == currencyUnit) { + return; + } + NumberFormat::setCurrency(theCurrency, ec); // to set field for compatibility + fields->properties->currency = currencyUnit; + // TODO: Set values in fields->symbols, too? + touchNoError(); } -void DecimalFormat::setCurrencyUsage(UCurrencyUsage newContext, UErrorCode* ec){ - fImpl->setCurrencyUsage(newContext, *ec); +void DecimalFormat::setCurrency(const char16_t* theCurrency) { + ErrorCode localStatus; + setCurrency(theCurrency, localStatus); +} + +void DecimalFormat::setCurrencyUsage(UCurrencyUsage newUsage, UErrorCode* ec) { + if (U_FAILURE(*ec)) { + return; + } + if (!fields->properties->currencyUsage.isNull() && newUsage == fields->properties->currencyUsage.getNoError()) { + return; + } + fields->properties->currencyUsage = newUsage; + touch(*ec); } UCurrencyUsage DecimalFormat::getCurrencyUsage() const { - return fImpl->getCurrencyUsage(); + // CurrencyUsage is not exported, so we have to get it from the input property bag. + // TODO: Should we export CurrencyUsage instead? + if (fields->properties->currencyUsage.isNull()) { + return UCURR_USAGE_STANDARD; + } + return fields->properties->currencyUsage.getNoError(); } -// Deprecated variant with no UErrorCode parameter -void DecimalFormat::setCurrency(const UChar* theCurrency) { - UErrorCode ec = U_ZERO_ERROR; - setCurrency(theCurrency, ec); +void +DecimalFormat::formatToDecimalQuantity(double number, DecimalQuantity& output, UErrorCode& status) const { + fields->formatter->formatDouble(number, status).getDecimalQuantity(output, status); } -void DecimalFormat::getEffectiveCurrency(UChar* result, UErrorCode& ec) const { - if (fImpl->fSymbols == NULL) { - ec = U_MEMORY_ALLOCATION_ERROR; +void DecimalFormat::formatToDecimalQuantity(const Formattable& number, DecimalQuantity& output, + UErrorCode& status) const { + UFormattedNumberData obj; + number.populateDecimalQuantity(obj.quantity, status); + fields->formatter->formatImpl(&obj, status); + output = std::move(obj.quantity); +} + +const number::LocalizedNumberFormatter& DecimalFormat::toNumberFormatter() const { + return *fields->formatter; +} + +/** Rebuilds the formatter object from the property bag. */ +void DecimalFormat::touch(UErrorCode& status) { + if (fields->exportedProperties == nullptr) { + // fields->exportedProperties is null only when the formatter is not ready yet. + // The only time when this happens is during legacy deserialization. return; } - ec = U_ZERO_ERROR; - const UChar* c = getCurrency(); - if (*c == 0) { - const UnicodeString &intl = - fImpl->getConstSymbol(DecimalFormatSymbols::kIntlCurrencySymbol); - c = intl.getBuffer(); // ok for intl to go out of scope - } - u_strncpy(result, c, 3); - result[3] = 0; + + // In C++, fields->symbols is the source of truth for the locale. + Locale locale = fields->symbols->getLocale(); + + // Note: The formatter is relatively cheap to create, and we need it to populate fields->exportedProperties, + // so automatically compute it here. The parser is a bit more expensive and is not needed until the + // parse method is called, so defer that until needed. + // TODO: Only update the pieces that changed instead of re-computing the whole formatter? + fields->formatter.adoptInstead( + new LocalizedNumberFormatter( + NumberPropertyMapper::create( + *fields->properties, *fields->symbols, fields->warehouse, *fields->exportedProperties, status).locale( + locale))); + + // Do this after fields->exportedProperties are set up + setupFastFormat(); + + // Delete the parsers if they were made previously + delete fields->atomicParser.exchange(nullptr); + delete fields->atomicCurrencyParser.exchange(nullptr); + + // In order for the getters to work, we need to populate some fields in NumberFormat. + NumberFormat::setCurrency(fields->exportedProperties->currency.get(status).getISOCurrency(), status); + NumberFormat::setMaximumIntegerDigits(fields->exportedProperties->maximumIntegerDigits); + NumberFormat::setMinimumIntegerDigits(fields->exportedProperties->minimumIntegerDigits); + NumberFormat::setMaximumFractionDigits(fields->exportedProperties->maximumFractionDigits); + NumberFormat::setMinimumFractionDigits(fields->exportedProperties->minimumFractionDigits); + // fImpl->properties, not fields->exportedProperties, since this information comes from the pattern: + NumberFormat::setGroupingUsed(fields->properties->groupingUsed); } -Hashtable* -DecimalFormat::initHashForAffixPattern(UErrorCode& status) { - if ( U_FAILURE(status) ) { - return NULL; +void DecimalFormat::touchNoError() { + UErrorCode localStatus = U_ZERO_ERROR; + touch(localStatus); +} + +void DecimalFormat::setPropertiesFromPattern(const UnicodeString& pattern, int32_t ignoreRounding, + UErrorCode& status) { + if (U_SUCCESS(status)) { + // Cast workaround to get around putting the enum in the public header file + auto actualIgnoreRounding = static_cast(ignoreRounding); + PatternParser::parseToExistingProperties(pattern, *fields->properties, actualIgnoreRounding, status); } - Hashtable* hTable; - if ( (hTable = new Hashtable(TRUE, status)) == NULL ) { +} + +const numparse::impl::NumberParserImpl* DecimalFormat::getParser(UErrorCode& status) const { + if (U_FAILURE(status)) { return nullptr; } + + // First try to get the pre-computed parser + auto* ptr = fields->atomicParser.load(); + if (ptr != nullptr) { + return ptr; + } + + // Try computing the parser on our own + auto* temp = NumberParserImpl::createParserFromProperties(*fields->properties, *fields->symbols, false, status); + if (temp == nullptr) { status = U_MEMORY_ALLOCATION_ERROR; - return NULL; + // although we may still dereference, call sites should be guarded } - if ( U_FAILURE(status) ) { - delete hTable; - return NULL; + + // 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 + delete temp; + return ptr; + } else { + // Our copy of the parser got stored in the atomic + return temp; + } +} + +const numparse::impl::NumberParserImpl* DecimalFormat::getCurrencyParser(UErrorCode& status) const { + if (U_FAILURE(status)) { return nullptr; } + + // First try to get the pre-computed parser + auto* ptr = fields->atomicCurrencyParser.load(); + if (ptr != nullptr) { + return ptr; + } + + // Try computing the parser on our own + auto* temp = NumberParserImpl::createParserFromProperties(*fields->properties, *fields->symbols, true, status); + if (temp == nullptr) { + status = U_MEMORY_ALLOCATION_ERROR; + // although we may still dereference, call sites should be guarded + } + + // 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->atomicCurrencyParser.compare_exchange_strong(ptr, temp)) { + // Another thread beat us to computing the parser + delete temp; + return ptr; + } else { + // Our copy of the parser got stored in the atomic + return temp; } - hTable->setValueComparator(decimfmtAffixPatternValueComparator); - return hTable; } void -DecimalFormat::deleteHashForAffixPattern() -{ - if ( fAffixPatternsForCurrency == NULL ) { - return; +DecimalFormat::fieldPositionHelper(const number::FormattedNumber& formatted, FieldPosition& fieldPosition, + int32_t offset, UErrorCode& status) { + // always return first occurrence: + fieldPosition.setBeginIndex(0); + fieldPosition.setEndIndex(0); + bool found = formatted.nextFieldPosition(fieldPosition, status); + if (found && offset != 0) { + FieldPositionOnlyHandler fpoh(fieldPosition); + fpoh.shiftLast(offset); } - int32_t pos = UHASH_FIRST; - const UHashElement* element = NULL; - while ( (element = fAffixPatternsForCurrency->nextElement(pos)) != NULL ) { - const UHashTok valueTok = element->value; - const AffixPatternsForCurrency* value = (AffixPatternsForCurrency*)valueTok.pointer; - delete value; - } - delete fAffixPatternsForCurrency; - fAffixPatternsForCurrency = NULL; } - void -DecimalFormat::copyHashForAffixPattern(const Hashtable* source, - Hashtable* target, - UErrorCode& status) { - if ( U_FAILURE(status) ) { +DecimalFormat::fieldPositionIteratorHelper(const number::FormattedNumber& formatted, FieldPositionIterator* fpi, + int32_t offset, UErrorCode& status) { + if (fpi != nullptr) { + FieldPositionIteratorHandler fpih(fpi, status); + fpih.setShift(offset); + formatted.getAllFieldPositionsImpl(fpih, status); + } +} + +// To debug fast-format, change void(x) to printf(x) +#define trace(x) void(x) + +void DecimalFormat::setupFastFormat() { + // Check the majority of properties: + if (!fields->properties->equalsDefaultExceptFastFormat()) { + trace("no fast format: equality\n"); + fields->canUseFastFormat = false; return; } - int32_t pos = UHASH_FIRST; - const UHashElement* element = NULL; - if ( source ) { - while ( (element = source->nextElement(pos)) != NULL ) { - const UHashTok keyTok = element->key; - const UnicodeString* key = (UnicodeString*)keyTok.pointer; - const UHashTok valueTok = element->value; - const AffixPatternsForCurrency* value = (AffixPatternsForCurrency*)valueTok.pointer; - AffixPatternsForCurrency* copy = new AffixPatternsForCurrency( - value->negPrefixPatternForCurrency, - value->negSuffixPatternForCurrency, - value->posPrefixPatternForCurrency, - value->posSuffixPatternForCurrency, - value->patternType); - target->put(UnicodeString(*key), copy, status); - if ( U_FAILURE(status) ) { - return; - } + + // Now check the remaining properties. + // Nontrivial affixes: + UBool trivialPP = fields->properties->positivePrefixPattern.isEmpty(); + UBool trivialPS = fields->properties->positiveSuffixPattern.isEmpty(); + UBool trivialNP = fields->properties->negativePrefixPattern.isBogus() || ( + fields->properties->negativePrefixPattern.length() == 1 && + fields->properties->negativePrefixPattern.charAt(0) == u'-'); + UBool trivialNS = fields->properties->negativeSuffixPattern.isEmpty(); + if (!trivialPP || !trivialPS || !trivialNP || !trivialNS) { + trace("no fast format: affixes\n"); + fields->canUseFastFormat = false; + return; + } + + // Grouping (secondary grouping is forbidden in equalsDefaultExceptFastFormat): + bool groupingUsed = fields->properties->groupingUsed; + int32_t groupingSize = fields->properties->groupingSize; + bool unusualGroupingSize = groupingSize > 0 && groupingSize != 3; + const UnicodeString& groupingString = fields->symbols->getConstSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol); + if (groupingUsed && (unusualGroupingSize || groupingString.length() != 1)) { + trace("no fast format: grouping\n"); + fields->canUseFastFormat = false; + return; + } + + // Integer length: + int32_t minInt = fields->exportedProperties->minimumIntegerDigits; + int32_t maxInt = fields->exportedProperties->maximumIntegerDigits; + // Fastpath supports up to only 10 digits (length of INT32_MIN) + if (minInt > 10) { + trace("no fast format: integer\n"); + fields->canUseFastFormat = false; + return; + } + + // Fraction length (no fraction part allowed in fast path): + int32_t minFrac = fields->exportedProperties->minimumFractionDigits; + if (minFrac > 0) { + trace("no fast format: fraction\n"); + fields->canUseFastFormat = false; + return; + } + + // Other symbols: + const UnicodeString& minusSignString = fields->symbols->getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol); + UChar32 codePointZero = fields->symbols->getCodePointZero(); + if (minusSignString.length() != 1 || U16_LENGTH(codePointZero) != 1) { + trace("no fast format: symbols\n"); + fields->canUseFastFormat = false; + return; + } + + // Good to go! + trace("can use fast format!\n"); + fields->canUseFastFormat = true; + fields->fastData.cpZero = static_cast(codePointZero); + fields->fastData.cpGroupingSeparator = groupingUsed && groupingSize == 3 ? groupingString.charAt(0) : 0; + fields->fastData.cpMinusSign = minusSignString.charAt(0); + fields->fastData.minInt = (minInt < 0 || minInt > 127) ? 0 : static_cast(minInt); + fields->fastData.maxInt = (maxInt < 0 || maxInt > 127) ? 127 : static_cast(maxInt); +} + +bool DecimalFormat::fastFormatDouble(double input, UnicodeString& output) const { + if (!fields->canUseFastFormat) { + return false; + } + if (std::isnan(input) + || std::trunc(input) != input + || input <= INT32_MIN + || input > INT32_MAX) { + return false; + } + doFastFormatInt32(static_cast(input), std::signbit(input), output); + return true; +} + +bool DecimalFormat::fastFormatInt64(int64_t input, UnicodeString& output) const { + if (!fields->canUseFastFormat) { + return false; + } + if (input <= INT32_MIN || input > INT32_MAX) { + return false; + } + doFastFormatInt32(static_cast(input), input < 0, output); + return true; +} + +void DecimalFormat::doFastFormatInt32(int32_t input, bool isNegative, UnicodeString& output) const { + U_ASSERT(fields->canUseFastFormat); + if (isNegative) { + output.append(fields->fastData.cpMinusSign); + U_ASSERT(input != INT32_MIN); // handled by callers + input = -input; + } + // Cap at int32_t to make the buffer small and operations fast. + // Longest string: "2,147,483,648" (13 chars in length) + static constexpr int32_t localCapacity = 13; + char16_t localBuffer[localCapacity]; + char16_t* ptr = localBuffer + localCapacity; + int8_t group = 0; + for (int8_t i = 0; i < fields->fastData.maxInt && (input != 0 || i < fields->fastData.minInt); i++) { + if (group++ == 3 && fields->fastData.cpGroupingSeparator != 0) { + *(--ptr) = fields->fastData.cpGroupingSeparator; + group = 1; } + std::div_t res = std::div(input, 10); + *(--ptr) = static_cast(fields->fastData.cpZero + res.rem); + input = res.quot; } + int32_t len = localCapacity - static_cast(ptr - localBuffer); + output.append(ptr, len); } -void -DecimalFormat::setGroupingUsed(UBool newValue) { - NumberFormat::setGroupingUsed(newValue); - fImpl->updateGrouping(); -} - -void -DecimalFormat::setParseIntegerOnly(UBool newValue) { - NumberFormat::setParseIntegerOnly(newValue); -} - -void -DecimalFormat::setContext(UDisplayContext value, UErrorCode& status) { - NumberFormat::setContext(value, status); -} - -DecimalFormat& DecimalFormat::setAttribute( UNumberFormatAttribute attr, - int32_t newValue, - UErrorCode &status) { - if(U_FAILURE(status)) return *this; - - switch(attr) { - case UNUM_LENIENT_PARSE: - setLenient(newValue!=0); - break; - - case UNUM_PARSE_INT_ONLY: - setParseIntegerOnly(newValue!=0); - break; - - case UNUM_GROUPING_USED: - setGroupingUsed(newValue!=0); - break; - - case UNUM_DECIMAL_ALWAYS_SHOWN: - setDecimalSeparatorAlwaysShown(newValue!=0); - break; - - case UNUM_MAX_INTEGER_DIGITS: - setMaximumIntegerDigits(newValue); - break; - - case UNUM_MIN_INTEGER_DIGITS: - setMinimumIntegerDigits(newValue); - break; - - case UNUM_INTEGER_DIGITS: - setMinimumIntegerDigits(newValue); - setMaximumIntegerDigits(newValue); - break; - - case UNUM_MAX_FRACTION_DIGITS: - setMaximumFractionDigits(newValue); - break; - - case UNUM_MIN_FRACTION_DIGITS: - setMinimumFractionDigits(newValue); - break; - - case UNUM_FRACTION_DIGITS: - setMinimumFractionDigits(newValue); - setMaximumFractionDigits(newValue); - break; - - case UNUM_SIGNIFICANT_DIGITS_USED: - setSignificantDigitsUsed(newValue!=0); - break; - - case UNUM_MAX_SIGNIFICANT_DIGITS: - setMaximumSignificantDigits(newValue); - break; - - case UNUM_MIN_SIGNIFICANT_DIGITS: - setMinimumSignificantDigits(newValue); - break; - - case UNUM_MULTIPLIER: - setMultiplier(newValue); - break; - - case UNUM_GROUPING_SIZE: - setGroupingSize(newValue); - break; - - case UNUM_ROUNDING_MODE: - setRoundingMode((DecimalFormat::ERoundingMode)newValue); - break; - - case UNUM_FORMAT_WIDTH: - setFormatWidth(newValue); - break; - - case UNUM_PADDING_POSITION: - /** The position at which padding will take place. */ - setPadPosition((DecimalFormat::EPadPosition)newValue); - break; - - case UNUM_SECONDARY_GROUPING_SIZE: - setSecondaryGroupingSize(newValue); - break; - -#if UCONFIG_HAVE_PARSEALLINPUT - case UNUM_PARSE_ALL_INPUT: - setParseAllInput((UNumberFormatAttributeValue)newValue); - break; -#endif - - /* These are stored in fBoolFlags */ - case UNUM_PARSE_NO_EXPONENT: - case UNUM_FORMAT_FAIL_IF_MORE_THAN_MAX_DIGITS: - case UNUM_PARSE_DECIMAL_MARK_REQUIRED: - if(!fBoolFlags.isValidValue(newValue)) { - status = U_ILLEGAL_ARGUMENT_ERROR; - } else { - if (attr == UNUM_FORMAT_FAIL_IF_MORE_THAN_MAX_DIGITS) { - fImpl->setFailIfMoreThanMaxDigits((UBool) newValue); - } - fBoolFlags.set(attr, newValue); - } - break; - - case UNUM_SCALE: - fImpl->setScale(newValue); - break; - - case UNUM_CURRENCY_USAGE: - setCurrencyUsage((UCurrencyUsage)newValue, &status); - break; - - case UNUM_MINIMUM_GROUPING_DIGITS: - setMinimumGroupingDigits(newValue); - break; - - default: - status = U_UNSUPPORTED_ERROR; - break; - } - return *this; -} - -int32_t DecimalFormat::getAttribute( UNumberFormatAttribute attr, - UErrorCode &status ) const { - if(U_FAILURE(status)) return -1; - switch(attr) { - case UNUM_LENIENT_PARSE: - return isLenient(); - - case UNUM_PARSE_INT_ONLY: - return isParseIntegerOnly(); - - case UNUM_GROUPING_USED: - return isGroupingUsed(); - - case UNUM_DECIMAL_ALWAYS_SHOWN: - return isDecimalSeparatorAlwaysShown(); - - case UNUM_MAX_INTEGER_DIGITS: - return getMaximumIntegerDigits(); - - case UNUM_MIN_INTEGER_DIGITS: - return getMinimumIntegerDigits(); - - case UNUM_INTEGER_DIGITS: - // TBD: what should this return? - return getMinimumIntegerDigits(); - - case UNUM_MAX_FRACTION_DIGITS: - return getMaximumFractionDigits(); - - case UNUM_MIN_FRACTION_DIGITS: - return getMinimumFractionDigits(); - - case UNUM_FRACTION_DIGITS: - // TBD: what should this return? - return getMinimumFractionDigits(); - - case UNUM_SIGNIFICANT_DIGITS_USED: - return areSignificantDigitsUsed(); - - case UNUM_MAX_SIGNIFICANT_DIGITS: - return getMaximumSignificantDigits(); - - case UNUM_MIN_SIGNIFICANT_DIGITS: - return getMinimumSignificantDigits(); - - case UNUM_MULTIPLIER: - return getMultiplier(); - - case UNUM_GROUPING_SIZE: - return getGroupingSize(); - - case UNUM_ROUNDING_MODE: - return getRoundingMode(); - - case UNUM_FORMAT_WIDTH: - return getFormatWidth(); - - case UNUM_PADDING_POSITION: - return getPadPosition(); - - case UNUM_SECONDARY_GROUPING_SIZE: - return getSecondaryGroupingSize(); - - /* These are stored in fBoolFlags */ - case UNUM_PARSE_NO_EXPONENT: - case UNUM_FORMAT_FAIL_IF_MORE_THAN_MAX_DIGITS: - case UNUM_PARSE_DECIMAL_MARK_REQUIRED: - return fBoolFlags.get(attr); - - case UNUM_SCALE: - return fImpl->fScale; - - case UNUM_CURRENCY_USAGE: - return fImpl->getCurrencyUsage(); - - case UNUM_MINIMUM_GROUPING_DIGITS: - return getMinimumGroupingDigits(); - - default: - status = U_UNSUPPORTED_ERROR; - break; - } - - return -1; /* undefined */ -} - -#if UCONFIG_HAVE_PARSEALLINPUT -void DecimalFormat::setParseAllInput(UNumberFormatAttributeValue value) { - fParseAllInput = value; -} -#endif - -U_NAMESPACE_END #endif /* #if !UCONFIG_NO_FORMATTING */ - -//eof diff --git a/deps/icu-small/source/i18n/decimfmtimpl.cpp b/deps/icu-small/source/i18n/decimfmtimpl.cpp deleted file mode 100644 index ef44eab0101..00000000000 --- a/deps/icu-small/source/i18n/decimfmtimpl.cpp +++ /dev/null @@ -1,1596 +0,0 @@ -// © 2016 and later: Unicode, Inc. and others. -// License & terms of use: http://www.unicode.org/copyright.html -/* - * Copyright (C) 2015, International Business Machines - * Corporation and others. All Rights Reserved. - * - * file name: decimfmtimpl.cpp - */ - -#include "unicode/utypes.h" - -#if !UCONFIG_NO_FORMATTING - -#include -#include "unicode/numfmt.h" -#include "unicode/plurrule.h" -#include "unicode/ustring.h" -#include "decimalformatpattern.h" -#include "decimalformatpatternimpl.h" -#include "decimfmtimpl.h" -#include "fphdlimp.h" -#include "plurrule_impl.h" -#include "valueformatter.h" -#include "visibledigits.h" - -U_NAMESPACE_BEGIN - -static const int32_t kMaxScientificIntegerDigits = 8; - -static const int32_t kFormattingPosPrefix = (1 << 0); -static const int32_t kFormattingNegPrefix = (1 << 1); -static const int32_t kFormattingPosSuffix = (1 << 2); -static const int32_t kFormattingNegSuffix = (1 << 3); -static const int32_t kFormattingSymbols = (1 << 4); -static const int32_t kFormattingCurrency = (1 << 5); -static const int32_t kFormattingUsesCurrency = (1 << 6); -static const int32_t kFormattingPluralRules = (1 << 7); -static const int32_t kFormattingAffixParser = (1 << 8); -static const int32_t kFormattingCurrencyAffixInfo = (1 << 9); -static const int32_t kFormattingAll = (1 << 10) - 1; -static const int32_t kFormattingAffixes = - kFormattingPosPrefix | kFormattingPosSuffix | - kFormattingNegPrefix | kFormattingNegSuffix; -static const int32_t kFormattingAffixParserWithCurrency = - kFormattingAffixParser | kFormattingCurrencyAffixInfo; - -DecimalFormatImpl::DecimalFormatImpl( - NumberFormat *super, - const Locale &locale, - const UnicodeString &pattern, - UErrorCode &status) - : fSuper(super), - fScale(0), - fRoundingMode(DecimalFormat::kRoundHalfEven), - fSymbols(NULL), - fCurrencyUsage(UCURR_USAGE_STANDARD), - fRules(NULL), - fMonetary(FALSE) { - if (U_FAILURE(status)) { - return; - } - fSymbols = new DecimalFormatSymbols( - locale, status); - if (fSymbols == NULL) { - status = U_MEMORY_ALLOCATION_ERROR; - return; - } - UParseError parseError; - applyPattern(pattern, FALSE, parseError, status); - updateAll(status); -} - -DecimalFormatImpl::DecimalFormatImpl( - NumberFormat *super, - const UnicodeString &pattern, - DecimalFormatSymbols *symbolsToAdopt, - UParseError &parseError, - UErrorCode &status) - : fSuper(super), - fScale(0), - fRoundingMode(DecimalFormat::kRoundHalfEven), - fSymbols(symbolsToAdopt), - fCurrencyUsage(UCURR_USAGE_STANDARD), - fRules(NULL), - fMonetary(FALSE) { - applyPattern(pattern, FALSE, parseError, status); - updateAll(status); -} - -DecimalFormatImpl::DecimalFormatImpl( - NumberFormat *super, const DecimalFormatImpl &other, UErrorCode &status) : - fSuper(super), - fMultiplier(other.fMultiplier), - fScale(other.fScale), - fRoundingMode(other.fRoundingMode), - fMinSigDigits(other.fMinSigDigits), - fMaxSigDigits(other.fMaxSigDigits), - fUseScientific(other.fUseScientific), - fUseSigDigits(other.fUseSigDigits), - fGrouping(other.fGrouping), - fPositivePrefixPattern(other.fPositivePrefixPattern), - fNegativePrefixPattern(other.fNegativePrefixPattern), - fPositiveSuffixPattern(other.fPositiveSuffixPattern), - fNegativeSuffixPattern(other.fNegativeSuffixPattern), - fSymbols(other.fSymbols), - fCurrencyUsage(other.fCurrencyUsage), - fRules(NULL), - fMonetary(other.fMonetary), - fAffixParser(other.fAffixParser), - fCurrencyAffixInfo(other.fCurrencyAffixInfo), - fEffPrecision(other.fEffPrecision), - fEffGrouping(other.fEffGrouping), - fOptions(other.fOptions), - fFormatter(other.fFormatter), - fAffixes(other.fAffixes) { - fSymbols = new DecimalFormatSymbols(*fSymbols); - if (fSymbols == NULL && U_SUCCESS(status)) { - status = U_MEMORY_ALLOCATION_ERROR; - } - if (other.fRules != NULL) { - fRules = new PluralRules(*other.fRules); - if (fRules == NULL && U_SUCCESS(status)) { - status = U_MEMORY_ALLOCATION_ERROR; - } - } -} - - -DecimalFormatImpl & -DecimalFormatImpl::assign(const DecimalFormatImpl &other, UErrorCode &status) { - if (U_FAILURE(status) || this == &other) { - return (*this); - } - UObject::operator=(other); - fMultiplier = other.fMultiplier; - fScale = other.fScale; - fRoundingMode = other.fRoundingMode; - fMinSigDigits = other.fMinSigDigits; - fMaxSigDigits = other.fMaxSigDigits; - fUseScientific = other.fUseScientific; - fUseSigDigits = other.fUseSigDigits; - fGrouping = other.fGrouping; - fPositivePrefixPattern = other.fPositivePrefixPattern; - fNegativePrefixPattern = other.fNegativePrefixPattern; - fPositiveSuffixPattern = other.fPositiveSuffixPattern; - fNegativeSuffixPattern = other.fNegativeSuffixPattern; - fCurrencyUsage = other.fCurrencyUsage; - fMonetary = other.fMonetary; - fAffixParser = other.fAffixParser; - fCurrencyAffixInfo = other.fCurrencyAffixInfo; - fEffPrecision = other.fEffPrecision; - fEffGrouping = other.fEffGrouping; - fOptions = other.fOptions; - fFormatter = other.fFormatter; - fAffixes = other.fAffixes; - *fSymbols = *other.fSymbols; - if (fRules != NULL && other.fRules != NULL) { - *fRules = *other.fRules; - } else { - delete fRules; - fRules = other.fRules; - if (fRules != NULL) { - fRules = new PluralRules(*fRules); - if (fRules == NULL) { - status = U_MEMORY_ALLOCATION_ERROR; - return *this; - } - } - } - return *this; -} - -UBool -DecimalFormatImpl::operator==(const DecimalFormatImpl &other) const { - if (this == &other) { - return TRUE; - } - return (fMultiplier == other.fMultiplier) - && (fScale == other.fScale) - && (fRoundingMode == other.fRoundingMode) - && (fMinSigDigits == other.fMinSigDigits) - && (fMaxSigDigits == other.fMaxSigDigits) - && (fUseScientific == other.fUseScientific) - && (fUseSigDigits == other.fUseSigDigits) - && fGrouping.equals(other.fGrouping) - && fPositivePrefixPattern.equals(other.fPositivePrefixPattern) - && fNegativePrefixPattern.equals(other.fNegativePrefixPattern) - && fPositiveSuffixPattern.equals(other.fPositiveSuffixPattern) - && fNegativeSuffixPattern.equals(other.fNegativeSuffixPattern) - && fCurrencyUsage == other.fCurrencyUsage - && fAffixParser.equals(other.fAffixParser) - && fCurrencyAffixInfo.equals(other.fCurrencyAffixInfo) - && fEffPrecision.equals(other.fEffPrecision) - && fEffGrouping.equals(other.fEffGrouping) - && fOptions.equals(other.fOptions) - && fFormatter.equals(other.fFormatter) - && fAffixes.equals(other.fAffixes) - && (*fSymbols == *other.fSymbols) - && ((fRules == other.fRules) || ( - (fRules != NULL) && (other.fRules != NULL) - && (*fRules == *other.fRules))) - && (fMonetary == other.fMonetary); -} - -DecimalFormatImpl::~DecimalFormatImpl() { - delete fSymbols; - delete fRules; -} - -ValueFormatter & -DecimalFormatImpl::prepareValueFormatter(ValueFormatter &vf) const { - if (fUseScientific) { - vf.prepareScientificFormatting( - fFormatter, fEffPrecision, fOptions); - return vf; - } - vf.prepareFixedDecimalFormatting( - fFormatter, fEffGrouping, fEffPrecision.fMantissa, fOptions.fMantissa); - return vf; -} - -int32_t -DecimalFormatImpl::getPatternScale() const { - UBool usesPercent = fPositivePrefixPattern.usesPercent() || - fPositiveSuffixPattern.usesPercent() || - fNegativePrefixPattern.usesPercent() || - fNegativeSuffixPattern.usesPercent(); - if (usesPercent) { - return 2; - } - UBool usesPermill = fPositivePrefixPattern.usesPermill() || - fPositiveSuffixPattern.usesPermill() || - fNegativePrefixPattern.usesPermill() || - fNegativeSuffixPattern.usesPermill(); - if (usesPermill) { - return 3; - } - return 0; -} - -void -DecimalFormatImpl::setMultiplierScale(int32_t scale) { - if (scale == 0) { - // Needed to preserve equality. fMultiplier == 0 means - // multiplier is 1. - fMultiplier.set((int32_t)0); - } else { - fMultiplier.set((int32_t)1); - fMultiplier.shiftDecimalRight(scale); - } -} - -UnicodeString & -DecimalFormatImpl::format( - int32_t number, - UnicodeString &appendTo, - FieldPosition &pos, - UErrorCode &status) const { - FieldPositionOnlyHandler handler(pos); - return formatInt32(number, appendTo, handler, status); -} - -UnicodeString & -DecimalFormatImpl::format( - int32_t number, - UnicodeString &appendTo, - FieldPositionIterator *posIter, - UErrorCode &status) const { - FieldPositionIteratorHandler handler(posIter, status); - return formatInt32(number, appendTo, handler, status); -} - -template -UBool DecimalFormatImpl::maybeFormatWithDigitList( - T number, - UnicodeString &appendTo, - FieldPositionHandler &handler, - UErrorCode &status) const { - if (!fMultiplier.isZero()) { - DigitList digits; - digits.set(number); - digits.mult(fMultiplier, status); - digits.shiftDecimalRight(fScale); - formatAdjustedDigitList(digits, appendTo, handler, status); - return TRUE; - } - if (fScale != 0) { - DigitList digits; - digits.set(number); - digits.shiftDecimalRight(fScale); - formatAdjustedDigitList(digits, appendTo, handler, status); - return TRUE; - } - return FALSE; -} - -template -UBool DecimalFormatImpl::maybeInitVisibleDigitsFromDigitList( - T number, - VisibleDigitsWithExponent &visibleDigits, - UErrorCode &status) const { - if (!fMultiplier.isZero()) { - DigitList digits; - digits.set(number); - digits.mult(fMultiplier, status); - digits.shiftDecimalRight(fScale); - initVisibleDigitsFromAdjusted(digits, visibleDigits, status); - return TRUE; - } - if (fScale != 0) { - DigitList digits; - digits.set(number); - digits.shiftDecimalRight(fScale); - initVisibleDigitsFromAdjusted(digits, visibleDigits, status); - return TRUE; - } - return FALSE; -} - -UnicodeString & -DecimalFormatImpl::formatInt32( - int32_t number, - UnicodeString &appendTo, - FieldPositionHandler &handler, - UErrorCode &status) const { - if (maybeFormatWithDigitList(number, appendTo, handler, status)) { - return appendTo; - } - ValueFormatter vf; - return fAffixes.formatInt32( - number, - prepareValueFormatter(vf), - handler, - fRules, - appendTo, - status); -} - -UnicodeString & -DecimalFormatImpl::formatInt64( - int64_t number, - UnicodeString &appendTo, - FieldPositionHandler &handler, - UErrorCode &status) const { - if (number >= INT32_MIN && number <= INT32_MAX) { - return formatInt32((int32_t) number, appendTo, handler, status); - } - VisibleDigitsWithExponent digits; - initVisibleDigitsWithExponent(number, digits, status); - return formatVisibleDigitsWithExponent( - digits, appendTo, handler, status); -} - -UnicodeString & -DecimalFormatImpl::formatDouble( - double number, - UnicodeString &appendTo, - FieldPositionHandler &handler, - UErrorCode &status) const { - VisibleDigitsWithExponent digits; - initVisibleDigitsWithExponent(number, digits, status); - return formatVisibleDigitsWithExponent( - digits, appendTo, handler, status); -} - -UnicodeString & -DecimalFormatImpl::format( - double number, - UnicodeString &appendTo, - FieldPosition &pos, - UErrorCode &status) const { - FieldPositionOnlyHandler handler(pos); - return formatDouble(number, appendTo, handler, status); -} - -UnicodeString & -DecimalFormatImpl::format( - const DigitList &number, - UnicodeString &appendTo, - FieldPosition &pos, - UErrorCode &status) const { - DigitList dl(number); - FieldPositionOnlyHandler handler(pos); - return formatDigitList(dl, appendTo, handler, status); -} - -UnicodeString & -DecimalFormatImpl::format( - int64_t number, - UnicodeString &appendTo, - FieldPosition &pos, - UErrorCode &status) const { - FieldPositionOnlyHandler handler(pos); - return formatInt64(number, appendTo, handler, status); -} - -UnicodeString & -DecimalFormatImpl::format( - int64_t number, - UnicodeString &appendTo, - FieldPositionIterator *posIter, - UErrorCode &status) const { - FieldPositionIteratorHandler handler(posIter, status); - return formatInt64(number, appendTo, handler, status); -} - -UnicodeString & -DecimalFormatImpl::format( - double number, - UnicodeString &appendTo, - FieldPositionIterator *posIter, - UErrorCode &status) const { - FieldPositionIteratorHandler handler(posIter, status); - return formatDouble(number, appendTo, handler, status); -} - -UnicodeString & -DecimalFormatImpl::format( - const DigitList &number, - UnicodeString &appendTo, - FieldPositionIterator *posIter, - UErrorCode &status) const { - DigitList dl(number); - FieldPositionIteratorHandler handler(posIter, status); - return formatDigitList(dl, appendTo, handler, status); -} - -UnicodeString & -DecimalFormatImpl::format( - StringPiece number, - UnicodeString &appendTo, - FieldPositionIterator *posIter, - UErrorCode &status) const { - DigitList dl; - dl.set(number, status); - FieldPositionIteratorHandler handler(posIter, status); - return formatDigitList(dl, appendTo, handler, status); -} - -UnicodeString & -DecimalFormatImpl::format( - const VisibleDigitsWithExponent &digits, - UnicodeString &appendTo, - FieldPosition &pos, - UErrorCode &status) const { - FieldPositionOnlyHandler handler(pos); - return formatVisibleDigitsWithExponent( - digits, appendTo, handler, status); -} - -UnicodeString & -DecimalFormatImpl::format( - const VisibleDigitsWithExponent &digits, - UnicodeString &appendTo, - FieldPositionIterator *posIter, - UErrorCode &status) const { - FieldPositionIteratorHandler handler(posIter, status); - return formatVisibleDigitsWithExponent( - digits, appendTo, handler, status); -} - -DigitList & -DecimalFormatImpl::adjustDigitList( - DigitList &number, UErrorCode &status) const { - number.setRoundingMode(fRoundingMode); - if (!fMultiplier.isZero()) { - number.mult(fMultiplier, status); - } - if (fScale != 0) { - number.shiftDecimalRight(fScale); - } - number.reduce(); - return number; -} - -UnicodeString & -DecimalFormatImpl::formatDigitList( - DigitList &number, - UnicodeString &appendTo, - FieldPositionHandler &handler, - UErrorCode &status) const { - VisibleDigitsWithExponent digits; - initVisibleDigitsWithExponent(number, digits, status); - return formatVisibleDigitsWithExponent( - digits, appendTo, handler, status); -} - -UnicodeString & -DecimalFormatImpl::formatAdjustedDigitList( - DigitList &number, - UnicodeString &appendTo, - FieldPositionHandler &handler, - UErrorCode &status) const { - ValueFormatter vf; - return fAffixes.format( - number, - prepareValueFormatter(vf), - handler, - fRules, - appendTo, - status); -} - -UnicodeString & -DecimalFormatImpl::formatVisibleDigitsWithExponent( - const VisibleDigitsWithExponent &digits, - UnicodeString &appendTo, - FieldPositionHandler &handler, - UErrorCode &status) const { - ValueFormatter vf; - return fAffixes.format( - digits, - prepareValueFormatter(vf), - handler, - fRules, - appendTo, - status); -} - -static FixedDecimal &initFixedDecimal( - const VisibleDigits &digits, FixedDecimal &result) { - result.source = 0.0; - result.isNegative = digits.isNegative(); - result._isNaN = digits.isNaN(); - result._isInfinite = digits.isInfinite(); - digits.getFixedDecimal( - result.source, result.intValue, result.decimalDigits, - result.decimalDigitsWithoutTrailingZeros, - result.visibleDecimalDigitCount, result.hasIntegerValue); - return result; -} - -FixedDecimal & -DecimalFormatImpl::getFixedDecimal(double number, FixedDecimal &result, UErrorCode &status) const { - if (U_FAILURE(status)) { - return result; - } - VisibleDigits digits; - fEffPrecision.fMantissa.initVisibleDigits(number, digits, status); - return initFixedDecimal(digits, result); -} - -FixedDecimal & -DecimalFormatImpl::getFixedDecimal( - DigitList &number, FixedDecimal &result, UErrorCode &status) const { - if (U_FAILURE(status)) { - return result; - } - VisibleDigits digits; - fEffPrecision.fMantissa.initVisibleDigits(number, digits, status); - return initFixedDecimal(digits, result); -} - -VisibleDigitsWithExponent & -DecimalFormatImpl::initVisibleDigitsWithExponent( - int64_t number, - VisibleDigitsWithExponent &digits, - UErrorCode &status) const { - if (maybeInitVisibleDigitsFromDigitList( - number, digits, status)) { - return digits; - } - if (fUseScientific) { - fEffPrecision.initVisibleDigitsWithExponent( - number, digits, status); - } else { - fEffPrecision.fMantissa.initVisibleDigitsWithExponent( - number, digits, status); - } - return digits; -} - -VisibleDigitsWithExponent & -DecimalFormatImpl::initVisibleDigitsWithExponent( - double number, - VisibleDigitsWithExponent &digits, - UErrorCode &status) const { - if (maybeInitVisibleDigitsFromDigitList( - number, digits, status)) { - return digits; - } - if (fUseScientific) { - fEffPrecision.initVisibleDigitsWithExponent( - number, digits, status); - } else { - fEffPrecision.fMantissa.initVisibleDigitsWithExponent( - number, digits, status); - } - return digits; -} - -VisibleDigitsWithExponent & -DecimalFormatImpl::initVisibleDigitsWithExponent( - DigitList &number, - VisibleDigitsWithExponent &digits, - UErrorCode &status) const { - adjustDigitList(number, status); - return initVisibleDigitsFromAdjusted(number, digits, status); -} - -VisibleDigitsWithExponent & -DecimalFormatImpl::initVisibleDigitsFromAdjusted( - DigitList &number, - VisibleDigitsWithExponent &digits, - UErrorCode &status) const { - if (fUseScientific) { - fEffPrecision.initVisibleDigitsWithExponent( - number, digits, status); - } else { - fEffPrecision.fMantissa.initVisibleDigitsWithExponent( - number, digits, status); - } - return digits; -} - -DigitList & -DecimalFormatImpl::round( - DigitList &number, UErrorCode &status) const { - if (number.isNaN() || number.isInfinite()) { - return number; - } - adjustDigitList(number, status); - ValueFormatter vf; - prepareValueFormatter(vf); - return vf.round(number, status); -} - -void -DecimalFormatImpl::setMinimumSignificantDigits(int32_t newValue) { - fMinSigDigits = newValue; - fUseSigDigits = TRUE; // ticket 9936 - updatePrecision(); -} - -void -DecimalFormatImpl::setMaximumSignificantDigits(int32_t newValue) { - fMaxSigDigits = newValue; - fUseSigDigits = TRUE; // ticket 9936 - updatePrecision(); -} - -void -DecimalFormatImpl::setMinMaxSignificantDigits(int32_t min, int32_t max) { - fMinSigDigits = min; - fMaxSigDigits = max; - fUseSigDigits = TRUE; // ticket 9936 - updatePrecision(); -} - -void -DecimalFormatImpl::setScientificNotation(UBool newValue) { - fUseScientific = newValue; - updatePrecision(); -} - -void -DecimalFormatImpl::setSignificantDigitsUsed(UBool newValue) { - fUseSigDigits = newValue; - updatePrecision(); -} - -void -DecimalFormatImpl::setGroupingSize(int32_t newValue) { - fGrouping.fGrouping = newValue; - updateGrouping(); -} - -void -DecimalFormatImpl::setSecondaryGroupingSize(int32_t newValue) { - fGrouping.fGrouping2 = newValue; - updateGrouping(); -} - -void -DecimalFormatImpl::setMinimumGroupingDigits(int32_t newValue) { - fGrouping.fMinGrouping = newValue; - updateGrouping(); -} - -void -DecimalFormatImpl::setCurrencyUsage( - UCurrencyUsage currencyUsage, UErrorCode &status) { - fCurrencyUsage = currencyUsage; - updateFormatting(kFormattingCurrency, status); -} - -void -DecimalFormatImpl::setRoundingIncrement(double d) { - if (d > 0.0) { - fEffPrecision.fMantissa.fRoundingIncrement.set(d); - } else { - fEffPrecision.fMantissa.fRoundingIncrement.set(0.0); - } -} - -double -DecimalFormatImpl::getRoundingIncrement() const { - return fEffPrecision.fMantissa.fRoundingIncrement.getDouble(); -} - -int32_t -DecimalFormatImpl::getMultiplier() const { - if (fMultiplier.isZero()) { - return 1; - } - return (int32_t) fMultiplier.getDouble(); -} - -void -DecimalFormatImpl::setMultiplier(int32_t m) { - if (m == 0 || m == 1) { - fMultiplier.set((int32_t)0); - } else { - fMultiplier.set(m); - } -} - -void -DecimalFormatImpl::setPositivePrefix(const UnicodeString &str) { - fPositivePrefixPattern.remove(); - fPositivePrefixPattern.addLiteral(str.getBuffer(), 0, str.length()); - UErrorCode status = U_ZERO_ERROR; - updateFormatting(kFormattingPosPrefix, status); -} - -void -DecimalFormatImpl::setPositiveSuffix(const UnicodeString &str) { - fPositiveSuffixPattern.remove(); - fPositiveSuffixPattern.addLiteral(str.getBuffer(), 0, str.length()); - UErrorCode status = U_ZERO_ERROR; - updateFormatting(kFormattingPosSuffix, status); -} - -void -DecimalFormatImpl::setNegativePrefix(const UnicodeString &str) { - fNegativePrefixPattern.remove(); - fNegativePrefixPattern.addLiteral(str.getBuffer(), 0, str.length()); - UErrorCode status = U_ZERO_ERROR; - updateFormatting(kFormattingNegPrefix, status); -} - -void -DecimalFormatImpl::setNegativeSuffix(const UnicodeString &str) { - fNegativeSuffixPattern.remove(); - fNegativeSuffixPattern.addLiteral(str.getBuffer(), 0, str.length()); - UErrorCode status = U_ZERO_ERROR; - updateFormatting(kFormattingNegSuffix, status); -} - -UnicodeString & -DecimalFormatImpl::getPositivePrefix(UnicodeString &result) const { - result = fAffixes.fPositivePrefix.getOtherVariant().toString(); - return result; -} - -UnicodeString & -DecimalFormatImpl::getPositiveSuffix(UnicodeString &result) const { - result = fAffixes.fPositiveSuffix.getOtherVariant().toString(); - return result; -} - -UnicodeString & -DecimalFormatImpl::getNegativePrefix(UnicodeString &result) const { - result = fAffixes.fNegativePrefix.getOtherVariant().toString(); - return result; -} - -UnicodeString & -DecimalFormatImpl::getNegativeSuffix(UnicodeString &result) const { - result = fAffixes.fNegativeSuffix.getOtherVariant().toString(); - return result; -} - -void -DecimalFormatImpl::adoptDecimalFormatSymbols(DecimalFormatSymbols *symbolsToAdopt) { - if (symbolsToAdopt == NULL) { - return; - } - delete fSymbols; - fSymbols = symbolsToAdopt; - UErrorCode status = U_ZERO_ERROR; - updateFormatting(kFormattingSymbols, status); -} - -void -DecimalFormatImpl::applyPatternFavorCurrencyPrecision( - const UnicodeString &pattern, UErrorCode &status) { - UParseError perror; - applyPattern(pattern, FALSE, perror, status); - updateForApplyPatternFavorCurrencyPrecision(status); -} - -void -DecimalFormatImpl::applyPattern( - const UnicodeString &pattern, UErrorCode &status) { - UParseError perror; - applyPattern(pattern, FALSE, perror, status); - updateForApplyPattern(status); -} - -void -DecimalFormatImpl::applyPattern( - const UnicodeString &pattern, - UParseError &perror, UErrorCode &status) { - applyPattern(pattern, FALSE, perror, status); - updateForApplyPattern(status); -} - -void -DecimalFormatImpl::applyLocalizedPattern( - const UnicodeString &pattern, UErrorCode &status) { - UParseError perror; - applyPattern(pattern, TRUE, perror, status); - updateForApplyPattern(status); -} - -void -DecimalFormatImpl::applyLocalizedPattern( - const UnicodeString &pattern, - UParseError &perror, UErrorCode &status) { - applyPattern(pattern, TRUE, perror, status); - updateForApplyPattern(status); -} - -void -DecimalFormatImpl::applyPattern( - const UnicodeString &pattern, - UBool localized, UParseError &perror, UErrorCode &status) { - if (U_FAILURE(status)) { - return; - } - DecimalFormatPatternParser patternParser; - if (localized) { - patternParser.useSymbols(*fSymbols); - } - DecimalFormatPattern out; - patternParser.applyPatternWithoutExpandAffix( - pattern, out, perror, status); - if (U_FAILURE(status)) { - return; - } - fUseScientific = out.fUseExponentialNotation; - fUseSigDigits = out.fUseSignificantDigits; - fSuper->NumberFormat::setMinimumIntegerDigits(out.fMinimumIntegerDigits); - fSuper->NumberFormat::setMaximumIntegerDigits(out.fMaximumIntegerDigits); - fSuper->NumberFormat::setMinimumFractionDigits(out.fMinimumFractionDigits); - fSuper->NumberFormat::setMaximumFractionDigits(out.fMaximumFractionDigits); - fMinSigDigits = out.fMinimumSignificantDigits; - fMaxSigDigits = out.fMaximumSignificantDigits; - fEffPrecision.fMinExponentDigits = out.fMinExponentDigits; - fOptions.fExponent.fAlwaysShowSign = out.fExponentSignAlwaysShown; - fSuper->NumberFormat::setGroupingUsed(out.fGroupingUsed); - fGrouping.fGrouping = out.fGroupingSize; - fGrouping.fGrouping2 = out.fGroupingSize2; - fOptions.fMantissa.fAlwaysShowDecimal = out.fDecimalSeparatorAlwaysShown; - if (out.fRoundingIncrementUsed) { - fEffPrecision.fMantissa.fRoundingIncrement = out.fRoundingIncrement; - } else { - fEffPrecision.fMantissa.fRoundingIncrement.clear(); - } - fAffixes.fPadChar = out.fPad; - fNegativePrefixPattern = out.fNegPrefixAffix; - fNegativeSuffixPattern = out.fNegSuffixAffix; - fPositivePrefixPattern = out.fPosPrefixAffix; - fPositiveSuffixPattern = out.fPosSuffixAffix; - - // Work around. Pattern parsing code and DecimalFormat code don't agree - // on the definition of field width, so we have to translate from - // pattern field width to decimal format field width here. - fAffixes.fWidth = out.fFormatWidth == 0 ? 0 : - out.fFormatWidth + fPositivePrefixPattern.countChar32() - + fPositiveSuffixPattern.countChar32(); - switch (out.fPadPosition) { - case DecimalFormatPattern::kPadBeforePrefix: - fAffixes.fPadPosition = DigitAffixesAndPadding::kPadBeforePrefix; - break; - case DecimalFormatPattern::kPadAfterPrefix: - fAffixes.fPadPosition = DigitAffixesAndPadding::kPadAfterPrefix; - break; - case DecimalFormatPattern::kPadBeforeSuffix: - fAffixes.fPadPosition = DigitAffixesAndPadding::kPadBeforeSuffix; - break; - case DecimalFormatPattern::kPadAfterSuffix: - fAffixes.fPadPosition = DigitAffixesAndPadding::kPadAfterSuffix; - break; - default: - break; - } -} - -void -DecimalFormatImpl::updatePrecision() { - if (fUseScientific) { - updatePrecisionForScientific(); - } else { - updatePrecisionForFixed(); - } -} - -static void updatePrecisionForScientificMinMax( - const DigitInterval &min, - const DigitInterval &max, - DigitInterval &resultMin, - DigitInterval &resultMax, - SignificantDigitInterval &resultSignificant) { - resultMin.setIntDigitCount(0); - resultMin.setFracDigitCount(0); - resultSignificant.clear(); - resultMax.clear(); - - int32_t maxIntDigitCount = max.getIntDigitCount(); - int32_t minIntDigitCount = min.getIntDigitCount(); - int32_t maxFracDigitCount = max.getFracDigitCount(); - int32_t minFracDigitCount = min.getFracDigitCount(); - - - // Not in spec: maxIntDigitCount > 8 assume - // maxIntDigitCount = minIntDigitCount. Current DecimalFormat API has - // no provision for unsetting maxIntDigitCount which would be useful for - // scientific notation. The best we can do is assume that if - // maxIntDigitCount is the default of 2000000000 or is "big enough" then - // user did not intend to explicitly set it. The 8 was derived emperically - // by extensive testing of legacy code. - if (maxIntDigitCount > 8) { - maxIntDigitCount = minIntDigitCount; - } - - // Per the spec, exponent grouping happens if maxIntDigitCount is more - // than 1 and more than minIntDigitCount. - UBool bExponentGrouping = maxIntDigitCount > 1 && minIntDigitCount < maxIntDigitCount; - if (bExponentGrouping) { - resultMax.setIntDigitCount(maxIntDigitCount); - - // For exponent grouping minIntDigits is always treated as 1 even - // if it wasn't set to 1! - resultMin.setIntDigitCount(1); - } else { - // Fixed digit count left of decimal. minIntDigitCount doesn't have - // to equal maxIntDigitCount i.e minIntDigitCount == 0 while - // maxIntDigitCount == 1. - int32_t fixedIntDigitCount = maxIntDigitCount; - - // If fixedIntDigitCount is 0 but - // min or max fraction count is 0 too then use 1. This way we can get - // unlimited precision for X.XXXEX - if (fixedIntDigitCount == 0 && (minFracDigitCount == 0 || maxFracDigitCount == 0)) { - fixedIntDigitCount = 1; - } - resultMax.setIntDigitCount(fixedIntDigitCount); - resultMin.setIntDigitCount(fixedIntDigitCount); - } - // Spec says this is how we compute significant digits. 0 means - // unlimited significant digits. - int32_t maxSigDigits = minIntDigitCount + maxFracDigitCount; - if (maxSigDigits > 0) { - int32_t minSigDigits = minIntDigitCount + minFracDigitCount; - resultSignificant.setMin(minSigDigits); - resultSignificant.setMax(maxSigDigits); - } -} - -void -DecimalFormatImpl::updatePrecisionForScientific() { - FixedPrecision *result = &fEffPrecision.fMantissa; - if (fUseSigDigits) { - result->fMax.setFracDigitCount(-1); - result->fMax.setIntDigitCount(1); - result->fMin.setFracDigitCount(0); - result->fMin.setIntDigitCount(1); - result->fSignificant.clear(); - extractSigDigits(result->fSignificant); - return; - } - DigitInterval max; - DigitInterval min; - extractMinMaxDigits(min, max); - updatePrecisionForScientificMinMax( - min, max, - result->fMin, result->fMax, result->fSignificant); -} - -void -DecimalFormatImpl::updatePrecisionForFixed() { - FixedPrecision *result = &fEffPrecision.fMantissa; - if (!fUseSigDigits) { - extractMinMaxDigits(result->fMin, result->fMax); - result->fSignificant.clear(); - } else { - extractSigDigits(result->fSignificant); - result->fMin.setIntDigitCount(1); - result->fMin.setFracDigitCount(0); - result->fMax.clear(); - } -} - -void - DecimalFormatImpl::extractMinMaxDigits( - DigitInterval &min, DigitInterval &max) const { - min.setIntDigitCount(fSuper->getMinimumIntegerDigits()); - max.setIntDigitCount(fSuper->getMaximumIntegerDigits()); - min.setFracDigitCount(fSuper->getMinimumFractionDigits()); - max.setFracDigitCount(fSuper->getMaximumFractionDigits()); -} - -void - DecimalFormatImpl::extractSigDigits( - SignificantDigitInterval &sig) const { - sig.setMin(fMinSigDigits < 0 ? 0 : fMinSigDigits); - sig.setMax(fMaxSigDigits < 0 ? 0 : fMaxSigDigits); -} - -void -DecimalFormatImpl::updateGrouping() { - if (fSuper->isGroupingUsed()) { - fEffGrouping = fGrouping; - } else { - fEffGrouping.clear(); - } -} - -void -DecimalFormatImpl::updateCurrency(UErrorCode &status) { - updateFormatting(kFormattingCurrency, TRUE, status); -} - -void -DecimalFormatImpl::updateFormatting( - int32_t changedFormattingFields, - UErrorCode &status) { - updateFormatting(changedFormattingFields, TRUE, status); -} - -void -DecimalFormatImpl::updateFormatting( - int32_t changedFormattingFields, - UBool updatePrecisionBasedOnCurrency, - UErrorCode &status) { - if (U_FAILURE(status)) { - return; - } - // Each function updates one field. Order matters. For instance, - // updatePluralRules comes before updateCurrencyAffixInfo because the - // fRules field is needed to update the fCurrencyAffixInfo field. - updateFormattingUsesCurrency(changedFormattingFields); - updateFormattingFixedPointFormatter(changedFormattingFields); - updateFormattingAffixParser(changedFormattingFields); - updateFormattingPluralRules(changedFormattingFields, status); - updateFormattingCurrencyAffixInfo( - changedFormattingFields, - updatePrecisionBasedOnCurrency, - status); - updateFormattingLocalizedPositivePrefix( - changedFormattingFields, status); - updateFormattingLocalizedPositiveSuffix( - changedFormattingFields, status); - updateFormattingLocalizedNegativePrefix( - changedFormattingFields, status); - updateFormattingLocalizedNegativeSuffix( - changedFormattingFields, status); -} - -void -DecimalFormatImpl::updateFormattingUsesCurrency( - int32_t &changedFormattingFields) { - if ((changedFormattingFields & kFormattingAffixes) == 0) { - // If no affixes changed, don't need to do any work - return; - } - UBool newUsesCurrency = - fPositivePrefixPattern.usesCurrency() || - fPositiveSuffixPattern.usesCurrency() || - fNegativePrefixPattern.usesCurrency() || - fNegativeSuffixPattern.usesCurrency(); - if (fMonetary != newUsesCurrency) { - fMonetary = newUsesCurrency; - changedFormattingFields |= kFormattingUsesCurrency; - } -} - -void -DecimalFormatImpl::updateFormattingPluralRules( - int32_t &changedFormattingFields, UErrorCode &status) { - if ((changedFormattingFields & (kFormattingSymbols | kFormattingUsesCurrency)) == 0) { - // No work to do if both fSymbols and fMonetary - // fields are unchanged - return; - } - if (U_FAILURE(status)) { - return; - } - PluralRules *newRules = NULL; - if (fMonetary) { - newRules = PluralRules::forLocale(fSymbols->getLocale(), status); - if (U_FAILURE(status)) { - return; - } - } - // Its ok to say a field has changed when it really hasn't but not - // the other way around. Here we assume the field changed unless it - // was NULL before and is still NULL now - if (fRules != newRules) { - delete fRules; - fRules = newRules; - changedFormattingFields |= kFormattingPluralRules; - } -} - -void -DecimalFormatImpl::updateFormattingCurrencyAffixInfo( - int32_t &changedFormattingFields, - UBool updatePrecisionBasedOnCurrency, - UErrorCode &status) { - if ((changedFormattingFields & ( - kFormattingSymbols | kFormattingCurrency | - kFormattingUsesCurrency | kFormattingPluralRules)) == 0) { - // If all these fields are unchanged, no work to do. - return; - } - if (U_FAILURE(status)) { - return; - } - if (!fMonetary) { - if (fCurrencyAffixInfo.isDefault()) { - // In this case don't have to do any work - return; - } - fCurrencyAffixInfo.set(NULL, NULL, NULL, status); - if (U_FAILURE(status)) { - return; - } - changedFormattingFields |= kFormattingCurrencyAffixInfo; - } else { - const UChar *currency = fSuper->getCurrency(); - UChar localeCurr[4]; - if (currency[0] == 0) { - ucurr_forLocale(fSymbols->getLocale().getName(), localeCurr, UPRV_LENGTHOF(localeCurr), &status); - if (U_SUCCESS(status)) { - currency = localeCurr; - fSuper->NumberFormat::setCurrency(currency, status); - } else { - currency = NULL; - status = U_ZERO_ERROR; - } - } - fCurrencyAffixInfo.set( - fSymbols->getLocale().getName(), fRules, currency, status); - if (U_FAILURE(status)) { - return; - } - UBool customCurrencySymbol = FALSE; - // If DecimalFormatSymbols has custom currency symbol, prefer - // that over what we just read from the resource bundles - if (fSymbols->isCustomCurrencySymbol()) { - fCurrencyAffixInfo.setSymbol( - fSymbols->getConstSymbol(DecimalFormatSymbols::kCurrencySymbol)); - customCurrencySymbol = TRUE; - } - if (fSymbols->isCustomIntlCurrencySymbol()) { - fCurrencyAffixInfo.setISO( - fSymbols->getConstSymbol(DecimalFormatSymbols::kIntlCurrencySymbol)); - customCurrencySymbol = TRUE; - } - changedFormattingFields |= kFormattingCurrencyAffixInfo; - if (currency && !customCurrencySymbol && updatePrecisionBasedOnCurrency) { - FixedPrecision precision; - CurrencyAffixInfo::adjustPrecision( - currency, fCurrencyUsage, precision, status); - if (U_FAILURE(status)) { - return; - } - fSuper->NumberFormat::setMinimumFractionDigits( - precision.fMin.getFracDigitCount()); - fSuper->NumberFormat::setMaximumFractionDigits( - precision.fMax.getFracDigitCount()); - updatePrecision(); - fEffPrecision.fMantissa.fRoundingIncrement = - precision.fRoundingIncrement; - } - - } -} - -void -DecimalFormatImpl::updateFormattingFixedPointFormatter( - int32_t &changedFormattingFields) { - if ((changedFormattingFields & (kFormattingSymbols | kFormattingUsesCurrency)) == 0) { - // No work to do if fSymbols is unchanged - return; - } - if (fMonetary) { - fFormatter.setDecimalFormatSymbolsForMonetary(*fSymbols); - } else { - fFormatter.setDecimalFormatSymbols(*fSymbols); - } -} - -void -DecimalFormatImpl::updateFormattingAffixParser( - int32_t &changedFormattingFields) { - if ((changedFormattingFields & kFormattingSymbols) == 0) { - // No work to do if fSymbols is unchanged - return; - } - fAffixParser.setDecimalFormatSymbols(*fSymbols); - changedFormattingFields |= kFormattingAffixParser; -} - -void -DecimalFormatImpl::updateFormattingLocalizedPositivePrefix( - int32_t &changedFormattingFields, UErrorCode &status) { - if (U_FAILURE(status)) { - return; - } - if ((changedFormattingFields & ( - kFormattingPosPrefix | kFormattingAffixParserWithCurrency)) == 0) { - // No work to do - return; - } - fAffixes.fPositivePrefix.remove(); - fAffixParser.parse( - fPositivePrefixPattern, - fCurrencyAffixInfo, - fAffixes.fPositivePrefix, - status); -} - -void -DecimalFormatImpl::updateFormattingLocalizedPositiveSuffix( - int32_t &changedFormattingFields, UErrorCode &status) { - if (U_FAILURE(status)) { - return; - } - if ((changedFormattingFields & ( - kFormattingPosSuffix | kFormattingAffixParserWithCurrency)) == 0) { - // No work to do - return; - } - fAffixes.fPositiveSuffix.remove(); - fAffixParser.parse( - fPositiveSuffixPattern, - fCurrencyAffixInfo, - fAffixes.fPositiveSuffix, - status); -} - -void -DecimalFormatImpl::updateFormattingLocalizedNegativePrefix( - int32_t &changedFormattingFields, UErrorCode &status) { - if (U_FAILURE(status)) { - return; - } - if ((changedFormattingFields & ( - kFormattingNegPrefix | kFormattingAffixParserWithCurrency)) == 0) { - // No work to do - return; - } - fAffixes.fNegativePrefix.remove(); - fAffixParser.parse( - fNegativePrefixPattern, - fCurrencyAffixInfo, - fAffixes.fNegativePrefix, - status); -} - -void -DecimalFormatImpl::updateFormattingLocalizedNegativeSuffix( - int32_t &changedFormattingFields, UErrorCode &status) { - if (U_FAILURE(status)) { - return; - } - if ((changedFormattingFields & ( - kFormattingNegSuffix | kFormattingAffixParserWithCurrency)) == 0) { - // No work to do - return; - } - fAffixes.fNegativeSuffix.remove(); - fAffixParser.parse( - fNegativeSuffixPattern, - fCurrencyAffixInfo, - fAffixes.fNegativeSuffix, - status); -} - -void -DecimalFormatImpl::updateForApplyPatternFavorCurrencyPrecision( - UErrorCode &status) { - updateAll(kFormattingAll & ~kFormattingSymbols, TRUE, status); -} - -void -DecimalFormatImpl::updateForApplyPattern(UErrorCode &status) { - updateAll(kFormattingAll & ~kFormattingSymbols, FALSE, status); -} - -void -DecimalFormatImpl::updateAll(UErrorCode &status) { - updateAll(kFormattingAll, TRUE, status); -} - -void -DecimalFormatImpl::updateAll( - int32_t formattingFlags, - UBool updatePrecisionBasedOnCurrency, - UErrorCode &status) { - if (U_FAILURE(status)) { - return; - } - updatePrecision(); - updateGrouping(); - updateFormatting( - formattingFlags, updatePrecisionBasedOnCurrency, status); - setMultiplierScale(getPatternScale()); -} - - -static int32_t -getMinimumLengthToDescribeGrouping(const DigitGrouping &grouping) { - if (grouping.fGrouping <= 0) { - return 0; - } - if (grouping.fGrouping2 <= 0) { - return grouping.fGrouping + 1; - } - return grouping.fGrouping + grouping.fGrouping2 + 1; -} - -/** - * Given a grouping policy, calculates how many digits are needed left of - * the decimal point to achieve a desired length left of the - * decimal point. - * @param grouping the grouping policy - * @param desiredLength number of characters needed left of decimal point - * @param minLeftDigits at least this many digits is returned - * @param leftDigits the number of digits needed stored here - * which is >= minLeftDigits. - * @return true if a perfect fit or false if having leftDigits would exceed - * desiredLength - */ -static UBool -getLeftDigitsForLeftLength( - const DigitGrouping &grouping, - int32_t desiredLength, - int32_t minLeftDigits, - int32_t &leftDigits) { - leftDigits = minLeftDigits; - int32_t lengthSoFar = leftDigits + grouping.getSeparatorCount(leftDigits); - while (lengthSoFar < desiredLength) { - lengthSoFar += grouping.isSeparatorAt(leftDigits + 1, leftDigits) ? 2 : 1; - ++leftDigits; - } - return (lengthSoFar == desiredLength); -} - -int32_t -DecimalFormatImpl::computeExponentPatternLength() const { - if (fUseScientific) { - return 1 + (fOptions.fExponent.fAlwaysShowSign ? 1 : 0) + fEffPrecision.fMinExponentDigits; - } - return 0; -} - -int32_t -DecimalFormatImpl::countFractionDigitAndDecimalPatternLength( - int32_t fracDigitCount) const { - if (!fOptions.fMantissa.fAlwaysShowDecimal && fracDigitCount == 0) { - return 0; - } - return fracDigitCount + 1; -} - -UnicodeString& -DecimalFormatImpl::toNumberPattern( - UBool hasPadding, int32_t minimumLength, UnicodeString& result) const { - // Get a grouping policy like the one in this object that does not - // have minimum grouping since toPattern doesn't support it. - DigitGrouping grouping(fEffGrouping); - grouping.fMinGrouping = 0; - - // Only for fixed digits, these are the digits that get 0's. - DigitInterval minInterval; - - // Only for fixed digits, these are the digits that get #'s. - DigitInterval maxInterval; - - // Only for significant digits - int32_t sigMin = 0; /* initialize to avoid compiler warning */ - int32_t sigMax = 0; /* initialize to avoid compiler warning */ - - // These are all the digits to be displayed. For significant digits, - // this interval always starts at the 1's place an extends left. - DigitInterval fullInterval; - - // Digit range of rounding increment. If rounding increment is .025. - // then roundingIncrementLowerExp = -3 and roundingIncrementUpperExp = -1 - int32_t roundingIncrementLowerExp = 0; - int32_t roundingIncrementUpperExp = 0; - - if (fUseSigDigits) { - SignificantDigitInterval sigInterval; - extractSigDigits(sigInterval); - sigMax = sigInterval.getMax(); - sigMin = sigInterval.getMin(); - fullInterval.setFracDigitCount(0); - fullInterval.setIntDigitCount(sigMax); - } else { - extractMinMaxDigits(minInterval, maxInterval); - if (fUseScientific) { - if (maxInterval.getIntDigitCount() > kMaxScientificIntegerDigits) { - maxInterval.setIntDigitCount(1); - minInterval.shrinkToFitWithin(maxInterval); - } - } else if (hasPadding) { - // Make max int digits match min int digits for now, we - // compute necessary padding later. - maxInterval.setIntDigitCount(minInterval.getIntDigitCount()); - } else { - // For some reason toPattern adds at least one leading '#' - maxInterval.setIntDigitCount(minInterval.getIntDigitCount() + 1); - } - if (!fEffPrecision.fMantissa.fRoundingIncrement.isZero()) { - roundingIncrementLowerExp = - fEffPrecision.fMantissa.fRoundingIncrement.getLowerExponent(); - roundingIncrementUpperExp = - fEffPrecision.fMantissa.fRoundingIncrement.getUpperExponent(); - // We have to include the rounding increment in what we display - maxInterval.expandToContainDigit(roundingIncrementLowerExp); - maxInterval.expandToContainDigit(roundingIncrementUpperExp - 1); - } - fullInterval = maxInterval; - } - // We have to include enough digits to show grouping strategy - int32_t minLengthToDescribeGrouping = - getMinimumLengthToDescribeGrouping(grouping); - if (minLengthToDescribeGrouping > 0) { - fullInterval.expandToContainDigit( - getMinimumLengthToDescribeGrouping(grouping) - 1); - } - - // If we have a minimum length, we have to add digits to the left to - // depict padding. - if (hasPadding) { - // For non scientific notation, - // minimumLengthForMantissa = minimumLength - int32_t minimumLengthForMantissa = - minimumLength - computeExponentPatternLength(); - int32_t mininumLengthForMantissaIntPart = - minimumLengthForMantissa - - countFractionDigitAndDecimalPatternLength( - fullInterval.getFracDigitCount()); - // Because of grouping, we may need fewer than expected digits to - // achieve the length we need. - int32_t digitsNeeded; - if (getLeftDigitsForLeftLength( - grouping, - mininumLengthForMantissaIntPart, - fullInterval.getIntDigitCount(), - digitsNeeded)) { - - // In this case, we achieved the exact length that we want. - fullInterval.setIntDigitCount(digitsNeeded); - } else if (digitsNeeded > fullInterval.getIntDigitCount()) { - - // Having digitsNeeded digits goes over desired length which - // means that to have desired length would mean starting on a - // grouping sepearator e.g ,###,### so add a '#' and use one - // less digit. This trick gives ####,### but that is the best - // we can do. - result.append(kPatternDigit); - fullInterval.setIntDigitCount(digitsNeeded - 1); - } - } - int32_t maxDigitPos = fullInterval.getMostSignificantExclusive(); - int32_t minDigitPos = fullInterval.getLeastSignificantInclusive(); - for (int32_t i = maxDigitPos - 1; i >= minDigitPos; --i) { - if (!fOptions.fMantissa.fAlwaysShowDecimal && i == -1) { - result.append(kPatternDecimalSeparator); - } - if (fUseSigDigits) { - // Use digit symbol - if (i >= sigMax || i < sigMax - sigMin) { - result.append(kPatternDigit); - } else { - result.append(kPatternSignificantDigit); - } - } else { - if (i < roundingIncrementUpperExp && i >= roundingIncrementLowerExp) { - result.append((UChar)(fEffPrecision.fMantissa.fRoundingIncrement.getDigitByExponent(i) + kPatternZeroDigit)); - } else if (minInterval.contains(i)) { - result.append(kPatternZeroDigit); - } else { - result.append(kPatternDigit); - } - } - if (grouping.isSeparatorAt(i + 1, i)) { - result.append(kPatternGroupingSeparator); - } - if (fOptions.fMantissa.fAlwaysShowDecimal && i == 0) { - result.append(kPatternDecimalSeparator); - } - } - if (fUseScientific) { - result.append(kPatternExponent); - if (fOptions.fExponent.fAlwaysShowSign) { - result.append(kPatternPlus); - } - for (int32_t i = 0; i < 1 || i < fEffPrecision.fMinExponentDigits; ++i) { - result.append(kPatternZeroDigit); - } - } - return result; -} - -UnicodeString& -DecimalFormatImpl::toPattern(UnicodeString& result) const { - result.remove(); - UnicodeString padSpec; - if (fAffixes.fWidth > 0) { - padSpec.append(kPatternPadEscape); - padSpec.append(fAffixes.fPadChar); - } - if (fAffixes.fPadPosition == DigitAffixesAndPadding::kPadBeforePrefix) { - result.append(padSpec); - } - fPositivePrefixPattern.toUserString(result); - if (fAffixes.fPadPosition == DigitAffixesAndPadding::kPadAfterPrefix) { - result.append(padSpec); - } - toNumberPattern( - fAffixes.fWidth > 0, - fAffixes.fWidth - fPositivePrefixPattern.countChar32() - fPositiveSuffixPattern.countChar32(), - result); - if (fAffixes.fPadPosition == DigitAffixesAndPadding::kPadBeforeSuffix) { - result.append(padSpec); - } - fPositiveSuffixPattern.toUserString(result); - if (fAffixes.fPadPosition == DigitAffixesAndPadding::kPadAfterSuffix) { - result.append(padSpec); - } - AffixPattern withNegative; - withNegative.add(AffixPattern::kNegative); - withNegative.append(fPositivePrefixPattern); - if (!fPositiveSuffixPattern.equals(fNegativeSuffixPattern) || - !withNegative.equals(fNegativePrefixPattern)) { - result.append(kPatternSeparator); - if (fAffixes.fPadPosition == DigitAffixesAndPadding::kPadBeforePrefix) { - result.append(padSpec); - } - fNegativePrefixPattern.toUserString(result); - if (fAffixes.fPadPosition == DigitAffixesAndPadding::kPadAfterPrefix) { - result.append(padSpec); - } - toNumberPattern( - fAffixes.fWidth > 0, - fAffixes.fWidth - fNegativePrefixPattern.countChar32() - fNegativeSuffixPattern.countChar32(), - result); - if (fAffixes.fPadPosition == DigitAffixesAndPadding::kPadBeforeSuffix) { - result.append(padSpec); - } - fNegativeSuffixPattern.toUserString(result); - if (fAffixes.fPadPosition == DigitAffixesAndPadding::kPadAfterSuffix) { - result.append(padSpec); - } - } - return result; -} - -int32_t -DecimalFormatImpl::getOldFormatWidth() const { - if (fAffixes.fWidth == 0) { - return 0; - } - return fAffixes.fWidth - fPositiveSuffixPattern.countChar32() - fPositivePrefixPattern.countChar32(); -} - -const UnicodeString & -DecimalFormatImpl::getConstSymbol( - DecimalFormatSymbols::ENumberFormatSymbol symbol) const { - return fSymbols->getConstSymbol(symbol); -} - -UBool -DecimalFormatImpl::isParseFastpath() const { - AffixPattern negative; - negative.add(AffixPattern::kNegative); - - return fAffixes.fWidth == 0 && - fPositivePrefixPattern.countChar32() == 0 && - fNegativePrefixPattern.equals(negative) && - fPositiveSuffixPattern.countChar32() == 0 && - fNegativeSuffixPattern.countChar32() == 0; -} - - -U_NAMESPACE_END - -#endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/deps/icu-small/source/i18n/decimfmtimpl.h b/deps/icu-small/source/i18n/decimfmtimpl.h deleted file mode 100644 index b4438cba9e1..00000000000 --- a/deps/icu-small/source/i18n/decimfmtimpl.h +++ /dev/null @@ -1,549 +0,0 @@ -// © 2016 and later: Unicode, Inc. and others. -// License & terms of use: http://www.unicode.org/copyright.html -/* -******************************************************************************** -* Copyright (C) 2015, International Business Machines -* Corporation and others. All Rights Reserved. -******************************************************************************** -* -* File decimfmtimpl.h -******************************************************************************** -*/ - -#ifndef DECIMFMTIMPL_H -#define DECIMFMTIMPL_H - -#include "unicode/utypes.h" - -#if !UCONFIG_NO_FORMATTING - -#include "unicode/decimfmt.h" -#include "unicode/uobject.h" -#include "affixpatternparser.h" -#include "digitaffixesandpadding.h" -#include "digitformatter.h" -#include "digitgrouping.h" -#include "precision.h" - -U_NAMESPACE_BEGIN - -class UnicodeString; -class FieldPosition; -class ValueFormatter; -class FieldPositionHandler; -class FixedDecimal; - -/** - * DecimalFormatImpl is the glue code between the legacy DecimalFormat class - * and the new decimal formatting classes. DecimalFormat still handles - * parsing directly. However, DecimalFormat uses attributes of this class - * for parsing when possible. - * - * The public API of this class closely mirrors the legacy API of the - * legacy DecimalFormat deviating only when the legacy API does not make - * sense. For example, although DecimalFormat has a - * getPadCharacterString() method, DecimalFormatImpl has a getPadCharacter() - * method because formatting uses only a single pad character for padding. - * - * Each legacy DecimalFormat instance heap allocates its own instance of - * this class. Most DecimalFormat methods that deal with formatting simply - * delegate to the DecimalFormat's DecimalFormatImpl method. - * - * Because DecimalFormat extends NumberFormat, Each instance of this class - * "borrows" a pointer to the NumberFormat part of its enclosing DecimalFormat - * instance. This way each DecimalFormatImpl instance can read or even modify - * the NumberFormat portion of its enclosing DecimalFormat instance. - * - * Directed acyclic graph (DAG): - * - * This class can be represented as a directed acyclic graph (DAG) where each - * vertex is an attribute, and each directed edge indicates that the value - * of the destination attribute is calculated from the value of the source - * attribute. Attributes with setter methods reside at the bottom of the - * DAG. That is, no edges point to them. We call these independent attributes - * because their values can be set independently of one another. The rest of - * the attributes are derived attributes because their values depend on the - * independent attributes. DecimalFormatImpl often uses the derived - * attributes, not the independent attributes, when formatting numbers. - * - * The independent attributes at the bottom of the DAG correspond to the legacy - * attributes of DecimalFormat while the attributes at the top of the DAG - * correspond to the attributes of the new code. The edges of the DAG - * correspond to the code that handles the complex interaction among all the - * legacy attributes of the DecimalFormat API. - * - * We use a DAG for three reasons. - * - * First, the DAG preserves backward compatibility. Clients of the legacy - * DecimalFormat expect existing getters and setters of each attribute to be - * consistent. That means if a client sets a particular attribute to a new - * value, the attribute should retain that value until the client sets it to - * a new value. The DAG allows these attributes to remain consistent even - * though the new code may not use them when formatting. - * - * Second, the DAG obviates the need to recalculate derived attributes with - * each format. Instead, the DAG "remembers" the values of all derived - * attributes. Only setting an independent attribute requires a recalculation. - * Moreover, setting an independent attribute recalculates only the affected - * dependent attributes rather than all dependent attributes. - * - * Third, the DAG abstracts away the complex interaction among the legacy - * attributes of the DecimalFormat API. - * - * Only the independent attributes of the DAG have setters and getters. - * Derived attributes have no setters (and often no getters either). - * - * Copy and assign: - * - * For copy and assign, DecimalFormatImpl copies and assigns every attribute - * regardless of whether or not it is independent. We do this for simplicity. - * - * Implementation of the DAG: - * - * The DAG consists of three smaller DAGs: - * 1. Grouping attributes - * 2. Precision attributes - * 3. Formatting attributes. - * - * The first two DAGs are simple in that setting any independent attribute - * in the DAG recalculates all the dependent attributes in that DAG. - * The updateGrouping() and updatePrecision() perform the respective - * recalculations. - * - * Because some of the derived formatting attributes are expensive to - * calculate, the formatting attributes DAG is more complex. The - * updateFormatting() method is composed of many updateFormattingXXX() - * methods, each of which recalculates a single derived attribute. The - * updateFormatting() method accepts a bitfield of recently changed - * attributes and passes this bitfield by reference to each of the - * updateFormattingXXX() methods. Each updateFormattingXXX() method checks - * the bitfield to see if any of the attributes it uses to compute the XXX - * attribute changed. If none of them changed, it exists immediately. However, - * if at least one of them changed, it recalculates the XXX attribute and - * sets the corresponding bit in the bitfield. In this way, each - * updateFormattingXXX() method encodes the directed edges in the formatting - * DAG that point to the attribute its calculating. - * - * Maintenance of the updateFormatting() method. - * - * Use care when changing the updateFormatting() method. - * The updateFormatting() method must call each updateFormattingXXX() in the - * same partial order that the formatting DAG prescribes. That is, the - * attributes near the bottom of the DAG must be calculated before attributes - * further up. As we mentioned in the prvious paragraph, the directed edges of - * the formatting DAG are encoded within each updateFormattingXXX() method. - * Finally, adding new attributes may involve adding to the bitmap that the - * updateFormatting() method uses. The top most attributes in the DAG, - * those that do not point to any attributes but only have attributes - * pointing to it, need not have a slot in the bitmap. - * - * Keep in mind that most of the code that makes the legacy DecimalFormat API - * work the way it always has before can be found in these various updateXXX() - * methods. For example the updatePrecisionForScientific() method - * handles the complex interactions amoung the various precision attributes - * when formatting in scientific notation. Changing the way attributes - * interract, often means changing one of these updateXXX() methods. - * - * Conclusion: - * - * The DecimFmtImpl class is the glue code between the legacy and new - * number formatting code. It uses a direct acyclic graph (DAG) to - * maintain backward compatibility, to make the code efficient, and to - * abstract away the complex interraction among legacy attributs. - */ - - -class DecimalFormatImpl : public UObject { -public: - -DecimalFormatImpl( - NumberFormat *super, - const Locale &locale, - const UnicodeString &pattern, - UErrorCode &status); -DecimalFormatImpl( - NumberFormat *super, - const UnicodeString &pattern, - DecimalFormatSymbols *symbolsToAdopt, - UParseError &parseError, - UErrorCode &status); -DecimalFormatImpl( - NumberFormat *super, - const DecimalFormatImpl &other, - UErrorCode &status); -DecimalFormatImpl &assign( - const DecimalFormatImpl &other, UErrorCode &status); -virtual ~DecimalFormatImpl(); -void adoptDecimalFormatSymbols(DecimalFormatSymbols *symbolsToAdopt); -const DecimalFormatSymbols &getDecimalFormatSymbols() const { - return *fSymbols; -} -UnicodeString &format( - int32_t number, - UnicodeString &appendTo, - FieldPosition &pos, - UErrorCode &status) const; -UnicodeString &format( - int32_t number, - UnicodeString &appendTo, - FieldPositionIterator *posIter, - UErrorCode &status) const; -UnicodeString &format( - int64_t number, - UnicodeString &appendTo, - FieldPosition &pos, - UErrorCode &status) const; -UnicodeString &format( - double number, - UnicodeString &appendTo, - FieldPosition &pos, - UErrorCode &status) const; -UnicodeString &format( - const DigitList &number, - UnicodeString &appendTo, - FieldPosition &pos, - UErrorCode &status) const; -UnicodeString &format( - int64_t number, - UnicodeString &appendTo, - FieldPositionIterator *posIter, - UErrorCode &status) const; -UnicodeString &format( - double number, - UnicodeString &appendTo, - FieldPositionIterator *posIter, - UErrorCode &status) const; -UnicodeString &format( - const DigitList &number, - UnicodeString &appendTo, - FieldPositionIterator *posIter, - UErrorCode &status) const; -UnicodeString &format( - StringPiece number, - UnicodeString &appendTo, - FieldPositionIterator *posIter, - UErrorCode &status) const; -UnicodeString &format( - const VisibleDigitsWithExponent &digits, - UnicodeString &appendTo, - FieldPosition &pos, - UErrorCode &status) const; -UnicodeString &format( - const VisibleDigitsWithExponent &digits, - UnicodeString &appendTo, - FieldPositionIterator *posIter, - UErrorCode &status) const; - -UBool operator==(const DecimalFormatImpl &) const; - -UBool operator!=(const DecimalFormatImpl &other) const { - return !(*this == other); -} - -void setRoundingMode(DecimalFormat::ERoundingMode mode) { - fRoundingMode = mode; - fEffPrecision.fMantissa.fExactOnly = (fRoundingMode == DecimalFormat::kRoundUnnecessary); - fEffPrecision.fMantissa.fRoundingMode = mode; -} -DecimalFormat::ERoundingMode getRoundingMode() const { - return fRoundingMode; -} -void setFailIfMoreThanMaxDigits(UBool b) { - fEffPrecision.fMantissa.fFailIfOverMax = b; -} -UBool isFailIfMoreThanMaxDigits() const { return fEffPrecision.fMantissa.fFailIfOverMax; } -void setMinimumSignificantDigits(int32_t newValue); -void setMaximumSignificantDigits(int32_t newValue); -void setMinMaxSignificantDigits(int32_t min, int32_t max); -void setScientificNotation(UBool newValue); -void setSignificantDigitsUsed(UBool newValue); - -int32_t getMinimumSignificantDigits() const { - return fMinSigDigits; } -int32_t getMaximumSignificantDigits() const { - return fMaxSigDigits; } -UBool isScientificNotation() const { return fUseScientific; } -UBool areSignificantDigitsUsed() const { return fUseSigDigits; } -void setGroupingSize(int32_t newValue); -void setSecondaryGroupingSize(int32_t newValue); -void setMinimumGroupingDigits(int32_t newValue); -int32_t getGroupingSize() const { return fGrouping.fGrouping; } -int32_t getSecondaryGroupingSize() const { return fGrouping.fGrouping2; } -int32_t getMinimumGroupingDigits() const { return fGrouping.fMinGrouping; } -void applyPattern(const UnicodeString &pattern, UErrorCode &status); -void applyPatternFavorCurrencyPrecision( - const UnicodeString &pattern, UErrorCode &status); -void applyPattern( - const UnicodeString &pattern, UParseError &perror, UErrorCode &status); -void applyLocalizedPattern(const UnicodeString &pattern, UErrorCode &status); -void applyLocalizedPattern( - const UnicodeString &pattern, UParseError &perror, UErrorCode &status); -void setCurrencyUsage(UCurrencyUsage usage, UErrorCode &status); -UCurrencyUsage getCurrencyUsage() const { return fCurrencyUsage; } -void setRoundingIncrement(double d); -double getRoundingIncrement() const; -int32_t getMultiplier() const; -void setMultiplier(int32_t m); -UChar32 getPadCharacter() const { return fAffixes.fPadChar; } -void setPadCharacter(UChar32 c) { fAffixes.fPadChar = c; } -int32_t getFormatWidth() const { return fAffixes.fWidth; } -void setFormatWidth(int32_t x) { fAffixes.fWidth = x; } -DigitAffixesAndPadding::EPadPosition getPadPosition() const { - return fAffixes.fPadPosition; -} -void setPadPosition(DigitAffixesAndPadding::EPadPosition x) { - fAffixes.fPadPosition = x; -} -int32_t getMinimumExponentDigits() const { - return fEffPrecision.fMinExponentDigits; -} -void setMinimumExponentDigits(int32_t x) { - fEffPrecision.fMinExponentDigits = x; -} -UBool isExponentSignAlwaysShown() const { - return fOptions.fExponent.fAlwaysShowSign; -} -void setExponentSignAlwaysShown(UBool x) { - fOptions.fExponent.fAlwaysShowSign = x; -} -UBool isDecimalSeparatorAlwaysShown() const { - return fOptions.fMantissa.fAlwaysShowDecimal; -} -void setDecimalSeparatorAlwaysShown(UBool x) { - fOptions.fMantissa.fAlwaysShowDecimal = x; -} -UnicodeString &getPositivePrefix(UnicodeString &result) const; -UnicodeString &getPositiveSuffix(UnicodeString &result) const; -UnicodeString &getNegativePrefix(UnicodeString &result) const; -UnicodeString &getNegativeSuffix(UnicodeString &result) const; -void setPositivePrefix(const UnicodeString &str); -void setPositiveSuffix(const UnicodeString &str); -void setNegativePrefix(const UnicodeString &str); -void setNegativeSuffix(const UnicodeString &str); -UnicodeString &toPattern(UnicodeString& result) const; -FixedDecimal &getFixedDecimal(double value, FixedDecimal &result, UErrorCode &status) const; -FixedDecimal &getFixedDecimal(DigitList &number, FixedDecimal &result, UErrorCode &status) const; -DigitList &round(DigitList &number, UErrorCode &status) const; - -VisibleDigitsWithExponent & -initVisibleDigitsWithExponent( - int64_t number, - VisibleDigitsWithExponent &digits, - UErrorCode &status) const; -VisibleDigitsWithExponent & -initVisibleDigitsWithExponent( - double number, - VisibleDigitsWithExponent &digits, - UErrorCode &status) const; -VisibleDigitsWithExponent & -initVisibleDigitsWithExponent( - DigitList &number, - VisibleDigitsWithExponent &digits, - UErrorCode &status) const; - -void updatePrecision(); -void updateGrouping(); -void updateCurrency(UErrorCode &status); - - -private: -// Disallow copy and assign -DecimalFormatImpl(const DecimalFormatImpl &other); -DecimalFormatImpl &operator=(const DecimalFormatImpl &other); -NumberFormat *fSuper; -DigitList fMultiplier; -int32_t fScale; - -DecimalFormat::ERoundingMode fRoundingMode; - -// These fields include what the user can see and set. -// When the user updates these fields, it triggers automatic updates of -// other fields that may be invisible to user - -// Updating any of the following fields triggers an update to -// fEffPrecision.fMantissa.fMin, -// fEffPrecision.fMantissa.fMax, -// fEffPrecision.fMantissa.fSignificant fields -// We have this two phase update because of backward compatibility. -// DecimalFormat has to remember all settings even if those settings are -// invalid or disabled. -int32_t fMinSigDigits; -int32_t fMaxSigDigits; -UBool fUseScientific; -UBool fUseSigDigits; -// In addition to these listed above, changes to min/max int digits and -// min/max frac digits from fSuper also trigger an update. - -// Updating any of the following fields triggers an update to -// fEffGrouping field Again we do it this way because original -// grouping settings have to be retained if grouping is turned off. -DigitGrouping fGrouping; -// In addition to these listed above, changes to isGroupingUsed in -// fSuper also triggers an update to fEffGrouping. - -// Updating any of the following fields triggers updates on the following: -// fMonetary, fRules, fAffixParser, fCurrencyAffixInfo, -// fFormatter, fAffixes.fPositivePrefiix, fAffixes.fPositiveSuffix, -// fAffixes.fNegativePrefiix, fAffixes.fNegativeSuffix -// We do this two phase update because localizing the affix patterns -// and formatters can be expensive. Better to do it once with the setters -// than each time within format. -AffixPattern fPositivePrefixPattern; -AffixPattern fNegativePrefixPattern; -AffixPattern fPositiveSuffixPattern; -AffixPattern fNegativeSuffixPattern; -DecimalFormatSymbols *fSymbols; -UCurrencyUsage fCurrencyUsage; -// In addition to these listed above, changes to getCurrency() in -// fSuper also triggers an update. - -// Optional may be NULL -PluralRules *fRules; - -// These fields are totally hidden from user and are used to derive the affixes -// in fAffixes below from the four affix patterns above. -UBool fMonetary; -AffixPatternParser fAffixParser; -CurrencyAffixInfo fCurrencyAffixInfo; - -// The actual precision used when formatting -ScientificPrecision fEffPrecision; - -// The actual grouping used when formatting -DigitGrouping fEffGrouping; -SciFormatterOptions fOptions; // Encapsulates fixed precision options -DigitFormatter fFormatter; -DigitAffixesAndPadding fAffixes; - -UnicodeString &formatInt32( - int32_t number, - UnicodeString &appendTo, - FieldPositionHandler &handler, - UErrorCode &status) const; - -UnicodeString &formatInt64( - int64_t number, - UnicodeString &appendTo, - FieldPositionHandler &handler, - UErrorCode &status) const; - -UnicodeString &formatDouble( - double number, - UnicodeString &appendTo, - FieldPositionHandler &handler, - UErrorCode &status) const; - -// Scales for precent or permille symbols -UnicodeString &formatDigitList( - DigitList &number, - UnicodeString &appendTo, - FieldPositionHandler &handler, - UErrorCode &status) const; - -// Does not scale for precent or permille symbols -UnicodeString &formatAdjustedDigitList( - DigitList &number, - UnicodeString &appendTo, - FieldPositionHandler &handler, - UErrorCode &status) const; - -UnicodeString &formatVisibleDigitsWithExponent( - const VisibleDigitsWithExponent &number, - UnicodeString &appendTo, - FieldPositionHandler &handler, - UErrorCode &status) const; - -VisibleDigitsWithExponent & -initVisibleDigitsFromAdjusted( - DigitList &number, - VisibleDigitsWithExponent &digits, - UErrorCode &status) const; - -template -UBool maybeFormatWithDigitList( - T number, - UnicodeString &appendTo, - FieldPositionHandler &handler, - UErrorCode &status) const; - -template -UBool maybeInitVisibleDigitsFromDigitList( - T number, - VisibleDigitsWithExponent &digits, - UErrorCode &status) const; - -DigitList &adjustDigitList(DigitList &number, UErrorCode &status) const; - -void applyPattern( - const UnicodeString &pattern, - UBool localized, UParseError &perror, UErrorCode &status); - -ValueFormatter &prepareValueFormatter(ValueFormatter &vf) const; -void setMultiplierScale(int32_t s); -int32_t getPatternScale() const; -void setScale(int32_t s) { fScale = s; } -int32_t getScale() const { return fScale; } - -// Updates everything -void updateAll(UErrorCode &status); -void updateAll( - int32_t formattingFlags, - UBool updatePrecisionBasedOnCurrency, - UErrorCode &status); - -// Updates from formatting pattern changes -void updateForApplyPattern(UErrorCode &status); -void updateForApplyPatternFavorCurrencyPrecision(UErrorCode &status); - -// Updates from changes to third group of attributes -void updateFormatting(int32_t changedFormattingFields, UErrorCode &status); -void updateFormatting( - int32_t changedFormattingFields, - UBool updatePrecisionBasedOnCurrency, - UErrorCode &status); - -// Helper functions for updatePrecision -void updatePrecisionForScientific(); -void updatePrecisionForFixed(); -void extractMinMaxDigits(DigitInterval &min, DigitInterval &max) const; -void extractSigDigits(SignificantDigitInterval &sig) const; - -// Helper functions for updateFormatting -void updateFormattingUsesCurrency(int32_t &changedFormattingFields); -void updateFormattingPluralRules( - int32_t &changedFormattingFields, UErrorCode &status); -void updateFormattingAffixParser(int32_t &changedFormattingFields); -void updateFormattingCurrencyAffixInfo( - int32_t &changedFormattingFields, - UBool updatePrecisionBasedOnCurrency, - UErrorCode &status); -void updateFormattingFixedPointFormatter( - int32_t &changedFormattingFields); -void updateFormattingLocalizedPositivePrefix( - int32_t &changedFormattingFields, UErrorCode &status); -void updateFormattingLocalizedPositiveSuffix( - int32_t &changedFormattingFields, UErrorCode &status); -void updateFormattingLocalizedNegativePrefix( - int32_t &changedFormattingFields, UErrorCode &status); -void updateFormattingLocalizedNegativeSuffix( - int32_t &changedFormattingFields, UErrorCode &status); - -int32_t computeExponentPatternLength() const; -int32_t countFractionDigitAndDecimalPatternLength(int32_t fracDigitCount) const; -UnicodeString &toNumberPattern( - UBool hasPadding, int32_t minimumLength, UnicodeString& result) const; - -int32_t getOldFormatWidth() const; -const UnicodeString &getConstSymbol( - DecimalFormatSymbols::ENumberFormatSymbol symbol) const; -UBool isParseFastpath() const; - -friend class DecimalFormat; - -}; - - -U_NAMESPACE_END -#endif /* #if !UCONFIG_NO_FORMATTING */ -#endif // DECIMFMTIMPL_H -//eof diff --git a/deps/icu-small/source/i18n/digitaffix.cpp b/deps/icu-small/source/i18n/digitaffix.cpp deleted file mode 100644 index 396df2cf1d7..00000000000 --- a/deps/icu-small/source/i18n/digitaffix.cpp +++ /dev/null @@ -1,109 +0,0 @@ -// © 2016 and later: Unicode, Inc. and others. -// License & terms of use: http://www.unicode.org/copyright.html -/* - * Copyright (C) 2015, International Business Machines - * Corporation and others. All Rights Reserved. - * - * file name: digitaffix.cpp - */ - -#include "unicode/utypes.h" - -#if !UCONFIG_NO_FORMATTING - -#include "digitaffix.h" -#include "fphdlimp.h" -#include "uassert.h" -#include "unistrappender.h" - -U_NAMESPACE_BEGIN - -DigitAffix::DigitAffix() : fAffix(), fAnnotations() { -} - -DigitAffix::DigitAffix( - const UChar *value, int32_t charCount, int32_t fieldId) - : fAffix(value, charCount), - fAnnotations(charCount, (UChar) fieldId, charCount) { -} - -void -DigitAffix::remove() { - fAffix.remove(); - fAnnotations.remove(); -} - -void -DigitAffix::appendUChar(UChar value, int32_t fieldId) { - fAffix.append(value); - fAnnotations.append((UChar) fieldId); -} - -void -DigitAffix::append(const UnicodeString &value, int32_t fieldId) { - fAffix.append(value); - { - UnicodeStringAppender appender(fAnnotations); - int32_t len = value.length(); - for (int32_t i = 0; i < len; ++i) { - appender.append((UChar) fieldId); - } - } -} - -void -DigitAffix::setTo(const UnicodeString &value, int32_t fieldId) { - fAffix = value; - fAnnotations.remove(); - { - UnicodeStringAppender appender(fAnnotations); - int32_t len = value.length(); - for (int32_t i = 0; i < len; ++i) { - appender.append((UChar) fieldId); - } - } -} - -void -DigitAffix::append(const UChar *value, int32_t charCount, int32_t fieldId) { - fAffix.append(value, charCount); - { - UnicodeStringAppender appender(fAnnotations); - for (int32_t i = 0; i < charCount; ++i) { - appender.append((UChar) fieldId); - } - } -} - -UnicodeString & -DigitAffix::format(FieldPositionHandler &handler, UnicodeString &appendTo) const { - int32_t len = fAffix.length(); - if (len == 0) { - return appendTo; - } - if (!handler.isRecording()) { - return appendTo.append(fAffix); - } - U_ASSERT(fAffix.length() == fAnnotations.length()); - int32_t appendToStart = appendTo.length(); - int32_t lastId = (int32_t) fAnnotations.charAt(0); - int32_t lastIdStart = 0; - for (int32_t i = 1; i < len; ++i) { - int32_t id = (int32_t) fAnnotations.charAt(i); - if (id != lastId) { - if (lastId != UNUM_FIELD_COUNT) { - handler.addAttribute(lastId, appendToStart + lastIdStart, appendToStart + i); - } - lastId = id; - lastIdStart = i; - } - } - if (lastId != UNUM_FIELD_COUNT) { - handler.addAttribute(lastId, appendToStart + lastIdStart, appendToStart + len); - } - return appendTo.append(fAffix); -} - -U_NAMESPACE_END - -#endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/deps/icu-small/source/i18n/digitaffix.h b/deps/icu-small/source/i18n/digitaffix.h deleted file mode 100644 index 005c36f8488..00000000000 --- a/deps/icu-small/source/i18n/digitaffix.h +++ /dev/null @@ -1,104 +0,0 @@ -// © 2016 and later: Unicode, Inc. and others. -// License & terms of use: http://www.unicode.org/copyright.html -/* -******************************************************************************* -* Copyright (C) 2015, International Business Machines -* Corporation and others. All Rights Reserved. -******************************************************************************* -* digitaffix.h -* -* created on: 2015jan06 -* created by: Travis Keep -*/ - -#ifndef __DIGITAFFIX_H__ -#define __DIGITAFFIX_H__ - -#include "unicode/uobject.h" - -#if !UCONFIG_NO_FORMATTING - -#include "unicode/unistr.h" -#include "unicode/unum.h" -#include "unicode/utypes.h" - -U_NAMESPACE_BEGIN - -class FieldPositionHandler; - -/** - * A prefix or suffix of a formatted number. - */ -class U_I18N_API DigitAffix : public UMemory { -public: - - /** - * Creates an empty DigitAffix. - */ - DigitAffix(); - - /** - * Creates a DigitAffix containing given UChars where all of it has - * a field type of fieldId. - */ - DigitAffix( - const UChar *value, - int32_t charCount, - int32_t fieldId=UNUM_FIELD_COUNT); - - /** - * Makes this affix be the empty string. - */ - void remove(); - - /** - * Append value to this affix. If fieldId is present, the appended - * string is considered to be the type fieldId. - */ - void appendUChar(UChar value, int32_t fieldId=UNUM_FIELD_COUNT); - - /** - * Append value to this affix. If fieldId is present, the appended - * string is considered to be the type fieldId. - */ - void append(const UnicodeString &value, int32_t fieldId=UNUM_FIELD_COUNT); - - /** - * Sets this affix to given string. The entire string - * is considered to be the type fieldId. - */ - void setTo(const UnicodeString &value, int32_t fieldId=UNUM_FIELD_COUNT); - - /** - * Append value to this affix. If fieldId is present, the appended - * string is considered to be the type fieldId. - */ - void append(const UChar *value, int32_t charCount, int32_t fieldId=UNUM_FIELD_COUNT); - - /** - * Formats this affix. - */ - UnicodeString &format( - FieldPositionHandler &handler, UnicodeString &appendTo) const; - int32_t countChar32() const { return fAffix.countChar32(); } - - /** - * Returns this affix as a unicode string. - */ - const UnicodeString & toString() const { return fAffix; } - - /** - * Returns TRUE if this object equals rhs. - */ - UBool equals(const DigitAffix &rhs) const { - return ((fAffix == rhs.fAffix) && (fAnnotations == rhs.fAnnotations)); - } -private: - UnicodeString fAffix; - UnicodeString fAnnotations; -}; - - -U_NAMESPACE_END -#endif // #if !UCONFIG_NO_FORMATTING -#endif // __DIGITAFFIX_H__ diff --git a/deps/icu-small/source/i18n/digitaffixesandpadding.cpp b/deps/icu-small/source/i18n/digitaffixesandpadding.cpp deleted file mode 100644 index 487d9a345d3..00000000000 --- a/deps/icu-small/source/i18n/digitaffixesandpadding.cpp +++ /dev/null @@ -1,175 +0,0 @@ -// © 2016 and later: Unicode, Inc. and others. -// License & terms of use: http://www.unicode.org/copyright.html -/* - * Copyright (C) 2015, International Business Machines - * Corporation and others. All Rights Reserved. - * - * file name: digitaffixesandpadding.cpp - */ - -#include "unicode/utypes.h" - -#if !UCONFIG_NO_FORMATTING - -#include "unicode/plurrule.h" -#include "charstr.h" -#include "digitaffix.h" -#include "digitaffixesandpadding.h" -#include "digitlst.h" -#include "uassert.h" -#include "valueformatter.h" -#include "visibledigits.h" - -U_NAMESPACE_BEGIN - -UBool -DigitAffixesAndPadding::needsPluralRules() const { - return ( - fPositivePrefix.hasMultipleVariants() || - fPositiveSuffix.hasMultipleVariants() || - fNegativePrefix.hasMultipleVariants() || - fNegativeSuffix.hasMultipleVariants()); -} - -UnicodeString & -DigitAffixesAndPadding::formatInt32( - int32_t value, - const ValueFormatter &formatter, - FieldPositionHandler &handler, - const PluralRules *optPluralRules, - UnicodeString &appendTo, - UErrorCode &status) const { - if (U_FAILURE(status)) { - return appendTo; - } - if (optPluralRules != NULL || fWidth > 0 || !formatter.isFastFormattable(value)) { - VisibleDigitsWithExponent digits; - formatter.toVisibleDigitsWithExponent( - (int64_t) value, digits, status); - return format( - digits, - formatter, - handler, - optPluralRules, - appendTo, - status); - } - UBool bPositive = value >= 0; - const DigitAffix *prefix = bPositive ? &fPositivePrefix.getOtherVariant() : &fNegativePrefix.getOtherVariant(); - const DigitAffix *suffix = bPositive ? &fPositiveSuffix.getOtherVariant() : &fNegativeSuffix.getOtherVariant(); - if (value < 0) { - value = -value; - } - prefix->format(handler, appendTo); - formatter.formatInt32(value, handler, appendTo); - return suffix->format(handler, appendTo); -} - -static UnicodeString & -formatAffix( - const DigitAffix *affix, - FieldPositionHandler &handler, - UnicodeString &appendTo) { - if (affix) { - affix->format(handler, appendTo); - } - return appendTo; -} - -static int32_t -countAffixChar32(const DigitAffix *affix) { - if (affix) { - return affix->countChar32(); - } - return 0; -} - -UnicodeString & -DigitAffixesAndPadding::format( - const VisibleDigitsWithExponent &digits, - const ValueFormatter &formatter, - FieldPositionHandler &handler, - const PluralRules *optPluralRules, - UnicodeString &appendTo, - UErrorCode &status) const { - if (U_FAILURE(status)) { - return appendTo; - } - const DigitAffix *prefix = NULL; - const DigitAffix *suffix = NULL; - if (!digits.isNaN()) { - UBool bPositive = !digits.isNegative(); - const PluralAffix *pluralPrefix = bPositive ? &fPositivePrefix : &fNegativePrefix; - const PluralAffix *pluralSuffix = bPositive ? &fPositiveSuffix : &fNegativeSuffix; - if (optPluralRules == NULL || digits.isInfinite()) { - prefix = &pluralPrefix->getOtherVariant(); - suffix = &pluralSuffix->getOtherVariant(); - } else { - UnicodeString count(optPluralRules->select(digits)); - prefix = &pluralPrefix->getByCategory(count); - suffix = &pluralSuffix->getByCategory(count); - } - } - if (fWidth <= 0) { - formatAffix(prefix, handler, appendTo); - formatter.format(digits, handler, appendTo); - return formatAffix(suffix, handler, appendTo); - } - int32_t codePointCount = countAffixChar32(prefix) + formatter.countChar32(digits) + countAffixChar32(suffix); - int32_t paddingCount = fWidth - codePointCount; - switch (fPadPosition) { - case kPadBeforePrefix: - appendPadding(paddingCount, appendTo); - formatAffix(prefix, handler, appendTo); - formatter.format(digits, handler, appendTo); - return formatAffix(suffix, handler, appendTo); - case kPadAfterPrefix: - formatAffix(prefix, handler, appendTo); - appendPadding(paddingCount, appendTo); - formatter.format(digits, handler, appendTo); - return formatAffix(suffix, handler, appendTo); - case kPadBeforeSuffix: - formatAffix(prefix, handler, appendTo); - formatter.format(digits, handler, appendTo); - appendPadding(paddingCount, appendTo); - return formatAffix(suffix, handler, appendTo); - case kPadAfterSuffix: - formatAffix(prefix, handler, appendTo); - formatter.format(digits, handler, appendTo); - formatAffix(suffix, handler, appendTo); - return appendPadding(paddingCount, appendTo); - default: - U_ASSERT(FALSE); - return appendTo; - } -} - -UnicodeString & -DigitAffixesAndPadding::format( - DigitList &value, - const ValueFormatter &formatter, - FieldPositionHandler &handler, - const PluralRules *optPluralRules, - UnicodeString &appendTo, - UErrorCode &status) const { - VisibleDigitsWithExponent digits; - formatter.toVisibleDigitsWithExponent( - value, digits, status); - if (U_FAILURE(status)) { - return appendTo; - } - return format( - digits, formatter, handler, optPluralRules, appendTo, status); -} - -UnicodeString & -DigitAffixesAndPadding::appendPadding(int32_t paddingCount, UnicodeString &appendTo) const { - for (int32_t i = 0; i < paddingCount; ++i) { - appendTo.append(fPadChar); - } - return appendTo; -} - - -U_NAMESPACE_END -#endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/deps/icu-small/source/i18n/digitaffixesandpadding.h b/deps/icu-small/source/i18n/digitaffixesandpadding.h deleted file mode 100644 index d570599d180..00000000000 --- a/deps/icu-small/source/i18n/digitaffixesandpadding.h +++ /dev/null @@ -1,179 +0,0 @@ -// © 2016 and later: Unicode, Inc. and others. -// License & terms of use: http://www.unicode.org/copyright.html -/* -******************************************************************************* -* Copyright (C) 2015, International Business Machines -* Corporation and others. All Rights Reserved. -******************************************************************************* -* digitaffixesandpadding.h -* -* created on: 2015jan06 -* created by: Travis Keep -*/ - -#ifndef __DIGITAFFIXESANDPADDING_H__ -#define __DIGITAFFIXESANDPADDING_H__ - -#include "unicode/utypes.h" - -#if !UCONFIG_NO_FORMATTING - -#include "unicode/uobject.h" -#include "pluralaffix.h" - -U_NAMESPACE_BEGIN - -class DigitList; -class ValueFormatter; -class UnicodeString; -class FieldPositionHandler; -class PluralRules; -class VisibleDigitsWithExponent; - -/** - * A formatter of numbers. This class can format any numerical value - * except for not a number (NaN), positive infinity, and negative infinity. - * This class manages prefixes, suffixes, and padding but delegates the - * formatting of actual positive values to a ValueFormatter. - */ -class U_I18N_API DigitAffixesAndPadding : public UMemory { -public: - -/** - * Equivalent to DecimalFormat EPadPosition, but redeclared here to prevent - * depending on DecimalFormat which would cause a circular dependency. - */ -enum EPadPosition { - kPadBeforePrefix, - kPadAfterPrefix, - kPadBeforeSuffix, - kPadAfterSuffix -}; - -/** - * The positive prefix - */ -PluralAffix fPositivePrefix; - -/** - * The positive suffix - */ -PluralAffix fPositiveSuffix; - -/** - * The negative suffix - */ -PluralAffix fNegativePrefix; - -/** - * The negative suffix - */ -PluralAffix fNegativeSuffix; - -/** - * The padding position - */ -EPadPosition fPadPosition; - -/** - * The padding character. - */ -UChar32 fPadChar; - -/** - * The field width in code points. The format method inserts instances of - * the padding character as needed in the desired padding position so that - * the entire formatted string contains this many code points. If the - * formatted string already exceeds this many code points, the format method - * inserts no padding. - */ -int32_t fWidth; - -/** - * Pad position is before prefix; padding character is '*' field width is 0. - * The affixes are all the empty string with no annotated fields with just - * the 'other' plural variation. - */ -DigitAffixesAndPadding() - : fPadPosition(kPadBeforePrefix), fPadChar(0x2a), fWidth(0) { } - -/** - * Returns TRUE if this object is equal to rhs. - */ -UBool equals(const DigitAffixesAndPadding &rhs) const { - return (fPositivePrefix.equals(rhs.fPositivePrefix) && - fPositiveSuffix.equals(rhs.fPositiveSuffix) && - fNegativePrefix.equals(rhs.fNegativePrefix) && - fNegativeSuffix.equals(rhs.fNegativeSuffix) && - fPadPosition == rhs.fPadPosition && - fWidth == rhs.fWidth && - fPadChar == rhs.fPadChar); -} - -/** - * Returns TRUE if a plural rules instance is needed to complete the - * formatting by detecting if any of the affixes have multiple plural - * variations. - */ -UBool needsPluralRules() const; - -/** - * Formats value and appends to appendTo. - * - * @param value the value to format. May be NaN or ininite. - * @param formatter handles the details of formatting the actual value. - * @param handler records field positions - * @param optPluralRules the plural rules, but may be NULL if - * needsPluralRules returns FALSE. - * @appendTo formatted string appended here. - * @status any error returned here. - */ -UnicodeString &format( - const VisibleDigitsWithExponent &value, - const ValueFormatter &formatter, - FieldPositionHandler &handler, - const PluralRules *optPluralRules, - UnicodeString &appendTo, - UErrorCode &status) const; - -/** - * For testing only. - */ -UnicodeString &format( - DigitList &value, - const ValueFormatter &formatter, - FieldPositionHandler &handler, - const PluralRules *optPluralRules, - UnicodeString &appendTo, - UErrorCode &status) const; - -/** - * Formats a 32-bit integer and appends to appendTo. When formatting an - * integer, this method is preferred to plain format as it can run - * several times faster under certain conditions. - * - * @param value the value to format. - * @param formatter handles the details of formatting the actual value. - * @param handler records field positions - * @param optPluralRules the plural rules, but may be NULL if - * needsPluralRules returns FALSE. - * @appendTo formatted string appended here. - * @status any error returned here. - */ -UnicodeString &formatInt32( - int32_t value, - const ValueFormatter &formatter, - FieldPositionHandler &handler, - const PluralRules *optPluralRules, - UnicodeString &appendTo, - UErrorCode &status) const; - -private: -UnicodeString &appendPadding(int32_t paddingCount, UnicodeString &appendTo) const; - -}; - - -U_NAMESPACE_END -#endif /* #if !UCONFIG_NO_FORMATTING */ -#endif // __DIGITAFFIXANDPADDING_H__ diff --git a/deps/icu-small/source/i18n/digitformatter.cpp b/deps/icu-small/source/i18n/digitformatter.cpp deleted file mode 100644 index 0d857f8f687..00000000000 --- a/deps/icu-small/source/i18n/digitformatter.cpp +++ /dev/null @@ -1,417 +0,0 @@ -// © 2016 and later: Unicode, Inc. and others. -// License & terms of use: http://www.unicode.org/copyright.html -/* - * Copyright (C) 2015, International Business Machines - * Corporation and others. All Rights Reserved. - * - * file name: digitformatter.cpp - */ - -#include "unicode/utypes.h" - -#if !UCONFIG_NO_FORMATTING - -#include "unicode/dcfmtsym.h" -#include "unicode/unum.h" - -#include "digitformatter.h" -#include "digitgrouping.h" -#include "digitinterval.h" -#include "digitlst.h" -#include "fphdlimp.h" -#include "smallintformatter.h" -#include "unistrappender.h" -#include "visibledigits.h" - -U_NAMESPACE_BEGIN - -DigitFormatter::DigitFormatter() - : fGroupingSeparator(",", -1, US_INV), fDecimal(".", -1, US_INV), - fNegativeSign("-", -1, US_INV), fPositiveSign("+", -1, US_INV), - fIsStandardDigits(TRUE), fExponent("E", -1, US_INV) { - for (int32_t i = 0; i < 10; ++i) { - fLocalizedDigits[i] = (UChar32) (0x30 + i); - } - fInfinity.setTo(UnicodeString("Inf", -1, US_INV), UNUM_INTEGER_FIELD); - fNan.setTo(UnicodeString("Nan", -1, US_INV), UNUM_INTEGER_FIELD); -} - -DigitFormatter::DigitFormatter(const DecimalFormatSymbols &symbols) { - setDecimalFormatSymbols(symbols); -} - -void -DigitFormatter::setOtherDecimalFormatSymbols( - const DecimalFormatSymbols &symbols) { - fLocalizedDigits[0] = symbols.getConstSymbol(DecimalFormatSymbols::kZeroDigitSymbol).char32At(0); - fLocalizedDigits[1] = symbols.getConstSymbol(DecimalFormatSymbols::kOneDigitSymbol).char32At(0); - fLocalizedDigits[2] = symbols.getConstSymbol(DecimalFormatSymbols::kTwoDigitSymbol).char32At(0); - fLocalizedDigits[3] = symbols.getConstSymbol(DecimalFormatSymbols::kThreeDigitSymbol).char32At(0); - fLocalizedDigits[4] = symbols.getConstSymbol(DecimalFormatSymbols::kFourDigitSymbol).char32At(0); - fLocalizedDigits[5] = symbols.getConstSymbol(DecimalFormatSymbols::kFiveDigitSymbol).char32At(0); - fLocalizedDigits[6] = symbols.getConstSymbol(DecimalFormatSymbols::kSixDigitSymbol).char32At(0); - fLocalizedDigits[7] = symbols.getConstSymbol(DecimalFormatSymbols::kSevenDigitSymbol).char32At(0); - fLocalizedDigits[8] = symbols.getConstSymbol(DecimalFormatSymbols::kEightDigitSymbol).char32At(0); - fLocalizedDigits[9] = symbols.getConstSymbol(DecimalFormatSymbols::kNineDigitSymbol).char32At(0); - fIsStandardDigits = isStandardDigits(); - fNegativeSign = symbols.getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol); - fPositiveSign = symbols.getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol); - fInfinity.setTo(symbols.getConstSymbol(DecimalFormatSymbols::kInfinitySymbol), UNUM_INTEGER_FIELD); - fNan.setTo(symbols.getConstSymbol(DecimalFormatSymbols::kNaNSymbol), UNUM_INTEGER_FIELD); - fExponent = symbols.getConstSymbol(DecimalFormatSymbols::kExponentialSymbol); -} - -void -DigitFormatter::setDecimalFormatSymbolsForMonetary( - const DecimalFormatSymbols &symbols) { - setOtherDecimalFormatSymbols(symbols); - fGroupingSeparator = symbols.getConstSymbol(DecimalFormatSymbols::kMonetaryGroupingSeparatorSymbol); - fDecimal = symbols.getConstSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol); -} - -void -DigitFormatter::setDecimalFormatSymbols( - const DecimalFormatSymbols &symbols) { - setOtherDecimalFormatSymbols(symbols); - fGroupingSeparator = symbols.getConstSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol); - fDecimal = symbols.getConstSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol); -} - -static void appendField( - int32_t fieldId, - const UnicodeString &value, - FieldPositionHandler &handler, - UnicodeString &appendTo) { - int32_t currentLength = appendTo.length(); - appendTo.append(value); - handler.addAttribute( - fieldId, - currentLength, - appendTo.length()); -} - -int32_t DigitFormatter::countChar32( - const DigitGrouping &grouping, - const DigitInterval &interval, - const DigitFormatterOptions &options) const { - int32_t result = interval.length(); - - // We always emit '0' in lieu of no digits. - if (result == 0) { - result = 1; - } - if (options.fAlwaysShowDecimal || interval.getLeastSignificantInclusive() < 0) { - result += fDecimal.countChar32(); - } - result += grouping.getSeparatorCount(interval.getIntDigitCount()) * fGroupingSeparator.countChar32(); - return result; -} - -int32_t -DigitFormatter::countChar32( - const VisibleDigits &digits, - const DigitGrouping &grouping, - const DigitFormatterOptions &options) const { - if (digits.isNaN()) { - return countChar32ForNaN(); - } - if (digits.isInfinite()) { - return countChar32ForInfinity(); - } - return countChar32( - grouping, - digits.getInterval(), - options); -} - -int32_t -DigitFormatter::countChar32( - const VisibleDigitsWithExponent &digits, - const SciFormatterOptions &options) const { - if (digits.isNaN()) { - return countChar32ForNaN(); - } - if (digits.isInfinite()) { - return countChar32ForInfinity(); - } - const VisibleDigits *exponent = digits.getExponent(); - if (exponent == NULL) { - DigitGrouping grouping; - return countChar32( - grouping, - digits.getMantissa().getInterval(), - options.fMantissa); - } - return countChar32( - *exponent, digits.getMantissa().getInterval(), options); -} - -int32_t -DigitFormatter::countChar32( - const VisibleDigits &exponent, - const DigitInterval &mantissaInterval, - const SciFormatterOptions &options) const { - DigitGrouping grouping; - int32_t count = countChar32( - grouping, mantissaInterval, options.fMantissa); - count += fExponent.countChar32(); - count += countChar32ForExponent( - exponent, options.fExponent); - return count; -} - -UnicodeString &DigitFormatter::format( - const VisibleDigits &digits, - const DigitGrouping &grouping, - const DigitFormatterOptions &options, - FieldPositionHandler &handler, - UnicodeString &appendTo) const { - if (digits.isNaN()) { - return formatNaN(handler, appendTo); - } - if (digits.isInfinite()) { - return formatInfinity(handler, appendTo); - } - - const DigitInterval &interval = digits.getInterval(); - int32_t digitsLeftOfDecimal = interval.getMostSignificantExclusive(); - int32_t lastDigitPos = interval.getLeastSignificantInclusive(); - int32_t intBegin = appendTo.length(); - int32_t fracBegin = 0; /* initialize to avoid compiler warning */ - - // Emit "0" instead of empty string. - if (digitsLeftOfDecimal == 0 && lastDigitPos == 0) { - appendTo.append(fLocalizedDigits[0]); - handler.addAttribute(UNUM_INTEGER_FIELD, intBegin, appendTo.length()); - if (options.fAlwaysShowDecimal) { - appendField( - UNUM_DECIMAL_SEPARATOR_FIELD, - fDecimal, - handler, - appendTo); - } - return appendTo; - } - { - UnicodeStringAppender appender(appendTo); - for (int32_t i = interval.getMostSignificantExclusive() - 1; - i >= interval.getLeastSignificantInclusive(); --i) { - if (i == -1) { - appender.flush(); - appendField( - UNUM_DECIMAL_SEPARATOR_FIELD, - fDecimal, - handler, - appendTo); - fracBegin = appendTo.length(); - } - appender.append(fLocalizedDigits[digits.getDigitByExponent(i)]); - if (grouping.isSeparatorAt(digitsLeftOfDecimal, i)) { - appender.flush(); - appendField( - UNUM_GROUPING_SEPARATOR_FIELD, - fGroupingSeparator, - handler, - appendTo); - } - if (i == 0) { - appender.flush(); - if (digitsLeftOfDecimal > 0) { - handler.addAttribute(UNUM_INTEGER_FIELD, intBegin, appendTo.length()); - } - } - } - if (options.fAlwaysShowDecimal && lastDigitPos == 0) { - appender.flush(); - appendField( - UNUM_DECIMAL_SEPARATOR_FIELD, - fDecimal, - handler, - appendTo); - } - } - // lastDigitPos is never > 0 so we are guaranteed that kIntegerField - // is already added. - if (lastDigitPos < 0) { - handler.addAttribute(UNUM_FRACTION_FIELD, fracBegin, appendTo.length()); - } - return appendTo; -} - -UnicodeString & -DigitFormatter::format( - const VisibleDigitsWithExponent &digits, - const SciFormatterOptions &options, - FieldPositionHandler &handler, - UnicodeString &appendTo) const { - DigitGrouping grouping; - format( - digits.getMantissa(), - grouping, - options.fMantissa, - handler, - appendTo); - const VisibleDigits *exponent = digits.getExponent(); - if (exponent == NULL) { - return appendTo; - } - int32_t expBegin = appendTo.length(); - appendTo.append(fExponent); - handler.addAttribute( - UNUM_EXPONENT_SYMBOL_FIELD, expBegin, appendTo.length()); - return formatExponent( - *exponent, - options.fExponent, - UNUM_EXPONENT_SIGN_FIELD, - UNUM_EXPONENT_FIELD, - handler, - appendTo); -} - -static int32_t formatInt( - int32_t value, uint8_t *digits) { - int32_t idx = 0; - while (value > 0) { - digits[idx++] = (uint8_t) (value % 10); - value /= 10; - } - return idx; -} - -UnicodeString & -DigitFormatter::formatDigits( - const uint8_t *digits, - int32_t count, - const IntDigitCountRange &range, - int32_t intField, - FieldPositionHandler &handler, - UnicodeString &appendTo) const { - int32_t i = range.pin(count) - 1; - int32_t begin = appendTo.length(); - - // Always emit '0' as placeholder for empty string. - if (i == -1) { - appendTo.append(fLocalizedDigits[0]); - handler.addAttribute(intField, begin, appendTo.length()); - return appendTo; - } - { - UnicodeStringAppender appender(appendTo); - for (; i >= count; --i) { - appender.append(fLocalizedDigits[0]); - } - for (; i >= 0; --i) { - appender.append(fLocalizedDigits[digits[i]]); - } - } - handler.addAttribute(intField, begin, appendTo.length()); - return appendTo; -} - -UnicodeString & -DigitFormatter::formatExponent( - const VisibleDigits &digits, - const DigitFormatterIntOptions &options, - int32_t signField, - int32_t intField, - FieldPositionHandler &handler, - UnicodeString &appendTo) const { - UBool neg = digits.isNegative(); - if (neg || options.fAlwaysShowSign) { - appendField( - signField, - neg ? fNegativeSign : fPositiveSign, - handler, - appendTo); - } - int32_t begin = appendTo.length(); - DigitGrouping grouping; - DigitFormatterOptions expOptions; - FieldPosition fpos(FieldPosition::DONT_CARE); - FieldPositionOnlyHandler noHandler(fpos); - format( - digits, - grouping, - expOptions, - noHandler, - appendTo); - handler.addAttribute(intField, begin, appendTo.length()); - return appendTo; -} - -int32_t -DigitFormatter::countChar32ForExponent( - const VisibleDigits &exponent, - const DigitFormatterIntOptions &options) const { - int32_t result = 0; - UBool neg = exponent.isNegative(); - if (neg || options.fAlwaysShowSign) { - result += neg ? fNegativeSign.countChar32() : fPositiveSign.countChar32(); - } - DigitGrouping grouping; - DigitFormatterOptions expOptions; - result += countChar32(grouping, exponent.getInterval(), expOptions); - return result; -} - -UnicodeString & -DigitFormatter::formatPositiveInt32( - int32_t positiveValue, - const IntDigitCountRange &range, - FieldPositionHandler &handler, - UnicodeString &appendTo) const { - // super fast path - if (fIsStandardDigits && SmallIntFormatter::canFormat(positiveValue, range)) { - int32_t begin = appendTo.length(); - SmallIntFormatter::format(positiveValue, range, appendTo); - handler.addAttribute(UNUM_INTEGER_FIELD, begin, appendTo.length()); - return appendTo; - } - uint8_t digits[10]; - int32_t count = formatInt(positiveValue, digits); - return formatDigits( - digits, - count, - range, - UNUM_INTEGER_FIELD, - handler, - appendTo); -} - -UBool DigitFormatter::isStandardDigits() const { - UChar32 cdigit = 0x30; - for (int32_t i = 0; i < UPRV_LENGTHOF(fLocalizedDigits); ++i) { - if (fLocalizedDigits[i] != cdigit) { - return FALSE; - } - ++cdigit; - } - return TRUE; -} - -UBool -DigitFormatter::equals(const DigitFormatter &rhs) const { - UBool result = (fGroupingSeparator == rhs.fGroupingSeparator) && - (fDecimal == rhs.fDecimal) && - (fNegativeSign == rhs.fNegativeSign) && - (fPositiveSign == rhs.fPositiveSign) && - (fInfinity.equals(rhs.fInfinity)) && - (fNan.equals(rhs.fNan)) && - (fIsStandardDigits == rhs.fIsStandardDigits) && - (fExponent == rhs.fExponent); - - if (!result) { - return FALSE; - } - for (int32_t i = 0; i < UPRV_LENGTHOF(fLocalizedDigits); ++i) { - if (fLocalizedDigits[i] != rhs.fLocalizedDigits[i]) { - return FALSE; - } - } - return TRUE; -} - - -U_NAMESPACE_END - -#endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/deps/icu-small/source/i18n/digitformatter.h b/deps/icu-small/source/i18n/digitformatter.h deleted file mode 100644 index 54a54c3639a..00000000000 --- a/deps/icu-small/source/i18n/digitformatter.h +++ /dev/null @@ -1,288 +0,0 @@ -// © 2016 and later: Unicode, Inc. and others. -// License & terms of use: http://www.unicode.org/copyright.html -/* -******************************************************************************* -* Copyright (C) 2015, International Business Machines -* Corporation and others. All Rights Reserved. -******************************************************************************* -* digitformatter.h -* -* created on: 2015jan06 -* created by: Travis Keep -*/ - -#ifndef __DIGITFORMATTER_H__ -#define __DIGITFORMATTER_H__ - -#include "unicode/uobject.h" - -#if !UCONFIG_NO_FORMATTING - -#include "unicode/utypes.h" -#include "unicode/unistr.h" -#include "digitaffix.h" - -U_NAMESPACE_BEGIN - -class DecimalFormatSymbols; -class DigitList; -class DigitGrouping; -class DigitInterval; -class UnicodeString; -class FieldPositionHandler; -class IntDigitCountRange; -class VisibleDigits; -class VisibleDigitsWithExponent; - -/** - * Various options for formatting in fixed point. - */ -class U_I18N_API DigitFormatterOptions : public UMemory { - public: - DigitFormatterOptions() : fAlwaysShowDecimal(FALSE) { } - - /** - * Returns TRUE if this object equals rhs. - */ - UBool equals(const DigitFormatterOptions &rhs) const { - return ( - fAlwaysShowDecimal == rhs.fAlwaysShowDecimal); - } - - /** - * Returns TRUE if these options allow for fast formatting of - * integers. - */ - UBool isFastFormattable() const { - return (fAlwaysShowDecimal == FALSE); - } - - /** - * If TRUE, show the decimal separator even when there are no fraction - * digits. default is FALSE. - */ - UBool fAlwaysShowDecimal; -}; - -/** - * Various options for formatting an integer. - */ -class U_I18N_API DigitFormatterIntOptions : public UMemory { - public: - DigitFormatterIntOptions() : fAlwaysShowSign(FALSE) { } - - /** - * Returns TRUE if this object equals rhs. - */ - UBool equals(const DigitFormatterIntOptions &rhs) const { - return (fAlwaysShowSign == rhs.fAlwaysShowSign); - } - - /** - * If TRUE, always prefix the integer with its sign even if the number is - * positive. Default is FALSE. - */ - UBool fAlwaysShowSign; -}; - -/** - * Options for formatting in scientific notation. - */ -class U_I18N_API SciFormatterOptions : public UMemory { - public: - - /** - * Returns TRUE if this object equals rhs. - */ - UBool equals(const SciFormatterOptions &rhs) const { - return (fMantissa.equals(rhs.fMantissa) && - fExponent.equals(rhs.fExponent)); - } - - /** - * Options for formatting the mantissa. - */ - DigitFormatterOptions fMantissa; - - /** - * Options for formatting the exponent. - */ - DigitFormatterIntOptions fExponent; -}; - - -/** - * Does fixed point formatting. - * - * This class only does fixed point formatting. It does no rounding before - * formatting. - */ -class U_I18N_API DigitFormatter : public UMemory { -public: - -/** - * Decimal separator is period (.), Plus sign is plus (+), - * minus sign is minus (-), grouping separator is comma (,), digits are 0-9. - */ -DigitFormatter(); - -/** - * Let symbols determine the digits, decimal separator, - * plus and mius sign, grouping separator, and possibly other settings. - */ -DigitFormatter(const DecimalFormatSymbols &symbols); - -/** - * Change what this instance uses for digits, decimal separator, - * plus and mius sign, grouping separator, and possibly other settings - * according to symbols. - */ -void setDecimalFormatSymbols(const DecimalFormatSymbols &symbols); - -/** - * Change what this instance uses for digits, decimal separator, - * plus and mius sign, grouping separator, and possibly other settings - * according to symbols in the context of monetary amounts. - */ -void setDecimalFormatSymbolsForMonetary(const DecimalFormatSymbols &symbols); - -/** - * Fixed point formatting. - * - * @param positiveDigits the value to format - * Negative sign can be present, but it won't show. - * @param grouping controls how digit grouping is done - * @param options formatting options - * @param handler records field positions - * @param appendTo formatted value appended here. - * @return appendTo - */ -UnicodeString &format( - const VisibleDigits &positiveDigits, - const DigitGrouping &grouping, - const DigitFormatterOptions &options, - FieldPositionHandler &handler, - UnicodeString &appendTo) const; - -/** - * formats in scientifc notation. - * @param positiveDigits the value to format. - * Negative sign can be present, but it won't show. - * @param options formatting options - * @param handler records field positions. - * @param appendTo formatted value appended here. - */ -UnicodeString &format( - const VisibleDigitsWithExponent &positiveDigits, - const SciFormatterOptions &options, - FieldPositionHandler &handler, - UnicodeString &appendTo) const; - -/** - * Fixed point formatting of integers. - * Always performed with no grouping and no decimal point. - * - * @param positiveValue the value to format must be positive. - * @param range specifies minimum and maximum number of digits. - * @param handler records field positions - * @param appendTo formatted value appended here. - * @return appendTo - */ -UnicodeString &formatPositiveInt32( - int32_t positiveValue, - const IntDigitCountRange &range, - FieldPositionHandler &handler, - UnicodeString &appendTo) const; - -/** - * Counts how many code points are needed for fixed formatting. - * If digits is negative, the negative sign is not included in the count. - */ -int32_t countChar32( - const VisibleDigits &digits, - const DigitGrouping &grouping, - const DigitFormatterOptions &options) const; - -/** - * Counts how many code points are needed for scientific formatting. - * If digits is negative, the negative sign is not included in the count. - */ -int32_t countChar32( - const VisibleDigitsWithExponent &digits, - const SciFormatterOptions &options) const; - -/** - * Returns TRUE if this object equals rhs. - */ -UBool equals(const DigitFormatter &rhs) const; - -private: -UChar32 fLocalizedDigits[10]; -UnicodeString fGroupingSeparator; -UnicodeString fDecimal; -UnicodeString fNegativeSign; -UnicodeString fPositiveSign; -DigitAffix fInfinity; -DigitAffix fNan; -UBool fIsStandardDigits; -UnicodeString fExponent; -UBool isStandardDigits() const; - -UnicodeString &formatDigits( - const uint8_t *digits, - int32_t count, - const IntDigitCountRange &range, - int32_t intField, - FieldPositionHandler &handler, - UnicodeString &appendTo) const; - -void setOtherDecimalFormatSymbols(const DecimalFormatSymbols &symbols); - -int32_t countChar32( - const VisibleDigits &exponent, - const DigitInterval &mantissaInterval, - const SciFormatterOptions &options) const; - -UnicodeString &formatNaN( - FieldPositionHandler &handler, - UnicodeString &appendTo) const { - return fNan.format(handler, appendTo); -} - -int32_t countChar32ForNaN() const { - return fNan.toString().countChar32(); -} - -UnicodeString &formatInfinity( - FieldPositionHandler &handler, - UnicodeString &appendTo) const { - return fInfinity.format(handler, appendTo); -} - -int32_t countChar32ForInfinity() const { - return fInfinity.toString().countChar32(); -} - -UnicodeString &formatExponent( - const VisibleDigits &digits, - const DigitFormatterIntOptions &options, - int32_t signField, - int32_t intField, - FieldPositionHandler &handler, - UnicodeString &appendTo) const; - -int32_t countChar32( - const DigitGrouping &grouping, - const DigitInterval &interval, - const DigitFormatterOptions &options) const; - -int32_t countChar32ForExponent( - const VisibleDigits &exponent, - const DigitFormatterIntOptions &options) const; - -}; - - -U_NAMESPACE_END -#endif /* #if !UCONFIG_NO_FORMATTING */ -#endif // __DIGITFORMATTER_H__ diff --git a/deps/icu-small/source/i18n/digitgrouping.cpp b/deps/icu-small/source/i18n/digitgrouping.cpp deleted file mode 100644 index cffa122b6ce..00000000000 --- a/deps/icu-small/source/i18n/digitgrouping.cpp +++ /dev/null @@ -1,58 +0,0 @@ -// © 2016 and later: Unicode, Inc. and others. -// License & terms of use: http://www.unicode.org/copyright.html -/* - * Copyright (C) 2015, International Business Machines - * Corporation and others. All Rights Reserved. - * - * file name: digitgrouping.cpp - */ - -#include "unicode/utypes.h" - -#include "digitgrouping.h" -#include "smallintformatter.h" - -U_NAMESPACE_BEGIN - -UBool DigitGrouping::isSeparatorAt( - int32_t digitsLeftOfDecimal, int32_t digitPos) const { - if (!isGroupingEnabled(digitsLeftOfDecimal) || digitPos < fGrouping) { - return FALSE; - } - return ((digitPos - fGrouping) % getGrouping2() == 0); -} - -int32_t DigitGrouping::getSeparatorCount(int32_t digitsLeftOfDecimal) const { - if (!isGroupingEnabled(digitsLeftOfDecimal)) { - return 0; - } - return (digitsLeftOfDecimal - 1 - fGrouping) / getGrouping2() + 1; -} - -UBool DigitGrouping::isGroupingEnabled(int32_t digitsLeftOfDecimal) const { - return (isGroupingUsed() - && digitsLeftOfDecimal >= fGrouping + getMinGrouping()); -} - -UBool DigitGrouping::isNoGrouping( - int32_t positiveValue, const IntDigitCountRange &range) const { - return getSeparatorCount( - SmallIntFormatter::estimateDigitCount(positiveValue, range)) == 0; -} - -int32_t DigitGrouping::getGrouping2() const { - return (fGrouping2 > 0 ? fGrouping2 : fGrouping); -} - -int32_t DigitGrouping::getMinGrouping() const { - return (fMinGrouping > 0 ? fMinGrouping : 1); -} - -void -DigitGrouping::clear() { - fMinGrouping = 0; - fGrouping = 0; - fGrouping2 = 0; -} - -U_NAMESPACE_END diff --git a/deps/icu-small/source/i18n/digitgrouping.h b/deps/icu-small/source/i18n/digitgrouping.h deleted file mode 100644 index f3f8679b879..00000000000 --- a/deps/icu-small/source/i18n/digitgrouping.h +++ /dev/null @@ -1,112 +0,0 @@ -// © 2016 and later: Unicode, Inc. and others. -// License & terms of use: http://www.unicode.org/copyright.html -/* -******************************************************************************* -* Copyright (C) 2015, International Business Machines -* Corporation and others. All Rights Reserved. -******************************************************************************* -* digitgrouping.h -* -* created on: 2015jan6 -* created by: Travis Keep -*/ - -#ifndef __DIGITGROUPING_H__ -#define __DIGITGROUPING_H__ - -#include "unicode/uobject.h" -#include "unicode/utypes.h" - -U_NAMESPACE_BEGIN - -class IntDigitCountRange; - -/** - * The digit grouping policy. - */ -class U_I18N_API DigitGrouping : public UMemory { -public: - /** - * Default is no digit grouping. - */ - DigitGrouping() : fGrouping(0), fGrouping2(0), fMinGrouping(0) { } - - /** - * Returns TRUE if this object is equal to rhs. - */ - UBool equals(const DigitGrouping &rhs) const { - return ((fGrouping == rhs.fGrouping) && - (fGrouping2 == rhs.fGrouping2) && - (fMinGrouping == rhs.fMinGrouping)); - } - - /** - * Returns true if a separator is needed after a particular digit. - * @param digitsLeftOfDecimal the total count of digits left of the - * decimal. - * @param digitPos 0 is the one's place; 1 is the 10's place; -1 is the - * 1/10's place etc. - */ - UBool isSeparatorAt(int32_t digitsLeftOfDecimal, int32_t digitPos) const; - - /** - * Returns the total number of separators to be used to format a particular - * number. - * @param digitsLeftOfDecimal the total number of digits to the left of - * the decimal. - */ - int32_t getSeparatorCount(int32_t digitsLeftOfDecimal) const; - - /** - * Returns true if grouping is used FALSE otherwise. When - * isGroupingUsed() returns FALSE; isSeparatorAt always returns FALSE - * and getSeparatorCount always returns 0. - */ - UBool isGroupingUsed() const { return fGrouping > 0; } - - /** - * Returns TRUE if this instance would not add grouping separators - * when formatting value using the given constraint on digit count. - * - * @param value the value to format. - * @param range the minimum and maximum digits for formatting value. - */ - UBool isNoGrouping( - int32_t positiveValue, const IntDigitCountRange &range) const; - - /** - * Clears this instance so that digit grouping is not in effect. - */ - void clear(); - -public: - - /** - * Primary grouping size. A value of 0, the default, or a negative - * number causes isGroupingUsed() to return FALSE. - */ - int32_t fGrouping; - - /** - * Secondary grouping size. If > 0, this size is used instead of - * 'fGrouping' for all but the group just to the left of the decimal - * point. The default value of 0, or a negative value indicates that - * there is no secondary grouping size. - */ - int32_t fGrouping2; - - /** - * If set (that is > 0), uses no grouping separators if fewer than - * (fGrouping + fMinGrouping) digits appear left of the decimal place. - * The default value for this field is 0. - */ - int32_t fMinGrouping; -private: - UBool isGroupingEnabled(int32_t digitsLeftOfDecimal) const; - int32_t getGrouping2() const; - int32_t getMinGrouping() const; -}; - -U_NAMESPACE_END - -#endif // __DIGITGROUPING_H__ diff --git a/deps/icu-small/source/i18n/digitinterval.cpp b/deps/icu-small/source/i18n/digitinterval.cpp deleted file mode 100644 index 32d952e0267..00000000000 --- a/deps/icu-small/source/i18n/digitinterval.cpp +++ /dev/null @@ -1,55 +0,0 @@ -// © 2016 and later: Unicode, Inc. and others. -// License & terms of use: http://www.unicode.org/copyright.html -/* - * Copyright (C) 2015, International Business Machines - * Corporation and others. All Rights Reserved. - * - * file name: digitinterval.cpp - */ - -#include "unicode/utypes.h" - -#include "digitinterval.h" - -U_NAMESPACE_BEGIN - -void DigitInterval::expandToContain(const DigitInterval &rhs) { - if (fSmallestInclusive > rhs.fSmallestInclusive) { - fSmallestInclusive = rhs.fSmallestInclusive; - } - if (fLargestExclusive < rhs.fLargestExclusive) { - fLargestExclusive = rhs.fLargestExclusive; - } -} - -void DigitInterval::shrinkToFitWithin(const DigitInterval &rhs) { - if (fSmallestInclusive < rhs.fSmallestInclusive) { - fSmallestInclusive = rhs.fSmallestInclusive; - } - if (fLargestExclusive > rhs.fLargestExclusive) { - fLargestExclusive = rhs.fLargestExclusive; - } -} - -void DigitInterval::setIntDigitCount(int32_t count) { - fLargestExclusive = count < 0 ? INT32_MAX : count; -} - -void DigitInterval::setFracDigitCount(int32_t count) { - fSmallestInclusive = count < 0 ? INT32_MIN : -count; -} - -void DigitInterval::expandToContainDigit(int32_t digitExponent) { - if (fLargestExclusive <= digitExponent) { - fLargestExclusive = digitExponent + 1; - } else if (fSmallestInclusive > digitExponent) { - fSmallestInclusive = digitExponent; - } -} - -UBool DigitInterval::contains(int32_t x) const { - return (x < fLargestExclusive && x >= fSmallestInclusive); -} - - -U_NAMESPACE_END diff --git a/deps/icu-small/source/i18n/digitinterval.h b/deps/icu-small/source/i18n/digitinterval.h deleted file mode 100644 index 95d406da206..00000000000 --- a/deps/icu-small/source/i18n/digitinterval.h +++ /dev/null @@ -1,159 +0,0 @@ -// © 2016 and later: Unicode, Inc. and others. -// License & terms of use: http://www.unicode.org/copyright.html -/* -******************************************************************************* -* Copyright (C) 2015, International Business Machines -* Corporation and others. All Rights Reserved. -******************************************************************************* -* digitinterval.h -* -* created on: 2015jan6 -* created by: Travis Keep -*/ - -#ifndef __DIGITINTERVAL_H__ -#define __DIGITINTERVAL_H__ - -#include "unicode/uobject.h" -#include "unicode/utypes.h" - -U_NAMESPACE_BEGIN - -/** - * An interval of digits. - * DigitIntervals are for fixed point formatting. A DigitInterval specifies - * zero or more integer digits and zero or more fractional digits. This class - * specifies particular digits in a number by their power of 10. For example, - * the digit position just to the left of the decimal is 0, and the digit - * position just left of that is 1. The digit position just to the right of - * the decimal is -1. The digit position just to the right of that is -2. - */ -class U_I18N_API DigitInterval : public UMemory { -public: - - /** - * Spans all integer and fraction digits - */ - DigitInterval() - : fLargestExclusive(INT32_MAX), fSmallestInclusive(INT32_MIN) { } - - - /** - * Makes this instance span all digits. - */ - void clear() { - fLargestExclusive = INT32_MAX; - fSmallestInclusive = INT32_MIN; - } - - /** - * Returns TRUE if this interval contains this digit position. - */ - UBool contains(int32_t digitPosition) const; - - /** - * Returns true if this object is the same as rhs. - */ - UBool equals(const DigitInterval &rhs) const { - return ((fLargestExclusive == rhs.fLargestExclusive) && - (fSmallestInclusive == rhs.fSmallestInclusive)); - } - - /** - * Expand this interval so that it contains all of rhs. - */ - void expandToContain(const DigitInterval &rhs); - - /** - * Shrink this interval so that it contains no more than rhs. - */ - void shrinkToFitWithin(const DigitInterval &rhs); - - /** - * Expand this interval as necessary to contain digit with given exponent - * After this method returns, this interval is guaranteed to contain - * digitExponent. - */ - void expandToContainDigit(int32_t digitExponent); - - /** - * Changes the number of digits to the left of the decimal point that - * this interval spans. If count is negative, it means span all digits - * to the left of the decimal point. - */ - void setIntDigitCount(int32_t count); - - /** - * Changes the number of digits to the right of the decimal point that - * this interval spans. If count is negative, it means span all digits - * to the right of the decimal point. - */ - void setFracDigitCount(int32_t count); - - /** - * Sets the least significant inclusive value to smallest. If smallest >= 0 - * then least significant inclusive value becomes 0. - */ - void setLeastSignificantInclusive(int32_t smallest) { - fSmallestInclusive = smallest < 0 ? smallest : 0; - } - - /** - * Sets the most significant exclusive value to largest. - * If largest <= 0 then most significant exclusive value becomes 0. - */ - void setMostSignificantExclusive(int32_t largest) { - fLargestExclusive = largest > 0 ? largest : 0; - } - - /** - * If returns 8, the most significant digit in interval is the 10^7 digit. - * Returns INT32_MAX if this interval spans all digits to left of - * decimal point. - */ - int32_t getMostSignificantExclusive() const { - return fLargestExclusive; - } - - /** - * Returns number of digits to the left of the decimal that this - * interval includes. This is a synonym for getMostSignificantExclusive(). - */ - int32_t getIntDigitCount() const { - return fLargestExclusive; - } - - /** - * Returns number of digits to the right of the decimal that this - * interval includes. - */ - int32_t getFracDigitCount() const { - return fSmallestInclusive == INT32_MIN ? INT32_MAX : -fSmallestInclusive; - } - - /** - * Returns the total number of digits that this interval spans. - * Caution: If this interval spans all digits to the left or right of - * decimal point instead of some fixed number, then what length() - * returns is undefined. - */ - int32_t length() const { - return fLargestExclusive - fSmallestInclusive; - } - - /** - * If returns -3, the least significant digit in interval is the 10^-3 - * digit. Returns INT32_MIN if this interval spans all digits to right of - * decimal point. - */ - int32_t getLeastSignificantInclusive() const { - return fSmallestInclusive; - } -private: - int32_t fLargestExclusive; - int32_t fSmallestInclusive; -}; - -U_NAMESPACE_END - -#endif // __DIGITINTERVAL_H__ diff --git a/deps/icu-small/source/i18n/digitlst.cpp b/deps/icu-small/source/i18n/digitlst.cpp deleted file mode 100644 index 37760defd70..00000000000 --- a/deps/icu-small/source/i18n/digitlst.cpp +++ /dev/null @@ -1,1143 +0,0 @@ -// © 2016 and later: Unicode, Inc. and others. -// License & terms of use: http://www.unicode.org/copyright.html -/* -********************************************************************** -* Copyright (C) 1997-2015, International Business Machines -* Corporation and others. All Rights Reserved. -********************************************************************** -* -* File DIGITLST.CPP -* -* Modification History: -* -* Date Name Description -* 03/21/97 clhuang Converted from java. -* 03/21/97 clhuang Implemented with new APIs. -* 03/27/97 helena Updated to pass the simple test after code review. -* 03/31/97 aliu Moved isLONG_MIN to here, and fixed it. -* 04/15/97 aliu Changed MAX_COUNT to DBL_DIG. Changed Digit to char. -* Reworked representation by replacing fDecimalAt -* with fExponent. -* 04/16/97 aliu Rewrote set() and getDouble() to use sprintf/atof -* to do digit conversion. -* 09/09/97 aliu Modified for exponential notation support. -* 08/02/98 stephen Added nearest/even rounding -* Fixed bug in fitsIntoLong -****************************************************************************** -*/ - -#if defined(__CYGWIN__) && !defined(_GNU_SOURCE) -#define _GNU_SOURCE -#endif - -#include "digitlst.h" - -#if !UCONFIG_NO_FORMATTING - -#include "unicode/putil.h" -#include "charstr.h" -#include "cmemory.h" -#include "cstring.h" -#include "mutex.h" -#include "putilimp.h" -#include "uassert.h" -#include "digitinterval.h" -#include "ucln_in.h" -#include "umutex.h" -#include "double-conversion.h" -#include -#include -#include -#include -#include - -using icu::double_conversion::DoubleToStringConverter; - -#if !defined(U_USE_STRTOD_L) -# if U_PLATFORM_USES_ONLY_WIN32_API -# define U_USE_STRTOD_L 1 -# define U_HAVE_XLOCALE_H 0 -# elif defined(U_HAVE_STRTOD_L) -# define U_USE_STRTOD_L U_HAVE_STRTOD_L -# else -# define U_USE_STRTOD_L 0 -# endif -#endif - -#if U_USE_STRTOD_L -# if U_HAVE_XLOCALE_H -# include -# else -# include -# endif -#endif - -// *************************************************************************** -// class DigitList -// A wrapper onto decNumber. -// Used to be standalone. -// *************************************************************************** - -/** - * This is the zero digit. The base for the digits returned by getDigit() - * Note that it is the platform invariant digit, and is not Unicode. - */ -#define kZero '0' - - -/* Only for 32 bit numbers. Ignore the negative sign. */ -//static const char LONG_MIN_REP[] = "2147483648"; -//static const char I64_MIN_REP[] = "9223372036854775808"; - - -U_NAMESPACE_BEGIN - -// ------------------------------------- -// default constructor - -DigitList::DigitList() -{ - uprv_decContextDefault(&fContext, DEC_INIT_BASE); - fContext.traps = 0; - uprv_decContextSetRounding(&fContext, DEC_ROUND_HALF_EVEN); - fContext.digits = fStorage.getCapacity(); - - fDecNumber = fStorage.getAlias(); - uprv_decNumberZero(fDecNumber); - - internalSetDouble(0.0); -} - -// ------------------------------------- - -DigitList::~DigitList() -{ -} - -// ------------------------------------- -// copy constructor - -DigitList::DigitList(const DigitList &other) -{ - fDecNumber = fStorage.getAlias(); - *this = other; -} - - -// ------------------------------------- -// assignment operator - -DigitList& -DigitList::operator=(const DigitList& other) -{ - if (this != &other) - { - uprv_memcpy(&fContext, &other.fContext, sizeof(decContext)); - - if (other.fStorage.getCapacity() > fStorage.getCapacity()) { - fDecNumber = fStorage.resize(other.fStorage.getCapacity()); - } - // Always reset the fContext.digits, even if fDecNumber was not reallocated, - // because above we copied fContext from other.fContext. - fContext.digits = fStorage.getCapacity(); - uprv_decNumberCopy(fDecNumber, other.fDecNumber); - - { - // fDouble is lazily created and cached. - // Avoid potential races with that happening with other.fDouble - // while we are doing the assignment. - Mutex mutex; - - if(other.fHave==kDouble) { - fUnion.fDouble = other.fUnion.fDouble; - } - fHave = other.fHave; - } - } - return *this; -} - -// ------------------------------------- -// operator == (does not exactly match the old DigitList function) - -UBool -DigitList::operator==(const DigitList& that) const -{ - if (this == &that) { - return TRUE; - } - decNumber n; // Has space for only a none digit value. - decContext c; - uprv_decContextDefault(&c, DEC_INIT_BASE); - c.digits = 1; - c.traps = 0; - - uprv_decNumberCompare(&n, this->fDecNumber, that.fDecNumber, &c); - UBool result = decNumberIsZero(&n); - return result; -} - -// ------------------------------------- -// comparison function. Returns -// Not Comparable : -2 -// < : -1 -// == : 0 -// > : +1 -int32_t DigitList::compare(const DigitList &other) { - decNumber result; - int32_t savedDigits = fContext.digits; - fContext.digits = 1; - uprv_decNumberCompare(&result, this->fDecNumber, other.fDecNumber, &fContext); - fContext.digits = savedDigits; - if (decNumberIsZero(&result)) { - return 0; - } else if (decNumberIsSpecial(&result)) { - return -2; - } else if (result.bits & DECNEG) { - return -1; - } else { - return 1; - } -} - - -// ------------------------------------- -// Reduce - remove trailing zero digits. -void -DigitList::reduce() { - uprv_decNumberReduce(fDecNumber, fDecNumber, &fContext); -} - - -// ------------------------------------- -// trim - remove trailing fraction zero digits. -void -DigitList::trim() { - uprv_decNumberTrim(fDecNumber); -} - -// ------------------------------------- -// Resets the digit list; sets all the digits to zero. - -void -DigitList::clear() -{ - uprv_decNumberZero(fDecNumber); - uprv_decContextSetRounding(&fContext, DEC_ROUND_HALF_EVEN); - internalSetDouble(0.0); -} - - -/** - * Formats a int64_t number into a base 10 string representation, and NULL terminates it. - * @param number The number to format - * @param outputStr The string to output to. Must be at least MAX_DIGITS+2 in length (21), - * to hold the longest int64_t value. - * @return the number of digits written, not including the sign. - */ -static int32_t -formatBase10(int64_t number, char *outputStr) { - // The number is output backwards, starting with the LSD. - // Fill the buffer from the far end. After the number is complete, - // slide the string contents to the front. - - const int32_t MAX_IDX = MAX_DIGITS+2; - int32_t destIdx = MAX_IDX; - outputStr[--destIdx] = 0; - - int64_t n = number; - if (number < 0) { // Negative numbers are slightly larger than a postive - outputStr[--destIdx] = (char)(-(n % 10) + kZero); - n /= -10; - } - do { - outputStr[--destIdx] = (char)(n % 10 + kZero); - n /= 10; - } while (n > 0); - - if (number < 0) { - outputStr[--destIdx] = '-'; - } - - // Slide the number to the start of the output str - U_ASSERT(destIdx >= 0); - int32_t length = MAX_IDX - destIdx; - uprv_memmove(outputStr, outputStr+MAX_IDX-length, length); - - return length; -} - - -// ------------------------------------- -// -// setRoundingMode() -// For most modes, the meaning and names are the same between the decNumber library -// (which DigitList follows) and the ICU Formatting Rounding Mode values. -// The flag constants are different, however. -// -// Note that ICU's kRoundingUnnecessary is not implemented directly by DigitList. -// This mode, inherited from Java, means that numbers that would not format exactly -// will return an error when formatting is attempted. - -void -DigitList::setRoundingMode(DecimalFormat::ERoundingMode m) { - enum rounding r; - - switch (m) { - case DecimalFormat::kRoundCeiling: r = DEC_ROUND_CEILING; break; - case DecimalFormat::kRoundFloor: r = DEC_ROUND_FLOOR; break; - case DecimalFormat::kRoundDown: r = DEC_ROUND_DOWN; break; - case DecimalFormat::kRoundUp: r = DEC_ROUND_UP; break; - case DecimalFormat::kRoundHalfEven: r = DEC_ROUND_HALF_EVEN; break; - case DecimalFormat::kRoundHalfDown: r = DEC_ROUND_HALF_DOWN; break; - case DecimalFormat::kRoundHalfUp: r = DEC_ROUND_HALF_UP; break; - case DecimalFormat::kRoundUnnecessary: r = DEC_ROUND_HALF_EVEN; break; - default: - // TODO: how to report the problem? - // Leave existing mode unchanged. - r = uprv_decContextGetRounding(&fContext); - } - uprv_decContextSetRounding(&fContext, r); - -} - - -// ------------------------------------- - -void -DigitList::setPositive(UBool s) { - if (s) { - fDecNumber->bits &= ~DECNEG; - } else { - fDecNumber->bits |= DECNEG; - } - internalClear(); -} -// ------------------------------------- - -void -DigitList::setDecimalAt(int32_t d) { - U_ASSERT((fDecNumber->bits & DECSPECIAL) == 0); // Not Infinity or NaN - U_ASSERT(d-1>-999999999); - U_ASSERT(d-1< 999999999); - int32_t adjustedDigits = fDecNumber->digits; - if (decNumberIsZero(fDecNumber)) { - // Account for difference in how zero is represented between DigitList & decNumber. - adjustedDigits = 0; - } - fDecNumber->exponent = d - adjustedDigits; - internalClear(); -} - -int32_t -DigitList::getDecimalAt() { - U_ASSERT((fDecNumber->bits & DECSPECIAL) == 0); // Not Infinity or NaN - if (decNumberIsZero(fDecNumber) || ((fDecNumber->bits & DECSPECIAL) != 0)) { - return fDecNumber->exponent; // Exponent should be zero for these cases. - } - return fDecNumber->exponent + fDecNumber->digits; -} - -void -DigitList::setCount(int32_t c) { - U_ASSERT(c <= fContext.digits); - if (c == 0) { - // For a value of zero, DigitList sets all fields to zero, while - // decNumber keeps one digit (with that digit being a zero) - c = 1; - fDecNumber->lsu[0] = 0; - } - fDecNumber->digits = c; - internalClear(); -} - -int32_t -DigitList::getCount() const { - if (decNumberIsZero(fDecNumber) && fDecNumber->exponent==0) { - // The extra test for exponent==0 is needed because parsing sometimes appends - // zero digits. It's bogus, decimalFormatter parsing needs to be cleaned up. - return 0; - } else { - return fDecNumber->digits; - } -} - -void -DigitList::setDigit(int32_t i, char v) { - int32_t count = fDecNumber->digits; - U_ASSERT(i='0' && v<='9'); - v &= 0x0f; - fDecNumber->lsu[count-i-1] = v; - internalClear(); -} - -char -DigitList::getDigit(int32_t i) { - int32_t count = fDecNumber->digits; - U_ASSERT(ilsu[count-i-1] + '0'; -} - -// copied from DigitList::getDigit() -uint8_t -DigitList::getDigitValue(int32_t i) { - int32_t count = fDecNumber->digits; - U_ASSERT(ilsu[count-i-1]; -} - -// ------------------------------------- -// Appends the digit to the digit list if it's not out of scope. -// Ignores the digit, otherwise. -// -// This function is horribly inefficient to implement with decNumber because -// the digits are stored least significant first, which requires moving all -// existing digits down one to make space for the new one to be appended. -// -void -DigitList::append(char digit) -{ - U_ASSERT(digit>='0' && digit<='9'); - // Ignore digits which exceed the precision we can represent - // And don't fix for larger precision. Fix callers instead. - if (decNumberIsZero(fDecNumber)) { - // Zero needs to be special cased because of the difference in the way - // that the old DigitList and decNumber represent it. - // digit cout was zero for digitList, is one for decNumber - fDecNumber->lsu[0] = digit & 0x0f; - fDecNumber->digits = 1; - fDecNumber->exponent--; // To match the old digit list implementation. - } else { - int32_t nDigits = fDecNumber->digits; - if (nDigits < fContext.digits) { - int i; - for (i=nDigits; i>0; i--) { - fDecNumber->lsu[i] = fDecNumber->lsu[i-1]; - } - fDecNumber->lsu[0] = digit & 0x0f; - fDecNumber->digits++; - // DigitList emulation - appending doesn't change the magnitude of existing - // digits. With decNumber's decimal being after the - // least signficant digit, we need to adjust the exponent. - fDecNumber->exponent--; - } - } - internalClear(); -} - -// ------------------------------------- - -/** - * Currently, getDouble() depends on strtod() to do its conversion. - * - * WARNING!! - * This is an extremely costly function. ~1/2 of the conversion time - * can be linked to this function. - */ -double -DigitList::getDouble() const -{ - { - Mutex mutex; - if (fHave == kDouble) { - return fUnion.fDouble; - } - } - - double tDouble = 0.0; - if (isZero()) { - tDouble = 0.0; - if (decNumberIsNegative(fDecNumber)) { - tDouble /= -1; - } - } else if (isInfinite()) { - if (std::numeric_limits::has_infinity) { - tDouble = std::numeric_limits::infinity(); - } else { - tDouble = std::numeric_limits::max(); - } - if (!isPositive()) { - tDouble = -tDouble; //this was incorrectly "-fDouble" originally. - } - } else { - MaybeStackArray s; - // Note: 14 is a magic constant from the decNumber library documentation, - // the max number of extra characters beyond the number of digits - // needed to represent the number in string form. Add a few more - // for the additional digits we retain. - - // Round down to appx. double precision, if the number is longer than that. - // Copy the number first, so that we don't modify the original. - if (getCount() > MAX_DBL_DIGITS + 3) { - DigitList numToConvert(*this); - numToConvert.reduce(); // Removes any trailing zeros, so that digit count is good. - numToConvert.round(MAX_DBL_DIGITS+3); - uprv_decNumberToString(numToConvert.fDecNumber, s.getAlias()); - // TODO: how many extra digits should be included for an accurate conversion? - } else { - uprv_decNumberToString(this->fDecNumber, s.getAlias()); - } - U_ASSERT(uprv_strlen(&s[0]) < MAX_DBL_DIGITS+18); - - char *end = NULL; - tDouble = decimalStrToDouble(s.getAlias(), &end); - } - { - Mutex mutex; - DigitList *nonConstThis = const_cast(this); - nonConstThis->internalSetDouble(tDouble); - } - return tDouble; -} - -#if U_USE_STRTOD_L && U_PLATFORM_USES_ONLY_WIN32_API -# define locale_t _locale_t -# define freelocale _free_locale -# define strtod_l _strtod_l -#endif - -#if U_USE_STRTOD_L -static locale_t gCLocale = (locale_t)0; -#endif -static icu::UInitOnce gCLocaleInitOnce = U_INITONCE_INITIALIZER; - -U_CDECL_BEGIN -// Cleanup callback func -static UBool U_CALLCONV digitList_cleanup(void) -{ -#if U_USE_STRTOD_L - if (gCLocale != (locale_t)0) { - freelocale(gCLocale); - } -#endif - return TRUE; -} -// C Locale initialization func -static void U_CALLCONV initCLocale(void) { - ucln_i18n_registerCleanup(UCLN_I18N_DIGITLIST, digitList_cleanup); -#if U_USE_STRTOD_L -# if U_PLATFORM_USES_ONLY_WIN32_API - gCLocale = _create_locale(LC_ALL, "C"); -# else - gCLocale = newlocale(LC_ALL_MASK, "C", (locale_t)0); -# endif -#endif -} -U_CDECL_END - -double -DigitList::decimalStrToDouble(char *decstr, char **end) { - umtx_initOnce(gCLocaleInitOnce, &initCLocale); -#if U_USE_STRTOD_L - return strtod_l(decstr, end, gCLocale); -#else - char *decimalPt = strchr(decstr, '.'); - if (decimalPt) { - // We need to know the decimal separator character that will be used with strtod(). - // Depends on the C runtime global locale. - // Most commonly is '.' - char rep[MAX_DIGITS]; - sprintf(rep, "%+1.1f", 1.0); - *decimalPt = rep[2]; - } - return uprv_strtod(decstr, end); -#endif -} - -// ------------------------------------- - -/** - * convert this number to an int32_t. Round if there is a fractional part. - * Return zero if the number cannot be represented. - */ -int32_t DigitList::getLong() /*const*/ -{ - int32_t result = 0; - if (getUpperExponent() > 10) { - // Overflow, absolute value too big. - return result; - } - if (fDecNumber->exponent != 0) { - // Force to an integer, with zero exponent, rounding if necessary. - // (decNumberToInt32 will only work if the exponent is exactly zero.) - DigitList copy(*this); - DigitList zero; - uprv_decNumberQuantize(copy.fDecNumber, copy.fDecNumber, zero.fDecNumber, &fContext); - result = uprv_decNumberToInt32(copy.fDecNumber, &fContext); - } else { - result = uprv_decNumberToInt32(fDecNumber, &fContext); - } - return result; -} - - -/** - * convert this number to an int64_t. Truncate if there is a fractional part. - * Return zero if the number cannot be represented. - */ -int64_t DigitList::getInt64() /*const*/ { - // TODO: fast conversion if fHave == fDouble - - // Truncate if non-integer. - // Return 0 if out of range. - // Range of in64_t is -9223372036854775808 to 9223372036854775807 (19 digits) - // - if (getUpperExponent() > 19) { - // Overflow, absolute value too big. - return 0; - } - - // The number of integer digits may differ from the number of digits stored - // in the decimal number. - // for 12.345 numIntDigits = 2, number->digits = 5 - // for 12E4 numIntDigits = 6, number->digits = 2 - // The conversion ignores the fraction digits in the first case, - // and fakes up extra zero digits in the second. - // TODO: It would be faster to store a table of powers of ten to multiply by - // instead of looping over zero digits, multiplying each time. - - int32_t numIntDigits = getUpperExponent(); - uint64_t value = 0; - for (int32_t i = 0; i < numIntDigits; i++) { - // Loop is iterating over digits starting with the most significant. - // Numbers are stored with the least significant digit at index zero. - int32_t digitIndex = fDecNumber->digits - i - 1; - int32_t v = (digitIndex >= 0) ? fDecNumber->lsu[digitIndex] : 0; - value = value * (uint64_t)10 + (uint64_t)v; - } - - if (decNumberIsNegative(fDecNumber)) { - value = ~value; - value += 1; - } - int64_t svalue = (int64_t)value; - - // Check overflow. It's convenient that the MSD is 9 only on overflow, the amount of - // overflow can't wrap too far. The test will also fail -0, but - // that does no harm; the right answer is 0. - if (numIntDigits == 19) { - if (( decNumberIsNegative(fDecNumber) && svalue>0) || - (!decNumberIsNegative(fDecNumber) && svalue<0)) { - svalue = 0; - } - } - - return svalue; -} - - -/** - * Return a string form of this number. - * Format is as defined by the decNumber library, for interchange of - * decimal numbers. - */ -void DigitList::getDecimal(CharString &str, UErrorCode &status) { - if (U_FAILURE(status)) { - return; - } - - // A decimal number in string form can, worst case, be 14 characters longer - // than the number of digits. So says the decNumber library doc. - int32_t maxLength = fDecNumber->digits + 14; - int32_t capacity = 0; - char *buffer = str.clear().getAppendBuffer(maxLength, 0, capacity, status); - if (U_FAILURE(status)) { - return; // Memory allocation error on growing the string. - } - U_ASSERT(capacity >= maxLength); - uprv_decNumberToString(this->fDecNumber, buffer); - U_ASSERT((int32_t)uprv_strlen(buffer) <= maxLength); - str.append(buffer, -1, status); -} - -/** - * Return true if this is an integer value that can be held - * by an int32_t type. - */ -UBool -DigitList::fitsIntoLong(UBool ignoreNegativeZero) /*const*/ -{ - if (decNumberIsSpecial(this->fDecNumber)) { - // NaN or Infinity. Does not fit in int32. - return FALSE; - } - uprv_decNumberTrim(this->fDecNumber); - if (fDecNumber->exponent < 0) { - // Number contains fraction digits. - return FALSE; - } - if (decNumberIsZero(this->fDecNumber) && !ignoreNegativeZero && - (fDecNumber->bits & DECNEG) != 0) { - // Negative Zero, not ingored. Cannot represent as a long. - return FALSE; - } - if (getUpperExponent() < 10) { - // The number is 9 or fewer digits. - // The max and min int32 are 10 digts, so this number fits. - // This is the common case. - return TRUE; - } - - // TODO: Should cache these constants; construction is relatively costly. - // But not of huge consequence; they're only needed for 10 digit ints. - UErrorCode status = U_ZERO_ERROR; - DigitList min32; min32.set("-2147483648", status); - if (this->compare(min32) < 0) { - return FALSE; - } - DigitList max32; max32.set("2147483647", status); - if (this->compare(max32) > 0) { - return FALSE; - } - if (U_FAILURE(status)) { - return FALSE; - } - return true; -} - - - -/** - * Return true if the number represented by this object can fit into - * a long. - */ -UBool -DigitList::fitsIntoInt64(UBool ignoreNegativeZero) /*const*/ -{ - if (decNumberIsSpecial(this->fDecNumber)) { - // NaN or Infinity. Does not fit in int32. - return FALSE; - } - uprv_decNumberTrim(this->fDecNumber); - if (fDecNumber->exponent < 0) { - // Number contains fraction digits. - return FALSE; - } - if (decNumberIsZero(this->fDecNumber) && !ignoreNegativeZero && - (fDecNumber->bits & DECNEG) != 0) { - // Negative Zero, not ingored. Cannot represent as a long. - return FALSE; - } - if (getUpperExponent() < 19) { - // The number is 18 or fewer digits. - // The max and min int64 are 19 digts, so this number fits. - // This is the common case. - return TRUE; - } - - // TODO: Should cache these constants; construction is relatively costly. - // But not of huge consequence; they're only needed for 19 digit ints. - UErrorCode status = U_ZERO_ERROR; - DigitList min64; min64.set("-9223372036854775808", status); - if (this->compare(min64) < 0) { - return FALSE; - } - DigitList max64; max64.set("9223372036854775807", status); - if (this->compare(max64) > 0) { - return FALSE; - } - if (U_FAILURE(status)) { - return FALSE; - } - return true; -} - - -// ------------------------------------- - -void -DigitList::set(int32_t source) -{ - set((int64_t)source); - internalSetDouble(source); -} - -// ------------------------------------- -/** - * Set an int64, via decnumber - */ -void -DigitList::set(int64_t source) -{ - char str[MAX_DIGITS+2]; // Leave room for sign and trailing nul. - formatBase10(source, str); - U_ASSERT(uprv_strlen(str) < sizeof(str)); - - uprv_decNumberFromString(fDecNumber, str, &fContext); - internalSetDouble(static_cast(source)); -} - -// ------------------------------------- -/** - * Set the DigitList from a decimal number string. - * - * The incoming string _must_ be nul terminated, even though it is arriving - * as a StringPiece because that is what the decNumber library wants. - * We can get away with this for an internal function; it would not - * be acceptable for a public API. - */ -void -DigitList::set(StringPiece source, UErrorCode &status, uint32_t /*fastpathBits*/) { - if (U_FAILURE(status)) { - return; - } - -#if 0 - if(fastpathBits==(kFastpathOk|kNoDecimal)) { - int32_t size = source.size(); - const char *data = source.data(); - int64_t r = 0; - int64_t m = 1; - // fast parse - while(size>0) { - char ch = data[--size]; - if(ch=='+') { - break; - } else if(ch=='-') { - r = -r; - break; - } else { - int64_t d = ch-'0'; - //printf("CH[%d]=%c, %d, *=%d\n", size,ch, (int)d, (int)m); - r+=(d)*m; - m *= 10; - } - } - //printf("R=%d\n", r); - set(r); - } else -#endif - { - // Figure out a max number of digits to use during the conversion, and - // resize the number up if necessary. - int32_t numDigits = source.length(); - if (numDigits > fContext.digits) { - // fContext.digits == fStorage.getCapacity() - decNumber *t = fStorage.resize(numDigits, fStorage.getCapacity()); - if (t == NULL) { - status = U_MEMORY_ALLOCATION_ERROR; - return; - } - fDecNumber = t; - fContext.digits = numDigits; - } - - fContext.status = 0; - uprv_decNumberFromString(fDecNumber, source.data(), &fContext); - if ((fContext.status & DEC_Conversion_syntax) != 0) { - status = U_DECIMAL_NUMBER_SYNTAX_ERROR; - } - } - internalClear(); -} - -/** - * Set the digit list to a representation of the given double value. - * This method supports both fixed-point and exponential notation. - * @param source Value to be converted. - */ -void -DigitList::set(double source) -{ - // for now, simple implementation; later, do proper IEEE stuff - char rep[MAX_DIGITS + 8]; // Extra space for '+', '.', e+NNN, and '\0' (actually +8 is enough) - - // Generate a representation of the form /[+-][0-9].[0-9]+e[+-][0-9]+/ - // Can also generate /[+-]nan/ or /[+-]inf/ - // TODO: Use something other than sprintf() here, since it's behavior is somewhat platform specific. - // That is why infinity is special cased here. - if (uprv_isInfinite(source)) { - if (uprv_isNegativeInfinity(source)) { - uprv_strcpy(rep,"-inf"); // Handle negative infinity - } else { - uprv_strcpy(rep,"inf"); - } - } else if (uprv_isNaN(source)) { - uprv_strcpy(rep, "NaN"); - } else { - bool sign; - int32_t length; - int32_t point; - DoubleToStringConverter::DoubleToAscii( - source, - DoubleToStringConverter::DtoaMode::SHORTEST, - 0, - rep + 1, - sizeof(rep), - &sign, - &length, - &point - ); - - // Convert the raw buffer into a string for decNumber - int32_t power = point - length; - if (sign) { - rep[0] = '-'; - } else { - rep[0] = '0'; - } - length++; - rep[length++] = 'E'; - if (power < 0) { - rep[length++] = '-'; - power = -power; - } else { - rep[length++] = '+'; - } - if (power < 10) { - rep[length++] = power + '0'; - } else if (power < 100) { - rep[length++] = (power / 10) + '0'; - rep[length++] = (power % 10) + '0'; - } else { - U_ASSERT(power < 1000); - rep[length + 2] = (power % 10) + '0'; - power /= 10; - rep[length + 1] = (power % 10) + '0'; - power /= 10; - rep[length] = power + '0'; - length += 3; - } - rep[length++] = 0; - } - U_ASSERT(uprv_strlen(rep) < sizeof(rep)); - - // uprv_decNumberFromString() will parse the string expecting '.' as a - // decimal separator, however sprintf() can use ',' in certain locales. - // Overwrite a ',' with '.' here before proceeding. - char *decimalSeparator = strchr(rep, ','); - if (decimalSeparator != NULL) { - *decimalSeparator = '.'; - } - - // Create a decNumber from the string. - uprv_decNumberFromString(fDecNumber, rep, &fContext); - uprv_decNumberTrim(fDecNumber); - internalSetDouble(source); -} - -// ------------------------------------- - -/* - * Multiply - * The number will be expanded if need be to retain full precision. - * In practice, for formatting, multiply is by 10, 100 or 1000, so more digits - * will not be required for this use. - */ -void -DigitList::mult(const DigitList &other, UErrorCode &status) { - if (U_FAILURE(status)) { - return; - } - fContext.status = 0; - int32_t requiredDigits = this->digits() + other.digits(); - if (requiredDigits > fContext.digits) { - reduce(); // Remove any trailing zeros - int32_t requiredDigits = this->digits() + other.digits(); - ensureCapacity(requiredDigits, status); - } - uprv_decNumberMultiply(fDecNumber, fDecNumber, other.fDecNumber, &fContext); - internalClear(); -} - -// ------------------------------------- - -/* - * Divide - * The number will _not_ be expanded for inexact results. - * TODO: probably should expand some, for rounding increments that - * could add a few digits, e.g. .25, but not expand arbitrarily. - */ -void -DigitList::div(const DigitList &other, UErrorCode &status) { - if (U_FAILURE(status)) { - return; - } - uprv_decNumberDivide(fDecNumber, fDecNumber, other.fDecNumber, &fContext); - internalClear(); -} - -// ------------------------------------- - -/* - * ensureCapacity. Grow the digit storage for the number if it's less than the requested - * amount. Never reduce it. Available size is kept in fContext.digits. - */ -void -DigitList::ensureCapacity(int32_t requestedCapacity, UErrorCode &status) { - if (U_FAILURE(status)) { - return; - } - if (requestedCapacity <= 0) { - status = U_ILLEGAL_ARGUMENT_ERROR; - return; - } - if (requestedCapacity > DEC_MAX_DIGITS) { - // Don't report an error for requesting too much. - // Arithemetic Results will be rounded to what can be supported. - // At 999,999,999 max digits, exceeding the limit is not too likely! - requestedCapacity = DEC_MAX_DIGITS; - } - if (requestedCapacity > fContext.digits) { - decNumber *newBuffer = fStorage.resize(requestedCapacity, fStorage.getCapacity()); - if (newBuffer == NULL) { - status = U_MEMORY_ALLOCATION_ERROR; - return; - } - fContext.digits = requestedCapacity; - fDecNumber = newBuffer; - } -} - -// ------------------------------------- - -/** - * Round the representation to the given number of digits. - * @param maximumDigits The maximum number of digits to be shown. - * Upon return, count will be less than or equal to maximumDigits. - */ -void -DigitList::round(int32_t maximumDigits) -{ - reduce(); - if (maximumDigits >= fDecNumber->digits) { - return; - } - int32_t savedDigits = fContext.digits; - fContext.digits = maximumDigits; - uprv_decNumberPlus(fDecNumber, fDecNumber, &fContext); - fContext.digits = savedDigits; - uprv_decNumberTrim(fDecNumber); - reduce(); - internalClear(); -} - - -void -DigitList::roundFixedPoint(int32_t maximumFractionDigits) { - reduce(); // Remove trailing zeros. - if (fDecNumber->exponent >= -maximumFractionDigits) { - return; - } - decNumber scale; // Dummy decimal number, but with the desired number of - uprv_decNumberZero(&scale); // fraction digits. - scale.exponent = -maximumFractionDigits; - scale.lsu[0] = 1; - - uprv_decNumberQuantize(fDecNumber, fDecNumber, &scale, &fContext); - reduce(); - internalClear(); -} - -// ------------------------------------- - -void -DigitList::toIntegralValue() { - uprv_decNumberToIntegralValue(fDecNumber, fDecNumber, &fContext); -} - - -// ------------------------------------- -UBool -DigitList::isZero() const -{ - return decNumberIsZero(fDecNumber); -} - -// ------------------------------------- -int32_t -DigitList::getUpperExponent() const { - return fDecNumber->digits + fDecNumber->exponent; -} - -DigitInterval & -DigitList::getSmallestInterval(DigitInterval &result) const { - result.setLeastSignificantInclusive(fDecNumber->exponent); - result.setMostSignificantExclusive(getUpperExponent()); - return result; -} - -uint8_t -DigitList::getDigitByExponent(int32_t exponent) const { - int32_t idx = exponent - fDecNumber->exponent; - if (idx < 0 || idx >= fDecNumber->digits) { - return 0; - } - return fDecNumber->lsu[idx]; -} - -void -DigitList::appendDigitsTo(CharString &str, UErrorCode &status) const { - str.append((const char *) fDecNumber->lsu, fDecNumber->digits, status); -} - -void -DigitList::roundAtExponent(int32_t exponent, int32_t maxSigDigits) { - reduce(); - if (maxSigDigits < fDecNumber->digits) { - int32_t minExponent = getUpperExponent() - maxSigDigits; - if (exponent < minExponent) { - exponent = minExponent; - } - } - if (exponent <= fDecNumber->exponent) { - return; - } - int32_t digits = getUpperExponent() - exponent; - if (digits > 0) { - round(digits); - } else { - roundFixedPoint(-exponent); - } -} - -void -DigitList::quantize(const DigitList &quantity, UErrorCode &status) { - if (U_FAILURE(status)) { - return; - } - div(quantity, status); - roundAtExponent(0); - mult(quantity, status); - reduce(); -} - -int32_t -DigitList::getScientificExponent( - int32_t minIntDigitCount, int32_t exponentMultiplier) const { - // The exponent for zero is always zero. - if (isZero()) { - return 0; - } - int32_t intDigitCount = getUpperExponent(); - int32_t exponent; - if (intDigitCount >= minIntDigitCount) { - int32_t maxAdjustment = intDigitCount - minIntDigitCount; - exponent = (maxAdjustment / exponentMultiplier) * exponentMultiplier; - } else { - int32_t minAdjustment = minIntDigitCount - intDigitCount; - exponent = ((minAdjustment + exponentMultiplier - 1) / exponentMultiplier) * -exponentMultiplier; - } - return exponent; -} - -int32_t -DigitList::toScientific( - int32_t minIntDigitCount, int32_t exponentMultiplier) { - int32_t exponent = getScientificExponent( - minIntDigitCount, exponentMultiplier); - shiftDecimalRight(-exponent); - return exponent; -} - -void -DigitList::shiftDecimalRight(int32_t n) { - fDecNumber->exponent += n; - internalClear(); -} - -U_NAMESPACE_END -#endif // #if !UCONFIG_NO_FORMATTING - -//eof diff --git a/deps/icu-small/source/i18n/digitlst.h b/deps/icu-small/source/i18n/digitlst.h deleted file mode 100644 index 6befaf32e6f..00000000000 --- a/deps/icu-small/source/i18n/digitlst.h +++ /dev/null @@ -1,529 +0,0 @@ -// © 2016 and later: Unicode, Inc. and others. -// License & terms of use: http://www.unicode.org/copyright.html -/* -****************************************************************************** -* -* Copyright (C) 1997-2015, International Business Machines -* Corporation and others. All Rights Reserved. -* -****************************************************************************** -* -* File DIGITLST.H -* -* Modification History: -* -* Date Name Description -* 02/25/97 aliu Converted from java. -* 03/21/97 clhuang Updated per C++ implementation. -* 04/15/97 aliu Changed MAX_COUNT to DBL_DIG. Changed Digit to char. -* 09/09/97 aliu Adapted for exponential notation support. -* 08/02/98 stephen Added nearest/even rounding -* 06/29/99 stephen Made LONG_DIGITS a macro to satisfy SUN compiler -* 07/09/99 stephen Removed kMaxCount (unused, for HP compiler) -****************************************************************************** -*/ - -#ifndef DIGITLST_H -#define DIGITLST_H - -#include "unicode/uobject.h" - -#if !UCONFIG_NO_FORMATTING -#include "unicode/decimfmt.h" -#include -#include "decContext.h" -#include "decNumber.h" -#include "cmemory.h" - -// Decimal digits in a 64-bit int -#define INT64_DIGITS 19 - -typedef enum EDigitListValues { - MAX_DBL_DIGITS = DBL_DIG, - MAX_I64_DIGITS = INT64_DIGITS, - MAX_DIGITS = MAX_I64_DIGITS, - MAX_EXPONENT = DBL_DIG, - DIGIT_PADDING = 3, - DEFAULT_DIGITS = 40, // Initial storage size, will grow as needed. - - // "+." + fDigits + "e" + fDecimalAt - MAX_DEC_DIGITS = MAX_DIGITS + DIGIT_PADDING + MAX_EXPONENT -} EDigitListValues; - -U_NAMESPACE_BEGIN - -class CharString; -class DigitInterval; - -// Export an explicit template instantiation of the MaybeStackHeaderAndArray that -// is used as a data member of DigitList. -// -// MSVC requires this, even though it should not be necessary. -// No direct access to the MaybeStackHeaderAndArray leaks out of the i18n library. -// -// Macintosh produces duplicate definition linker errors with the explicit template -// instantiation. -// -#if !U_PLATFORM_IS_DARWIN_BASED -template class U_I18N_API MaybeStackHeaderAndArray; -#endif - - -enum EStackMode { kOnStack }; - -enum EFastpathBits { kFastpathOk = 1, kNoDecimal = 2 }; - -/** - * Digit List is actually a Decimal Floating Point number. - * The original implementation has been replaced by a thin wrapper onto a - * decimal number from the decNumber library. - * - * The original DigitList API has been retained, to minimize the impact of - * the change on the rest of the ICU formatting code. - * - * The change to decNumber enables support for big decimal numbers, and - * allows rounding computations to be done directly in decimal, avoiding - * extra, and inaccurate, conversions to and from doubles. - * - * Original DigitList comments: - * - * Digit List utility class. Private to DecimalFormat. Handles the transcoding - * between numeric values and strings of characters. Only handles - * non-negative numbers. The division of labor between DigitList and - * DecimalFormat is that DigitList handles the radix 10 representation - * issues; DecimalFormat handles the locale-specific issues such as - * positive/negative, grouping, decimal point, currency, and so on. - *

- * A DigitList is really a representation of a floating point value. - * It may be an integer value; we assume that a double has sufficient - * precision to represent all digits of a long. - *

- * The DigitList representation consists of a string of characters, - * which are the digits radix 10, from '0' to '9'. It also has a radix - * 10 exponent associated with it. The value represented by a DigitList - * object can be computed by mulitplying the fraction f, where 0 <= f < 1, - * derived by placing all the digits of the list to the right of the - * decimal point, by 10^exponent. - * - * -------- - * - * DigitList vs. decimalNumber: - * - * DigitList stores digits with the most significant first. - * decNumber stores digits with the least significant first. - * - * DigitList, decimal point is before the most significant. - * decNumber, decimal point is after the least signficant digit. - * - * digitList: 0.ddddd * 10 ^ exp - * decNumber: ddddd. * 10 ^ exp - * - * digitList exponent = decNumber exponent + digit count - * - * digitList, digits are platform invariant chars, '0' - '9' - * decNumber, digits are binary, one per byte, 0 - 9. - * - * (decNumber library is configurable in how digits are stored, ICU has configured - * it this way for convenience in replacing the old DigitList implementation.) - */ -class U_I18N_API DigitList : public UMemory { // Declare external to make compiler happy -public: - - DigitList(); - ~DigitList(); - - /* copy constructor - * @param DigitList The object to be copied. - * @return the newly created object. - */ - DigitList(const DigitList&); // copy constructor - - /* assignment operator - * @param DigitList The object to be copied. - * @return the newly created object. - */ - DigitList& operator=(const DigitList&); // assignment operator - - /** - * Return true if another object is semantically equal to this one. - * @param other The DigitList to be compared for equality - * @return true if another object is semantically equal to this one. - * return false otherwise. - */ - UBool operator==(const DigitList& other) const; - - int32_t compare(const DigitList& other); - - - inline UBool operator!=(const DigitList& other) const { return !operator==(other); } - - /** - * Clears out the digits. - * Use before appending them. - * Typically, you set a series of digits with append, then at the point - * you hit the decimal point, you set myDigitList.fDecimalAt = myDigitList.fCount; - * then go on appending digits. - */ - void clear(void); - - /** - * Remove, by rounding, any fractional part of the decimal number, - * leaving an integer value. - */ - void toIntegralValue(); - - /** - * Appends digits to the list. - * CAUTION: this function is not recommended for new code. - * In the original DigitList implementation, decimal numbers were - * parsed by appending them to a digit list as they were encountered. - * With the revamped DigitList based on decNumber, append is very - * inefficient, and the interaction with the exponent value is confusing. - * Best avoided. - * TODO: remove this function once all use has been replaced. - * TODO: describe alternative to append() - * @param digit The digit to be appended. - */ - void append(char digit); - - /** - * Utility routine to get the value of the digit list - * Returns 0.0 if zero length. - * @return the value of the digit list. - */ - double getDouble(void) const; - - /** - * Utility routine to get the value of the digit list - * Make sure that fitsIntoLong() is called before calling this function. - * Returns 0 if zero length. - * @return the value of the digit list, return 0 if it is zero length - */ - int32_t getLong(void) /*const*/; - - /** - * Utility routine to get the value of the digit list - * Make sure that fitsIntoInt64() is called before calling this function. - * Returns 0 if zero length. - * @return the value of the digit list, return 0 if it is zero length - */ - int64_t getInt64(void) /*const*/; - - /** - * Utility routine to get the value of the digit list as a decimal string. - */ - void getDecimal(CharString &str, UErrorCode &status); - - /** - * Return true if the number represented by this object can fit into - * a long. - * @param ignoreNegativeZero True if negative zero is ignored. - * @return true if the number represented by this object can fit into - * a long, return false otherwise. - */ - UBool fitsIntoLong(UBool ignoreNegativeZero) /*const*/; - - /** - * Return true if the number represented by this object can fit into - * an int64_t. - * @param ignoreNegativeZero True if negative zero is ignored. - * @return true if the number represented by this object can fit into - * a long, return false otherwise. - */ - UBool fitsIntoInt64(UBool ignoreNegativeZero) /*const*/; - - /** - * Utility routine to set the value of the digit list from a double. - * @param source The value to be set - */ - void set(double source); - - /** - * Utility routine to set the value of the digit list from a long. - * If a non-zero maximumDigits is specified, no more than that number of - * significant digits will be produced. - * @param source The value to be set - */ - void set(int32_t source); - - /** - * Utility routine to set the value of the digit list from an int64. - * If a non-zero maximumDigits is specified, no more than that number of - * significant digits will be produced. - * @param source The value to be set - */ - void set(int64_t source); - - /** - * Utility routine to set the value of the digit list from an int64. - * Does not set the decnumber unless requested later - * If a non-zero maximumDigits is specified, no more than that number of - * significant digits will be produced. - * @param source The value to be set - */ - void setInteger(int64_t source); - - /** - * Utility routine to set the value of the digit list from a decimal number - * string. - * @param source The value to be set. The string must be nul-terminated. - * @param fastpathBits special flags for fast parsing - */ - void set(StringPiece source, UErrorCode &status, uint32_t fastpathBits = 0); - - /** - * Multiply this = this * arg - * This digitlist will be expanded if necessary to accomodate the result. - * @param arg the number to multiply by. - */ - void mult(const DigitList &arg, UErrorCode &status); - - /** - * Divide this = this / arg - */ - void div(const DigitList &arg, UErrorCode &status); - - // The following functions replace direct access to the original DigitList implmentation - // data structures. - - void setRoundingMode(DecimalFormat::ERoundingMode m); - - /** Test a number for zero. - * @return TRUE if the number is zero - */ - UBool isZero(void) const; - - /** Test for a Nan - * @return TRUE if the number is a NaN - */ - UBool isNaN(void) const {return decNumberIsNaN(fDecNumber);} - - UBool isInfinite() const {return decNumberIsInfinite(fDecNumber);} - - /** Reduce, or normalize. Removes trailing zeroes, adjusts exponent appropriately. */ - void reduce(); - - /** Remove trailing fraction zeros, adjust exponent accordingly. */ - void trim(); - - /** Set to zero */ - void setToZero() {uprv_decNumberZero(fDecNumber);} - - /** get the number of digits in the decimal number */ - int32_t digits() const {return fDecNumber->digits;} - - /** - * Round the number to the given number of digits. - * @param maximumDigits The maximum number of digits to be shown. - * Upon return, count will be less than or equal to maximumDigits. - * result is guaranteed to be trimmed. - */ - void round(int32_t maximumDigits); - - void roundFixedPoint(int32_t maximumFractionDigits); - - /** Ensure capacity for digits. Grow the storage if it is currently less than - * the requested size. Capacity is not reduced if it is already greater - * than requested. - */ - void ensureCapacity(int32_t requestedSize, UErrorCode &status); - - UBool isPositive(void) const { return decNumberIsNegative(fDecNumber) == 0;} - void setPositive(UBool s); - - void setDecimalAt(int32_t d); - int32_t getDecimalAt(); - - void setCount(int32_t c); - int32_t getCount() const; - - /** - * Set the digit in platform (invariant) format, from '0'..'9' - * @param i index of digit - * @param v digit value, from '0' to '9' in platform invariant format - */ - void setDigit(int32_t i, char v); - - /** - * Get the digit in platform (invariant) format, from '0'..'9' inclusive - * @param i index of digit - * @return invariant format of the digit - */ - char getDigit(int32_t i); - - - /** - * Get the digit's value, as an integer from 0..9 inclusive. - * Note that internally this value is a decNumberUnit, but ICU configures it to be a uint8_t. - * @param i index of digit - * @return value of that digit - */ - uint8_t getDigitValue(int32_t i); - - /** - * Gets the upper bound exponent for this value. For 987, returns 3 - * because 10^3 is the smallest power of 10 that is just greater than - * 987. - */ - int32_t getUpperExponent() const; - - /** - * Gets the lower bound exponent for this value. For 98.7, returns -1 - * because the right most digit, is the 10^-1 place. - */ - int32_t getLowerExponent() const { return fDecNumber->exponent; } - - /** - * Sets result to the smallest DigitInterval needed to display this - * DigitList in fixed point form and returns result. - */ - DigitInterval& getSmallestInterval(DigitInterval &result) const; - - /** - * Like getDigitValue, but the digit is identified by exponent. - * For example, getDigitByExponent(7) returns the 10^7 place of this - * DigitList. Unlike getDigitValue, there are no upper or lower bounds - * for passed parameter. Instead, getDigitByExponent returns 0 if - * the exponent falls outside the interval for this DigitList. - */ - uint8_t getDigitByExponent(int32_t exponent) const; - - /** - * Appends the digits in this object to a CharString. - * 3 is appended as (char) 3, not '3' - */ - void appendDigitsTo(CharString &str, UErrorCode &status) const; - - /** - * Equivalent to roundFixedPoint(-digitExponent) except unlike - * roundFixedPoint, this works for any digitExponent value. - * If maxSigDigits is set then this instance is rounded to have no more - * than maxSigDigits. The end result is guaranteed to be trimmed. - */ - void roundAtExponent(int32_t digitExponent, int32_t maxSigDigits=INT32_MAX); - - /** - * Quantizes according to some amount and rounds according to the - * context of this instance. Quantizing 3.233 with 0.05 gives 3.25. - */ - void quantize(const DigitList &amount, UErrorCode &status); - - /** - * Like toScientific but only returns the exponent - * leaving this instance unchanged. - */ - int32_t getScientificExponent( - int32_t minIntDigitCount, int32_t exponentMultiplier) const; - - /** - * Converts this instance to scientific notation. This instance - * becomes the mantissa and the exponent is returned. - * @param minIntDigitCount minimum integer digits in mantissa - * Exponent is set so that the actual number of integer digits - * in mantissa is as close to the minimum as possible. - * @param exponentMultiplier The exponent is always a multiple of - * This number. Usually 1, but set to 3 for engineering notation. - * @return exponent - */ - int32_t toScientific( - int32_t minIntDigitCount, int32_t exponentMultiplier); - - /** - * Shifts decimal to the right. - */ - void shiftDecimalRight(int32_t numPlaces); - -private: - /* - * These data members are intentionally public and can be set directly. - *

- * The value represented is given by placing the decimal point before - * fDigits[fDecimalAt]. If fDecimalAt is < 0, then leading zeros between - * the decimal point and the first nonzero digit are implied. If fDecimalAt - * is > fCount, then trailing zeros between the fDigits[fCount-1] and the - * decimal point are implied. - *

- * Equivalently, the represented value is given by f * 10^fDecimalAt. Here - * f is a value 0.1 <= f < 1 arrived at by placing the digits in fDigits to - * the right of the decimal. - *

- * DigitList is normalized, so if it is non-zero, fDigits[0] is non-zero. We - * don't allow denormalized numbers because our exponent is effectively of - * unlimited magnitude. The fCount value contains the number of significant - * digits present in fDigits[]. - *

- * Zero is represented by any DigitList with fCount == 0 or with each fDigits[i] - * for all i <= fCount == '0'. - * - * int32_t fDecimalAt; - * int32_t fCount; - * UBool fIsPositive; - * char *fDigits; - * DecimalFormat::ERoundingMode fRoundingMode; - */ - -public: - decContext fContext; // public access to status flags. - -private: - decNumber *fDecNumber; - MaybeStackHeaderAndArray fStorage; - - /* Cached double value corresponding to this decimal number. - * This is an optimization for the formatting implementation, which may - * ask for the double value multiple times. - */ - union DoubleOrInt64 { - double fDouble; - int64_t fInt64; - } fUnion; - enum EHave { - kNone=0, - kDouble - } fHave; - - - - UBool shouldRoundUp(int32_t maximumDigits) const; - - public: - -#if U_OVERRIDE_CXX_ALLOCATION - using UMemory::operator new; - using UMemory::operator delete; -#else - static inline void * U_EXPORT2 operator new(size_t size) U_NO_THROW { return ::operator new(size); }; - static inline void U_EXPORT2 operator delete(void *ptr ) U_NO_THROW { ::operator delete(ptr); }; -#endif - - static double U_EXPORT2 decimalStrToDouble(char *decstr, char **end); - - /** - * Placement new for stack usage - * @internal - */ - static inline void * U_EXPORT2 operator new(size_t /*size*/, void * onStack, EStackMode /*mode*/) U_NO_THROW { return onStack; } - - /** - * Placement delete for stack usage - * @internal - */ - static inline void U_EXPORT2 operator delete(void * /*ptr*/, void * /*onStack*/, EStackMode /*mode*/) U_NO_THROW {} - - private: - inline void internalSetDouble(double d) { - fHave = kDouble; - fUnion.fDouble=d; - } - inline void internalClear() { - fHave = kNone; - } -}; - - -U_NAMESPACE_END - -#endif // #if !UCONFIG_NO_FORMATTING -#endif // _DIGITLST - -//eof diff --git a/deps/icu-small/source/i18n/double-conversion-strtod.cpp b/deps/icu-small/source/i18n/double-conversion-strtod.cpp new file mode 100644 index 00000000000..be9b0b3bce0 --- /dev/null +++ b/deps/icu-small/source/i18n/double-conversion-strtod.cpp @@ -0,0 +1,574 @@ +// © 2018 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html +// +// From the double-conversion library. Original license: +// +// Copyright 2010 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// ICU PATCH: ifdef around UCONFIG_NO_FORMATTING +#include "unicode/utypes.h" +#if !UCONFIG_NO_FORMATTING + +#include +#include + +// ICU PATCH: Customize header file paths for ICU. +// The file fixed-dtoa.h is not needed. + +#include "double-conversion-strtod.h" +#include "double-conversion-bignum.h" +#include "double-conversion-cached-powers.h" +#include "double-conversion-ieee.h" + +// ICU PATCH: Wrap in ICU namespace +U_NAMESPACE_BEGIN + +namespace double_conversion { + +// 2^53 = 9007199254740992. +// Any integer with at most 15 decimal digits will hence fit into a double +// (which has a 53bit significand) without loss of precision. +static const int kMaxExactDoubleIntegerDecimalDigits = 15; +// 2^64 = 18446744073709551616 > 10^19 +static const int kMaxUint64DecimalDigits = 19; + +// Max double: 1.7976931348623157 x 10^308 +// Min non-zero double: 4.9406564584124654 x 10^-324 +// Any x >= 10^309 is interpreted as +infinity. +// Any x <= 10^-324 is interpreted as 0. +// Note that 2.5e-324 (despite being smaller than the min double) will be read +// as non-zero (equal to the min non-zero double). +static const int kMaxDecimalPower = 309; +static const int kMinDecimalPower = -324; + +// 2^64 = 18446744073709551616 +static const uint64_t kMaxUint64 = UINT64_2PART_C(0xFFFFFFFF, FFFFFFFF); + + +static const double exact_powers_of_ten[] = { + 1.0, // 10^0 + 10.0, + 100.0, + 1000.0, + 10000.0, + 100000.0, + 1000000.0, + 10000000.0, + 100000000.0, + 1000000000.0, + 10000000000.0, // 10^10 + 100000000000.0, + 1000000000000.0, + 10000000000000.0, + 100000000000000.0, + 1000000000000000.0, + 10000000000000000.0, + 100000000000000000.0, + 1000000000000000000.0, + 10000000000000000000.0, + 100000000000000000000.0, // 10^20 + 1000000000000000000000.0, + // 10^22 = 0x21e19e0c9bab2400000 = 0x878678326eac9 * 2^22 + 10000000000000000000000.0 +}; +static const int kExactPowersOfTenSize = ARRAY_SIZE(exact_powers_of_ten); + +// Maximum number of significant digits in the decimal representation. +// In fact the value is 772 (see conversions.cc), but to give us some margin +// we round up to 780. +static const int kMaxSignificantDecimalDigits = 780; + +static Vector TrimLeadingZeros(Vector buffer) { + for (int i = 0; i < buffer.length(); i++) { + if (buffer[i] != '0') { + return buffer.SubVector(i, buffer.length()); + } + } + return Vector(buffer.start(), 0); +} + + +static Vector TrimTrailingZeros(Vector buffer) { + for (int i = buffer.length() - 1; i >= 0; --i) { + if (buffer[i] != '0') { + return buffer.SubVector(0, i + 1); + } + } + return Vector(buffer.start(), 0); +} + + +static void CutToMaxSignificantDigits(Vector buffer, + int exponent, + char* significant_buffer, + int* significant_exponent) { + for (int i = 0; i < kMaxSignificantDecimalDigits - 1; ++i) { + significant_buffer[i] = buffer[i]; + } + // The input buffer has been trimmed. Therefore the last digit must be + // different from '0'. + ASSERT(buffer[buffer.length() - 1] != '0'); + // Set the last digit to be non-zero. This is sufficient to guarantee + // correct rounding. + significant_buffer[kMaxSignificantDecimalDigits - 1] = '1'; + *significant_exponent = + exponent + (buffer.length() - kMaxSignificantDecimalDigits); +} + + +// Trims the buffer and cuts it to at most kMaxSignificantDecimalDigits. +// If possible the input-buffer is reused, but if the buffer needs to be +// modified (due to cutting), then the input needs to be copied into the +// buffer_copy_space. +static void TrimAndCut(Vector buffer, int exponent, + char* buffer_copy_space, int space_size, + Vector* trimmed, int* updated_exponent) { + Vector left_trimmed = TrimLeadingZeros(buffer); + Vector right_trimmed = TrimTrailingZeros(left_trimmed); + exponent += left_trimmed.length() - right_trimmed.length(); + if (right_trimmed.length() > kMaxSignificantDecimalDigits) { + (void) space_size; // Mark variable as used. + ASSERT(space_size >= kMaxSignificantDecimalDigits); + CutToMaxSignificantDigits(right_trimmed, exponent, + buffer_copy_space, updated_exponent); + *trimmed = Vector(buffer_copy_space, + kMaxSignificantDecimalDigits); + } else { + *trimmed = right_trimmed; + *updated_exponent = exponent; + } +} + + +// Reads digits from the buffer and converts them to a uint64. +// Reads in as many digits as fit into a uint64. +// When the string starts with "1844674407370955161" no further digit is read. +// Since 2^64 = 18446744073709551616 it would still be possible read another +// digit if it was less or equal than 6, but this would complicate the code. +static uint64_t ReadUint64(Vector buffer, + int* number_of_read_digits) { + uint64_t result = 0; + int i = 0; + while (i < buffer.length() && result <= (kMaxUint64 / 10 - 1)) { + int digit = buffer[i++] - '0'; + ASSERT(0 <= digit && digit <= 9); + result = 10 * result + digit; + } + *number_of_read_digits = i; + return result; +} + + +// Reads a DiyFp from the buffer. +// The returned DiyFp is not necessarily normalized. +// If remaining_decimals is zero then the returned DiyFp is accurate. +// Otherwise it has been rounded and has error of at most 1/2 ulp. +static void ReadDiyFp(Vector buffer, + DiyFp* result, + int* remaining_decimals) { + int read_digits; + uint64_t significand = ReadUint64(buffer, &read_digits); + if (buffer.length() == read_digits) { + *result = DiyFp(significand, 0); + *remaining_decimals = 0; + } else { + // Round the significand. + if (buffer[read_digits] >= '5') { + significand++; + } + // Compute the binary exponent. + int exponent = 0; + *result = DiyFp(significand, exponent); + *remaining_decimals = buffer.length() - read_digits; + } +} + + +static bool DoubleStrtod(Vector trimmed, + int exponent, + double* result) { +#if !defined(DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS) + // On x86 the floating-point stack can be 64 or 80 bits wide. If it is + // 80 bits wide (as is the case on Linux) then double-rounding occurs and the + // result is not accurate. + // We know that Windows32 uses 64 bits and is therefore accurate. + // Note that the ARM simulator is compiled for 32bits. It therefore exhibits + // the same problem. + return false; +#endif + if (trimmed.length() <= kMaxExactDoubleIntegerDecimalDigits) { + int read_digits; + // The trimmed input fits into a double. + // If the 10^exponent (resp. 10^-exponent) fits into a double too then we + // can compute the result-double simply by multiplying (resp. dividing) the + // two numbers. + // This is possible because IEEE guarantees that floating-point operations + // return the best possible approximation. + if (exponent < 0 && -exponent < kExactPowersOfTenSize) { + // 10^-exponent fits into a double. + *result = static_cast(ReadUint64(trimmed, &read_digits)); + ASSERT(read_digits == trimmed.length()); + *result /= exact_powers_of_ten[-exponent]; + return true; + } + if (0 <= exponent && exponent < kExactPowersOfTenSize) { + // 10^exponent fits into a double. + *result = static_cast(ReadUint64(trimmed, &read_digits)); + ASSERT(read_digits == trimmed.length()); + *result *= exact_powers_of_ten[exponent]; + return true; + } + int remaining_digits = + kMaxExactDoubleIntegerDecimalDigits - trimmed.length(); + if ((0 <= exponent) && + (exponent - remaining_digits < kExactPowersOfTenSize)) { + // The trimmed string was short and we can multiply it with + // 10^remaining_digits. As a result the remaining exponent now fits + // into a double too. + *result = static_cast(ReadUint64(trimmed, &read_digits)); + ASSERT(read_digits == trimmed.length()); + *result *= exact_powers_of_ten[remaining_digits]; + *result *= exact_powers_of_ten[exponent - remaining_digits]; + return true; + } + } + return false; +} + + +// Returns 10^exponent as an exact DiyFp. +// The given exponent must be in the range [1; kDecimalExponentDistance[. +static DiyFp AdjustmentPowerOfTen(int exponent) { + ASSERT(0 < exponent); + ASSERT(exponent < PowersOfTenCache::kDecimalExponentDistance); + // Simply hardcode the remaining powers for the given decimal exponent + // distance. + ASSERT(PowersOfTenCache::kDecimalExponentDistance == 8); + switch (exponent) { + case 1: return DiyFp(UINT64_2PART_C(0xa0000000, 00000000), -60); + case 2: return DiyFp(UINT64_2PART_C(0xc8000000, 00000000), -57); + case 3: return DiyFp(UINT64_2PART_C(0xfa000000, 00000000), -54); + case 4: return DiyFp(UINT64_2PART_C(0x9c400000, 00000000), -50); + case 5: return DiyFp(UINT64_2PART_C(0xc3500000, 00000000), -47); + case 6: return DiyFp(UINT64_2PART_C(0xf4240000, 00000000), -44); + case 7: return DiyFp(UINT64_2PART_C(0x98968000, 00000000), -40); + default: + UNREACHABLE(); + } +} + + +// If the function returns true then the result is the correct double. +// Otherwise it is either the correct double or the double that is just below +// the correct double. +static bool DiyFpStrtod(Vector buffer, + int exponent, + double* result) { + DiyFp input; + int remaining_decimals; + ReadDiyFp(buffer, &input, &remaining_decimals); + // Since we may have dropped some digits the input is not accurate. + // If remaining_decimals is different than 0 than the error is at most + // .5 ulp (unit in the last place). + // We don't want to deal with fractions and therefore keep a common + // denominator. + const int kDenominatorLog = 3; + const int kDenominator = 1 << kDenominatorLog; + // Move the remaining decimals into the exponent. + exponent += remaining_decimals; + uint64_t error = (remaining_decimals == 0 ? 0 : kDenominator / 2); + + int old_e = input.e(); + input.Normalize(); + error <<= old_e - input.e(); + + ASSERT(exponent <= PowersOfTenCache::kMaxDecimalExponent); + if (exponent < PowersOfTenCache::kMinDecimalExponent) { + *result = 0.0; + return true; + } + DiyFp cached_power; + int cached_decimal_exponent; + PowersOfTenCache::GetCachedPowerForDecimalExponent(exponent, + &cached_power, + &cached_decimal_exponent); + + if (cached_decimal_exponent != exponent) { + int adjustment_exponent = exponent - cached_decimal_exponent; + DiyFp adjustment_power = AdjustmentPowerOfTen(adjustment_exponent); + input.Multiply(adjustment_power); + if (kMaxUint64DecimalDigits - buffer.length() >= adjustment_exponent) { + // The product of input with the adjustment power fits into a 64 bit + // integer. + ASSERT(DiyFp::kSignificandSize == 64); + } else { + // The adjustment power is exact. There is hence only an error of 0.5. + error += kDenominator / 2; + } + } + + input.Multiply(cached_power); + // The error introduced by a multiplication of a*b equals + // error_a + error_b + error_a*error_b/2^64 + 0.5 + // Substituting a with 'input' and b with 'cached_power' we have + // error_b = 0.5 (all cached powers have an error of less than 0.5 ulp), + // error_ab = 0 or 1 / kDenominator > error_a*error_b/ 2^64 + int error_b = kDenominator / 2; + int error_ab = (error == 0 ? 0 : 1); // We round up to 1. + int fixed_error = kDenominator / 2; + error += error_b + error_ab + fixed_error; + + old_e = input.e(); + input.Normalize(); + error <<= old_e - input.e(); + + // See if the double's significand changes if we add/subtract the error. + int order_of_magnitude = DiyFp::kSignificandSize + input.e(); + int effective_significand_size = + Double::SignificandSizeForOrderOfMagnitude(order_of_magnitude); + int precision_digits_count = + DiyFp::kSignificandSize - effective_significand_size; + if (precision_digits_count + kDenominatorLog >= DiyFp::kSignificandSize) { + // This can only happen for very small denormals. In this case the + // half-way multiplied by the denominator exceeds the range of an uint64. + // Simply shift everything to the right. + int shift_amount = (precision_digits_count + kDenominatorLog) - + DiyFp::kSignificandSize + 1; + input.set_f(input.f() >> shift_amount); + input.set_e(input.e() + shift_amount); + // We add 1 for the lost precision of error, and kDenominator for + // the lost precision of input.f(). + error = (error >> shift_amount) + 1 + kDenominator; + precision_digits_count -= shift_amount; + } + // We use uint64_ts now. This only works if the DiyFp uses uint64_ts too. + ASSERT(DiyFp::kSignificandSize == 64); + ASSERT(precision_digits_count < 64); + uint64_t one64 = 1; + uint64_t precision_bits_mask = (one64 << precision_digits_count) - 1; + uint64_t precision_bits = input.f() & precision_bits_mask; + uint64_t half_way = one64 << (precision_digits_count - 1); + precision_bits *= kDenominator; + half_way *= kDenominator; + DiyFp rounded_input(input.f() >> precision_digits_count, + input.e() + precision_digits_count); + if (precision_bits >= half_way + error) { + rounded_input.set_f(rounded_input.f() + 1); + } + // If the last_bits are too close to the half-way case than we are too + // inaccurate and round down. In this case we return false so that we can + // fall back to a more precise algorithm. + + *result = Double(rounded_input).value(); + if (half_way - error < precision_bits && precision_bits < half_way + error) { + // Too imprecise. The caller will have to fall back to a slower version. + // However the returned number is guaranteed to be either the correct + // double, or the next-lower double. + return false; + } else { + return true; + } +} + + +// Returns +// - -1 if buffer*10^exponent < diy_fp. +// - 0 if buffer*10^exponent == diy_fp. +// - +1 if buffer*10^exponent > diy_fp. +// Preconditions: +// buffer.length() + exponent <= kMaxDecimalPower + 1 +// buffer.length() + exponent > kMinDecimalPower +// buffer.length() <= kMaxDecimalSignificantDigits +static int CompareBufferWithDiyFp(Vector buffer, + int exponent, + DiyFp diy_fp) { + ASSERT(buffer.length() + exponent <= kMaxDecimalPower + 1); + ASSERT(buffer.length() + exponent > kMinDecimalPower); + ASSERT(buffer.length() <= kMaxSignificantDecimalDigits); + // Make sure that the Bignum will be able to hold all our numbers. + // Our Bignum implementation has a separate field for exponents. Shifts will + // consume at most one bigit (< 64 bits). + // ln(10) == 3.3219... + ASSERT(((kMaxDecimalPower + 1) * 333 / 100) < Bignum::kMaxSignificantBits); + Bignum buffer_bignum; + Bignum diy_fp_bignum; + buffer_bignum.AssignDecimalString(buffer); + diy_fp_bignum.AssignUInt64(diy_fp.f()); + if (exponent >= 0) { + buffer_bignum.MultiplyByPowerOfTen(exponent); + } else { + diy_fp_bignum.MultiplyByPowerOfTen(-exponent); + } + if (diy_fp.e() > 0) { + diy_fp_bignum.ShiftLeft(diy_fp.e()); + } else { + buffer_bignum.ShiftLeft(-diy_fp.e()); + } + return Bignum::Compare(buffer_bignum, diy_fp_bignum); +} + + +// Returns true if the guess is the correct double. +// Returns false, when guess is either correct or the next-lower double. +static bool ComputeGuess(Vector trimmed, int exponent, + double* guess) { + if (trimmed.length() == 0) { + *guess = 0.0; + return true; + } + if (exponent + trimmed.length() - 1 >= kMaxDecimalPower) { + *guess = Double::Infinity(); + return true; + } + if (exponent + trimmed.length() <= kMinDecimalPower) { + *guess = 0.0; + return true; + } + + if (DoubleStrtod(trimmed, exponent, guess) || + DiyFpStrtod(trimmed, exponent, guess)) { + return true; + } + if (*guess == Double::Infinity()) { + return true; + } + return false; +} + +double Strtod(Vector buffer, int exponent) { + char copy_buffer[kMaxSignificantDecimalDigits]; + Vector trimmed; + int updated_exponent; + TrimAndCut(buffer, exponent, copy_buffer, kMaxSignificantDecimalDigits, + &trimmed, &updated_exponent); + exponent = updated_exponent; + + double guess; + bool is_correct = ComputeGuess(trimmed, exponent, &guess); + if (is_correct) return guess; + + DiyFp upper_boundary = Double(guess).UpperBoundary(); + int comparison = CompareBufferWithDiyFp(trimmed, exponent, upper_boundary); + if (comparison < 0) { + return guess; + } else if (comparison > 0) { + return Double(guess).NextDouble(); + } else if ((Double(guess).Significand() & 1) == 0) { + // Round towards even. + return guess; + } else { + return Double(guess).NextDouble(); + } +} + +float Strtof(Vector buffer, int exponent) { + char copy_buffer[kMaxSignificantDecimalDigits]; + Vector trimmed; + int updated_exponent; + TrimAndCut(buffer, exponent, copy_buffer, kMaxSignificantDecimalDigits, + &trimmed, &updated_exponent); + exponent = updated_exponent; + + double double_guess; + bool is_correct = ComputeGuess(trimmed, exponent, &double_guess); + + float float_guess = static_cast(double_guess); + if (float_guess == double_guess) { + // This shortcut triggers for integer values. + return float_guess; + } + + // We must catch double-rounding. Say the double has been rounded up, and is + // now a boundary of a float, and rounds up again. This is why we have to + // look at previous too. + // Example (in decimal numbers): + // input: 12349 + // high-precision (4 digits): 1235 + // low-precision (3 digits): + // when read from input: 123 + // when rounded from high precision: 124. + // To do this we simply look at the neigbors of the correct result and see + // if they would round to the same float. If the guess is not correct we have + // to look at four values (since two different doubles could be the correct + // double). + + double double_next = Double(double_guess).NextDouble(); + double double_previous = Double(double_guess).PreviousDouble(); + + float f1 = static_cast(double_previous); + float f2 = float_guess; + float f3 = static_cast(double_next); + float f4; + if (is_correct) { + f4 = f3; + } else { + double double_next2 = Double(double_next).NextDouble(); + f4 = static_cast(double_next2); + } + (void) f2; // Mark variable as used. + ASSERT(f1 <= f2 && f2 <= f3 && f3 <= f4); + + // If the guess doesn't lie near a single-precision boundary we can simply + // return its float-value. + if (f1 == f4) { + return float_guess; + } + + ASSERT((f1 != f2 && f2 == f3 && f3 == f4) || + (f1 == f2 && f2 != f3 && f3 == f4) || + (f1 == f2 && f2 == f3 && f3 != f4)); + + // guess and next are the two possible canditates (in the same way that + // double_guess was the lower candidate for a double-precision guess). + float guess = f1; + float next = f4; + DiyFp upper_boundary; + if (guess == 0.0f) { + float min_float = 1e-45f; + upper_boundary = Double(static_cast(min_float) / 2).AsDiyFp(); + } else { + upper_boundary = Single(guess).UpperBoundary(); + } + int comparison = CompareBufferWithDiyFp(trimmed, exponent, upper_boundary); + if (comparison < 0) { + return guess; + } else if (comparison > 0) { + return next; + } else if ((Single(guess).Significand() & 1) == 0) { + // Round towards even. + return guess; + } else { + return next; + } +} + +} // namespace double_conversion + +// ICU PATCH: Close ICU namespace +U_NAMESPACE_END +#endif // ICU PATCH: close #if !UCONFIG_NO_FORMATTING diff --git a/deps/icu-small/source/i18n/double-conversion-strtod.h b/deps/icu-small/source/i18n/double-conversion-strtod.h new file mode 100644 index 00000000000..e2d6d3c2fe5 --- /dev/null +++ b/deps/icu-small/source/i18n/double-conversion-strtod.h @@ -0,0 +1,63 @@ +// © 2018 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html +// +// From the double-conversion library. Original license: +// +// Copyright 2010 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// ICU PATCH: ifdef around UCONFIG_NO_FORMATTING +#include "unicode/utypes.h" +#if !UCONFIG_NO_FORMATTING + +#ifndef DOUBLE_CONVERSION_STRTOD_H_ +#define DOUBLE_CONVERSION_STRTOD_H_ + +// ICU PATCH: Customize header file paths for ICU. + +#include "double-conversion-utils.h" + +// ICU PATCH: Wrap in ICU namespace +U_NAMESPACE_BEGIN + +namespace double_conversion { + +// The buffer must only contain digits in the range [0-9]. It must not +// contain a dot or a sign. It must not start with '0', and must not be empty. +double Strtod(Vector buffer, int exponent); + +// The buffer must only contain digits in the range [0-9]. It must not +// contain a dot or a sign. It must not start with '0', and must not be empty. +float Strtof(Vector buffer, int exponent); + +} // namespace double_conversion + +// ICU PATCH: Close ICU namespace +U_NAMESPACE_END + +#endif // DOUBLE_CONVERSION_STRTOD_H_ +#endif // ICU PATCH: close #if !UCONFIG_NO_FORMATTING diff --git a/deps/icu-small/source/i18n/double-conversion-utils.h b/deps/icu-small/source/i18n/double-conversion-utils.h index 02795b4bc56..57fc49b231a 100644 --- a/deps/icu-small/source/i18n/double-conversion-utils.h +++ b/deps/icu-small/source/i18n/double-conversion-utils.h @@ -75,9 +75,9 @@ inline void abort_noreturn() { abort(); } // the output of the division with the expected result. (Inlining must be // disabled.) // On Linux,x86 89255e-22 != Div_double(89255.0/1e22) -// ICU PATCH: Enable ARM builds for Windows with 'defined(_M_ARM)'. +// ICU PATCH: Enable ARM32 & ARM64 builds for Windows with 'defined(_M_ARM) || defined(_M_ARM64)'. #if defined(_M_X64) || defined(__x86_64__) || \ - defined(__ARMEL__) || defined(__avr32__) || defined(_M_ARM) || \ + defined(__ARMEL__) || defined(__avr32__) || defined(_M_ARM) || defined(_M_ARM64) || \ defined(__hppa__) || defined(__ia64__) || \ defined(__mips__) || \ defined(__powerpc__) || defined(__ppc__) || defined(__ppc64__) || \ diff --git a/deps/icu-small/source/i18n/double-conversion.cpp b/deps/icu-small/source/i18n/double-conversion.cpp index 8629284aa0e..570a05bc429 100644 --- a/deps/icu-small/source/i18n/double-conversion.cpp +++ b/deps/icu-small/source/i18n/double-conversion.cpp @@ -38,13 +38,14 @@ #include // ICU PATCH: Customize header file paths for ICU. -// The files fixed-dtoa.h and strtod.h are not needed. +// The file fixed-dtoa.h is not needed. #include "double-conversion.h" #include "double-conversion-bignum-dtoa.h" #include "double-conversion-fast-dtoa.h" #include "double-conversion-ieee.h" +#include "double-conversion-strtod.h" #include "double-conversion-utils.h" // ICU PATCH: Wrap in ICU namespace @@ -431,7 +432,6 @@ void DoubleToStringConverter::DoubleToAscii(double v, } -#if 0 // not needed for ICU // Consumes the given substring from the iterator. // Returns false, if the substring does not match. template @@ -469,6 +469,7 @@ static const uc16 kWhitespaceTable16[] = { static const int kWhitespaceTable16Length = ARRAY_SIZE(kWhitespaceTable16); + static bool isWhitespace(int x) { if (x < 128) { for (int i = 0; i < kWhitespaceTable7Length; i++) { @@ -647,7 +648,6 @@ static double RadixStringToIeee(Iterator* current, return Double(DiyFp(number, exponent)).value(); } - template double StringToDoubleConverter::StringToIeee( Iterator input, @@ -996,7 +996,6 @@ float StringToDoubleConverter::StringToFloat( return static_cast(StringToIeee(buffer, length, false, processed_characters_count)); } -#endif // not needed for ICU } // namespace double_conversion diff --git a/deps/icu-small/source/i18n/double-conversion.h b/deps/icu-small/source/i18n/double-conversion.h index 0939412734a..200537a360a 100644 --- a/deps/icu-small/source/i18n/double-conversion.h +++ b/deps/icu-small/source/i18n/double-conversion.h @@ -391,6 +391,7 @@ class DoubleToStringConverter { const int decimal_in_shortest_high_; const int max_leading_padding_zeroes_in_precision_mode_; const int max_trailing_padding_zeroes_in_precision_mode_; +#endif // not needed for ICU DISALLOW_IMPLICIT_CONSTRUCTORS(DoubleToStringConverter); }; @@ -554,7 +555,6 @@ class StringToDoubleConverter { int* processed_characters_count) const; DISALLOW_IMPLICIT_CONSTRUCTORS(StringToDoubleConverter); -#endif // not needed for ICU }; } // namespace double_conversion diff --git a/deps/icu-small/source/i18n/fmtable.cpp b/deps/icu-small/source/i18n/fmtable.cpp index 73f9b66ab6f..cb6134cb4b2 100644 --- a/deps/icu-small/source/i18n/fmtable.cpp +++ b/deps/icu-small/source/i18n/fmtable.cpp @@ -19,6 +19,7 @@ #if !UCONFIG_NO_FORMATTING +#include #include #include "unicode/fmtable.h" #include "unicode/ustring.h" @@ -28,9 +29,8 @@ #include "charstr.h" #include "cmemory.h" #include "cstring.h" -#include "decNumber.h" -#include "digitlst.h" #include "fmtableimp.h" +#include "number_decimalquantity.h" // ***************************************************************************** // class Formattable @@ -40,6 +40,8 @@ U_NAMESPACE_BEGIN UOBJECT_DEFINE_RTTI_IMPLEMENTATION(Formattable) +using number::impl::DecimalQuantity; + //-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. @@ -103,7 +105,7 @@ void Formattable::init() { fValue.fInt64 = 0; fType = kLong; fDecimalStr = NULL; - fDecimalNum = NULL; + fDecimalQuantity = NULL; fBogus.setToBogus(); } @@ -257,8 +259,8 @@ Formattable::operator=(const Formattable& source) } UErrorCode status = U_ZERO_ERROR; - if (source.fDecimalNum != NULL) { - fDecimalNum = new DigitList(*source.fDecimalNum); // TODO: use internal digit list + if (source.fDecimalQuantity != NULL) { + fDecimalQuantity = new DecimalQuantity(*source.fDecimalQuantity); } if (source.fDecimalStr != NULL) { fDecimalStr = new CharString(*source.fDecimalStr, status); @@ -357,13 +359,8 @@ void Formattable::dispose() delete fDecimalStr; fDecimalStr = NULL; - FmtStackData *stackData = (FmtStackData*)fStackData; - if(fDecimalNum != &(stackData->stackDecimalNum)) { - delete fDecimalNum; - } else { - fDecimalNum->~DigitList(); // destruct, don't deallocate - } - fDecimalNum = NULL; + delete fDecimalQuantity; + fDecimalQuantity = NULL; } Formattable * @@ -465,13 +462,13 @@ Formattable::getInt64(UErrorCode& status) const } else if (fValue.fDouble < (double)U_INT64_MIN) { status = U_INVALID_FORMAT_ERROR; return U_INT64_MIN; - } else if (fabs(fValue.fDouble) > U_DOUBLE_MAX_EXACT_INT && fDecimalNum != NULL) { - int64_t val = fDecimalNum->getInt64(); - if (val != 0) { - return val; + } else if (fabs(fValue.fDouble) > U_DOUBLE_MAX_EXACT_INT && fDecimalQuantity != NULL) { + if (fDecimalQuantity->fitsInLong(true)) { + return fDecimalQuantity->toLong(); } else { + // Unexpected status = U_INVALID_FORMAT_ERROR; - return fValue.fDouble > 0 ? U_INT64_MAX : U_INT64_MIN; + return fDecimalQuantity->isNegative() ? U_INT64_MIN : U_INT64_MAX; } } else { return (int64_t)fValue.fDouble; @@ -714,84 +711,85 @@ StringPiece Formattable::getDecimalNumber(UErrorCode &status) { CharString *Formattable::internalGetCharString(UErrorCode &status) { if(fDecimalStr == NULL) { - if (fDecimalNum == NULL) { + if (fDecimalQuantity == NULL) { // No decimal number for the formattable yet. Which means the value was // set directly by the user as an int, int64 or double. If the value came // from parsing, or from the user setting a decimal number, fDecimalNum // would already be set. // - fDecimalNum = new DigitList; // TODO: use internal digit list - if (fDecimalNum == NULL) { - status = U_MEMORY_ALLOCATION_ERROR; - return NULL; - } - - switch (fType) { - case kDouble: - fDecimalNum->set(this->getDouble()); - break; - case kLong: - fDecimalNum->set(this->getLong()); - break; - case kInt64: - fDecimalNum->set(this->getInt64()); - break; - default: - // The formattable's value is not a numeric type. - status = U_INVALID_STATE_ERROR; - return NULL; - } + LocalPointer dq(new DecimalQuantity(), status); + if (U_FAILURE(status)) { return nullptr; } + populateDecimalQuantity(*dq, status); + if (U_FAILURE(status)) { return nullptr; } + fDecimalQuantity = dq.orphan(); } - fDecimalStr = new CharString; + fDecimalStr = new CharString(); if (fDecimalStr == NULL) { status = U_MEMORY_ALLOCATION_ERROR; return NULL; } - fDecimalNum->getDecimal(*fDecimalStr, status); + // Older ICUs called uprv_decNumberToString here, which is not exactly the same as + // DecimalQuantity::toScientificString(). The biggest difference is that uprv_decNumberToString does + // not print scientific notation for magnitudes greater than -5 and smaller than some amount (+5?). + if (fDecimalQuantity->isZero()) { + fDecimalStr->append("0", -1, status); + } else if (std::abs(fDecimalQuantity->getMagnitude()) < 5) { + fDecimalStr->appendInvariantChars(fDecimalQuantity->toPlainString(), status); + } else { + fDecimalStr->appendInvariantChars(fDecimalQuantity->toScientificString(), status); + } } return fDecimalStr; } +void +Formattable::populateDecimalQuantity(number::impl::DecimalQuantity& output, UErrorCode& status) const { + if (fDecimalQuantity != nullptr) { + output = *fDecimalQuantity; + return; + } -DigitList * -Formattable::getInternalDigitList() { - FmtStackData *stackData = (FmtStackData*)fStackData; - if(fDecimalNum != &(stackData->stackDecimalNum)) { - delete fDecimalNum; - fDecimalNum = new (&(stackData->stackDecimalNum), kOnStack) DigitList(); - } else { - fDecimalNum->clear(); - } - return fDecimalNum; + switch (fType) { + case kDouble: + output.setToDouble(this->getDouble()); + output.roundToInfinity(); + break; + case kLong: + output.setToInt(this->getLong()); + break; + case kInt64: + output.setToLong(this->getInt64()); + break; + default: + // The formattable's value is not a numeric type. + status = U_INVALID_STATE_ERROR; + } } // --------------------------------------- void -Formattable::adoptDigitList(DigitList *dl) { - if(fDecimalNum==dl) { - fDecimalNum = NULL; // don't delete - } - dispose(); - - fDecimalNum = dl; - - if(dl==NULL) { // allow adoptDigitList(NULL) to clear - return; - } +Formattable::adoptDecimalQuantity(DecimalQuantity *dq) { + if (fDecimalQuantity != NULL) { + delete fDecimalQuantity; + } + fDecimalQuantity = dq; + if (dq == NULL) { // allow adoptDigitList(NULL) to clear + return; + } // Set the value into the Union of simple type values. - // Cannot use the set() functions because they would delete the fDecimalNum value, - - if (fDecimalNum->fitsIntoLong(FALSE)) { - fType = kLong; - fValue.fInt64 = fDecimalNum->getLong(); - } else if (fDecimalNum->fitsIntoInt64(FALSE)) { - fType = kInt64; - fValue.fInt64 = fDecimalNum->getInt64(); + // Cannot use the set() functions because they would delete the fDecimalNum value. + if (fDecimalQuantity->fitsInLong()) { + fValue.fInt64 = fDecimalQuantity->toLong(); + if (fValue.fInt64 <= INT32_MAX && fValue.fInt64 >= INT32_MIN) { + fType = kLong; + } else { + fType = kInt64; + } } else { fType = kDouble; - fValue.fDouble = fDecimalNum->getDouble(); + fValue.fDouble = fDecimalQuantity->toDouble(); } } @@ -804,24 +802,12 @@ Formattable::setDecimalNumber(StringPiece numberString, UErrorCode &status) { } dispose(); - // Copy the input string and nul-terminate it. - // The decNumber library requires nul-terminated input. StringPiece input - // is not guaranteed nul-terminated. Too bad. - // CharString automatically adds the nul. - DigitList *dnum = new DigitList(); // TODO: use getInternalDigitList - if (dnum == NULL) { - status = U_MEMORY_ALLOCATION_ERROR; - return; - } - dnum->set(CharString(numberString, status).toStringPiece(), status); - if (U_FAILURE(status)) { - delete dnum; - return; // String didn't contain a decimal number. - } - adoptDigitList(dnum); + auto* dq = new DecimalQuantity(); + dq->setToDecNumber(numberString, status); + adoptDecimalQuantity(dq); // Note that we do not hang on to the caller's input string. - // If we are asked for the string, we will regenerate one from fDecimalNum. + // If we are asked for the string, we will regenerate one from fDecimalQuantity. } #if 0 diff --git a/deps/icu-small/source/i18n/fmtableimp.h b/deps/icu-small/source/i18n/fmtableimp.h index 0e6ccd24da7..78b7caff548 100644 --- a/deps/icu-small/source/i18n/fmtableimp.h +++ b/deps/icu-small/source/i18n/fmtableimp.h @@ -10,22 +10,12 @@ #ifndef FMTABLEIMP_H #define FMTABLEIMP_H -#include "digitlst.h" +#include "number_decimalquantity.h" #if !UCONFIG_NO_FORMATTING U_NAMESPACE_BEGIN -/** - * @internal - */ -struct FmtStackData { - DigitList stackDecimalNum; // 128 - //CharString stackDecimalStr; // 64 - // ----- - // 192 total -}; - /** * Maximum int64_t value that can be stored in a double without chancing losing precision. * IEEE doubles have 53 bits of mantissa, 10 bits exponent, 1 bit sign. diff --git a/deps/icu-small/source/i18n/fphdlimp.cpp b/deps/icu-small/source/i18n/fphdlimp.cpp index abcec97ee31..c4015fae1bb 100644 --- a/deps/icu-small/source/i18n/fphdlimp.cpp +++ b/deps/icu-small/source/i18n/fphdlimp.cpp @@ -22,17 +22,8 @@ U_NAMESPACE_BEGIN FieldPositionHandler::~FieldPositionHandler() { } -void -FieldPositionHandler::addAttribute(int32_t, int32_t, int32_t) { -} - -void -FieldPositionHandler::shiftLast(int32_t) { -} - -UBool -FieldPositionHandler::isRecording(void) const { - return FALSE; +void FieldPositionHandler::setShift(int32_t delta) { + fShift = delta; } @@ -48,8 +39,8 @@ FieldPositionOnlyHandler::~FieldPositionOnlyHandler() { void FieldPositionOnlyHandler::addAttribute(int32_t id, int32_t start, int32_t limit) { if (pos.getField() == id) { - pos.setBeginIndex(start); - pos.setEndIndex(limit); + pos.setBeginIndex(start + fShift); + pos.setEndIndex(limit + fShift); } } @@ -91,8 +82,8 @@ FieldPositionIteratorHandler::addAttribute(int32_t id, int32_t start, int32_t li if (iter && U_SUCCESS(status) && start < limit) { int32_t size = vec->size(); vec->addElement(id, status); - vec->addElement(start, status); - vec->addElement(limit, status); + vec->addElement(start + fShift, status); + vec->addElement(limit + fShift, status); if (!U_SUCCESS(status)) { vec->setSize(size); } diff --git a/deps/icu-small/source/i18n/fphdlimp.h b/deps/icu-small/source/i18n/fphdlimp.h index f3ac12c2bac..2e9d5622b1b 100644 --- a/deps/icu-small/source/i18n/fphdlimp.h +++ b/deps/icu-small/source/i18n/fphdlimp.h @@ -22,11 +22,16 @@ U_NAMESPACE_BEGIN // base class, null implementation class U_I18N_API FieldPositionHandler: public UMemory { + protected: + int32_t fShift = 0; + public: virtual ~FieldPositionHandler(); - virtual void addAttribute(int32_t id, int32_t start, int32_t limit); - virtual void shiftLast(int32_t delta); - virtual UBool isRecording(void) const; + virtual void addAttribute(int32_t id, int32_t start, int32_t limit) = 0; + virtual void shiftLast(int32_t delta) = 0; + virtual UBool isRecording(void) const = 0; + + void setShift(int32_t delta); }; @@ -39,9 +44,9 @@ class FieldPositionOnlyHandler : public FieldPositionHandler { FieldPositionOnlyHandler(FieldPosition& pos); virtual ~FieldPositionOnlyHandler(); - virtual void addAttribute(int32_t id, int32_t start, int32_t limit); - virtual void shiftLast(int32_t delta); - virtual UBool isRecording(void) const; + void addAttribute(int32_t id, int32_t start, int32_t limit) U_OVERRIDE; + void shiftLast(int32_t delta) U_OVERRIDE; + UBool isRecording(void) const U_OVERRIDE; }; @@ -63,9 +68,9 @@ class FieldPositionIteratorHandler : public FieldPositionHandler { FieldPositionIteratorHandler(FieldPositionIterator* posIter, UErrorCode& status); ~FieldPositionIteratorHandler(); - virtual void addAttribute(int32_t id, int32_t start, int32_t limit); - virtual void shiftLast(int32_t delta); - virtual UBool isRecording(void) const; + void addAttribute(int32_t id, int32_t start, int32_t limit) U_OVERRIDE; + void shiftLast(int32_t delta) U_OVERRIDE; + UBool isRecording(void) const U_OVERRIDE; }; U_NAMESPACE_END diff --git a/deps/icu-small/source/i18n/measunit.cpp b/deps/icu-small/source/i18n/measunit.cpp index e21afcba029..dc156aa720a 100644 --- a/deps/icu-small/source/i18n/measunit.cpp +++ b/deps/icu-small/source/i18n/measunit.cpp @@ -41,21 +41,21 @@ static const int32_t gOffsets[] = { 16, 20, 24, - 285, - 295, - 306, - 310, - 316, - 320, - 340, - 341, + 321, + 331, + 342, + 346, 352, - 355, - 361, - 366, - 370, - 374, - 399 + 356, + 376, + 377, + 388, + 391, + 397, + 402, + 406, + 410, + 435 }; static const int32_t gIndexes[] = { @@ -136,15 +136,18 @@ static const char * const gSubTypes[] = { "AED", "AFA", "AFN", + "ALK", "ALL", "AMD", "ANG", "AOA", + "AOK", "AON", "AOR", "ARA", "ARP", "ARS", + "ARY", "ATS", "AUD", "AWG", @@ -158,6 +161,8 @@ static const char * const gSubTypes[] = { "BEC", "BEF", "BEL", + "BGJ", + "BGK", "BGL", "BGN", "BHD", @@ -165,7 +170,9 @@ static const char * const gSubTypes[] = { "BMD", "BND", "BOB", + "BOP", "BOV", + "BRB", "BRC", "BRE", "BRL", @@ -173,6 +180,7 @@ static const char * const gSubTypes[] = { "BRR", "BSD", "BTN", + "BUK", "BWP", "BYB", "BYN", @@ -191,6 +199,7 @@ static const char * const gSubTypes[] = { "COU", "CRC", "CSD", + "CSJ", "CSK", "CUC", "CUP", @@ -225,10 +234,13 @@ static const char * const gSubTypes[] = { "GHS", "GIP", "GMD", + "GNE", "GNF", + "GNS", "GQE", "GRD", "GTQ", + "GWE", "GWP", "GYD", "HKD", @@ -239,10 +251,13 @@ static const char * const gSubTypes[] = { "HUF", "IDR", "IEP", + "ILP", + "ILR", "ILS", "INR", "IQD", "IRR", + "ISJ", "ISK", "ITL", "JMD", @@ -257,11 +272,13 @@ static const char * const gSubTypes[] = { "KWD", "KYD", "KZT", + "LAJ", "LAK", "LBP", "LKR", "LRD", "LSL", + "LSM", "LTL", "LTT", "LUC", @@ -280,17 +297,23 @@ static const char * const gSubTypes[] = { "MNT", "MOP", "MRO", + "MRU", "MTL", + "MTP", "MUR", + "MVQ", "MVR", "MWK", "MXN", + "MXP", "MXV", "MYR", + "MZE", "MZM", "MZN", "NAD", "NGN", + "NIC", "NIO", "NLG", "NOK", @@ -298,6 +321,7 @@ static const char * const gSubTypes[] = { "NZD", "OMR", "PAB", + "PEH", "PEI", "PEN", "PES", @@ -309,6 +333,8 @@ static const char * const gSubTypes[] = { "PTE", "PYG", "QAR", + "RHD", + "ROK", "ROL", "RON", "RSD", @@ -320,6 +346,7 @@ static const char * const gSubTypes[] = { "SCR", "SDD", "SDG", + "SDP", "SEK", "SGD", "SHP", @@ -331,6 +358,8 @@ static const char * const gSubTypes[] = { "SRG", "SSP", "STD", + "STN", + "SUR", "SVC", "SYP", "SZL", @@ -349,15 +378,20 @@ static const char * const gSubTypes[] = { "TZS", "UAH", "UAK", + "UGS", + "UGW", "UGX", "USD", "USN", "USS", "UYI", + "UYN", + "UYP", "UYU", "UZS", "VEB", "VEF", + "VNC", "VND", "VUV", "WST", @@ -381,6 +415,7 @@ static const char * const gSubTypes[] = { "XXX", "YDD", "YER", + "YUD", "YUM", "YUN", "ZAL", @@ -389,6 +424,7 @@ static const char * const gSubTypes[] = { "ZMW", "ZRN", "ZRZ", + "ZWC", "ZWD", "ZWL", "ZWN", @@ -511,16 +547,20 @@ static const char * const gSubTypes[] = { // Must be sorted by first value and then second value. static int32_t unitPerUnitToSingleUnit[][4] = { - {327, 297, 17, 0}, - {329, 303, 17, 2}, - {331, 297, 17, 3}, - {331, 388, 4, 2}, - {331, 389, 4, 3}, - {346, 386, 3, 1}, - {349, 11, 16, 4}, - {391, 327, 4, 1} + {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} }; +// Shortcuts to the base unit in order to make the default constructor fast +static const int32_t kBaseTypeIdx = 14; +static const int32_t kBaseSubTypeIdx = 0; + MeasureUnit *MeasureUnit::createGForce(UErrorCode &status) { return MeasureUnit::create(0, 0, status); } @@ -1082,7 +1122,8 @@ static int32_t binarySearch( MeasureUnit::MeasureUnit() { fCurrency[0] = 0; - initNoUnit("base"); + fTypeId = kBaseTypeIdx; + fSubTypeId = kBaseSubTypeIdx; } MeasureUnit::MeasureUnit(const MeasureUnit &other) diff --git a/deps/icu-small/source/i18n/msgfmt.cpp b/deps/icu-small/source/i18n/msgfmt.cpp index 064585665ae..8b3807e6714 100644 --- a/deps/icu-small/source/i18n/msgfmt.cpp +++ b/deps/icu-small/source/i18n/msgfmt.cpp @@ -31,6 +31,7 @@ #include "unicode/decimfmt.h" #include "unicode/localpointer.h" #include "unicode/msgfmt.h" +#include "unicode/numberformatter.h" #include "unicode/plurfmt.h" #include "unicode/rbnf.h" #include "unicode/selfmt.h" @@ -48,7 +49,7 @@ #include "ustrfmt.h" #include "util.h" #include "uvector.h" -#include "visibledigits.h" +#include "number_decimalquantity.h" // ***************************************************************************** // class MessageFormat @@ -1700,12 +1701,21 @@ Format* MessageFormat::createAppropriateFormat(UnicodeString& type, UnicodeStrin formattableType = Formattable::kLong; fmt = createIntegerFormat(fLocale, ec); break; - default: // pattern - fmt = NumberFormat::createInstance(fLocale, ec); - if (fmt) { - DecimalFormat* decfmt = dynamic_cast(fmt); - if (decfmt != NULL) { - decfmt->applyPattern(style,parseError,ec); + default: // pattern or skeleton + int32_t i = 0; + for (; PatternProps::isWhiteSpace(style.charAt(i)); i++); + if (style.compare(i, 2, u"::", 0, 2) == 0) { + // Skeleton + UnicodeString skeleton = style.tempSubString(i + 2); + fmt = number::NumberFormatter::forSkeleton(skeleton, ec).locale(fLocale).toFormat(ec); + } else { + // Pattern + fmt = NumberFormat::createInstance(fLocale, ec); + if (fmt) { + auto* decfmt = dynamic_cast(fmt); + if (decfmt != nullptr) { + decfmt->applyPattern(style, parseError, ec); + } } } break; @@ -1959,14 +1969,14 @@ UnicodeString MessageFormat::PluralSelectorProvider::select(void *ctx, double nu return UnicodeString(FALSE, OTHER_STRING, 5); } context.formatter->format(context.number, context.numberString, ec); - const DecimalFormat *decFmt = dynamic_cast(context.formatter); + auto* decFmt = dynamic_cast(context.formatter); if(decFmt != NULL) { - VisibleDigitsWithExponent digits; - decFmt->initVisibleDigitsWithExponent(context.number, digits, ec); + number::impl::DecimalQuantity dq; + decFmt->formatToDecimalQuantity(context.number, dq, ec); if (U_FAILURE(ec)) { return UnicodeString(FALSE, OTHER_STRING, 5); } - return rules->select(digits); + return rules->select(dq); } else { return rules->select(number); } diff --git a/deps/icu-small/source/i18n/nfsubs.cpp b/deps/icu-small/source/i18n/nfsubs.cpp index ea817453d87..3733f0ca74d 100644 --- a/deps/icu-small/source/i18n/nfsubs.cpp +++ b/deps/icu-small/source/i18n/nfsubs.cpp @@ -19,8 +19,9 @@ #include "utypeinfo.h" // for 'typeid' to work #include "nfsubs.h" -#include "digitlst.h" #include "fmtableimp.h" +#include "putilimp.h" +#include "number_decimalquantity.h" #if U_HAVE_RBNF @@ -47,6 +48,8 @@ static const UChar gGreaterGreaterThan[] = U_NAMESPACE_BEGIN +using number::impl::DecimalQuantity; + class SameValueSubstitution : public NFSubstitution { public: SameValueSubstitution(int32_t pos, @@ -1069,13 +1072,12 @@ FractionalPartSubstitution::doSubstitution(double number, UnicodeString& toInser // numberToFormat /= 10; // } - DigitList dl; - dl.set(number); - dl.roundFixedPoint(20); // round to 20 fraction digits. - dl.reduce(); // Removes any trailing zeros. + DecimalQuantity dl; + dl.setToDouble(number); + dl.roundToMagnitude(-20, UNUM_ROUND_HALFEVEN, status); // round to 20 fraction digits. UBool pad = FALSE; - for (int32_t didx = dl.getCount()-1; didx>=dl.getDecimalAt(); didx--) { + for (int32_t didx = dl.getLowerDisplayMagnitude(); didx<0; didx++) { // Loop iterates over fraction digits, starting with the LSD. // include both real digits from the number, and zeros // to the left of the MSD but to the right of the decimal point. @@ -1084,7 +1086,7 @@ FractionalPartSubstitution::doSubstitution(double number, UnicodeString& toInser } else { pad = TRUE; } - int64_t digit = didx>=0 ? dl.getDigit(didx) - '0' : 0; + int64_t digit = dl.getDigit(didx); getRuleSet()->format(digit, toInsertInto, _pos + getPos(), recursionCount, status); } @@ -1142,7 +1144,8 @@ FractionalPartSubstitution::doParse(const UnicodeString& text, int32_t digit; // double p10 = 0.1; - DigitList dl; + DecimalQuantity dl; + int32_t totalDigits = 0; NumberFormat* fmt = NULL; while (workText.length() > 0 && workPos.getIndex() != 0) { workPos.setIndex(0); @@ -1170,7 +1173,8 @@ FractionalPartSubstitution::doParse(const UnicodeString& text, } if (workPos.getIndex() != 0) { - dl.append((char)('0' + digit)); + dl.appendDigit(static_cast(digit), 0, true); + totalDigits++; // result += digit * p10; // p10 /= 10; parsePosition.setIndex(parsePosition.getIndex() + workPos.getIndex()); @@ -1183,7 +1187,8 @@ FractionalPartSubstitution::doParse(const UnicodeString& text, } delete fmt; - result = dl.getCount() == 0 ? 0 : dl.getDouble(); + dl.adjustMagnitude(-totalDigits); + result = dl.toDouble(); result = composeRuleValue(result, baseValue); resVal.setDouble(result); return TRUE; diff --git a/deps/icu-small/source/i18n/number_affixutils.cpp b/deps/icu-small/source/i18n/number_affixutils.cpp index df4b267af5a..8da29a03d52 100644 --- a/deps/icu-small/source/i18n/number_affixutils.cpp +++ b/deps/icu-small/source/i18n/number_affixutils.cpp @@ -3,21 +3,25 @@ #include "unicode/utypes.h" -#if !UCONFIG_NO_FORMATTING && !UPRV_INCOMPLETE_CPP11_SUPPORT +#if !UCONFIG_NO_FORMATTING #include "number_affixutils.h" #include "unicode/utf16.h" +#include "unicode/uniset.h" using namespace icu; using namespace icu::number; using namespace icu::number::impl; -int32_t AffixUtils::estimateLength(const CharSequence &patternString, UErrorCode &status) { +TokenConsumer::~TokenConsumer() = default; +SymbolProvider::~SymbolProvider() = default; + +int32_t AffixUtils::estimateLength(const UnicodeString &patternString, UErrorCode &status) { AffixPatternState state = STATE_BASE; int32_t offset = 0; int32_t length = 0; for (; offset < patternString.length();) { - UChar32 cp = patternString.codePointAt(offset); + UChar32 cp = patternString.char32At(offset); switch (state) { case STATE_BASE: @@ -78,12 +82,12 @@ int32_t AffixUtils::estimateLength(const CharSequence &patternString, UErrorCode return length; } -UnicodeString AffixUtils::escape(const CharSequence &input) { +UnicodeString AffixUtils::escape(const UnicodeString &input) { AffixPatternState state = STATE_BASE; int32_t offset = 0; UnicodeString output; for (; offset < input.length();) { - UChar32 cp = input.codePointAt(offset); + UChar32 cp = input.char32At(offset); switch (cp) { case u'\'': @@ -153,7 +157,7 @@ Field AffixUtils::getFieldForType(AffixPatternType type) { } int32_t -AffixUtils::unescape(const CharSequence &affixPattern, NumberStringBuilder &output, int32_t position, +AffixUtils::unescape(const UnicodeString &affixPattern, NumberStringBuilder &output, int32_t position, const SymbolProvider &provider, UErrorCode &status) { int32_t length = 0; AffixTag tag; @@ -173,7 +177,7 @@ AffixUtils::unescape(const CharSequence &affixPattern, NumberStringBuilder &outp return length; } -int32_t AffixUtils::unescapedCodePointCount(const CharSequence &affixPattern, +int32_t AffixUtils::unescapedCodePointCount(const UnicodeString &affixPattern, const SymbolProvider &provider, UErrorCode &status) { int32_t length = 0; AffixTag tag; @@ -192,7 +196,7 @@ int32_t AffixUtils::unescapedCodePointCount(const CharSequence &affixPattern, } bool -AffixUtils::containsType(const CharSequence &affixPattern, AffixPatternType type, UErrorCode &status) { +AffixUtils::containsType(const UnicodeString &affixPattern, AffixPatternType type, UErrorCode &status) { if (affixPattern.length() == 0) { return false; } @@ -207,7 +211,7 @@ AffixUtils::containsType(const CharSequence &affixPattern, AffixPatternType type return false; } -bool AffixUtils::hasCurrencySymbols(const CharSequence &affixPattern, UErrorCode &status) { +bool AffixUtils::hasCurrencySymbols(const UnicodeString &affixPattern, UErrorCode &status) { if (affixPattern.length() == 0) { return false; } @@ -222,9 +226,9 @@ bool AffixUtils::hasCurrencySymbols(const CharSequence &affixPattern, UErrorCode return false; } -UnicodeString AffixUtils::replaceType(const CharSequence &affixPattern, AffixPatternType type, +UnicodeString AffixUtils::replaceType(const UnicodeString &affixPattern, AffixPatternType type, char16_t replacementChar, UErrorCode &status) { - UnicodeString output = affixPattern.toUnicodeString(); + UnicodeString output(affixPattern); // copy if (affixPattern.length() == 0) { return output; }; @@ -239,11 +243,41 @@ UnicodeString AffixUtils::replaceType(const CharSequence &affixPattern, AffixPat return output; } -AffixTag AffixUtils::nextToken(AffixTag tag, const CharSequence &patternString, UErrorCode &status) { +bool AffixUtils::containsOnlySymbolsAndIgnorables(const UnicodeString& affixPattern, + const UnicodeSet& ignorables, UErrorCode& status) { + if (affixPattern.length() == 0) { + return true; + }; + AffixTag tag; + while (hasNext(tag, affixPattern)) { + tag = nextToken(tag, affixPattern, status); + if (U_FAILURE(status)) { return false; } + if (tag.type == TYPE_CODEPOINT && !ignorables.contains(tag.codePoint)) { + return false; + } + } + return true; +} + +void AffixUtils::iterateWithConsumer(const UnicodeString& affixPattern, TokenConsumer& consumer, + UErrorCode& status) { + if (affixPattern.length() == 0) { + return; + }; + AffixTag tag; + while (hasNext(tag, affixPattern)) { + tag = nextToken(tag, affixPattern, status); + if (U_FAILURE(status)) { return; } + consumer.consumeToken(tag.type, tag.codePoint, status); + if (U_FAILURE(status)) { return; } + } +} + +AffixTag AffixUtils::nextToken(AffixTag tag, const UnicodeString &patternString, UErrorCode &status) { int32_t offset = tag.offset; int32_t state = tag.state; for (; offset < patternString.length();) { - UChar32 cp = patternString.codePointAt(offset); + UChar32 cp = patternString.char32At(offset); int32_t count = U16_LENGTH(cp); switch (state) { @@ -382,7 +416,7 @@ AffixTag AffixUtils::nextToken(AffixTag tag, const CharSequence &patternString, } } -bool AffixUtils::hasNext(const AffixTag &tag, const CharSequence &string) { +bool AffixUtils::hasNext(const AffixTag &tag, const UnicodeString &string) { // First check for the {-1} and default initializer syntax. if (tag.offset < 0) { return false; diff --git a/deps/icu-small/source/i18n/number_affixutils.h b/deps/icu-small/source/i18n/number_affixutils.h index fd76c99b975..1d7e1a115e0 100644 --- a/deps/icu-small/source/i18n/number_affixutils.h +++ b/deps/icu-small/source/i18n/number_affixutils.h @@ -3,7 +3,7 @@ #include "unicode/utypes.h" -#if !UCONFIG_NO_FORMATTING && !UPRV_INCOMPLETE_CPP11_SUPPORT +#if !UCONFIG_NO_FORMATTING #ifndef __NUMBER_AFFIXUTILS_H__ #define __NUMBER_AFFIXUTILS_H__ @@ -12,6 +12,7 @@ #include "unicode/stringpiece.h" #include "unicode/unistr.h" #include "number_stringbuilder.h" +#include "unicode/uniset.h" U_NAMESPACE_BEGIN namespace number { namespace impl { @@ -37,19 +38,27 @@ struct AffixTag { AffixPatternState state; AffixPatternType type; - AffixTag() : offset(0), state(STATE_BASE) {} + AffixTag() + : offset(0), state(STATE_BASE) {} - AffixTag(int32_t offset) : offset(offset) {} + AffixTag(int32_t offset) + : offset(offset) {} AffixTag(int32_t offset, UChar32 codePoint, AffixPatternState state, AffixPatternType type) - : offset(offset), codePoint(codePoint), state(state), type(type) - {} + : offset(offset), codePoint(codePoint), state(state), type(type) {} +}; + +class TokenConsumer { + public: + virtual ~TokenConsumer(); + + virtual void consumeToken(AffixPatternType type, UChar32 cp, UErrorCode& status) = 0; }; // Exported as U_I18N_API because it is a base class for other exported types class U_I18N_API SymbolProvider { public: - virtual ~SymbolProvider() = default; + virtual ~SymbolProvider(); // TODO: Could this be more efficient if it returned by reference? virtual UnicodeString getSymbol(AffixPatternType type) const = 0; @@ -107,7 +116,7 @@ class U_I18N_API AffixUtils { * @param patternString The original string whose width will be estimated. * @return The length of the unescaped string. */ - static int32_t estimateLength(const CharSequence &patternString, UErrorCode &status); + static int32_t estimateLength(const UnicodeString& patternString, UErrorCode& status); /** * Takes a string and escapes (quotes) characters that have special meaning in the affix pattern @@ -118,7 +127,7 @@ class U_I18N_API AffixUtils { * @param input The string to be escaped. * @return The resulting UnicodeString. */ - static UnicodeString escape(const CharSequence &input); + static UnicodeString escape(const UnicodeString& input); static Field getFieldForType(AffixPatternType type); @@ -134,9 +143,8 @@ class U_I18N_API AffixUtils { * @param position The index into the NumberStringBuilder to insert the string. * @param provider An object to generate locale symbols. */ - static int32_t - unescape(const CharSequence &affixPattern, NumberStringBuilder &output, int32_t position, - const SymbolProvider &provider, UErrorCode &status); + static int32_t unescape(const UnicodeString& affixPattern, NumberStringBuilder& output, + int32_t position, const SymbolProvider& provider, UErrorCode& status); /** * Sames as {@link #unescape}, but only calculates the code point count. More efficient than {@link #unescape} @@ -146,8 +154,8 @@ class U_I18N_API AffixUtils { * @param provider An object to generate locale symbols. * @return The same return value as if you called {@link #unescape}. */ - static int32_t unescapedCodePointCount(const CharSequence &affixPattern, - const SymbolProvider &provider, UErrorCode &status); + static int32_t unescapedCodePointCount(const UnicodeString& affixPattern, + const SymbolProvider& provider, UErrorCode& status); /** * Checks whether the given affix pattern contains at least one token of the given type, which is @@ -157,8 +165,7 @@ class U_I18N_API AffixUtils { * @param type The token type. * @return true if the affix pattern contains the given token type; false otherwise. */ - static bool - containsType(const CharSequence &affixPattern, AffixPatternType type, UErrorCode &status); + static bool containsType(const UnicodeString& affixPattern, AffixPatternType type, UErrorCode& status); /** * Checks whether the specified affix pattern has any unquoted currency symbols ("¤"). @@ -166,7 +173,7 @@ class U_I18N_API AffixUtils { * @param affixPattern The string to check for currency symbols. * @return true if the literal has at least one unquoted currency symbol; false otherwise. */ - static bool hasCurrencySymbols(const CharSequence &affixPattern, UErrorCode &status); + static bool hasCurrencySymbols(const UnicodeString& affixPattern, UErrorCode& status); /** * Replaces all occurrences of tokens with the given type with the given replacement char. @@ -176,9 +183,21 @@ class U_I18N_API AffixUtils { * @param replacementChar The char to substitute in place of chars of the given token type. * @return A string containing the new affix pattern. */ - static UnicodeString - replaceType(const CharSequence &affixPattern, AffixPatternType type, char16_t replacementChar, - UErrorCode &status); + static UnicodeString replaceType(const UnicodeString& affixPattern, AffixPatternType type, + char16_t replacementChar, UErrorCode& status); + + /** + * Returns whether the given affix pattern contains only symbols and ignorables as defined by the + * given ignorables set. + */ + static bool containsOnlySymbolsAndIgnorables(const UnicodeString& affixPattern, + const UnicodeSet& ignorables, UErrorCode& status); + + /** + * Iterates over the affix pattern, calling the TokenConsumer for each token. + */ + static void iterateWithConsumer(const UnicodeString& affixPattern, TokenConsumer& consumer, + UErrorCode& status); /** * Returns the next token from the affix pattern. @@ -190,7 +209,7 @@ class U_I18N_API AffixUtils { * (never negative), or -1 if there were no more tokens in the affix pattern. * @see #hasNext */ - static AffixTag nextToken(AffixTag tag, const CharSequence &patternString, UErrorCode &status); + static AffixTag nextToken(AffixTag tag, const UnicodeString& patternString, UErrorCode& status); /** * Returns whether the affix pattern string has any more tokens to be retrieved from a call to @@ -200,7 +219,7 @@ class U_I18N_API AffixUtils { * @param string The affix pattern. * @return true if there are more tokens to consume; false otherwise. */ - static bool hasNext(const AffixTag &tag, const CharSequence &string); + static bool hasNext(const AffixTag& tag, const UnicodeString& string); private: /** @@ -208,8 +227,8 @@ class U_I18N_API AffixUtils { * The order of the arguments is consistent with Java, but the order of the stored * fields is not necessarily the same. */ - static inline AffixTag - makeTag(int32_t offset, AffixPatternType type, AffixPatternState state, UChar32 cp) { + static inline AffixTag makeTag(int32_t offset, AffixPatternType type, AffixPatternState state, + UChar32 cp) { return {offset, cp, state, type}; } }; diff --git a/deps/icu-small/source/i18n/number_asformat.cpp b/deps/icu-small/source/i18n/number_asformat.cpp new file mode 100644 index 00000000000..c6bb538932c --- /dev/null +++ b/deps/icu-small/source/i18n/number_asformat.cpp @@ -0,0 +1,105 @@ +// © 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 +#include +#include "number_asformat.h" +#include "number_types.h" +#include "number_utils.h" +#include "fphdlimp.h" +#include "number_utypes.h" + +using namespace icu; +using namespace icu::number; +using namespace icu::number::impl; + +UOBJECT_DEFINE_RTTI_IMPLEMENTATION(LocalizedNumberFormatterAsFormat) + +LocalizedNumberFormatterAsFormat::LocalizedNumberFormatterAsFormat( + const LocalizedNumberFormatter& formatter, const Locale& locale) + : fFormatter(formatter), fLocale(locale) { + const char* localeName = locale.getName(); + setLocaleIDs(localeName, localeName); +} + +LocalizedNumberFormatterAsFormat::~LocalizedNumberFormatterAsFormat() = default; + +UBool LocalizedNumberFormatterAsFormat::operator==(const Format& other) const { + auto* _other = dynamic_cast(&other); + if (_other == nullptr) { + return false; + } + // TODO: Change this to use LocalizedNumberFormatter::operator== if it is ever proposed. + // This implementation is fine, but not particularly efficient. + UErrorCode localStatus = U_ZERO_ERROR; + return fFormatter.toSkeleton(localStatus) == _other->fFormatter.toSkeleton(localStatus); +} + +Format* LocalizedNumberFormatterAsFormat::clone() const { + return new LocalizedNumberFormatterAsFormat(*this); +} + +UnicodeString& LocalizedNumberFormatterAsFormat::format(const Formattable& obj, UnicodeString& appendTo, + FieldPosition& pos, UErrorCode& status) const { + if (U_FAILURE(status)) { return appendTo; } + UFormattedNumberData data; + obj.populateDecimalQuantity(data.quantity, status); + if (U_FAILURE(status)) { + return appendTo; + } + fFormatter.formatImpl(&data, status); + if (U_FAILURE(status)) { + return appendTo; + } + // always return first occurrence: + pos.setBeginIndex(0); + pos.setEndIndex(0); + bool found = data.string.nextFieldPosition(pos, status); + if (found && appendTo.length() != 0) { + pos.setBeginIndex(pos.getBeginIndex() + appendTo.length()); + pos.setEndIndex(pos.getEndIndex() + appendTo.length()); + } + appendTo.append(data.string.toTempUnicodeString()); + return appendTo; +} + +UnicodeString& LocalizedNumberFormatterAsFormat::format(const Formattable& obj, UnicodeString& appendTo, + FieldPositionIterator* posIter, + UErrorCode& status) const { + if (U_FAILURE(status)) { return appendTo; } + UFormattedNumberData data; + obj.populateDecimalQuantity(data.quantity, status); + if (U_FAILURE(status)) { + return appendTo; + } + fFormatter.formatImpl(&data, status); + if (U_FAILURE(status)) { + return appendTo; + } + appendTo.append(data.string.toTempUnicodeString()); + if (posIter != nullptr) { + FieldPositionIteratorHandler fpih(posIter, status); + data.string.getAllFieldPositions(fpih, status); + } + return appendTo; +} + +void LocalizedNumberFormatterAsFormat::parseObject(const UnicodeString&, Formattable&, + ParsePosition& parse_pos) const { + // Not supported. + parse_pos.setErrorIndex(0); +} + +const LocalizedNumberFormatter& LocalizedNumberFormatterAsFormat::getNumberFormatter() const { + return fFormatter; +} + +#endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/deps/icu-small/source/i18n/number_asformat.h b/deps/icu-small/source/i18n/number_asformat.h new file mode 100644 index 00000000000..bf82d72ae30 --- /dev/null +++ b/deps/icu-small/source/i18n/number_asformat.h @@ -0,0 +1,107 @@ +// © 2017 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 __NUMBER_ASFORMAT_H__ +#define __NUMBER_ASFORMAT_H__ + +#include "unicode/numberformatter.h" +#include "number_types.h" +#include "number_decimalquantity.h" +#include "number_scientific.h" +#include "number_patternstring.h" +#include "number_modifiers.h" +#include "number_multiplier.h" +#include "number_roundingutils.h" +#include "decNumber.h" +#include "charstr.h" + +U_NAMESPACE_BEGIN namespace number { +namespace impl { + +/** + * A wrapper around LocalizedNumberFormatter implementing the Format interface, enabling improved + * compatibility with other APIs. + * + * @draft ICU 62 + * @see NumberFormatter + */ +class U_I18N_API LocalizedNumberFormatterAsFormat : public Format { + public: + LocalizedNumberFormatterAsFormat(const LocalizedNumberFormatter& formatter, const Locale& locale); + + /** + * Destructor. + */ + ~LocalizedNumberFormatterAsFormat() U_OVERRIDE; + + /** + * Equals operator. + */ + UBool operator==(const Format& other) const U_OVERRIDE; + + /** + * Creates a copy of this object. + */ + Format* clone() const U_OVERRIDE; + + /** + * Formats a Number using the wrapped LocalizedNumberFormatter. The provided formattable must be a + * number type. + */ + UnicodeString& format(const Formattable& obj, UnicodeString& appendTo, FieldPosition& pos, + UErrorCode& status) const U_OVERRIDE; + + /** + * Formats a Number using the wrapped LocalizedNumberFormatter. The provided formattable must be a + * number type. + */ + UnicodeString& format(const Formattable& obj, UnicodeString& appendTo, FieldPositionIterator* posIter, + UErrorCode& status) const U_OVERRIDE; + + /** + * Not supported: sets an error index and returns. + */ + void parseObject(const UnicodeString& source, Formattable& result, + ParsePosition& parse_pos) const U_OVERRIDE; + + /** + * Gets the LocalizedNumberFormatter that this wrapper class uses to format numbers. + * + * For maximum efficiency, this function returns by const reference. You must copy the return value + * into a local variable if you want to use it beyond the lifetime of the current object: + * + *

+     * LocalizedNumberFormatter localFormatter = fmt->getNumberFormatter();
+     * 
+ * + * You can however use the return value directly when chaining: + * + *
+     * FormattedNumber result = fmt->getNumberFormatter().formatDouble(514.23, status);
+     * 
+ * + * @return The unwrapped LocalizedNumberFormatter. + */ + const LocalizedNumberFormatter& getNumberFormatter() const; + + UClassID getDynamicClassID() const U_OVERRIDE; + static UClassID U_EXPORT2 getStaticClassID(); + + private: + LocalizedNumberFormatter fFormatter; + + // Even though the locale is inside the LocalizedNumberFormatter, we have to keep it here, too, because + // LocalizedNumberFormatter doesn't have a getLocale() method, and ICU-TC didn't want to add one. + Locale fLocale; +}; + +} // namespace impl +} // namespace number +U_NAMESPACE_END + +#endif // __NUMBER_ASFORMAT_H__ + +#endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/deps/icu-small/source/i18n/number_capi.cpp b/deps/icu-small/source/i18n/number_capi.cpp new file mode 100644 index 00000000000..37ad8bd76fc --- /dev/null +++ b/deps/icu-small/source/i18n/number_capi.cpp @@ -0,0 +1,213 @@ +// © 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 "fphdlimp.h" +#include "number_utypes.h" +#include "numparse_types.h" +#include "unicode/numberformatter.h" +#include "unicode/unumberformatter.h" + +using namespace icu; +using namespace icu::number; +using namespace icu::number::impl; + + +////////////////////////////////// +/// C API CONVERSION FUNCTIONS /// +////////////////////////////////// + +UNumberFormatterData* UNumberFormatterData::validate(UNumberFormatter* input, UErrorCode& status) { + auto* constInput = static_cast(input); + auto* validated = validate(constInput, status); + return const_cast(validated); +} + +const UNumberFormatterData* +UNumberFormatterData::validate(const UNumberFormatter* input, UErrorCode& status) { + if (U_FAILURE(status)) { + return nullptr; + } + if (input == nullptr) { + status = U_ILLEGAL_ARGUMENT_ERROR; + return nullptr; + } + auto* impl = reinterpret_cast(input); + if (impl->fMagic != UNumberFormatterData::kMagic) { + status = U_INVALID_FORMAT_ERROR; + return nullptr; + } + return impl; +} + +UNumberFormatter* UNumberFormatterData::exportForC() { + return reinterpret_cast(this); +} + +UFormattedNumberData* UFormattedNumberData::validate(UFormattedNumber* input, UErrorCode& status) { + auto* constInput = static_cast(input); + auto* validated = validate(constInput, status); + return const_cast(validated); +} + +const UFormattedNumberData* +UFormattedNumberData::validate(const UFormattedNumber* input, UErrorCode& status) { + if (U_FAILURE(status)) { + return nullptr; + } + if (input == nullptr) { + status = U_ILLEGAL_ARGUMENT_ERROR; + return nullptr; + } + auto* impl = reinterpret_cast(input); + if (impl->fMagic != UFormattedNumberData::kMagic) { + status = U_INVALID_FORMAT_ERROR; + return nullptr; + } + return impl; +} + +UFormattedNumber* UFormattedNumberData::exportForC() { + return reinterpret_cast(this); +} + +///////////////////////////////////// +/// END CAPI CONVERSION FUNCTIONS /// +///////////////////////////////////// + + +U_CAPI UNumberFormatter* U_EXPORT2 +unumf_openForSkeletonAndLocale(const UChar* skeleton, int32_t skeletonLen, const char* locale, + UErrorCode* ec) { + auto* impl = new UNumberFormatterData(); + if (impl == nullptr) { + *ec = U_MEMORY_ALLOCATION_ERROR; + return nullptr; + } + // Readonly-alias constructor (first argument is whether we are NUL-terminated) + UnicodeString skeletonString(skeletonLen == -1, skeleton, skeletonLen); + impl->fFormatter = NumberFormatter::forSkeleton(skeletonString, *ec).locale(locale); + return impl->exportForC(); +} + +U_CAPI UFormattedNumber* U_EXPORT2 +unumf_openResult(UErrorCode* ec) { + auto* impl = new UFormattedNumberData(); + if (impl == nullptr) { + *ec = U_MEMORY_ALLOCATION_ERROR; + return nullptr; + } + return impl->exportForC(); +} + +U_CAPI void U_EXPORT2 +unumf_formatInt(const UNumberFormatter* uformatter, int64_t value, UFormattedNumber* uresult, + UErrorCode* ec) { + const UNumberFormatterData* formatter = UNumberFormatterData::validate(uformatter, *ec); + UFormattedNumberData* result = UFormattedNumberData::validate(uresult, *ec); + if (U_FAILURE(*ec)) { return; } + + result->string.clear(); + result->quantity.setToLong(value); + formatter->fFormatter.formatImpl(result, *ec); +} + +U_CAPI void U_EXPORT2 +unumf_formatDouble(const UNumberFormatter* uformatter, double value, UFormattedNumber* uresult, + UErrorCode* ec) { + const UNumberFormatterData* formatter = UNumberFormatterData::validate(uformatter, *ec); + UFormattedNumberData* result = UFormattedNumberData::validate(uresult, *ec); + if (U_FAILURE(*ec)) { return; } + + result->string.clear(); + result->quantity.setToDouble(value); + formatter->fFormatter.formatImpl(result, *ec); +} + +U_CAPI void U_EXPORT2 +unumf_formatDecimal(const UNumberFormatter* uformatter, const char* value, int32_t valueLen, + UFormattedNumber* uresult, UErrorCode* ec) { + const UNumberFormatterData* formatter = UNumberFormatterData::validate(uformatter, *ec); + UFormattedNumberData* result = UFormattedNumberData::validate(uresult, *ec); + if (U_FAILURE(*ec)) { return; } + + result->string.clear(); + result->quantity.setToDecNumber({value, valueLen}, *ec); + if (U_FAILURE(*ec)) { return; } + formatter->fFormatter.formatImpl(result, *ec); +} + +U_CAPI int32_t U_EXPORT2 +unumf_resultToString(const UFormattedNumber* uresult, UChar* buffer, int32_t bufferCapacity, + UErrorCode* ec) { + const UFormattedNumberData* result = UFormattedNumberData::validate(uresult, *ec); + if (U_FAILURE(*ec)) { return 0; } + + if (buffer == nullptr ? bufferCapacity != 0 : bufferCapacity < 0) { + *ec = U_ILLEGAL_ARGUMENT_ERROR; + return 0; + } + + return result->string.toTempUnicodeString().extract(buffer, bufferCapacity, *ec); +} + +U_CAPI UBool U_EXPORT2 +unumf_resultNextFieldPosition(const UFormattedNumber* uresult, UFieldPosition* ufpos, UErrorCode* ec) { + const UFormattedNumberData* result = UFormattedNumberData::validate(uresult, *ec); + if (U_FAILURE(*ec)) { return FALSE; } + + if (ufpos == nullptr) { + *ec = U_ILLEGAL_ARGUMENT_ERROR; + return FALSE; + } + + FieldPosition fp; + fp.setField(ufpos->field); + fp.setBeginIndex(ufpos->beginIndex); + fp.setEndIndex(ufpos->endIndex); + bool retval = result->string.nextFieldPosition(fp, *ec); + ufpos->beginIndex = fp.getBeginIndex(); + ufpos->endIndex = fp.getEndIndex(); + // NOTE: MSVC sometimes complains when implicitly converting between bool and UBool + return retval ? TRUE : FALSE; +} + +U_CAPI void U_EXPORT2 +unumf_resultGetAllFieldPositions(const UFormattedNumber* uresult, UFieldPositionIterator* ufpositer, + UErrorCode* ec) { + const UFormattedNumberData* result = UFormattedNumberData::validate(uresult, *ec); + if (U_FAILURE(*ec)) { return; } + + if (ufpositer == nullptr) { + *ec = U_ILLEGAL_ARGUMENT_ERROR; + return; + } + + auto* fpi = reinterpret_cast(ufpositer); + FieldPositionIteratorHandler fpih(fpi, *ec); + result->string.getAllFieldPositions(fpih, *ec); +} + +U_CAPI void U_EXPORT2 +unumf_closeResult(UFormattedNumber* uresult) { + UErrorCode localStatus = U_ZERO_ERROR; + const UFormattedNumberData* impl = UFormattedNumberData::validate(uresult, localStatus); + delete impl; +} + +U_CAPI void U_EXPORT2 +unumf_close(UNumberFormatter* f) { + UErrorCode localStatus = U_ZERO_ERROR; + const UNumberFormatterData* impl = UNumberFormatterData::validate(f, localStatus); + delete impl; +} + + +#endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/deps/icu-small/source/i18n/number_compact.cpp b/deps/icu-small/source/i18n/number_compact.cpp index cc0d8fd2a20..40278e1a012 100644 --- a/deps/icu-small/source/i18n/number_compact.cpp +++ b/deps/icu-small/source/i18n/number_compact.cpp @@ -3,14 +3,15 @@ #include "unicode/utypes.h" -#if !UCONFIG_NO_FORMATTING && !UPRV_INCOMPLETE_CPP11_SUPPORT +#if !UCONFIG_NO_FORMATTING -#include "resource.h" -#include "number_compact.h" #include "unicode/ustring.h" #include "unicode/ures.h" #include "cstring.h" #include "charstr.h" +#include "resource.h" +#include "number_compact.h" +#include "number_microprops.h" #include "uresimp.h" using namespace icu; @@ -275,15 +276,15 @@ void CompactHandler::processQuantity(DecimalQuantity &quantity, MicroProps &micr int magnitude; if (quantity.isZero()) { magnitude = 0; - micros.rounding.apply(quantity, status); + micros.rounder.apply(quantity, status); } else { // TODO: Revisit chooseMultiplierAndApply - int multiplier = micros.rounding.chooseMultiplierAndApply(quantity, data, status); + int multiplier = micros.rounder.chooseMultiplierAndApply(quantity, data, status); magnitude = quantity.isZero() ? 0 : quantity.getMagnitude(); magnitude -= multiplier; } - StandardPlural::Form plural = quantity.getStandardPlural(rules); + StandardPlural::Form plural = utils::getStandardPlural(rules, quantity); const UChar *patternString = data.getPattern(magnitude, plural); if (patternString == nullptr) { // Use the default (non-compact) modifier. @@ -313,7 +314,7 @@ void CompactHandler::processQuantity(DecimalQuantity &quantity, MicroProps &micr } // We already performed rounding. Do not perform it again. - micros.rounding = Rounder::constructPassThrough(); + micros.rounder = RoundingImpl::passThrough(); } #endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/deps/icu-small/source/i18n/number_compact.h b/deps/icu-small/source/i18n/number_compact.h index f7adf36416e..dda5f9f9b2d 100644 --- a/deps/icu-small/source/i18n/number_compact.h +++ b/deps/icu-small/source/i18n/number_compact.h @@ -3,7 +3,7 @@ #include "unicode/utypes.h" -#if !UCONFIG_NO_FORMATTING && !UPRV_INCOMPLETE_CPP11_SUPPORT +#if !UCONFIG_NO_FORMATTING #ifndef __NUMBER_COMPACT_H__ #define __NUMBER_COMPACT_H__ diff --git a/deps/icu-small/source/i18n/number_currencysymbols.cpp b/deps/icu-small/source/i18n/number_currencysymbols.cpp new file mode 100644 index 00000000000..0b79d6596f1 --- /dev/null +++ b/deps/icu-small/source/i18n/number_currencysymbols.cpp @@ -0,0 +1,123 @@ +// © 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 "numparse_types.h" +#include "number_currencysymbols.h" + +using namespace icu; +using namespace icu::number; +using namespace icu::number::impl; + + +CurrencySymbols::CurrencySymbols(CurrencyUnit currency, const Locale& locale, UErrorCode& status) + : fCurrency(currency), fLocaleName(locale.getName(), status) { + fCurrencySymbol.setToBogus(); + fIntlCurrencySymbol.setToBogus(); +} + +CurrencySymbols::CurrencySymbols(CurrencyUnit currency, const Locale& locale, + const DecimalFormatSymbols& symbols, UErrorCode& status) + : CurrencySymbols(currency, locale, status) { + // If either of the overrides is present, save it in the local UnicodeString. + if (symbols.isCustomCurrencySymbol()) { + fCurrencySymbol = symbols.getConstSymbol(DecimalFormatSymbols::kCurrencySymbol); + } + if (symbols.isCustomIntlCurrencySymbol()) { + fIntlCurrencySymbol = symbols.getConstSymbol(DecimalFormatSymbols::kIntlCurrencySymbol); + } +} + +const char16_t* CurrencySymbols::getIsoCode() const { + return fCurrency.getISOCurrency(); +} + +UnicodeString CurrencySymbols::getNarrowCurrencySymbol(UErrorCode& status) const { + // Note: currently no override is available for narrow currency symbol + return loadSymbol(UCURR_NARROW_SYMBOL_NAME, status); +} + +UnicodeString CurrencySymbols::getCurrencySymbol(UErrorCode& status) const { + if (!fCurrencySymbol.isBogus()) { + return fCurrencySymbol; + } + return loadSymbol(UCURR_SYMBOL_NAME, status); +} + +UnicodeString CurrencySymbols::loadSymbol(UCurrNameStyle selector, UErrorCode& status) const { + const char16_t* isoCode = fCurrency.getISOCurrency(); + UBool ignoredIsChoiceFormatFillIn = FALSE; + int32_t symbolLen = 0; + const char16_t* symbol = ucurr_getName( + isoCode, + fLocaleName.data(), + selector, + &ignoredIsChoiceFormatFillIn, + &symbolLen, + &status); + // If given an unknown currency, ucurr_getName returns the input string, which we can't alias safely! + // Otherwise, symbol points to a resource bundle, and we can use readonly-aliasing constructor. + if (symbol == isoCode) { + return UnicodeString(isoCode, 3); + } else { + return UnicodeString(TRUE, symbol, symbolLen); + } +} + +UnicodeString CurrencySymbols::getIntlCurrencySymbol(UErrorCode&) const { + if (!fIntlCurrencySymbol.isBogus()) { + return fIntlCurrencySymbol; + } + // Note: Not safe to use readonly-aliasing constructor here because the buffer belongs to this object, + // which could be destructed or moved during the lifetime of the return value. + return UnicodeString(fCurrency.getISOCurrency(), 3); +} + +UnicodeString CurrencySymbols::getPluralName(StandardPlural::Form plural, UErrorCode& status) const { + const char16_t* isoCode = fCurrency.getISOCurrency(); + UBool isChoiceFormat = FALSE; + int32_t symbolLen = 0; + const char16_t* symbol = ucurr_getPluralName( + isoCode, + fLocaleName.data(), + &isChoiceFormat, + StandardPlural::getKeyword(plural), + &symbolLen, + &status); + // If given an unknown currency, ucurr_getName returns the input string, which we can't alias safely! + // Otherwise, symbol points to a resource bundle, and we can use readonly-aliasing constructor. + if (symbol == isoCode) { + return UnicodeString(isoCode, 3); + } else { + return UnicodeString(TRUE, symbol, symbolLen); + } +} + + +CurrencyUnit +icu::number::impl::resolveCurrency(const DecimalFormatProperties& properties, const Locale& locale, + UErrorCode& status) { + if (!properties.currency.isNull()) { + return properties.currency.getNoError(); + } else { + UErrorCode localStatus = U_ZERO_ERROR; + char16_t buf[4] = {}; + ucurr_forLocale(locale.getName(), buf, 4, &localStatus); + if (U_SUCCESS(localStatus)) { + return CurrencyUnit(buf, status); + } else { + // Default currency (XXX) + return CurrencyUnit(); + } + } +} + + +#endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/deps/icu-small/source/i18n/number_currencysymbols.h b/deps/icu-small/source/i18n/number_currencysymbols.h new file mode 100644 index 00000000000..9996bf96ae0 --- /dev/null +++ b/deps/icu-small/source/i18n/number_currencysymbols.h @@ -0,0 +1,65 @@ +// © 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_NUMBER_CURRENCYSYMBOLS_H__ +#define __SOURCE_NUMBER_CURRENCYSYMBOLS_H__ + +#include "numparse_types.h" +#include "charstr.h" +#include "number_decimfmtprops.h" + +U_NAMESPACE_BEGIN namespace number { +namespace impl { + + +// Exported as U_I18N_API for tests +class U_I18N_API CurrencySymbols : public UMemory { + public: + CurrencySymbols() = default; // default constructor: leaves class in valid but undefined state + + /** Creates an instance in which all symbols are loaded from data. */ + CurrencySymbols(CurrencyUnit currency, const Locale& locale, UErrorCode& status); + + /** Creates an instance in which some symbols might be pre-populated. */ + CurrencySymbols(CurrencyUnit currency, const Locale& locale, const DecimalFormatSymbols& symbols, + UErrorCode& status); + + const char16_t* getIsoCode() const; + + UnicodeString getNarrowCurrencySymbol(UErrorCode& status) const; + + UnicodeString getCurrencySymbol(UErrorCode& status) const; + + UnicodeString getIntlCurrencySymbol(UErrorCode& status) const; + + UnicodeString getPluralName(StandardPlural::Form plural, UErrorCode& status) const; + + protected: + // Required fields: + CurrencyUnit fCurrency; + CharString fLocaleName; + + // Optional fields: + UnicodeString fCurrencySymbol; + UnicodeString fIntlCurrencySymbol; + + UnicodeString loadSymbol(UCurrNameStyle selector, UErrorCode& status) const; +}; + + +/** + * Resolves the effective currency from the property bag. + */ +CurrencyUnit +resolveCurrency(const DecimalFormatProperties& properties, const Locale& locale, UErrorCode& status); + + +} // namespace impl +} // namespace numparse +U_NAMESPACE_END + +#endif //__SOURCE_NUMBER_CURRENCYSYMBOLS_H__ +#endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/deps/icu-small/source/i18n/number_decimalquantity.cpp b/deps/icu-small/source/i18n/number_decimalquantity.cpp index b68df26ba26..9d80e3349cb 100644 --- a/deps/icu-small/source/i18n/number_decimalquantity.cpp +++ b/deps/icu-small/source/i18n/number_decimalquantity.cpp @@ -3,25 +3,30 @@ #include "unicode/utypes.h" -#if !UCONFIG_NO_FORMATTING && !UPRV_INCOMPLETE_CPP11_SUPPORT +#if !UCONFIG_NO_FORMATTING -#include "uassert.h" +#include #include -#include "cmemory.h" -#include "decNumber.h" #include +#include + +#include "unicode/plurrule.h" +#include "cmemory.h" +#include "number_decnum.h" +#include "putilimp.h" #include "number_decimalquantity.h" -#include "decContext.h" -#include "decNumber.h" #include "number_roundingutils.h" #include "double-conversion.h" -#include "unicode/plurrule.h" +#include "charstr.h" +#include "number_utils.h" +#include "uassert.h" using namespace icu; using namespace icu::number; using namespace icu::number::impl; using icu::double_conversion::DoubleToStringConverter; +using icu::double_conversion::StringToDoubleConverter; namespace { @@ -29,25 +34,6 @@ int8_t NEGATIVE_FLAG = 1; int8_t INFINITY_FLAG = 2; int8_t NAN_FLAG = 4; -static constexpr int32_t DEFAULT_DIGITS = 34; -typedef MaybeStackHeaderAndArray DecNumberWithStorage; - -/** Helper function to convert a decNumber-compatible string into a decNumber. */ -void stringToDecNumber(StringPiece n, DecNumberWithStorage &dn) { - decContext set; - uprv_decContextDefault(&set, DEC_INIT_BASE); - uprv_decContextSetRounding(&set, DEC_ROUND_HALF_EVEN); - set.traps = 0; // no traps, thank you - if (n.length() > DEFAULT_DIGITS) { - dn.resize(n.length(), 0); - set.digits = n.length(); - } else { - set.digits = DEFAULT_DIGITS; - } - uprv_decNumberFromString(dn.getAlias(), n.data(), &set); - U_ASSERT(DECDPUN == 1); -} - /** Helper function for safe subtraction (no overflow). */ inline int32_t safeSubtract(int32_t a, int32_t b) { // Note: In C++, signed integer subtraction is undefined behavior. @@ -83,6 +69,7 @@ static double DOUBLE_MULTIPLIERS[] = { } // namespace +icu::IFixedDecimal::~IFixedDecimal() = default; DecimalQuantity::DecimalQuantity() { setBcdToZero(); @@ -101,11 +88,30 @@ DecimalQuantity::DecimalQuantity(const DecimalQuantity &other) { *this = other; } +DecimalQuantity::DecimalQuantity(DecimalQuantity&& src) U_NOEXCEPT { + *this = std::move(src); +} + DecimalQuantity &DecimalQuantity::operator=(const DecimalQuantity &other) { if (this == &other) { return *this; } copyBcdFrom(other); + copyFieldsFrom(other); + return *this; +} + +DecimalQuantity& DecimalQuantity::operator=(DecimalQuantity&& src) U_NOEXCEPT { + if (this == &src) { + return *this; + } + moveBcdFrom(src); + copyFieldsFrom(src); + return *this; +} + +void DecimalQuantity::copyFieldsFrom(const DecimalQuantity& other) { + bogus = other.bogus; lOptPos = other.lOptPos; lReqPos = other.lReqPos; rReqPos = other.rReqPos; @@ -116,7 +122,6 @@ DecimalQuantity &DecimalQuantity::operator=(const DecimalQuantity &other) { origDouble = other.origDouble; origDelta = other.origDelta; isApproximate = other.isApproximate; - return *this; } void DecimalQuantity::clear() { @@ -129,10 +134,16 @@ void DecimalQuantity::clear() { } void DecimalQuantity::setIntegerLength(int32_t minInt, int32_t maxInt) { - // Validation should happen outside of DecimalQuantity, e.g., in the Rounder class. + // Validation should happen outside of DecimalQuantity, e.g., in the Precision class. U_ASSERT(minInt >= 0); U_ASSERT(maxInt >= minInt); + // Special behavior: do not set minInt to be less than what is already set. + // This is so significant digits rounding can set the integer length. + if (minInt < lReqPos) { + minInt = lReqPos; + } + // Save values into internal state // Negation is safe for minFrac/maxFrac because -Integer.MAX_VALUE > Integer.MIN_VALUE lOptPos = maxInt; @@ -140,7 +151,7 @@ void DecimalQuantity::setIntegerLength(int32_t minInt, int32_t maxInt) { } void DecimalQuantity::setFractionLength(int32_t minFrac, int32_t maxFrac) { - // Validation should happen outside of DecimalQuantity, e.g., in the Rounder class. + // Validation should happen outside of DecimalQuantity, e.g., in the Precision class. U_ASSERT(minFrac >= 0); U_ASSERT(maxFrac >= minFrac); @@ -160,29 +171,53 @@ uint64_t DecimalQuantity::getPositionFingerprint() const { } void DecimalQuantity::roundToIncrement(double roundingIncrement, RoundingMode roundingMode, - int32_t minMaxFrac, UErrorCode& status) { - // TODO: This is innefficient. Improve? - // TODO: Should we convert to decNumber instead? + int32_t maxFrac, UErrorCode& status) { + // TODO(13701): This is innefficient. Improve? + // TODO(13701): Should we convert to decNumber instead? + roundToInfinity(); double temp = toDouble(); temp /= roundingIncrement; - setToDouble(temp); - roundToMagnitude(0, roundingMode, status); - temp = toDouble(); + // Use another DecimalQuantity to perform the actual rounding... + DecimalQuantity dq; + dq.setToDouble(temp); + dq.roundToMagnitude(0, roundingMode, status); + temp = dq.toDouble(); temp *= roundingIncrement; setToDouble(temp); // Since we reset the value to a double, we need to specify the rounding boundary // in order to get the DecimalQuantity out of approximation mode. - roundToMagnitude(-minMaxFrac, roundingMode, status); + // NOTE: In Java, we have minMaxFrac, but in C++, the two are differentiated. + roundToMagnitude(-maxFrac, roundingMode, status); } -void DecimalQuantity::multiplyBy(int32_t multiplicand) { +void DecimalQuantity::multiplyBy(const DecNum& multiplicand, UErrorCode& status) { if (isInfinite() || isZero() || isNaN()) { return; } - // TODO: Should we convert to decNumber instead? - double temp = toDouble(); - temp *= multiplicand; - setToDouble(temp); + // Convert to DecNum, multiply, and convert back. + DecNum decnum; + toDecNum(decnum, status); + if (U_FAILURE(status)) { return; } + decnum.multiplyBy(multiplicand, status); + if (U_FAILURE(status)) { return; } + setToDecNum(decnum, status); +} + +void DecimalQuantity::divideBy(const DecNum& divisor, UErrorCode& status) { + if (isInfinite() || isZero() || isNaN()) { + return; + } + // Convert to DecNum, multiply, and convert back. + DecNum decnum; + toDecNum(decnum, status); + if (U_FAILURE(status)) { return; } + decnum.divideBy(divisor, status); + if (U_FAILURE(status)) { return; } + setToDecNum(decnum, status); +} + +void DecimalQuantity::negate() { + flags ^= NEGATIVE_FLAG; } int32_t DecimalQuantity::getMagnitude() const { @@ -190,21 +225,17 @@ int32_t DecimalQuantity::getMagnitude() const { return scale + precision - 1; } -void DecimalQuantity::adjustMagnitude(int32_t delta) { +bool DecimalQuantity::adjustMagnitude(int32_t delta) { if (precision != 0) { - scale += delta; - origDelta += delta; - } -} - -StandardPlural::Form DecimalQuantity::getStandardPlural(const PluralRules *rules) const { - if (rules == nullptr) { - // Fail gracefully if the user didn't provide a PluralRules - return StandardPlural::Form::OTHER; - } else { - UnicodeString ruleString = rules->select(*this); - return StandardPlural::orOtherFromString(ruleString); + // i.e., scale += delta; origDelta += delta + bool overflow = uprv_add32_overflow(scale, delta, &scale); + overflow = uprv_add32_overflow(origDelta, delta, &origDelta) || overflow; + // Make sure that precision + scale won't overflow, either + int32_t dummy; + overflow = overflow || uprv_add32_overflow(scale, precision, &dummy); + return overflow; } + return false; } double DecimalQuantity::getPluralOperand(PluralOperand operand) const { @@ -214,7 +245,8 @@ double DecimalQuantity::getPluralOperand(PluralOperand operand) const { switch (operand) { case PLURAL_OPERAND_I: - return static_cast(toLong()); + // Invert the negative sign if necessary + return static_cast(isNegative() ? -toLong(true) : toLong(true)); case PLURAL_OPERAND_F: return static_cast(toFractionLong(true)); case PLURAL_OPERAND_T: @@ -228,6 +260,10 @@ double DecimalQuantity::getPluralOperand(PluralOperand operand) const { } } +bool DecimalQuantity::hasIntegerValue() const { + return scale >= 0; +} + int32_t DecimalQuantity::getUpperDisplayMagnitude() const { // If this assertion fails, you need to call roundToInfinity() or some other rounding method. // See the comment in the header file explaining the "isApproximate" field. @@ -287,7 +323,10 @@ bool DecimalQuantity::isZero() const { DecimalQuantity &DecimalQuantity::setToInt(int32_t n) { setBcdToZero(); flags = 0; - if (n < 0) { + if (n == INT32_MIN) { + flags |= NEGATIVE_FLAG; + // leave as INT32_MIN; handled below in _setToInt() + } else if (n < 0) { flags |= NEGATIVE_FLAG; n = -n; } @@ -309,7 +348,7 @@ void DecimalQuantity::_setToInt(int32_t n) { DecimalQuantity &DecimalQuantity::setToLong(int64_t n) { setBcdToZero(); flags = 0; - if (n < 0) { + if (n < 0 && n > INT64_MIN) { flags |= NEGATIVE_FLAG; n = -n; } @@ -322,10 +361,12 @@ DecimalQuantity &DecimalQuantity::setToLong(int64_t n) { void DecimalQuantity::_setToLong(int64_t n) { if (n == INT64_MIN) { - static const char *int64minStr = "9.223372036854775808E+18"; - DecNumberWithStorage dn; - stringToDecNumber(int64minStr, dn); - readDecNumberToBcd(dn.getAlias()); + DecNum decnum; + UErrorCode localStatus = U_ZERO_ERROR; + decnum.setTo("9.223372036854775808E+18", localStatus); + if (U_FAILURE(localStatus)) { return; } // unexpected + flags |= NEGATIVE_FLAG; + readDecNumberToBcd(decnum); } else if (n <= INT32_MAX) { readIntToBcd(static_cast(n)); } else { @@ -337,7 +378,7 @@ DecimalQuantity &DecimalQuantity::setToDouble(double n) { setBcdToZero(); flags = 0; // signbit() from handles +0.0 vs -0.0 - if (std::signbit(n) != 0) { + if (std::signbit(n)) { flags |= NEGATIVE_FLAG; n = -n; } @@ -424,51 +465,107 @@ void DecimalQuantity::convertToAccurateDouble() { explicitExactDouble = true; } -DecimalQuantity &DecimalQuantity::setToDecNumber(StringPiece n) { +DecimalQuantity &DecimalQuantity::setToDecNumber(StringPiece n, UErrorCode& status) { setBcdToZero(); flags = 0; - DecNumberWithStorage dn; - stringToDecNumber(n, dn); + // Compute the decNumber representation + DecNum decnum; + decnum.setTo(n, status); - // The code path for decNumber is modeled after BigDecimal in Java. - if (decNumberIsNegative(dn.getAlias())) { - flags |= NEGATIVE_FLAG; - } - if (!decNumberIsZero(dn.getAlias())) { - _setToDecNumber(dn.getAlias()); - } + _setToDecNum(decnum, status); return *this; } -void DecimalQuantity::_setToDecNumber(decNumber *n) { - // Java fastpaths for ints here. In C++, just always read directly from the decNumber. - readDecNumberToBcd(n); - compact(); +DecimalQuantity& DecimalQuantity::setToDecNum(const DecNum& decnum, UErrorCode& status) { + setBcdToZero(); + flags = 0; + + _setToDecNum(decnum, status); + return *this; } -int64_t DecimalQuantity::toLong() const { - int64_t result = 0L; - for (int32_t magnitude = scale + precision - 1; magnitude >= 0; magnitude--) { +void DecimalQuantity::_setToDecNum(const DecNum& decnum, UErrorCode& status) { + if (U_FAILURE(status)) { return; } + if (decnum.isNegative()) { + flags |= NEGATIVE_FLAG; + } + if (!decnum.isZero()) { + readDecNumberToBcd(decnum); + compact(); + } +} + +int64_t DecimalQuantity::toLong(bool truncateIfOverflow) const { + // NOTE: Call sites should be guarded by fitsInLong(), like this: + // if (dq.fitsInLong()) { /* use dq.toLong() */ } else { /* use some fallback */ } + // Fallback behavior upon truncateIfOverflow is to truncate at 17 digits. + uint64_t result = 0L; + int32_t upperMagnitude = std::min(scale + precision, lOptPos) - 1; + if (truncateIfOverflow) { + upperMagnitude = std::min(upperMagnitude, 17); + } + for (int32_t magnitude = upperMagnitude; magnitude >= 0; magnitude--) { result = result * 10 + getDigitPos(magnitude - scale); } - return result; + if (isNegative()) { + return static_cast(0LL - result); // i.e., -result + } + return static_cast(result); } -int64_t DecimalQuantity::toFractionLong(bool includeTrailingZeros) const { - int64_t result = 0L; +uint64_t DecimalQuantity::toFractionLong(bool includeTrailingZeros) const { + uint64_t result = 0L; int32_t magnitude = -1; - for (; (magnitude >= scale || (includeTrailingZeros && magnitude >= rReqPos)) && - magnitude >= rOptPos; magnitude--) { + int32_t lowerMagnitude = std::max(scale, rOptPos); + if (includeTrailingZeros) { + lowerMagnitude = std::min(lowerMagnitude, rReqPos); + } + for (; magnitude >= lowerMagnitude && result <= 1e18L; magnitude--) { result = result * 10 + getDigitPos(magnitude - scale); } + // Remove trailing zeros; this can happen during integer overflow cases. + if (!includeTrailingZeros) { + while (result > 0 && (result % 10) == 0) { + result /= 10; + } + } return result; } +bool DecimalQuantity::fitsInLong(bool ignoreFraction) const { + if (isZero()) { + return true; + } + if (scale < 0 && !ignoreFraction) { + return false; + } + int magnitude = getMagnitude(); + if (magnitude < 18) { + return true; + } + if (magnitude > 18) { + return false; + } + // Hard case: the magnitude is 10^18. + // The largest int64 is: 9,223,372,036,854,775,807 + for (int p = 0; p < precision; p++) { + int8_t digit = getDigit(18 - p); + static int8_t INT64_BCD[] = { 9, 2, 2, 3, 3, 7, 2, 0, 3, 6, 8, 5, 4, 7, 7, 5, 8, 0, 8 }; + if (digit < INT64_BCD[p]) { + return true; + } else if (digit > INT64_BCD[p]) { + return false; + } + } + // Exactly equal to max long plus one. + return isNegative(); +} + double DecimalQuantity::toDouble() const { - if (isApproximate) { - return toDoubleFromOriginal(); - } + // If this assertion fails, you need to call roundToInfinity() or some other rounding method. + // See the comment in the header file explaining the "isApproximate" field. + U_ASSERT(!isApproximate); if (isNaN()) { return NAN; @@ -476,42 +573,37 @@ double DecimalQuantity::toDouble() const { return isNegative() ? -INFINITY : INFINITY; } - int64_t tempLong = 0L; - int32_t lostDigits = precision - (precision < 17 ? precision : 17); - for (int shift = precision - 1; shift >= lostDigits; shift--) { - tempLong = tempLong * 10 + getDigitPos(shift); - } - double result = static_cast(tempLong); - int32_t _scale = scale + lostDigits; - if (_scale >= 0) { - // 1e22 is the largest exact double. - int32_t i = _scale; - for (; i >= 22; i -= 22) result *= 1e22; - result *= DOUBLE_MULTIPLIERS[i]; - } else { - // 1e22 is the largest exact double. - int32_t i = _scale; - for (; i <= -22; i += 22) result /= 1e22; - result /= DOUBLE_MULTIPLIERS[-i]; - } - if (isNegative()) { result = -result; } - return result; + // We are processing well-formed input, so we don't need any special options to StringToDoubleConverter. + StringToDoubleConverter converter(0, 0, 0, "", ""); + UnicodeString numberString = this->toScientificString(); + int32_t count; + return converter.StringToDouble( + reinterpret_cast(numberString.getBuffer()), + numberString.length(), + &count); } -double DecimalQuantity::toDoubleFromOriginal() const { - double result = origDouble; - int32_t delta = origDelta; - if (delta >= 0) { - // 1e22 is the largest exact double. - for (; delta >= 22; delta -= 22) result *= 1e22; - result *= DOUBLE_MULTIPLIERS[delta]; - } else { - // 1e22 is the largest exact double. - for (; delta <= -22; delta += 22) result /= 1e22; - result /= DOUBLE_MULTIPLIERS[-delta]; +void DecimalQuantity::toDecNum(DecNum& output, UErrorCode& status) const { + // Special handling for zero + if (precision == 0) { + output.setTo("0", status); + } + + // Use the BCD constructor. We need to do a little bit of work to convert, though. + // The decNumber constructor expects most-significant first, but we store least-significant first. + MaybeStackArray ubcd(precision); + for (int32_t m = 0; m < precision; m++) { + ubcd[precision - m - 1] = static_cast(getDigitPos(m)); + } + output.setTo(ubcd.getAlias(), precision, scale, isNegative(), status); +} + +void DecimalQuantity::truncate() { + if (scale < 0) { + shiftRight(-scale); + scale = 0; + compact(); } - if (isNegative()) { result *= -1; } - return result; } void DecimalQuantity::roundToMagnitude(int32_t magnitude, RoundingMode roundingMode, UErrorCode& status) { @@ -689,17 +781,63 @@ void DecimalQuantity::appendDigit(int8_t value, int32_t leadingZeros, bool appen } UnicodeString DecimalQuantity::toPlainString() const { + U_ASSERT(!isApproximate); UnicodeString sb; if (isNegative()) { sb.append(u'-'); } + if (precision == 0 || getMagnitude() < 0) { + sb.append(u'0'); + } for (int m = getUpperDisplayMagnitude(); m >= getLowerDisplayMagnitude(); m--) { + if (m == -1) { sb.append(u'.'); } sb.append(getDigit(m) + u'0'); - if (m == 0) { sb.append(u'.'); } } return sb; } +UnicodeString DecimalQuantity::toScientificString() const { + U_ASSERT(!isApproximate); + UnicodeString result; + if (isNegative()) { + result.append(u'-'); + } + if (precision == 0) { + result.append(u"0E+0", -1); + return result; + } + // NOTE: It is not safe to add to lOptPos (aka maxInt) or subtract from + // rOptPos (aka -maxFrac) due to overflow. + int32_t upperPos = std::min(precision + scale, lOptPos) - scale - 1; + int32_t lowerPos = std::max(scale, rOptPos) - scale; + int32_t p = upperPos; + result.append(u'0' + getDigitPos(p)); + if ((--p) >= lowerPos) { + result.append(u'.'); + for (; p >= lowerPos; p--) { + result.append(u'0' + getDigitPos(p)); + } + } + result.append(u'E'); + int32_t _scale = upperPos + scale; + if (_scale < 0) { + _scale *= -1; + result.append(u'-'); + } else { + result.append(u'+'); + } + if (_scale == 0) { + result.append(u'0'); + } + int32_t insertIndex = result.length(); + while (_scale > 0) { + std::div_t res = std::div(_scale, 10); + result.insert(insertIndex, u'0' + res.rem); + _scale = res.quot; + } + return result; +} + //////////////////////////////////////////////////// /// End of DecimalQuantity_AbstractBCD.java /// /// Start of DecimalQuantity_DualStorageBCD.java /// @@ -707,7 +845,7 @@ UnicodeString DecimalQuantity::toPlainString() const { int8_t DecimalQuantity::getDigitPos(int32_t position) const { if (usingBytes) { - if (position < 0 || position > precision) { return 0; } + if (position < 0 || position >= precision) { return 0; } return fBCD.bcdBytes.ptr[position]; } else { if (position < 0 || position >= 16) { return 0; } @@ -819,7 +957,8 @@ void DecimalQuantity::readLongToBcd(int64_t n) { } } -void DecimalQuantity::readDecNumberToBcd(decNumber *dn) { +void DecimalQuantity::readDecNumberToBcd(const DecNum& decnum) { + const decNumber* dn = decnum.getRawDecNumber(); if (dn->digits > 16) { ensureCapacity(dn->digits); for (int32_t i = 0; i < dn->digits; i++) { @@ -919,7 +1058,7 @@ void DecimalQuantity::ensureCapacity(int32_t capacity) { auto bcd1 = static_cast(uprv_malloc(capacity * 2 * sizeof(int8_t))); uprv_memcpy(bcd1, fBCD.bcdBytes.ptr, oldCapacity * sizeof(int8_t)); // Initialize the rest of the byte array to zeros (this is done automatically in Java) - uprv_memset(fBCD.bcdBytes.ptr + oldCapacity, 0, (capacity - oldCapacity) * sizeof(int8_t)); + uprv_memset(bcd1 + oldCapacity, 0, (capacity - oldCapacity) * sizeof(int8_t)); uprv_free(fBCD.bcdBytes.ptr); fBCD.bcdBytes.ptr = bcd1; fBCD.bcdBytes.len = capacity * 2; @@ -962,6 +1101,20 @@ void DecimalQuantity::copyBcdFrom(const DecimalQuantity &other) { } } +void DecimalQuantity::moveBcdFrom(DecimalQuantity &other) { + setBcdToZero(); + if (other.usingBytes) { + usingBytes = true; + fBCD.bcdBytes.ptr = other.fBCD.bcdBytes.ptr; + fBCD.bcdBytes.len = other.fBCD.bcdBytes.len; + // Take ownership away from the old instance: + other.fBCD.bcdBytes.ptr = nullptr; + other.usingBytes = false; + } else { + fBCD.bcdLong = other.fBCD.bcdLong; + } +} + const char16_t* DecimalQuantity::checkHealth() const { if (usingBytes) { if (precision == 0) { return u"Zero precision but we are in byte mode"; } @@ -1000,6 +1153,11 @@ const char16_t* DecimalQuantity::checkHealth() const { return nullptr; } +bool DecimalQuantity::operator==(const DecimalQuantity& other) const { + // FIXME: Make a faster implementation. + return toString() == other.toString(); +} + UnicodeString DecimalQuantity::toString() const { MaybeStackArray digits(precision + 1); for (int32_t i = 0; i < precision; i++) { @@ -1010,25 +1168,17 @@ UnicodeString DecimalQuantity::toString() const { snprintf( buffer8, sizeof(buffer8), - "", + "", (lOptPos > 999 ? 999 : lOptPos), lReqPos, rReqPos, (rOptPos < -999 ? -999 : rOptPos), (usingBytes ? "bytes" : "long"), + (isNegative() ? "-" : ""), (precision == 0 ? "0" : digits.getAlias()), "E", scale); return UnicodeString(buffer8, -1, US_INV); } -UnicodeString DecimalQuantity::toNumberString() const { - MaybeStackArray digits(precision + 11); - for (int32_t i = 0; i < precision; i++) { - digits[i] = getDigitPos(precision - i - 1) + '0'; - } - snprintf(digits.getAlias() + precision, 11, "E%d", scale); - return UnicodeString(digits.getAlias(), -1, US_INV); -} - #endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/deps/icu-small/source/i18n/number_decimalquantity.h b/deps/icu-small/source/i18n/number_decimalquantity.h index 4309c3c6380..8e04dea7eb5 100644 --- a/deps/icu-small/source/i18n/number_decimalquantity.h +++ b/deps/icu-small/source/i18n/number_decimalquantity.h @@ -3,13 +3,12 @@ #include "unicode/utypes.h" -#if !UCONFIG_NO_FORMATTING && !UPRV_INCOMPLETE_CPP11_SUPPORT +#if !UCONFIG_NO_FORMATTING #ifndef __NUMBER_DECIMALQUANTITY_H__ #define __NUMBER_DECIMALQUANTITY_H__ #include #include "unicode/umachine.h" -#include "decNumber.h" #include "standardplural.h" #include "plurrule_impl.h" #include "number_types.h" @@ -17,6 +16,9 @@ U_NAMESPACE_BEGIN namespace number { namespace impl { +// Forward-declare (maybe don't want number_utils.h included here): +class DecNum; + /** * An class for representing a number to be processed by the decimal formatting pipeline. Includes * methods for rounding, plural rules, and decimal digit extraction. @@ -33,9 +35,12 @@ class U_I18N_API DecimalQuantity : public IFixedDecimal, public UMemory { /** Copy constructor. */ DecimalQuantity(const DecimalQuantity &other); + /** Move constructor. */ + DecimalQuantity(DecimalQuantity &&src) U_NOEXCEPT; + DecimalQuantity(); - ~DecimalQuantity(); + ~DecimalQuantity() override; /** * Sets this instance to be equal to another instance. @@ -44,6 +49,9 @@ class U_I18N_API DecimalQuantity : public IFixedDecimal, public UMemory { */ DecimalQuantity &operator=(const DecimalQuantity &other); + /** Move assignment */ + DecimalQuantity &operator=(DecimalQuantity&& src) U_NOEXCEPT; + /** * Sets the minimum and maximum integer digits that this {@link DecimalQuantity} should generate. * This method does not perform rounding. @@ -71,7 +79,10 @@ class U_I18N_API DecimalQuantity : public IFixedDecimal, public UMemory { * @param mathContext The {@link RoundingMode} to use if rounding is necessary. */ void roundToIncrement(double roundingIncrement, RoundingMode roundingMode, - int32_t minMaxFrac, UErrorCode& status); + int32_t maxFrac, UErrorCode& status); + + /** Removes all fraction digits. */ + void truncate(); /** * Rounds the number to a specified magnitude (power of ten). @@ -89,19 +100,30 @@ class U_I18N_API DecimalQuantity : public IFixedDecimal, public UMemory { void roundToInfinity(); /** - * Multiply the internal value. + * Multiply the internal value. Uses decNumber. * * @param multiplicand The value by which to multiply. */ - void multiplyBy(int32_t multiplicand); + void multiplyBy(const DecNum& multiplicand, UErrorCode& status); + + /** + * Divide the internal value. Uses decNumber. + * + * @param multiplicand The value by which to multiply. + */ + void divideBy(const DecNum& divisor, UErrorCode& status); + + /** Flips the sign from positive to negative and back. */ + void negate(); /** * Scales the number by a power of ten. For example, if the value is currently "1234.56", calling * this method with delta=-3 will change the value to "1.23456". * * @param delta The number of magnitudes of ten to change by. + * @return true if integer overflow occured; false otherwise. */ - void adjustMagnitude(int32_t delta); + bool adjustMagnitude(int32_t delta); /** * @return The power of ten corresponding to the most significant nonzero digit. @@ -124,13 +146,23 @@ class U_I18N_API DecimalQuantity : public IFixedDecimal, public UMemory { /** @return Whether the value represented by this {@link DecimalQuantity} is not a number. */ bool isNaN() const U_OVERRIDE; - int64_t toLong() const; + /** @param truncateIfOverflow if false and the number does NOT fit, fails with an assertion error. */ + int64_t toLong(bool truncateIfOverflow = false) const; - int64_t toFractionLong(bool includeTrailingZeros) const; + uint64_t toFractionLong(bool includeTrailingZeros) const; + + /** + * Returns whether or not a Long can fully represent the value stored in this DecimalQuantity. + * @param ignoreFraction if true, silently ignore digits after the decimal place. + */ + bool fitsInLong(bool ignoreFraction = false) const; /** @return The value contained in this {@link DecimalQuantity} approximated as a double. */ double toDouble() const; + /** Computes a DecNum representation of this DecimalQuantity, saving it to the output parameter. */ + void toDecNum(DecNum& output, UErrorCode& status) const; + DecimalQuantity &setToInt(int32_t n); DecimalQuantity &setToLong(int64_t n); @@ -138,8 +170,10 @@ class U_I18N_API DecimalQuantity : public IFixedDecimal, public UMemory { DecimalQuantity &setToDouble(double n); /** decNumber is similar to BigDecimal in Java. */ + DecimalQuantity &setToDecNumber(StringPiece n, UErrorCode& status); - DecimalQuantity &setToDecNumber(StringPiece n); + /** Internal method if the caller already has a DecNum. */ + DecimalQuantity &setToDecNum(const DecNum& n, UErrorCode& status); /** * Appends a digit, optionally with one or more leading zeros, to the end of the value represented @@ -160,17 +194,10 @@ class U_I18N_API DecimalQuantity : public IFixedDecimal, public UMemory { */ void appendDigit(int8_t value, int32_t leadingZeros, bool appendAsInteger); - /** - * Computes the plural form for this number based on the specified set of rules. - * - * @param rules A {@link PluralRules} object representing the set of rules. - * @return The {@link StandardPlural} according to the PluralRules. If the plural form is not in - * the set of standard plurals, {@link StandardPlural#OTHER} is returned instead. - */ - StandardPlural::Form getStandardPlural(const PluralRules *rules) const; - double getPluralOperand(PluralOperand operand) const U_OVERRIDE; + bool hasIntegerValue() const U_OVERRIDE; + /** * Gets the digit at the specified magnitude. For example, if the represented number is 12.3, * getDigit(-1) returns 3, since 3 is the digit corresponding to 10^-1. @@ -223,10 +250,10 @@ class U_I18N_API DecimalQuantity : public IFixedDecimal, public UMemory { UnicodeString toString() const; - /* Returns the string in exponential notation. */ - UnicodeString toNumberString() const; + /** Returns the string in standard exponential notation. */ + UnicodeString toScientificString() const; - /* Returns the string without exponential notation. Slightly slower than toNumberString(). */ + /** Returns the string without exponential notation. Slightly slower than toScientificString(). */ UnicodeString toPlainString() const; /** Visible for testing */ @@ -235,6 +262,17 @@ class U_I18N_API DecimalQuantity : public IFixedDecimal, public UMemory { /** Visible for testing */ inline bool isExplicitExactDouble() { return explicitExactDouble; }; + bool operator==(const DecimalQuantity& other) const; + + inline bool operator!=(const DecimalQuantity& other) const { + return !(*this == other); + } + + /** + * Bogus flag for when a DecimalQuantity is stored on the stack. + */ + bool bogus = false; + private: /** * The power of ten corresponding to the least significant digit in the BCD. For example, if this @@ -396,12 +434,16 @@ class U_I18N_API DecimalQuantity : public IFixedDecimal, public UMemory { */ void readLongToBcd(int64_t n); - void readDecNumberToBcd(decNumber *dn); + void readDecNumberToBcd(const DecNum& dn); void readDoubleConversionToBcd(const char* buffer, int32_t length, int32_t point); + void copyFieldsFrom(const DecimalQuantity& other); + void copyBcdFrom(const DecimalQuantity &other); + void moveBcdFrom(DecimalQuantity& src); + /** * Removes trailing zeros from the BCD (adjusting the scale as required) and then computes the * precision. The precision is the number of digits in the number up through the greatest nonzero @@ -418,12 +460,10 @@ class U_I18N_API DecimalQuantity : public IFixedDecimal, public UMemory { void _setToDoubleFast(double n); - void _setToDecNumber(decNumber *n); + void _setToDecNum(const DecNum& dn, UErrorCode& status); void convertToAccurateDouble(); - double toDoubleFromOriginal() const; - /** Ensure that a byte array of at least 40 digits is allocated. */ void ensureCapacity(); diff --git a/deps/icu-small/source/i18n/number_decimfmtprops.cpp b/deps/icu-small/source/i18n/number_decimfmtprops.cpp index cc57cfce6ac..6754fe19eca 100644 --- a/deps/icu-small/source/i18n/number_decimfmtprops.cpp +++ b/deps/icu-small/source/i18n/number_decimfmtprops.cpp @@ -3,14 +3,29 @@ #include "unicode/utypes.h" -#if !UCONFIG_NO_FORMATTING && !UPRV_INCOMPLETE_CPP11_SUPPORT +#if !UCONFIG_NO_FORMATTING #include "number_decimfmtprops.h" +#include "umutex.h" using namespace icu; using namespace icu::number; using namespace icu::number::impl; + +namespace { + +char kRawDefaultProperties[sizeof(DecimalFormatProperties)]; + +icu::UInitOnce gDefaultPropertiesInitOnce = U_INITONCE_INITIALIZER; + +void U_CALLCONV initDefaultProperties(UErrorCode&) { + new(kRawDefaultProperties) DecimalFormatProperties(); // set to the default instance +} + +} + + DecimalFormatProperties::DecimalFormatProperties() { clear(); } @@ -23,8 +38,10 @@ void DecimalFormatProperties::clear() { decimalPatternMatchRequired = false; decimalSeparatorAlwaysShown = false; exponentSignAlwaysShown = false; + formatFailIfMoreThanMaxDigits = false; formatWidth = -1; groupingSize = -1; + groupingUsed = true; magnitudeMultiplier = 0; maximumFractionDigits = -1; maximumIntegerDigits = -1; @@ -34,7 +51,8 @@ void DecimalFormatProperties::clear() { minimumGroupingDigits = -1; minimumIntegerDigits = -1; minimumSignificantDigits = -1; - multiplier = 0; + multiplier = 1; + multiplierScale = 0; negativePrefix.setToBogus(); negativePrefixPattern.setToBogus(); negativeSuffix.setToBogus(); @@ -43,9 +61,10 @@ void DecimalFormatProperties::clear() { padString.setToBogus(); parseCaseSensitive = false; parseIntegerOnly = false; - parseLenient = false; + parseMode.nullify(); parseNoExponent = false; parseToBigDecimal = false; + parseAllInput = UNUM_MAYBE; positivePrefix.setToBogus(); positivePrefixPattern.setToBogus(); positiveSuffix.setToBogus(); @@ -56,47 +75,70 @@ void DecimalFormatProperties::clear() { signAlwaysShown = false; } -bool DecimalFormatProperties::operator==(const DecimalFormatProperties &other) const { +bool +DecimalFormatProperties::_equals(const DecimalFormatProperties& other, bool ignoreForFastFormat) const { bool eq = true; + + // Properties that must be equal both normally and for fast-path formatting eq = eq && compactStyle == other.compactStyle; eq = eq && currency == other.currency; eq = eq && currencyPluralInfo.fPtr.getAlias() == other.currencyPluralInfo.fPtr.getAlias(); eq = eq && currencyUsage == other.currencyUsage; - eq = eq && decimalPatternMatchRequired == other.decimalPatternMatchRequired; eq = eq && decimalSeparatorAlwaysShown == other.decimalSeparatorAlwaysShown; eq = eq && exponentSignAlwaysShown == other.exponentSignAlwaysShown; + eq = eq && formatFailIfMoreThanMaxDigits == other.formatFailIfMoreThanMaxDigits; eq = eq && formatWidth == other.formatWidth; - eq = eq && groupingSize == other.groupingSize; eq = eq && magnitudeMultiplier == other.magnitudeMultiplier; - eq = eq && maximumFractionDigits == other.maximumFractionDigits; - eq = eq && maximumIntegerDigits == other.maximumIntegerDigits; eq = eq && maximumSignificantDigits == other.maximumSignificantDigits; eq = eq && minimumExponentDigits == other.minimumExponentDigits; - eq = eq && minimumFractionDigits == other.minimumFractionDigits; eq = eq && minimumGroupingDigits == other.minimumGroupingDigits; - eq = eq && minimumIntegerDigits == other.minimumIntegerDigits; eq = eq && minimumSignificantDigits == other.minimumSignificantDigits; eq = eq && multiplier == other.multiplier; + eq = eq && multiplierScale == other.multiplierScale; eq = eq && negativePrefix == other.negativePrefix; - eq = eq && negativePrefixPattern == other.negativePrefixPattern; eq = eq && negativeSuffix == other.negativeSuffix; - eq = eq && negativeSuffixPattern == other.negativeSuffixPattern; eq = eq && padPosition == other.padPosition; eq = eq && padString == other.padString; - eq = eq && parseCaseSensitive == other.parseCaseSensitive; - eq = eq && parseIntegerOnly == other.parseIntegerOnly; - eq = eq && parseLenient == other.parseLenient; - eq = eq && parseNoExponent == other.parseNoExponent; - eq = eq && parseToBigDecimal == other.parseToBigDecimal; eq = eq && positivePrefix == other.positivePrefix; - eq = eq && positivePrefixPattern == other.positivePrefixPattern; eq = eq && positiveSuffix == other.positiveSuffix; - eq = eq && positiveSuffixPattern == other.positiveSuffixPattern; eq = eq && roundingIncrement == other.roundingIncrement; eq = eq && roundingMode == other.roundingMode; eq = eq && secondaryGroupingSize == other.secondaryGroupingSize; eq = eq && signAlwaysShown == other.signAlwaysShown; + + if (ignoreForFastFormat) { + return eq; + } + + // Properties ignored by fast-path formatting + // Formatting (special handling required): + eq = eq && groupingSize == other.groupingSize; + eq = eq && groupingUsed == other.groupingUsed; + eq = eq && minimumFractionDigits == other.minimumFractionDigits; + eq = eq && maximumFractionDigits == other.maximumFractionDigits; + eq = eq && maximumIntegerDigits == other.maximumIntegerDigits; + eq = eq && minimumIntegerDigits == other.minimumIntegerDigits; + eq = eq && negativePrefixPattern == other.negativePrefixPattern; + eq = eq && negativeSuffixPattern == other.negativeSuffixPattern; + eq = eq && positivePrefixPattern == other.positivePrefixPattern; + eq = eq && positiveSuffixPattern == other.positiveSuffixPattern; + + // Parsing (always safe to ignore): + eq = eq && decimalPatternMatchRequired == other.decimalPatternMatchRequired; + eq = eq && parseCaseSensitive == other.parseCaseSensitive; + eq = eq && parseIntegerOnly == other.parseIntegerOnly; + eq = eq && parseMode == other.parseMode; + eq = eq && parseNoExponent == other.parseNoExponent; + eq = eq && parseToBigDecimal == other.parseToBigDecimal; + eq = eq && parseAllInput == other.parseAllInput; + return eq; } +bool DecimalFormatProperties::equalsDefaultExceptFastFormat() const { + UErrorCode localStatus = U_ZERO_ERROR; + umtx_initOnce(gDefaultPropertiesInitOnce, &initDefaultProperties, localStatus); + return _equals(*reinterpret_cast(kRawDefaultProperties), true); +} + #endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/deps/icu-small/source/i18n/number_decimfmtprops.h b/deps/icu-small/source/i18n/number_decimfmtprops.h index 96356cad453..f288b6e0d97 100644 --- a/deps/icu-small/source/i18n/number_decimfmtprops.h +++ b/deps/icu-small/source/i18n/number_decimfmtprops.h @@ -3,7 +3,7 @@ #include "unicode/utypes.h" -#if !UCONFIG_NO_FORMATTING && !UPRV_INCOMPLETE_CPP11_SUPPORT +#if !UCONFIG_NO_FORMATTING #ifndef __NUMBER_DECIMFMTPROPS_H__ #define __NUMBER_DECIMFMTPROPS_H__ @@ -30,21 +30,65 @@ template class U_I18N_API LocalPointer; namespace number { namespace impl { -// TODO: Figure out a nicer way to deal with CurrencyPluralInfo. // Exported as U_I18N_API because it is a public member field of exported DecimalFormatProperties -struct U_I18N_API CurrencyPluralInfoWrapper { +// Using this wrapper is rather unfortunate, but is needed on Windows platforms in order to allow +// for DLL-exporting an fully specified template instantiation. +class U_I18N_API CurrencyPluralInfoWrapper { +public: LocalPointer fPtr; - CurrencyPluralInfoWrapper() {} + CurrencyPluralInfoWrapper() = default; + CurrencyPluralInfoWrapper(const CurrencyPluralInfoWrapper& other) { if (!other.fPtr.isNull()) { fPtr.adoptInstead(new CurrencyPluralInfo(*other.fPtr)); } } + + CurrencyPluralInfoWrapper& operator=(const CurrencyPluralInfoWrapper& other) { + if (!other.fPtr.isNull()) { + fPtr.adoptInstead(new CurrencyPluralInfo(*other.fPtr)); + } + return *this; + } +}; + +/** Controls the set of rules for parsing a string from the old DecimalFormat API. */ +enum ParseMode { + /** + * Lenient mode should be used if you want to accept malformed user input. It will use heuristics + * to attempt to parse through typographical errors in the string. + */ + PARSE_MODE_LENIENT, + + /** + * Strict mode should be used if you want to require that the input is well-formed. More + * specifically, it differs from lenient mode in the following ways: + * + *
    + *
  • Grouping widths must match the grouping settings. For example, "12,3,45" will fail if the + * grouping width is 3, as in the pattern "#,##0". + *
  • The string must contain a complete prefix and suffix. For example, if the pattern is + * "{#};(#)", then "{123}" or "(123)" would match, but "{123", "123}", and "123" would all fail. + * (The latter strings would be accepted in lenient mode.) + *
  • Whitespace may not appear at arbitrary places in the string. In lenient mode, whitespace + * is allowed to occur arbitrarily before and after prefixes and exponent separators. + *
  • Leading grouping separators are not allowed, as in ",123". + *
  • Minus and plus signs can only appear if specified in the pattern. In lenient mode, a plus + * or minus sign can always precede a number. + *
  • The set of characters that can be interpreted as a decimal or grouping separator is + * smaller. + *
  • If currency parsing is enabled, currencies must only appear where + * specified in either the current pattern string or in a valid pattern string for the current + * locale. For example, if the pattern is "¤0.00", then "$1.23" would match, but "1.23$" would + * fail to match. + *
+ */ + PARSE_MODE_STRICT, }; // Exported as U_I18N_API because it is needed for the unit test PatternStringTest -struct U_I18N_API DecimalFormatProperties { +struct U_I18N_API DecimalFormatProperties : public UMemory { public: NullableValue compactStyle; @@ -54,9 +98,11 @@ struct U_I18N_API DecimalFormatProperties { bool decimalPatternMatchRequired; bool decimalSeparatorAlwaysShown; bool exponentSignAlwaysShown; + bool formatFailIfMoreThanMaxDigits; // ICU4C-only int32_t formatWidth; int32_t groupingSize; - int32_t magnitudeMultiplier; + bool groupingUsed; + int32_t magnitudeMultiplier; // internal field like multiplierScale but separate to avoid conflict int32_t maximumFractionDigits; int32_t maximumIntegerDigits; int32_t maximumSignificantDigits; @@ -66,6 +112,7 @@ struct U_I18N_API DecimalFormatProperties { int32_t minimumIntegerDigits; int32_t minimumSignificantDigits; int32_t multiplier; + int32_t multiplierScale; // ICU4C-only UnicodeString negativePrefix; UnicodeString negativePrefixPattern; UnicodeString negativeSuffix; @@ -74,9 +121,10 @@ struct U_I18N_API DecimalFormatProperties { UnicodeString padString; bool parseCaseSensitive; bool parseIntegerOnly; - bool parseLenient; + NullableValue parseMode; bool parseNoExponent; - bool parseToBigDecimal; + bool parseToBigDecimal; // TODO: Not needed in ICU4C? + UNumberFormatAttributeValue parseAllInput; // ICU4C-only //PluralRules pluralRules; UnicodeString positivePrefix; UnicodeString positivePrefixPattern; @@ -89,13 +137,20 @@ struct U_I18N_API DecimalFormatProperties { DecimalFormatProperties(); - //DecimalFormatProperties(const DecimalFormatProperties &other) = default; - - DecimalFormatProperties &operator=(const DecimalFormatProperties &other) = default; - - bool operator==(const DecimalFormatProperties &other) const; + inline bool operator==(const DecimalFormatProperties& other) const { + return _equals(other, false); + } void clear(); + + /** + * Checks for equality to the default DecimalFormatProperties, but ignores the prescribed set of + * options for fast-path formatting. + */ + bool equalsDefaultExceptFastFormat() const; + + private: + bool _equals(const DecimalFormatProperties& other, bool ignoreForFastFormat) const; }; } // namespace impl diff --git a/deps/icu-small/source/i18n/number_decnum.h b/deps/icu-small/source/i18n/number_decnum.h new file mode 100644 index 00000000000..a7793470b55 --- /dev/null +++ b/deps/icu-small/source/i18n/number_decnum.h @@ -0,0 +1,77 @@ +// © 2017 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 __NUMBER_DECNUM_H__ +#define __NUMBER_DECNUM_H__ + +#include "decNumber.h" +#include "charstr.h" + +U_NAMESPACE_BEGIN + +#define DECNUM_INITIAL_CAPACITY 34 + +// Export an explicit template instantiation of the MaybeStackHeaderAndArray that is used as a data member of DecNum. +// When building DLLs for Windows this is required even though no direct access to the MaybeStackHeaderAndArray 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 +template class U_I18N_API MaybeStackHeaderAndArray; +#endif + +namespace number { +namespace impl { + +/** A very thin C++ wrapper around decNumber.h */ +// Exported as U_I18N_API for tests +class U_I18N_API DecNum : public UMemory { + public: + DecNum(); // leaves object in valid but undefined state + + // Copy-like constructor; use the default move operators. + DecNum(const DecNum& other, UErrorCode& status); + + /** Sets the decNumber to the StringPiece. */ + void setTo(StringPiece str, UErrorCode& status); + + /** Sets the decNumber to the NUL-terminated char string. */ + void setTo(const char* str, UErrorCode& status); + + /** Uses double_conversion to set this decNumber to the given double. */ + void setTo(double d, UErrorCode& status); + + /** Sets the decNumber to the BCD representation. */ + void setTo(const uint8_t* bcd, int32_t length, int32_t scale, bool isNegative, UErrorCode& status); + + void normalize(); + + void multiplyBy(const DecNum& rhs, UErrorCode& status); + + void divideBy(const DecNum& rhs, UErrorCode& status); + + bool isNegative() const; + + bool isZero() const; + + inline const decNumber* getRawDecNumber() const { + return fData.getAlias(); + } + + private: + static constexpr int32_t kDefaultDigits = DECNUM_INITIAL_CAPACITY; + MaybeStackHeaderAndArray fData; + decContext fContext; + + void _setTo(const char* str, int32_t maxDigits, UErrorCode& status); +}; + +} // namespace impl +} // namespace number + +U_NAMESPACE_END + +#endif // __NUMBER_DECNUM_H__ + +#endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/deps/icu-small/source/i18n/number_fluent.cpp b/deps/icu-small/source/i18n/number_fluent.cpp index 27113106c50..687adb6b5ba 100644 --- a/deps/icu-small/source/i18n/number_fluent.cpp +++ b/deps/icu-small/source/i18n/number_fluent.cpp @@ -3,20 +3,26 @@ #include "unicode/utypes.h" -#if !UCONFIG_NO_FORMATTING && !UPRV_INCOMPLETE_CPP11_SUPPORT +#if !UCONFIG_NO_FORMATTING #include "uassert.h" #include "unicode/numberformatter.h" #include "number_decimalquantity.h" #include "number_formatimpl.h" #include "umutex.h" +#include "number_asformat.h" +#include "number_skeletons.h" +#include "number_utils.h" +#include "number_utypes.h" +#include "util.h" +#include "fphdlimp.h" using namespace icu; using namespace icu::number; using namespace icu::number::impl; template -Derived NumberFormatterSettings::notation(const Notation ¬ation) const { +Derived NumberFormatterSettings::notation(const Notation& notation) const& { Derived copy(*this); // NOTE: Slicing is OK. copy.fMacros.notation = notation; @@ -24,7 +30,15 @@ Derived NumberFormatterSettings::notation(const Notation ¬ation) con } template -Derived NumberFormatterSettings::unit(const icu::MeasureUnit &unit) const { +Derived NumberFormatterSettings::notation(const Notation& notation)&& { + Derived move(std::move(*this)); + // NOTE: Slicing is OK. + move.fMacros.notation = notation; + return move; +} + +template +Derived NumberFormatterSettings::unit(const icu::MeasureUnit& unit) const& { Derived copy(*this); // NOTE: Slicing occurs here. However, CurrencyUnit can be restored from MeasureUnit. // TimeUnit may be affected, but TimeUnit is not as relevant to number formatting. @@ -33,21 +47,41 @@ Derived NumberFormatterSettings::unit(const icu::MeasureUnit &unit) con } template -Derived NumberFormatterSettings::adoptUnit(icu::MeasureUnit *unit) const { +Derived NumberFormatterSettings::unit(const icu::MeasureUnit& unit)&& { + Derived move(std::move(*this)); + // See comments above about slicing. + move.fMacros.unit = unit; + return move; +} + +template +Derived NumberFormatterSettings::adoptUnit(icu::MeasureUnit* unit) const& { Derived copy(*this); - // Just copy the unit into the MacroProps by value, and delete it since we have ownership. + // Just move the unit into the MacroProps by value, and delete it since we have ownership. // NOTE: Slicing occurs here. However, CurrencyUnit can be restored from MeasureUnit. // TimeUnit may be affected, but TimeUnit is not as relevant to number formatting. if (unit != nullptr) { - // TODO: On nullptr, reset to default value? - copy.fMacros.unit = *unit; + // TODO: On nullptr, reset to default value? + copy.fMacros.unit = std::move(*unit); delete unit; } return copy; } template -Derived NumberFormatterSettings::perUnit(const icu::MeasureUnit &perUnit) const { +Derived NumberFormatterSettings::adoptUnit(icu::MeasureUnit* unit)&& { + Derived move(std::move(*this)); + // See comments above about slicing and ownership. + if (unit != nullptr) { + // TODO: On nullptr, reset to default value? + move.fMacros.unit = std::move(*unit); + delete unit; + } + return move; +} + +template +Derived NumberFormatterSettings::perUnit(const icu::MeasureUnit& perUnit) const& { Derived copy(*this); // See comments above about slicing. copy.fMacros.perUnit = perUnit; @@ -55,27 +89,69 @@ Derived NumberFormatterSettings::perUnit(const icu::MeasureUnit &perUni } template -Derived NumberFormatterSettings::adoptPerUnit(icu::MeasureUnit *perUnit) const { +Derived NumberFormatterSettings::perUnit(const icu::MeasureUnit& perUnit)&& { + Derived move(std::move(*this)); + // See comments above about slicing. + move.fMacros.perUnit = perUnit; + return move; +} + +template +Derived NumberFormatterSettings::adoptPerUnit(icu::MeasureUnit* perUnit) const& { Derived copy(*this); // See comments above about slicing and ownership. if (perUnit != nullptr) { - // TODO: On nullptr, reset to default value? - copy.fMacros.perUnit = *perUnit; + // TODO: On nullptr, reset to default value? + copy.fMacros.perUnit = std::move(*perUnit); delete perUnit; } return copy; } template -Derived NumberFormatterSettings::rounding(const Rounder &rounder) const { +Derived NumberFormatterSettings::adoptPerUnit(icu::MeasureUnit* perUnit)&& { + Derived move(std::move(*this)); + // See comments above about slicing and ownership. + if (perUnit != nullptr) { + // TODO: On nullptr, reset to default value? + move.fMacros.perUnit = std::move(*perUnit); + delete perUnit; + } + return move; +} + +template +Derived NumberFormatterSettings::precision(const Precision& precision) const& { Derived copy(*this); // NOTE: Slicing is OK. - copy.fMacros.rounder = rounder; + copy.fMacros.precision = precision; return copy; } template -Derived NumberFormatterSettings::grouping(const UGroupingStrategy &strategy) const { +Derived NumberFormatterSettings::precision(const Precision& precision)&& { + Derived move(std::move(*this)); + // NOTE: Slicing is OK. + move.fMacros.precision = precision; + return move; +} + +template +Derived NumberFormatterSettings::roundingMode(UNumberFormatRoundingMode roundingMode) const& { + Derived copy(*this); + copy.fMacros.roundingMode = roundingMode; + return copy; +} + +template +Derived NumberFormatterSettings::roundingMode(UNumberFormatRoundingMode roundingMode)&& { + Derived move(std::move(*this)); + move.fMacros.roundingMode = roundingMode; + return move; +} + +template +Derived NumberFormatterSettings::grouping(UGroupingStrategy strategy) const& { Derived copy(*this); // NOTE: This is slightly different than how the setting is stored in Java // because we want to put it on the stack. @@ -84,61 +160,174 @@ Derived NumberFormatterSettings::grouping(const UGroupingStrategy &stra } template -Derived NumberFormatterSettings::integerWidth(const IntegerWidth &style) const { +Derived NumberFormatterSettings::grouping(UGroupingStrategy strategy)&& { + Derived move(std::move(*this)); + move.fMacros.grouper = Grouper::forStrategy(strategy); + return move; +} + +template +Derived NumberFormatterSettings::integerWidth(const IntegerWidth& style) const& { Derived copy(*this); copy.fMacros.integerWidth = style; return copy; } template -Derived NumberFormatterSettings::symbols(const DecimalFormatSymbols &symbols) const { +Derived NumberFormatterSettings::integerWidth(const IntegerWidth& style)&& { + Derived move(std::move(*this)); + move.fMacros.integerWidth = style; + return move; +} + +template +Derived NumberFormatterSettings::symbols(const DecimalFormatSymbols& symbols) const& { Derived copy(*this); copy.fMacros.symbols.setTo(symbols); return copy; } template -Derived NumberFormatterSettings::adoptSymbols(NumberingSystem *ns) const { +Derived NumberFormatterSettings::symbols(const DecimalFormatSymbols& symbols)&& { + Derived move(std::move(*this)); + move.fMacros.symbols.setTo(symbols); + return move; +} + +template +Derived NumberFormatterSettings::adoptSymbols(NumberingSystem* ns) const& { Derived copy(*this); copy.fMacros.symbols.setTo(ns); return copy; } template -Derived NumberFormatterSettings::unitWidth(const UNumberUnitWidth &width) const { +Derived NumberFormatterSettings::adoptSymbols(NumberingSystem* ns)&& { + Derived move(std::move(*this)); + move.fMacros.symbols.setTo(ns); + return move; +} + +template +Derived NumberFormatterSettings::unitWidth(UNumberUnitWidth width) const& { Derived copy(*this); copy.fMacros.unitWidth = width; return copy; } template -Derived NumberFormatterSettings::sign(const UNumberSignDisplay &style) const { +Derived NumberFormatterSettings::unitWidth(UNumberUnitWidth width)&& { + Derived move(std::move(*this)); + move.fMacros.unitWidth = width; + return move; +} + +template +Derived NumberFormatterSettings::sign(UNumberSignDisplay style) const& { Derived copy(*this); copy.fMacros.sign = style; return copy; } template -Derived NumberFormatterSettings::decimal(const UNumberDecimalSeparatorDisplay &style) const { +Derived NumberFormatterSettings::sign(UNumberSignDisplay style)&& { + Derived move(std::move(*this)); + move.fMacros.sign = style; + return move; +} + +template +Derived NumberFormatterSettings::decimal(UNumberDecimalSeparatorDisplay style) const& { Derived copy(*this); copy.fMacros.decimal = style; return copy; } template -Derived NumberFormatterSettings::padding(const Padder &padder) const { +Derived NumberFormatterSettings::decimal(UNumberDecimalSeparatorDisplay style)&& { + Derived move(std::move(*this)); + move.fMacros.decimal = style; + return move; +} + +template +Derived NumberFormatterSettings::scale(const Scale& scale) const& { + Derived copy(*this); + copy.fMacros.scale = scale; + return copy; +} + +template +Derived NumberFormatterSettings::scale(const Scale& scale)&& { + Derived move(std::move(*this)); + move.fMacros.scale = scale; + return move; +} + +template +Derived NumberFormatterSettings::padding(const Padder& padder) const& { Derived copy(*this); copy.fMacros.padder = padder; return copy; } template -Derived NumberFormatterSettings::threshold(int32_t threshold) const { +Derived NumberFormatterSettings::padding(const Padder& padder)&& { + Derived move(std::move(*this)); + move.fMacros.padder = padder; + return move; +} + +template +Derived NumberFormatterSettings::threshold(int32_t threshold) const& { Derived copy(*this); copy.fMacros.threshold = threshold; return copy; } +template +Derived NumberFormatterSettings::threshold(int32_t threshold)&& { + Derived move(std::move(*this)); + move.fMacros.threshold = threshold; + return move; +} + +template +Derived NumberFormatterSettings::macros(const impl::MacroProps& macros) const& { + Derived copy(*this); + copy.fMacros = macros; + return copy; +} + +template +Derived NumberFormatterSettings::macros(const impl::MacroProps& macros)&& { + Derived move(std::move(*this)); + move.fMacros = macros; + return move; +} + +template +Derived NumberFormatterSettings::macros(impl::MacroProps&& macros) const& { + Derived copy(*this); + copy.fMacros = std::move(macros); + return copy; +} + +template +Derived NumberFormatterSettings::macros(impl::MacroProps&& macros)&& { + Derived move(std::move(*this)); + move.fMacros = std::move(macros); + return move; +} + +template +UnicodeString NumberFormatterSettings::toSkeleton(UErrorCode& status) const { + if (fMacros.copyErrorTo(status)) { + return ICU_Utility::makeBogusString(); + } + return skeleton::generate(fMacros, status); +} + // Declare all classes that implement NumberFormatterSettings // See https://stackoverflow.com/a/495056/1407170 template @@ -152,38 +341,135 @@ UnlocalizedNumberFormatter NumberFormatter::with() { return result; } -LocalizedNumberFormatter NumberFormatter::withLocale(const Locale &locale) { +LocalizedNumberFormatter NumberFormatter::withLocale(const Locale& locale) { return with().locale(locale); } -// Make the child class constructor that takes the parent class call the parent class's copy constructor -UnlocalizedNumberFormatter::UnlocalizedNumberFormatter( - const NumberFormatterSettings &other) - : NumberFormatterSettings(other) { +UnlocalizedNumberFormatter +NumberFormatter::forSkeleton(const UnicodeString& skeleton, UErrorCode& status) { + return skeleton::create(skeleton, status); } -// Make the child class constructor that takes the parent class call the parent class's copy constructor -// For LocalizedNumberFormatter, also copy over the extra fields -LocalizedNumberFormatter::LocalizedNumberFormatter( - const NumberFormatterSettings &other) - : NumberFormatterSettings(other) { - // No additional copies required + +template using NFS = NumberFormatterSettings; +using LNF = LocalizedNumberFormatter; +using UNF = UnlocalizedNumberFormatter; + +UnlocalizedNumberFormatter::UnlocalizedNumberFormatter(const UNF& other) + : UNF(static_cast&>(other)) {} + +UnlocalizedNumberFormatter::UnlocalizedNumberFormatter(const NFS& other) + : NFS(other) { + // No additional fields to assign } -LocalizedNumberFormatter::LocalizedNumberFormatter(const MacroProps ¯os, const Locale &locale) { +UnlocalizedNumberFormatter::UnlocalizedNumberFormatter(UNF&& src) U_NOEXCEPT + : UNF(static_cast&&>(src)) {} + +UnlocalizedNumberFormatter::UnlocalizedNumberFormatter(NFS&& src) U_NOEXCEPT + : NFS(std::move(src)) { + // No additional fields to assign +} + +UnlocalizedNumberFormatter& UnlocalizedNumberFormatter::operator=(const UNF& other) { + NFS::operator=(static_cast&>(other)); + // No additional fields to assign + return *this; +} + +UnlocalizedNumberFormatter& UnlocalizedNumberFormatter::operator=(UNF&& src) U_NOEXCEPT { + NFS::operator=(static_cast&&>(src)); + // No additional fields to assign + return *this; +} + +LocalizedNumberFormatter::LocalizedNumberFormatter(const LNF& other) + : LNF(static_cast&>(other)) {} + +LocalizedNumberFormatter::LocalizedNumberFormatter(const NFS& other) + : NFS(other) { + // No additional fields to assign (let call count and compiled formatter reset to defaults) +} + +LocalizedNumberFormatter::LocalizedNumberFormatter(LocalizedNumberFormatter&& src) U_NOEXCEPT + : LNF(static_cast&&>(src)) {} + +LocalizedNumberFormatter::LocalizedNumberFormatter(NFS&& src) U_NOEXCEPT + : NFS(std::move(src)) { + // For the move operators, copy over the compiled formatter. + // Note: if the formatter is not compiled, call count information is lost. + if (static_cast(src).fCompiled != nullptr) { + lnfMoveHelper(static_cast(src)); + } +} + +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) + return *this; +} + +LocalizedNumberFormatter& LocalizedNumberFormatter::operator=(LNF&& src) U_NOEXCEPT { + NFS::operator=(static_cast&&>(src)); + // For the move operators, copy over the compiled formatter. + // Note: if the formatter is not compiled, call count information is lost. + if (static_cast(src).fCompiled != nullptr) { + // Formatter is compiled + lnfMoveHelper(static_cast(src)); + } else { + // Reset to default values. + auto* callCount = reinterpret_cast(fUnsafeCallCount); + umtx_storeRelease(*callCount, 0); + fCompiled = nullptr; + } + return *this; +} + +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); + fCompiled = src.fCompiled; + // Reset the source object to leave it in a safe state. + auto* srcCallCount = reinterpret_cast(src.fUnsafeCallCount); + umtx_storeRelease(*srcCallCount, 0); + src.fCompiled = nullptr; +} + + +LocalizedNumberFormatter::~LocalizedNumberFormatter() { + delete fCompiled; +} + +LocalizedNumberFormatter::LocalizedNumberFormatter(const MacroProps& macros, const Locale& locale) { fMacros = macros; fMacros.locale = locale; } -LocalizedNumberFormatter UnlocalizedNumberFormatter::locale(const Locale &locale) const { +LocalizedNumberFormatter::LocalizedNumberFormatter(MacroProps&& macros, const Locale& locale) { + fMacros = std::move(macros); + fMacros.locale = locale; +} + +LocalizedNumberFormatter UnlocalizedNumberFormatter::locale(const Locale& locale) const& { return LocalizedNumberFormatter(fMacros, locale); } -SymbolsWrapper::SymbolsWrapper(const SymbolsWrapper &other) { +LocalizedNumberFormatter UnlocalizedNumberFormatter::locale(const Locale& locale)&& { + return LocalizedNumberFormatter(std::move(fMacros), locale); +} + +SymbolsWrapper::SymbolsWrapper(const SymbolsWrapper& other) { doCopyFrom(other); } -SymbolsWrapper &SymbolsWrapper::operator=(const SymbolsWrapper &other) { +SymbolsWrapper::SymbolsWrapper(SymbolsWrapper&& src) U_NOEXCEPT { + doMoveFrom(std::move(src)); +} + +SymbolsWrapper& SymbolsWrapper::operator=(const SymbolsWrapper& other) { if (this == &other) { return *this; } @@ -192,23 +478,32 @@ SymbolsWrapper &SymbolsWrapper::operator=(const SymbolsWrapper &other) { return *this; } +SymbolsWrapper& SymbolsWrapper::operator=(SymbolsWrapper&& src) U_NOEXCEPT { + if (this == &src) { + return *this; + } + doCleanup(); + doMoveFrom(std::move(src)); + return *this; +} + SymbolsWrapper::~SymbolsWrapper() { doCleanup(); } -void SymbolsWrapper::setTo(const DecimalFormatSymbols &dfs) { +void SymbolsWrapper::setTo(const DecimalFormatSymbols& dfs) { doCleanup(); fType = SYMPTR_DFS; fPtr.dfs = new DecimalFormatSymbols(dfs); } -void SymbolsWrapper::setTo(const NumberingSystem *ns) { +void SymbolsWrapper::setTo(const NumberingSystem* ns) { doCleanup(); fType = SYMPTR_NS; fPtr.ns = ns; } -void SymbolsWrapper::doCopyFrom(const SymbolsWrapper &other) { +void SymbolsWrapper::doCopyFrom(const SymbolsWrapper& other) { fType = other.fType; switch (fType) { case SYMPTR_NONE: @@ -233,6 +528,23 @@ void SymbolsWrapper::doCopyFrom(const SymbolsWrapper &other) { } } +void SymbolsWrapper::doMoveFrom(SymbolsWrapper&& src) { + fType = src.fType; + switch (fType) { + case SYMPTR_NONE: + // No action necessary + break; + case SYMPTR_DFS: + fPtr.dfs = src.fPtr.dfs; + src.fPtr.dfs = nullptr; + break; + case SYMPTR_NS: + fPtr.ns = src.fPtr.ns; + src.fPtr.ns = nullptr; + break; + } +} + void SymbolsWrapper::doCleanup() { switch (fType) { case SYMPTR_NONE: @@ -265,53 +577,122 @@ const NumberingSystem* SymbolsWrapper::getNumberingSystem() const { return fPtr.ns; } -LocalizedNumberFormatter::~LocalizedNumberFormatter() { - delete fCompiled; -} -FormattedNumber LocalizedNumberFormatter::formatInt(int64_t value, UErrorCode &status) const { +FormattedNumber LocalizedNumberFormatter::formatInt(int64_t value, UErrorCode& status) const { if (U_FAILURE(status)) { return FormattedNumber(U_ILLEGAL_ARGUMENT_ERROR); } - auto results = new NumberFormatterResults(); + auto results = new UFormattedNumberData(); if (results == nullptr) { status = U_MEMORY_ALLOCATION_ERROR; return FormattedNumber(status); } results->quantity.setToLong(value); - return formatImpl(results, status); + formatImpl(results, status); + + // Do not save the results object if we encountered a failure. + if (U_SUCCESS(status)) { + return FormattedNumber(results); + } else { + delete results; + return FormattedNumber(status); + } } -FormattedNumber LocalizedNumberFormatter::formatDouble(double value, UErrorCode &status) const { +FormattedNumber LocalizedNumberFormatter::formatDouble(double value, UErrorCode& status) const { if (U_FAILURE(status)) { return FormattedNumber(U_ILLEGAL_ARGUMENT_ERROR); } - auto results = new NumberFormatterResults(); + auto results = new UFormattedNumberData(); if (results == nullptr) { status = U_MEMORY_ALLOCATION_ERROR; return FormattedNumber(status); } results->quantity.setToDouble(value); - return formatImpl(results, status); + formatImpl(results, status); + + // Do not save the results object if we encountered a failure. + if (U_SUCCESS(status)) { + return FormattedNumber(results); + } else { + delete results; + return FormattedNumber(status); + } } -FormattedNumber LocalizedNumberFormatter::formatDecimal(StringPiece value, UErrorCode &status) const { +FormattedNumber LocalizedNumberFormatter::formatDecimal(StringPiece value, UErrorCode& status) const { if (U_FAILURE(status)) { return FormattedNumber(U_ILLEGAL_ARGUMENT_ERROR); } - auto results = new NumberFormatterResults(); + auto results = new UFormattedNumberData(); if (results == nullptr) { status = U_MEMORY_ALLOCATION_ERROR; return FormattedNumber(status); } - results->quantity.setToDecNumber(value); - return formatImpl(results, status); + results->quantity.setToDecNumber(value, status); + formatImpl(results, status); + + // Do not save the results object if we encountered a failure. + if (U_SUCCESS(status)) { + return FormattedNumber(results); + } else { + delete results; + return FormattedNumber(status); + } } FormattedNumber -LocalizedNumberFormatter::formatImpl(impl::NumberFormatterResults *results, UErrorCode &status) const { +LocalizedNumberFormatter::formatDecimalQuantity(const DecimalQuantity& dq, UErrorCode& status) const { + if (U_FAILURE(status)) { return FormattedNumber(U_ILLEGAL_ARGUMENT_ERROR); } + auto results = new UFormattedNumberData(); + if (results == nullptr) { + status = U_MEMORY_ALLOCATION_ERROR; + return FormattedNumber(status); + } + results->quantity = dq; + formatImpl(results, status); + + // Do not save the results object if we encountered a failure. + if (U_SUCCESS(status)) { + return FormattedNumber(results); + } else { + delete results; + return FormattedNumber(status); + } +} + +void LocalizedNumberFormatter::formatImpl(impl::UFormattedNumberData* results, UErrorCode& status) const { + if (computeCompiled(status)) { + fCompiled->apply(results->quantity, results->string, status); + } else { + NumberFormatterImpl::applyStatic(fMacros, results->quantity, results->string, status); + } +} + +void LocalizedNumberFormatter::getAffixImpl(bool isPrefix, bool isNegative, UnicodeString& result, + UErrorCode& status) const { + NumberStringBuilder string; + auto signum = static_cast(isNegative ? -1 : 1); + // Always return affixes for plural form OTHER. + static const StandardPlural::Form plural = StandardPlural::OTHER; + int32_t prefixLength; + if (computeCompiled(status)) { + prefixLength = fCompiled->getPrefixSuffix(signum, plural, string, status); + } else { + prefixLength = NumberFormatterImpl::getPrefixSuffixStatic(fMacros, signum, plural, string, status); + } + result.remove(); + if (isPrefix) { + result.append(string.toTempUnicodeString().tempSubStringBetween(0, prefixLength)); + } else { + result.append(string.toTempUnicodeString().tempSubStringBetween(prefixLength, string.length())); + } +} + +bool LocalizedNumberFormatter::computeCompiled(UErrorCode& status) const { // fUnsafeCallCount contains memory to be interpreted as an atomic int, most commonly // std::atomic. Since the type of atomic int is platform-dependent, we cast the // bytes in fUnsafeCallCount to u_atomic_int32_t, a typedef for the platform-dependent // atomic int type defined in umutex.h. - static_assert(sizeof(u_atomic_int32_t) <= sizeof(fUnsafeCallCount), - "Atomic integer size on this platform exceeds the size allocated by fUnsafeCallCount"); - u_atomic_int32_t* callCount = reinterpret_cast( - const_cast(this)->fUnsafeCallCount); + static_assert( + sizeof(u_atomic_int32_t) <= sizeof(fUnsafeCallCount), + "Atomic integer size on this platform exceeds the size allocated by fUnsafeCallCount"); + auto* callCount = reinterpret_cast( + const_cast(this)->fUnsafeCallCount); // A positive value in the atomic int indicates that the data structure is not yet ready; // a negative value indicates that it is ready. If, after the increment, the atomic int @@ -325,64 +706,144 @@ LocalizedNumberFormatter::formatImpl(impl::NumberFormatterResults *results, UErr 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 = NumberFormatterImpl::fromMacros(fMacros, status); U_ASSERT(fCompiled == nullptr); - const_cast(this)->fCompiled = compiled; + const_cast(this)->fCompiled = compiled; umtx_storeRelease(*callCount, INT32_MIN); - compiled->apply(results->quantity, results->string, status); + return true; } else if (currentCount < 0) { // The data structure is already built; use it (fast path). U_ASSERT(fCompiled != nullptr); - fCompiled->apply(results->quantity, results->string, status); + return true; } else { // Format the number without building the data structure (slow path). - NumberFormatterImpl::applyStatic(fMacros, results->quantity, results->string, status); - } - - // Do not save the results object if we encountered a failure. - if (U_SUCCESS(status)) { - return FormattedNumber(results); - } else { - delete results; - return FormattedNumber(status); + return false; } } +const impl::NumberFormatterImpl* LocalizedNumberFormatter::getCompiled() const { + return fCompiled; +} + +int32_t LocalizedNumberFormatter::getCallCount() const { + auto* callCount = reinterpret_cast( + const_cast(this)->fUnsafeCallCount); + return umtx_loadAcquire(*callCount); +} + +Format* LocalizedNumberFormatter::toFormat(UErrorCode& status) const { + LocalPointer retval( + new LocalizedNumberFormatterAsFormat(*this, fMacros.locale), status); + return retval.orphan(); +} + + +FormattedNumber::FormattedNumber(FormattedNumber&& 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; +} + +FormattedNumber& FormattedNumber::operator=(FormattedNumber&& 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 FormattedNumber::toString() const { + UErrorCode localStatus = U_ZERO_ERROR; + return toString(localStatus); +} + +UnicodeString FormattedNumber::toString(UErrorCode& status) const { + if (U_FAILURE(status)) { + return ICU_Utility::makeBogusString(); + } if (fResults == nullptr) { - // TODO: http://bugs.icu-project.org/trac/ticket/13437 - return {}; + status = fErrorCode; + return ICU_Utility::makeBogusString(); } return fResults->string.toUnicodeString(); } -Appendable &FormattedNumber::appendTo(Appendable &appendable) { +Appendable& FormattedNumber::appendTo(Appendable& appendable) { + UErrorCode localStatus = U_ZERO_ERROR; + return appendTo(appendable, localStatus); +} + +Appendable& FormattedNumber::appendTo(Appendable& appendable, UErrorCode& status) { + if (U_FAILURE(status)) { + return appendable; + } if (fResults == nullptr) { - // TODO: http://bugs.icu-project.org/trac/ticket/13437 + status = fErrorCode; return appendable; } appendable.appendString(fResults->string.chars(), fResults->string.length()); return appendable; } -void FormattedNumber::populateFieldPosition(FieldPosition &fieldPosition, UErrorCode &status) { - if (U_FAILURE(status)) { return; } +void FormattedNumber::populateFieldPosition(FieldPosition& fieldPosition, UErrorCode& status) { + if (U_FAILURE(status)) { + return; + } if (fResults == nullptr) { status = fErrorCode; return; } - fResults->string.populateFieldPosition(fieldPosition, 0, status); + // in case any users were depending on the old behavior: + fieldPosition.setBeginIndex(0); + fieldPosition.setEndIndex(0); + fResults->string.nextFieldPosition(fieldPosition, status); } -void -FormattedNumber::populateFieldPositionIterator(FieldPositionIterator &iterator, UErrorCode &status) { - if (U_FAILURE(status)) { return; } +UBool FormattedNumber::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 FormattedNumber::populateFieldPositionIterator(FieldPositionIterator& iterator, UErrorCode& status) { + getAllFieldPositions(iterator, status); +} + +void FormattedNumber::getAllFieldPositions(FieldPositionIterator& iterator, UErrorCode& status) const { + FieldPositionIteratorHandler fpih(&iterator, status); + getAllFieldPositionsImpl(fpih, status); +} + +void FormattedNumber::getAllFieldPositionsImpl(FieldPositionIteratorHandler& fpih, + UErrorCode& status) const { + if (U_FAILURE(status)) { + return; + } if (fResults == nullptr) { status = fErrorCode; return; } - fResults->string.populateFieldPositionIterator(iterator, status); + fResults->string.getAllFieldPositions(fpih, status); +} + +void FormattedNumber::getDecimalQuantity(DecimalQuantity& output, UErrorCode& status) const { + if (U_FAILURE(status)) { + return; + } + if (fResults == nullptr) { + status = fErrorCode; + return; + } + output = fResults->quantity; } FormattedNumber::~FormattedNumber() { diff --git a/deps/icu-small/source/i18n/number_formatimpl.cpp b/deps/icu-small/source/i18n/number_formatimpl.cpp index bc96cb15dab..3f887128bcc 100644 --- a/deps/icu-small/source/i18n/number_formatimpl.cpp +++ b/deps/icu-small/source/i18n/number_formatimpl.cpp @@ -3,7 +3,7 @@ #include "unicode/utypes.h" -#if !UCONFIG_NO_FORMATTING && !UPRV_INCOMPLETE_CPP11_SUPPORT +#if !UCONFIG_NO_FORMATTING #include "cstring.h" #include "unicode/ures.h" @@ -26,88 +26,28 @@ using namespace icu::number::impl; namespace { -// NOTE: In Java, the method to get a pattern from the resource bundle exists in NumberFormat. -// In C++, we have to implement that logic here. -// TODO: Make Java and C++ consistent? - -enum CldrPatternStyle { - CLDR_PATTERN_STYLE_DECIMAL, - CLDR_PATTERN_STYLE_CURRENCY, - CLDR_PATTERN_STYLE_ACCOUNTING, - CLDR_PATTERN_STYLE_PERCENT - // TODO: Consider scientific format. -}; - -const char16_t * -doGetPattern(UResourceBundle *res, const char *nsName, const char *patternKey, UErrorCode &publicStatus, - UErrorCode &localStatus) { - // Construct the path into the resource bundle - CharString key; - key.append("NumberElements/", publicStatus); - key.append(nsName, publicStatus); - key.append("/patterns/", publicStatus); - key.append(patternKey, publicStatus); - if (U_FAILURE(publicStatus)) { - return u""; - } - return ures_getStringByKeyWithFallback(res, key.data(), nullptr, &localStatus); -} - -const char16_t *getPatternForStyle(const Locale &locale, const char *nsName, CldrPatternStyle style, - UErrorCode &status) { - const char *patternKey; - switch (style) { - case CLDR_PATTERN_STYLE_DECIMAL: - patternKey = "decimalFormat"; - break; - case CLDR_PATTERN_STYLE_CURRENCY: - patternKey = "currencyFormat"; - break; - case CLDR_PATTERN_STYLE_ACCOUNTING: - patternKey = "accountingFormat"; - break; - case CLDR_PATTERN_STYLE_PERCENT: - default: - patternKey = "percentFormat"; - break; - } - LocalUResourceBundlePointer res(ures_open(nullptr, locale.getName(), &status)); - if (U_FAILURE(status)) { return u""; } - - // Attempt to get the pattern with the native numbering system. - UErrorCode localStatus = U_ZERO_ERROR; - const char16_t *pattern; - pattern = doGetPattern(res.getAlias(), nsName, patternKey, status, localStatus); - if (U_FAILURE(status)) { return u""; } - - // Fall back to latn if native numbering system does not have the right pattern - if (U_FAILURE(localStatus) && uprv_strcmp("latn", nsName) != 0) { - localStatus = U_ZERO_ERROR; - pattern = doGetPattern(res.getAlias(), "latn", patternKey, status, localStatus); - if (U_FAILURE(status)) { return u""; } - } - - return pattern; -} - struct CurrencyFormatInfoResult { bool exists; const char16_t* pattern; const char16_t* decimalSeparator; const char16_t* groupingSeparator; }; -CurrencyFormatInfoResult getCurrencyFormatInfo(const Locale& locale, const char* isoCode, UErrorCode& status) { + +CurrencyFormatInfoResult +getCurrencyFormatInfo(const Locale& locale, const char* isoCode, UErrorCode& status) { // TODO: Load this data in a centralized location like ICU4J? + // TODO: Move this into the CurrencySymbols class? // TODO: Parts of this same data are loaded in dcfmtsym.cpp; should clean up. - CurrencyFormatInfoResult result = { false, nullptr, nullptr, nullptr }; - if (U_FAILURE(status)) return result; + CurrencyFormatInfoResult result = {false, nullptr, nullptr, nullptr}; + if (U_FAILURE(status)) { return result; } CharString key; key.append("Currencies/", status); key.append(isoCode, status); UErrorCode localStatus = status; LocalUResourceBundlePointer bundle(ures_open(U_ICUDATA_CURR, locale.getName(), &localStatus)); ures_getByKeyWithFallback(bundle.getAlias(), key.data(), bundle.getAlias(), &localStatus); - if (U_SUCCESS(localStatus) && ures_getSize(bundle.getAlias())>2) { // the length is 3 if more data is present + if (U_SUCCESS(localStatus) && + ures_getSize(bundle.getAlias()) > 2) { // the length is 3 if more data is present ures_getByIndex(bundle.getAlias(), 2, bundle.getAlias(), &localStatus); int32_t dummy; result.exists = true; @@ -121,65 +61,84 @@ CurrencyFormatInfoResult getCurrencyFormatInfo(const Locale& locale, const char* return result; } -inline bool unitIsCurrency(const MeasureUnit &unit) { - return uprv_strcmp("currency", unit.getType()) == 0; -} - -inline bool unitIsNoUnit(const MeasureUnit &unit) { - return uprv_strcmp("none", unit.getType()) == 0; -} - -inline bool unitIsPercent(const MeasureUnit &unit) { - return uprv_strcmp("percent", unit.getSubtype()) == 0; -} - -inline bool unitIsPermille(const MeasureUnit &unit) { - return uprv_strcmp("permille", unit.getSubtype()) == 0; -} - } // namespace -NumberFormatterImpl *NumberFormatterImpl::fromMacros(const MacroProps ¯os, UErrorCode &status) { + +MicroPropsGenerator::~MicroPropsGenerator() = default; + + +NumberFormatterImpl* NumberFormatterImpl::fromMacros(const MacroProps& macros, UErrorCode& status) { return new NumberFormatterImpl(macros, true, status); } -void NumberFormatterImpl::applyStatic(const MacroProps ¯os, DecimalQuantity &inValue, - NumberStringBuilder &outString, UErrorCode &status) { +void NumberFormatterImpl::applyStatic(const MacroProps& macros, DecimalQuantity& inValue, + NumberStringBuilder& outString, UErrorCode& status) { NumberFormatterImpl impl(macros, false, status); impl.applyUnsafe(inValue, outString, status); } +int32_t NumberFormatterImpl::getPrefixSuffixStatic(const MacroProps& macros, int8_t signum, + StandardPlural::Form plural, + NumberStringBuilder& outString, UErrorCode& status) { + NumberFormatterImpl impl(macros, false, status); + return impl.getPrefixSuffixUnsafe(signum, plural, outString, status); +} + // NOTE: C++ SPECIFIC DIFFERENCE FROM JAVA: // The "safe" apply method uses a new MicroProps. In the MicroPropsGenerator, fMicros is copied into the new instance. // The "unsafe" method simply re-uses fMicros, eliminating the extra copy operation. // See MicroProps::processQuantity() for details. -void NumberFormatterImpl::apply(DecimalQuantity &inValue, NumberStringBuilder &outString, - UErrorCode &status) const { +void NumberFormatterImpl::apply(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); } -void NumberFormatterImpl::applyUnsafe(DecimalQuantity &inValue, NumberStringBuilder &outString, - UErrorCode &status) { +void NumberFormatterImpl::applyUnsafe(DecimalQuantity& inValue, NumberStringBuilder& outString, + UErrorCode& status) { if (U_FAILURE(status)) { return; } fMicroPropsGenerator->processQuantity(inValue, fMicros, status); if (U_FAILURE(status)) { return; } microsToString(fMicros, inValue, outString, status); } -NumberFormatterImpl::NumberFormatterImpl(const MacroProps ¯os, bool safe, UErrorCode &status) { +int32_t NumberFormatterImpl::getPrefixSuffix(int8_t signum, StandardPlural::Form plural, + NumberStringBuilder& outString, UErrorCode& status) const { + if (U_FAILURE(status)) { return 0; } + // #13453: DecimalFormat wants the affixes from the pattern only (modMiddle, aka pattern modifier). + // Safe path: use fImmutablePatternModifier. + const Modifier* modifier = fImmutablePatternModifier->getModifier(signum, plural); + modifier->apply(outString, 0, 0, status); + if (U_FAILURE(status)) { return 0; } + return modifier->getPrefixLength(status); +} + +int32_t NumberFormatterImpl::getPrefixSuffixUnsafe(int8_t signum, StandardPlural::Form plural, + NumberStringBuilder& outString, UErrorCode& status) { + if (U_FAILURE(status)) { return 0; } + // #13453: DecimalFormat wants the affixes from the pattern only (modMiddle, aka pattern modifier). + // Unsafe path: use fPatternModifier. + fPatternModifier->setNumberProperties(signum, plural); + fPatternModifier->apply(outString, 0, 0, status); + if (U_FAILURE(status)) { return 0; } + return fPatternModifier->getPrefixLength(status); +} + +NumberFormatterImpl::NumberFormatterImpl(const MacroProps& macros, bool safe, UErrorCode& status) { fMicroPropsGenerator = macrosToMicroGenerator(macros, safe, status); } ////////// -const MicroPropsGenerator * -NumberFormatterImpl::macrosToMicroGenerator(const MacroProps ¯os, bool safe, UErrorCode &status) { - const MicroPropsGenerator *chain = &fMicros; +const MicroPropsGenerator* +NumberFormatterImpl::macrosToMicroGenerator(const MacroProps& macros, bool safe, UErrorCode& status) { + if (U_FAILURE(status)) { return nullptr; } + const MicroPropsGenerator* chain = &fMicros; // Check that macros is error-free before continuing. if (macros.copyErrorTo(status)) { @@ -189,18 +148,26 @@ NumberFormatterImpl::macrosToMicroGenerator(const MacroProps ¯os, bool safe, // TODO: Accept currency symbols from DecimalFormatSymbols? // Pre-compute a few values for efficiency. - bool isCurrency = unitIsCurrency(macros.unit); - bool isNoUnit = unitIsNoUnit(macros.unit); - bool isPercent = isNoUnit && unitIsPercent(macros.unit); - bool isPermille = isNoUnit && unitIsPermille(macros.unit); + bool isCurrency = utils::unitIsCurrency(macros.unit); + bool isNoUnit = utils::unitIsNoUnit(macros.unit); + bool isPercent = isNoUnit && utils::unitIsPercent(macros.unit); + bool isPermille = isNoUnit && utils::unitIsPermille(macros.unit); bool isCldrUnit = !isCurrency && !isNoUnit; - bool isAccounting = macros.sign == UNUM_SIGN_ACCOUNTING - || macros.sign == UNUM_SIGN_ACCOUNTING_ALWAYS - || macros.sign == UNUM_SIGN_ACCOUNTING_EXCEPT_ZERO; - CurrencyUnit currency(kDefaultCurrency, status); + bool isAccounting = + macros.sign == UNUM_SIGN_ACCOUNTING || macros.sign == UNUM_SIGN_ACCOUNTING_ALWAYS || + macros.sign == UNUM_SIGN_ACCOUNTING_EXCEPT_ZERO; + CurrencyUnit currency(nullptr, status); if (isCurrency) { currency = CurrencyUnit(macros.unit, status); // Restore CurrencyUnit from MeasureUnit } + const CurrencySymbols* currencySymbols; + if (macros.currencySymbols != nullptr) { + // Used by the DecimalFormat code path + currencySymbols = macros.currencySymbols; + } else { + fWarehouse.fCurrencySymbols = {currency, macros.locale, status}; + currencySymbols = &fWarehouse.fCurrencySymbols; + } UNumberUnitWidth unitWidth = UNUM_UNIT_WIDTH_SHORT; if (macros.unitWidth != UNUM_UNIT_WIDTH_COUNT) { unitWidth = macros.unitWidth; @@ -208,7 +175,7 @@ NumberFormatterImpl::macrosToMicroGenerator(const MacroProps ¯os, bool safe, // Select the numbering system. LocalPointer nsLocal; - const NumberingSystem *ns; + const NumberingSystem* ns; if (macros.symbols.isNumberingSystem()) { ns = macros.symbols.getNumberingSystem(); } else { @@ -217,7 +184,7 @@ NumberFormatterImpl::macrosToMicroGenerator(const MacroProps ¯os, bool safe, // Give ownership to the function scope. nsLocal.adoptInstead(ns); } - const char *nsName = U_SUCCESS(status) ? ns->getName() : "latn"; + const char* nsName = U_SUCCESS(status) ? ns->getName() : "latn"; // Resolve the symbols. Do this here because currency may need to customize them. if (macros.symbols.isDecimalFormatSymbols()) { @@ -232,21 +199,22 @@ NumberFormatterImpl::macrosToMicroGenerator(const MacroProps ¯os, bool safe, // If we are formatting currency, check for a currency-specific pattern. const char16_t* pattern = nullptr; if (isCurrency) { - CurrencyFormatInfoResult info = getCurrencyFormatInfo(macros.locale, currency.getSubtype(), status); + CurrencyFormatInfoResult info = getCurrencyFormatInfo( + macros.locale, currency.getSubtype(), status); if (info.exists) { pattern = info.pattern; // It's clunky to clone an object here, but this code is not frequently executed. - DecimalFormatSymbols* symbols = new DecimalFormatSymbols(*fMicros.symbols); + auto* symbols = new DecimalFormatSymbols(*fMicros.symbols); fMicros.symbols = symbols; fSymbols.adoptInstead(symbols); symbols->setSymbol( - DecimalFormatSymbols::ENumberFormatSymbol::kMonetarySeparatorSymbol, - UnicodeString(info.decimalSeparator), - FALSE); + DecimalFormatSymbols::ENumberFormatSymbol::kMonetarySeparatorSymbol, + UnicodeString(info.decimalSeparator), + FALSE); symbols->setSymbol( - DecimalFormatSymbols::ENumberFormatSymbol::kMonetaryGroupingSeparatorSymbol, - UnicodeString(info.groupingSeparator), - FALSE); + DecimalFormatSymbols::ENumberFormatSymbol::kMonetaryGroupingSeparatorSymbol, + UnicodeString(info.groupingSeparator), + FALSE); } } if (pattern == nullptr) { @@ -262,7 +230,7 @@ NumberFormatterImpl::macrosToMicroGenerator(const MacroProps ¯os, bool safe, } else { patternStyle = CLDR_PATTERN_STYLE_CURRENCY; } - pattern = getPatternForStyle(macros.locale, nsName, patternStyle, status); + pattern = utils::getPatternForStyle(macros.locale, nsName, patternStyle, status); } auto patternInfo = new ParsedPatternInfo(); fPatternInfo.adoptInstead(patternInfo); @@ -272,17 +240,31 @@ NumberFormatterImpl::macrosToMicroGenerator(const MacroProps ¯os, bool safe, /// START POPULATING THE DEFAULT MICROPROPS AND BUILDING THE MICROPROPS GENERATOR /// ///////////////////////////////////////////////////////////////////////////////////// - // Rounding strategy - if (!macros.rounder.isBogus()) { - fMicros.rounding = macros.rounder; - } else if (macros.notation.fType == Notation::NTN_COMPACT) { - fMicros.rounding = Rounder::integer().withMinDigits(2); - } else if (isCurrency) { - fMicros.rounding = Rounder::currency(UCURR_USAGE_STANDARD); - } else { - fMicros.rounding = Rounder::maxFraction(6); + // Multiplier + if (macros.scale.isValid()) { + fMicros.helpers.multiplier.setAndChain(macros.scale, chain); + chain = &fMicros.helpers.multiplier; } - fMicros.rounding.setLocaleData(currency, status); + + // Rounding strategy + Precision precision; + if (!macros.precision.isBogus()) { + precision = macros.precision; + } else if (macros.notation.fType == Notation::NTN_COMPACT) { + precision = Precision::integer().withMinDigits(2); + } else if (isCurrency) { + precision = Precision::currency(UCURR_USAGE_STANDARD); + } else { + precision = Precision::maxFraction(6); + } + UNumberFormatRoundingMode roundingMode; + if (macros.roundingMode != kDefaultMode) { + roundingMode = macros.roundingMode; + } else { + // Temporary until ICU 64 + roundingMode = precision.fRoundingMode; + } + fMicros.rounder = {precision, roundingMode, currency, status}; // Grouping strategy if (!macros.grouper.isBogus()) { @@ -306,7 +288,7 @@ NumberFormatterImpl::macrosToMicroGenerator(const MacroProps ¯os, bool safe, if (!macros.integerWidth.isBogus()) { fMicros.integerWidth = macros.integerWidth; } else { - fMicros.integerWidth = IntegerWidth::zeroFillTo(1); + fMicros.integerWidth = IntegerWidth::standard(); } // Sign display @@ -338,16 +320,18 @@ NumberFormatterImpl::macrosToMicroGenerator(const MacroProps ¯os, bool safe, // Middle modifier (patterns, positive/negative, currency symbols, percent) auto patternModifier = new MutablePatternModifier(false); fPatternModifier.adoptInstead(patternModifier); - patternModifier->setPatternInfo(fPatternInfo.getAlias()); + patternModifier->setPatternInfo( + macros.affixProvider != nullptr ? macros.affixProvider + : static_cast(fPatternInfo.getAlias())); patternModifier->setPatternAttributes(fMicros.sign, isPermille); if (patternModifier->needsPlurals()) { patternModifier->setSymbols( fMicros.symbols, - currency, + currencySymbols, unitWidth, resolvePluralRules(macros.rules, macros.locale, status)); } else { - patternModifier->setSymbols(fMicros.symbols, currency, unitWidth, nullptr); + patternModifier->setSymbols(fMicros.symbols, currencySymbols, unitWidth, nullptr); } if (safe) { fImmutablePatternModifier.adoptInstead(patternModifier->createImmutableAndChain(chain, status)); @@ -407,9 +391,9 @@ NumberFormatterImpl::macrosToMicroGenerator(const MacroProps ¯os, bool safe, return chain; } -const PluralRules * -NumberFormatterImpl::resolvePluralRules(const PluralRules *rulesPtr, const Locale &locale, - UErrorCode &status) { +const PluralRules* +NumberFormatterImpl::resolvePluralRules(const PluralRules* rulesPtr, const Locale& locale, + UErrorCode& status) { if (rulesPtr != nullptr) { return rulesPtr; } @@ -420,9 +404,9 @@ NumberFormatterImpl::resolvePluralRules(const PluralRules *rulesPtr, const Local return fRules.getAlias(); } -int32_t NumberFormatterImpl::microsToString(const MicroProps µs, DecimalQuantity &quantity, - NumberStringBuilder &string, UErrorCode &status) { - micros.rounding.apply(quantity, status); +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. @@ -439,8 +423,8 @@ int32_t NumberFormatterImpl::microsToString(const MicroProps µs, DecimalQua return length; } -int32_t NumberFormatterImpl::writeNumber(const MicroProps µs, DecimalQuantity &quantity, - NumberStringBuilder &string, UErrorCode &status) { +int32_t NumberFormatterImpl::writeNumber(const MicroProps& micros, DecimalQuantity& quantity, + NumberStringBuilder& string, UErrorCode& status) { int32_t length = 0; if (quantity.isInfinite()) { length += string.insert( @@ -480,8 +464,8 @@ int32_t NumberFormatterImpl::writeNumber(const MicroProps µs, DecimalQuanti return length; } -int32_t NumberFormatterImpl::writeIntegerDigits(const MicroProps µs, DecimalQuantity &quantity, - NumberStringBuilder &string, UErrorCode &status) { +int32_t NumberFormatterImpl::writeIntegerDigits(const MicroProps& micros, DecimalQuantity& quantity, + NumberStringBuilder& string, UErrorCode& status) { int length = 0; int integerCount = quantity.getUpperDisplayMagnitude() + 1; for (int i = 0; i < integerCount; i++) { @@ -499,21 +483,21 @@ int32_t NumberFormatterImpl::writeIntegerDigits(const MicroProps µs, Decima // Get and append the next digit value int8_t nextDigit = quantity.getDigit(i); - length += string.insert( - 0, getDigitFromSymbols(nextDigit, *micros.symbols), UNUM_INTEGER_FIELD, status); + length += utils::insertDigitFromSymbols( + string, 0, nextDigit, *micros.symbols, UNUM_INTEGER_FIELD, status); } return length; } -int32_t NumberFormatterImpl::writeFractionDigits(const MicroProps µs, DecimalQuantity &quantity, - NumberStringBuilder &string, UErrorCode &status) { +int32_t NumberFormatterImpl::writeFractionDigits(const MicroProps& micros, DecimalQuantity& quantity, + NumberStringBuilder& string, 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 += string.append( - getDigitFromSymbols(nextDigit, *micros.symbols), UNUM_FRACTION_FIELD, status); + length += utils::insertDigitFromSymbols( + string, string.length(), 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 cbc04ba30df..744fecec13f 100644 --- a/deps/icu-small/source/i18n/number_formatimpl.h +++ b/deps/icu-small/source/i18n/number_formatimpl.h @@ -3,7 +3,7 @@ #include "unicode/utypes.h" -#if !UCONFIG_NO_FORMATTING && !UPRV_INCOMPLETE_CPP11_SUPPORT +#if !UCONFIG_NO_FORMATTING #ifndef __NUMBER_FORMATIMPL_H__ #define __NUMBER_FORMATIMPL_H__ @@ -14,6 +14,7 @@ #include "number_patternmodifier.h" #include "number_longnames.h" #include "number_compact.h" +#include "number_microprops.h" U_NAMESPACE_BEGIN namespace number { namespace impl { @@ -37,10 +38,26 @@ class NumberFormatterImpl : public UMemory { applyStatic(const MacroProps ¯os, DecimalQuantity &inValue, NumberStringBuilder &outString, UErrorCode &status); + /** + * Prints only the prefix and suffix; used for DecimalFormat getters. + * + * @return The index into the output at which the prefix ends and the suffix starts; in other words, + * the prefix length. + */ + static int32_t getPrefixSuffixStatic(const MacroProps& macros, int8_t signum, + StandardPlural::Form plural, NumberStringBuilder& outString, + UErrorCode& status); + /** * Evaluates the "safe" MicroPropsGenerator created by "fromMacros". */ - void apply(DecimalQuantity &inValue, NumberStringBuilder &outString, UErrorCode &status) const; + void apply(DecimalQuantity& inValue, NumberStringBuilder& outString, UErrorCode& status) const; + + /** + * Like getPrefixSuffixStatic() but uses the safe compiled object. + */ + int32_t getPrefixSuffix(int8_t signum, StandardPlural::Form plural, NumberStringBuilder& outString, + UErrorCode& status) const; private: // Head of the MicroPropsGenerator linked list: @@ -50,21 +67,29 @@ class NumberFormatterImpl : public UMemory { MicroProps fMicros; // Other fields possibly used by the number formatting pipeline: - // TODO: Convert some of these LocalPointers to value objects to reduce the number of news? + // TODO: Convert more of these LocalPointers to value objects to reduce the number of news? LocalPointer fSymbols; LocalPointer fRules; LocalPointer fPatternInfo; LocalPointer fScientificHandler; - LocalPointer fPatternModifier; + LocalPointer fPatternModifier; LocalPointer fImmutablePatternModifier; LocalPointer fLongNameHandler; LocalPointer fCompactHandler; + // Value objects possibly used by the number formatting pipeline: + struct Warehouse { + CurrencySymbols fCurrencySymbols; + } fWarehouse; + NumberFormatterImpl(const MacroProps ¯os, bool safe, UErrorCode &status); void applyUnsafe(DecimalQuantity &inValue, NumberStringBuilder &outString, UErrorCode &status); + int32_t getPrefixSuffixUnsafe(int8_t signum, StandardPlural::Form plural, + NumberStringBuilder& outString, UErrorCode& status); + /** * If rulesPtr is non-null, return it. Otherwise, return a PluralRules owned by this object for the * specified locale, creating it if necessary. diff --git a/deps/icu-small/source/i18n/number_grouping.cpp b/deps/icu-small/source/i18n/number_grouping.cpp index a2b1bbd6b33..4a1cceb4994 100644 --- a/deps/icu-small/source/i18n/number_grouping.cpp +++ b/deps/icu-small/source/i18n/number_grouping.cpp @@ -3,7 +3,7 @@ #include "unicode/utypes.h" -#if !UCONFIG_NO_FORMATTING && !UPRV_INCOMPLETE_CPP11_SUPPORT +#if !UCONFIG_NO_FORMATTING #include "unicode/numberformatter.h" #include "number_patternstring.h" @@ -37,20 +37,33 @@ int16_t getMinGroupingForLocale(const Locale& locale) { Grouper Grouper::forStrategy(UGroupingStrategy grouping) { switch (grouping) { case UNUM_GROUPING_OFF: - return {-1, -1, -2}; + return {-1, -1, -2, grouping}; case UNUM_GROUPING_AUTO: - return {-2, -2, -2}; + return {-2, -2, -2, grouping}; case UNUM_GROUPING_MIN2: - return {-2, -2, -3}; + return {-2, -2, -3, grouping}; case UNUM_GROUPING_ON_ALIGNED: - return {-4, -4, 1}; + return {-4, -4, 1, grouping}; case UNUM_GROUPING_THOUSANDS: - return {3, 3, 1}; + return {3, 3, 1, grouping}; default: U_ASSERT(FALSE); + return {}; // return a value: silence compiler warning } } +Grouper Grouper::forProperties(const DecimalFormatProperties& properties) { + if (!properties.groupingUsed) { + return forStrategy(UNUM_GROUPING_OFF); + } + auto grouping1 = static_cast(properties.groupingSize); + auto grouping2 = static_cast(properties.secondaryGroupingSize); + auto minGrouping = static_cast(properties.minimumGroupingDigits); + grouping1 = grouping1 > 0 ? grouping1 : grouping2 > 0 ? grouping2 : grouping1; + grouping2 = grouping2 > 0 ? grouping2 : grouping1; + return {grouping1, grouping2, minGrouping, UNUM_GROUPING_COUNT}; +} + void Grouper::setLocaleData(const impl::ParsedPatternInfo &patternInfo, const Locale& locale) { if (fGrouping1 != -2 && fGrouping2 != -4) { return; @@ -86,4 +99,12 @@ bool Grouper::groupAtPosition(int32_t position, const impl::DecimalQuantity &val && value.getUpperDisplayMagnitude() - fGrouping1 + 1 >= fMinGrouping; } +int16_t Grouper::getPrimary() const { + return fGrouping1; +} + +int16_t Grouper::getSecondary() const { + return fGrouping2; +} + #endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/deps/icu-small/source/i18n/number_integerwidth.cpp b/deps/icu-small/source/i18n/number_integerwidth.cpp index 4a612273f5e..6416b292982 100644 --- a/deps/icu-small/source/i18n/number_integerwidth.cpp +++ b/deps/icu-small/source/i18n/number_integerwidth.cpp @@ -3,7 +3,7 @@ #include "unicode/utypes.h" -#if !UCONFIG_NO_FORMATTING && !UPRV_INCOMPLETE_CPP11_SUPPORT +#if !UCONFIG_NO_FORMATTING #include "unicode/numberformatter.h" #include "number_types.h" @@ -13,14 +13,15 @@ using namespace icu; using namespace icu::number; using namespace icu::number::impl; -IntegerWidth::IntegerWidth(digits_t minInt, digits_t maxInt) { +IntegerWidth::IntegerWidth(digits_t minInt, digits_t maxInt, bool formatFailIfMoreThanMaxDigits) { fUnion.minMaxInt.fMinInt = minInt; fUnion.minMaxInt.fMaxInt = maxInt; + fUnion.minMaxInt.fFormatFailIfMoreThanMaxDigits = formatFailIfMoreThanMaxDigits; } IntegerWidth IntegerWidth::zeroFillTo(int32_t minInt) { if (minInt >= 0 && minInt <= kMaxIntFracSig) { - return {static_cast(minInt), -1}; + return {static_cast(minInt), -1, false}; } else { return {U_NUMBER_ARG_OUTOFBOUNDS_ERROR}; } @@ -30,22 +31,37 @@ IntegerWidth IntegerWidth::truncateAt(int32_t maxInt) { if (fHasError) { return *this; } // No-op on error digits_t minInt = fUnion.minMaxInt.fMinInt; if (maxInt >= 0 && maxInt <= kMaxIntFracSig && minInt <= maxInt) { - return {minInt, static_cast(maxInt)}; + return {minInt, static_cast(maxInt), false}; } else if (maxInt == -1) { - return {minInt, -1}; + return {minInt, -1, false}; } else { return {U_NUMBER_ARG_OUTOFBOUNDS_ERROR}; } } -void IntegerWidth::apply(impl::DecimalQuantity &quantity, UErrorCode &status) const { +void IntegerWidth::apply(impl::DecimalQuantity& quantity, UErrorCode& status) const { if (fHasError) { status = U_ILLEGAL_ARGUMENT_ERROR; } else if (fUnion.minMaxInt.fMaxInt == -1) { quantity.setIntegerLength(fUnion.minMaxInt.fMinInt, INT32_MAX); } else { + // Enforce the backwards-compatibility feature "FormatFailIfMoreThanMaxDigits" + if (fUnion.minMaxInt.fFormatFailIfMoreThanMaxDigits && + fUnion.minMaxInt.fMaxInt < quantity.getMagnitude()) { + status = U_ILLEGAL_ARGUMENT_ERROR; + } quantity.setIntegerLength(fUnion.minMaxInt.fMinInt, fUnion.minMaxInt.fMaxInt); } } +bool IntegerWidth::operator==(const IntegerWidth& other) const { + // Private operator==; do error and bogus checking first! + U_ASSERT(!fHasError); + U_ASSERT(!other.fHasError); + U_ASSERT(!isBogus()); + U_ASSERT(!other.isBogus()); + return fUnion.minMaxInt.fMinInt == other.fUnion.minMaxInt.fMinInt && + fUnion.minMaxInt.fMaxInt == other.fUnion.minMaxInt.fMaxInt; +} + #endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/deps/icu-small/source/i18n/number_longnames.cpp b/deps/icu-small/source/i18n/number_longnames.cpp index 5c363442e7c..26f9af4c9bd 100644 --- a/deps/icu-small/source/i18n/number_longnames.cpp +++ b/deps/icu-small/source/i18n/number_longnames.cpp @@ -3,7 +3,7 @@ #include "unicode/utypes.h" -#if !UCONFIG_NO_FORMATTING && !UPRV_INCOMPLETE_CPP11_SUPPORT +#if !UCONFIG_NO_FORMATTING #include "unicode/simpleformatter.h" #include "unicode/ures.h" @@ -11,6 +11,7 @@ #include "charstr.h" #include "uresimp.h" #include "number_longnames.h" +#include "number_microprops.h" #include #include "cstring.h" @@ -260,8 +261,8 @@ void LongNameHandler::processQuantity(DecimalQuantity &quantity, MicroProps &mic parent->processQuantity(quantity, micros, status); // TODO: Avoid the copy here? DecimalQuantity copy(quantity); - micros.rounding.apply(copy, status); - micros.modOuter = &fModifiers[copy.getStandardPlural(rules)]; + micros.rounder.apply(copy, status); + micros.modOuter = &fModifiers[utils::getStandardPlural(rules, copy)]; } #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 8738bb99e7d..1d1e7dd3e86 100644 --- a/deps/icu-small/source/i18n/number_longnames.h +++ b/deps/icu-small/source/i18n/number_longnames.h @@ -3,7 +3,7 @@ #include "unicode/utypes.h" -#if !UCONFIG_NO_FORMATTING && !UPRV_INCOMPLETE_CPP11_SUPPORT +#if !UCONFIG_NO_FORMATTING #ifndef __NUMBER_LONGNAMES_H__ #define __NUMBER_LONGNAMES_H__ diff --git a/deps/icu-small/source/i18n/number_mapper.cpp b/deps/icu-small/source/i18n/number_mapper.cpp new file mode 100644 index 00000000000..d260632f93b --- /dev/null +++ b/deps/icu-small/source/i18n/number_mapper.cpp @@ -0,0 +1,502 @@ +// © 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 "number_mapper.h" +#include "number_patternstring.h" +#include "unicode/errorcode.h" +#include "number_utils.h" +#include "number_currencysymbols.h" + +using namespace icu; +using namespace icu::number; +using namespace icu::number::impl; + + +UnlocalizedNumberFormatter NumberPropertyMapper::create(const DecimalFormatProperties& properties, + const DecimalFormatSymbols& symbols, + DecimalFormatWarehouse& warehouse, + UErrorCode& status) { + return NumberFormatter::with().macros(oldToNew(properties, symbols, warehouse, nullptr, status)); +} + +UnlocalizedNumberFormatter NumberPropertyMapper::create(const DecimalFormatProperties& properties, + const DecimalFormatSymbols& symbols, + DecimalFormatWarehouse& warehouse, + DecimalFormatProperties& exportedProperties, + UErrorCode& status) { + return NumberFormatter::with().macros( + oldToNew( + properties, symbols, warehouse, &exportedProperties, status)); +} + +MacroProps NumberPropertyMapper::oldToNew(const DecimalFormatProperties& properties, + const DecimalFormatSymbols& symbols, + DecimalFormatWarehouse& warehouse, + DecimalFormatProperties* exportedProperties, + UErrorCode& status) { + MacroProps macros; + Locale locale = symbols.getLocale(); + + ///////////// + // SYMBOLS // + ///////////// + + macros.symbols.setTo(symbols); + + ////////////////// + // PLURAL RULES // + ////////////////// + + if (!properties.currencyPluralInfo.fPtr.isNull()) { + macros.rules = properties.currencyPluralInfo.fPtr->getPluralRules(); + } + + ///////////// + // AFFIXES // + ///////////// + + AffixPatternProvider* affixProvider; + if (properties.currencyPluralInfo.fPtr.isNull()) { + warehouse.currencyPluralInfoAPP.setToBogus(); + warehouse.propertiesAPP.setTo(properties, status); + affixProvider = &warehouse.propertiesAPP; + } else { + warehouse.currencyPluralInfoAPP.setTo(*properties.currencyPluralInfo.fPtr, properties, status); + warehouse.propertiesAPP.setToBogus(); + affixProvider = &warehouse.currencyPluralInfoAPP; + } + macros.affixProvider = affixProvider; + + /////////// + // UNITS // + /////////// + + bool useCurrency = ( + !properties.currency.isNull() || !properties.currencyPluralInfo.fPtr.isNull() || + !properties.currencyUsage.isNull() || affixProvider->hasCurrencySign()); + CurrencyUnit currency = resolveCurrency(properties, locale, status); + UCurrencyUsage currencyUsage = properties.currencyUsage.getOrDefault(UCURR_USAGE_STANDARD); + if (useCurrency) { + // NOTE: Slicing is OK. + macros.unit = currency; // NOLINT + } + warehouse.currencySymbols = {currency, locale, symbols, status}; + macros.currencySymbols = &warehouse.currencySymbols; + + /////////////////////// + // ROUNDING STRATEGY // + /////////////////////// + + int32_t maxInt = properties.maximumIntegerDigits; + int32_t minInt = properties.minimumIntegerDigits; + int32_t maxFrac = properties.maximumFractionDigits; + int32_t minFrac = properties.minimumFractionDigits; + int32_t minSig = properties.minimumSignificantDigits; + int32_t maxSig = properties.maximumSignificantDigits; + double roundingIncrement = properties.roundingIncrement; + RoundingMode roundingMode = properties.roundingMode.getOrDefault(UNUM_ROUND_HALFEVEN); + bool explicitMinMaxFrac = minFrac != -1 || maxFrac != -1; + bool explicitMinMaxSig = minSig != -1 || maxSig != -1; + // Resolve min/max frac for currencies, required for the validation logic and for when minFrac or + // maxFrac was + // set (but not both) on a currency instance. + // NOTE: Increments are handled in "Precision.constructCurrency()". + if (useCurrency && (minFrac == -1 || maxFrac == -1)) { + int32_t digits = ucurr_getDefaultFractionDigitsForUsage( + currency.getISOCurrency(), currencyUsage, &status); + if (minFrac == -1 && maxFrac == -1) { + minFrac = digits; + maxFrac = digits; + } else if (minFrac == -1) { + minFrac = std::min(maxFrac, digits); + } else /* if (maxFrac == -1) */ { + maxFrac = std::max(minFrac, digits); + } + } + // Validate min/max int/frac. + // For backwards compatibility, minimum overrides maximum if the two conflict. + // The following logic ensures that there is always a minimum of at least one digit. + if (minInt == 0 && maxFrac != 0) { + // Force a digit after the decimal point. + minFrac = minFrac <= 0 ? 1 : minFrac; + maxFrac = maxFrac < 0 ? -1 : maxFrac < minFrac ? minFrac : maxFrac; + minInt = 0; + maxInt = maxInt < 0 ? -1 : maxInt > kMaxIntFracSig ? -1 : maxInt; + } else { + // Force a digit before the decimal point. + minFrac = minFrac < 0 ? 0 : minFrac; + maxFrac = maxFrac < 0 ? -1 : maxFrac < minFrac ? minFrac : maxFrac; + minInt = minInt <= 0 ? 1 : minInt > kMaxIntFracSig ? 1 : minInt; + maxInt = maxInt < 0 ? -1 : maxInt < minInt ? minInt : maxInt > kMaxIntFracSig ? -1 : maxInt; + } + Precision precision; + if (!properties.currencyUsage.isNull()) { + precision = Precision::constructCurrency(currencyUsage).withCurrency(currency); + } else if (roundingIncrement != 0.0) { + precision = Precision::constructIncrement(roundingIncrement, minFrac); + } else if (explicitMinMaxSig) { + minSig = minSig < 1 ? 1 : minSig > kMaxIntFracSig ? kMaxIntFracSig : minSig; + maxSig = maxSig < 0 ? kMaxIntFracSig : maxSig < minSig ? minSig : maxSig > kMaxIntFracSig + ? kMaxIntFracSig : maxSig; + precision = Precision::constructSignificant(minSig, maxSig); + } else if (explicitMinMaxFrac) { + precision = Precision::constructFraction(minFrac, maxFrac); + } else if (useCurrency) { + precision = Precision::constructCurrency(currencyUsage); + } + if (!precision.isBogus()) { + precision = precision.withMode(roundingMode); + macros.precision = precision; + } + + /////////////////// + // INTEGER WIDTH // + /////////////////// + + macros.integerWidth = IntegerWidth( + static_cast(minInt), + static_cast(maxInt), + properties.formatFailIfMoreThanMaxDigits); + + /////////////////////// + // GROUPING STRATEGY // + /////////////////////// + + macros.grouper = Grouper::forProperties(properties); + + ///////////// + // PADDING // + ///////////// + + if (properties.formatWidth != -1) { + macros.padder = Padder::forProperties(properties); + } + + /////////////////////////////// + // DECIMAL MARK ALWAYS SHOWN // + /////////////////////////////// + + macros.decimal = properties.decimalSeparatorAlwaysShown ? UNUM_DECIMAL_SEPARATOR_ALWAYS + : UNUM_DECIMAL_SEPARATOR_AUTO; + + /////////////////////// + // SIGN ALWAYS SHOWN // + /////////////////////// + + macros.sign = properties.signAlwaysShown ? UNUM_SIGN_ALWAYS : UNUM_SIGN_AUTO; + + ///////////////////////// + // SCIENTIFIC NOTATION // + ///////////////////////// + + if (properties.minimumExponentDigits != -1) { + // Scientific notation is required. + // This whole section feels like a hack, but it is needed for regression tests. + // The mapping from property bag to scientific notation is nontrivial due to LDML rules. + if (maxInt > 8) { + // But #13110: The maximum of 8 digits has unknown origins and is not in the spec. + // If maxInt is greater than 8, it is set to minInt, even if minInt is greater than 8. + maxInt = minInt; + macros.integerWidth = IntegerWidth::zeroFillTo(minInt).truncateAt(maxInt); + } else if (maxInt > minInt && minInt > 1) { + // Bug #13289: if maxInt > minInt > 1, then minInt should be 1. + minInt = 1; + macros.integerWidth = IntegerWidth::zeroFillTo(minInt).truncateAt(maxInt); + } + int engineering = maxInt < 0 ? -1 : maxInt; + macros.notation = ScientificNotation( + // Engineering interval: + static_cast(engineering), + // Enforce minimum integer digits (for patterns like "000.00E0"): + (engineering == minInt), + // Minimum exponent digits: + static_cast(properties.minimumExponentDigits), + // Exponent sign always shown: + properties.exponentSignAlwaysShown ? UNUM_SIGN_ALWAYS : UNUM_SIGN_AUTO); + // Scientific notation also involves overriding the rounding mode. + // 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. + int minInt_ = properties.minimumIntegerDigits; + int minFrac_ = properties.minimumFractionDigits; + int maxFrac_ = properties.maximumFractionDigits; + if (minInt_ == 0 && maxFrac_ == 0) { + // Patterns like "#E0" and "##E0", which mean no rounding! + macros.precision = Precision::unlimited().withMode(roundingMode); + } else if (minInt_ == 0 && minFrac_ == 0) { + // 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); + } + } + } + + ////////////////////// + // COMPACT NOTATION // + ////////////////////// + + if (!properties.compactStyle.isNull()) { + if (properties.compactStyle.getNoError() == UNumberCompactStyle::UNUM_LONG) { + macros.notation = Notation::compactLong(); + } else { + macros.notation = Notation::compactShort(); + } + // Do not forward the affix provider. + macros.affixProvider = nullptr; + } + + ///////////////// + // MULTIPLIERS // + ///////////////// + + macros.scale = scaleFromProperties(properties); + + ////////////////////// + // PROPERTY EXPORTS // + ////////////////////// + + if (exportedProperties != nullptr) { + + exportedProperties->currency = currency; + exportedProperties->roundingMode = roundingMode; + exportedProperties->minimumIntegerDigits = minInt; + exportedProperties->maximumIntegerDigits = maxInt == -1 ? INT32_MAX : maxInt; + + Precision rounding_; + if (precision.fType == Precision::PrecisionType::RND_CURRENCY) { + rounding_ = precision.withCurrency(currency, status); + } else { + rounding_ = precision; + } + int minFrac_ = minFrac; + int maxFrac_ = maxFrac; + int minSig_ = minSig; + int maxSig_ = maxSig; + double increment_ = 0.0; + if (rounding_.fType == Precision::PrecisionType::RND_FRACTION) { + minFrac_ = rounding_.fUnion.fracSig.fMinFrac; + maxFrac_ = rounding_.fUnion.fracSig.fMaxFrac; + } else if (rounding_.fType == Precision::PrecisionType::RND_INCREMENT) { + increment_ = rounding_.fUnion.increment.fIncrement; + minFrac_ = rounding_.fUnion.increment.fMinFrac; + maxFrac_ = rounding_.fUnion.increment.fMinFrac; + } else if (rounding_.fType == Precision::PrecisionType::RND_SIGNIFICANT) { + minSig_ = rounding_.fUnion.fracSig.fMinSig; + maxSig_ = rounding_.fUnion.fracSig.fMaxSig; + } + + exportedProperties->minimumFractionDigits = minFrac_; + exportedProperties->maximumFractionDigits = maxFrac_; + exportedProperties->minimumSignificantDigits = minSig_; + exportedProperties->maximumSignificantDigits = maxSig_; + exportedProperties->roundingIncrement = increment_; + } + + return macros; +} + + +void PropertiesAffixPatternProvider::setTo(const DecimalFormatProperties& properties, UErrorCode&) { + fBogus = false; + + // There are two ways to set affixes in DecimalFormat: via the pattern string (applyPattern), and via the + // explicit setters (setPositivePrefix and friends). The way to resolve the settings is as follows: + // + // 1) If the explicit setting is present for the field, use it. + // 2) Otherwise, follows UTS 35 rules based on the pattern string. + // + // Importantly, the explicit setters affect only the one field they override. If you set the positive + // prefix, that should not affect the negative prefix. Since it is impossible for the user of this class + // to know whether the origin for a string was the override or the pattern, we have to say that we always + // have a negative subpattern and perform all resolution logic here. + + // Convenience: Extract the properties into local variables. + // Variables are named with three chars: [p/n][p/s][o/p] + // [p/n] => p for positive, n for negative + // [p/s] => p for prefix, s for suffix + // [o/p] => o for escaped custom override string, p for pattern string + UnicodeString ppo = AffixUtils::escape(properties.positivePrefix); + UnicodeString pso = AffixUtils::escape(properties.positiveSuffix); + UnicodeString npo = AffixUtils::escape(properties.negativePrefix); + UnicodeString nso = AffixUtils::escape(properties.negativeSuffix); + const UnicodeString& ppp = properties.positivePrefixPattern; + const UnicodeString& psp = properties.positiveSuffixPattern; + const UnicodeString& npp = properties.negativePrefixPattern; + const UnicodeString& nsp = properties.negativeSuffixPattern; + + if (!properties.positivePrefix.isBogus()) { + posPrefix = ppo; + } else if (!ppp.isBogus()) { + posPrefix = ppp; + } else { + // UTS 35: Default positive prefix is empty string. + posPrefix = u""; + } + + if (!properties.positiveSuffix.isBogus()) { + posSuffix = pso; + } else if (!psp.isBogus()) { + posSuffix = psp; + } else { + // UTS 35: Default positive suffix is empty string. + posSuffix = u""; + } + + if (!properties.negativePrefix.isBogus()) { + negPrefix = npo; + } else if (!npp.isBogus()) { + negPrefix = npp; + } else { + // UTS 35: Default negative prefix is "-" with positive prefix. + // Important: We prepend the "-" to the pattern, not the override! + negPrefix = ppp.isBogus() ? u"-" : u"-" + ppp; + } + + if (!properties.negativeSuffix.isBogus()) { + negSuffix = nso; + } else if (!nsp.isBogus()) { + negSuffix = nsp; + } else { + // UTS 35: Default negative prefix is the positive prefix. + negSuffix = psp.isBogus() ? u"" : psp; + } +} + +char16_t PropertiesAffixPatternProvider::charAt(int flags, int i) const { + return getStringInternal(flags).charAt(i); +} + +int PropertiesAffixPatternProvider::length(int flags) const { + return getStringInternal(flags).length(); +} + +UnicodeString PropertiesAffixPatternProvider::getString(int32_t flags) const { + return getStringInternal(flags); +} + +const UnicodeString& PropertiesAffixPatternProvider::getStringInternal(int32_t flags) const { + bool prefix = (flags & AFFIX_PREFIX) != 0; + bool negative = (flags & AFFIX_NEGATIVE_SUBPATTERN) != 0; + if (prefix && negative) { + return negPrefix; + } else if (prefix) { + return posPrefix; + } else if (negative) { + return negSuffix; + } else { + return posSuffix; + } +} + +bool PropertiesAffixPatternProvider::positiveHasPlusSign() const { + // TODO: Change the internal APIs to propagate out the error? + ErrorCode localStatus; + return AffixUtils::containsType(posPrefix, TYPE_PLUS_SIGN, localStatus) || + AffixUtils::containsType(posSuffix, TYPE_PLUS_SIGN, localStatus); +} + +bool PropertiesAffixPatternProvider::hasNegativeSubpattern() const { + // See comments in the constructor for more information on why this is always true. + return true; +} + +bool PropertiesAffixPatternProvider::negativeHasMinusSign() const { + ErrorCode localStatus; + return AffixUtils::containsType(negPrefix, TYPE_MINUS_SIGN, localStatus) || + AffixUtils::containsType(negSuffix, TYPE_MINUS_SIGN, localStatus); +} + +bool PropertiesAffixPatternProvider::hasCurrencySign() const { + ErrorCode localStatus; + return AffixUtils::hasCurrencySymbols(posPrefix, localStatus) || + AffixUtils::hasCurrencySymbols(posSuffix, localStatus) || + AffixUtils::hasCurrencySymbols(negPrefix, localStatus) || + AffixUtils::hasCurrencySymbols(negSuffix, localStatus); +} + +bool PropertiesAffixPatternProvider::containsSymbolType(AffixPatternType type, UErrorCode& status) const { + return AffixUtils::containsType(posPrefix, type, status) || + AffixUtils::containsType(posSuffix, type, status) || + AffixUtils::containsType(negPrefix, type, status) || + AffixUtils::containsType(negSuffix, type, status); +} + +bool PropertiesAffixPatternProvider::hasBody() const { + return true; +} + + +void CurrencyPluralInfoAffixProvider::setTo(const CurrencyPluralInfo& cpi, + const DecimalFormatProperties& properties, + UErrorCode& status) { + // We need to use a PropertiesAffixPatternProvider, not the simpler version ParsedPatternInfo, + // because user-specified affix overrides still need to work. + fBogus = false; + DecimalFormatProperties pluralProperties(properties); + for (int32_t plural = 0; plural < StandardPlural::COUNT; plural++) { + const char* keyword = StandardPlural::getKeyword(static_cast(plural)); + UnicodeString patternString; + patternString = cpi.getCurrencyPluralPattern(keyword, patternString); + PatternParser::parseToExistingProperties( + patternString, + pluralProperties, + IGNORE_ROUNDING_NEVER, + status); + affixesByPlural[plural].setTo(pluralProperties, status); + } +} + +char16_t CurrencyPluralInfoAffixProvider::charAt(int32_t flags, int32_t i) const { + int32_t pluralOrdinal = (flags & AFFIX_PLURAL_MASK); + return affixesByPlural[pluralOrdinal].charAt(flags, i); +} + +int32_t CurrencyPluralInfoAffixProvider::length(int32_t flags) const { + int32_t pluralOrdinal = (flags & AFFIX_PLURAL_MASK); + return affixesByPlural[pluralOrdinal].length(flags); +} + +UnicodeString CurrencyPluralInfoAffixProvider::getString(int32_t flags) const { + int32_t pluralOrdinal = (flags & AFFIX_PLURAL_MASK); + return affixesByPlural[pluralOrdinal].getString(flags); +} + +bool CurrencyPluralInfoAffixProvider::positiveHasPlusSign() const { + return affixesByPlural[StandardPlural::OTHER].positiveHasPlusSign(); +} + +bool CurrencyPluralInfoAffixProvider::hasNegativeSubpattern() const { + return affixesByPlural[StandardPlural::OTHER].hasNegativeSubpattern(); +} + +bool CurrencyPluralInfoAffixProvider::negativeHasMinusSign() const { + return affixesByPlural[StandardPlural::OTHER].negativeHasMinusSign(); +} + +bool CurrencyPluralInfoAffixProvider::hasCurrencySign() const { + return affixesByPlural[StandardPlural::OTHER].hasCurrencySign(); +} + +bool CurrencyPluralInfoAffixProvider::containsSymbolType(AffixPatternType type, UErrorCode& status) const { + return affixesByPlural[StandardPlural::OTHER].containsSymbolType(type, status); +} + +bool CurrencyPluralInfoAffixProvider::hasBody() const { + return affixesByPlural[StandardPlural::OTHER].hasBody(); +} + + +#endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/deps/icu-small/source/i18n/number_mapper.h b/deps/icu-small/source/i18n/number_mapper.h new file mode 100644 index 00000000000..82c5711c8d0 --- /dev/null +++ b/deps/icu-small/source/i18n/number_mapper.h @@ -0,0 +1,206 @@ +// © 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 __NUMBER_MAPPER_H__ +#define __NUMBER_MAPPER_H__ + +#include +#include "number_types.h" +#include "unicode/currpinf.h" +#include "standardplural.h" +#include "number_patternstring.h" +#include "number_currencysymbols.h" +#include "numparse_impl.h" + +U_NAMESPACE_BEGIN +namespace number { +namespace impl { + + +class PropertiesAffixPatternProvider : public AffixPatternProvider, public UMemory { + public: + bool isBogus() const { + return fBogus; + } + + void setToBogus() { + fBogus = true; + } + + void setTo(const DecimalFormatProperties& properties, UErrorCode& status); + + PropertiesAffixPatternProvider() = default; // puts instance in valid but undefined state + + PropertiesAffixPatternProvider(const DecimalFormatProperties& properties, UErrorCode& status) { + setTo(properties, status); + } + + // AffixPatternProvider Methods: + + char16_t charAt(int32_t flags, int32_t i) const U_OVERRIDE; + + int32_t length(int32_t flags) const U_OVERRIDE; + + UnicodeString getString(int32_t flags) const U_OVERRIDE; + + bool hasCurrencySign() const U_OVERRIDE; + + bool positiveHasPlusSign() const U_OVERRIDE; + + bool hasNegativeSubpattern() const U_OVERRIDE; + + bool negativeHasMinusSign() const U_OVERRIDE; + + bool containsSymbolType(AffixPatternType, UErrorCode&) const U_OVERRIDE; + + bool hasBody() const U_OVERRIDE; + + private: + UnicodeString posPrefix; + UnicodeString posSuffix; + UnicodeString negPrefix; + UnicodeString negSuffix; + + const UnicodeString& getStringInternal(int32_t flags) const; + + bool fBogus{true}; +}; + + +class CurrencyPluralInfoAffixProvider : public AffixPatternProvider, public UMemory { + public: + bool isBogus() const { + return fBogus; + } + + void setToBogus() { + fBogus = true; + } + + void setTo(const CurrencyPluralInfo& cpi, const DecimalFormatProperties& properties, + UErrorCode& status); + + // AffixPatternProvider Methods: + + char16_t charAt(int32_t flags, int32_t i) const U_OVERRIDE; + + int32_t length(int32_t flags) const U_OVERRIDE; + + UnicodeString getString(int32_t flags) const U_OVERRIDE; + + bool hasCurrencySign() const U_OVERRIDE; + + bool positiveHasPlusSign() const U_OVERRIDE; + + bool hasNegativeSubpattern() const U_OVERRIDE; + + bool negativeHasMinusSign() const U_OVERRIDE; + + bool containsSymbolType(AffixPatternType, UErrorCode&) const U_OVERRIDE; + + bool hasBody() const U_OVERRIDE; + + private: + PropertiesAffixPatternProvider affixesByPlural[StandardPlural::COUNT]; + + bool fBogus{true}; +}; + + +/** + * A struct for ownership of a few objects needed for formatting. + */ +struct DecimalFormatWarehouse { + PropertiesAffixPatternProvider propertiesAPP; + CurrencyPluralInfoAffixProvider currencyPluralInfoAPP; + CurrencySymbols currencySymbols; +}; + + +/** +* Internal fields for DecimalFormat. +* TODO: Make some of these fields by value instead of by LocalPointer? +*/ +struct DecimalFormatFields : public UMemory { + /** The property bag corresponding to user-specified settings and settings from the pattern string. */ + LocalPointer properties; + + /** The symbols for the current locale. */ + LocalPointer symbols; + + /** + * The pre-computed formatter object. Setters cause this to be re-computed atomically. The {@link + * #format} method uses the formatter directly without needing to synchronize. + */ + LocalPointer formatter; + + /** The lazy-computed parser for .parse() */ + std::atomic<::icu::numparse::impl::NumberParserImpl*> atomicParser = {}; + + /** The lazy-computed parser for .parseCurrency() */ + std::atomic<::icu::numparse::impl::NumberParserImpl*> atomicCurrencyParser = {}; + + /** Small object ownership warehouse for the formatter and parser */ + DecimalFormatWarehouse warehouse; + + /** The effective properties as exported from the formatter object. Used by some getters. */ + LocalPointer exportedProperties; + + // Data for fastpath + bool canUseFastFormat = false; + struct FastFormatData { + char16_t cpZero; + char16_t cpGroupingSeparator; + char16_t cpMinusSign; + int8_t minInt; + int8_t maxInt; + } fastData; +}; + + +/** + * Utilities for converting between a DecimalFormatProperties and a MacroProps. + */ +class NumberPropertyMapper { + public: + /** Convenience method to create a NumberFormatter directly from Properties. */ + static UnlocalizedNumberFormatter create(const DecimalFormatProperties& properties, + const DecimalFormatSymbols& symbols, + DecimalFormatWarehouse& warehouse, UErrorCode& status); + + /** Convenience method to create a NumberFormatter directly from Properties. */ + static UnlocalizedNumberFormatter create(const DecimalFormatProperties& properties, + const DecimalFormatSymbols& symbols, + DecimalFormatWarehouse& warehouse, + DecimalFormatProperties& exportedProperties, + UErrorCode& status); + + /** + * Creates a new {@link MacroProps} object based on the content of a {@link DecimalFormatProperties} + * object. In other words, maps Properties to MacroProps. This function is used by the + * JDK-compatibility API to call into the ICU 60 fluent number formatting pipeline. + * + * @param properties + * The property bag to be mapped. + * @param symbols + * The symbols associated with the property bag. + * @param exportedProperties + * A property bag in which to store validated properties. Used by some DecimalFormat + * getters. + * @return A new MacroProps containing all of the information in the Properties. + */ + static MacroProps oldToNew(const DecimalFormatProperties& properties, + const DecimalFormatSymbols& symbols, DecimalFormatWarehouse& warehouse, + DecimalFormatProperties* exportedProperties, UErrorCode& status); +}; + + +} // namespace impl +} // namespace numparse +U_NAMESPACE_END + +#endif //__NUMBER_MAPPER_H__ +#endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/deps/icu-small/source/i18n/number_microprops.h b/deps/icu-small/source/i18n/number_microprops.h new file mode 100644 index 00000000000..daa887bb0dd --- /dev/null +++ b/deps/icu-small/source/i18n/number_microprops.h @@ -0,0 +1,82 @@ +// © 2017 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 __NUMBER_MICROPROPS_H__ +#define __NUMBER_MICROPROPS_H__ + +// TODO: minimize includes +#include "unicode/numberformatter.h" +#include "number_types.h" +#include "number_decimalquantity.h" +#include "number_scientific.h" +#include "number_patternstring.h" +#include "number_modifiers.h" +#include "number_multiplier.h" +#include "number_roundingutils.h" +#include "decNumber.h" +#include "charstr.h" + +U_NAMESPACE_BEGIN namespace number { +namespace impl { + +struct MicroProps : public MicroPropsGenerator { + + // NOTE: All of these fields are properly initialized in NumberFormatterImpl. + RoundingImpl rounder; + Grouper grouping; + Padder padding; + IntegerWidth integerWidth; + UNumberSignDisplay sign; + UNumberDecimalSeparatorDisplay decimal; + bool useCurrency; + + // Note: This struct has no direct ownership of the following pointers. + const DecimalFormatSymbols* symbols; + const Modifier* modOuter; + const Modifier* modMiddle; + const Modifier* modInner; + + // The following "helper" fields may optionally be used during the MicroPropsGenerator. + // They live here to retain memory. + struct { + ScientificModifier scientificModifier; + EmptyModifier emptyWeakModifier{false}; + EmptyModifier emptyStrongModifier{true}; + MultiplierFormatHandler multiplier; + } helpers; + + + MicroProps() = default; + + MicroProps(const MicroProps& other) = default; + + MicroProps& operator=(const MicroProps& other) = default; + + void processQuantity(DecimalQuantity&, MicroProps& micros, UErrorCode& status) const U_OVERRIDE { + (void) status; + if (this == µs) { + // Unsafe path: no need to perform a copy. + U_ASSERT(!exhausted); + micros.exhausted = true; + U_ASSERT(exhausted); + } else { + // Safe path: copy self into the output micros. + micros = *this; + } + } + + private: + // Internal fields: + bool exhausted = false; +}; + +} // namespace impl +} // namespace number +U_NAMESPACE_END + +#endif // __NUMBER_MICROPROPS_H__ + +#endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/deps/icu-small/source/i18n/number_modifiers.cpp b/deps/icu-small/source/i18n/number_modifiers.cpp index 872b97010d7..4385499b54f 100644 --- a/deps/icu-small/source/i18n/number_modifiers.cpp +++ b/deps/icu-small/source/i18n/number_modifiers.cpp @@ -3,7 +3,7 @@ #include "unicode/utypes.h" -#if !UCONFIG_NO_FORMATTING && !UPRV_INCOMPLETE_CPP11_SUPPORT +#if !UCONFIG_NO_FORMATTING #include "umutex.h" #include "ucln_cmn.h" @@ -32,6 +32,7 @@ UBool U_CALLCONV cleanupDefaultCurrencySpacing() { UNISET_DIGIT = nullptr; delete UNISET_NOTS; UNISET_NOTS = nullptr; + gDefaultCurrencySpacingInitOnce.reset(); return TRUE; } @@ -50,6 +51,9 @@ void U_CALLCONV initDefaultCurrencySpacing(UErrorCode &status) { } // namespace +Modifier::~Modifier() = default; + + int32_t ConstantAffixModifier::apply(NumberStringBuilder &output, int leftIndex, int rightIndex, UErrorCode &status) const { // Insert the suffix first since inserting the prefix will change the rightIndex diff --git a/deps/icu-small/source/i18n/number_modifiers.h b/deps/icu-small/source/i18n/number_modifiers.h index 4762a6f6d37..a553100cd92 100644 --- a/deps/icu-small/source/i18n/number_modifiers.h +++ b/deps/icu-small/source/i18n/number_modifiers.h @@ -3,7 +3,7 @@ #include "unicode/utypes.h" -#if !UCONFIG_NO_FORMATTING && !UPRV_INCOMPLETE_CPP11_SUPPORT +#if !UCONFIG_NO_FORMATTING #ifndef __NUMBER_MODIFIERS_H__ #define __NUMBER_MODIFIERS_H__ diff --git a/deps/icu-small/source/i18n/number_multiplier.cpp b/deps/icu-small/source/i18n/number_multiplier.cpp new file mode 100644 index 00000000000..a27142c9bd6 --- /dev/null +++ b/deps/icu-small/source/i18n/number_multiplier.cpp @@ -0,0 +1,156 @@ +// © 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 "number_decnum.h" +#include "number_types.h" +#include "number_multiplier.h" +#include "numparse_validators.h" +#include "number_utils.h" +#include "decNumber.h" + +using namespace icu; +using namespace icu::number; +using namespace icu::number::impl; +using namespace icu::numparse::impl; + + +Scale::Scale(int32_t magnitude, DecNum* arbitraryToAdopt) + : fMagnitude(magnitude), fArbitrary(arbitraryToAdopt), fError(U_ZERO_ERROR) { + if (fArbitrary != nullptr) { + // Attempt to convert the DecNum to a magnitude multiplier. + fArbitrary->normalize(); + if (fArbitrary->getRawDecNumber()->digits == 1 && fArbitrary->getRawDecNumber()->lsu[0] == 1 && + !fArbitrary->isNegative()) { + // Success! + fMagnitude += fArbitrary->getRawDecNumber()->exponent; + delete fArbitrary; + fArbitrary = nullptr; + } + } +} + +Scale::Scale(const Scale& other) + : fMagnitude(other.fMagnitude), fArbitrary(nullptr), fError(other.fError) { + if (other.fArbitrary != nullptr) { + UErrorCode localStatus = U_ZERO_ERROR; + fArbitrary = new DecNum(*other.fArbitrary, localStatus); + } +} + +Scale& Scale::operator=(const Scale& other) { + fMagnitude = other.fMagnitude; + if (other.fArbitrary != nullptr) { + UErrorCode localStatus = U_ZERO_ERROR; + fArbitrary = new DecNum(*other.fArbitrary, localStatus); + } else { + fArbitrary = nullptr; + } + fError = other.fError; + return *this; +} + +Scale::Scale(Scale&& src) U_NOEXCEPT + : fMagnitude(src.fMagnitude), fArbitrary(src.fArbitrary), fError(src.fError) { + // Take ownership away from src if necessary + src.fArbitrary = nullptr; +} + +Scale& Scale::operator=(Scale&& src) U_NOEXCEPT { + fMagnitude = src.fMagnitude; + fArbitrary = src.fArbitrary; + fError = src.fError; + // Take ownership away from src if necessary + src.fArbitrary = nullptr; + return *this; +} + +Scale::~Scale() { + delete fArbitrary; +} + + +Scale Scale::none() { + return {0, nullptr}; +} + +Scale Scale::powerOfTen(int32_t power) { + return {power, nullptr}; +} + +Scale Scale::byDecimal(StringPiece multiplicand) { + UErrorCode localError = U_ZERO_ERROR; + LocalPointer decnum(new DecNum(), localError); + if (U_FAILURE(localError)) { + return {localError}; + } + decnum->setTo(multiplicand, localError); + if (U_FAILURE(localError)) { + return {localError}; + } + return {0, decnum.orphan()}; +} + +Scale Scale::byDouble(double multiplicand) { + UErrorCode localError = U_ZERO_ERROR; + LocalPointer decnum(new DecNum(), localError); + if (U_FAILURE(localError)) { + return {localError}; + } + decnum->setTo(multiplicand, localError); + if (U_FAILURE(localError)) { + return {localError}; + } + return {0, decnum.orphan()}; +} + +Scale Scale::byDoubleAndPowerOfTen(double multiplicand, int32_t power) { + UErrorCode localError = U_ZERO_ERROR; + LocalPointer decnum(new DecNum(), localError); + if (U_FAILURE(localError)) { + return {localError}; + } + decnum->setTo(multiplicand, localError); + if (U_FAILURE(localError)) { + return {localError}; + } + return {power, decnum.orphan()}; +} + +void Scale::applyTo(impl::DecimalQuantity& quantity) const { + quantity.adjustMagnitude(fMagnitude); + if (fArbitrary != nullptr) { + UErrorCode localStatus = U_ZERO_ERROR; + quantity.multiplyBy(*fArbitrary, localStatus); + } +} + +void Scale::applyReciprocalTo(impl::DecimalQuantity& quantity) const { + quantity.adjustMagnitude(-fMagnitude); + if (fArbitrary != nullptr) { + UErrorCode localStatus = U_ZERO_ERROR; + quantity.divideBy(*fArbitrary, localStatus); + } +} + + +void +MultiplierFormatHandler::setAndChain(const Scale& multiplier, const MicroPropsGenerator* parent) { + this->multiplier = multiplier; + this->parent = parent; +} + +void MultiplierFormatHandler::processQuantity(DecimalQuantity& quantity, MicroProps& micros, + UErrorCode& status) const { + parent->processQuantity(quantity, micros, status); + multiplier.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 new file mode 100644 index 00000000000..82c30c78426 --- /dev/null +++ b/deps/icu-small/source/i18n/number_multiplier.h @@ -0,0 +1,57 @@ +// © 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_NUMBER_MULTIPLIER_H__ +#define __SOURCE_NUMBER_MULTIPLIER_H__ + +#include "numparse_types.h" +#include "number_decimfmtprops.h" + +U_NAMESPACE_BEGIN namespace number { +namespace impl { + + +/** + * Wraps a {@link Multiplier} for use in the number formatting pipeline. + */ +// Exported as U_I18N_API for tests +class U_I18N_API MultiplierFormatHandler : public MicroPropsGenerator, public UMemory { + public: + MultiplierFormatHandler() = default; // WARNING: Leaves object in an unusable state; call setAndChain() + + void setAndChain(const Scale& multiplier, const MicroPropsGenerator* parent); + + void processQuantity(DecimalQuantity& quantity, MicroProps& micros, + UErrorCode& status) const U_OVERRIDE; + + private: + Scale multiplier; + const MicroPropsGenerator *parent; +}; + + +/** Gets a Scale from a DecimalFormatProperties. In Java, defined in RoundingUtils.java */ +static inline Scale scaleFromProperties(const DecimalFormatProperties& properties) { + int32_t magnitudeMultiplier = properties.magnitudeMultiplier + properties.multiplierScale; + int32_t arbitraryMultiplier = properties.multiplier; + if (magnitudeMultiplier != 0 && arbitraryMultiplier != 1) { + return Scale::byDoubleAndPowerOfTen(arbitraryMultiplier, magnitudeMultiplier); + } else if (magnitudeMultiplier != 0) { + return Scale::powerOfTen(magnitudeMultiplier); + } else if (arbitraryMultiplier != 1) { + return Scale::byDouble(arbitraryMultiplier); + } else { + return Scale::none(); + } +} + + +} // namespace impl +} // namespace number +U_NAMESPACE_END + +#endif //__SOURCE_NUMBER_MULTIPLIER_H__ +#endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/deps/icu-small/source/i18n/number_notation.cpp b/deps/icu-small/source/i18n/number_notation.cpp index f4ad333354d..b3cabb57a50 100644 --- a/deps/icu-small/source/i18n/number_notation.cpp +++ b/deps/icu-small/source/i18n/number_notation.cpp @@ -3,7 +3,7 @@ #include "unicode/utypes.h" -#if !UCONFIG_NO_FORMATTING && !UPRV_INCOMPLETE_CPP11_SUPPORT +#if !UCONFIG_NO_FORMATTING #include "unicode/numberformatter.h" #include "number_types.h" @@ -36,6 +36,19 @@ ScientificNotation Notation::engineering() { return {NTN_SCIENTIFIC, union_}; } +ScientificNotation::ScientificNotation(int8_t fEngineeringInterval, bool fRequireMinInt, + impl::digits_t fMinExponentDigits, + UNumberSignDisplay fExponentSignDisplay) { + ScientificSettings settings; + settings.fEngineeringInterval = fEngineeringInterval; + settings.fRequireMinInt = fRequireMinInt; + settings.fMinExponentDigits = fMinExponentDigits; + settings.fExponentSignDisplay = fExponentSignDisplay; + NotationUnion union_; + union_.scientific = settings; + *this = {NTN_SCIENTIFIC, union_}; +} + Notation Notation::compactShort() { NotationUnion union_; union_.compactStyle = CompactStyle::UNUM_SHORT; diff --git a/deps/icu-small/source/i18n/number_padding.cpp b/deps/icu-small/source/i18n/number_padding.cpp index b1db3490cd4..97e7b6014f9 100644 --- a/deps/icu-small/source/i18n/number_padding.cpp +++ b/deps/icu-small/source/i18n/number_padding.cpp @@ -3,11 +3,12 @@ #include "unicode/utypes.h" -#if !UCONFIG_NO_FORMATTING && !UPRV_INCOMPLETE_CPP11_SUPPORT +#if !UCONFIG_NO_FORMATTING #include "unicode/numberformatter.h" #include "number_types.h" #include "number_stringbuilder.h" +#include "number_decimfmtprops.h" using namespace icu; using namespace icu::number; @@ -28,6 +29,7 @@ addPaddingHelper(UChar32 paddingCp, int32_t requiredPadding, NumberStringBuilder } Padder::Padder(UChar32 cp, int32_t width, UNumberFormatPadPosition position) : fWidth(width) { + // TODO(13034): Consider making this a string instead of code point. fUnion.padding.fCp = cp; fUnion.padding.fPosition = position; } @@ -47,6 +49,16 @@ Padder Padder::codePoints(UChar32 cp, int32_t targetWidth, UNumberFormatPadPosit } } +Padder Padder::forProperties(const DecimalFormatProperties& properties) { + UChar32 padCp; + if (properties.padString.length() > 0) { + padCp = properties.padString.char32At(0); + } else { + padCp = kFallbackPaddingString[0]; + } + return {padCp, properties.formatWidth, properties.padPosition.getOrDefault(UNUM_PAD_BEFORE_PREFIX)}; +} + int32_t Padder::padAndApply(const Modifier &mod1, const Modifier &mod2, NumberStringBuilder &string, int32_t leftIndex, int32_t rightIndex, UErrorCode &status) const { diff --git a/deps/icu-small/source/i18n/number_patternmodifier.cpp b/deps/icu-small/source/i18n/number_patternmodifier.cpp index e182104c911..6417e14378b 100644 --- a/deps/icu-small/source/i18n/number_patternmodifier.cpp +++ b/deps/icu-small/source/i18n/number_patternmodifier.cpp @@ -3,21 +3,27 @@ #include "unicode/utypes.h" -#if !UCONFIG_NO_FORMATTING && !UPRV_INCOMPLETE_CPP11_SUPPORT +#if !UCONFIG_NO_FORMATTING #include "cstring.h" #include "number_patternmodifier.h" #include "unicode/dcfmtsym.h" #include "unicode/ucurr.h" #include "unicode/unistr.h" +#include "number_microprops.h" using namespace icu; using namespace icu::number; using namespace icu::number::impl; -MutablePatternModifier::MutablePatternModifier(bool isStrong) : fStrong(isStrong) {} -void MutablePatternModifier::setPatternInfo(const AffixPatternProvider *patternInfo) { +AffixPatternProvider::~AffixPatternProvider() = default; + + +MutablePatternModifier::MutablePatternModifier(bool isStrong) + : fStrong(isStrong) {} + +void MutablePatternModifier::setPatternInfo(const AffixPatternProvider* patternInfo) { this->patternInfo = patternInfo; } @@ -26,14 +32,12 @@ void MutablePatternModifier::setPatternAttributes(UNumberSignDisplay signDisplay this->perMilleReplacesPercent = perMille; } -void -MutablePatternModifier::setSymbols(const DecimalFormatSymbols *symbols, const CurrencyUnit ¤cy, - const UNumberUnitWidth unitWidth, const PluralRules *rules) { +void MutablePatternModifier::setSymbols(const DecimalFormatSymbols* symbols, + const CurrencySymbols* currencySymbols, + const UNumberUnitWidth unitWidth, const PluralRules* rules) { U_ASSERT((rules != nullptr) == needsPlurals()); this->symbols = symbols; - uprv_memcpy(static_cast(this->currencyCode), - currency.getISOCurrency(), - sizeof(char16_t) * 4); + this->currencySymbols = currencySymbols; this->unitWidth = unitWidth; this->rules = rules; } @@ -49,12 +53,12 @@ bool MutablePatternModifier::needsPlurals() const { // Silently ignore any error codes. } -ImmutablePatternModifier *MutablePatternModifier::createImmutable(UErrorCode &status) { +ImmutablePatternModifier* MutablePatternModifier::createImmutable(UErrorCode& status) { return createImmutableAndChain(nullptr, status); } -ImmutablePatternModifier * -MutablePatternModifier::createImmutableAndChain(const MicroPropsGenerator *parent, UErrorCode &status) { +ImmutablePatternModifier* +MutablePatternModifier::createImmutableAndChain(const MicroPropsGenerator* parent, UErrorCode& status) { // TODO: Move StandardPlural VALUES to standardplural.h static const StandardPlural::Form STANDARD_PLURAL_VALUES[] = { @@ -89,11 +93,11 @@ MutablePatternModifier::createImmutableAndChain(const MicroPropsGenerator *paren } else { // Faster path when plural keyword is not needed. setNumberProperties(1, StandardPlural::Form::COUNT); - Modifier *positive = createConstantModifier(status); + Modifier* positive = createConstantModifier(status); setNumberProperties(0, StandardPlural::Form::COUNT); - Modifier *zero = createConstantModifier(status); + Modifier* zero = createConstantModifier(status); setNumberProperties(-1, StandardPlural::Form::COUNT); - Modifier *negative = createConstantModifier(status); + Modifier* negative = createConstantModifier(status); pm->adoptPositiveNegativeModifiers(positive, zero, negative); if (U_FAILURE(status)) { delete pm; @@ -103,77 +107,91 @@ MutablePatternModifier::createImmutableAndChain(const MicroPropsGenerator *paren } } -ConstantMultiFieldModifier *MutablePatternModifier::createConstantModifier(UErrorCode &status) { +ConstantMultiFieldModifier* MutablePatternModifier::createConstantModifier(UErrorCode& status) { NumberStringBuilder a; NumberStringBuilder b; insertPrefix(a, 0, status); insertSuffix(b, 0, status); if (patternInfo->hasCurrencySign()) { - return new CurrencySpacingEnabledModifier(a, b, !patternInfo->hasBody(), fStrong, *symbols, status); + return new CurrencySpacingEnabledModifier( + a, b, !patternInfo->hasBody(), fStrong, *symbols, status); } else { return new ConstantMultiFieldModifier(a, b, !patternInfo->hasBody(), fStrong); } } -ImmutablePatternModifier::ImmutablePatternModifier(ParameterizedModifier *pm, const PluralRules *rules, - const MicroPropsGenerator *parent) +ImmutablePatternModifier::ImmutablePatternModifier(ParameterizedModifier* pm, const PluralRules* rules, + const MicroPropsGenerator* parent) : pm(pm), rules(rules), parent(parent) {} -void ImmutablePatternModifier::processQuantity(DecimalQuantity &quantity, MicroProps µs, - UErrorCode &status) const { +void ImmutablePatternModifier::processQuantity(DecimalQuantity& quantity, MicroProps& micros, + UErrorCode& status) const { parent->processQuantity(quantity, micros, status); applyToMicros(micros, quantity); } -void ImmutablePatternModifier::applyToMicros(MicroProps µs, DecimalQuantity &quantity) const { +void ImmutablePatternModifier::applyToMicros(MicroProps& micros, DecimalQuantity& quantity) const { if (rules == nullptr) { micros.modMiddle = pm->getModifier(quantity.signum()); } else { // TODO: Fix this. Avoid the copy. DecimalQuantity copy(quantity); copy.roundToInfinity(); - StandardPlural::Form plural = copy.getStandardPlural(rules); + StandardPlural::Form plural = utils::getStandardPlural(rules, copy); micros.modMiddle = pm->getModifier(quantity.signum(), plural); } } +const Modifier* ImmutablePatternModifier::getModifier(int8_t signum, StandardPlural::Form plural) const { + if (rules == nullptr) { + return pm->getModifier(signum); + } else { + return pm->getModifier(signum, plural); + } +} + + /** Used by the unsafe code path. */ -MicroPropsGenerator &MutablePatternModifier::addToChain(const MicroPropsGenerator *parent) { +MicroPropsGenerator& MutablePatternModifier::addToChain(const MicroPropsGenerator* parent) { this->parent = parent; return *this; } -void MutablePatternModifier::processQuantity(DecimalQuantity &fq, MicroProps µs, - UErrorCode &status) const { +void MutablePatternModifier::processQuantity(DecimalQuantity& fq, MicroProps& micros, + UErrorCode& status) const { parent->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); + auto nonConstThis = const_cast(this); if (needsPlurals()) { // TODO: Fix this. Avoid the copy. DecimalQuantity copy(fq); - micros.rounding.apply(copy, status); - nonConstThis->setNumberProperties(fq.signum(), copy.getStandardPlural(rules)); + micros.rounder.apply(copy, status); + nonConstThis->setNumberProperties(fq.signum(), utils::getStandardPlural(rules, copy)); } else { nonConstThis->setNumberProperties(fq.signum(), StandardPlural::Form::COUNT); } micros.modMiddle = this; } -int32_t MutablePatternModifier::apply(NumberStringBuilder &output, int32_t leftIndex, int32_t rightIndex, - UErrorCode &status) const { +int32_t MutablePatternModifier::apply(NumberStringBuilder& output, int32_t leftIndex, int32_t rightIndex, + UErrorCode& status) 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); + auto nonConstThis = const_cast(this); int32_t prefixLen = nonConstThis->insertPrefix(output, leftIndex, status); 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()) { overwriteLen = output.splice( - leftIndex + prefixLen, rightIndex + prefixLen, - UnicodeString(), 0, 0, UNUM_FIELD_COUNT, - status); + leftIndex + prefixLen, + rightIndex + prefixLen, + UnicodeString(), + 0, + 0, + UNUM_FIELD_COUNT, + status); } CurrencySpacingEnabledModifier::applyCurrencySpacing( output, @@ -186,30 +204,27 @@ int32_t MutablePatternModifier::apply(NumberStringBuilder &output, int32_t leftI return prefixLen + overwriteLen + suffixLen; } -int32_t MutablePatternModifier::getPrefixLength(UErrorCode &status) const { +int32_t MutablePatternModifier::getPrefixLength(UErrorCode& status) 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); + auto nonConstThis = const_cast(this); // Enter and exit CharSequence Mode to get the length. - nonConstThis->enterCharSequenceMode(true); - int result = AffixUtils::unescapedCodePointCount(*this, *this, status); // prefix length - nonConstThis->exitCharSequenceMode(); + 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(UErrorCode& status) 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); + auto nonConstThis = const_cast(this); - // Enter and exit CharSequence Mode to get the length. - nonConstThis->enterCharSequenceMode(true); - int result = AffixUtils::unescapedCodePointCount(*this, *this, status); // prefix length - nonConstThis->exitCharSequenceMode(); - nonConstThis->enterCharSequenceMode(false); - result += AffixUtils::unescapedCodePointCount(*this, *this, status); // suffix length - nonConstThis->exitCharSequenceMode(); + // Render the affixes to get the length + nonConstThis->prepareAffix(true); + int result = AffixUtils::unescapedCodePointCount(currentAffix, *this, status); // prefix length + nonConstThis->prepareAffix(false); + result += AffixUtils::unescapedCodePointCount(currentAffix, *this, status); // suffix length return result; } @@ -217,21 +232,26 @@ bool MutablePatternModifier::isStrong() const { return fStrong; } -int32_t MutablePatternModifier::insertPrefix(NumberStringBuilder &sb, int position, UErrorCode &status) { - enterCharSequenceMode(true); - int length = AffixUtils::unescape(*this, sb, position, *this, status); - exitCharSequenceMode(); +int32_t MutablePatternModifier::insertPrefix(NumberStringBuilder& sb, int position, UErrorCode& status) { + prepareAffix(true); + int length = AffixUtils::unescape(currentAffix, sb, position, *this, status); return length; } -int32_t MutablePatternModifier::insertSuffix(NumberStringBuilder &sb, int position, UErrorCode &status) { - enterCharSequenceMode(false); - int length = AffixUtils::unescape(*this, sb, position, *this, status); - exitCharSequenceMode(); +int32_t MutablePatternModifier::insertSuffix(NumberStringBuilder& sb, int position, UErrorCode& status) { + prepareAffix(false); + int length = AffixUtils::unescape(currentAffix, sb, position, *this, status); return length; } +/** 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); +} + UnicodeString MutablePatternModifier::getSymbol(AffixPatternType type) const { + UErrorCode localStatus = U_ZERO_ERROR; switch (type) { case AffixPatternType::TYPE_MINUS_SIGN: return symbols->getSymbol(DecimalFormatSymbols::ENumberFormatSymbol::kMinusSignSymbol); @@ -244,45 +264,23 @@ UnicodeString MutablePatternModifier::getSymbol(AffixPatternType type) const { case AffixPatternType::TYPE_CURRENCY_SINGLE: { // UnitWidth ISO and HIDDEN overrides the singular currency symbol. if (unitWidth == UNumberUnitWidth::UNUM_UNIT_WIDTH_ISO_CODE) { - return UnicodeString(currencyCode, 3); + return currencySymbols->getIntlCurrencySymbol(localStatus); } else if (unitWidth == UNumberUnitWidth::UNUM_UNIT_WIDTH_HIDDEN) { return UnicodeString(); + } else if (unitWidth == UNumberUnitWidth::UNUM_UNIT_WIDTH_NARROW) { + return currencySymbols->getNarrowCurrencySymbol(localStatus); } else { - UCurrNameStyle selector = (unitWidth == UNumberUnitWidth::UNUM_UNIT_WIDTH_NARROW) - ? UCurrNameStyle::UCURR_NARROW_SYMBOL_NAME - : UCurrNameStyle::UCURR_SYMBOL_NAME; - UErrorCode status = U_ZERO_ERROR; - UBool isChoiceFormat = FALSE; - int32_t symbolLen = 0; - const char16_t *symbol = ucurr_getName( - currencyCode, - symbols->getLocale().getName(), - selector, - &isChoiceFormat, - &symbolLen, - &status); - return UnicodeString(symbol, symbolLen); + return currencySymbols->getCurrencySymbol(localStatus); } } case AffixPatternType::TYPE_CURRENCY_DOUBLE: - return UnicodeString(currencyCode, 3); - case AffixPatternType::TYPE_CURRENCY_TRIPLE: { + return currencySymbols->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); - UErrorCode status = U_ZERO_ERROR; - UBool isChoiceFormat = FALSE; - int32_t symbolLen = 0; - const char16_t *symbol = ucurr_getPluralName( - currencyCode, - symbols->getLocale().getName(), - &isChoiceFormat, - StandardPlural::getKeyword(plural), - &symbolLen, - &status); - return UnicodeString(symbol, symbolLen); - } + return currencySymbols->getPluralName(plural, localStatus); case AffixPatternType::TYPE_CURRENCY_QUAD: return UnicodeString(u"\uFFFD"); case AffixPatternType::TYPE_CURRENCY_QUINT: @@ -293,79 +291,6 @@ UnicodeString MutablePatternModifier::getSymbol(AffixPatternType type) const { } } -/** This method contains the heart of the logic for rendering LDML affix strings. */ -void MutablePatternModifier::enterCharSequenceMode(bool isPrefix) { - U_ASSERT(!inCharSequenceMode); - inCharSequenceMode = true; - - // Should the output render '+' where '-' would normally appear in the pattern? - plusReplacesMinusSign = signum != -1 - && (signDisplay == UNUM_SIGN_ALWAYS - || signDisplay == UNUM_SIGN_ACCOUNTING_ALWAYS - || (signum == 1 - && (signDisplay == UNUM_SIGN_EXCEPT_ZERO - || signDisplay == UNUM_SIGN_ACCOUNTING_EXCEPT_ZERO))) - && patternInfo->positiveHasPlusSign() == false; - - // Should we use the affix from the negative subpattern? (If not, we will use the positive subpattern.) - bool useNegativeAffixPattern = patternInfo->hasNegativeSubpattern() && ( - signum == -1 || (patternInfo->negativeHasMinusSign() && plusReplacesMinusSign)); - - // Resolve the flags for the affix pattern. - fFlags = 0; - if (useNegativeAffixPattern) { - fFlags |= AffixPatternProvider::AFFIX_NEGATIVE_SUBPATTERN; - } - if (isPrefix) { - fFlags |= AffixPatternProvider::AFFIX_PREFIX; - } - if (plural != StandardPlural::Form::COUNT) { - U_ASSERT(plural == (AffixPatternProvider::AFFIX_PLURAL_MASK & plural)); - fFlags |= plural; - } - - // Should we prepend a sign to the pattern? - if (!isPrefix || useNegativeAffixPattern) { - prependSign = false; - } else if (signum == -1) { - prependSign = signDisplay != UNUM_SIGN_NEVER; - } else { - prependSign = plusReplacesMinusSign; - } - - // Finally, compute the length of the affix pattern. - fLength = patternInfo->length(fFlags) + (prependSign ? 1 : 0); -} - -void MutablePatternModifier::exitCharSequenceMode() { - U_ASSERT(inCharSequenceMode); - inCharSequenceMode = false; -} - -int32_t MutablePatternModifier::length() const { - U_ASSERT(inCharSequenceMode); - return fLength; -} - -char16_t MutablePatternModifier::charAt(int32_t index) const { - U_ASSERT(inCharSequenceMode); - char16_t candidate; - if (prependSign && index == 0) { - candidate = u'-'; - } else if (prependSign) { - candidate = patternInfo->charAt(fFlags, index - 1); - } else { - candidate = patternInfo->charAt(fFlags, index); - } - if (plusReplacesMinusSign && candidate == u'-') { - return u'+'; - } - if (perMilleReplacesPercent && candidate == u'%') { - return u'‰'; - } - return candidate; -} - UnicodeString MutablePatternModifier::toUnicodeString() const { // Never called by AffixUtils U_ASSERT(false); diff --git a/deps/icu-small/source/i18n/number_patternmodifier.h b/deps/icu-small/source/i18n/number_patternmodifier.h index 9c8b95f7764..f1359bd5747 100644 --- a/deps/icu-small/source/i18n/number_patternmodifier.h +++ b/deps/icu-small/source/i18n/number_patternmodifier.h @@ -3,7 +3,7 @@ #include "unicode/utypes.h" -#if !UCONFIG_NO_FORMATTING && !UPRV_INCOMPLETE_CPP11_SUPPORT +#if !UCONFIG_NO_FORMATTING #ifndef __NUMBER_PATTERNMODIFIER_H__ #define __NUMBER_PATTERNMODIFIER_H__ @@ -13,6 +13,7 @@ #include "number_types.h" #include "number_modifiers.h" #include "number_utils.h" +#include "number_currencysymbols.h" U_NAMESPACE_BEGIN @@ -35,20 +36,23 @@ class MutablePatternModifier; // Exported as U_I18N_API because it is needed for the unit test PatternModifierTest class U_I18N_API ImmutablePatternModifier : public MicroPropsGenerator, public UMemory { public: - ~ImmutablePatternModifier() U_OVERRIDE = default; + ~ImmutablePatternModifier() U_OVERRIDE = default; - void processQuantity(DecimalQuantity &, MicroProps µs, UErrorCode &status) const U_OVERRIDE; + void processQuantity(DecimalQuantity&, MicroProps& micros, UErrorCode& status) const U_OVERRIDE; - void applyToMicros(MicroProps µs, DecimalQuantity &quantity) const; + void applyToMicros(MicroProps& micros, DecimalQuantity& quantity) const; + + const Modifier* getModifier(int8_t signum, StandardPlural::Form plural) const; private: - ImmutablePatternModifier(ParameterizedModifier *pm, const PluralRules *rules, const MicroPropsGenerator *parent); + ImmutablePatternModifier(ParameterizedModifier* pm, const PluralRules* rules, + const MicroPropsGenerator* parent); const LocalPointer pm; - const PluralRules *rules; - const MicroPropsGenerator *parent; + const PluralRules* rules; + const MicroPropsGenerator* parent; - friend class MutablePatternModifier; + friend class MutablePatternModifier; }; /** @@ -74,7 +78,6 @@ class U_I18N_API MutablePatternModifier : public MicroPropsGenerator, public Modifier, public SymbolProvider, - public CharSequence, public UMemory { public: @@ -110,17 +113,16 @@ class U_I18N_API MutablePatternModifier * * @param symbols * The desired instance of DecimalFormatSymbols. - * @param currency - * The currency to be used when substituting currency values into the affixes. + * @param currencySymbols + * The currency symbols to be used when substituting currency values into the affixes. * @param unitWidth * The width used to render currencies. * @param rules * Required if the triple currency sign, "¤¤¤", appears in the pattern, which can be determined from the * convenience method {@link #needsPlurals()}. */ - void - setSymbols(const DecimalFormatSymbols *symbols, const CurrencyUnit ¤cy, UNumberUnitWidth unitWidth, - const PluralRules *rules); + void setSymbols(const DecimalFormatSymbols* symbols, const CurrencySymbols* currencySymbols, + UNumberUnitWidth unitWidth, const PluralRules* rules); /** * Sets attributes of the current number being processed. @@ -187,13 +189,7 @@ class U_I18N_API MutablePatternModifier */ UnicodeString getSymbol(AffixPatternType type) const U_OVERRIDE; - int32_t length() const U_OVERRIDE; - - char16_t charAt(int32_t index) const U_OVERRIDE; - - // Use default implementation of codePointAt - - UnicodeString toUnicodeString() const U_OVERRIDE; + UnicodeString toUnicodeString() const; private: // Modifier details (initialized in constructor) @@ -207,7 +203,7 @@ class U_I18N_API MutablePatternModifier // Symbol details (initialized in setSymbols) const DecimalFormatSymbols *symbols; UNumberUnitWidth unitWidth; - char16_t currencyCode[4]; + const CurrencySymbols *currencySymbols; const PluralRules *rules; // Number details (initialized in setNumberProperties) @@ -217,12 +213,8 @@ class U_I18N_API MutablePatternModifier // QuantityChain details (initialized in addToChain) const MicroPropsGenerator *parent; - // Transient CharSequence fields (initialized in enterCharSequenceMode) - bool inCharSequenceMode = false; - int32_t fFlags; - int32_t fLength; - bool prependSign; - bool plusReplacesMinusSign; + // Transient fields for rendering + UnicodeString currentAffix; /** * Uses the current properties to create a single {@link ConstantMultiFieldModifier} with currency spacing support @@ -244,9 +236,7 @@ class U_I18N_API MutablePatternModifier int32_t insertSuffix(NumberStringBuilder &sb, int position, UErrorCode &status); - void enterCharSequenceMode(bool isPrefix); - - void exitCharSequenceMode(); + void prepareAffix(bool isPrefix); }; diff --git a/deps/icu-small/source/i18n/number_patternstring.cpp b/deps/icu-small/source/i18n/number_patternstring.cpp index 20178824b0e..63195eed989 100644 --- a/deps/icu-small/source/i18n/number_patternstring.cpp +++ b/deps/icu-small/source/i18n/number_patternstring.cpp @@ -3,36 +3,51 @@ #include "unicode/utypes.h" -#if !UCONFIG_NO_FORMATTING && !UPRV_INCOMPLETE_CPP11_SUPPORT +#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 +#define UNISTR_FROM_CHAR_EXPLICIT #include "uassert.h" #include "number_patternstring.h" #include "unicode/utf16.h" #include "number_utils.h" +#include "number_roundingutils.h" using namespace icu; using namespace icu::number; using namespace icu::number::impl; -void PatternParser::parseToPatternInfo(const UnicodeString& patternString, ParsedPatternInfo& patternInfo, UErrorCode &status) { + +void PatternParser::parseToPatternInfo(const UnicodeString& patternString, ParsedPatternInfo& patternInfo, + UErrorCode& status) { patternInfo.consumePattern(patternString, status); } DecimalFormatProperties PatternParser::parseToProperties(const UnicodeString& pattern, IgnoreRounding ignoreRounding, - UErrorCode &status) { + UErrorCode& status) { DecimalFormatProperties properties; parseToExistingPropertiesImpl(pattern, properties, ignoreRounding, status); return properties; } -void PatternParser::parseToExistingProperties(const UnicodeString& pattern, DecimalFormatProperties& properties, - IgnoreRounding ignoreRounding, UErrorCode &status) { +DecimalFormatProperties PatternParser::parseToProperties(const UnicodeString& pattern, + UErrorCode& status) { + return parseToProperties(pattern, IGNORE_ROUNDING_NEVER, status); +} + +void +PatternParser::parseToExistingProperties(const UnicodeString& pattern, DecimalFormatProperties& properties, + IgnoreRounding ignoreRounding, UErrorCode& status) { parseToExistingPropertiesImpl(pattern, properties, ignoreRounding, status); } + char16_t ParsedPatternInfo::charAt(int32_t flags, int32_t index) const { - const Endpoints &endpoints = getEndpoints(flags); + const Endpoints& endpoints = getEndpoints(flags); if (index < 0 || index >= endpoints.end - endpoints.start) { U_ASSERT(false); } @@ -43,12 +58,12 @@ int32_t ParsedPatternInfo::length(int32_t flags) const { return getLengthFromEndpoints(getEndpoints(flags)); } -int32_t ParsedPatternInfo::getLengthFromEndpoints(const Endpoints &endpoints) { +int32_t ParsedPatternInfo::getLengthFromEndpoints(const Endpoints& endpoints) { return endpoints.end - endpoints.start; } UnicodeString ParsedPatternInfo::getString(int32_t flags) const { - const Endpoints &endpoints = getEndpoints(flags); + const Endpoints& endpoints = getEndpoints(flags); if (endpoints.start == endpoints.end) { return UnicodeString(); } @@ -56,7 +71,7 @@ UnicodeString ParsedPatternInfo::getString(int32_t flags) const { return UnicodeString(pattern, endpoints.start, endpoints.end - endpoints.start); } -const Endpoints &ParsedPatternInfo::getEndpoints(int32_t flags) const { +const Endpoints& ParsedPatternInfo::getEndpoints(int32_t flags) const { bool prefix = (flags & AFFIX_PREFIX) != 0; bool isNegative = (flags & AFFIX_NEGATIVE_SUBPATTERN) != 0; bool padding = (flags & AFFIX_PADDING) != 0; @@ -91,8 +106,8 @@ bool ParsedPatternInfo::hasCurrencySign() const { return positive.hasCurrencySign || (fHasNegativeSubpattern && negative.hasCurrencySign); } -bool ParsedPatternInfo::containsSymbolType(AffixPatternType type, UErrorCode &status) const { - return AffixUtils::containsType(UnicodeStringCharSequence(pattern), type, status); +bool ParsedPatternInfo::containsSymbolType(AffixPatternType type, UErrorCode& status) const { + return AffixUtils::containsType(pattern, type, status); } bool ParsedPatternInfo::hasBody() const { @@ -117,10 +132,14 @@ UChar32 ParsedPatternInfo::ParserState::next() { return codePoint; } -void ParsedPatternInfo::consumePattern(const UnicodeString& patternString, UErrorCode &status) { +void ParsedPatternInfo::consumePattern(const UnicodeString& patternString, UErrorCode& status) { if (U_FAILURE(status)) { return; } this->pattern = patternString; + // This class is not intended for writing twice! + // Use move assignment to overwrite instead. + U_ASSERT(state.offset == 0); + // pattern := subpattern (';' subpattern)? currentSubpattern = &positive; consumeSubpattern(status); @@ -141,7 +160,7 @@ void ParsedPatternInfo::consumePattern(const UnicodeString& patternString, UErro } } -void ParsedPatternInfo::consumeSubpattern(UErrorCode &status) { +void ParsedPatternInfo::consumeSubpattern(UErrorCode& status) { // subpattern := literals? number exponent? literals? consumePadding(PadPosition::UNUM_PAD_BEFORE_PREFIX, status); if (U_FAILURE(status)) { return; } @@ -161,23 +180,24 @@ void ParsedPatternInfo::consumeSubpattern(UErrorCode &status) { if (U_FAILURE(status)) { return; } } -void ParsedPatternInfo::consumePadding(PadPosition paddingLocation, UErrorCode &status) { +void ParsedPatternInfo::consumePadding(PadPosition paddingLocation, UErrorCode& status) { if (state.peek() != u'*') { return; } - if (!currentSubpattern->paddingLocation.isNull()) { + if (currentSubpattern->hasPadding) { state.toParseException(u"Cannot have multiple pad specifiers"); status = U_MULTIPLE_PAD_SPECIFIERS; return; } currentSubpattern->paddingLocation = paddingLocation; + currentSubpattern->hasPadding = true; state.next(); // consume the '*' currentSubpattern->paddingEndpoints.start = state.offset; consumeLiteral(status); currentSubpattern->paddingEndpoints.end = state.offset; } -void ParsedPatternInfo::consumeAffix(Endpoints &endpoints, UErrorCode &status) { +void ParsedPatternInfo::consumeAffix(Endpoints& endpoints, UErrorCode& status) { // literals := { literal } endpoints.start = state.offset; while (true) { @@ -233,7 +253,7 @@ void ParsedPatternInfo::consumeAffix(Endpoints &endpoints, UErrorCode &status) { endpoints.end = state.offset; } -void ParsedPatternInfo::consumeLiteral(UErrorCode &status) { +void ParsedPatternInfo::consumeLiteral(UErrorCode& status) { if (state.peek() == -1) { state.toParseException(u"Expected unquoted literal but found EOL"); status = U_PATTERN_SYNTAX_ERROR; @@ -256,7 +276,7 @@ void ParsedPatternInfo::consumeLiteral(UErrorCode &status) { } } -void ParsedPatternInfo::consumeFormat(UErrorCode &status) { +void ParsedPatternInfo::consumeFormat(UErrorCode& status) { consumeIntegerFormat(status); if (U_FAILURE(status)) { return; } if (state.peek() == u'.') { @@ -268,9 +288,9 @@ void ParsedPatternInfo::consumeFormat(UErrorCode &status) { } } -void ParsedPatternInfo::consumeIntegerFormat(UErrorCode &status) { +void ParsedPatternInfo::consumeIntegerFormat(UErrorCode& status) { // Convenience reference: - ParsedSubpatternInfo &result = *currentSubpattern; + ParsedSubpatternInfo& result = *currentSubpattern; while (true) { switch (state.peek()) { @@ -359,9 +379,9 @@ void ParsedPatternInfo::consumeIntegerFormat(UErrorCode &status) { } } -void ParsedPatternInfo::consumeFractionFormat(UErrorCode &status) { +void ParsedPatternInfo::consumeFractionFormat(UErrorCode& status) { // Convenience reference: - ParsedSubpatternInfo &result = *currentSubpattern; + ParsedSubpatternInfo& result = *currentSubpattern; int32_t zeroCounter = 0; while (true) { @@ -407,9 +427,9 @@ void ParsedPatternInfo::consumeFractionFormat(UErrorCode &status) { } } -void ParsedPatternInfo::consumeExponent(UErrorCode &status) { +void ParsedPatternInfo::consumeExponent(UErrorCode& status) { // Convenience reference: - ParsedSubpatternInfo &result = *currentSubpattern; + ParsedSubpatternInfo& result = *currentSubpattern; if (state.peek() != u'E') { return; @@ -437,9 +457,9 @@ void ParsedPatternInfo::consumeExponent(UErrorCode &status) { /// END RECURSIVE DESCENT PARSER IMPLEMENTATION /// /////////////////////////////////////////////////// -void -PatternParser::parseToExistingPropertiesImpl(const UnicodeString& pattern, DecimalFormatProperties &properties, - IgnoreRounding ignoreRounding, UErrorCode &status) { +void PatternParser::parseToExistingPropertiesImpl(const UnicodeString& pattern, + DecimalFormatProperties& properties, + IgnoreRounding ignoreRounding, UErrorCode& status) { if (pattern.length() == 0) { // Backwards compatibility requires that we reset to the default values. // TODO: Only overwrite the properties that "saveToProperties" normally touches? @@ -453,13 +473,13 @@ PatternParser::parseToExistingPropertiesImpl(const UnicodeString& pattern, Decim patternInfoToProperties(properties, patternInfo, ignoreRounding, status); } -void PatternParser::patternInfoToProperties(DecimalFormatProperties &properties, - ParsedPatternInfo& patternInfo, - IgnoreRounding _ignoreRounding, UErrorCode &status) { +void +PatternParser::patternInfoToProperties(DecimalFormatProperties& properties, ParsedPatternInfo& patternInfo, + IgnoreRounding _ignoreRounding, UErrorCode& status) { // Translate from PatternParseResult to Properties. // Note that most data from "negative" is ignored per the specification of DecimalFormat. - const ParsedSubpatternInfo &positive = patternInfo.positive; + const ParsedSubpatternInfo& positive = patternInfo.positive; bool ignoreRounding; if (_ignoreRounding == IGNORE_ROUNDING_NEVER) { @@ -477,8 +497,10 @@ void PatternParser::patternInfoToProperties(DecimalFormatProperties &properties, auto grouping3 = static_cast ((positive.groupingSizes >> 32) & 0xffff); if (grouping2 != -1) { properties.groupingSize = grouping1; + properties.groupingUsed = true; } else { properties.groupingSize = -1; + properties.groupingUsed = false; } if (grouping3 != -1) { properties.secondaryGroupingSize = grouping2; @@ -508,8 +530,7 @@ void PatternParser::patternInfoToProperties(DecimalFormatProperties &properties, properties.maximumFractionDigits = -1; properties.roundingIncrement = 0.0; properties.minimumSignificantDigits = positive.integerAtSigns; - properties.maximumSignificantDigits = - positive.integerAtSigns + positive.integerTrailingHashSigns; + properties.maximumSignificantDigits = positive.integerAtSigns + positive.integerTrailingHashSigns; } else if (!positive.rounding.isZero()) { if (!ignoreRounding) { properties.minimumFractionDigits = minFrac; @@ -568,11 +589,11 @@ void PatternParser::patternInfoToProperties(DecimalFormatProperties &properties, UnicodeString posSuffix = patternInfo.getString(0); // Padding settings - if (!positive.paddingLocation.isNull()) { + if (positive.hasPadding) { // The width of the positive prefix and suffix templates are included in the padding - int paddingWidth = - positive.widthExceptAffixes + AffixUtils::estimateLength(UnicodeStringCharSequence(posPrefix), status) + - AffixUtils::estimateLength(UnicodeStringCharSequence(posSuffix), status); + int paddingWidth = positive.widthExceptAffixes + + AffixUtils::estimateLength(posPrefix, status) + + AffixUtils::estimateLength(posSuffix, status); properties.formatWidth = paddingWidth; UnicodeString rawPaddingString = patternInfo.getString(AffixPatternProvider::AFFIX_PADDING); if (rawPaddingString.length() == 1) { @@ -622,8 +643,8 @@ void PatternParser::patternInfoToProperties(DecimalFormatProperties &properties, /// End PatternStringParser.java; begin PatternStringUtils.java /// /////////////////////////////////////////////////////////////////// -UnicodeString PatternStringUtils::propertiesToPatternString(const DecimalFormatProperties &properties, - UErrorCode &status) { +UnicodeString PatternStringUtils::propertiesToPatternString(const DecimalFormatProperties& properties, + UErrorCode& status) { UnicodeString sb; // Convenience references @@ -656,7 +677,7 @@ UnicodeString PatternStringUtils::propertiesToPatternString(const DecimalFormatP if (!ppp.isBogus()) { sb.append(ppp); } - sb.append(AffixUtils::escape(UnicodeStringCharSequence(pp))); + sb.append(AffixUtils::escape(pp)); int afterPrefixPos = sb.length(); // Figure out the grouping sizes. @@ -695,11 +716,11 @@ UnicodeString PatternStringUtils::propertiesToPatternString(const DecimalFormatP } } else if (roundingInterval != 0.0) { // Rounding Interval. - digitsStringScale = minFrac; + digitsStringScale = -roundingutils::doubleFractionLength(roundingInterval); // TODO: Check for DoS here? DecimalQuantity incrementQuantity; incrementQuantity.setToDouble(roundingInterval); - incrementQuantity.adjustMagnitude(minFrac); + incrementQuantity.adjustMagnitude(-digitsStringScale); incrementQuantity.roundToMagnitude(0, kDefaultMode, status); UnicodeString str = incrementQuantity.toPlainString(); if (str.charAt(0) == u'-') { @@ -753,7 +774,7 @@ UnicodeString PatternStringUtils::propertiesToPatternString(const DecimalFormatP if (!psp.isBogus()) { sb.append(psp); } - sb.append(AffixUtils::escape(UnicodeStringCharSequence(ps))); + sb.append(AffixUtils::escape(ps)); // Resolve Padding if (paddingWidth != -1 && !paddingLocation.isNull()) { @@ -795,22 +816,25 @@ UnicodeString PatternStringUtils::propertiesToPatternString(const DecimalFormatP if (!npp.isBogus()) { sb.append(npp); } - sb.append(AffixUtils::escape(UnicodeStringCharSequence(np))); + sb.append(AffixUtils::escape(np)); // Copy the positive digit format into the negative. // This is optional; the pattern is the same as if '#' were appended here instead. - sb.append(sb, afterPrefixPos, beforeSuffixPos); + // NOTE: It is not safe to append the UnicodeString to itself, so we need to copy. + // See http://bugs.icu-project.org/trac/ticket/13707 + UnicodeString copy(sb); + sb.append(copy, afterPrefixPos, beforeSuffixPos - afterPrefixPos); if (!nsp.isBogus()) { sb.append(nsp); } - sb.append(AffixUtils::escape(UnicodeStringCharSequence(ns))); + sb.append(AffixUtils::escape(ns)); } return sb; } int PatternStringUtils::escapePaddingString(UnicodeString input, UnicodeString& output, int startIndex, - UErrorCode &status) { - (void)status; + UErrorCode& status) { + (void) status; if (input.length() == 0) { input.setTo(kFallbackPaddingString, -1); } @@ -840,4 +864,207 @@ int PatternStringUtils::escapePaddingString(UnicodeString input, UnicodeString& return output.length() - startLength; } +UnicodeString +PatternStringUtils::convertLocalized(const UnicodeString& input, const DecimalFormatSymbols& symbols, + bool toLocalized, UErrorCode& status) { + // Construct a table of strings to be converted between localized and standard. + static constexpr int32_t LEN = 21; + UnicodeString table[LEN][2]; + int standIdx = toLocalized ? 0 : 1; + int localIdx = toLocalized ? 1 : 0; + table[0][standIdx] = u"%"; + table[0][localIdx] = symbols.getConstSymbol(DecimalFormatSymbols::kPercentSymbol); + table[1][standIdx] = u"‰"; + table[1][localIdx] = symbols.getConstSymbol(DecimalFormatSymbols::kPerMillSymbol); + table[2][standIdx] = u"."; + table[2][localIdx] = symbols.getConstSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol); + table[3][standIdx] = u","; + table[3][localIdx] = symbols.getConstSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol); + table[4][standIdx] = u"-"; + table[4][localIdx] = symbols.getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol); + table[5][standIdx] = u"+"; + table[5][localIdx] = symbols.getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol); + table[6][standIdx] = u";"; + table[6][localIdx] = symbols.getConstSymbol(DecimalFormatSymbols::kPatternSeparatorSymbol); + table[7][standIdx] = u"@"; + table[7][localIdx] = symbols.getConstSymbol(DecimalFormatSymbols::kSignificantDigitSymbol); + table[8][standIdx] = u"E"; + table[8][localIdx] = symbols.getConstSymbol(DecimalFormatSymbols::kExponentialSymbol); + table[9][standIdx] = u"*"; + table[9][localIdx] = symbols.getConstSymbol(DecimalFormatSymbols::kPadEscapeSymbol); + table[10][standIdx] = u"#"; + table[10][localIdx] = symbols.getConstSymbol(DecimalFormatSymbols::kDigitSymbol); + for (int i = 0; i < 10; i++) { + table[11 + i][standIdx] = u'0' + i; + table[11 + i][localIdx] = symbols.getConstDigitSymbol(i); + } + + // Special case: quotes are NOT allowed to be in any localIdx strings. + // Substitute them with '’' instead. + for (int32_t i = 0; i < LEN; i++) { + table[i][localIdx].findAndReplace(u'\'', u'’'); + } + + // Iterate through the string and convert. + // State table: + // 0 => base state + // 1 => first char inside a quoted sequence in input and output string + // 2 => inside a quoted sequence in input and output string + // 3 => first char after a close quote in input string; + // close quote still needs to be written to output string + // 4 => base state in input string; inside quoted sequence in output string + // 5 => first char inside a quoted sequence in input string; + // inside quoted sequence in output string + UnicodeString result; + int state = 0; + for (int offset = 0; offset < input.length(); offset++) { + UChar ch = input.charAt(offset); + + // Handle a quote character (state shift) + if (ch == u'\'') { + if (state == 0) { + result.append(u'\''); + state = 1; + continue; + } else if (state == 1) { + result.append(u'\''); + state = 0; + continue; + } else if (state == 2) { + state = 3; + continue; + } else if (state == 3) { + result.append(u'\''); + result.append(u'\''); + state = 1; + continue; + } else if (state == 4) { + state = 5; + continue; + } else { + U_ASSERT(state == 5); + result.append(u'\''); + result.append(u'\''); + state = 4; + continue; + } + } + + if (state == 0 || state == 3 || state == 4) { + for (auto& pair : table) { + // Perform a greedy match on this symbol string + UnicodeString temp = input.tempSubString(offset, pair[0].length()); + if (temp == pair[0]) { + // Skip ahead past this region for the next iteration + offset += pair[0].length() - 1; + if (state == 3 || state == 4) { + result.append(u'\''); + state = 0; + } + result.append(pair[1]); + goto continue_outer; + } + } + // No replacement found. Check if a special quote is necessary + for (auto& pair : table) { + UnicodeString temp = input.tempSubString(offset, pair[1].length()); + if (temp == pair[1]) { + if (state == 0) { + result.append(u'\''); + state = 4; + } + result.append(ch); + goto continue_outer; + } + } + // Still nothing. Copy the char verbatim. (Add a close quote if necessary) + if (state == 3 || state == 4) { + result.append(u'\''); + state = 0; + } + result.append(ch); + } else { + U_ASSERT(state == 1 || state == 2 || state == 5); + result.append(ch); + state = 2; + } + continue_outer:; + } + // Resolve final quotes + if (state == 3 || state == 4) { + result.append(u'\''); + state = 0; + } + if (state != 0) { + // Malformed localized pattern: unterminated quote + status = U_PATTERN_SYNTAX_ERROR; + } + return result; +} + +void PatternStringUtils::patternInfoToStringBuilder(const AffixPatternProvider& patternInfo, bool isPrefix, + int8_t signum, UNumberSignDisplay signDisplay, + StandardPlural::Form plural, + bool perMilleReplacesPercent, UnicodeString& output) { + + // Should the output render '+' where '-' would normally appear in the pattern? + bool plusReplacesMinusSign = signum != -1 && ( + signDisplay == UNUM_SIGN_ALWAYS || signDisplay == UNUM_SIGN_ACCOUNTING_ALWAYS || ( + signum == 1 && ( + signDisplay == UNUM_SIGN_EXCEPT_ZERO || + signDisplay == UNUM_SIGN_ACCOUNTING_EXCEPT_ZERO))) && + patternInfo.positiveHasPlusSign() == false; + + // Should we use the affix from the negative subpattern? (If not, we will use the positive + // subpattern.) + bool useNegativeAffixPattern = patternInfo.hasNegativeSubpattern() && ( + signum == -1 || (patternInfo.negativeHasMinusSign() && plusReplacesMinusSign)); + + // Resolve the flags for the affix pattern. + int flags = 0; + if (useNegativeAffixPattern) { + flags |= AffixPatternProvider::AFFIX_NEGATIVE_SUBPATTERN; + } + if (isPrefix) { + flags |= AffixPatternProvider::AFFIX_PREFIX; + } + if (plural != StandardPlural::Form::COUNT) { + U_ASSERT(plural == (AffixPatternProvider::AFFIX_PLURAL_MASK & plural)); + flags |= plural; + } + + // Should we prepend a sign to the pattern? + bool prependSign; + if (!isPrefix || useNegativeAffixPattern) { + prependSign = false; + } else if (signum == -1) { + prependSign = signDisplay != UNUM_SIGN_NEVER; + } else { + prependSign = plusReplacesMinusSign; + } + + // Compute the length of the affix pattern. + int length = patternInfo.length(flags) + (prependSign ? 1 : 0); + + // Finally, set the result into the StringBuilder. + output.remove(); + for (int index = 0; index < length; index++) { + char16_t candidate; + if (prependSign && index == 0) { + candidate = u'-'; + } else if (prependSign) { + candidate = patternInfo.charAt(flags, index - 1); + } else { + candidate = patternInfo.charAt(flags, index); + } + if (plusReplacesMinusSign && candidate == u'-') { + candidate = u'+'; + } + if (perMilleReplacesPercent && candidate == u'%') { + candidate = u'‰'; + } + output.append(candidate); + } +} + #endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/deps/icu-small/source/i18n/number_patternstring.h b/deps/icu-small/source/i18n/number_patternstring.h index ec44290d663..91e120c16a1 100644 --- a/deps/icu-small/source/i18n/number_patternstring.h +++ b/deps/icu-small/source/i18n/number_patternstring.h @@ -3,7 +3,7 @@ #include "unicode/utypes.h" -#if !UCONFIG_NO_FORMATTING && !UPRV_INCOMPLETE_CPP11_SUPPORT +#if !UCONFIG_NO_FORMATTING #ifndef __NUMBER_PATTERNSTRING_H__ #define __NUMBER_PATTERNSTRING_H__ @@ -30,7 +30,7 @@ struct U_I18N_API Endpoints { // Exported as U_I18N_API because it is a public member field of exported ParsedPatternInfo struct U_I18N_API ParsedSubpatternInfo { - int64_t groupingSizes = 0x0000ffffffff0000L; + uint64_t groupingSizes = 0x0000ffffffff0000L; int32_t integerLeadingHashSigns = 0; int32_t integerTrailingHashSigns = 0; int32_t integerNumerals = 0; @@ -41,7 +41,9 @@ struct U_I18N_API ParsedSubpatternInfo { int32_t fractionTotal = 0; // for convenience bool hasDecimal = false; int32_t widthExceptAffixes = 0; - NullableValue paddingLocation; + // Note: NullableValue causes issues here with std::move. + bool hasPadding = false; + UNumberFormatPadPosition paddingLocation = UNUM_PAD_BEFORE_PREFIX; DecimalQuantity rounding; bool exponentHasPlusSign = false; int32_t exponentZeros = 0; @@ -62,17 +64,21 @@ struct U_I18N_API ParsedPatternInfo : public AffixPatternProvider, public UMemor ParsedSubpatternInfo positive; ParsedSubpatternInfo negative; - ParsedPatternInfo() : state(this->pattern), currentSubpattern(nullptr) {} + ParsedPatternInfo() + : state(this->pattern), currentSubpattern(nullptr) {} ~ParsedPatternInfo() U_OVERRIDE = default; - static int32_t getLengthFromEndpoints(const Endpoints &endpoints); + // Need to declare this explicitly because of the destructor + ParsedPatternInfo& operator=(ParsedPatternInfo&& src) U_NOEXCEPT = default; + + static int32_t getLengthFromEndpoints(const Endpoints& endpoints); char16_t charAt(int32_t flags, int32_t index) const U_OVERRIDE; int32_t length(int32_t flags) const U_OVERRIDE; - UnicodeString getString(int32_t flags) const; + UnicodeString getString(int32_t flags) const U_OVERRIDE; bool positiveHasPlusSign() const U_OVERRIDE; @@ -82,16 +88,24 @@ struct U_I18N_API ParsedPatternInfo : public AffixPatternProvider, public UMemor bool hasCurrencySign() const U_OVERRIDE; - bool containsSymbolType(AffixPatternType type, UErrorCode &status) const U_OVERRIDE; + bool containsSymbolType(AffixPatternType type, UErrorCode& status) const U_OVERRIDE; bool hasBody() const U_OVERRIDE; private: struct U_I18N_API ParserState { - const UnicodeString &pattern; // reference to the parent + const UnicodeString& pattern; // reference to the parent int32_t offset = 0; - explicit ParserState(const UnicodeString &_pattern) : pattern(_pattern) {}; + explicit ParserState(const UnicodeString& _pattern) + : pattern(_pattern) {}; + + ParserState& operator=(ParserState&& src) U_NOEXCEPT { + // Leave pattern reference alone; it will continue to point to the same place in memory, + // which gets overwritten by ParsedPatternInfo's implicit move assignment. + offset = src.offset; + return *this; + } UChar32 peek(); @@ -99,45 +113,48 @@ struct U_I18N_API ParsedPatternInfo : public AffixPatternProvider, public UMemor // TODO: We don't currently do anything with the message string. // This method is here as a shell for Java compatibility. - inline void toParseException(const char16_t *message) { (void)message; } - } - state; + inline void toParseException(const char16_t* message) { (void) message; } + } state; // NOTE: In Java, these are written as pure functions. // In C++, they're written as methods. // The behavior is the same. // Mutable transient pointer: - ParsedSubpatternInfo *currentSubpattern; + ParsedSubpatternInfo* currentSubpattern; // In Java, "negative == null" tells us whether or not we had a negative subpattern. // In C++, we need to remember in another boolean. bool fHasNegativeSubpattern = false; - const Endpoints &getEndpoints(int32_t flags) const; + const Endpoints& getEndpoints(int32_t flags) const; /** Run the recursive descent parser. */ - void consumePattern(const UnicodeString &patternString, UErrorCode &status); + void consumePattern(const UnicodeString& patternString, UErrorCode& status); - void consumeSubpattern(UErrorCode &status); + void consumeSubpattern(UErrorCode& status); - void consumePadding(PadPosition paddingLocation, UErrorCode &status); + void consumePadding(PadPosition paddingLocation, UErrorCode& status); - void consumeAffix(Endpoints &endpoints, UErrorCode &status); + void consumeAffix(Endpoints& endpoints, UErrorCode& status); - void consumeLiteral(UErrorCode &status); + void consumeLiteral(UErrorCode& status); - void consumeFormat(UErrorCode &status); + void consumeFormat(UErrorCode& status); - void consumeIntegerFormat(UErrorCode &status); + void consumeIntegerFormat(UErrorCode& status); - void consumeFractionFormat(UErrorCode &status); + void consumeFractionFormat(UErrorCode& status); - void consumeExponent(UErrorCode &status); + void consumeExponent(UErrorCode& status); friend class PatternParser; }; +enum IgnoreRounding { + IGNORE_ROUNDING_NEVER = 0, IGNORE_ROUNDING_IF_CURRENCY = 1, IGNORE_ROUNDING_ALWAYS = 2 +}; + class U_I18N_API PatternParser { public: /** @@ -153,12 +170,8 @@ class U_I18N_API PatternParser { * The LDML decimal format pattern (Excel-style pattern) to parse. * @return The results of the parse. */ - static void - parseToPatternInfo(const UnicodeString& patternString, ParsedPatternInfo &patternInfo, UErrorCode &status); - - enum IgnoreRounding { - IGNORE_ROUNDING_NEVER = 0, IGNORE_ROUNDING_IF_CURRENCY = 1, IGNORE_ROUNDING_ALWAYS = 2 - }; + static void parseToPatternInfo(const UnicodeString& patternString, ParsedPatternInfo& patternInfo, + UErrorCode& status); /** * Parses a pattern string into a new property bag. @@ -173,8 +186,10 @@ class U_I18N_API PatternParser { * @throws IllegalArgumentException * If there is a syntax error in the pattern string. */ - static DecimalFormatProperties - parseToProperties(const UnicodeString& pattern, IgnoreRounding ignoreRounding, UErrorCode &status); + static DecimalFormatProperties parseToProperties(const UnicodeString& pattern, + IgnoreRounding ignoreRounding, UErrorCode& status); + + static DecimalFormatProperties parseToProperties(const UnicodeString& pattern, UErrorCode& status); /** * Parses a pattern string into an existing property bag. All properties that can be encoded into a pattern string @@ -190,18 +205,19 @@ class U_I18N_API PatternParser { * @throws IllegalArgumentException * If there was a syntax error in the pattern string. */ - static void parseToExistingProperties(const UnicodeString& pattern, DecimalFormatProperties& properties, - IgnoreRounding ignoreRounding, UErrorCode &status); + static void parseToExistingProperties(const UnicodeString& pattern, + DecimalFormatProperties& properties, + IgnoreRounding ignoreRounding, UErrorCode& status); private: - static void - parseToExistingPropertiesImpl(const UnicodeString& pattern, DecimalFormatProperties &properties, - IgnoreRounding ignoreRounding, UErrorCode &status); + static void parseToExistingPropertiesImpl(const UnicodeString& pattern, + DecimalFormatProperties& properties, + IgnoreRounding ignoreRounding, UErrorCode& status); /** Finalizes the temporary data stored in the ParsedPatternInfo to the Properties. */ - static void - patternInfoToProperties(DecimalFormatProperties &properties, ParsedPatternInfo& patternInfo, - IgnoreRounding _ignoreRounding, UErrorCode &status); + static void patternInfoToProperties(DecimalFormatProperties& properties, + ParsedPatternInfo& patternInfo, IgnoreRounding _ignoreRounding, + UErrorCode& status); }; class U_I18N_API PatternStringUtils { @@ -217,8 +233,8 @@ class U_I18N_API PatternStringUtils { * The property bag to serialize. * @return A pattern string approximately serializing the property bag. */ - static UnicodeString - propertiesToPatternString(const DecimalFormatProperties &properties, UErrorCode &status); + static UnicodeString propertiesToPatternString(const DecimalFormatProperties& properties, + UErrorCode& status); /** @@ -248,14 +264,23 @@ class U_I18N_API PatternStringUtils { * notation. * @return The pattern expressed in the other notation. */ - static UnicodeString - convertLocalized(UnicodeString input, DecimalFormatSymbols symbols, bool toLocalized, - UErrorCode &status); + static UnicodeString convertLocalized(const UnicodeString& input, const DecimalFormatSymbols& symbols, + bool toLocalized, UErrorCode& status); + + /** + * This method contains the heart of the logic for rendering LDML affix strings. It handles + * sign-always-shown resolution, whether to use the positive or negative subpattern, permille + * substitution, and plural forms for CurrencyPluralInfo. + */ + static void patternInfoToStringBuilder(const AffixPatternProvider& patternInfo, bool isPrefix, + int8_t signum, UNumberSignDisplay signDisplay, + StandardPlural::Form plural, bool perMilleReplacesPercent, + UnicodeString& output); private: /** @return The number of chars inserted. */ - static int - escapePaddingString(UnicodeString input, UnicodeString &output, int startIndex, UErrorCode &status); + static int escapePaddingString(UnicodeString input, UnicodeString& output, int startIndex, + UErrorCode& status); }; } // namespace impl diff --git a/deps/icu-small/source/i18n/number_rounding.cpp b/deps/icu-small/source/i18n/number_rounding.cpp index fd4dafdf983..ae4b8849fbe 100644 --- a/deps/icu-small/source/i18n/number_rounding.cpp +++ b/deps/icu-small/source/i18n/number_rounding.cpp @@ -3,17 +3,23 @@ #include "unicode/utypes.h" -#if !UCONFIG_NO_FORMATTING && !UPRV_INCOMPLETE_CPP11_SUPPORT +#if !UCONFIG_NO_FORMATTING #include "uassert.h" #include "unicode/numberformatter.h" #include "number_types.h" #include "number_decimalquantity.h" +#include "double-conversion.h" +#include "number_roundingutils.h" +#include "putilimp.h" using namespace icu; using namespace icu::number; using namespace icu::number::impl; + +using double_conversion::DoubleToStringConverter; + namespace { int32_t getRoundingMagnitudeFraction(int maxFrac) { @@ -46,15 +52,38 @@ int32_t getDisplayMagnitudeSignificant(const DecimalQuantity &value, int minSig) } -Rounder Rounder::unlimited() { - return Rounder(RND_NONE, {}, kDefaultMode); +MultiplierProducer::~MultiplierProducer() = default; + + +digits_t roundingutils::doubleFractionLength(double input) { + char buffer[DoubleToStringConverter::kBase10MaximalLength + 1]; + bool sign; // unused; always positive + int32_t length; + int32_t point; + DoubleToStringConverter::DoubleToAscii( + input, + DoubleToStringConverter::DtoaMode::SHORTEST, + 0, + buffer, + sizeof(buffer), + &sign, + &length, + &point + ); + + return static_cast(length - point); } -FractionRounder Rounder::integer() { + +Precision Precision::unlimited() { + return Precision(RND_NONE, {}, kDefaultMode); +} + +FractionPrecision Precision::integer() { return constructFraction(0, 0); } -FractionRounder Rounder::fixedFraction(int32_t minMaxFractionPlaces) { +FractionPrecision Precision::fixedFraction(int32_t minMaxFractionPlaces) { if (minMaxFractionPlaces >= 0 && minMaxFractionPlaces <= kMaxIntFracSig) { return constructFraction(minMaxFractionPlaces, minMaxFractionPlaces); } else { @@ -62,7 +91,7 @@ FractionRounder Rounder::fixedFraction(int32_t minMaxFractionPlaces) { } } -FractionRounder Rounder::minFraction(int32_t minFractionPlaces) { +FractionPrecision Precision::minFraction(int32_t minFractionPlaces) { if (minFractionPlaces >= 0 && minFractionPlaces <= kMaxIntFracSig) { return constructFraction(minFractionPlaces, -1); } else { @@ -70,7 +99,7 @@ FractionRounder Rounder::minFraction(int32_t minFractionPlaces) { } } -FractionRounder Rounder::maxFraction(int32_t maxFractionPlaces) { +FractionPrecision Precision::maxFraction(int32_t maxFractionPlaces) { if (maxFractionPlaces >= 0 && maxFractionPlaces <= kMaxIntFracSig) { return constructFraction(0, maxFractionPlaces); } else { @@ -78,7 +107,7 @@ FractionRounder Rounder::maxFraction(int32_t maxFractionPlaces) { } } -FractionRounder Rounder::minMaxFraction(int32_t minFractionPlaces, int32_t maxFractionPlaces) { +FractionPrecision Precision::minMaxFraction(int32_t minFractionPlaces, int32_t maxFractionPlaces) { if (minFractionPlaces >= 0 && maxFractionPlaces <= kMaxIntFracSig && minFractionPlaces <= maxFractionPlaces) { return constructFraction(minFractionPlaces, maxFractionPlaces); @@ -87,7 +116,7 @@ FractionRounder Rounder::minMaxFraction(int32_t minFractionPlaces, int32_t maxFr } } -Rounder Rounder::fixedDigits(int32_t minMaxSignificantDigits) { +Precision Precision::fixedSignificantDigits(int32_t minMaxSignificantDigits) { if (minMaxSignificantDigits >= 1 && minMaxSignificantDigits <= kMaxIntFracSig) { return constructSignificant(minMaxSignificantDigits, minMaxSignificantDigits); } else { @@ -95,7 +124,7 @@ Rounder Rounder::fixedDigits(int32_t minMaxSignificantDigits) { } } -Rounder Rounder::minDigits(int32_t minSignificantDigits) { +Precision Precision::minSignificantDigits(int32_t minSignificantDigits) { if (minSignificantDigits >= 1 && minSignificantDigits <= kMaxIntFracSig) { return constructSignificant(minSignificantDigits, -1); } else { @@ -103,7 +132,7 @@ Rounder Rounder::minDigits(int32_t minSignificantDigits) { } } -Rounder Rounder::maxDigits(int32_t maxSignificantDigits) { +Precision Precision::maxSignificantDigits(int32_t maxSignificantDigits) { if (maxSignificantDigits >= 1 && maxSignificantDigits <= kMaxIntFracSig) { return constructSignificant(1, maxSignificantDigits); } else { @@ -111,7 +140,7 @@ Rounder Rounder::maxDigits(int32_t maxSignificantDigits) { } } -Rounder Rounder::minMaxDigits(int32_t minSignificantDigits, int32_t maxSignificantDigits) { +Precision Precision::minMaxSignificantDigits(int32_t minSignificantDigits, int32_t maxSignificantDigits) { if (minSignificantDigits >= 1 && maxSignificantDigits <= kMaxIntFracSig && minSignificantDigits <= maxSignificantDigits) { return constructSignificant(minSignificantDigits, maxSignificantDigits); @@ -120,7 +149,7 @@ Rounder Rounder::minMaxDigits(int32_t minSignificantDigits, int32_t maxSignifica } } -IncrementRounder Rounder::increment(double roundingIncrement) { +IncrementPrecision Precision::increment(double roundingIncrement) { if (roundingIncrement > 0.0) { return constructIncrement(roundingIncrement, 0); } else { @@ -128,16 +157,18 @@ IncrementRounder Rounder::increment(double roundingIncrement) { } } -CurrencyRounder Rounder::currency(UCurrencyUsage currencyUsage) { +CurrencyPrecision Precision::currency(UCurrencyUsage currencyUsage) { return constructCurrency(currencyUsage); } -Rounder Rounder::withMode(RoundingMode roundingMode) const { +Precision Precision::withMode(RoundingMode roundingMode) const { if (fType == RND_ERROR) { return *this; } // no-op in error state - return {fType, fUnion, roundingMode}; + Precision retval = *this; + retval.fRoundingMode = roundingMode; + return retval; } -Rounder FractionRounder::withMinDigits(int32_t minSignificantDigits) const { +Precision FractionPrecision::withMinDigits(int32_t minSignificantDigits) const { if (fType == RND_ERROR) { return *this; } // no-op in error state if (minSignificantDigits >= 1 && minSignificantDigits <= kMaxIntFracSig) { return constructFractionSignificant(*this, minSignificantDigits, -1); @@ -146,7 +177,7 @@ Rounder FractionRounder::withMinDigits(int32_t minSignificantDigits) const { } } -Rounder FractionRounder::withMaxDigits(int32_t maxSignificantDigits) const { +Precision FractionPrecision::withMaxDigits(int32_t maxSignificantDigits) const { if (fType == RND_ERROR) { return *this; } // no-op in error state if (maxSignificantDigits >= 1 && maxSignificantDigits <= kMaxIntFracSig) { return constructFractionSignificant(*this, -1, maxSignificantDigits); @@ -156,7 +187,7 @@ Rounder FractionRounder::withMaxDigits(int32_t maxSignificantDigits) const { } // Private method on base class -Rounder Rounder::withCurrency(const CurrencyUnit ¤cy, UErrorCode &status) const { +Precision Precision::withCurrency(const CurrencyUnit ¤cy, UErrorCode &status) const { if (fType == RND_ERROR) { return *this; } // no-op in error state U_ASSERT(fType == RND_CURRENCY); const char16_t *isoCode = currency.getISOCurrency(); @@ -170,17 +201,17 @@ Rounder Rounder::withCurrency(const CurrencyUnit ¤cy, UErrorCode &status) } } -// Public method on CurrencyRounder subclass -Rounder CurrencyRounder::withCurrency(const CurrencyUnit ¤cy) const { +// Public method on CurrencyPrecision subclass +Precision CurrencyPrecision::withCurrency(const CurrencyUnit ¤cy) const { UErrorCode localStatus = U_ZERO_ERROR; - Rounder result = Rounder::withCurrency(currency, localStatus); + Precision result = Precision::withCurrency(currency, localStatus); if (U_FAILURE(localStatus)) { return {localStatus}; } return result; } -Rounder IncrementRounder::withMinFraction(int32_t minFrac) const { +Precision IncrementPrecision::withMinFraction(int32_t minFrac) const { if (fType == RND_ERROR) { return *this; } // no-op in error state if (minFrac >= 0 && minFrac <= kMaxIntFracSig) { return constructIncrement(fUnion.increment.fIncrement, minFrac); @@ -189,67 +220,77 @@ Rounder IncrementRounder::withMinFraction(int32_t minFrac) const { } } -FractionRounder Rounder::constructFraction(int32_t minFrac, int32_t maxFrac) { +FractionPrecision Precision::constructFraction(int32_t minFrac, int32_t maxFrac) { FractionSignificantSettings settings; settings.fMinFrac = static_cast(minFrac); settings.fMaxFrac = static_cast(maxFrac); settings.fMinSig = -1; settings.fMaxSig = -1; - RounderUnion union_; + PrecisionUnion union_; union_.fracSig = settings; return {RND_FRACTION, union_, kDefaultMode}; } -Rounder Rounder::constructSignificant(int32_t minSig, int32_t maxSig) { +Precision Precision::constructSignificant(int32_t minSig, int32_t maxSig) { FractionSignificantSettings settings; settings.fMinFrac = -1; settings.fMaxFrac = -1; settings.fMinSig = static_cast(minSig); settings.fMaxSig = static_cast(maxSig); - RounderUnion union_; + PrecisionUnion union_; union_.fracSig = settings; return {RND_SIGNIFICANT, union_, kDefaultMode}; } -Rounder -Rounder::constructFractionSignificant(const FractionRounder &base, int32_t minSig, int32_t maxSig) { +Precision +Precision::constructFractionSignificant(const FractionPrecision &base, int32_t minSig, int32_t maxSig) { FractionSignificantSettings settings = base.fUnion.fracSig; settings.fMinSig = static_cast(minSig); settings.fMaxSig = static_cast(maxSig); - RounderUnion union_; + PrecisionUnion union_; union_.fracSig = settings; return {RND_FRACTION_SIGNIFICANT, union_, kDefaultMode}; } -IncrementRounder Rounder::constructIncrement(double increment, int32_t minFrac) { +IncrementPrecision Precision::constructIncrement(double increment, int32_t minFrac) { IncrementSettings settings; settings.fIncrement = increment; settings.fMinFrac = static_cast(minFrac); - RounderUnion union_; + // One of the few pre-computed quantities: + // Note: it is possible for minFrac to be more than maxFrac... (misleading) + settings.fMaxFrac = roundingutils::doubleFractionLength(increment); + PrecisionUnion union_; union_.increment = settings; return {RND_INCREMENT, union_, kDefaultMode}; } -CurrencyRounder Rounder::constructCurrency(UCurrencyUsage usage) { - RounderUnion union_; +CurrencyPrecision Precision::constructCurrency(UCurrencyUsage usage) { + PrecisionUnion union_; union_.currencyUsage = usage; return {RND_CURRENCY, union_, kDefaultMode}; } -Rounder Rounder::constructPassThrough() { - RounderUnion union_; - union_.errorCode = U_ZERO_ERROR; // initialize the variable - return {RND_PASS_THROUGH, union_, kDefaultMode}; -} -void Rounder::setLocaleData(const CurrencyUnit ¤cy, UErrorCode &status) { - if (fType == RND_CURRENCY) { - *this = withCurrency(currency, status); +RoundingImpl::RoundingImpl(const Precision& precision, UNumberFormatRoundingMode roundingMode, + const CurrencyUnit& currency, UErrorCode& status) + : fPrecision(precision), fRoundingMode(roundingMode), fPassThrough(false) { + if (precision.fType == Precision::RND_CURRENCY) { + fPrecision = precision.withCurrency(currency, status); } } +RoundingImpl RoundingImpl::passThrough() { + RoundingImpl retval; + retval.fPassThrough = true; + return retval; +} + +bool RoundingImpl::isSignificantDigits() const { + return fPrecision.fType == Precision::RND_SIGNIFICANT; +} + int32_t -Rounder::chooseMultiplierAndApply(impl::DecimalQuantity &input, const impl::MultiplierProducer &producer, +RoundingImpl::chooseMultiplierAndApply(impl::DecimalQuantity &input, const impl::MultiplierProducer &producer, UErrorCode &status) { // Do not call this method with zero. U_ASSERT(!input.isZero()); @@ -287,45 +328,59 @@ Rounder::chooseMultiplierAndApply(impl::DecimalQuantity &input, const impl::Mult } /** This is the method that contains the actual rounding logic. */ -void Rounder::apply(impl::DecimalQuantity &value, UErrorCode& status) const { - switch (fType) { - case RND_BOGUS: - case RND_ERROR: +void RoundingImpl::apply(impl::DecimalQuantity &value, UErrorCode& status) const { + if (fPassThrough) { + return; + } + switch (fPrecision.fType) { + case Precision::RND_BOGUS: + case Precision::RND_ERROR: // Errors should be caught before the apply() method is called status = U_INTERNAL_PROGRAM_ERROR; break; - case RND_NONE: + case Precision::RND_NONE: value.roundToInfinity(); break; - case RND_FRACTION: + case Precision::RND_FRACTION: value.roundToMagnitude( - getRoundingMagnitudeFraction(fUnion.fracSig.fMaxFrac), fRoundingMode, status); - value.setFractionLength( - uprv_max(0, -getDisplayMagnitudeFraction(fUnion.fracSig.fMinFrac)), INT32_MAX); - break; - - case RND_SIGNIFICANT: - value.roundToMagnitude( - getRoundingMagnitudeSignificant(value, fUnion.fracSig.fMaxSig), + getRoundingMagnitudeFraction(fPrecision.fUnion.fracSig.fMaxFrac), fRoundingMode, status); value.setFractionLength( - uprv_max(0, -getDisplayMagnitudeSignificant(value, fUnion.fracSig.fMinSig)), + uprv_max(0, -getDisplayMagnitudeFraction(fPrecision.fUnion.fracSig.fMinFrac)), INT32_MAX); break; - case RND_FRACTION_SIGNIFICANT: { - int32_t displayMag = getDisplayMagnitudeFraction(fUnion.fracSig.fMinFrac); - int32_t roundingMag = getRoundingMagnitudeFraction(fUnion.fracSig.fMaxFrac); - if (fUnion.fracSig.fMinSig == -1) { + case Precision::RND_SIGNIFICANT: + value.roundToMagnitude( + getRoundingMagnitudeSignificant(value, fPrecision.fUnion.fracSig.fMaxSig), + fRoundingMode, + status); + value.setFractionLength( + uprv_max(0, -getDisplayMagnitudeSignificant(value, fPrecision.fUnion.fracSig.fMinSig)), + INT32_MAX); + // Make sure that digits are displayed on zero. + if (value.isZero() && fPrecision.fUnion.fracSig.fMinSig > 0) { + value.setIntegerLength(1, INT32_MAX); + } + break; + + case Precision::RND_FRACTION_SIGNIFICANT: { + int32_t displayMag = getDisplayMagnitudeFraction(fPrecision.fUnion.fracSig.fMinFrac); + int32_t roundingMag = getRoundingMagnitudeFraction(fPrecision.fUnion.fracSig.fMaxFrac); + if (fPrecision.fUnion.fracSig.fMinSig == -1) { // Max Sig override - int32_t candidate = getRoundingMagnitudeSignificant(value, fUnion.fracSig.fMaxSig); + int32_t candidate = getRoundingMagnitudeSignificant( + value, + fPrecision.fUnion.fracSig.fMaxSig); roundingMag = uprv_max(roundingMag, candidate); } else { // Min Sig override - int32_t candidate = getDisplayMagnitudeSignificant(value, fUnion.fracSig.fMinSig); + int32_t candidate = getDisplayMagnitudeSignificant( + value, + fPrecision.fUnion.fracSig.fMinSig); roundingMag = uprv_min(roundingMag, candidate); } value.roundToMagnitude(roundingMag, fRoundingMode, status); @@ -333,27 +388,27 @@ void Rounder::apply(impl::DecimalQuantity &value, UErrorCode& status) const { break; } - case RND_INCREMENT: + case Precision::RND_INCREMENT: value.roundToIncrement( - fUnion.increment.fIncrement, fRoundingMode, fUnion.increment.fMinFrac, status); - value.setFractionLength(fUnion.increment.fMinFrac, fUnion.increment.fMinFrac); + fPrecision.fUnion.increment.fIncrement, + fRoundingMode, + fPrecision.fUnion.increment.fMaxFrac, + status); + value.setFractionLength(fPrecision.fUnion.increment.fMinFrac, INT32_MAX); break; - case RND_CURRENCY: + case Precision::RND_CURRENCY: // Call .withCurrency() before .apply()! U_ASSERT(false); break; - - case RND_PASS_THROUGH: - break; } } -void Rounder::apply(impl::DecimalQuantity &value, int32_t minInt, UErrorCode /*status*/) { +void RoundingImpl::apply(impl::DecimalQuantity &value, int32_t minInt, UErrorCode /*status*/) { // This method is intended for the one specific purpose of helping print "00.000E0". - U_ASSERT(fType == RND_SIGNIFICANT); + U_ASSERT(isSignificantDigits()); U_ASSERT(value.isZero()); - value.setFractionLength(fUnion.fracSig.fMinSig - minInt, INT32_MAX); + value.setFractionLength(fPrecision.fUnion.fracSig.fMinSig - minInt, INT32_MAX); } #endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/deps/icu-small/source/i18n/number_roundingutils.h b/deps/icu-small/source/i18n/number_roundingutils.h index 6868ee0b868..66d58bb775b 100644 --- a/deps/icu-small/source/i18n/number_roundingutils.h +++ b/deps/icu-small/source/i18n/number_roundingutils.h @@ -3,7 +3,7 @@ #include "unicode/utypes.h" -#if !UCONFIG_NO_FORMATTING && !UPRV_INCOMPLETE_CPP11_SUPPORT +#if !UCONFIG_NO_FORMATTING #ifndef __NUMBER_ROUNDINGUTILS_H__ #define __NUMBER_ROUNDINGUTILS_H__ @@ -131,7 +131,62 @@ inline bool roundsAtMidpoint(int roundingMode) { } } +/** + * Computes the number of fraction digits in a double. Used for computing maxFrac for an increment. + * Calls into the DoubleToStringConverter library to do so. + */ +digits_t doubleFractionLength(double input); + } // namespace roundingutils + + +/** + * Encapsulates a Precision and a RoundingMode and performs rounding on a DecimalQuantity. + * + * This class does not exist in Java: instead, the base Precision class is used. + */ +class RoundingImpl { + public: + RoundingImpl() = default; // default constructor: leaves object in undefined state + + RoundingImpl(const Precision& precision, UNumberFormatRoundingMode roundingMode, + const CurrencyUnit& currency, UErrorCode& status); + + static RoundingImpl passThrough(); + + /** Required for ScientificFormatter */ + bool isSignificantDigits() const; + + /** + * Rounding endpoint used by Engineering and Compact notation. Chooses the most appropriate multiplier (magnitude + * adjustment), applies the adjustment, rounds, and returns the chosen multiplier. + * + *

+ * In most cases, this is simple. However, when rounding the number causes it to cross a multiplier boundary, we + * need to re-do the rounding. For example, to display 999,999 in Engineering notation with 2 sigfigs, first you + * guess the multiplier to be -3. However, then you end up getting 1000E3, which is not the correct output. You then + * change your multiplier to be -6, and you get 1.0E6, which is correct. + * + * @param input The quantity to process. + * @param producer Function to call to return a multiplier based on a magnitude. + * @return The number of orders of magnitude the input was adjusted by this method. + */ + int32_t + chooseMultiplierAndApply(impl::DecimalQuantity &input, const impl::MultiplierProducer &producer, + UErrorCode &status); + + void apply(impl::DecimalQuantity &value, UErrorCode &status) const; + + /** Version of {@link #apply} that obeys minInt constraints. Used for scientific notation compatibility mode. */ + void apply(impl::DecimalQuantity &value, int32_t minInt, UErrorCode status); + + private: + Precision fPrecision; + UNumberFormatRoundingMode fRoundingMode; + bool fPassThrough; +}; + + } // namespace impl } // namespace number U_NAMESPACE_END diff --git a/deps/icu-small/source/i18n/number_scientific.cpp b/deps/icu-small/source/i18n/number_scientific.cpp index a2f2bf85a1f..40952024e99 100644 --- a/deps/icu-small/source/i18n/number_scientific.cpp +++ b/deps/icu-small/source/i18n/number_scientific.cpp @@ -3,13 +3,14 @@ #include "unicode/utypes.h" -#if !UCONFIG_NO_FORMATTING && !UPRV_INCOMPLETE_CPP11_SUPPORT +#if !UCONFIG_NO_FORMATTING #include #include "number_scientific.h" #include "number_utils.h" #include "number_stringbuilder.h" #include "unicode/unum.h" +#include "number_microprops.h" using namespace icu; using namespace icu::number; @@ -64,8 +65,13 @@ int32_t ScientificModifier::apply(NumberStringBuilder &output, int32_t /*leftInd int32_t disp = std::abs(fExponent); for (int j = 0; j < fHandler->fSettings.fMinExponentDigits || disp > 0; j++, disp /= 10) { auto d = static_cast(disp % 10); - const UnicodeString &digitString = getDigitFromSymbols(d, *fHandler->fSymbols); - i += output.insert(i - j, digitString, UNUM_EXPONENT_FIELD, status); + i += utils::insertDigitFromSymbols( + output, + i - j, + d, + *fHandler->fSymbols, + UNUM_EXPONENT_FIELD, + status); } return i - rightIndex; } @@ -101,22 +107,25 @@ void ScientificHandler::processQuantity(DecimalQuantity &quantity, MicroProps &m // Treat zero as if it had magnitude 0 int32_t exponent; if (quantity.isZero()) { - if (fSettings.fRequireMinInt && micros.rounding.fType == Rounder::RND_SIGNIFICANT) { + if (fSettings.fRequireMinInt && micros.rounder.isSignificantDigits()) { // Show "00.000E0" on pattern "00.000E0" - micros.rounding.apply(quantity, fSettings.fEngineeringInterval, status); + micros.rounder.apply(quantity, fSettings.fEngineeringInterval, status); exponent = 0; } else { - micros.rounding.apply(quantity, status); + micros.rounder.apply(quantity, status); exponent = 0; } } else { - exponent = -micros.rounding.chooseMultiplierAndApply(quantity, *this, status); + exponent = -micros.rounder.chooseMultiplierAndApply(quantity, *this, status); } // Use MicroProps's helper ScientificModifier and save it as the modInner. ScientificModifier &mod = micros.helpers.scientificModifier; mod.set(exponent, this); micros.modInner = &mod; + + // We already performed rounding. Do not perform it again. + micros.rounder = RoundingImpl::passThrough(); } int32_t ScientificHandler::getMultiplier(int32_t magnitude) const { diff --git a/deps/icu-small/source/i18n/number_scientific.h b/deps/icu-small/source/i18n/number_scientific.h index f5e4d30e6a9..974ab3adb61 100644 --- a/deps/icu-small/source/i18n/number_scientific.h +++ b/deps/icu-small/source/i18n/number_scientific.h @@ -3,7 +3,7 @@ #include "unicode/utypes.h" -#if !UCONFIG_NO_FORMATTING && !UPRV_INCOMPLETE_CPP11_SUPPORT +#if !UCONFIG_NO_FORMATTING #ifndef __NUMBER_SCIENTIFIC_H__ #define __NUMBER_SCIENTIFIC_H__ diff --git a/deps/icu-small/source/i18n/number_skeletons.cpp b/deps/icu-small/source/i18n/number_skeletons.cpp new file mode 100644 index 00000000000..c7bb18b5f3d --- /dev/null +++ b/deps/icu-small/source/i18n/number_skeletons.cpp @@ -0,0 +1,1510 @@ +// © 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 "number_decnum.h" +#include "number_skeletons.h" +#include "umutex.h" +#include "ucln_in.h" +#include "patternprops.h" +#include "unicode/ucharstriebuilder.h" +#include "number_utils.h" +#include "number_decimalquantity.h" +#include "unicode/numberformatter.h" +#include "uinvchar.h" +#include "charstr.h" + +using namespace icu; +using namespace icu::number; +using namespace icu::number::impl; +using namespace icu::number::impl::skeleton; + +namespace { + +icu::UInitOnce gNumberSkeletonsInitOnce = U_INITONCE_INITIALIZER; + +char16_t* kSerializedStemTrie = nullptr; + +UBool U_CALLCONV cleanupNumberSkeletons() { + uprv_free(kSerializedStemTrie); + kSerializedStemTrie = nullptr; + gNumberSkeletonsInitOnce.reset(); + return TRUE; +} + +void U_CALLCONV initNumberSkeletons(UErrorCode& status) { + ucln_i18n_registerCleanup(UCLN_I18N_NUMBER_SKELETONS, cleanupNumberSkeletons); + + UCharsTrieBuilder b(status); + if (U_FAILURE(status)) { return; } + + // Section 1: + b.add(u"compact-short", STEM_COMPACT_SHORT, status); + b.add(u"compact-long", STEM_COMPACT_LONG, status); + b.add(u"scientific", STEM_SCIENTIFIC, status); + b.add(u"engineering", STEM_ENGINEERING, status); + b.add(u"notation-simple", STEM_NOTATION_SIMPLE, status); + b.add(u"base-unit", STEM_BASE_UNIT, status); + b.add(u"percent", STEM_PERCENT, status); + b.add(u"permille", STEM_PERMILLE, status); + b.add(u"precision-integer", STEM_PRECISION_INTEGER, status); + b.add(u"precision-unlimited", STEM_PRECISION_UNLIMITED, status); + b.add(u"precision-currency-standard", STEM_PRECISION_CURRENCY_STANDARD, status); + b.add(u"precision-currency-cash", STEM_PRECISION_CURRENCY_CASH, status); + b.add(u"rounding-mode-ceiling", STEM_ROUNDING_MODE_CEILING, status); + b.add(u"rounding-mode-floor", STEM_ROUNDING_MODE_FLOOR, status); + b.add(u"rounding-mode-down", STEM_ROUNDING_MODE_DOWN, status); + b.add(u"rounding-mode-up", STEM_ROUNDING_MODE_UP, status); + b.add(u"rounding-mode-half-even", STEM_ROUNDING_MODE_HALF_EVEN, status); + b.add(u"rounding-mode-half-down", STEM_ROUNDING_MODE_HALF_DOWN, status); + b.add(u"rounding-mode-half-up", STEM_ROUNDING_MODE_HALF_UP, status); + b.add(u"rounding-mode-unnecessary", STEM_ROUNDING_MODE_UNNECESSARY, status); + b.add(u"group-off", STEM_GROUP_OFF, status); + b.add(u"group-min2", STEM_GROUP_MIN2, status); + b.add(u"group-auto", STEM_GROUP_AUTO, status); + b.add(u"group-on-aligned", STEM_GROUP_ON_ALIGNED, status); + b.add(u"group-thousands", STEM_GROUP_THOUSANDS, status); + b.add(u"latin", STEM_LATIN, status); + b.add(u"unit-width-narrow", STEM_UNIT_WIDTH_NARROW, status); + b.add(u"unit-width-short", STEM_UNIT_WIDTH_SHORT, status); + b.add(u"unit-width-full-name", STEM_UNIT_WIDTH_FULL_NAME, status); + b.add(u"unit-width-iso-code", STEM_UNIT_WIDTH_ISO_CODE, status); + b.add(u"unit-width-hidden", STEM_UNIT_WIDTH_HIDDEN, status); + b.add(u"sign-auto", STEM_SIGN_AUTO, status); + b.add(u"sign-always", STEM_SIGN_ALWAYS, status); + b.add(u"sign-never", STEM_SIGN_NEVER, status); + b.add(u"sign-accounting", STEM_SIGN_ACCOUNTING, status); + b.add(u"sign-accounting-always", STEM_SIGN_ACCOUNTING_ALWAYS, status); + b.add(u"sign-except-zero", STEM_SIGN_EXCEPT_ZERO, status); + b.add(u"sign-accounting-except-zero", STEM_SIGN_ACCOUNTING_EXCEPT_ZERO, status); + b.add(u"decimal-auto", STEM_DECIMAL_AUTO, status); + b.add(u"decimal-always", STEM_DECIMAL_ALWAYS, status); + if (U_FAILURE(status)) { return; } + + // Section 2: + b.add(u"precision-increment", STEM_PRECISION_INCREMENT, status); + b.add(u"measure-unit", STEM_MEASURE_UNIT, status); + b.add(u"per-measure-unit", STEM_PER_MEASURE_UNIT, status); + b.add(u"currency", STEM_CURRENCY, status); + b.add(u"integer-width", STEM_INTEGER_WIDTH, status); + b.add(u"numbering-system", STEM_NUMBERING_SYSTEM, status); + b.add(u"scale", STEM_SCALE, status); + if (U_FAILURE(status)) { return; } + + // Build the CharsTrie + // TODO: Use SLOW or FAST here? + UnicodeString result; + b.buildUnicodeString(USTRINGTRIE_BUILD_FAST, result, status); + if (U_FAILURE(status)) { return; } + + // Copy the result into the global constant pointer + size_t numBytes = result.length() * sizeof(char16_t); + kSerializedStemTrie = static_cast(uprv_malloc(numBytes)); + uprv_memcpy(kSerializedStemTrie, result.getBuffer(), numBytes); +} + + +inline void appendMultiple(UnicodeString& sb, UChar32 cp, int32_t count) { + for (int i = 0; i < count; i++) { + sb.append(cp); + } +} + + +#define CHECK_NULL(seen, field, status) (void)(seen); /* for auto-format line wrapping */ \ +{ \ + if ((seen).field) { \ + (status) = U_NUMBER_SKELETON_SYNTAX_ERROR; \ + return STATE_NULL; \ + } \ + (seen).field = true; \ +} + + +#define SKELETON_UCHAR_TO_CHAR(dest, src, start, end, status) (void)(dest); \ +{ \ + UErrorCode conversionStatus = U_ZERO_ERROR; \ + (dest).appendInvariantChars({FALSE, (src).getBuffer() + (start), (end) - (start)}, conversionStatus); \ + if (conversionStatus == U_INVARIANT_CONVERSION_ERROR) { \ + /* Don't propagate the invariant conversion error; it is a skeleton syntax error */ \ + (status) = U_NUMBER_SKELETON_SYNTAX_ERROR; \ + return; \ + } else if (U_FAILURE(conversionStatus)) { \ + (status) = conversionStatus; \ + return; \ + } \ +} + + +} // anonymous namespace + + +Notation stem_to_object::notation(skeleton::StemEnum stem) { + switch (stem) { + case STEM_COMPACT_SHORT: + return Notation::compactShort(); + case STEM_COMPACT_LONG: + return Notation::compactLong(); + case STEM_SCIENTIFIC: + return Notation::scientific(); + case STEM_ENGINEERING: + return Notation::engineering(); + case STEM_NOTATION_SIMPLE: + return Notation::simple(); + default: + U_ASSERT(false); + return Notation::simple(); // return a value: silence compiler warning + } +} + +MeasureUnit stem_to_object::unit(skeleton::StemEnum stem) { + switch (stem) { + case STEM_BASE_UNIT: + // Slicing is okay + return NoUnit::base(); // NOLINT + case STEM_PERCENT: + // Slicing is okay + return NoUnit::percent(); // NOLINT + case STEM_PERMILLE: + // Slicing is okay + return NoUnit::permille(); // NOLINT + default: + U_ASSERT(false); + return {}; // return a value: silence compiler warning + } +} + +Precision stem_to_object::precision(skeleton::StemEnum stem) { + switch (stem) { + case STEM_PRECISION_INTEGER: + return Precision::integer(); + case STEM_PRECISION_UNLIMITED: + return Precision::unlimited(); + case STEM_PRECISION_CURRENCY_STANDARD: + return Precision::currency(UCURR_USAGE_STANDARD); + case STEM_PRECISION_CURRENCY_CASH: + return Precision::currency(UCURR_USAGE_CASH); + default: + U_ASSERT(false); + return Precision::integer(); // return a value: silence compiler warning + } +} + +UNumberFormatRoundingMode stem_to_object::roundingMode(skeleton::StemEnum stem) { + switch (stem) { + case STEM_ROUNDING_MODE_CEILING: + return UNUM_ROUND_CEILING; + case STEM_ROUNDING_MODE_FLOOR: + return UNUM_ROUND_FLOOR; + case STEM_ROUNDING_MODE_DOWN: + return UNUM_ROUND_DOWN; + case STEM_ROUNDING_MODE_UP: + return UNUM_ROUND_UP; + case STEM_ROUNDING_MODE_HALF_EVEN: + return UNUM_ROUND_HALFEVEN; + case STEM_ROUNDING_MODE_HALF_DOWN: + return UNUM_ROUND_HALFDOWN; + case STEM_ROUNDING_MODE_HALF_UP: + return UNUM_ROUND_HALFUP; + case STEM_ROUNDING_MODE_UNNECESSARY: + return UNUM_ROUND_UNNECESSARY; + default: + U_ASSERT(false); + return UNUM_ROUND_UNNECESSARY; + } +} + +UGroupingStrategy stem_to_object::groupingStrategy(skeleton::StemEnum stem) { + switch (stem) { + case STEM_GROUP_OFF: + return UNUM_GROUPING_OFF; + case STEM_GROUP_MIN2: + return UNUM_GROUPING_MIN2; + case STEM_GROUP_AUTO: + return UNUM_GROUPING_AUTO; + case STEM_GROUP_ON_ALIGNED: + return UNUM_GROUPING_ON_ALIGNED; + case STEM_GROUP_THOUSANDS: + return UNUM_GROUPING_THOUSANDS; + default: + return UNUM_GROUPING_COUNT; // for objects, throw; for enums, return COUNT + } +} + +UNumberUnitWidth stem_to_object::unitWidth(skeleton::StemEnum stem) { + switch (stem) { + case STEM_UNIT_WIDTH_NARROW: + return UNUM_UNIT_WIDTH_NARROW; + case STEM_UNIT_WIDTH_SHORT: + return UNUM_UNIT_WIDTH_SHORT; + case STEM_UNIT_WIDTH_FULL_NAME: + return UNUM_UNIT_WIDTH_FULL_NAME; + case STEM_UNIT_WIDTH_ISO_CODE: + return UNUM_UNIT_WIDTH_ISO_CODE; + case STEM_UNIT_WIDTH_HIDDEN: + return UNUM_UNIT_WIDTH_HIDDEN; + default: + return UNUM_UNIT_WIDTH_COUNT; // for objects, throw; for enums, return COUNT + } +} + +UNumberSignDisplay stem_to_object::signDisplay(skeleton::StemEnum stem) { + switch (stem) { + case STEM_SIGN_AUTO: + return UNUM_SIGN_AUTO; + case STEM_SIGN_ALWAYS: + return UNUM_SIGN_ALWAYS; + case STEM_SIGN_NEVER: + return UNUM_SIGN_NEVER; + case STEM_SIGN_ACCOUNTING: + return UNUM_SIGN_ACCOUNTING; + case STEM_SIGN_ACCOUNTING_ALWAYS: + return UNUM_SIGN_ACCOUNTING_ALWAYS; + case STEM_SIGN_EXCEPT_ZERO: + return UNUM_SIGN_EXCEPT_ZERO; + case STEM_SIGN_ACCOUNTING_EXCEPT_ZERO: + return UNUM_SIGN_ACCOUNTING_EXCEPT_ZERO; + default: + return UNUM_SIGN_COUNT; // for objects, throw; for enums, return COUNT + } +} + +UNumberDecimalSeparatorDisplay stem_to_object::decimalSeparatorDisplay(skeleton::StemEnum stem) { + switch (stem) { + case STEM_DECIMAL_AUTO: + return UNUM_DECIMAL_SEPARATOR_AUTO; + case STEM_DECIMAL_ALWAYS: + return UNUM_DECIMAL_SEPARATOR_ALWAYS; + default: + return UNUM_DECIMAL_SEPARATOR_COUNT; // for objects, throw; for enums, return COUNT + } +} + + +void enum_to_stem_string::roundingMode(UNumberFormatRoundingMode value, UnicodeString& sb) { + switch (value) { + case UNUM_ROUND_CEILING: + sb.append(u"rounding-mode-ceiling", -1); + break; + case UNUM_ROUND_FLOOR: + sb.append(u"rounding-mode-floor", -1); + break; + case UNUM_ROUND_DOWN: + sb.append(u"rounding-mode-down", -1); + break; + case UNUM_ROUND_UP: + sb.append(u"rounding-mode-up", -1); + break; + case UNUM_ROUND_HALFEVEN: + sb.append(u"rounding-mode-half-even", -1); + break; + case UNUM_ROUND_HALFDOWN: + sb.append(u"rounding-mode-half-down", -1); + break; + case UNUM_ROUND_HALFUP: + sb.append(u"rounding-mode-half-up", -1); + break; + case UNUM_ROUND_UNNECESSARY: + sb.append(u"rounding-mode-unnecessary", -1); + break; + default: + U_ASSERT(false); + } +} + +void enum_to_stem_string::groupingStrategy(UGroupingStrategy value, UnicodeString& sb) { + switch (value) { + case UNUM_GROUPING_OFF: + sb.append(u"group-off", -1); + break; + case UNUM_GROUPING_MIN2: + sb.append(u"group-min2", -1); + break; + case UNUM_GROUPING_AUTO: + sb.append(u"group-auto", -1); + break; + case UNUM_GROUPING_ON_ALIGNED: + sb.append(u"group-on-aligned", -1); + break; + case UNUM_GROUPING_THOUSANDS: + sb.append(u"group-thousands", -1); + break; + default: + U_ASSERT(false); + } +} + +void enum_to_stem_string::unitWidth(UNumberUnitWidth value, UnicodeString& sb) { + switch (value) { + case UNUM_UNIT_WIDTH_NARROW: + sb.append(u"unit-width-narrow", -1); + break; + case UNUM_UNIT_WIDTH_SHORT: + sb.append(u"unit-width-short", -1); + break; + case UNUM_UNIT_WIDTH_FULL_NAME: + sb.append(u"unit-width-full-name", -1); + break; + case UNUM_UNIT_WIDTH_ISO_CODE: + sb.append(u"unit-width-iso-code", -1); + break; + case UNUM_UNIT_WIDTH_HIDDEN: + sb.append(u"unit-width-hidden", -1); + break; + default: + U_ASSERT(false); + } +} + +void enum_to_stem_string::signDisplay(UNumberSignDisplay value, UnicodeString& sb) { + switch (value) { + case UNUM_SIGN_AUTO: + sb.append(u"sign-auto", -1); + break; + case UNUM_SIGN_ALWAYS: + sb.append(u"sign-always", -1); + break; + case UNUM_SIGN_NEVER: + sb.append(u"sign-never", -1); + break; + case UNUM_SIGN_ACCOUNTING: + sb.append(u"sign-accounting", -1); + break; + case UNUM_SIGN_ACCOUNTING_ALWAYS: + sb.append(u"sign-accounting-always", -1); + break; + case UNUM_SIGN_EXCEPT_ZERO: + sb.append(u"sign-except-zero", -1); + break; + case UNUM_SIGN_ACCOUNTING_EXCEPT_ZERO: + sb.append(u"sign-accounting-except-zero", -1); + break; + default: + U_ASSERT(false); + } +} + +void +enum_to_stem_string::decimalSeparatorDisplay(UNumberDecimalSeparatorDisplay value, UnicodeString& sb) { + switch (value) { + case UNUM_DECIMAL_SEPARATOR_AUTO: + sb.append(u"decimal-auto", -1); + break; + case UNUM_DECIMAL_SEPARATOR_ALWAYS: + sb.append(u"decimal-always", -1); + break; + default: + U_ASSERT(false); + } +} + + +UnlocalizedNumberFormatter skeleton::create(const UnicodeString& skeletonString, UErrorCode& status) { + umtx_initOnce(gNumberSkeletonsInitOnce, &initNumberSkeletons, status); + MacroProps macros = parseSkeleton(skeletonString, status); + return NumberFormatter::with().macros(macros); +} + +UnicodeString skeleton::generate(const MacroProps& macros, UErrorCode& status) { + umtx_initOnce(gNumberSkeletonsInitOnce, &initNumberSkeletons, status); + UnicodeString sb; + GeneratorHelpers::generateSkeleton(macros, sb, status); + return sb; +} + +MacroProps skeleton::parseSkeleton(const UnicodeString& skeletonString, UErrorCode& status) { + if (U_FAILURE(status)) { return MacroProps(); } + + // Add a trailing whitespace to the end of the skeleton string to make code cleaner. + UnicodeString tempSkeletonString(skeletonString); + tempSkeletonString.append(u' '); + + SeenMacroProps seen; + MacroProps macros; + StringSegment segment(tempSkeletonString, false); + UCharsTrie stemTrie(kSerializedStemTrie); + ParseState stem = STATE_NULL; + int32_t offset = 0; + + // Primary skeleton parse loop: + while (offset < segment.length()) { + UChar32 cp = segment.codePointAt(offset); + bool isTokenSeparator = PatternProps::isWhiteSpace(cp); + bool isOptionSeparator = (cp == u'/'); + + if (!isTokenSeparator && !isOptionSeparator) { + // Non-separator token; consume it. + offset += U16_LENGTH(cp); + if (stem == STATE_NULL) { + // We are currently consuming a stem. + // Go to the next state in the stem trie. + stemTrie.nextForCodePoint(cp); + } + continue; + } + + // We are looking at a token or option separator. + // If the segment is nonempty, parse it and reset the segment. + // Otherwise, make sure it is a valid repeating separator. + if (offset != 0) { + segment.setLength(offset); + if (stem == STATE_NULL) { + // The first separator after the start of a token. Parse it as a stem. + stem = parseStem(segment, stemTrie, seen, macros, status); + stemTrie.reset(); + } else { + // A separator after the first separator of a token. Parse it as an option. + stem = parseOption(stem, segment, macros, status); + } + segment.resetLength(); + if (U_FAILURE(status)) { return macros; } + + // Consume the segment: + segment.adjustOffset(offset); + offset = 0; + + } else if (stem != STATE_NULL) { + // A separator ('/' or whitespace) following an option separator ('/') + // segment.setLength(U16_LENGTH(cp)); // for error message + // throw new SkeletonSyntaxException("Unexpected separator character", segment); + status = U_NUMBER_SKELETON_SYNTAX_ERROR; + return macros; + + } else { + // Two spaces in a row; this is OK. + } + + // Does the current stem forbid options? + if (isOptionSeparator && stem == STATE_NULL) { + // segment.setLength(U16_LENGTH(cp)); // for error message + // throw new SkeletonSyntaxException("Unexpected option separator", segment); + status = U_NUMBER_SKELETON_SYNTAX_ERROR; + return macros; + } + + // Does the current stem require an option? + if (isTokenSeparator && stem != STATE_NULL) { + switch (stem) { + case STATE_INCREMENT_PRECISION: + case STATE_MEASURE_UNIT: + case STATE_PER_MEASURE_UNIT: + case STATE_CURRENCY_UNIT: + case STATE_INTEGER_WIDTH: + case STATE_NUMBERING_SYSTEM: + case STATE_SCALE: + // segment.setLength(U16_LENGTH(cp)); // for error message + // throw new SkeletonSyntaxException("Stem requires an option", segment); + status = U_NUMBER_SKELETON_SYNTAX_ERROR; + return macros; + default: + break; + } + stem = STATE_NULL; + } + + // Consume the separator: + segment.adjustOffset(U16_LENGTH(cp)); + } + U_ASSERT(stem == STATE_NULL); + return macros; +} + +ParseState +skeleton::parseStem(const StringSegment& segment, const UCharsTrie& stemTrie, SeenMacroProps& seen, + MacroProps& macros, UErrorCode& status) { + // First check for "blueprint" stems, which start with a "signal char" + switch (segment.charAt(0)) { + case u'.': + CHECK_NULL(seen, precision, status); + blueprint_helpers::parseFractionStem(segment, macros, status); + return STATE_FRACTION_PRECISION; + case u'@': + CHECK_NULL(seen, precision, status); + blueprint_helpers::parseDigitsStem(segment, macros, status); + return STATE_NULL; + default: + break; + } + + // Now look at the stemsTrie, which is already be pointing at our stem. + UStringTrieResult stemResult = stemTrie.current(); + + if (stemResult != USTRINGTRIE_INTERMEDIATE_VALUE && stemResult != USTRINGTRIE_FINAL_VALUE) { + // throw new SkeletonSyntaxException("Unknown stem", segment); + status = U_NUMBER_SKELETON_SYNTAX_ERROR; + return STATE_NULL; + } + + auto stem = static_cast(stemTrie.getValue()); + switch (stem) { + + // Stems with meaning on their own, not requiring an option: + + case STEM_COMPACT_SHORT: + case STEM_COMPACT_LONG: + case STEM_SCIENTIFIC: + case STEM_ENGINEERING: + case STEM_NOTATION_SIMPLE: + CHECK_NULL(seen, notation, status); + macros.notation = stem_to_object::notation(stem); + switch (stem) { + case STEM_SCIENTIFIC: + case STEM_ENGINEERING: + return STATE_SCIENTIFIC; // allows for scientific options + default: + return STATE_NULL; + } + + case STEM_BASE_UNIT: + case STEM_PERCENT: + case STEM_PERMILLE: + CHECK_NULL(seen, unit, status); + macros.unit = stem_to_object::unit(stem); + return STATE_NULL; + + case STEM_PRECISION_INTEGER: + case STEM_PRECISION_UNLIMITED: + case STEM_PRECISION_CURRENCY_STANDARD: + case STEM_PRECISION_CURRENCY_CASH: + CHECK_NULL(seen, precision, status); + macros.precision = stem_to_object::precision(stem); + switch (stem) { + case STEM_PRECISION_INTEGER: + return STATE_FRACTION_PRECISION; // allows for "precision-integer/@##" + default: + return STATE_NULL; + } + + case STEM_ROUNDING_MODE_CEILING: + case STEM_ROUNDING_MODE_FLOOR: + case STEM_ROUNDING_MODE_DOWN: + case STEM_ROUNDING_MODE_UP: + case STEM_ROUNDING_MODE_HALF_EVEN: + case STEM_ROUNDING_MODE_HALF_DOWN: + case STEM_ROUNDING_MODE_HALF_UP: + case STEM_ROUNDING_MODE_UNNECESSARY: + CHECK_NULL(seen, roundingMode, status); + macros.roundingMode = stem_to_object::roundingMode(stem); + return STATE_NULL; + + case STEM_GROUP_OFF: + case STEM_GROUP_MIN2: + case STEM_GROUP_AUTO: + case STEM_GROUP_ON_ALIGNED: + case STEM_GROUP_THOUSANDS: + CHECK_NULL(seen, grouper, status); + macros.grouper = Grouper::forStrategy(stem_to_object::groupingStrategy(stem)); + return STATE_NULL; + + case STEM_LATIN: + CHECK_NULL(seen, symbols, status); + macros.symbols.setTo(NumberingSystem::createInstanceByName("latn", status)); + return STATE_NULL; + + case STEM_UNIT_WIDTH_NARROW: + case STEM_UNIT_WIDTH_SHORT: + case STEM_UNIT_WIDTH_FULL_NAME: + case STEM_UNIT_WIDTH_ISO_CODE: + case STEM_UNIT_WIDTH_HIDDEN: + CHECK_NULL(seen, unitWidth, status); + macros.unitWidth = stem_to_object::unitWidth(stem); + return STATE_NULL; + + case STEM_SIGN_AUTO: + case STEM_SIGN_ALWAYS: + case STEM_SIGN_NEVER: + case STEM_SIGN_ACCOUNTING: + case STEM_SIGN_ACCOUNTING_ALWAYS: + case STEM_SIGN_EXCEPT_ZERO: + case STEM_SIGN_ACCOUNTING_EXCEPT_ZERO: + CHECK_NULL(seen, sign, status); + macros.sign = stem_to_object::signDisplay(stem); + return STATE_NULL; + + case STEM_DECIMAL_AUTO: + case STEM_DECIMAL_ALWAYS: + CHECK_NULL(seen, decimal, status); + macros.decimal = stem_to_object::decimalSeparatorDisplay(stem); + return STATE_NULL; + + // Stems requiring an option: + + case STEM_PRECISION_INCREMENT: + CHECK_NULL(seen, precision, status); + return STATE_INCREMENT_PRECISION; + + case STEM_MEASURE_UNIT: + CHECK_NULL(seen, unit, status); + return STATE_MEASURE_UNIT; + + case STEM_PER_MEASURE_UNIT: + CHECK_NULL(seen, perUnit, status); + return STATE_PER_MEASURE_UNIT; + + case STEM_CURRENCY: + CHECK_NULL(seen, unit, status); + return STATE_CURRENCY_UNIT; + + case STEM_INTEGER_WIDTH: + CHECK_NULL(seen, integerWidth, status); + return STATE_INTEGER_WIDTH; + + case STEM_NUMBERING_SYSTEM: + CHECK_NULL(seen, symbols, status); + return STATE_NUMBERING_SYSTEM; + + case STEM_SCALE: + CHECK_NULL(seen, scale, status); + return STATE_SCALE; + + default: + U_ASSERT(false); + return STATE_NULL; // return a value: silence compiler warning + } +} + +ParseState skeleton::parseOption(ParseState stem, const StringSegment& segment, MacroProps& macros, + UErrorCode& status) { + + ///// Required options: ///// + + switch (stem) { + case STATE_CURRENCY_UNIT: + blueprint_helpers::parseCurrencyOption(segment, macros, status); + return STATE_NULL; + case STATE_MEASURE_UNIT: + blueprint_helpers::parseMeasureUnitOption(segment, macros, status); + return STATE_NULL; + case STATE_PER_MEASURE_UNIT: + blueprint_helpers::parseMeasurePerUnitOption(segment, macros, status); + return STATE_NULL; + case STATE_INCREMENT_PRECISION: + blueprint_helpers::parseIncrementOption(segment, macros, status); + return STATE_NULL; + case STATE_INTEGER_WIDTH: + blueprint_helpers::parseIntegerWidthOption(segment, macros, status); + return STATE_NULL; + case STATE_NUMBERING_SYSTEM: + blueprint_helpers::parseNumberingSystemOption(segment, macros, status); + return STATE_NULL; + case STATE_SCALE: + blueprint_helpers::parseScaleOption(segment, macros, status); + return STATE_NULL; + default: + break; + } + + ///// Non-required options: ///// + + // Scientific options + switch (stem) { + case STATE_SCIENTIFIC: + if (blueprint_helpers::parseExponentWidthOption(segment, macros, status)) { + return STATE_SCIENTIFIC; + } + if (U_FAILURE(status)) { + return {}; + } + if (blueprint_helpers::parseExponentSignOption(segment, macros, status)) { + return STATE_SCIENTIFIC; + } + if (U_FAILURE(status)) { + return {}; + } + break; + default: + break; + } + + // Frac-sig option + switch (stem) { + case STATE_FRACTION_PRECISION: + if (blueprint_helpers::parseFracSigOption(segment, macros, status)) { + return STATE_NULL; + } + if (U_FAILURE(status)) { + return {}; + } + break; + default: + break; + } + + // Unknown option + // throw new SkeletonSyntaxException("Invalid option", segment); + status = U_NUMBER_SKELETON_SYNTAX_ERROR; + return STATE_NULL; +} + +void GeneratorHelpers::generateSkeleton(const MacroProps& macros, UnicodeString& sb, UErrorCode& status) { + if (U_FAILURE(status)) { return; } + + // Supported options + if (GeneratorHelpers::notation(macros, sb, status)) { + sb.append(u' '); + } + if (U_FAILURE(status)) { return; } + if (GeneratorHelpers::unit(macros, sb, status)) { + sb.append(u' '); + } + if (U_FAILURE(status)) { return; } + if (GeneratorHelpers::perUnit(macros, sb, status)) { + sb.append(u' '); + } + if (U_FAILURE(status)) { return; } + if (GeneratorHelpers::precision(macros, sb, status)) { + sb.append(u' '); + } + if (U_FAILURE(status)) { return; } + if (GeneratorHelpers::roundingMode(macros, sb, status)) { + sb.append(u' '); + } + if (U_FAILURE(status)) { return; } + if (GeneratorHelpers::grouping(macros, sb, status)) { + sb.append(u' '); + } + if (U_FAILURE(status)) { return; } + if (GeneratorHelpers::integerWidth(macros, sb, status)) { + sb.append(u' '); + } + if (U_FAILURE(status)) { return; } + if (GeneratorHelpers::symbols(macros, sb, status)) { + sb.append(u' '); + } + if (U_FAILURE(status)) { return; } + if (GeneratorHelpers::unitWidth(macros, sb, status)) { + sb.append(u' '); + } + if (U_FAILURE(status)) { return; } + if (GeneratorHelpers::sign(macros, sb, status)) { + sb.append(u' '); + } + if (U_FAILURE(status)) { return; } + if (GeneratorHelpers::decimal(macros, sb, status)) { + sb.append(u' '); + } + if (U_FAILURE(status)) { return; } + if (GeneratorHelpers::scale(macros, sb, status)) { + sb.append(u' '); + } + if (U_FAILURE(status)) { return; } + + // Unsupported options + if (!macros.padder.isBogus()) { + status = U_UNSUPPORTED_ERROR; + return; + } + if (macros.affixProvider != nullptr) { + status = U_UNSUPPORTED_ERROR; + return; + } + if (macros.rules != nullptr) { + status = U_UNSUPPORTED_ERROR; + return; + } + if (macros.currencySymbols != nullptr) { + status = U_UNSUPPORTED_ERROR; + return; + } + + // Remove the trailing space + if (sb.length() > 0) { + sb.truncate(sb.length() - 1); + } +} + + +bool blueprint_helpers::parseExponentWidthOption(const StringSegment& segment, MacroProps& macros, + UErrorCode&) { + if (segment.charAt(0) != u'+') { + return false; + } + int32_t offset = 1; + int32_t minExp = 0; + for (; offset < segment.length(); offset++) { + if (segment.charAt(offset) == u'e') { + minExp++; + } else { + break; + } + } + if (offset < segment.length()) { + return false; + } + // Use the public APIs to enforce bounds checking + macros.notation = static_cast(macros.notation).withMinExponentDigits(minExp); + return true; +} + +void +blueprint_helpers::generateExponentWidthOption(int32_t minExponentDigits, UnicodeString& sb, UErrorCode&) { + sb.append(u'+'); + appendMultiple(sb, u'e', minExponentDigits); +} + +bool +blueprint_helpers::parseExponentSignOption(const StringSegment& segment, MacroProps& macros, UErrorCode&) { + // Get the sign display type out of the CharsTrie data structure. + UCharsTrie tempStemTrie(kSerializedStemTrie); + UStringTrieResult result = tempStemTrie.next( + segment.toTempUnicodeString().getBuffer(), + segment.length()); + if (result != USTRINGTRIE_INTERMEDIATE_VALUE && result != USTRINGTRIE_FINAL_VALUE) { + return false; + } + auto sign = stem_to_object::signDisplay(static_cast(tempStemTrie.getValue())); + if (sign == UNUM_SIGN_COUNT) { + return false; + } + macros.notation = static_cast(macros.notation).withExponentSignDisplay(sign); + return true; +} + +void blueprint_helpers::parseCurrencyOption(const StringSegment& segment, MacroProps& macros, + UErrorCode& status) { + // Unlike ICU4J, have to check length manually because ICU4C CurrencyUnit does not check it for us + if (segment.length() != 3) { + status = U_NUMBER_SKELETON_SYNTAX_ERROR; + return; + } + const UChar* currencyCode = segment.toTempUnicodeString().getBuffer(); + UErrorCode localStatus = U_ZERO_ERROR; + CurrencyUnit currency(currencyCode, localStatus); + if (U_FAILURE(localStatus)) { + // Not 3 ascii chars + // throw new SkeletonSyntaxException("Invalid currency", segment); + status = U_NUMBER_SKELETON_SYNTAX_ERROR; + return; + } + // Slicing is OK + macros.unit = currency; // NOLINT +} + +void +blueprint_helpers::generateCurrencyOption(const CurrencyUnit& currency, UnicodeString& sb, UErrorCode&) { + sb.append(currency.getISOCurrency(), -1); +} + +void blueprint_helpers::parseMeasureUnitOption(const StringSegment& segment, MacroProps& macros, + UErrorCode& status) { + const UnicodeString stemString = segment.toTempUnicodeString(); + + // NOTE: The category (type) of the unit is guaranteed to be a valid subtag (alphanumeric) + // http://unicode.org/reports/tr35/#Validity_Data + int firstHyphen = 0; + while (firstHyphen < stemString.length() && stemString.charAt(firstHyphen) != '-') { + firstHyphen++; + } + if (firstHyphen == stemString.length()) { + // throw new SkeletonSyntaxException("Invalid measure unit option", segment); + status = U_NUMBER_SKELETON_SYNTAX_ERROR; + return; + } + + // Need to do char <-> UChar conversion... + U_ASSERT(U_SUCCESS(status)); + CharString type; + SKELETON_UCHAR_TO_CHAR(type, stemString, 0, firstHyphen, status); + CharString subType; + SKELETON_UCHAR_TO_CHAR(subType, stemString, firstHyphen + 1, stemString.length(), status); + + // Note: the largest type as of this writing (March 2018) is "volume", which has 24 units. + static constexpr int32_t CAPACITY = 30; + MeasureUnit units[CAPACITY]; + UErrorCode localStatus = U_ZERO_ERROR; + int32_t numUnits = MeasureUnit::getAvailable(type.data(), units, CAPACITY, localStatus); + if (U_FAILURE(localStatus)) { + // More than 30 units in this type? + status = U_INTERNAL_PROGRAM_ERROR; + return; + } + for (int32_t i = 0; i < numUnits; i++) { + auto& unit = units[i]; + if (uprv_strcmp(subType.data(), unit.getSubtype()) == 0) { + macros.unit = unit; + return; + } + } + + // throw new SkeletonSyntaxException("Unknown measure unit", segment); + status = U_NUMBER_SKELETON_SYNTAX_ERROR; +} + +void blueprint_helpers::generateMeasureUnitOption(const MeasureUnit& measureUnit, UnicodeString& sb, + UErrorCode&) { + // Need to do char <-> UChar conversion... + sb.append(UnicodeString(measureUnit.getType(), -1, US_INV)); + sb.append(u'-'); + sb.append(UnicodeString(measureUnit.getSubtype(), -1, US_INV)); +} + +void blueprint_helpers::parseMeasurePerUnitOption(const StringSegment& segment, MacroProps& macros, + UErrorCode& status) { + // A little bit of a hack: safe the current unit (numerator), call the main measure unit + // parsing code, put back the numerator unit, and put the new unit into per-unit. + MeasureUnit numerator = macros.unit; + parseMeasureUnitOption(segment, macros, status); + if (U_FAILURE(status)) { return; } + macros.perUnit = macros.unit; + macros.unit = numerator; +} + +void blueprint_helpers::parseFractionStem(const StringSegment& segment, MacroProps& macros, + UErrorCode& status) { + U_ASSERT(segment.charAt(0) == u'.'); + int32_t offset = 1; + int32_t minFrac = 0; + int32_t maxFrac; + for (; offset < segment.length(); offset++) { + if (segment.charAt(offset) == u'0') { + minFrac++; + } else { + break; + } + } + if (offset < segment.length()) { + if (segment.charAt(offset) == u'+') { + maxFrac = -1; + offset++; + } else { + maxFrac = minFrac; + for (; offset < segment.length(); offset++) { + if (segment.charAt(offset) == u'#') { + maxFrac++; + } else { + break; + } + } + } + } else { + maxFrac = minFrac; + } + if (offset < segment.length()) { + // throw new SkeletonSyntaxException("Invalid fraction stem", segment); + status = U_NUMBER_SKELETON_SYNTAX_ERROR; + return; + } + // Use the public APIs to enforce bounds checking + if (maxFrac == -1) { + macros.precision = Precision::minFraction(minFrac); + } else { + macros.precision = Precision::minMaxFraction(minFrac, maxFrac); + } +} + +void +blueprint_helpers::generateFractionStem(int32_t minFrac, int32_t maxFrac, UnicodeString& sb, UErrorCode&) { + if (minFrac == 0 && maxFrac == 0) { + sb.append(u"precision-integer", -1); + return; + } + sb.append(u'.'); + appendMultiple(sb, u'0', minFrac); + if (maxFrac == -1) { + sb.append(u'+'); + } else { + appendMultiple(sb, u'#', maxFrac - minFrac); + } +} + +void +blueprint_helpers::parseDigitsStem(const StringSegment& segment, MacroProps& macros, UErrorCode& status) { + U_ASSERT(segment.charAt(0) == u'@'); + int offset = 0; + int minSig = 0; + int maxSig; + for (; offset < segment.length(); offset++) { + if (segment.charAt(offset) == u'@') { + minSig++; + } else { + break; + } + } + if (offset < segment.length()) { + if (segment.charAt(offset) == u'+') { + maxSig = -1; + offset++; + } else { + maxSig = minSig; + for (; offset < segment.length(); offset++) { + if (segment.charAt(offset) == u'#') { + maxSig++; + } else { + break; + } + } + } + } else { + maxSig = minSig; + } + if (offset < segment.length()) { + // throw new SkeletonSyntaxException("Invalid significant digits stem", segment); + status = U_NUMBER_SKELETON_SYNTAX_ERROR; + return; + } + // Use the public APIs to enforce bounds checking + if (maxSig == -1) { + macros.precision = Precision::minSignificantDigits(minSig); + } else { + macros.precision = Precision::minMaxSignificantDigits(minSig, maxSig); + } +} + +void +blueprint_helpers::generateDigitsStem(int32_t minSig, int32_t maxSig, UnicodeString& sb, UErrorCode&) { + appendMultiple(sb, u'@', minSig); + if (maxSig == -1) { + sb.append(u'+'); + } else { + appendMultiple(sb, u'#', maxSig - minSig); + } +} + +bool blueprint_helpers::parseFracSigOption(const StringSegment& segment, MacroProps& macros, + UErrorCode& status) { + if (segment.charAt(0) != u'@') { + return false; + } + int offset = 0; + int minSig = 0; + int maxSig; + for (; offset < segment.length(); offset++) { + if (segment.charAt(offset) == u'@') { + minSig++; + } else { + break; + } + } + // For the frac-sig option, there must be minSig or maxSig but not both. + // Valid: @+, @@+, @@@+ + // Valid: @#, @##, @### + // Invalid: @, @@, @@@ + // Invalid: @@#, @@##, @@@# + if (offset < segment.length()) { + if (segment.charAt(offset) == u'+') { + maxSig = -1; + offset++; + } else if (minSig > 1) { + // @@#, @@##, @@@# + // throw new SkeletonSyntaxException("Invalid digits option for fraction rounder", segment); + status = U_NUMBER_SKELETON_SYNTAX_ERROR; + return false; + } else { + maxSig = minSig; + for (; offset < segment.length(); offset++) { + if (segment.charAt(offset) == u'#') { + maxSig++; + } else { + break; + } + } + } + } else { + // @, @@, @@@ + // throw new SkeletonSyntaxException("Invalid digits option for fraction rounder", segment); + status = U_NUMBER_SKELETON_SYNTAX_ERROR; + return false; + } + if (offset < segment.length()) { + // throw new SkeletonSyntaxException("Invalid digits option for fraction rounder", segment); + status = U_NUMBER_SKELETON_SYNTAX_ERROR; + return false; + } + + auto& oldPrecision = static_cast(macros.precision); + if (maxSig == -1) { + macros.precision = oldPrecision.withMinDigits(minSig); + } else { + macros.precision = oldPrecision.withMaxDigits(maxSig); + } + return true; +} + +void blueprint_helpers::parseIncrementOption(const StringSegment& segment, MacroProps& macros, + UErrorCode& status) { + // Need to do char <-> UChar conversion... + U_ASSERT(U_SUCCESS(status)); + CharString buffer; + SKELETON_UCHAR_TO_CHAR(buffer, segment.toTempUnicodeString(), 0, segment.length(), status); + + // Utilize DecimalQuantity/decNumber to parse this for us. + DecimalQuantity dq; + UErrorCode localStatus = U_ZERO_ERROR; + dq.setToDecNumber({buffer.data(), buffer.length()}, localStatus); + if (U_FAILURE(localStatus)) { + // throw new SkeletonSyntaxException("Invalid rounding increment", segment, e); + status = U_NUMBER_SKELETON_SYNTAX_ERROR; + return; + } + double increment = dq.toDouble(); + + // We also need to figure out how many digits. Do a brute force string operation. + int decimalOffset = 0; + while (decimalOffset < segment.length() && segment.charAt(decimalOffset) != '.') { + decimalOffset++; + } + if (decimalOffset == segment.length()) { + macros.precision = Precision::increment(increment); + } else { + int32_t fractionLength = segment.length() - decimalOffset - 1; + macros.precision = Precision::increment(increment).withMinFraction(fractionLength); + } +} + +void blueprint_helpers::generateIncrementOption(double increment, int32_t trailingZeros, UnicodeString& sb, + UErrorCode&) { + // Utilize DecimalQuantity/double_conversion to format this for us. + DecimalQuantity dq; + dq.setToDouble(increment); + dq.roundToInfinity(); + sb.append(dq.toPlainString()); + + // We might need to append extra trailing zeros for min fraction... + if (trailingZeros > 0) { + appendMultiple(sb, u'0', trailingZeros); + } +} + +void blueprint_helpers::parseIntegerWidthOption(const StringSegment& segment, MacroProps& macros, + UErrorCode& status) { + int32_t offset = 0; + int32_t minInt = 0; + int32_t maxInt; + if (segment.charAt(0) == u'+') { + maxInt = -1; + offset++; + } else { + maxInt = 0; + } + for (; offset < segment.length(); offset++) { + if (segment.charAt(offset) == u'#') { + maxInt++; + } else { + break; + } + } + if (offset < segment.length()) { + for (; offset < segment.length(); offset++) { + if (segment.charAt(offset) == u'0') { + minInt++; + } else { + break; + } + } + } + if (maxInt != -1) { + maxInt += minInt; + } + if (offset < segment.length()) { + // throw new SkeletonSyntaxException("Invalid integer width stem", segment); + status = U_NUMBER_SKELETON_SYNTAX_ERROR; + return; + } + // Use the public APIs to enforce bounds checking + if (maxInt == -1) { + macros.integerWidth = IntegerWidth::zeroFillTo(minInt); + } else { + macros.integerWidth = IntegerWidth::zeroFillTo(minInt).truncateAt(maxInt); + } +} + +void blueprint_helpers::generateIntegerWidthOption(int32_t minInt, int32_t maxInt, UnicodeString& sb, + UErrorCode&) { + if (maxInt == -1) { + sb.append(u'+'); + } else { + appendMultiple(sb, u'#', maxInt - minInt); + } + appendMultiple(sb, u'0', minInt); +} + +void blueprint_helpers::parseNumberingSystemOption(const StringSegment& segment, MacroProps& macros, + UErrorCode& status) { + // Need to do char <-> UChar conversion... + U_ASSERT(U_SUCCESS(status)); + CharString buffer; + SKELETON_UCHAR_TO_CHAR(buffer, segment.toTempUnicodeString(), 0, segment.length(), status); + + NumberingSystem* ns = NumberingSystem::createInstanceByName(buffer.data(), status); + if (ns == nullptr || U_FAILURE(status)) { + // This is a skeleton syntax error; don't bubble up the low-level NumberingSystem error + // throw new SkeletonSyntaxException("Unknown numbering system", segment); + status = U_NUMBER_SKELETON_SYNTAX_ERROR; + return; + } + macros.symbols.setTo(ns); +} + +void blueprint_helpers::generateNumberingSystemOption(const NumberingSystem& ns, UnicodeString& sb, + UErrorCode&) { + // Need to do char <-> UChar conversion... + sb.append(UnicodeString(ns.getName(), -1, US_INV)); +} + +void blueprint_helpers::parseScaleOption(const StringSegment& segment, MacroProps& macros, + UErrorCode& status) { + // Need to do char <-> UChar conversion... + U_ASSERT(U_SUCCESS(status)); + CharString buffer; + SKELETON_UCHAR_TO_CHAR(buffer, segment.toTempUnicodeString(), 0, segment.length(), status); + + LocalPointer decnum(new DecNum(), status); + if (U_FAILURE(status)) { return; } + decnum->setTo({buffer.data(), buffer.length()}, status); + if (U_FAILURE(status)) { + // This is a skeleton syntax error; don't let the low-level decnum error bubble up + status = U_NUMBER_SKELETON_SYNTAX_ERROR; + return; + } + + // NOTE: The constructor will optimize the decnum for us if possible. + macros.scale = {0, decnum.orphan()}; +} + +void blueprint_helpers::generateScaleOption(int32_t magnitude, const DecNum* arbitrary, UnicodeString& sb, + UErrorCode& status) { + // Utilize DecimalQuantity/double_conversion to format this for us. + DecimalQuantity dq; + if (arbitrary != nullptr) { + dq.setToDecNum(*arbitrary, status); + if (U_FAILURE(status)) { return; } + } else { + dq.setToInt(1); + } + dq.adjustMagnitude(magnitude); + dq.roundToInfinity(); + sb.append(dq.toPlainString()); +} + + +bool GeneratorHelpers::notation(const MacroProps& macros, UnicodeString& sb, UErrorCode& status) { + if (macros.notation.fType == Notation::NTN_COMPACT) { + UNumberCompactStyle style = macros.notation.fUnion.compactStyle; + if (style == UNumberCompactStyle::UNUM_LONG) { + sb.append(u"compact-long", -1); + return true; + } else if (style == UNumberCompactStyle::UNUM_SHORT) { + sb.append(u"compact-short", -1); + return true; + } else { + // Compact notation generated from custom data (not supported in skeleton) + // The other compact notations are literals + status = U_UNSUPPORTED_ERROR; + return false; + } + } else if (macros.notation.fType == Notation::NTN_SCIENTIFIC) { + const Notation::ScientificSettings& impl = macros.notation.fUnion.scientific; + if (impl.fEngineeringInterval == 3) { + sb.append(u"engineering", -1); + } else { + sb.append(u"scientific", -1); + } + if (impl.fMinExponentDigits > 1) { + sb.append(u'/'); + blueprint_helpers::generateExponentWidthOption(impl.fMinExponentDigits, sb, status); + if (U_FAILURE(status)) { + return false; + } + } + if (impl.fExponentSignDisplay != UNUM_SIGN_AUTO) { + sb.append(u'/'); + enum_to_stem_string::signDisplay(impl.fExponentSignDisplay, sb); + } + return true; + } else { + // Default value is not shown in normalized form + return false; + } +} + +bool GeneratorHelpers::unit(const MacroProps& macros, UnicodeString& sb, UErrorCode& status) { + if (utils::unitIsCurrency(macros.unit)) { + sb.append(u"currency/", -1); + CurrencyUnit currency(macros.unit, status); + if (U_FAILURE(status)) { + return false; + } + blueprint_helpers::generateCurrencyOption(currency, sb, status); + return true; + } else if (utils::unitIsNoUnit(macros.unit)) { + if (utils::unitIsPercent(macros.unit)) { + sb.append(u"percent", -1); + return true; + } else if (utils::unitIsPermille(macros.unit)) { + sb.append(u"permille", -1); + return true; + } else { + // Default value is not shown in normalized form + return false; + } + } else { + sb.append(u"measure-unit/", -1); + blueprint_helpers::generateMeasureUnitOption(macros.unit, sb, status); + return true; + } +} + +bool GeneratorHelpers::perUnit(const MacroProps& macros, UnicodeString& sb, UErrorCode& status) { + // Per-units are currently expected to be only MeasureUnits. + if (utils::unitIsNoUnit(macros.perUnit)) { + if (utils::unitIsPercent(macros.perUnit) || utils::unitIsPermille(macros.perUnit)) { + status = U_UNSUPPORTED_ERROR; + return false; + } else { + // Default value: ok to ignore + return false; + } + } else if (utils::unitIsCurrency(macros.perUnit)) { + status = U_UNSUPPORTED_ERROR; + return false; + } else { + sb.append(u"per-measure-unit/", -1); + blueprint_helpers::generateMeasureUnitOption(macros.perUnit, sb, status); + return true; + } +} + +bool GeneratorHelpers::precision(const MacroProps& macros, UnicodeString& sb, UErrorCode& status) { + if (macros.precision.fType == Precision::RND_NONE) { + sb.append(u"precision-unlimited", -1); + } else if (macros.precision.fType == Precision::RND_FRACTION) { + const Precision::FractionSignificantSettings& impl = macros.precision.fUnion.fracSig; + blueprint_helpers::generateFractionStem(impl.fMinFrac, impl.fMaxFrac, sb, status); + } else if (macros.precision.fType == Precision::RND_SIGNIFICANT) { + const Precision::FractionSignificantSettings& impl = macros.precision.fUnion.fracSig; + blueprint_helpers::generateDigitsStem(impl.fMinSig, impl.fMaxSig, sb, status); + } else if (macros.precision.fType == Precision::RND_FRACTION_SIGNIFICANT) { + const Precision::FractionSignificantSettings& impl = macros.precision.fUnion.fracSig; + blueprint_helpers::generateFractionStem(impl.fMinFrac, impl.fMaxFrac, sb, status); + sb.append(u'/'); + if (impl.fMinSig == -1) { + blueprint_helpers::generateDigitsStem(1, impl.fMaxSig, sb, status); + } else { + blueprint_helpers::generateDigitsStem(impl.fMinSig, -1, sb, status); + } + } else if (macros.precision.fType == Precision::RND_INCREMENT) { + const Precision::IncrementSettings& impl = macros.precision.fUnion.increment; + sb.append(u"precision-increment/", -1); + blueprint_helpers::generateIncrementOption( + impl.fIncrement, + impl.fMinFrac - impl.fMaxFrac, + sb, + status); + } else if (macros.precision.fType == Precision::RND_CURRENCY) { + UCurrencyUsage usage = macros.precision.fUnion.currencyUsage; + if (usage == UCURR_USAGE_STANDARD) { + sb.append(u"precision-currency-standard", -1); + } else { + sb.append(u"precision-currency-cash", -1); + } + } else { + // Bogus or Error + return false; + } + + // NOTE: Always return true for rounding because the default value depends on other options. + return true; +} + +bool GeneratorHelpers::roundingMode(const MacroProps& macros, UnicodeString& sb, UErrorCode&) { + if (macros.roundingMode == kDefaultMode) { + return false; // Default + } + enum_to_stem_string::roundingMode(macros.roundingMode, sb); + return true; +} + +bool GeneratorHelpers::grouping(const MacroProps& macros, UnicodeString& sb, UErrorCode& status) { + if (macros.grouper.isBogus()) { + return false; // No value + } else if (macros.grouper.fStrategy == UNUM_GROUPING_COUNT) { + status = U_UNSUPPORTED_ERROR; + return false; + } else if (macros.grouper.fStrategy == UNUM_GROUPING_AUTO) { + return false; // Default value + } else { + enum_to_stem_string::groupingStrategy(macros.grouper.fStrategy, sb); + return true; + } +} + +bool GeneratorHelpers::integerWidth(const MacroProps& macros, UnicodeString& sb, UErrorCode& status) { + if (macros.integerWidth.fHasError || macros.integerWidth.isBogus() || + macros.integerWidth == IntegerWidth::standard()) { + // Error or Default + return false; + } + sb.append(u"integer-width/", -1); + blueprint_helpers::generateIntegerWidthOption( + macros.integerWidth.fUnion.minMaxInt.fMinInt, + macros.integerWidth.fUnion.minMaxInt.fMaxInt, + sb, + status); + return true; +} + +bool GeneratorHelpers::symbols(const MacroProps& macros, UnicodeString& sb, UErrorCode& status) { + if (macros.symbols.isNumberingSystem()) { + const NumberingSystem& ns = *macros.symbols.getNumberingSystem(); + if (uprv_strcmp(ns.getName(), "latn") == 0) { + sb.append(u"latin", -1); + } else { + sb.append(u"numbering-system/", -1); + blueprint_helpers::generateNumberingSystemOption(ns, sb, status); + } + return true; + } else if (macros.symbols.isDecimalFormatSymbols()) { + status = U_UNSUPPORTED_ERROR; + return false; + } else { + // No custom symbols + return false; + } +} + +bool GeneratorHelpers::unitWidth(const MacroProps& macros, UnicodeString& sb, UErrorCode&) { + if (macros.unitWidth == UNUM_UNIT_WIDTH_SHORT || macros.unitWidth == UNUM_UNIT_WIDTH_COUNT) { + return false; // Default or Bogus + } + enum_to_stem_string::unitWidth(macros.unitWidth, sb); + return true; +} + +bool GeneratorHelpers::sign(const MacroProps& macros, UnicodeString& sb, UErrorCode&) { + if (macros.sign == UNUM_SIGN_AUTO || macros.sign == UNUM_SIGN_COUNT) { + return false; // Default or Bogus + } + enum_to_stem_string::signDisplay(macros.sign, sb); + return true; +} + +bool GeneratorHelpers::decimal(const MacroProps& macros, UnicodeString& sb, UErrorCode&) { + if (macros.decimal == UNUM_DECIMAL_SEPARATOR_AUTO || macros.decimal == UNUM_DECIMAL_SEPARATOR_COUNT) { + return false; // Default or Bogus + } + enum_to_stem_string::decimalSeparatorDisplay(macros.decimal, sb); + return true; +} + +bool GeneratorHelpers::scale(const MacroProps& macros, UnicodeString& sb, UErrorCode& status) { + if (!macros.scale.isValid()) { + return false; // Default or Bogus + } + sb.append(u"scale/", -1); + blueprint_helpers::generateScaleOption( + macros.scale.fMagnitude, + macros.scale.fArbitrary, + sb, + status); + return true; +} + + +#endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/deps/icu-small/source/i18n/number_skeletons.h b/deps/icu-small/source/i18n/number_skeletons.h new file mode 100644 index 00000000000..0161f5f0ba8 --- /dev/null +++ b/deps/icu-small/source/i18n/number_skeletons.h @@ -0,0 +1,327 @@ +// © 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_NUMBER_SKELETONS_H__ +#define __SOURCE_NUMBER_SKELETONS_H__ + +#include "number_types.h" +#include "numparse_types.h" +#include "unicode/ucharstrie.h" + +using icu::numparse::impl::StringSegment; + +U_NAMESPACE_BEGIN namespace number { +namespace impl { + +// Forward-declaration +struct SeenMacroProps; + +// namespace for enums and entrypoint functions +namespace skeleton { + +/////////////////////////////////////////////////////////////////////////////////////// +// NOTE: For an example of how to add a new stem to the number skeleton parser, see: // +// http://bugs.icu-project.org/trac/changeset/41193 // +/////////////////////////////////////////////////////////////////////////////////////// + +/** + * While parsing a skeleton, this enum records what type of option we expect to find next. + */ +enum ParseState { + + // Section 0: We expect whitespace or a stem, but not an option: + + STATE_NULL, + + // Section 1: We might accept an option, but it is not required: + + STATE_SCIENTIFIC, + STATE_FRACTION_PRECISION, + + // Section 2: An option is required: + + STATE_INCREMENT_PRECISION, + STATE_MEASURE_UNIT, + STATE_PER_MEASURE_UNIT, + STATE_CURRENCY_UNIT, + STATE_INTEGER_WIDTH, + STATE_NUMBERING_SYSTEM, + STATE_SCALE, +}; + +/** + * All possible stem literals have an entry in the StemEnum. The enum name is the kebab case stem + * string literal written in upper snake case. + * + * @see StemToObject + * @see #SERIALIZED_STEM_TRIE + */ +enum StemEnum { + + // Section 1: Stems that do not require an option: + + STEM_COMPACT_SHORT, + STEM_COMPACT_LONG, + STEM_SCIENTIFIC, + STEM_ENGINEERING, + STEM_NOTATION_SIMPLE, + STEM_BASE_UNIT, + STEM_PERCENT, + STEM_PERMILLE, + STEM_PRECISION_INTEGER, + STEM_PRECISION_UNLIMITED, + STEM_PRECISION_CURRENCY_STANDARD, + STEM_PRECISION_CURRENCY_CASH, + STEM_ROUNDING_MODE_CEILING, + STEM_ROUNDING_MODE_FLOOR, + STEM_ROUNDING_MODE_DOWN, + STEM_ROUNDING_MODE_UP, + STEM_ROUNDING_MODE_HALF_EVEN, + STEM_ROUNDING_MODE_HALF_DOWN, + STEM_ROUNDING_MODE_HALF_UP, + STEM_ROUNDING_MODE_UNNECESSARY, + STEM_GROUP_OFF, + STEM_GROUP_MIN2, + STEM_GROUP_AUTO, + STEM_GROUP_ON_ALIGNED, + STEM_GROUP_THOUSANDS, + STEM_LATIN, + STEM_UNIT_WIDTH_NARROW, + STEM_UNIT_WIDTH_SHORT, + STEM_UNIT_WIDTH_FULL_NAME, + STEM_UNIT_WIDTH_ISO_CODE, + STEM_UNIT_WIDTH_HIDDEN, + STEM_SIGN_AUTO, + STEM_SIGN_ALWAYS, + STEM_SIGN_NEVER, + STEM_SIGN_ACCOUNTING, + STEM_SIGN_ACCOUNTING_ALWAYS, + STEM_SIGN_EXCEPT_ZERO, + STEM_SIGN_ACCOUNTING_EXCEPT_ZERO, + STEM_DECIMAL_AUTO, + STEM_DECIMAL_ALWAYS, + + // Section 2: Stems that DO require an option: + + STEM_PRECISION_INCREMENT, + STEM_MEASURE_UNIT, + STEM_PER_MEASURE_UNIT, + STEM_CURRENCY, + STEM_INTEGER_WIDTH, + STEM_NUMBERING_SYSTEM, + STEM_SCALE, +}; + +/** + * Creates a NumberFormatter corresponding to the given skeleton string. + * + * @param skeletonString + * A number skeleton string, possibly not in its shortest form. + * @return An UnlocalizedNumberFormatter with behavior defined by the given skeleton string. + */ +UnlocalizedNumberFormatter create(const UnicodeString& skeletonString, UErrorCode& status); + +/** + * Create a skeleton string corresponding to the given NumberFormatter. + * + * @param macros + * The NumberFormatter options object. + * @return A skeleton string in normalized form. + */ +UnicodeString generate(const MacroProps& macros, UErrorCode& status); + +/** + * Converts from a skeleton string to a MacroProps. This method contains the primary parse loop. + * + * Internal: use the create() endpoint instead of this function. + */ +MacroProps parseSkeleton(const UnicodeString& skeletonString, UErrorCode& status); + +/** + * Given that the current segment represents a stem, parse it and save the result. + * + * @return The next state after parsing this stem, corresponding to what subset of options to expect. + */ +ParseState parseStem(const StringSegment& segment, const UCharsTrie& stemTrie, SeenMacroProps& seen, + MacroProps& macros, UErrorCode& status); + +/** + * Given that the current segment represents an option, parse it and save the result. + * + * @return The next state after parsing this option, corresponding to what subset of options to + * expect next. + */ +ParseState +parseOption(ParseState stem, const StringSegment& segment, MacroProps& macros, UErrorCode& status); + +} // namespace skeleton + + +/** + * Namespace for utility methods that convert from StemEnum to corresponding objects or enums. This + * applies to only the "Section 1" stems, those that are well-defined without an option. + */ +namespace stem_to_object { + +Notation notation(skeleton::StemEnum stem); + +MeasureUnit unit(skeleton::StemEnum stem); + +Precision precision(skeleton::StemEnum stem); + +UNumberFormatRoundingMode roundingMode(skeleton::StemEnum stem); + +UGroupingStrategy groupingStrategy(skeleton::StemEnum stem); + +UNumberUnitWidth unitWidth(skeleton::StemEnum stem); + +UNumberSignDisplay signDisplay(skeleton::StemEnum stem); + +UNumberDecimalSeparatorDisplay decimalSeparatorDisplay(skeleton::StemEnum stem); + +} // namespace stem_to_object + +/** + * Namespace for utility methods that convert from enums to stem strings. More complex object conversions + * take place in the object_to_stem_string namespace. + */ +namespace enum_to_stem_string { + +void roundingMode(UNumberFormatRoundingMode value, UnicodeString& sb); + +void groupingStrategy(UGroupingStrategy value, UnicodeString& sb); + +void unitWidth(UNumberUnitWidth value, UnicodeString& sb); + +void signDisplay(UNumberSignDisplay value, UnicodeString& sb); + +void decimalSeparatorDisplay(UNumberDecimalSeparatorDisplay value, UnicodeString& sb); + +} // namespace enum_to_stem_string + +/** + * Namespace for utility methods for processing stems and options that cannot be interpreted literally. + */ +namespace blueprint_helpers { + +/** @return Whether we successfully found and parsed an exponent width option. */ +bool parseExponentWidthOption(const StringSegment& segment, MacroProps& macros, UErrorCode& status); + +void generateExponentWidthOption(int32_t minExponentDigits, UnicodeString& sb, UErrorCode& status); + +/** @return Whether we successfully found and parsed an exponent sign option. */ +bool parseExponentSignOption(const StringSegment& segment, MacroProps& macros, UErrorCode& status); + +void parseCurrencyOption(const StringSegment& segment, MacroProps& macros, UErrorCode& status); + +void generateCurrencyOption(const CurrencyUnit& currency, UnicodeString& sb, UErrorCode& status); + +void parseMeasureUnitOption(const StringSegment& segment, MacroProps& macros, UErrorCode& status); + +void generateMeasureUnitOption(const MeasureUnit& measureUnit, UnicodeString& sb, UErrorCode& status); + +void parseMeasurePerUnitOption(const StringSegment& segment, MacroProps& macros, UErrorCode& status); + +void parseFractionStem(const StringSegment& segment, MacroProps& macros, UErrorCode& status); + +void generateFractionStem(int32_t minFrac, int32_t maxFrac, UnicodeString& sb, UErrorCode& status); + +void parseDigitsStem(const StringSegment& segment, MacroProps& macros, UErrorCode& status); + +void generateDigitsStem(int32_t minSig, int32_t maxSig, UnicodeString& sb, UErrorCode& status); + +/** @return Whether we successfully found and parsed a frac-sig option. */ +bool parseFracSigOption(const StringSegment& segment, MacroProps& macros, UErrorCode& status); + +void parseIncrementOption(const StringSegment& segment, MacroProps& macros, UErrorCode& status); + +void +generateIncrementOption(double increment, int32_t trailingZeros, UnicodeString& sb, UErrorCode& status); + +void parseIntegerWidthOption(const StringSegment& segment, MacroProps& macros, UErrorCode& status); + +void generateIntegerWidthOption(int32_t minInt, int32_t maxInt, UnicodeString& sb, UErrorCode& status); + +void parseNumberingSystemOption(const StringSegment& segment, MacroProps& macros, UErrorCode& status); + +void generateNumberingSystemOption(const NumberingSystem& ns, UnicodeString& sb, UErrorCode& status); + +void parseScaleOption(const StringSegment& segment, MacroProps& macros, UErrorCode& status); + +void generateScaleOption(int32_t magnitude, const DecNum* arbitrary, UnicodeString& sb, + UErrorCode& status); + +} // namespace blueprint_helpers + +/** + * Class for utility methods for generating a token corresponding to each macro-prop. Each method + * returns whether or not a token was written to the string builder. + * + * This needs to be a class, not a namespace, so it can be friended. + */ +class GeneratorHelpers { + public: + /** + * Main skeleton generator function. Appends the normalized skeleton for the MacroProps to the given + * StringBuilder. + * + * Internal: use the create() endpoint instead of this function. + */ + static void generateSkeleton(const MacroProps& macros, UnicodeString& sb, UErrorCode& status); + + private: + static bool notation(const MacroProps& macros, UnicodeString& sb, UErrorCode& status); + + static bool unit(const MacroProps& macros, UnicodeString& sb, UErrorCode& status); + + static bool perUnit(const MacroProps& macros, UnicodeString& sb, UErrorCode& status); + + static bool precision(const MacroProps& macros, UnicodeString& sb, UErrorCode& status); + + static bool roundingMode(const MacroProps& macros, UnicodeString& sb, UErrorCode& status); + + static bool grouping(const MacroProps& macros, UnicodeString& sb, UErrorCode& status); + + static bool integerWidth(const MacroProps& macros, UnicodeString& sb, UErrorCode& status); + + static bool symbols(const MacroProps& macros, UnicodeString& sb, UErrorCode& status); + + static bool unitWidth(const MacroProps& macros, UnicodeString& sb, UErrorCode& status); + + static bool sign(const MacroProps& macros, UnicodeString& sb, UErrorCode& status); + + static bool decimal(const MacroProps& macros, UnicodeString& sb, UErrorCode& status); + + static bool scale(const MacroProps& macros, UnicodeString& sb, UErrorCode& status); + +}; + +/** + * Struct for null-checking. + * In Java, we can just check the object reference. In C++, we need a different method. + */ +struct SeenMacroProps { + bool notation = false; + bool unit = false; + bool perUnit = false; + bool precision = false; + bool roundingMode = false; + bool grouper = false; + bool padder = false; + bool integerWidth = false; + bool symbols = false; + bool unitWidth = false; + bool sign = false; + bool decimal = false; + bool scale = false; +}; + +} // namespace impl +} // namespace number +U_NAMESPACE_END + +#endif //__SOURCE_NUMBER_SKELETONS_H__ +#endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/deps/icu-small/source/i18n/number_stringbuilder.cpp b/deps/icu-small/source/i18n/number_stringbuilder.cpp index 37159d7e53a..37770d11d51 100644 --- a/deps/icu-small/source/i18n/number_stringbuilder.cpp +++ b/deps/icu-small/source/i18n/number_stringbuilder.cpp @@ -3,11 +3,10 @@ #include "unicode/utypes.h" -#if !UCONFIG_NO_FORMATTING && !UPRV_INCOMPLETE_CPP11_SUPPORT +#if !UCONFIG_NO_FORMATTING #include "number_stringbuilder.h" #include "unicode/utf16.h" -#include "uvectr32.h" using namespace icu; using namespace icu::number; @@ -337,6 +336,11 @@ UnicodeString NumberStringBuilder::toUnicodeString() const { return UnicodeString(getCharPtr() + fZero, fLength); } +const UnicodeString NumberStringBuilder::toTempUnicodeString() const { + // Readonly-alias constructor: + return UnicodeString(FALSE, getCharPtr() + fZero, fLength); +} + UnicodeString NumberStringBuilder::toDebugString() const { UnicodeString sb; sb.append(u"= UNUM_FIELD_COUNT) { status = U_ILLEGAL_ARGUMENT_ERROR; - return; + return FALSE; } auto field = static_cast(rawField); bool seenStart = false; int32_t fractionStart = -1; - for (int i = fZero; i <= fZero + fLength; i++) { + int32_t startIndex = fp.getEndIndex(); + for (int i = fZero + startIndex; i <= fZero + fLength; i++) { Field _field = UNUM_FIELD_COUNT; if (i < fZero + fLength) { _field = getFieldPtr()[i]; @@ -434,10 +439,10 @@ void NumberStringBuilder::populateFieldPosition(FieldPosition &fp, int32_t offse if (field == UNUM_INTEGER_FIELD && _field == UNUM_GROUPING_SEPARATOR_FIELD) { continue; } - fp.setEndIndex(i - fZero + offset); + fp.setEndIndex(i - fZero); break; } else if (!seenStart && field == _field) { - fp.setBeginIndex(i - fZero + offset); + fp.setBeginIndex(i - fZero); seenStart = true; } if (_field == UNUM_INTEGER_FIELD || _field == UNUM_DECIMAL_SEPARATOR_FIELD) { @@ -445,36 +450,28 @@ void NumberStringBuilder::populateFieldPosition(FieldPosition &fp, int32_t offse } } - // Backwards compatibility: FRACTION needs to start after INTEGER if empty - if (field == UNUM_FRACTION_FIELD && !seenStart) { - fp.setBeginIndex(fractionStart + offset); - fp.setEndIndex(fractionStart + offset); + // Backwards compatibility: FRACTION needs to start after INTEGER if empty. + // Do not return that a field was found, though, since there is not actually a fraction part. + if (field == UNUM_FRACTION_FIELD && !seenStart && fractionStart != -1) { + fp.setBeginIndex(fractionStart); + fp.setEndIndex(fractionStart); } + + return seenStart; } -void NumberStringBuilder::populateFieldPositionIterator(FieldPositionIterator &fpi, UErrorCode &status) const { - // TODO: Set an initial capacity on uvec? - LocalPointer uvec(new UVector32(status)); - if (U_FAILURE(status)) { - return; - } - +void NumberStringBuilder::getAllFieldPositions(FieldPositionIteratorHandler& fpih, + UErrorCode& status) const { Field current = UNUM_FIELD_COUNT; int32_t currentStart = -1; for (int32_t i = 0; i < fLength; i++) { Field field = fieldAt(i); if (current == UNUM_INTEGER_FIELD && field == UNUM_GROUPING_SEPARATOR_FIELD) { // Special case: GROUPING_SEPARATOR counts as an INTEGER. - // Add the field, followed by the start index, followed by the end index to uvec. - uvec->addElement(UNUM_GROUPING_SEPARATOR_FIELD, status); - uvec->addElement(i, status); - uvec->addElement(i + 1, status); + fpih.addAttribute(UNUM_GROUPING_SEPARATOR_FIELD, i, i + 1); } else if (current != field) { if (current != UNUM_FIELD_COUNT) { - // Add the field, followed by the start index, followed by the end index to uvec. - uvec->addElement(current, status); - uvec->addElement(currentStart, status); - uvec->addElement(i, status); + fpih.addAttribute(current, currentStart, i); } current = field; currentStart = i; @@ -484,14 +481,8 @@ void NumberStringBuilder::populateFieldPositionIterator(FieldPositionIterator &f } } if (current != UNUM_FIELD_COUNT) { - // Add the field, followed by the start index, followed by the end index to uvec. - uvec->addElement(current, status); - uvec->addElement(currentStart, status); - uvec->addElement(fLength, status); + fpih.addAttribute(current, currentStart, fLength); } - - // Give uvec to the FieldPositionIterator, which adopts it. - fpi.setData(uvec.orphan(), status); } #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 a97cc9ca026..cd8ce2f805e 100644 --- a/deps/icu-small/source/i18n/number_stringbuilder.h +++ b/deps/icu-small/source/i18n/number_stringbuilder.h @@ -3,7 +3,7 @@ #include "unicode/utypes.h" -#if !UCONFIG_NO_FORMATTING && !UPRV_INCOMPLETE_CPP11_SUPPORT +#if !UCONFIG_NO_FORMATTING #ifndef __NUMBER_STRINGBUILDER_H__ #define __NUMBER_STRINGBUILDER_H__ @@ -14,6 +14,7 @@ #include "cstring.h" #include "uassert.h" #include "number_types.h" +#include "fphdlimp.h" U_NAMESPACE_BEGIN namespace number { namespace impl { @@ -84,17 +85,26 @@ class U_I18N_API NumberStringBuilder : public UMemory { int32_t insert(int32_t index, const NumberStringBuilder &other, UErrorCode &status); + /** + * Gets a "safe" UnicodeString that can be used even after the NumberStringBuilder is destructed. + * */ UnicodeString toUnicodeString() const; + /** + * Gets an "unsafe" UnicodeString that is valid only as long as the NumberStringBuilder is alive and + * unchanged. Slightly faster than toUnicodeString(). + */ + const UnicodeString toTempUnicodeString() const; + UnicodeString toDebugString() const; const char16_t *chars() const; bool contentEquals(const NumberStringBuilder &other) const; - void populateFieldPosition(FieldPosition &fp, int32_t offset, UErrorCode &status) const; + bool nextFieldPosition(FieldPosition& fp, UErrorCode& status) const; - void populateFieldPositionIterator(FieldPositionIterator &fpi, UErrorCode &status) const; + void getAllFieldPositions(FieldPositionIteratorHandler& fpih, UErrorCode& status) const; private: bool fUsingHeap = false; diff --git a/deps/icu-small/source/i18n/number_types.h b/deps/icu-small/source/i18n/number_types.h index c01765e2cea..57da72f8aa0 100644 --- a/deps/icu-small/source/i18n/number_types.h +++ b/deps/icu-small/source/i18n/number_types.h @@ -3,7 +3,7 @@ #include "unicode/utypes.h" -#if !UCONFIG_NO_FORMATTING && !UPRV_INCOMPLETE_CPP11_SUPPORT +#if !UCONFIG_NO_FORMATTING #ifndef __NUMBER_TYPES_H__ #define __NUMBER_TYPES_H__ @@ -15,9 +15,9 @@ #include "unicode/utf16.h" #include "uassert.h" #include "unicode/platform.h" +#include "unicode/uniset.h" -U_NAMESPACE_BEGIN -namespace number { +U_NAMESPACE_BEGIN namespace number { namespace impl { // Typedef several enums for brevity and for easier comparison to Java. @@ -39,9 +39,6 @@ static constexpr RoundingMode kDefaultMode = RoundingMode::UNUM_FOUND_HALFEVEN; // ICU4J Equivalent: Padder.FALLBACK_PADDING_STRING static constexpr char16_t kFallbackPaddingString[] = u" "; -// ICU4J Equivalent: NumberFormatterImpl.DEFAULT_CURRENCY -static constexpr char16_t kDefaultCurrency[] = u"XXX"; - // Forward declarations: class Modifier; @@ -87,35 +84,10 @@ enum AffixPatternType { }; enum CompactType { - TYPE_DECIMAL, - TYPE_CURRENCY + TYPE_DECIMAL, TYPE_CURRENCY }; -// TODO: Should this be moved somewhere else, maybe where other ICU classes can use it? -// Exported as U_I18N_API because it is a base class for other exported types -class U_I18N_API CharSequence { -public: - virtual ~CharSequence() = default; - - virtual int32_t length() const = 0; - - virtual char16_t charAt(int32_t index) const = 0; - - virtual UChar32 codePointAt(int32_t index) const { - // Default implementation; can be overridden with a more efficient version - char16_t leading = charAt(index); - if (U16_IS_LEAD(leading) && length() > index + 1) { - char16_t trailing = charAt(index + 1); - return U16_GET_SUPPLEMENTARY(leading, trailing); - } else { - return leading; - } - } - - virtual UnicodeString toUnicodeString() const = 0; -}; - class U_I18N_API AffixPatternProvider { public: static const int32_t AFFIX_PLURAL_MASK = 0xff; @@ -123,12 +95,20 @@ class U_I18N_API AffixPatternProvider { static const int32_t AFFIX_NEGATIVE_SUBPATTERN = 0x200; static const int32_t AFFIX_PADDING = 0x400; - virtual ~AffixPatternProvider() = default; + // Convenience compound flags + static const int32_t AFFIX_POS_PREFIX = AFFIX_PREFIX; + static const int32_t AFFIX_POS_SUFFIX = 0; + static const int32_t AFFIX_NEG_PREFIX = AFFIX_PREFIX | AFFIX_NEGATIVE_SUBPATTERN; + static const int32_t AFFIX_NEG_SUFFIX = AFFIX_NEGATIVE_SUBPATTERN; + + virtual ~AffixPatternProvider(); virtual char16_t charAt(int flags, int i) const = 0; virtual int length(int flags) const = 0; + virtual UnicodeString getString(int flags) const = 0; + virtual bool hasCurrencySign() const = 0; virtual bool positiveHasPlusSign() const = 0; @@ -137,7 +117,7 @@ class U_I18N_API AffixPatternProvider { virtual bool negativeHasMinusSign() const = 0; - virtual bool containsSymbolType(AffixPatternType, UErrorCode &) const = 0; + virtual bool containsSymbolType(AffixPatternType, UErrorCode&) const = 0; /** * True if the pattern has a number placeholder like "0" or "#,##0.00"; false if the pattern does not @@ -159,7 +139,7 @@ class U_I18N_API AffixPatternProvider { */ class U_I18N_API Modifier { public: - virtual ~Modifier() = default; + virtual ~Modifier(); /** * Apply this Modifier to the string builder. @@ -173,8 +153,8 @@ class U_I18N_API Modifier { * formatted. * @return The number of characters (UTF-16 code units) that were added to the string builder. */ - virtual int32_t - apply(NumberStringBuilder &output, int leftIndex, int rightIndex, UErrorCode &status) const = 0; + virtual int32_t apply(NumberStringBuilder& output, int leftIndex, int rightIndex, + UErrorCode& status) const = 0; /** * Gets the length of the prefix. This information can be used in combination with {@link #apply} to extract the @@ -187,7 +167,7 @@ class U_I18N_API Modifier { /** * Returns the number of code points in the modifier, prefix plus suffix. */ - virtual int32_t getCodePointCount(UErrorCode &status) const = 0; + virtual int32_t getCodePointCount(UErrorCode& status) const = 0; /** * Whether this modifier is strong. If a modifier is strong, it should always be applied immediately and not allowed @@ -219,7 +199,7 @@ class U_I18N_API Modifier { */ class U_I18N_API MicroPropsGenerator { public: - virtual ~MicroPropsGenerator() = default; + virtual ~MicroPropsGenerator(); /** * Considers the given {@link DecimalQuantity}, optionally mutates it, and returns a {@link MicroProps}. @@ -230,7 +210,8 @@ class U_I18N_API MicroPropsGenerator { * The MicroProps instance to populate. * @return A MicroProps instance resolved for the quantity. */ - virtual void processQuantity(DecimalQuantity& quantity, MicroProps& micros, UErrorCode& status) const = 0; + virtual void processQuantity(DecimalQuantity& quantity, MicroProps& micros, + UErrorCode& status) const = 0; }; /** @@ -238,7 +219,7 @@ class U_I18N_API MicroPropsGenerator { */ class MultiplierProducer { public: - virtual ~MultiplierProducer() = default; + virtual ~MultiplierProducer(); /** * Maps a magnitude to a multiplier in powers of ten. For example, in compact notation in English, a magnitude of 5 @@ -255,24 +236,31 @@ class MultiplierProducer { template class U_I18N_API NullableValue { public: - NullableValue() : fNull(true) {} + NullableValue() + : fNull(true) {} - NullableValue(const NullableValue &other) = default; + NullableValue(const NullableValue& other) = default; - explicit NullableValue(const T &other) { + explicit NullableValue(const T& other) { fValue = other; fNull = false; } - NullableValue &operator=(const NullableValue &other) = default; + NullableValue& operator=(const NullableValue& other) { + fNull = other.fNull; + if (!fNull) { + fValue = other.fValue; + } + return *this; + } - NullableValue &operator=(const T &other) { + NullableValue& operator=(const T& other) { fValue = other; fNull = false; return *this; } - bool operator==(const NullableValue &other) const { + bool operator==(const NullableValue& other) const { // "fValue == other.fValue" returns UBool, not bool (causes compiler warnings) return fNull ? other.fNull : (other.fNull ? false : static_cast(fValue == other.fValue)); } @@ -286,13 +274,21 @@ class U_I18N_API NullableValue { return fNull; } - T get(UErrorCode &status) const { + T get(UErrorCode& status) const { if (fNull) { status = U_UNDEFINED_VARIABLE; } return fValue; } + T getNoError() const { + return fValue; + } + + T getOrDefault(T defaultValue) const { + return fNull ? defaultValue : fValue; + } + private: bool fNull; T fValue; diff --git a/deps/icu-small/source/i18n/number_utils.cpp b/deps/icu-small/source/i18n/number_utils.cpp new file mode 100644 index 00000000000..c79d2de9fa3 --- /dev/null +++ b/deps/icu-small/source/i18n/number_utils.cpp @@ -0,0 +1,253 @@ +// © 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 +#include +#include "number_decnum.h" +#include "number_types.h" +#include "number_utils.h" +#include "charstr.h" +#include "decContext.h" +#include "decNumber.h" +#include "double-conversion.h" +#include "fphdlimp.h" +#include "uresimp.h" +#include "ureslocs.h" + +using namespace icu; +using namespace icu::number; +using namespace icu::number::impl; + +using icu::double_conversion::DoubleToStringConverter; + + +namespace { + +const char16_t* +doGetPattern(UResourceBundle* res, const char* nsName, const char* patternKey, UErrorCode& publicStatus, + UErrorCode& localStatus) { + // Construct the path into the resource bundle + CharString key; + key.append("NumberElements/", publicStatus); + key.append(nsName, publicStatus); + key.append("/patterns/", publicStatus); + key.append(patternKey, publicStatus); + if (U_FAILURE(publicStatus)) { + return u""; + } + return ures_getStringByKeyWithFallback(res, key.data(), nullptr, &localStatus); +} + +} + + +const char16_t* utils::getPatternForStyle(const Locale& locale, const char* nsName, CldrPatternStyle style, + UErrorCode& status) { + const char* patternKey; + switch (style) { + case CLDR_PATTERN_STYLE_DECIMAL: + patternKey = "decimalFormat"; + break; + case CLDR_PATTERN_STYLE_CURRENCY: + patternKey = "currencyFormat"; + break; + case CLDR_PATTERN_STYLE_ACCOUNTING: + patternKey = "accountingFormat"; + break; + case CLDR_PATTERN_STYLE_PERCENT: + patternKey = "percentFormat"; + break; + case CLDR_PATTERN_STYLE_SCIENTIFIC: + patternKey = "scientificFormat"; + break; + default: + patternKey = "decimalFormat"; // silence compiler error + U_ASSERT(false); + } + LocalUResourceBundlePointer res(ures_open(nullptr, locale.getName(), &status)); + if (U_FAILURE(status)) { return u""; } + + // Attempt to get the pattern with the native numbering system. + UErrorCode localStatus = U_ZERO_ERROR; + const char16_t* pattern; + pattern = doGetPattern(res.getAlias(), nsName, patternKey, status, localStatus); + if (U_FAILURE(status)) { return u""; } + + // Fall back to latn if native numbering system does not have the right pattern + if (U_FAILURE(localStatus) && uprv_strcmp("latn", nsName) != 0) { + localStatus = U_ZERO_ERROR; + pattern = doGetPattern(res.getAlias(), "latn", patternKey, status, localStatus); + if (U_FAILURE(status)) { return u""; } + } + + return pattern; +} + + +DecNum::DecNum() { + uprv_decContextDefault(&fContext, DEC_INIT_BASE); + uprv_decContextSetRounding(&fContext, DEC_ROUND_HALF_EVEN); + fContext.traps = 0; // no traps, thank you (what does this even mean?) +} + +DecNum::DecNum(const DecNum& other, UErrorCode& status) + : fContext(other.fContext) { + // Allocate memory for the new DecNum. + U_ASSERT(fContext.digits == other.fData.getCapacity()); + if (fContext.digits > kDefaultDigits) { + void* p = fData.resize(fContext.digits, 0); + if (p == nullptr) { + status = U_MEMORY_ALLOCATION_ERROR; + return; + } + } + + // Copy the data from the old DecNum to the new one. + uprv_memcpy(fData.getAlias(), other.fData.getAlias(), sizeof(decNumber)); + uprv_memcpy(fData.getArrayStart(), + other.fData.getArrayStart(), + other.fData.getArrayLimit() - other.fData.getArrayStart()); +} + +void DecNum::setTo(StringPiece str, UErrorCode& status) { + // We need NUL-terminated for decNumber; CharString guarantees this, but not StringPiece. + CharString cstr(str, status); + if (U_FAILURE(status)) { return; } + _setTo(cstr.data(), str.length(), status); +} + +void DecNum::setTo(const char* str, UErrorCode& status) { + _setTo(str, static_cast(uprv_strlen(str)), status); +} + +void DecNum::setTo(double d, UErrorCode& status) { + // Need to check for NaN and Infinity before going into DoubleToStringConverter + if (std::isnan(d) != 0 || std::isfinite(d) == 0) { + status = U_UNSUPPORTED_ERROR; + return; + } + + // First convert from double to string, then string to DecNum. + // Allocate enough room for: all digits, "E-324", and NUL-terminator. + char buffer[DoubleToStringConverter::kBase10MaximalLength + 6]; + bool sign; // unused; always positive + int32_t length; + int32_t point; + DoubleToStringConverter::DoubleToAscii( + d, + DoubleToStringConverter::DtoaMode::SHORTEST, + 0, + buffer, + sizeof(buffer), + &sign, + &length, + &point + ); + + // Read initial result as a string. + _setTo(buffer, length, status); + + // Set exponent and bitmask. Note that DoubleToStringConverter does not do negatives. + fData.getAlias()->exponent += point - length; + fData.getAlias()->bits |= static_cast(std::signbit(d) ? DECNEG : 0); +} + +void DecNum::_setTo(const char* str, int32_t maxDigits, UErrorCode& status) { + if (maxDigits > kDefaultDigits) { + fData.resize(maxDigits, 0); + fContext.digits = maxDigits; + } else { + fContext.digits = kDefaultDigits; + } + + static_assert(DECDPUN == 1, "Assumes that DECDPUN is set to 1"); + uprv_decNumberFromString(fData.getAlias(), str, &fContext); + + // Check for invalid syntax and set the corresponding error code. + if ((fContext.status & DEC_Conversion_syntax) != 0) { + status = U_DECIMAL_NUMBER_SYNTAX_ERROR; + return; + } else if (fContext.status != 0) { + // Not a syntax error, but some other error, like an exponent that is too large. + status = U_UNSUPPORTED_ERROR; + return; + } + + // For consistency with Java BigDecimal, no support for DecNum that is NaN or Infinity! + if (decNumberIsSpecial(fData.getAlias())) { + status = U_UNSUPPORTED_ERROR; + return; + } +} + +void +DecNum::setTo(const uint8_t* bcd, int32_t length, int32_t scale, bool isNegative, UErrorCode& status) { + if (length > kDefaultDigits) { + fData.resize(length, 0); + fContext.digits = length; + } else { + fContext.digits = kDefaultDigits; + } + + // "digits is of type int32_t, and must have a value in the range 1 through 999,999,999." + if (length < 1 || length > 999999999) { + // Too large for decNumber + status = U_UNSUPPORTED_ERROR; + return; + } + // "The exponent field holds the exponent of the number. Its range is limited by the requirement that + // "the range of the adjusted exponent of the number be balanced and fit within a whole number of + // "decimal digits (in this implementation, be –999,999,999 through +999,999,999). The adjusted + // "exponent is the exponent that would result if the number were expressed with a single digit before + // "the decimal point, and is therefore given by exponent+digits-1." + if (scale > 999999999 - length + 1 || scale < -999999999 - length + 1) { + // Too large for decNumber + status = U_UNSUPPORTED_ERROR; + return; + } + + fData.getAlias()->digits = length; + fData.getAlias()->exponent = scale; + fData.getAlias()->bits = static_cast(isNegative ? DECNEG : 0); + uprv_decNumberSetBCD(fData, bcd, static_cast(length)); + if (fContext.status != 0) { + // Some error occurred while constructing the decNumber. + status = U_INTERNAL_PROGRAM_ERROR; + } +} + +void DecNum::normalize() { + uprv_decNumberReduce(fData, fData, &fContext); +} + +void DecNum::multiplyBy(const DecNum& rhs, UErrorCode& status) { + uprv_decNumberMultiply(fData, fData, rhs.fData, &fContext); + if (fContext.status != 0) { + status = U_INTERNAL_PROGRAM_ERROR; + } +} + +void DecNum::divideBy(const DecNum& rhs, UErrorCode& status) { + uprv_decNumberDivide(fData, fData, rhs.fData, &fContext); + if (fContext.status != 0) { + status = U_INTERNAL_PROGRAM_ERROR; + } +} + +bool DecNum::isNegative() const { + return decNumberIsNegative(fData.getAlias()); +} + +bool DecNum::isZero() const { + return decNumberIsZero(fData.getAlias()); +} + +#endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/deps/icu-small/source/i18n/number_utils.h b/deps/icu-small/source/i18n/number_utils.h index 3a408d6007a..c367166009c 100644 --- a/deps/icu-small/source/i18n/number_utils.h +++ b/deps/icu-small/source/i18n/number_utils.h @@ -3,7 +3,7 @@ #include "unicode/utypes.h" -#if !UCONFIG_NO_FORMATTING && !UPRV_INCOMPLETE_CPP11_SUPPORT +#if !UCONFIG_NO_FORMATTING #ifndef __NUMBER_UTILS_H__ #define __NUMBER_UTILS_H__ @@ -13,116 +13,80 @@ #include "number_scientific.h" #include "number_patternstring.h" #include "number_modifiers.h" +#include "number_multiplier.h" +#include "number_roundingutils.h" +#include "decNumber.h" +#include "charstr.h" -U_NAMESPACE_BEGIN namespace number { +U_NAMESPACE_BEGIN + +namespace number { namespace impl { -class UnicodeStringCharSequence : public CharSequence { - public: - explicit UnicodeStringCharSequence(const UnicodeString &other) { - fStr = other; - } - - ~UnicodeStringCharSequence() U_OVERRIDE = default; - - int32_t length() const U_OVERRIDE { - return fStr.length(); - } - - char16_t charAt(int32_t index) const U_OVERRIDE { - return fStr.charAt(index); - } - - UChar32 codePointAt(int32_t index) const U_OVERRIDE { - return fStr.char32At(index); - } - - UnicodeString toUnicodeString() const U_OVERRIDE { - // Allocate a UnicodeString of the correct length - UnicodeString output(length(), 0, -1); - for (int32_t i = 0; i < length(); i++) { - output.append(charAt(i)); - } - return output; - } - - private: - UnicodeString fStr; +enum CldrPatternStyle { + CLDR_PATTERN_STYLE_DECIMAL, + CLDR_PATTERN_STYLE_CURRENCY, + CLDR_PATTERN_STYLE_ACCOUNTING, + CLDR_PATTERN_STYLE_PERCENT, + CLDR_PATTERN_STYLE_SCIENTIFIC, + CLDR_PATTERN_STYLE_COUNT, }; -struct MicroProps : public MicroPropsGenerator { +// Namespace for naked functions +namespace utils { - // NOTE: All of these fields are properly initialized in NumberFormatterImpl. - Rounder rounding; - Grouper grouping; - Padder padding; - IntegerWidth integerWidth; - UNumberSignDisplay sign; - UNumberDecimalSeparatorDisplay decimal; - bool useCurrency; - - // Note: This struct has no direct ownership of the following pointers. - const DecimalFormatSymbols *symbols; - const Modifier *modOuter; - const Modifier *modMiddle; - const Modifier *modInner; - - // The following "helper" fields may optionally be used during the MicroPropsGenerator. - // They live here to retain memory. - struct { - ScientificModifier scientificModifier; - EmptyModifier emptyWeakModifier{false}; - EmptyModifier emptyStrongModifier{true}; - } helpers; - - - MicroProps() = default; - - MicroProps(const MicroProps &other) = default; - - MicroProps &operator=(const MicroProps &other) = default; - - void processQuantity(DecimalQuantity &, MicroProps µs, UErrorCode &status) const U_OVERRIDE { - (void)status; - if (this == µs) { - // Unsafe path: no need to perform a copy. - U_ASSERT(!exhausted); - micros.exhausted = true; - U_ASSERT(exhausted); - } else { - // Safe path: copy self into the output micros. - micros = *this; - } +inline int32_t insertDigitFromSymbols(NumberStringBuilder& output, int32_t index, int8_t digit, + const DecimalFormatSymbols& symbols, Field field, + UErrorCode& status) { + if (symbols.getCodePointZero() != -1) { + return output.insertCodePoint(index, symbols.getCodePointZero() + digit, field, status); } + return output.insert(index, symbols.getConstDigitSymbol(digit), field, status); +} - private: - // Internal fields: - bool exhausted = false; -}; +inline bool unitIsCurrency(const MeasureUnit& unit) { + return uprv_strcmp("currency", unit.getType()) == 0; +} + +inline bool unitIsNoUnit(const MeasureUnit& unit) { + return uprv_strcmp("none", unit.getType()) == 0; +} + +inline bool unitIsPercent(const MeasureUnit& unit) { + return uprv_strcmp("percent", unit.getSubtype()) == 0; +} + +inline bool unitIsPermille(const MeasureUnit& unit) { + return uprv_strcmp("permille", unit.getSubtype()) == 0; +} + +// NOTE: In Java, this method is in NumberFormat.java +const char16_t* +getPatternForStyle(const Locale& locale, const char* nsName, CldrPatternStyle style, UErrorCode& status); /** - * This struct provides the result of the number formatting pipeline to FormattedNumber. + * Computes the plural form for this number based on the specified set of rules. * - * The DecimalQuantity is not currently being used by FormattedNumber, but at some point it could be used - * to add a toDecNumber() or similar method. + * @param rules A {@link PluralRules} object representing the set of rules. + * @return The {@link StandardPlural} according to the PluralRules. If the plural form is not in + * the set of standard plurals, {@link StandardPlural#OTHER} is returned instead. */ -struct NumberFormatterResults : public UMemory { - DecimalQuantity quantity; - NumberStringBuilder string; -}; - -inline const UnicodeString getDigitFromSymbols(int8_t digit, const DecimalFormatSymbols &symbols) { - // TODO: Implement DecimalFormatSymbols.getCodePointZero()? - if (digit == 0) { - return symbols.getSymbol(DecimalFormatSymbols::ENumberFormatSymbol::kZeroDigitSymbol); +inline StandardPlural::Form getStandardPlural(const PluralRules *rules, + const IFixedDecimal &fdec) { + if (rules == nullptr) { + // Fail gracefully if the user didn't provide a PluralRules + return StandardPlural::Form::OTHER; } else { - return symbols.getSymbol(static_cast( - DecimalFormatSymbols::ENumberFormatSymbol::kOneDigitSymbol + digit - 1)); + UnicodeString ruleString = rules->select(fdec); + return StandardPlural::orOtherFromString(ruleString); } } +} // namespace utils + } // namespace impl } // namespace number + U_NAMESPACE_END #endif //__NUMBER_UTILS_H__ diff --git a/deps/icu-small/source/i18n/number_utypes.h b/deps/icu-small/source/i18n/number_utypes.h new file mode 100644 index 00000000000..48bfce19697 --- /dev/null +++ b/deps/icu-small/source/i18n/number_utypes.h @@ -0,0 +1,79 @@ +// © 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_NUMBER_UTYPES_H__ +#define __SOURCE_NUMBER_UTYPES_H__ + +#include "unicode/numberformatter.h" +#include "number_types.h" +#include "number_decimalquantity.h" +#include "number_stringbuilder.h" + +U_NAMESPACE_BEGIN namespace number { +namespace impl { + + +/** + * Implementation class for UNumberFormatter with a magic number for safety. + * + * Wraps a LocalizedNumberFormatter by value. + */ +struct UNumberFormatterData : public UMemory { + // The magic number to identify incoming objects. + // Reads in ASCII as "NFR" (NumberFormatteR with room at the end) + static constexpr int32_t kMagic = 0x4E465200; + + // Data members: + int32_t fMagic = kMagic; + LocalizedNumberFormatter fFormatter; + + /** Convert from UNumberFormatter -> UNumberFormatterData. */ + static UNumberFormatterData* validate(UNumberFormatter* input, UErrorCode& status); + + /** Convert from UNumberFormatter -> UNumberFormatterData (const version). */ + static const UNumberFormatterData* validate(const UNumberFormatter* input, UErrorCode& status); + + /** Convert from UNumberFormatterData -> UNumberFormatter. */ + UNumberFormatter* exportForC(); +}; + + +/** + * Implementation class for UFormattedNumber with magic number for safety. + * + * This struct is also held internally by the C++ version FormattedNumber since the member types are not + * declared in the public header file. + * + * The DecimalQuantity is not currently being used by FormattedNumber, but at some point it could be used + * to add a toDecNumber() or similar method. + */ +struct UFormattedNumberData : public UMemory { + // The magic number to identify incoming objects. + // Reads in ASCII as "FDN" (FormatteDNumber with room at the end) + static constexpr int32_t kMagic = 0x46444E00; + + // Data members: + int32_t fMagic = kMagic; + DecimalQuantity quantity; + NumberStringBuilder string; + + /** Convert from UFormattedNumber -> UFormattedNumberData. */ + static UFormattedNumberData* validate(UFormattedNumber* input, UErrorCode& status); + + /** Convert from UFormattedNumber -> UFormattedNumberData (const version). */ + static const UFormattedNumberData* validate(const UFormattedNumber* input, UErrorCode& status); + + /** Convert from UFormattedNumberData -> UFormattedNumber. */ + UFormattedNumber* exportForC(); +}; + + +} // namespace impl +} // namespace number +U_NAMESPACE_END + +#endif //__SOURCE_NUMBER_UTYPES_H__ +#endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/deps/icu-small/source/i18n/numfmt.cpp b/deps/icu-small/source/i18n/numfmt.cpp index fee3bed8bfb..13f23131b18 100644 --- a/deps/icu-small/source/i18n/numfmt.cpp +++ b/deps/icu-small/source/i18n/numfmt.cpp @@ -51,10 +51,11 @@ #include "uassert.h" #include "umutex.h" #include "mutex.h" -#include "digitlst.h" #include #include "sharednumberformat.h" #include "unifiedcache.h" +#include "number_decimalquantity.h" +#include "number_utils.h" //#define FMT_DEBUG @@ -129,31 +130,28 @@ static const UChar * const gLastResortNumberPatterns[UNUM_FORMAT_STYLE_COUNT] = // Keys used for accessing resource bundles -static const char *gNumberElements = "NumberElements"; -static const char *gLatn = "latn"; -static const char *gPatterns = "patterns"; -static const char *gFormatKeys[UNUM_FORMAT_STYLE_COUNT] = { - NULL, // UNUM_PATTERN_DECIMAL - "decimalFormat", // UNUM_DECIMAL - "currencyFormat", // UNUM_CURRENCY - "percentFormat", // UNUM_PERCENT - "scientificFormat", // UNUM_SCIENTIFIC - NULL, // UNUM_SPELLOUT - NULL, // UNUM_ORDINAL - NULL, // UNUM_DURATION - NULL, // UNUM_NUMBERING_SYSTEM - NULL, // UNUM_PATTERN_RULEBASED +static const icu::number::impl::CldrPatternStyle gFormatCldrStyles[UNUM_FORMAT_STYLE_COUNT] = { + /* NULL */ icu::number::impl::CLDR_PATTERN_STYLE_COUNT, // UNUM_PATTERN_DECIMAL + icu::number::impl::CLDR_PATTERN_STYLE_DECIMAL, // UNUM_DECIMAL + icu::number::impl::CLDR_PATTERN_STYLE_CURRENCY, // UNUM_CURRENCY + icu::number::impl::CLDR_PATTERN_STYLE_PERCENT, // UNUM_PERCENT + icu::number::impl::CLDR_PATTERN_STYLE_SCIENTIFIC, // UNUM_SCIENTIFIC + /* NULL */ icu::number::impl::CLDR_PATTERN_STYLE_COUNT, // UNUM_SPELLOUT + /* NULL */ icu::number::impl::CLDR_PATTERN_STYLE_COUNT, // UNUM_ORDINAL + /* NULL */ icu::number::impl::CLDR_PATTERN_STYLE_COUNT, // UNUM_DURATION + /* NULL */ icu::number::impl::CLDR_PATTERN_STYLE_COUNT, // UNUM_NUMBERING_SYSTEM + /* NULL */ icu::number::impl::CLDR_PATTERN_STYLE_COUNT, // UNUM_PATTERN_RULEBASED // For UNUM_CURRENCY_ISO and UNUM_CURRENCY_PLURAL, // the pattern is the same as the pattern of UNUM_CURRENCY // except for replacing the single currency sign with // double currency sign or triple currency sign. - "currencyFormat", // UNUM_CURRENCY_ISO - "currencyFormat", // UNUM_CURRENCY_PLURAL - "accountingFormat", // UNUM_CURRENCY_ACCOUNTING - "currencyFormat", // UNUM_CASH_CURRENCY - NULL, // UNUM_DECIMAL_COMPACT_SHORT - NULL, // UNUM_DECIMAL_COMPACT_LONG - "currencyFormat", // UNUM_CURRENCY_STANDARD + icu::number::impl::CLDR_PATTERN_STYLE_CURRENCY, // UNUM_CURRENCY_ISO + icu::number::impl::CLDR_PATTERN_STYLE_CURRENCY, // UNUM_CURRENCY_PLURAL + icu::number::impl::CLDR_PATTERN_STYLE_ACCOUNTING, // UNUM_CURRENCY_ACCOUNTING + icu::number::impl::CLDR_PATTERN_STYLE_CURRENCY, // UNUM_CASH_CURRENCY + /* NULL */ icu::number::impl::CLDR_PATTERN_STYLE_COUNT, // UNUM_DECIMAL_COMPACT_SHORT + /* NULL */ icu::number::impl::CLDR_PATTERN_STYLE_COUNT, // UNUM_DECIMAL_COMPACT_LONG + icu::number::impl::CLDR_PATTERN_STYLE_CURRENCY, // UNUM_CURRENCY_STANDARD }; // Static hashtable cache of NumberingSystem objects used by NumberFormat @@ -524,7 +522,7 @@ ArgExtractor::ArgExtractor(const NumberFormat& /*nf*/, const Formattable& obj, U ArgExtractor::~ArgExtractor() { } -UnicodeString& NumberFormat::format(const DigitList &number, +UnicodeString& NumberFormat::format(const number::impl::DecimalQuantity &number, UnicodeString& appendTo, FieldPositionIterator* posIter, UErrorCode& status) const { @@ -534,7 +532,7 @@ UnicodeString& NumberFormat::format(const DigitList &number, if (U_FAILURE(status)) { return appendTo; } - double dnum = number.getDouble(); + double dnum = number.toDouble(); format(dnum, appendTo, posIter, status); return appendTo; } @@ -542,7 +540,7 @@ UnicodeString& NumberFormat::format(const DigitList &number, UnicodeString& -NumberFormat::format(const DigitList &number, +NumberFormat::format(const number::impl::DecimalQuantity &number, UnicodeString& appendTo, FieldPosition& pos, UErrorCode &status) const { @@ -552,7 +550,7 @@ NumberFormat::format(const DigitList &number, if (U_FAILURE(status)) { return appendTo; } - double dnum = number.getDouble(); + double dnum = number.toDouble(); format(dnum, appendTo, pos, status); return appendTo; } @@ -578,7 +576,7 @@ NumberFormat::format(const Formattable& obj, return cloneFmt->format(*n, appendTo, pos, status); } - if (n->isNumeric() && n->getDigitList() != NULL) { + if (n->isNumeric() && n->getDecimalQuantity() != NULL) { // Decimal Number. We will have a DigitList available if the value was // set to a decimal number, or if the value originated with a parse. // @@ -587,17 +585,17 @@ NumberFormat::format(const Formattable& obj, // know about DigitList to continue to operate as they had. // // DecimalFormat overrides the DigitList formatting functions. - format(*n->getDigitList(), appendTo, pos, status); + format(*n->getDecimalQuantity(), appendTo, pos, status); } else { switch (n->getType()) { case Formattable::kDouble: - format(n->getDouble(), appendTo, pos); + format(n->getDouble(), appendTo, pos, status); break; case Formattable::kLong: - format(n->getLong(), appendTo, pos); + format(n->getLong(), appendTo, pos, status); break; case Formattable::kInt64: - format(n->getInt64(), appendTo, pos); + format(n->getInt64(), appendTo, pos, status); break; default: status = U_INVALID_FORMAT_ERROR; @@ -633,9 +631,9 @@ NumberFormat::format(const Formattable& obj, return cloneFmt->format(*n, appendTo, posIter, status); } - if (n->isNumeric() && n->getDigitList() != NULL) { + if (n->isNumeric() && n->getDecimalQuantity() != NULL) { // Decimal Number - format(*n->getDigitList(), appendTo, posIter, status); + format(*n->getDecimalQuantity(), appendTo, posIter, status); } else { switch (n->getType()) { case Formattable::kDouble: @@ -1400,27 +1398,13 @@ NumberFormat::makeInstance(const Locale& desiredLocale, return NULL; } - UResourceBundle *resource = ownedResource.orphan(); - UResourceBundle *numElements = ures_getByKeyWithFallback(resource, gNumberElements, NULL, &status); - resource = ures_getByKeyWithFallback(numElements, ns->getName(), resource, &status); - resource = ures_getByKeyWithFallback(resource, gPatterns, resource, &status); - ownedResource.adoptInstead(resource); - - int32_t patLen = 0; - const UChar *patResStr = ures_getStringByKeyWithFallback(resource, gFormatKeys[style], &patLen, &status); - - // Didn't find a pattern specific to the numbering system, so fall back to "latn" - if ( status == U_MISSING_RESOURCE_ERROR && uprv_strcmp(gLatn,ns->getName())) { - status = U_ZERO_ERROR; - resource = ures_getByKeyWithFallback(numElements, gLatn, resource, &status); - resource = ures_getByKeyWithFallback(resource, gPatterns, resource, &status); - patResStr = ures_getStringByKeyWithFallback(resource, gFormatKeys[style], &patLen, &status); - } - - ures_close(numElements); - - // Creates the specified decimal format style of the desired locale. - pattern.setTo(TRUE, patResStr, patLen); + // Load the pattern from data using the common library function + const char16_t* patternPtr = number::impl::utils::getPatternForStyle( + desiredLocale, + ns->getName(), + gFormatCldrStyles[style], + status); + pattern = UnicodeString(TRUE, patternPtr, -1); } if (U_FAILURE(status)) { return NULL; diff --git a/deps/icu-small/source/i18n/numparse_affixes.cpp b/deps/icu-small/source/i18n/numparse_affixes.cpp new file mode 100644 index 00000000000..c30d241693c --- /dev/null +++ b/deps/icu-small/source/i18n/numparse_affixes.cpp @@ -0,0 +1,470 @@ +// © 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 "numparse_types.h" +#include "numparse_affixes.h" +#include "numparse_utils.h" +#include "number_utils.h" + +using namespace icu; +using namespace icu::numparse; +using namespace icu::numparse::impl; +using namespace icu::number; +using namespace icu::number::impl; + + +namespace { + +/** + * Helper method to return whether the given AffixPatternMatcher equals the given pattern string. + * Either both arguments must be null or the pattern string inside the AffixPatternMatcher must equal + * the given pattern string. + */ +static bool matched(const AffixPatternMatcher* affix, const UnicodeString& patternString) { + return (affix == nullptr && patternString.isBogus()) || + (affix != nullptr && affix->getPattern() == patternString); +} + +/** + * Helper method to return the length of the given AffixPatternMatcher. Returns 0 for null. + */ +static int32_t length(const AffixPatternMatcher* matcher) { + return matcher == nullptr ? 0 : matcher->getPattern().length(); +} + +/** + * Helper method to return whether (1) both lhs and rhs are null/invalid, or (2) if they are both + * valid, whether they are equal according to operator==. Similar to Java Objects.equals() + */ +static bool equals(const AffixPatternMatcher* lhs, const AffixPatternMatcher* rhs) { + if (lhs == nullptr && rhs == nullptr) { + return true; + } + if (lhs == nullptr || rhs == nullptr) { + return false; + } + return *lhs == *rhs; +} + +} + + +AffixPatternMatcherBuilder::AffixPatternMatcherBuilder(const UnicodeString& pattern, + AffixTokenMatcherWarehouse& warehouse, + IgnorablesMatcher* ignorables) + : fMatchersLen(0), + fLastTypeOrCp(0), + fPattern(pattern), + fWarehouse(warehouse), + fIgnorables(ignorables) {} + +void AffixPatternMatcherBuilder::consumeToken(AffixPatternType type, UChar32 cp, UErrorCode& status) { + // This is called by AffixUtils.iterateWithConsumer() for each token. + + // Add an ignorables matcher between tokens except between two literals, and don't put two + // ignorables matchers in a row. + if (fIgnorables != nullptr && fMatchersLen > 0 && + (fLastTypeOrCp < 0 || !fIgnorables->getSet()->contains(fLastTypeOrCp))) { + addMatcher(*fIgnorables); + } + + if (type != TYPE_CODEPOINT) { + // Case 1: the token is a symbol. + switch (type) { + case TYPE_MINUS_SIGN: + addMatcher(fWarehouse.minusSign()); + break; + case TYPE_PLUS_SIGN: + addMatcher(fWarehouse.plusSign()); + break; + case TYPE_PERCENT: + addMatcher(fWarehouse.percent()); + break; + case TYPE_PERMILLE: + addMatcher(fWarehouse.permille()); + break; + case TYPE_CURRENCY_SINGLE: + case TYPE_CURRENCY_DOUBLE: + case TYPE_CURRENCY_TRIPLE: + case TYPE_CURRENCY_QUAD: + case TYPE_CURRENCY_QUINT: + // All currency symbols use the same matcher + addMatcher(fWarehouse.currency(status)); + break; + default: + U_ASSERT(FALSE); + } + + } else if (fIgnorables != nullptr && fIgnorables->getSet()->contains(cp)) { + // Case 2: the token is an ignorable literal. + // No action necessary: the ignorables matcher has already been added. + + } else { + // Case 3: the token is a non-ignorable literal. + addMatcher(fWarehouse.nextCodePointMatcher(cp)); + } + fLastTypeOrCp = type != TYPE_CODEPOINT ? type : cp; +} + +void AffixPatternMatcherBuilder::addMatcher(NumberParseMatcher& matcher) { + if (fMatchersLen >= fMatchers.getCapacity()) { + fMatchers.resize(fMatchersLen * 2, fMatchersLen); + } + fMatchers[fMatchersLen++] = &matcher; +} + +AffixPatternMatcher AffixPatternMatcherBuilder::build() { + return AffixPatternMatcher(fMatchers, fMatchersLen, fPattern); +} + + +CodePointMatcherWarehouse::CodePointMatcherWarehouse() + : codePointCount(0), codePointNumBatches(0) {} + +CodePointMatcherWarehouse::~CodePointMatcherWarehouse() { + // Delete the variable number of batches of code point matchers + for (int32_t i = 0; i < codePointNumBatches; i++) { + delete[] codePointsOverflow[i]; + } +} + +CodePointMatcherWarehouse::CodePointMatcherWarehouse(CodePointMatcherWarehouse&& src) U_NOEXCEPT + : codePoints(std::move(src.codePoints)), + codePointsOverflow(std::move(src.codePointsOverflow)), + codePointCount(src.codePointCount), + codePointNumBatches(src.codePointNumBatches) {} + +CodePointMatcherWarehouse& +CodePointMatcherWarehouse::operator=(CodePointMatcherWarehouse&& src) U_NOEXCEPT { + codePoints = std::move(src.codePoints); + codePointsOverflow = std::move(src.codePointsOverflow); + codePointCount = src.codePointCount; + codePointNumBatches = src.codePointNumBatches; + return *this; +} + +NumberParseMatcher& CodePointMatcherWarehouse::nextCodePointMatcher(UChar32 cp) { + if (codePointCount < CODE_POINT_STACK_CAPACITY) { + return codePoints[codePointCount++] = {cp}; + } + int32_t totalCapacity = CODE_POINT_STACK_CAPACITY + codePointNumBatches * CODE_POINT_BATCH_SIZE; + if (codePointCount >= totalCapacity) { + // Need a new batch + auto* nextBatch = new CodePointMatcher[CODE_POINT_BATCH_SIZE]; + if (codePointNumBatches >= codePointsOverflow.getCapacity()) { + // Need more room for storing pointers to batches + codePointsOverflow.resize(codePointNumBatches * 2, codePointNumBatches); + } + codePointsOverflow[codePointNumBatches++] = nextBatch; + } + return codePointsOverflow[codePointNumBatches - 1][(codePointCount++ - CODE_POINT_STACK_CAPACITY) % + CODE_POINT_BATCH_SIZE] = {cp}; +} + + +AffixTokenMatcherWarehouse::AffixTokenMatcherWarehouse(const AffixTokenMatcherSetupData* setupData) + : fSetupData(setupData) {} + +NumberParseMatcher& AffixTokenMatcherWarehouse::minusSign() { + return fMinusSign = {fSetupData->dfs, true}; +} + +NumberParseMatcher& AffixTokenMatcherWarehouse::plusSign() { + return fPlusSign = {fSetupData->dfs, true}; +} + +NumberParseMatcher& AffixTokenMatcherWarehouse::percent() { + return fPercent = {fSetupData->dfs}; +} + +NumberParseMatcher& AffixTokenMatcherWarehouse::permille() { + return fPermille = {fSetupData->dfs}; +} + +NumberParseMatcher& AffixTokenMatcherWarehouse::currency(UErrorCode& status) { + return fCurrency = {fSetupData->currencySymbols, fSetupData->dfs, fSetupData->parseFlags, status}; +} + +IgnorablesMatcher& AffixTokenMatcherWarehouse::ignorables() { + return fSetupData->ignorables; +} + +NumberParseMatcher& AffixTokenMatcherWarehouse::nextCodePointMatcher(UChar32 cp) { + return fCodePoints.nextCodePointMatcher(cp); +} + + +CodePointMatcher::CodePointMatcher(UChar32 cp) + : fCp(cp) {} + +bool CodePointMatcher::match(StringSegment& segment, ParsedNumber& result, UErrorCode&) const { + if (segment.startsWith(fCp)) { + segment.adjustOffsetByCodePoint(); + result.setCharsConsumed(segment); + } + return false; +} + +bool CodePointMatcher::smokeTest(const StringSegment& segment) const { + return segment.startsWith(fCp); +} + +UnicodeString CodePointMatcher::toString() const { + return u""; +} + + +AffixPatternMatcher AffixPatternMatcher::fromAffixPattern(const UnicodeString& affixPattern, + AffixTokenMatcherWarehouse& tokenWarehouse, + parse_flags_t parseFlags, bool* success, + UErrorCode& status) { + if (affixPattern.isEmpty()) { + *success = false; + return {}; + } + *success = true; + + IgnorablesMatcher* ignorables; + if (0 != (parseFlags & PARSE_FLAG_EXACT_AFFIX)) { + ignorables = nullptr; + } else { + ignorables = &tokenWarehouse.ignorables(); + } + + AffixPatternMatcherBuilder builder(affixPattern, tokenWarehouse, ignorables); + AffixUtils::iterateWithConsumer(affixPattern, builder, status); + return builder.build(); +} + +AffixPatternMatcher::AffixPatternMatcher(MatcherArray& matchers, int32_t matchersLen, + const UnicodeString& pattern) + : ArraySeriesMatcher(matchers, matchersLen), fPattern(pattern) {} + +UnicodeString AffixPatternMatcher::getPattern() const { + return fPattern.toAliasedUnicodeString(); +} + +bool AffixPatternMatcher::operator==(const AffixPatternMatcher& other) const { + return fPattern == other.fPattern; +} + + +AffixMatcherWarehouse::AffixMatcherWarehouse(AffixTokenMatcherWarehouse* tokenWarehouse) + : fTokenWarehouse(tokenWarehouse) { +} + +bool AffixMatcherWarehouse::isInteresting(const AffixPatternProvider& patternInfo, + const IgnorablesMatcher& ignorables, parse_flags_t parseFlags, + UErrorCode& status) { + UnicodeString posPrefixString = patternInfo.getString(AffixPatternProvider::AFFIX_POS_PREFIX); + UnicodeString posSuffixString = patternInfo.getString(AffixPatternProvider::AFFIX_POS_SUFFIX); + UnicodeString negPrefixString; + UnicodeString negSuffixString; + if (patternInfo.hasNegativeSubpattern()) { + negPrefixString = patternInfo.getString(AffixPatternProvider::AFFIX_NEG_PREFIX); + negSuffixString = patternInfo.getString(AffixPatternProvider::AFFIX_NEG_SUFFIX); + } + + if (0 == (parseFlags & PARSE_FLAG_USE_FULL_AFFIXES) && + AffixUtils::containsOnlySymbolsAndIgnorables(posPrefixString, *ignorables.getSet(), status) && + AffixUtils::containsOnlySymbolsAndIgnorables(posSuffixString, *ignorables.getSet(), status) && + AffixUtils::containsOnlySymbolsAndIgnorables(negPrefixString, *ignorables.getSet(), status) && + AffixUtils::containsOnlySymbolsAndIgnorables(negSuffixString, *ignorables.getSet(), status) + // HACK: Plus and minus sign are a special case: we accept them trailing only if they are + // trailing in the pattern string. + && !AffixUtils::containsType(posSuffixString, TYPE_PLUS_SIGN, status) && + !AffixUtils::containsType(posSuffixString, TYPE_MINUS_SIGN, status) && + !AffixUtils::containsType(negSuffixString, TYPE_PLUS_SIGN, status) && + !AffixUtils::containsType(negSuffixString, TYPE_MINUS_SIGN, status)) { + // The affixes contain only symbols and ignorables. + // No need to generate affix matchers. + return false; + } + return true; +} + +void AffixMatcherWarehouse::createAffixMatchers(const AffixPatternProvider& patternInfo, + MutableMatcherCollection& output, + const IgnorablesMatcher& ignorables, + parse_flags_t parseFlags, UErrorCode& status) { + if (!isInteresting(patternInfo, ignorables, parseFlags, status)) { + return; + } + + // The affixes have interesting characters, or we are in strict mode. + // Use initial capacity of 6, the highest possible number of AffixMatchers. + UnicodeString sb; + bool includeUnpaired = 0 != (parseFlags & PARSE_FLAG_INCLUDE_UNPAIRED_AFFIXES); + UNumberSignDisplay signDisplay = (0 != (parseFlags & PARSE_FLAG_PLUS_SIGN_ALLOWED)) ? UNUM_SIGN_ALWAYS + : UNUM_SIGN_AUTO; + + int32_t numAffixMatchers = 0; + int32_t numAffixPatternMatchers = 0; + + AffixPatternMatcher* posPrefix = nullptr; + AffixPatternMatcher* posSuffix = nullptr; + + // Pre-process the affix strings to resolve LDML rules like sign display. + for (int8_t signum = 1; signum >= -1; signum--) { + // Generate Prefix + bool hasPrefix = false; + PatternStringUtils::patternInfoToStringBuilder( + patternInfo, true, signum, signDisplay, StandardPlural::OTHER, false, sb); + fAffixPatternMatchers[numAffixPatternMatchers] = AffixPatternMatcher::fromAffixPattern( + sb, *fTokenWarehouse, parseFlags, &hasPrefix, status); + AffixPatternMatcher* prefix = hasPrefix ? &fAffixPatternMatchers[numAffixPatternMatchers++] + : nullptr; + + // Generate Suffix + bool hasSuffix = false; + PatternStringUtils::patternInfoToStringBuilder( + patternInfo, false, signum, signDisplay, StandardPlural::OTHER, false, sb); + fAffixPatternMatchers[numAffixPatternMatchers] = AffixPatternMatcher::fromAffixPattern( + sb, *fTokenWarehouse, parseFlags, &hasSuffix, status); + AffixPatternMatcher* suffix = hasSuffix ? &fAffixPatternMatchers[numAffixPatternMatchers++] + : nullptr; + + if (signum == 1) { + posPrefix = prefix; + posSuffix = suffix; + } else if (equals(prefix, posPrefix) && equals(suffix, posSuffix)) { + // Skip adding these matchers (we already have equivalents) + continue; + } + + // Flags for setting in the ParsedNumber; the token matchers may add more. + int flags = (signum == -1) ? FLAG_NEGATIVE : 0; + + // Note: it is indeed possible for posPrefix and posSuffix to both be null. + // We still need to add that matcher for strict mode to work. + fAffixMatchers[numAffixMatchers++] = {prefix, suffix, flags}; + if (includeUnpaired && prefix != nullptr && suffix != nullptr) { + // The following if statements are designed to prevent adding two identical matchers. + if (signum == 1 || !equals(prefix, posPrefix)) { + fAffixMatchers[numAffixMatchers++] = {prefix, nullptr, flags}; + } + if (signum == 1 || !equals(suffix, posSuffix)) { + fAffixMatchers[numAffixMatchers++] = {nullptr, suffix, flags}; + } + } + } + + // Put the AffixMatchers in order, and then add them to the output. + // Since there are at most 9 elements, do a simple-to-implement bubble sort. + bool madeChanges; + do { + madeChanges = false; + for (int32_t i = 1; i < numAffixMatchers; i++) { + if (fAffixMatchers[i - 1].compareTo(fAffixMatchers[i]) > 0) { + madeChanges = true; + AffixMatcher temp = std::move(fAffixMatchers[i - 1]); + fAffixMatchers[i - 1] = std::move(fAffixMatchers[i]); + fAffixMatchers[i] = std::move(temp); + } + } + } while (madeChanges); + + for (int32_t i = 0; i < numAffixMatchers; i++) { + // Enable the following line to debug affixes + //std::cout << "Adding affix matcher: " << CStr(fAffixMatchers[i].toString())() << std::endl; + output.addMatcher(fAffixMatchers[i]); + } +} + + +AffixMatcher::AffixMatcher(AffixPatternMatcher* prefix, AffixPatternMatcher* suffix, result_flags_t flags) + : fPrefix(prefix), fSuffix(suffix), fFlags(flags) {} + +bool AffixMatcher::match(StringSegment& segment, ParsedNumber& result, UErrorCode& status) const { + if (!result.seenNumber()) { + // Prefix + // Do not match if: + // 1. We have already seen a prefix (result.prefix != null) + // 2. The prefix in this AffixMatcher is empty (prefix == null) + if (!result.prefix.isBogus() || fPrefix == nullptr) { + return false; + } + + // Attempt to match the prefix. + int initialOffset = segment.getOffset(); + bool maybeMore = fPrefix->match(segment, result, status); + if (initialOffset != segment.getOffset()) { + result.prefix = fPrefix->getPattern(); + } + return maybeMore; + + } else { + // Suffix + // Do not match if: + // 1. We have already seen a suffix (result.suffix != null) + // 2. The suffix in this AffixMatcher is empty (suffix == null) + // 3. The matched prefix does not equal this AffixMatcher's prefix + if (!result.suffix.isBogus() || fSuffix == nullptr || !matched(fPrefix, result.prefix)) { + return false; + } + + // Attempt to match the suffix. + int initialOffset = segment.getOffset(); + bool maybeMore = fSuffix->match(segment, result, status); + if (initialOffset != segment.getOffset()) { + result.suffix = fSuffix->getPattern(); + } + return maybeMore; + } +} + +bool AffixMatcher::smokeTest(const StringSegment& segment) const { + return (fPrefix != nullptr && fPrefix->smokeTest(segment)) || + (fSuffix != nullptr && fSuffix->smokeTest(segment)); +} + +void AffixMatcher::postProcess(ParsedNumber& result) const { + // Check to see if our affix is the one that was matched. If so, set the flags in the result. + if (matched(fPrefix, result.prefix) && matched(fSuffix, result.suffix)) { + // Fill in the result prefix and suffix with non-null values (empty string). + // Used by strict mode to determine whether an entire affix pair was matched. + if (result.prefix.isBogus()) { + result.prefix = UnicodeString(); + } + if (result.suffix.isBogus()) { + result.suffix = UnicodeString(); + } + result.flags |= fFlags; + if (fPrefix != nullptr) { + fPrefix->postProcess(result); + } + if (fSuffix != nullptr) { + fSuffix->postProcess(result); + } + } +} + +int8_t AffixMatcher::compareTo(const AffixMatcher& rhs) const { + const AffixMatcher& lhs = *this; + if (length(lhs.fPrefix) != length(rhs.fPrefix)) { + return length(lhs.fPrefix) > length(rhs.fPrefix) ? -1 : 1; + } else if (length(lhs.fSuffix) != length(rhs.fSuffix)) { + return length(lhs.fSuffix) > length(rhs.fSuffix) ? -1 : 1; + } else { + return 0; + } +} + +UnicodeString AffixMatcher::toString() const { + bool isNegative = 0 != (fFlags & FLAG_NEGATIVE); + return UnicodeString(u"getPattern() : u"null") + u"#" + + (fSuffix ? fSuffix->getPattern() : u"null") + u">"; + +} + + +#endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/deps/icu-small/source/i18n/numparse_affixes.h b/deps/icu-small/source/i18n/numparse_affixes.h new file mode 100644 index 00000000000..be8c4fb5647 --- /dev/null +++ b/deps/icu-small/source/i18n/numparse_affixes.h @@ -0,0 +1,255 @@ +// © 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 __NUMPARSE_AFFIXES_H__ +#define __NUMPARSE_AFFIXES_H__ + +#include "numparse_types.h" +#include "numparse_symbols.h" +#include "numparse_currency.h" +#include "number_affixutils.h" +#include "number_currencysymbols.h" + +#include + +U_NAMESPACE_BEGIN +namespace numparse { +namespace impl { + +// Forward-declaration of implementation classes for friending +class AffixPatternMatcherBuilder; +class AffixPatternMatcher; + +using ::icu::number::impl::AffixPatternProvider; +using ::icu::number::impl::TokenConsumer; +using ::icu::number::impl::CurrencySymbols; + + +class CodePointMatcher : public NumberParseMatcher, public UMemory { + public: + CodePointMatcher() = default; // WARNING: Leaves the object in an unusable state + + CodePointMatcher(UChar32 cp); + + bool match(StringSegment& segment, ParsedNumber& result, UErrorCode& status) const override; + + bool smokeTest(const StringSegment& segment) const override; + + UnicodeString toString() const override; + + private: + UChar32 fCp; +}; + +} // namespace impl +} // namespace numparse + +// Export a explicit template instantiations of MaybeStackArray and CompactUnicodeString. +// 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.) +// Note: These need to be outside of the impl::numparse namespace, or Clang will generate a compile error. +#if U_PF_WINDOWS <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN +template class U_I18N_API MaybeStackArray; +template class U_I18N_API MaybeStackArray; +template class U_I18N_API numparse::impl::CompactUnicodeString<4>; +#endif + +namespace numparse { +namespace impl { + +/** + * A warehouse to retain ownership of CodePointMatchers. + */ +// Exported as U_I18N_API for tests +class U_I18N_API CodePointMatcherWarehouse : public UMemory { + private: + static constexpr int32_t CODE_POINT_STACK_CAPACITY = 5; // Number of entries directly on the stack + static constexpr int32_t CODE_POINT_BATCH_SIZE = 10; // Number of entries per heap allocation + + public: + CodePointMatcherWarehouse(); + + // A custom destructor is needed to free the memory from MaybeStackArray. + // A custom move constructor and move assignment seem to be needed because of the custom destructor. + + ~CodePointMatcherWarehouse(); + + CodePointMatcherWarehouse(CodePointMatcherWarehouse&& src) U_NOEXCEPT; + + CodePointMatcherWarehouse& operator=(CodePointMatcherWarehouse&& src) U_NOEXCEPT; + + NumberParseMatcher& nextCodePointMatcher(UChar32 cp); + + private: + std::array codePoints; // By value + MaybeStackArray codePointsOverflow; // On heap in "batches" + int32_t codePointCount; // Total for both the ones by value and on heap + int32_t codePointNumBatches; // Number of batches in codePointsOverflow +}; + + +struct AffixTokenMatcherSetupData { + const CurrencySymbols& currencySymbols; + const DecimalFormatSymbols& dfs; + IgnorablesMatcher& ignorables; + const Locale& locale; + parse_flags_t parseFlags; +}; + + +/** + * Small helper class that generates matchers for individual tokens for AffixPatternMatcher. + * + * In Java, this is called AffixTokenMatcherFactory (a "factory"). However, in C++, it is called a + * "warehouse", because in addition to generating the matchers, it also retains ownership of them. The + * warehouse must stay in scope for the whole lifespan of the AffixPatternMatcher that uses matchers from + * the warehouse. + * + * @author sffc + */ +// Exported as U_I18N_API for tests +class U_I18N_API AffixTokenMatcherWarehouse : public UMemory { + public: + AffixTokenMatcherWarehouse() = default; // WARNING: Leaves the object in an unusable state + + AffixTokenMatcherWarehouse(const AffixTokenMatcherSetupData* setupData); + + NumberParseMatcher& minusSign(); + + NumberParseMatcher& plusSign(); + + NumberParseMatcher& percent(); + + NumberParseMatcher& permille(); + + NumberParseMatcher& currency(UErrorCode& status); + + IgnorablesMatcher& ignorables(); + + NumberParseMatcher& nextCodePointMatcher(UChar32 cp); + + private: + // NOTE: The following field may be unsafe to access after construction is done! + const AffixTokenMatcherSetupData* fSetupData; + + // NOTE: These are default-constructed and should not be used until initialized. + MinusSignMatcher fMinusSign; + PlusSignMatcher fPlusSign; + PercentMatcher fPercent; + PermilleMatcher fPermille; + CombinedCurrencyMatcher fCurrency; + + // Use a child class for code point matchers, since it requires non-default operators. + CodePointMatcherWarehouse fCodePoints; + + friend class AffixPatternMatcherBuilder; + friend class AffixPatternMatcher; +}; + + +class AffixPatternMatcherBuilder : public TokenConsumer, public MutableMatcherCollection { + public: + AffixPatternMatcherBuilder(const UnicodeString& pattern, AffixTokenMatcherWarehouse& warehouse, + IgnorablesMatcher* ignorables); + + void consumeToken(::icu::number::impl::AffixPatternType type, UChar32 cp, UErrorCode& status) override; + + /** NOTE: You can build only once! */ + AffixPatternMatcher build(); + + private: + ArraySeriesMatcher::MatcherArray fMatchers; + int32_t fMatchersLen; + int32_t fLastTypeOrCp; + + const UnicodeString& fPattern; + AffixTokenMatcherWarehouse& fWarehouse; + IgnorablesMatcher* fIgnorables; + + void addMatcher(NumberParseMatcher& matcher) override; +}; + + +// Exported as U_I18N_API for tests +class U_I18N_API AffixPatternMatcher : public ArraySeriesMatcher { + public: + AffixPatternMatcher() = default; // WARNING: Leaves the object in an unusable state + + static AffixPatternMatcher fromAffixPattern(const UnicodeString& affixPattern, + AffixTokenMatcherWarehouse& warehouse, + parse_flags_t parseFlags, bool* success, + UErrorCode& status); + + UnicodeString getPattern() const; + + bool operator==(const AffixPatternMatcher& other) const; + + private: + CompactUnicodeString<4> fPattern; + + AffixPatternMatcher(MatcherArray& matchers, int32_t matchersLen, const UnicodeString& pattern); + + friend class AffixPatternMatcherBuilder; +}; + + +class AffixMatcher : public NumberParseMatcher, public UMemory { + public: + AffixMatcher() = default; // WARNING: Leaves the object in an unusable state + + AffixMatcher(AffixPatternMatcher* prefix, AffixPatternMatcher* suffix, result_flags_t flags); + + bool match(StringSegment& segment, ParsedNumber& result, UErrorCode& status) const override; + + void postProcess(ParsedNumber& result) const override; + + bool smokeTest(const StringSegment& segment) const override; + + int8_t compareTo(const AffixMatcher& rhs) const; + + UnicodeString toString() const override; + + private: + AffixPatternMatcher* fPrefix; + AffixPatternMatcher* fSuffix; + result_flags_t fFlags; +}; + + +/** + * A C++-only class to retain ownership of the AffixMatchers needed for parsing. + */ +class AffixMatcherWarehouse { + public: + AffixMatcherWarehouse() = default; // WARNING: Leaves the object in an unusable state + + AffixMatcherWarehouse(AffixTokenMatcherWarehouse* tokenWarehouse); + + void createAffixMatchers(const AffixPatternProvider& patternInfo, MutableMatcherCollection& output, + const IgnorablesMatcher& ignorables, parse_flags_t parseFlags, + UErrorCode& status); + + private: + // 9 is the limit: positive, zero, and negative, each with prefix, suffix, and prefix+suffix + AffixMatcher fAffixMatchers[9]; + // 6 is the limit: positive, zero, and negative, a prefix and a suffix for each + AffixPatternMatcher fAffixPatternMatchers[6]; + // Reference to the warehouse for tokens used by the AffixPatternMatchers + AffixTokenMatcherWarehouse* fTokenWarehouse; + + friend class AffixMatcher; + + static bool isInteresting(const AffixPatternProvider& patternInfo, const IgnorablesMatcher& ignorables, + parse_flags_t parseFlags, UErrorCode& status); +}; + + +} // namespace impl +} // namespace numparse +U_NAMESPACE_END + +#endif //__NUMPARSE_AFFIXES_H__ +#endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/deps/icu-small/source/i18n/numparse_compositions.cpp b/deps/icu-small/source/i18n/numparse_compositions.cpp new file mode 100644 index 00000000000..19253da805f --- /dev/null +++ b/deps/icu-small/source/i18n/numparse_compositions.cpp @@ -0,0 +1,107 @@ +// © 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 "numparse_types.h" +#include "numparse_compositions.h" +#include "unicode/uniset.h" + +using namespace icu; +using namespace icu::numparse; +using namespace icu::numparse::impl; + + +bool SeriesMatcher::match(StringSegment& segment, ParsedNumber& result, UErrorCode& status) const { + ParsedNumber backup(result); + + int32_t initialOffset = segment.getOffset(); + bool maybeMore = true; + for (auto* it = begin(); it < end();) { + const NumberParseMatcher* matcher = *it; + int matcherOffset = segment.getOffset(); + if (segment.length() != 0) { + maybeMore = matcher->match(segment, result, status); + } else { + // Nothing for this matcher to match; ask for more. + maybeMore = true; + } + + bool success = (segment.getOffset() != matcherOffset); + bool isFlexible = matcher->isFlexible(); + if (success && isFlexible) { + // Match succeeded, and this is a flexible matcher. Re-run it. + } else if (success) { + // Match succeeded, and this is NOT a flexible matcher. Proceed to the next matcher. + it++; + // Small hack: if there is another matcher coming, do not accept trailing weak chars. + // Needed for proper handling of currency spacing. + if (it < end() && segment.getOffset() != result.charEnd && result.charEnd > matcherOffset) { + segment.setOffset(result.charEnd); + } + } else if (isFlexible) { + // Match failed, and this is a flexible matcher. Try again with the next matcher. + it++; + } else { + // Match failed, and this is NOT a flexible matcher. Exit. + segment.setOffset(initialOffset); + result = backup; + return maybeMore; + } + } + + // All matchers in the series succeeded. + return maybeMore; +} + +bool SeriesMatcher::smokeTest(const StringSegment& segment) const { + // NOTE: The range-based for loop calls the virtual begin() and end() methods. + // NOTE: We only want the first element. Use the for loop for boundary checking. + for (auto& matcher : *this) { + // SeriesMatchers are never allowed to start with a Flexible matcher. + U_ASSERT(!matcher->isFlexible()); + return matcher->smokeTest(segment); + } + return false; +} + +void SeriesMatcher::postProcess(ParsedNumber& result) const { + // NOTE: The range-based for loop calls the virtual begin() and end() methods. + for (auto* matcher : *this) { + matcher->postProcess(result); + } +} + + +ArraySeriesMatcher::ArraySeriesMatcher() + : fMatchersLen(0) { +} + +ArraySeriesMatcher::ArraySeriesMatcher(MatcherArray& matchers, int32_t matchersLen) + : fMatchers(std::move(matchers)), fMatchersLen(matchersLen) { +} + +int32_t ArraySeriesMatcher::length() const { + return fMatchersLen; +} + +const NumberParseMatcher* const* ArraySeriesMatcher::begin() const { + return fMatchers.getAlias(); +} + +const NumberParseMatcher* const* ArraySeriesMatcher::end() const { + return fMatchers.getAlias() + fMatchersLen; +} + +UnicodeString ArraySeriesMatcher::toString() const { + return u""; +} + + +#endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/deps/icu-small/source/i18n/numparse_compositions.h b/deps/icu-small/source/i18n/numparse_compositions.h new file mode 100644 index 00000000000..f085912def1 --- /dev/null +++ b/deps/icu-small/source/i18n/numparse_compositions.h @@ -0,0 +1,124 @@ +// © 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_NUMPARSE_COMPOSITIONS__ +#define __SOURCE_NUMPARSE_COMPOSITIONS__ + +#include "numparse_types.h" + +U_NAMESPACE_BEGIN + +// Export an explicit template instantiation of the MaybeStackArray that is used as a data member of ArraySeriesMatcher. +// When building DLLs for Windows this is required even though no direct access to the MaybeStackArray 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 +template class U_I18N_API MaybeStackArray; +#endif + +namespace numparse { +namespace impl { + +/** + * Base class for AnyMatcher and SeriesMatcher. + */ +// Exported as U_I18N_API for tests +class U_I18N_API CompositionMatcher : public NumberParseMatcher { + protected: + // No construction except by subclasses! + CompositionMatcher() = default; + + // To be overridden by subclasses (used for iteration): + virtual const NumberParseMatcher* const* begin() const = 0; + + // To be overridden by subclasses (used for iteration): + virtual const NumberParseMatcher* const* end() const = 0; +}; + + +// NOTE: AnyMatcher is no longer being used. The previous definition is shown below. +// The implementation can be found in SVN source control, deleted around March 30, 2018. +///** +// * Composes a number of matchers, and succeeds if any of the matchers succeed. Always greedily chooses +// * the first matcher in the list to succeed. +// * +// * NOTE: In C++, this is a base class, unlike ICU4J, which uses a factory-style interface. +// * +// * @author sffc +// * @see SeriesMatcher +// */ +//class AnyMatcher : public CompositionMatcher { +// public: +// bool match(StringSegment& segment, ParsedNumber& result, UErrorCode& status) const override; +// +// bool smokeTest(const StringSegment& segment) const override; +// +// void postProcess(ParsedNumber& result) const override; +// +// protected: +// // No construction except by subclasses! +// AnyMatcher() = default; +//}; + + +/** + * Composes a number of matchers, running one after another. Matches the input string only if all of the + * matchers in the series succeed. Performs greedy matches within the context of the series. + * + * @author sffc + * @see AnyMatcher + */ +// Exported as U_I18N_API for tests +class U_I18N_API SeriesMatcher : public CompositionMatcher { + public: + bool match(StringSegment& segment, ParsedNumber& result, UErrorCode& status) const override; + + bool smokeTest(const StringSegment& segment) const override; + + void postProcess(ParsedNumber& result) const override; + + virtual int32_t length() const = 0; + + protected: + // No construction except by subclasses! + SeriesMatcher() = default; +}; + +/** + * An implementation of SeriesMatcher that references an array of matchers. + * + * The object adopts the array, but NOT the matchers contained inside the array. + */ +// Exported as U_I18N_API for tests +class U_I18N_API ArraySeriesMatcher : public SeriesMatcher { + public: + ArraySeriesMatcher(); // WARNING: Leaves the object in an unusable state + + typedef MaybeStackArray MatcherArray; + + /** The array is std::move'd */ + ArraySeriesMatcher(MatcherArray& matchers, int32_t matchersLen); + + UnicodeString toString() const override; + + int32_t length() const override; + + protected: + const NumberParseMatcher* const* begin() const override; + + const NumberParseMatcher* const* end() const override; + + private: + MatcherArray fMatchers; + int32_t fMatchersLen; +}; + + +} // namespace impl +} // namespace numparse +U_NAMESPACE_END + +#endif //__SOURCE_NUMPARSE_COMPOSITIONS__ +#endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/deps/icu-small/source/i18n/numparse_currency.cpp b/deps/icu-small/source/i18n/numparse_currency.cpp new file mode 100644 index 00000000000..ae8196ec483 --- /dev/null +++ b/deps/icu-small/source/i18n/numparse_currency.cpp @@ -0,0 +1,186 @@ +// © 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 "numparse_types.h" +#include "numparse_currency.h" +#include "ucurrimp.h" +#include "unicode/errorcode.h" +#include "numparse_utils.h" + +using namespace icu; +using namespace icu::numparse; +using namespace icu::numparse::impl; + + +CombinedCurrencyMatcher::CombinedCurrencyMatcher(const CurrencySymbols& currencySymbols, const DecimalFormatSymbols& dfs, + parse_flags_t parseFlags, UErrorCode& status) + : fCurrency1(currencySymbols.getCurrencySymbol(status)), + fCurrency2(currencySymbols.getIntlCurrencySymbol(status)), + fUseFullCurrencyData(0 == (parseFlags & PARSE_FLAG_NO_FOREIGN_CURRENCY)), + afterPrefixInsert(dfs.getPatternForCurrencySpacing(UNUM_CURRENCY_INSERT, false, status)), + beforeSuffixInsert(dfs.getPatternForCurrencySpacing(UNUM_CURRENCY_INSERT, true, status)), + fLocaleName(dfs.getLocale().getName(), -1, status) { + utils::copyCurrencyCode(fCurrencyCode, currencySymbols.getIsoCode()); + + // Pre-load the long names for the current locale and currency + // if we are parsing without the full currency data. + if (!fUseFullCurrencyData) { + for (int32_t i=0; i(i); + fLocalLongNames[i] = currencySymbols.getPluralName(plural, status); + } + } + + // TODO: Figure out how to make this faster and re-enable. + // Computing the "lead code points" set for fastpathing is too slow to use in production. + // See http://bugs.icu-project.org/trac/ticket/13584 +// // Compute the full set of characters that could be the first in a currency to allow for +// // efficient smoke test. +// fLeadCodePoints.add(fCurrency1.char32At(0)); +// fLeadCodePoints.add(fCurrency2.char32At(0)); +// fLeadCodePoints.add(beforeSuffixInsert.char32At(0)); +// uprv_currencyLeads(fLocaleName.data(), fLeadCodePoints, status); +// // Always apply case mapping closure for currencies +// fLeadCodePoints.closeOver(USET_ADD_CASE_MAPPINGS); +// fLeadCodePoints.freeze(); +} + +bool +CombinedCurrencyMatcher::match(StringSegment& segment, ParsedNumber& result, UErrorCode& status) const { + if (result.currencyCode[0] != 0) { + return false; + } + + // Try to match a currency spacing separator. + int32_t initialOffset = segment.getOffset(); + bool maybeMore = false; + if (result.seenNumber() && !beforeSuffixInsert.isEmpty()) { + int32_t overlap = segment.getCommonPrefixLength(beforeSuffixInsert); + if (overlap == beforeSuffixInsert.length()) { + segment.adjustOffset(overlap); + // Note: let currency spacing be a weak match. Don't update chars consumed. + } + maybeMore = maybeMore || overlap == segment.length(); + } + + // Match the currency string, and reset if we didn't find one. + maybeMore = maybeMore || matchCurrency(segment, result, status); + if (result.currencyCode[0] == 0) { + segment.setOffset(initialOffset); + return maybeMore; + } + + // Try to match a currency spacing separator. + if (!result.seenNumber() && !afterPrefixInsert.isEmpty()) { + int32_t overlap = segment.getCommonPrefixLength(afterPrefixInsert); + if (overlap == afterPrefixInsert.length()) { + segment.adjustOffset(overlap); + // Note: let currency spacing be a weak match. Don't update chars consumed. + } + maybeMore = maybeMore || overlap == segment.length(); + } + + return maybeMore; +} + +bool CombinedCurrencyMatcher::matchCurrency(StringSegment& segment, ParsedNumber& result, + UErrorCode& status) const { + bool maybeMore = false; + + int32_t overlap1; + if (!fCurrency1.isEmpty()) { + overlap1 = segment.getCaseSensitivePrefixLength(fCurrency1); + } else { + overlap1 = -1; + } + maybeMore = maybeMore || overlap1 == segment.length(); + if (overlap1 == fCurrency1.length()) { + utils::copyCurrencyCode(result.currencyCode, fCurrencyCode); + segment.adjustOffset(overlap1); + result.setCharsConsumed(segment); + return maybeMore; + } + + int32_t overlap2; + if (!fCurrency2.isEmpty()) { + overlap2 = segment.getCaseSensitivePrefixLength(fCurrency2); + } else { + overlap2 = -1; + } + maybeMore = maybeMore || overlap2 == segment.length(); + if (overlap2 == fCurrency2.length()) { + utils::copyCurrencyCode(result.currencyCode, fCurrencyCode); + segment.adjustOffset(overlap2); + result.setCharsConsumed(segment); + return maybeMore; + } + + if (fUseFullCurrencyData) { + // Use the full currency data. + // NOTE: This call site should be improved with #13584. + const UnicodeString segmentString = segment.toTempUnicodeString(); + + // Try to parse the currency + ParsePosition ppos(0); + int32_t partialMatchLen = 0; + uprv_parseCurrency( + fLocaleName.data(), + segmentString, + ppos, + UCURR_SYMBOL_NAME, // checks for both UCURR_SYMBOL_NAME and UCURR_LONG_NAME + &partialMatchLen, + result.currencyCode, + status); + maybeMore = maybeMore || partialMatchLen == segment.length(); + + if (U_SUCCESS(status) && ppos.getIndex() != 0) { + // Complete match. + // NOTE: The currency code should already be saved in the ParsedNumber. + segment.adjustOffset(ppos.getIndex()); + result.setCharsConsumed(segment); + return maybeMore; + } + + } else { + // Use the locale long names. + int32_t longestFullMatch = 0; + for (int32_t i=0; i longestFullMatch) { + longestFullMatch = name.length(); + } + maybeMore = maybeMore || overlap > 0; + } + if (longestFullMatch > 0) { + utils::copyCurrencyCode(result.currencyCode, fCurrencyCode); + segment.adjustOffset(longestFullMatch); + result.setCharsConsumed(segment); + return maybeMore; + } + } + + // No match found. + return maybeMore; +} + +bool CombinedCurrencyMatcher::smokeTest(const StringSegment&) const { + // TODO: See constructor + return true; + //return segment.startsWith(fLeadCodePoints); +} + +UnicodeString CombinedCurrencyMatcher::toString() const { + return u""; +} + + +#endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/deps/icu-small/source/i18n/numparse_currency.h b/deps/icu-small/source/i18n/numparse_currency.h new file mode 100644 index 00000000000..a94943312fd --- /dev/null +++ b/deps/icu-small/source/i18n/numparse_currency.h @@ -0,0 +1,74 @@ +// © 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 __NUMPARSE_CURRENCY_H__ +#define __NUMPARSE_CURRENCY_H__ + +#include "numparse_types.h" +#include "numparse_compositions.h" +#include "charstr.h" +#include "number_currencysymbols.h" +#include "unicode/uniset.h" + +U_NAMESPACE_BEGIN namespace numparse { +namespace impl { + +using ::icu::number::impl::CurrencySymbols; + +/** + * Matches a currency, either a custom currency or one from the data bundle. The class is called + * "combined" to emphasize that the currency string may come from one of multiple sources. + * + * Will match currency spacing either before or after the number depending on whether we are currently in + * the prefix or suffix. + * + * The implementation of this class is slightly different between J and C. See #13584 for a follow-up. + * + * @author sffc + */ +// Exported as U_I18N_API for tests +class U_I18N_API CombinedCurrencyMatcher : public NumberParseMatcher, public UMemory { + public: + CombinedCurrencyMatcher() = default; // WARNING: Leaves the object in an unusable state + + CombinedCurrencyMatcher(const CurrencySymbols& currencySymbols, const DecimalFormatSymbols& dfs, + parse_flags_t parseFlags, UErrorCode& status); + + bool match(StringSegment& segment, ParsedNumber& result, UErrorCode& status) const override; + + bool smokeTest(const StringSegment& segment) const override; + + UnicodeString toString() const override; + + private: + UChar fCurrencyCode[4]; + UnicodeString fCurrency1; + UnicodeString fCurrency2; + + bool fUseFullCurrencyData; + UnicodeString fLocalLongNames[StandardPlural::COUNT]; + + UnicodeString afterPrefixInsert; + UnicodeString beforeSuffixInsert; + + // We could use Locale instead of CharString here, but + // Locale has a non-trivial default constructor. + CharString fLocaleName; + + // TODO: See comments in constructor in numparse_currency.cpp + // UnicodeSet fLeadCodePoints; + + /** Matches the currency string without concern for currency spacing. */ + bool matchCurrency(StringSegment& segment, ParsedNumber& result, UErrorCode& status) const; +}; + + +} // namespace impl +} // namespace numparse +U_NAMESPACE_END + +#endif //__NUMPARSE_CURRENCY_H__ +#endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/deps/icu-small/source/i18n/numparse_decimal.cpp b/deps/icu-small/source/i18n/numparse_decimal.cpp new file mode 100644 index 00000000000..b120c5c6ad2 --- /dev/null +++ b/deps/icu-small/source/i18n/numparse_decimal.cpp @@ -0,0 +1,458 @@ +// © 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 "numparse_types.h" +#include "numparse_decimal.h" +#include "static_unicode_sets.h" +#include "numparse_utils.h" +#include "unicode/uchar.h" +#include "putilimp.h" +#include "number_decimalquantity.h" + +using namespace icu; +using namespace icu::numparse; +using namespace icu::numparse::impl; + + +DecimalMatcher::DecimalMatcher(const DecimalFormatSymbols& symbols, const Grouper& grouper, + parse_flags_t parseFlags) { + if (0 != (parseFlags & PARSE_FLAG_MONETARY_SEPARATORS)) { + groupingSeparator = symbols.getConstSymbol(DecimalFormatSymbols::kMonetaryGroupingSeparatorSymbol); + decimalSeparator = symbols.getConstSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol); + } else { + groupingSeparator = symbols.getConstSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol); + decimalSeparator = symbols.getConstSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol); + } + bool strictSeparators = 0 != (parseFlags & PARSE_FLAG_STRICT_SEPARATORS); + unisets::Key groupingKey = strictSeparators ? unisets::STRICT_ALL_SEPARATORS + : unisets::ALL_SEPARATORS; + + // Attempt to find separators in the static cache + + groupingUniSet = unisets::get(groupingKey); + unisets::Key decimalKey = unisets::chooseFrom( + decimalSeparator, + strictSeparators ? unisets::STRICT_COMMA : unisets::COMMA, + strictSeparators ? unisets::STRICT_PERIOD : unisets::PERIOD); + if (decimalKey >= 0) { + decimalUniSet = unisets::get(decimalKey); + } else if (!decimalSeparator.isEmpty()) { + auto* set = new UnicodeSet(); + set->add(decimalSeparator.char32At(0)); + set->freeze(); + decimalUniSet = set; + fLocalDecimalUniSet.adoptInstead(set); + } else { + decimalUniSet = unisets::get(unisets::EMPTY); + } + + if (groupingKey >= 0 && decimalKey >= 0) { + // Everything is available in the static cache + separatorSet = groupingUniSet; + leadSet = unisets::get( + strictSeparators ? unisets::DIGITS_OR_ALL_SEPARATORS + : unisets::DIGITS_OR_STRICT_ALL_SEPARATORS); + } else { + auto* set = new UnicodeSet(); + set->addAll(*groupingUniSet); + set->addAll(*decimalUniSet); + set->freeze(); + separatorSet = set; + fLocalSeparatorSet.adoptInstead(set); + leadSet = nullptr; + } + + UChar32 cpZero = symbols.getCodePointZero(); + if (cpZero == -1 || !u_isdigit(cpZero) || u_digit(cpZero, 10) != 0) { + // Uncommon case: okay to allocate. + auto digitStrings = new UnicodeString[10]; + fLocalDigitStrings.adoptInstead(digitStrings); + for (int32_t i = 0; i <= 9; i++) { + digitStrings[i] = symbols.getConstDigitSymbol(i); + } + } + + requireGroupingMatch = 0 != (parseFlags & PARSE_FLAG_STRICT_GROUPING_SIZE); + groupingDisabled = 0 != (parseFlags & PARSE_FLAG_GROUPING_DISABLED); + integerOnly = 0 != (parseFlags & PARSE_FLAG_INTEGER_ONLY); + grouping1 = grouper.getPrimary(); + grouping2 = grouper.getSecondary(); + + // Fraction grouping parsing is disabled for now but could be enabled later. + // See http://bugs.icu-project.org/trac/ticket/10794 + // fractionGrouping = 0 != (parseFlags & PARSE_FLAG_FRACTION_GROUPING_ENABLED); +} + +bool DecimalMatcher::match(StringSegment& segment, ParsedNumber& result, UErrorCode& status) const { + return match(segment, result, 0, status); +} + +bool DecimalMatcher::match(StringSegment& segment, ParsedNumber& result, int8_t exponentSign, + UErrorCode&) const { + if (result.seenNumber() && exponentSign == 0) { + // A number has already been consumed. + return false; + } else if (exponentSign != 0) { + // scientific notation always comes after the number + U_ASSERT(!result.quantity.bogus); + } + + // Initial offset before any character consumption. + int32_t initialOffset = segment.getOffset(); + + // Return value: whether to ask for more characters. + bool maybeMore = false; + + // All digits consumed so far. + number::impl::DecimalQuantity digitsConsumed; + digitsConsumed.bogus = true; + + // The total number of digits after the decimal place, used for scaling the result. + int32_t digitsAfterDecimalPlace = 0; + + // The actual grouping and decimal separators used in the string. + // If non-null, we have seen that token. + UnicodeString actualGroupingString; + UnicodeString actualDecimalString; + actualGroupingString.setToBogus(); + actualDecimalString.setToBogus(); + + // Information for two groups: the previous group and the current group. + // + // Each group has three pieces of information: + // + // Offset: the string position of the beginning of the group, including a leading separator + // if there was a leading separator. This is needed in case we need to rewind the parse to + // that position. + // + // Separator type: + // 0 => beginning of string + // 1 => lead separator is a grouping separator + // 2 => lead separator is a decimal separator + // + // Count: the number of digits in the group. If -1, the group has been validated. + int32_t currGroupOffset = 0; + int32_t currGroupSepType = 0; + int32_t currGroupCount = 0; + int32_t prevGroupOffset = -1; + int32_t prevGroupSepType = -1; + int32_t prevGroupCount = -1; + + while (segment.length() > 0) { + maybeMore = false; + + // Attempt to match a digit. + int8_t digit = -1; + + // Try by code point digit value. + UChar32 cp = segment.getCodePoint(); + if (u_isdigit(cp)) { + segment.adjustOffset(U16_LENGTH(cp)); + digit = static_cast(u_digit(cp, 10)); + } + + // Try by digit string. + if (digit == -1 && !fLocalDigitStrings.isNull()) { + for (int32_t i = 0; i < 10; i++) { + const UnicodeString& str = fLocalDigitStrings[i]; + if (str.isEmpty()) { + continue; + } + int32_t overlap = segment.getCommonPrefixLength(str); + if (overlap == str.length()) { + segment.adjustOffset(overlap); + digit = static_cast(i); + break; + } + maybeMore = maybeMore || (overlap == segment.length()); + } + } + + if (digit >= 0) { + // Digit was found. + if (digitsConsumed.bogus) { + digitsConsumed.bogus = false; + digitsConsumed.clear(); + } + digitsConsumed.appendDigit(digit, 0, true); + currGroupCount++; + if (!actualDecimalString.isBogus()) { + digitsAfterDecimalPlace++; + } + continue; + } + + // Attempt to match a literal grouping or decimal separator. + bool isDecimal = false; + bool isGrouping = false; + + // 1) Attempt the decimal separator string literal. + // if (we have not seen a decimal separator yet) { ... } + if (actualDecimalString.isBogus() && !decimalSeparator.isEmpty()) { + int32_t overlap = segment.getCommonPrefixLength(decimalSeparator); + maybeMore = maybeMore || (overlap == segment.length()); + if (overlap == decimalSeparator.length()) { + isDecimal = true; + actualDecimalString = decimalSeparator; + } + } + + // 2) Attempt to match the actual grouping string literal. + if (!actualGroupingString.isBogus()) { + int32_t overlap = segment.getCommonPrefixLength(actualGroupingString); + maybeMore = maybeMore || (overlap == segment.length()); + if (overlap == actualGroupingString.length()) { + isGrouping = true; + } + } + + // 2.5) Attempt to match a new the grouping separator string literal. + // if (we have not seen a grouping or decimal separator yet) { ... } + if (!groupingDisabled && actualGroupingString.isBogus() && actualDecimalString.isBogus() && + !groupingSeparator.isEmpty()) { + int32_t overlap = segment.getCommonPrefixLength(groupingSeparator); + maybeMore = maybeMore || (overlap == segment.length()); + if (overlap == groupingSeparator.length()) { + isGrouping = true; + actualGroupingString = groupingSeparator; + } + } + + // 3) Attempt to match a decimal separator from the equivalence set. + // if (we have not seen a decimal separator yet) { ... } + // The !isGrouping is to confirm that we haven't yet matched the current character. + if (!isGrouping && actualDecimalString.isBogus()) { + if (decimalUniSet->contains(cp)) { + isDecimal = true; + actualDecimalString = UnicodeString(cp); + } + } + + // 4) Attempt to match a grouping separator from the equivalence set. + // if (we have not seen a grouping or decimal separator yet) { ... } + if (!groupingDisabled && actualGroupingString.isBogus() && actualDecimalString.isBogus()) { + if (groupingUniSet->contains(cp)) { + isGrouping = true; + actualGroupingString = UnicodeString(cp); + } + } + + // Leave if we failed to match this as a separator. + if (!isDecimal && !isGrouping) { + break; + } + + // Check for conditions when we don't want to accept the separator. + if (isDecimal && integerOnly) { + break; + } else if (currGroupSepType == 2 && isGrouping) { + // Fraction grouping + break; + } + + // Validate intermediate grouping sizes. + bool prevValidSecondary = validateGroup(prevGroupSepType, prevGroupCount, false); + bool currValidPrimary = validateGroup(currGroupSepType, currGroupCount, true); + if (!prevValidSecondary || (isDecimal && !currValidPrimary)) { + // Invalid grouping sizes. + if (isGrouping && currGroupCount == 0) { + // Trailing grouping separators: these are taken care of below + U_ASSERT(currGroupSepType == 1); + } else if (requireGroupingMatch) { + // Strict mode: reject the parse + digitsConsumed.clear(); + digitsConsumed.bogus = true; + } + break; + } else if (requireGroupingMatch && currGroupCount == 0 && currGroupSepType == 1) { + break; + } else { + // Grouping sizes OK so far. + prevGroupOffset = currGroupOffset; + prevGroupCount = currGroupCount; + if (isDecimal) { + // Do not validate this group any more. + prevGroupSepType = -1; + } else { + prevGroupSepType = currGroupSepType; + } + } + + // OK to accept the separator. + // Special case: don't update currGroup if it is empty; this allows two grouping + // separators in a row in lenient mode. + if (currGroupCount != 0) { + currGroupOffset = segment.getOffset(); + } + currGroupSepType = isGrouping ? 1 : 2; + currGroupCount = 0; + if (isGrouping) { + segment.adjustOffset(actualGroupingString.length()); + } else { + segment.adjustOffset(actualDecimalString.length()); + } + } + + // End of main loop. + // Back up if there was a trailing grouping separator. + // Shift prev -> curr so we can check it as a final group. + if (currGroupSepType != 2 && currGroupCount == 0) { + maybeMore = true; + segment.setOffset(currGroupOffset); + currGroupOffset = prevGroupOffset; + currGroupSepType = prevGroupSepType; + currGroupCount = prevGroupCount; + prevGroupOffset = -1; + prevGroupSepType = 0; + prevGroupCount = 1; + } + + // Validate final grouping sizes. + bool prevValidSecondary = validateGroup(prevGroupSepType, prevGroupCount, false); + bool currValidPrimary = validateGroup(currGroupSepType, currGroupCount, true); + if (!requireGroupingMatch) { + // The cases we need to handle here are lone digits. + // Examples: "1,1" "1,1," "1,1,1" "1,1,1," ",1" (all parse as 1) + // See more examples in numberformattestspecification.txt + int32_t digitsToRemove = 0; + if (!prevValidSecondary) { + segment.setOffset(prevGroupOffset); + digitsToRemove += prevGroupCount; + digitsToRemove += currGroupCount; + } else if (!currValidPrimary && (prevGroupSepType != 0 || prevGroupCount != 0)) { + maybeMore = true; + segment.setOffset(currGroupOffset); + digitsToRemove += currGroupCount; + } + if (digitsToRemove != 0) { + digitsConsumed.adjustMagnitude(-digitsToRemove); + digitsConsumed.truncate(); + } + prevValidSecondary = true; + currValidPrimary = true; + } + if (currGroupSepType != 2 && (!prevValidSecondary || !currValidPrimary)) { + // Grouping failure. + digitsConsumed.bogus = true; + } + + // Strings that start with a separator but have no digits, + // or strings that failed a grouping size check. + if (digitsConsumed.bogus) { + maybeMore = maybeMore || (segment.length() == 0); + segment.setOffset(initialOffset); + return maybeMore; + } + + // We passed all inspections. Start post-processing. + + // Adjust for fraction part. + digitsConsumed.adjustMagnitude(-digitsAfterDecimalPlace); + + // Set the digits, either normal or exponent. + if (exponentSign != 0 && segment.getOffset() != initialOffset) { + bool overflow = false; + if (digitsConsumed.fitsInLong()) { + int64_t exponentLong = digitsConsumed.toLong(false); + U_ASSERT(exponentLong >= 0); + if (exponentLong <= INT32_MAX) { + auto exponentInt = static_cast(exponentLong); + if (result.quantity.adjustMagnitude(exponentSign * exponentInt)) { + overflow = true; + } + } else { + overflow = true; + } + } else { + overflow = true; + } + if (overflow) { + if (exponentSign == -1) { + // Set to zero + result.quantity.clear(); + } else { + // Set to infinity + result.quantity.bogus = true; + result.flags |= FLAG_INFINITY; + } + } + } else { + result.quantity = digitsConsumed; + } + + // Set other information into the result and return. + if (!actualDecimalString.isBogus()) { + result.flags |= FLAG_HAS_DECIMAL_SEPARATOR; + } + result.setCharsConsumed(segment); + return segment.length() == 0 || maybeMore; +} + +bool DecimalMatcher::validateGroup(int32_t sepType, int32_t count, bool isPrimary) const { + if (requireGroupingMatch) { + if (sepType == -1) { + // No such group (prevGroup before first shift). + return true; + } else if (sepType == 0) { + // First group. + if (isPrimary) { + // No grouping separators is OK. + return true; + } else { + return count != 0 && count <= grouping2; + } + } else if (sepType == 1) { + // Middle group. + if (isPrimary) { + return count == grouping1; + } else { + return count == grouping2; + } + } else { + U_ASSERT(sepType == 2); + // After the decimal separator. + return true; + } + } else { + if (sepType == 1) { + // #11230: don't accept middle groups with only 1 digit. + return count != 1; + } else { + return true; + } + } +} + +bool DecimalMatcher::smokeTest(const StringSegment& segment) const { + // The common case uses a static leadSet for efficiency. + if (fLocalDigitStrings.isNull() && leadSet != nullptr) { + return segment.startsWith(*leadSet); + } + if (segment.startsWith(*separatorSet) || u_isdigit(segment.getCodePoint())) { + return true; + } + if (fLocalDigitStrings.isNull()) { + return false; + } + for (int32_t i = 0; i < 10; i++) { + if (segment.startsWith(fLocalDigitStrings[i])) { + return true; + } + } + return false; +} + +UnicodeString DecimalMatcher::toString() const { + return u""; +} + + +#endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/deps/icu-small/source/i18n/numparse_decimal.h b/deps/icu-small/source/i18n/numparse_decimal.h new file mode 100644 index 00000000000..ec6c76487e4 --- /dev/null +++ b/deps/icu-small/source/i18n/numparse_decimal.h @@ -0,0 +1,76 @@ +// © 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 __NUMPARSE_DECIMAL_H__ +#define __NUMPARSE_DECIMAL_H__ + +#include "unicode/uniset.h" +#include "numparse_types.h" + +U_NAMESPACE_BEGIN namespace numparse { +namespace impl { + +using ::icu::number::impl::Grouper; + +class DecimalMatcher : public NumberParseMatcher, public UMemory { + public: + DecimalMatcher() = default; // WARNING: Leaves the object in an unusable state + + DecimalMatcher(const DecimalFormatSymbols& symbols, const Grouper& grouper, + parse_flags_t parseFlags); + + bool match(StringSegment& segment, ParsedNumber& result, UErrorCode& status) const override; + + bool + match(StringSegment& segment, ParsedNumber& result, int8_t exponentSign, UErrorCode& status) const; + + bool smokeTest(const StringSegment& segment) const override; + + UnicodeString toString() const override; + + private: + /** If true, only accept strings whose grouping sizes match the locale */ + bool requireGroupingMatch; + + /** If true, do not accept grouping separators at all */ + bool groupingDisabled; + + // Fraction grouping parsing is disabled for now but could be enabled later. + // See http://bugs.icu-project.org/trac/ticket/10794 + // bool fractionGrouping; + + /** If true, do not accept numbers in the fraction */ + bool integerOnly; + + int16_t grouping1; + int16_t grouping2; + + UnicodeString groupingSeparator; + UnicodeString decimalSeparator; + + // Assumption: these sets all consist of single code points. If this assumption needs to be broken, + // fix getLeadCodePoints() as well as matching logic. Be careful of the performance impact. + const UnicodeSet* groupingUniSet; + const UnicodeSet* decimalUniSet; + const UnicodeSet* separatorSet; + const UnicodeSet* leadSet; + + // Make this class the owner of a few objects that could be allocated. + // The first three LocalPointers are used for assigning ownership only. + LocalPointer fLocalDecimalUniSet; + LocalPointer fLocalSeparatorSet; + LocalArray fLocalDigitStrings; + + bool validateGroup(int32_t sepType, int32_t count, bool isPrimary) const; +}; + + +} // namespace impl +} // namespace numparse +U_NAMESPACE_END + +#endif //__NUMPARSE_DECIMAL_H__ +#endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/deps/icu-small/source/i18n/numparse_impl.cpp b/deps/icu-small/source/i18n/numparse_impl.cpp new file mode 100644 index 00000000000..5fa52f63351 --- /dev/null +++ b/deps/icu-small/source/i18n/numparse_impl.cpp @@ -0,0 +1,361 @@ +// © 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 +#include +#include "number_types.h" +#include "number_patternstring.h" +#include "numparse_types.h" +#include "numparse_impl.h" +#include "numparse_symbols.h" +#include "numparse_decimal.h" +#include "unicode/numberformatter.h" +#include "cstr.h" +#include "number_mapper.h" +#include "static_unicode_sets.h" + +using namespace icu; +using namespace icu::number; +using namespace icu::number::impl; +using namespace icu::numparse; +using namespace icu::numparse::impl; + + +NumberParseMatcher::~NumberParseMatcher() = default; + + +NumberParserImpl* +NumberParserImpl::createSimpleParser(const Locale& locale, const UnicodeString& patternString, + parse_flags_t parseFlags, UErrorCode& status) { + + LocalPointer parser(new NumberParserImpl(parseFlags)); + DecimalFormatSymbols symbols(locale, status); + + parser->fLocalMatchers.ignorables = {unisets::DEFAULT_IGNORABLES}; + IgnorablesMatcher& ignorables = parser->fLocalMatchers.ignorables; + + DecimalFormatSymbols dfs(locale, status); + dfs.setSymbol(DecimalFormatSymbols::kCurrencySymbol, u"IU$"); + dfs.setSymbol(DecimalFormatSymbols::kIntlCurrencySymbol, u"ICU"); + CurrencySymbols currencySymbols({u"ICU", status}, locale, dfs, status); + + ParsedPatternInfo patternInfo; + PatternParser::parseToPatternInfo(patternString, patternInfo, status); + + // The following statements set up the affix matchers. + AffixTokenMatcherSetupData affixSetupData = { + currencySymbols, symbols, ignorables, locale, parseFlags}; + parser->fLocalMatchers.affixTokenMatcherWarehouse = {&affixSetupData}; + parser->fLocalMatchers.affixMatcherWarehouse = {&parser->fLocalMatchers.affixTokenMatcherWarehouse}; + parser->fLocalMatchers.affixMatcherWarehouse.createAffixMatchers( + patternInfo, *parser, ignorables, parseFlags, status); + + Grouper grouper = Grouper::forStrategy(UNUM_GROUPING_AUTO); + grouper.setLocaleData(patternInfo, locale); + + parser->addMatcher(parser->fLocalMatchers.ignorables); + parser->addMatcher(parser->fLocalMatchers.decimal = {symbols, grouper, parseFlags}); + parser->addMatcher(parser->fLocalMatchers.minusSign = {symbols, false}); + parser->addMatcher(parser->fLocalMatchers.plusSign = {symbols, false}); + parser->addMatcher(parser->fLocalMatchers.percent = {symbols}); + parser->addMatcher(parser->fLocalMatchers.permille = {symbols}); + parser->addMatcher(parser->fLocalMatchers.nan = {symbols}); + parser->addMatcher(parser->fLocalMatchers.infinity = {symbols}); + parser->addMatcher(parser->fLocalMatchers.padding = {u"@"}); + parser->addMatcher(parser->fLocalMatchers.scientific = {symbols, grouper}); + parser->addMatcher(parser->fLocalMatchers.currency = {currencySymbols, symbols, parseFlags, status}); +// parser.addMatcher(new RequireNumberMatcher()); + + parser->freeze(); + return parser.orphan(); +} + +NumberParserImpl* +NumberParserImpl::createParserFromProperties(const number::impl::DecimalFormatProperties& properties, + const DecimalFormatSymbols& symbols, bool parseCurrency, + UErrorCode& status) { + Locale locale = symbols.getLocale(); + PropertiesAffixPatternProvider localPAPP; + CurrencyPluralInfoAffixProvider localCPIAP; + AffixPatternProvider* affixProvider; + if (properties.currencyPluralInfo.fPtr.isNull()) { + localPAPP.setTo(properties, status); + affixProvider = &localPAPP; + } else { + localCPIAP.setTo(*properties.currencyPluralInfo.fPtr, properties, status); + affixProvider = &localCPIAP; + } + if (affixProvider == nullptr || U_FAILURE(status)) { return nullptr; } + CurrencyUnit currency = resolveCurrency(properties, locale, status); + CurrencySymbols currencySymbols(currency, locale, symbols, status); + bool isStrict = properties.parseMode.getOrDefault(PARSE_MODE_STRICT) == PARSE_MODE_STRICT; + Grouper grouper = Grouper::forProperties(properties); + int parseFlags = 0; + if (affixProvider == nullptr || U_FAILURE(status)) { return nullptr; } + if (!properties.parseCaseSensitive) { + parseFlags |= PARSE_FLAG_IGNORE_CASE; + } + if (properties.parseIntegerOnly) { + parseFlags |= PARSE_FLAG_INTEGER_ONLY; + } + if (properties.signAlwaysShown) { + parseFlags |= PARSE_FLAG_PLUS_SIGN_ALLOWED; + } + if (isStrict) { + parseFlags |= PARSE_FLAG_STRICT_GROUPING_SIZE; + parseFlags |= PARSE_FLAG_STRICT_SEPARATORS; + parseFlags |= PARSE_FLAG_USE_FULL_AFFIXES; + parseFlags |= PARSE_FLAG_EXACT_AFFIX; + } else { + parseFlags |= PARSE_FLAG_INCLUDE_UNPAIRED_AFFIXES; + } + if (grouper.getPrimary() <= 0) { + parseFlags |= PARSE_FLAG_GROUPING_DISABLED; + } + if (parseCurrency || affixProvider->hasCurrencySign()) { + parseFlags |= PARSE_FLAG_MONETARY_SEPARATORS; + } + if (!parseCurrency) { + parseFlags |= PARSE_FLAG_NO_FOREIGN_CURRENCY; + } + + LocalPointer parser(new NumberParserImpl(parseFlags)); + + parser->fLocalMatchers.ignorables = { + isStrict ? unisets::STRICT_IGNORABLES : unisets::DEFAULT_IGNORABLES}; + IgnorablesMatcher& ignorables = parser->fLocalMatchers.ignorables; + + ////////////////////// + /// AFFIX MATCHERS /// + ////////////////////// + + // The following statements set up the affix matchers. + AffixTokenMatcherSetupData affixSetupData = { + currencySymbols, symbols, ignorables, locale, parseFlags}; + parser->fLocalMatchers.affixTokenMatcherWarehouse = {&affixSetupData}; + parser->fLocalMatchers.affixMatcherWarehouse = {&parser->fLocalMatchers.affixTokenMatcherWarehouse}; + parser->fLocalMatchers.affixMatcherWarehouse.createAffixMatchers( + *affixProvider, *parser, ignorables, parseFlags, status); + + //////////////////////// + /// CURRENCY MATCHER /// + //////////////////////// + + if (parseCurrency || affixProvider->hasCurrencySign()) { + parser->addMatcher(parser->fLocalMatchers.currency = {currencySymbols, symbols, parseFlags, status}); + } + + /////////////// + /// PERCENT /// + /////////////// + + // 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)) { + parser->addMatcher(parser->fLocalMatchers.percent = {symbols}); + } + if (affixProvider->containsSymbolType(AffixPatternType::TYPE_PERMILLE, status)) { + parser->addMatcher(parser->fLocalMatchers.permille = {symbols}); + } + + /////////////////////////////// + /// OTHER STANDARD MATCHERS /// + /////////////////////////////// + + if (!isStrict) { + parser->addMatcher(parser->fLocalMatchers.plusSign = {symbols, false}); + parser->addMatcher(parser->fLocalMatchers.minusSign = {symbols, false}); + } + parser->addMatcher(parser->fLocalMatchers.nan = {symbols}); + parser->addMatcher(parser->fLocalMatchers.infinity = {symbols}); + UnicodeString padString = properties.padString; + if (!padString.isBogus() && !ignorables.getSet()->contains(padString)) { + parser->addMatcher(parser->fLocalMatchers.padding = {padString}); + } + parser->addMatcher(parser->fLocalMatchers.ignorables); + parser->addMatcher(parser->fLocalMatchers.decimal = {symbols, grouper, parseFlags}); + // NOTE: parseNoExponent doesn't disable scientific parsing if we have a scientific formatter + if (!properties.parseNoExponent || properties.minimumExponentDigits > 0) { + parser->addMatcher(parser->fLocalMatchers.scientific = {symbols, grouper}); + } + + ////////////////// + /// VALIDATORS /// + ////////////////// + + parser->addMatcher(parser->fLocalValidators.number = {}); + if (isStrict) { + parser->addMatcher(parser->fLocalValidators.affix = {}); + } + if (parseCurrency) { + parser->addMatcher(parser->fLocalValidators.currency = {}); + } + if (properties.decimalPatternMatchRequired) { + bool patternHasDecimalSeparator = + properties.decimalSeparatorAlwaysShown || properties.maximumFractionDigits != 0; + parser->addMatcher(parser->fLocalValidators.decimalSeparator = {patternHasDecimalSeparator}); + } + // The multiplier takes care of scaling percentages. + Scale multiplier = scaleFromProperties(properties); + if (multiplier.isValid()) { + parser->addMatcher(parser->fLocalValidators.multiplier = {multiplier}); + } + + parser->freeze(); + return parser.orphan(); +} + +NumberParserImpl::NumberParserImpl(parse_flags_t parseFlags) + : fParseFlags(parseFlags) { +} + +NumberParserImpl::~NumberParserImpl() { + fNumMatchers = 0; +} + +void NumberParserImpl::addMatcher(NumberParseMatcher& matcher) { + if (fNumMatchers + 1 > fMatchers.getCapacity()) { + fMatchers.resize(fNumMatchers * 2, fNumMatchers); + } + fMatchers[fNumMatchers] = &matcher; + fNumMatchers++; +} + +void NumberParserImpl::freeze() { + fFrozen = true; +} + +parse_flags_t NumberParserImpl::getParseFlags() const { + return fParseFlags; +} + +void NumberParserImpl::parse(const UnicodeString& input, bool greedy, ParsedNumber& result, + UErrorCode& status) const { + return parse(input, 0, greedy, result, status); +} + +void NumberParserImpl::parse(const UnicodeString& input, int32_t start, bool greedy, ParsedNumber& result, + UErrorCode& status) const { + if (U_FAILURE(status)) { + return; + } + U_ASSERT(fFrozen); + // TODO: Check start >= 0 and start < input.length() + StringSegment segment(input, 0 != (fParseFlags & PARSE_FLAG_IGNORE_CASE)); + segment.adjustOffset(start); + if (greedy) { + parseGreedyRecursive(segment, result, status); + } else { + parseLongestRecursive(segment, result, status); + } + for (int32_t i = 0; i < fNumMatchers; i++) { + fMatchers[i]->postProcess(result); + } + result.postProcess(); +} + +void NumberParserImpl::parseGreedyRecursive(StringSegment& segment, ParsedNumber& result, + UErrorCode& status) const { + // Base Case + if (segment.length() == 0) { + return; + } + + int initialOffset = segment.getOffset(); + for (int32_t i = 0; i < fNumMatchers; i++) { + const NumberParseMatcher* matcher = fMatchers[i]; + if (!matcher->smokeTest(segment)) { + continue; + } + matcher->match(segment, result, status); + if (U_FAILURE(status)) { + return; + } + if (segment.getOffset() != initialOffset) { + // In a greedy parse, recurse on only the first match. + parseGreedyRecursive(segment, result, status); + // The following line resets the offset so that the StringSegment says the same across + // the function + // call boundary. Since we recurse only once, this line is not strictly necessary. + segment.setOffset(initialOffset); + return; + } + } + + // NOTE: If we get here, the greedy parse completed without consuming the entire string. +} + +void NumberParserImpl::parseLongestRecursive(StringSegment& segment, ParsedNumber& result, + UErrorCode& status) const { + // Base Case + if (segment.length() == 0) { + return; + } + + // TODO: Give a nice way for the matcher to reset the ParsedNumber? + ParsedNumber initial(result); + ParsedNumber candidate; + + int initialOffset = segment.getOffset(); + for (int32_t i = 0; i < fNumMatchers; i++) { + const NumberParseMatcher* matcher = fMatchers[i]; + if (!matcher->smokeTest(segment)) { + continue; + } + + // In a non-greedy parse, we attempt all possible matches and pick the best. + for (int32_t charsToConsume = 0; charsToConsume < segment.length();) { + charsToConsume += U16_LENGTH(segment.codePointAt(charsToConsume)); + + // Run the matcher on a segment of the current length. + candidate = initial; + segment.setLength(charsToConsume); + bool maybeMore = matcher->match(segment, candidate, status); + segment.resetLength(); + if (U_FAILURE(status)) { + return; + } + + // If the entire segment was consumed, recurse. + if (segment.getOffset() - initialOffset == charsToConsume) { + parseLongestRecursive(segment, candidate, status); + if (U_FAILURE(status)) { + return; + } + if (candidate.isBetterThan(result)) { + result = candidate; + } + } + + // Since the segment can be re-used, reset the offset. + // This does not have an effect if the matcher did not consume any chars. + segment.setOffset(initialOffset); + + // Unless the matcher wants to see the next char, continue to the next matcher. + if (!maybeMore) { + break; + } + } + } +} + +UnicodeString NumberParserImpl::toString() const { + UnicodeString result(u"toString()); + } + result.append(u" ]>", -1); + return result; +} + + +#endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/deps/icu-small/source/i18n/numparse_impl.h b/deps/icu-small/source/i18n/numparse_impl.h new file mode 100644 index 00000000000..992114c7ede --- /dev/null +++ b/deps/icu-small/source/i18n/numparse_impl.h @@ -0,0 +1,109 @@ +// © 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 __NUMPARSE_IMPL_H__ +#define __NUMPARSE_IMPL_H__ + +#include "numparse_types.h" +#include "numparse_decimal.h" +#include "numparse_symbols.h" +#include "numparse_scientific.h" +#include "unicode/uniset.h" +#include "numparse_currency.h" +#include "numparse_affixes.h" +#include "number_decimfmtprops.h" +#include "unicode/localpointer.h" +#include "numparse_validators.h" +#include "number_multiplier.h" + +U_NAMESPACE_BEGIN + +// Export an explicit template instantiation of the MaybeStackArray that is used as a data member of NumberParserImpl. +// When building DLLs for Windows this is required even though no direct access to the MaybeStackArray leaks out of the i18n library. +// (See numparse_compositions.h, numparse_affixes.h, datefmt.h, and others for similar examples.) +#if U_PF_WINDOWS <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN +template class U_I18N_API MaybeStackArray; +#endif + +namespace numparse { +namespace impl { + +// Exported as U_I18N_API for tests +class U_I18N_API NumberParserImpl : public MutableMatcherCollection, public UMemory { + public: + virtual ~NumberParserImpl(); + + static NumberParserImpl* createSimpleParser(const Locale& locale, const UnicodeString& patternString, + parse_flags_t parseFlags, UErrorCode& status); + + static NumberParserImpl* createParserFromProperties( + const number::impl::DecimalFormatProperties& properties, const DecimalFormatSymbols& symbols, + bool parseCurrency, UErrorCode& status); + + /** + * Does NOT take ownership of the matcher. The matcher MUST remain valid for the lifespan of the + * NumberParserImpl. + * @param matcher The matcher to reference. + */ + void addMatcher(NumberParseMatcher& matcher) override; + + void freeze(); + + parse_flags_t getParseFlags() const; + + void parse(const UnicodeString& input, bool greedy, ParsedNumber& result, UErrorCode& status) const; + + void parse(const UnicodeString& input, int32_t start, bool greedy, ParsedNumber& result, + UErrorCode& status) const; + + UnicodeString toString() const; + + private: + parse_flags_t fParseFlags; + int32_t fNumMatchers = 0; + // NOTE: The stack capacity for fMatchers and fLeads should be the same + MaybeStackArray fMatchers; + bool fFrozen = false; + + // WARNING: All of these matchers start in an undefined state (default-constructed). + // You must use an assignment operator on them before using. + struct { + IgnorablesMatcher ignorables; + InfinityMatcher infinity; + MinusSignMatcher minusSign; + NanMatcher nan; + PaddingMatcher padding; + PercentMatcher percent; + PermilleMatcher permille; + PlusSignMatcher plusSign; + DecimalMatcher decimal; + ScientificMatcher scientific; + CombinedCurrencyMatcher currency; + AffixMatcherWarehouse affixMatcherWarehouse; + AffixTokenMatcherWarehouse affixTokenMatcherWarehouse; + } fLocalMatchers; + struct { + RequireAffixValidator affix; + RequireCurrencyValidator currency; + RequireDecimalSeparatorValidator decimalSeparator; + RequireNumberValidator number; + MultiplierParseHandler multiplier; + } fLocalValidators; + + explicit NumberParserImpl(parse_flags_t parseFlags); + + void parseGreedyRecursive(StringSegment& segment, ParsedNumber& result, UErrorCode& status) const; + + void parseLongestRecursive(StringSegment& segment, ParsedNumber& result, UErrorCode& status) const; +}; + + +} // namespace impl +} // namespace numparse +U_NAMESPACE_END + +#endif //__NUMPARSE_IMPL_H__ +#endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/deps/icu-small/source/i18n/numparse_parsednumber.cpp b/deps/icu-small/source/i18n/numparse_parsednumber.cpp new file mode 100644 index 00000000000..98da4e83192 --- /dev/null +++ b/deps/icu-small/source/i18n/numparse_parsednumber.cpp @@ -0,0 +1,122 @@ +// © 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 "numparse_types.h" +#include "number_decimalquantity.h" +#include "putilimp.h" +#include + +using namespace icu; +using namespace icu::number; +using namespace icu::number::impl; +using namespace icu::numparse; +using namespace icu::numparse::impl; + + +ParsedNumber::ParsedNumber() { + clear(); +} + +void ParsedNumber::clear() { + quantity.bogus = true; + charEnd = 0; + flags = 0; + prefix.setToBogus(); + suffix.setToBogus(); + currencyCode[0] = 0; +} + +void ParsedNumber::setCharsConsumed(const StringSegment& segment) { + charEnd = segment.getOffset(); +} + +void ParsedNumber::postProcess() { + if (!quantity.bogus && 0 != (flags & FLAG_NEGATIVE)) { + quantity.negate(); + } +} + +bool ParsedNumber::success() const { + return charEnd > 0 && 0 == (flags & FLAG_FAIL); +} + +bool ParsedNumber::seenNumber() const { + return !quantity.bogus || 0 != (flags & FLAG_NAN) || 0 != (flags & FLAG_INFINITY); +} + +double ParsedNumber::getDouble() const { + bool sawNaN = 0 != (flags & FLAG_NAN); + bool sawInfinity = 0 != (flags & FLAG_INFINITY); + + // Check for NaN, infinity, and -0.0 + if (sawNaN) { + // Can't use NAN or std::nan because the byte pattern is platform-dependent; + // MSVC sets the sign bit, but Clang and GCC do not + return uprv_getNaN(); + } + if (sawInfinity) { + if (0 != (flags & FLAG_NEGATIVE)) { + return -INFINITY; + } else { + return INFINITY; + } + } + U_ASSERT(!quantity.bogus); + if (quantity.isZero() && quantity.isNegative()) { + return -0.0; + } + + if (quantity.fitsInLong()) { + return static_cast(quantity.toLong()); + } else { + return quantity.toDouble(); + } +} + +void ParsedNumber::populateFormattable(Formattable& output, parse_flags_t parseFlags) const { + bool sawNaN = 0 != (flags & FLAG_NAN); + bool sawInfinity = 0 != (flags & FLAG_INFINITY); + bool integerOnly = 0 != (parseFlags & PARSE_FLAG_INTEGER_ONLY); + + // Check for NaN, infinity, and -0.0 + if (sawNaN) { + // Can't use NAN or std::nan because the byte pattern is platform-dependent; + // MSVC sets the sign bit, but Clang and GCC do not + output.setDouble(uprv_getNaN()); + return; + } + if (sawInfinity) { + if (0 != (flags & FLAG_NEGATIVE)) { + output.setDouble(-INFINITY); + return; + } else { + output.setDouble(INFINITY); + return; + } + } + U_ASSERT(!quantity.bogus); + if (quantity.isZero() && quantity.isNegative() && !integerOnly) { + output.setDouble(-0.0); + return; + } + + // All other numbers + output.adoptDecimalQuantity(new DecimalQuantity(quantity)); +} + +bool ParsedNumber::isBetterThan(const ParsedNumber& other) { + // Favor results with strictly more characters consumed. + return charEnd > other.charEnd; +} + + + +#endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/deps/icu-small/source/i18n/numparse_scientific.cpp b/deps/icu-small/source/i18n/numparse_scientific.cpp new file mode 100644 index 00000000000..611695e57d4 --- /dev/null +++ b/deps/icu-small/source/i18n/numparse_scientific.cpp @@ -0,0 +1,133 @@ +// © 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 "numparse_types.h" +#include "numparse_scientific.h" +#include "static_unicode_sets.h" + +using namespace icu; +using namespace icu::numparse; +using namespace icu::numparse::impl; + + +namespace { + +inline const UnicodeSet& minusSignSet() { + return *unisets::get(unisets::MINUS_SIGN); +} + +inline const UnicodeSet& plusSignSet() { + return *unisets::get(unisets::PLUS_SIGN); +} + +} // namespace + + +ScientificMatcher::ScientificMatcher(const DecimalFormatSymbols& dfs, const Grouper& grouper) + : fExponentSeparatorString(dfs.getConstSymbol(DecimalFormatSymbols::kExponentialSymbol)), + fExponentMatcher(dfs, grouper, PARSE_FLAG_INTEGER_ONLY | PARSE_FLAG_GROUPING_DISABLED) { + + const UnicodeString& minusSign = dfs.getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol); + if (minusSignSet().contains(minusSign)) { + fCustomMinusSign.setToBogus(); + } else { + fCustomMinusSign = minusSign; + } + + const UnicodeString& plusSign = dfs.getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol); + if (plusSignSet().contains(plusSign)) { + fCustomPlusSign.setToBogus(); + } else { + fCustomPlusSign = plusSign; + } +} + +bool ScientificMatcher::match(StringSegment& segment, ParsedNumber& result, UErrorCode& status) const { + // Only accept scientific notation after the mantissa. + if (!result.seenNumber()) { + 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); + if (overlap1 == fExponentSeparatorString.length()) { + // Full exponent separator match. + + // First attempt to get a code point, returning true if we can't get one. + if (segment.length() == overlap1) { + return true; + } + segment.adjustOffset(overlap1); + + // Allow a sign, and then try to match digits. + int8_t exponentSign = 1; + if (segment.startsWith(minusSignSet())) { + exponentSign = -1; + segment.adjustOffsetByCodePoint(); + } else if (segment.startsWith(plusSignSet())) { + segment.adjustOffsetByCodePoint(); + } else if (segment.startsWith(fCustomMinusSign)) { + // Note: call site is guarded with startsWith, which returns false on empty string + int32_t overlap2 = segment.getCommonPrefixLength(fCustomMinusSign); + if (overlap2 != fCustomMinusSign.length()) { + // Partial custom sign match; un-match the exponent separator. + segment.adjustOffset(-overlap1); + return true; + } + exponentSign = -1; + segment.adjustOffset(overlap2); + } else if (segment.startsWith(fCustomPlusSign)) { + // Note: call site is guarded with startsWith, which returns false on empty string + int32_t overlap2 = segment.getCommonPrefixLength(fCustomPlusSign); + if (overlap2 != fCustomPlusSign.length()) { + // Partial custom sign match; un-match the exponent separator. + segment.adjustOffset(-overlap1); + return true; + } + segment.adjustOffset(overlap2); + } + + // We are supposed to accept E0 after NaN, so we need to make sure result.quantity is available. + bool wasBogus = result.quantity.bogus; + result.quantity.bogus = false; + int digitsOffset = segment.getOffset(); + bool digitsReturnValue = fExponentMatcher.match(segment, result, exponentSign, status); + result.quantity.bogus = wasBogus; + + if (segment.getOffset() != digitsOffset) { + // At least one exponent digit was matched. + result.flags |= FLAG_HAS_EXPONENT; + } else { + // No exponent digits were matched; un-match the exponent separator. + segment.adjustOffset(-overlap1); + } + return digitsReturnValue; + + } else if (overlap1 == segment.length()) { + // Partial exponent separator match + return true; + } + + // No match + return false; +} + +bool ScientificMatcher::smokeTest(const StringSegment& segment) const { + return segment.startsWith(fExponentSeparatorString); +} + +UnicodeString ScientificMatcher::toString() const { + return u""; +} + + +#endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/deps/icu-small/source/i18n/numparse_scientific.h b/deps/icu-small/source/i18n/numparse_scientific.h new file mode 100644 index 00000000000..ddecf858af3 --- /dev/null +++ b/deps/icu-small/source/i18n/numparse_scientific.h @@ -0,0 +1,45 @@ +// © 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 __NUMPARSE_SCIENTIFIC_H__ +#define __NUMPARSE_SCIENTIFIC_H__ + +#include "numparse_types.h" +#include "numparse_decimal.h" +#include "unicode/numberformatter.h" + +using icu::number::impl::Grouper; + +U_NAMESPACE_BEGIN namespace numparse { +namespace impl { + + +class ScientificMatcher : public NumberParseMatcher, public UMemory { + public: + ScientificMatcher() = default; // WARNING: Leaves the object in an unusable state + + ScientificMatcher(const DecimalFormatSymbols& dfs, const Grouper& grouper); + + bool match(StringSegment& segment, ParsedNumber& result, UErrorCode& status) const override; + + bool smokeTest(const StringSegment& segment) const override; + + UnicodeString toString() const override; + + private: + UnicodeString fExponentSeparatorString; + DecimalMatcher fExponentMatcher; + UnicodeString fCustomMinusSign; + UnicodeString fCustomPlusSign; +}; + + +} // namespace impl +} // namespace numparse +U_NAMESPACE_END + +#endif //__NUMPARSE_SCIENTIFIC_H__ +#endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/deps/icu-small/source/i18n/numparse_stringsegment.cpp b/deps/icu-small/source/i18n/numparse_stringsegment.cpp new file mode 100644 index 00000000000..3db4fe618a6 --- /dev/null +++ b/deps/icu-small/source/i18n/numparse_stringsegment.cpp @@ -0,0 +1,146 @@ +// © 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 "numparse_types.h" +#include "numparse_stringsegment.h" +#include "putilimp.h" +#include "unicode/utf16.h" +#include "unicode/uniset.h" + +using namespace icu; +using namespace icu::numparse; +using namespace icu::numparse::impl; + + +StringSegment::StringSegment(const UnicodeString& str, bool ignoreCase) + : fStr(str), fStart(0), fEnd(str.length()), + fFoldCase(ignoreCase) {} + +int32_t StringSegment::getOffset() const { + return fStart; +} + +void StringSegment::setOffset(int32_t start) { + fStart = start; +} + +void StringSegment::adjustOffset(int32_t delta) { + fStart += delta; +} + +void StringSegment::adjustOffsetByCodePoint() { + fStart += U16_LENGTH(getCodePoint()); +} + +void StringSegment::setLength(int32_t length) { + fEnd = fStart + length; +} + +void StringSegment::resetLength() { + fEnd = fStr.length(); +} + +int32_t StringSegment::length() const { + return fEnd - fStart; +} + +char16_t StringSegment::charAt(int32_t index) const { + return fStr.charAt(index + fStart); +} + +UChar32 StringSegment::codePointAt(int32_t index) const { + return fStr.char32At(index + fStart); +} + +UnicodeString StringSegment::toUnicodeString() const { + return UnicodeString(fStr.getBuffer() + fStart, fEnd - fStart); +} + +const UnicodeString StringSegment::toTempUnicodeString() const { + // Use the readonly-aliasing constructor for efficiency. + return UnicodeString(FALSE, fStr.getBuffer() + fStart, fEnd - fStart); +} + +UChar32 StringSegment::getCodePoint() const { + char16_t lead = fStr.charAt(fStart); + if (U16_IS_LEAD(lead) && fStart + 1 < fEnd) { + return fStr.char32At(fStart); + } else if (U16_IS_SURROGATE(lead)) { + return -1; + } else { + return lead; + } +} + +bool StringSegment::startsWith(UChar32 otherCp) const { + return codePointsEqual(getCodePoint(), otherCp, fFoldCase); +} + +bool StringSegment::startsWith(const UnicodeSet& uniset) const { + // TODO: Move UnicodeSet case-folding logic here. + // TODO: Handle string matches here instead of separately. + UChar32 cp = getCodePoint(); + if (cp == -1) { + return false; + } + return uniset.contains(cp); +} + +bool StringSegment::startsWith(const UnicodeString& other) const { + if (other.isBogus() || other.length() == 0 || length() == 0) { + return false; + } + int cp1 = getCodePoint(); + int cp2 = other.char32At(0); + return codePointsEqual(cp1, cp2, fFoldCase); +} + +int32_t StringSegment::getCommonPrefixLength(const UnicodeString& other) { + return getPrefixLengthInternal(other, fFoldCase); +} + +int32_t StringSegment::getCaseSensitivePrefixLength(const UnicodeString& other) { + return getPrefixLengthInternal(other, false); +} + +int32_t StringSegment::getPrefixLengthInternal(const UnicodeString& other, bool foldCase) { + U_ASSERT(other.length() > 0); + int32_t offset = 0; + for (; offset < uprv_min(length(), other.length());) { + // TODO: case-fold code points, not chars + char16_t c1 = charAt(offset); + char16_t c2 = other.charAt(offset); + if (!codePointsEqual(c1, c2, foldCase)) { + break; + } + offset++; + } + return offset; +} + +bool StringSegment::codePointsEqual(UChar32 cp1, UChar32 cp2, bool foldCase) { + if (cp1 == cp2) { + return true; + } + if (!foldCase) { + return false; + } + cp1 = u_foldCase(cp1, TRUE); + cp2 = u_foldCase(cp2, TRUE); + return cp1 == cp2; +} + +bool StringSegment::operator==(const UnicodeString& other) const { + return toTempUnicodeString() == other; +} + + +#endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/deps/icu-small/source/i18n/numparse_stringsegment.h b/deps/icu-small/source/i18n/numparse_stringsegment.h new file mode 100644 index 00000000000..7a84444d414 --- /dev/null +++ b/deps/icu-small/source/i18n/numparse_stringsegment.h @@ -0,0 +1,24 @@ +// © 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 __NUMPARSE_STRINGSEGMENT_H__ +#define __NUMPARSE_STRINGSEGMENT_H__ + +#include "numparse_types.h" +#include "number_types.h" +#include "unicode/unistr.h" + +U_NAMESPACE_BEGIN +namespace numparse { +namespace impl { + + +} // namespace impl +} // namespace numparse +U_NAMESPACE_END + +#endif //__NUMPARSE_STRINGSEGMENT_H__ +#endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/deps/icu-small/source/i18n/numparse_symbols.cpp b/deps/icu-small/source/i18n/numparse_symbols.cpp new file mode 100644 index 00000000000..9ccceec8475 --- /dev/null +++ b/deps/icu-small/source/i18n/numparse_symbols.cpp @@ -0,0 +1,193 @@ +// © 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 "numparse_types.h" +#include "numparse_symbols.h" +#include "numparse_utils.h" + +using namespace icu; +using namespace icu::numparse; +using namespace icu::numparse::impl; + + +SymbolMatcher::SymbolMatcher(const UnicodeString& symbolString, unisets::Key key) { + fUniSet = unisets::get(key); + if (fUniSet->contains(symbolString)) { + fString.setToBogus(); + } else { + fString = symbolString; + } +} + +const UnicodeSet* SymbolMatcher::getSet() const { + return fUniSet; +} + +bool SymbolMatcher::match(StringSegment& segment, ParsedNumber& result, UErrorCode&) const { + // Smoke test first; this matcher might be disabled. + if (isDisabled(result)) { + return false; + } + + // Test the string first in order to consume trailing chars greedily. + int overlap = 0; + if (!fString.isEmpty()) { + overlap = segment.getCommonPrefixLength(fString); + if (overlap == fString.length()) { + segment.adjustOffset(fString.length()); + accept(segment, result); + return false; + } + } + + int cp = segment.getCodePoint(); + if (cp != -1 && fUniSet->contains(cp)) { + segment.adjustOffset(U16_LENGTH(cp)); + accept(segment, result); + return false; + } + + return overlap == segment.length(); +} + +bool SymbolMatcher::smokeTest(const StringSegment& segment) const { + return segment.startsWith(*fUniSet) || segment.startsWith(fString); +} + +UnicodeString SymbolMatcher::toString() const { + // TODO: Customize output for each symbol + return u""; +} + + +IgnorablesMatcher::IgnorablesMatcher(unisets::Key key) + : SymbolMatcher({}, key) { +} + +bool IgnorablesMatcher::isFlexible() const { + return true; +} + +UnicodeString IgnorablesMatcher::toString() const { + return u""; +} + +bool IgnorablesMatcher::isDisabled(const ParsedNumber&) const { + return false; +} + +void IgnorablesMatcher::accept(StringSegment&, ParsedNumber&) const { + // No-op +} + + +InfinityMatcher::InfinityMatcher(const DecimalFormatSymbols& dfs) + : SymbolMatcher(dfs.getConstSymbol(DecimalFormatSymbols::kInfinitySymbol), unisets::INFINITY_KEY) { +} + +bool InfinityMatcher::isDisabled(const ParsedNumber& result) const { + return 0 != (result.flags & FLAG_INFINITY); +} + +void InfinityMatcher::accept(StringSegment& segment, ParsedNumber& result) const { + result.flags |= FLAG_INFINITY; + result.setCharsConsumed(segment); +} + + +MinusSignMatcher::MinusSignMatcher(const DecimalFormatSymbols& dfs, bool allowTrailing) + : SymbolMatcher(dfs.getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol), unisets::MINUS_SIGN), + fAllowTrailing(allowTrailing) { +} + +bool MinusSignMatcher::isDisabled(const ParsedNumber& result) const { + return !fAllowTrailing && result.seenNumber(); +} + +void MinusSignMatcher::accept(StringSegment& segment, ParsedNumber& result) const { + result.flags |= FLAG_NEGATIVE; + result.setCharsConsumed(segment); +} + + +NanMatcher::NanMatcher(const DecimalFormatSymbols& dfs) + : SymbolMatcher(dfs.getConstSymbol(DecimalFormatSymbols::kNaNSymbol), unisets::EMPTY) { +} + +bool NanMatcher::isDisabled(const ParsedNumber& result) const { + return result.seenNumber(); +} + +void NanMatcher::accept(StringSegment& segment, ParsedNumber& result) const { + result.flags |= FLAG_NAN; + result.setCharsConsumed(segment); +} + + +PaddingMatcher::PaddingMatcher(const UnicodeString& padString) + : SymbolMatcher(padString, unisets::EMPTY) {} + +bool PaddingMatcher::isFlexible() const { + return true; +} + +bool PaddingMatcher::isDisabled(const ParsedNumber&) const { + return false; +} + +void PaddingMatcher::accept(StringSegment&, ParsedNumber&) const { + // No-op +} + + +PercentMatcher::PercentMatcher(const DecimalFormatSymbols& dfs) + : SymbolMatcher(dfs.getConstSymbol(DecimalFormatSymbols::kPercentSymbol), unisets::PERCENT_SIGN) { +} + +bool PercentMatcher::isDisabled(const ParsedNumber& result) const { + return 0 != (result.flags & FLAG_PERCENT); +} + +void PercentMatcher::accept(StringSegment& segment, ParsedNumber& result) const { + result.flags |= FLAG_PERCENT; + result.setCharsConsumed(segment); +} + + +PermilleMatcher::PermilleMatcher(const DecimalFormatSymbols& dfs) + : SymbolMatcher(dfs.getConstSymbol(DecimalFormatSymbols::kPerMillSymbol), unisets::PERMILLE_SIGN) { +} + +bool PermilleMatcher::isDisabled(const ParsedNumber& result) const { + return 0 != (result.flags & FLAG_PERMILLE); +} + +void PermilleMatcher::accept(StringSegment& segment, ParsedNumber& result) const { + result.flags |= FLAG_PERMILLE; + result.setCharsConsumed(segment); +} + + +PlusSignMatcher::PlusSignMatcher(const DecimalFormatSymbols& dfs, bool allowTrailing) + : SymbolMatcher(dfs.getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol), unisets::PLUS_SIGN), + fAllowTrailing(allowTrailing) { +} + +bool PlusSignMatcher::isDisabled(const ParsedNumber& result) const { + return !fAllowTrailing && result.seenNumber(); +} + +void PlusSignMatcher::accept(StringSegment& segment, ParsedNumber& result) const { + result.setCharsConsumed(segment); +} + + +#endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/deps/icu-small/source/i18n/numparse_symbols.h b/deps/icu-small/source/i18n/numparse_symbols.h new file mode 100644 index 00000000000..8912ee95b0d --- /dev/null +++ b/deps/icu-small/source/i18n/numparse_symbols.h @@ -0,0 +1,173 @@ +// © 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 __NUMPARSE_SYMBOLS_H__ +#define __NUMPARSE_SYMBOLS_H__ + +#include "numparse_types.h" +#include "unicode/uniset.h" +#include "static_unicode_sets.h" + +U_NAMESPACE_BEGIN namespace numparse { +namespace impl { + + +/** + * A base class for many matchers that performs a simple match against a UnicodeString and/or UnicodeSet. + * + * @author sffc + */ +// Exported as U_I18N_API for tests +class U_I18N_API SymbolMatcher : public NumberParseMatcher, public UMemory { + public: + SymbolMatcher() = default; // WARNING: Leaves the object in an unusable state + + const UnicodeSet* getSet() const; + + bool match(StringSegment& segment, ParsedNumber& result, UErrorCode& status) const override; + + bool smokeTest(const StringSegment& segment) const override; + + UnicodeString toString() const override; + + virtual bool isDisabled(const ParsedNumber& result) const = 0; + + virtual void accept(StringSegment& segment, ParsedNumber& result) const = 0; + + protected: + UnicodeString fString; + const UnicodeSet* fUniSet; // a reference from numparse_unisets.h; never owned + + SymbolMatcher(const UnicodeString& symbolString, unisets::Key key); +}; + + +// Exported as U_I18N_API for tests +class U_I18N_API IgnorablesMatcher : public SymbolMatcher { + public: + IgnorablesMatcher() = default; // WARNING: Leaves the object in an unusable state + + IgnorablesMatcher(unisets::Key key); + + bool isFlexible() const override; + + UnicodeString toString() const override; + + protected: + bool isDisabled(const ParsedNumber& result) const override; + + void accept(StringSegment& segment, ParsedNumber& result) const override; +}; + + +class InfinityMatcher : public SymbolMatcher { + public: + InfinityMatcher() = default; // WARNING: Leaves the object in an unusable state + + InfinityMatcher(const DecimalFormatSymbols& dfs); + + protected: + bool isDisabled(const ParsedNumber& result) const override; + + void accept(StringSegment& segment, ParsedNumber& result) const override; +}; + + +// Exported as U_I18N_API for tests +class U_I18N_API MinusSignMatcher : public SymbolMatcher { + public: + MinusSignMatcher() = default; // WARNING: Leaves the object in an unusable state + + MinusSignMatcher(const DecimalFormatSymbols& dfs, bool allowTrailing); + + protected: + bool isDisabled(const ParsedNumber& result) const override; + + void accept(StringSegment& segment, ParsedNumber& result) const override; + + private: + bool fAllowTrailing; +}; + + +class NanMatcher : public SymbolMatcher { + public: + NanMatcher() = default; // WARNING: Leaves the object in an unusable state + + NanMatcher(const DecimalFormatSymbols& dfs); + + protected: + bool isDisabled(const ParsedNumber& result) const override; + + void accept(StringSegment& segment, ParsedNumber& result) const override; +}; + + +class PaddingMatcher : public SymbolMatcher { + public: + PaddingMatcher() = default; // WARNING: Leaves the object in an unusable state + + PaddingMatcher(const UnicodeString& padString); + + bool isFlexible() const override; + + protected: + bool isDisabled(const ParsedNumber& result) const override; + + void accept(StringSegment& segment, ParsedNumber& result) const override; +}; + + +// Exported as U_I18N_API for tests +class U_I18N_API PercentMatcher : public SymbolMatcher { + public: + PercentMatcher() = default; // WARNING: Leaves the object in an unusable state + + PercentMatcher(const DecimalFormatSymbols& dfs); + + protected: + bool isDisabled(const ParsedNumber& result) const override; + + void accept(StringSegment& segment, ParsedNumber& result) const override; +}; + +// Exported as U_I18N_API for tests +class U_I18N_API PermilleMatcher : public SymbolMatcher { + public: + PermilleMatcher() = default; // WARNING: Leaves the object in an unusable state + + PermilleMatcher(const DecimalFormatSymbols& dfs); + + protected: + bool isDisabled(const ParsedNumber& result) const override; + + void accept(StringSegment& segment, ParsedNumber& result) const override; +}; + + +// Exported as U_I18N_API for tests +class U_I18N_API PlusSignMatcher : public SymbolMatcher { + public: + PlusSignMatcher() = default; // WARNING: Leaves the object in an unusable state + + PlusSignMatcher(const DecimalFormatSymbols& dfs, bool allowTrailing); + + protected: + bool isDisabled(const ParsedNumber& result) const override; + + void accept(StringSegment& segment, ParsedNumber& result) const override; + + private: + bool fAllowTrailing; +}; + + +} // namespace impl +} // namespace numparse +U_NAMESPACE_END + +#endif //__NUMPARSE_SYMBOLS_H__ +#endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/deps/icu-small/source/i18n/numparse_types.h b/deps/icu-small/source/i18n/numparse_types.h new file mode 100644 index 00000000000..ab591eaba83 --- /dev/null +++ b/deps/icu-small/source/i18n/numparse_types.h @@ -0,0 +1,377 @@ +// © 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 __NUMPARSE_TYPES_H__ +#define __NUMPARSE_TYPES_H__ + +#include "unicode/uobject.h" +#include "number_decimalquantity.h" + +U_NAMESPACE_BEGIN namespace numparse { +namespace impl { + +// Forward-declarations +class StringSegment; +class ParsedNumber; + +typedef int32_t result_flags_t; +typedef int32_t parse_flags_t; + +/** Flags for the type result_flags_t */ +enum ResultFlags { + FLAG_NEGATIVE = 0x0001, + FLAG_PERCENT = 0x0002, + FLAG_PERMILLE = 0x0004, + FLAG_HAS_EXPONENT = 0x0008, + // FLAG_HAS_DEFAULT_CURRENCY = 0x0010, // no longer used + FLAG_HAS_DECIMAL_SEPARATOR = 0x0020, + FLAG_NAN = 0x0040, + FLAG_INFINITY = 0x0080, + FLAG_FAIL = 0x0100, +}; + +/** Flags for the type parse_flags_t */ +enum ParseFlags { + PARSE_FLAG_IGNORE_CASE = 0x0001, + PARSE_FLAG_MONETARY_SEPARATORS = 0x0002, + PARSE_FLAG_STRICT_SEPARATORS = 0x0004, + PARSE_FLAG_STRICT_GROUPING_SIZE = 0x0008, + PARSE_FLAG_INTEGER_ONLY = 0x0010, + PARSE_FLAG_GROUPING_DISABLED = 0x0020, + // PARSE_FLAG_FRACTION_GROUPING_ENABLED = 0x0040, // see #10794 + PARSE_FLAG_INCLUDE_UNPAIRED_AFFIXES = 0x0080, + PARSE_FLAG_USE_FULL_AFFIXES = 0x0100, + PARSE_FLAG_EXACT_AFFIX = 0x0200, + PARSE_FLAG_PLUS_SIGN_ALLOWED = 0x0400, + // PARSE_FLAG_OPTIMIZE = 0x0800, // no longer used + // PARSE_FLAG_FORCE_BIG_DECIMAL = 0x1000, // not used in ICU4C + PARSE_FLAG_NO_FOREIGN_CURRENCY = 0x2000, +}; + + +// TODO: Is this class worthwhile? +template +class CompactUnicodeString { + public: + CompactUnicodeString() { + static_assert(stackCapacity > 0, "cannot have zero space on stack"); + fBuffer[0] = 0; + } + + CompactUnicodeString(const UnicodeString& text) + : fBuffer(text.length() + 1) { + memcpy(fBuffer.getAlias(), text.getBuffer(), sizeof(UChar) * text.length()); + fBuffer[text.length()] = 0; + } + + inline UnicodeString toAliasedUnicodeString() const { + return UnicodeString(TRUE, fBuffer.getAlias(), -1); + } + + bool operator==(const CompactUnicodeString& other) const { + // Use the alias-only constructor and then call UnicodeString operator== + return toAliasedUnicodeString() == other.toAliasedUnicodeString(); + } + + private: + MaybeStackArray fBuffer; +}; + + +/** + * Struct-like class to hold the results of a parsing routine. + * + * @author sffc + */ +// Exported as U_I18N_API for tests +class U_I18N_API ParsedNumber { + public: + + /** + * The numerical value that was parsed. + */ + ::icu::number::impl::DecimalQuantity quantity; + + /** + * The index of the last char consumed during parsing. If parsing started at index 0, this is equal + * to the number of chars consumed. This is NOT necessarily the same as the StringSegment offset; + * "weak" chars, like whitespace, change the offset, but the charsConsumed is not touched until a + * "strong" char is encountered. + */ + int32_t charEnd; + + /** + * Boolean flags (see constants above). + */ + result_flags_t flags; + + /** + * The pattern string corresponding to the prefix that got consumed. + */ + UnicodeString prefix; + + /** + * The pattern string corresponding to the suffix that got consumed. + */ + UnicodeString suffix; + + /** + * The currency that got consumed. + */ + UChar currencyCode[4]; + + ParsedNumber(); + + ParsedNumber(const ParsedNumber& other) = default; + + ParsedNumber& operator=(const ParsedNumber& other) = default; + + void clear(); + + /** + * Call this method to register that a "strong" char was consumed. This should be done after calling + * {@link StringSegment#setOffset} or {@link StringSegment#adjustOffset} except when the char is + * "weak", like whitespace. + * + *

+ * What is a strong versus weak char? The behavior of number parsing is to "stop" + * after reading the number, even if there is other content following the number. For example, after + * parsing the string "123 " (123 followed by a space), the cursor should be set to 3, not 4, even + * though there are matchers that accept whitespace. In this example, the digits are strong, whereas + * the whitespace is weak. Grouping separators are weak, whereas decimal separators are strong. Most + * other chars are strong. + * + * @param segment + * The current StringSegment, usually immediately following a call to setOffset. + */ + void setCharsConsumed(const StringSegment& segment); + + /** Apply certain number-related flags to the DecimalQuantity. */ + void postProcess(); + + /** + * Returns whether this the parse was successful. To be successful, at least one char must have been + * consumed, and the failure flag must not be set. + */ + bool success() const; + + bool seenNumber() const; + + double getDouble() const; + + void populateFormattable(Formattable& output, parse_flags_t parseFlags) const; + + bool isBetterThan(const ParsedNumber& other); +}; + + +/** + * A mutable class allowing for a String with a variable offset and length. The charAt, length, and + * subSequence methods all operate relative to the fixed offset into the String. + * + * @author sffc + */ +// Exported as U_I18N_API for tests +class U_I18N_API StringSegment : public UMemory { + public: + StringSegment(const UnicodeString& str, bool ignoreCase); + + int32_t getOffset() const; + + void setOffset(int32_t start); + + /** + * Equivalent to setOffset(getOffset()+delta). + * + *

+ * This method is usually called by a Matcher to register that a char was consumed. If the char is + * strong (it usually is, except for things like whitespace), follow this with a call to + * {@link ParsedNumber#setCharsConsumed}. For more information on strong chars, see that method. + */ + void adjustOffset(int32_t delta); + + /** + * Adjusts the offset by the width of the current code point, either 1 or 2 chars. + */ + void adjustOffsetByCodePoint(); + + void setLength(int32_t length); + + void resetLength(); + + int32_t length() const; + + char16_t charAt(int32_t index) const; + + UChar32 codePointAt(int32_t index) const; + + UnicodeString toUnicodeString() const; + + const UnicodeString toTempUnicodeString() const; + + /** + * Returns the first code point in the string segment, or -1 if the string starts with an invalid + * code point. + * + *

+ * Important: Most of the time, you should use {@link #matches}, which handles case + * folding logic, instead of this method. + */ + UChar32 getCodePoint() const; + + /** + * Returns true if the first code point of this StringSegment equals the given code point. + * + *

+ * This method will perform case folding if case folding is enabled for the parser. + */ + bool startsWith(UChar32 otherCp) const; + + /** + * Returns true if the first code point of this StringSegment is in the given UnicodeSet. + */ + bool startsWith(const UnicodeSet& uniset) const; + + /** + * Returns true if there is at least one code point of overlap between this StringSegment and the + * given UnicodeString. + */ + bool startsWith(const UnicodeString& other) const; + + /** + * Returns the length of the prefix shared by this StringSegment and the given CharSequence. For + * example, if this string segment is "aab", and the char sequence is "aac", this method returns 2, + * since the first 2 characters are the same. + * + *

+ * This method only returns offsets along code point boundaries. + * + *

+ * This method will perform case folding if case folding was enabled in the constructor. + * + *

+ * IMPORTANT: The given UnicodeString must not be empty! It is the caller's responsibility to check. + */ + int32_t getCommonPrefixLength(const UnicodeString& other); + + /** + * Like {@link #getCommonPrefixLength}, but never performs case folding, even if case folding is + * enabled for the parser. + */ + int32_t getCaseSensitivePrefixLength(const UnicodeString& other); + + bool operator==(const UnicodeString& other) const; + + private: + const UnicodeString fStr; + int32_t fStart; + int32_t fEnd; + bool fFoldCase; + + int32_t getPrefixLengthInternal(const UnicodeString& other, bool foldCase); + + static bool codePointsEqual(UChar32 cp1, UChar32 cp2, bool foldCase); +}; + + +/** + * The core interface implemented by all matchers used for number parsing. + * + * Given a string, there should NOT be more than one way to consume the string with the same matcher + * applied multiple times. If there is, the non-greedy parsing algorithm will be unhappy and may enter an + * exponential-time loop. For example, consider the "A Matcher" that accepts "any number of As". Given + * the string "AAAA", there are 2^N = 8 ways to apply the A Matcher to this string: you could have the A + * Matcher apply 4 times to each character; you could have it apply just once to all the characters; you + * could have it apply to the first 2 characters and the second 2 characters; and so on. A better version + * of the "A Matcher" would be for it to accept exactly one A, and allow the algorithm to run it + * repeatedly to consume a string of multiple As. The A Matcher can implement the Flexible interface + * below to signal that it can be applied multiple times in a row. + * + * @author sffc + */ +// Exported as U_I18N_API for tests +class U_I18N_API NumberParseMatcher { + public: + virtual ~NumberParseMatcher(); + + /** + * Matchers can override this method to return true to indicate that they are optional and can be run + * repeatedly. Used by SeriesMatcher, primarily in the context of IgnorablesMatcher. + */ + virtual bool isFlexible() const { + return false; + } + + /** + * Runs this matcher starting at the beginning of the given StringSegment. If this matcher finds + * something interesting in the StringSegment, it should update the offset of the StringSegment + * corresponding to how many chars were matched. + * + * This method is thread-safe. + * + * @param segment + * The StringSegment to match against. Matches always start at the beginning of the + * segment. The segment is guaranteed to contain at least one char. + * @param result + * The data structure to store results if the match succeeds. + * @return Whether this matcher thinks there may be more interesting chars beyond the end of the + * string segment. + */ + virtual bool match(StringSegment& segment, ParsedNumber& result, UErrorCode& status) const = 0; + + /** + * Performs a fast "smoke check" for whether or not this matcher could possibly match against the + * given string segment. The test should be as fast as possible but also as restrictive as possible. + * For example, matchers can maintain a UnicodeSet of all code points that count possibly start a + * match. Matchers should use the {@link StringSegment#startsWith} method in order to correctly + * handle case folding. + * + * @param segment + * The segment to check against. + * @return true if the matcher might be able to match against this segment; false if it definitely + * will not be able to match. + */ + virtual bool smokeTest(const StringSegment& segment) const = 0; + + /** + * Method called at the end of a parse, after all matchers have failed to consume any more chars. + * Allows a matcher to make final modifications to the result given the knowledge that no more + * matches are possible. + * + * @param result + * The data structure to store results. + */ + virtual void postProcess(ParsedNumber&) const { + // Default implementation: no-op + }; + + // String for debugging + virtual UnicodeString toString() const = 0; + + protected: + // No construction except by subclasses! + NumberParseMatcher() = default; +}; + + +/** + * Interface for use in arguments. + */ +// Exported as U_I18N_API for tests +class U_I18N_API MutableMatcherCollection { + public: + virtual ~MutableMatcherCollection() = default; + + virtual void addMatcher(NumberParseMatcher& matcher) = 0; +}; + + +} // namespace impl +} // namespace numparse +U_NAMESPACE_END + +#endif //__NUMPARSE_TYPES_H__ +#endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/deps/icu-small/source/i18n/numparse_utils.h b/deps/icu-small/source/i18n/numparse_utils.h new file mode 100644 index 00000000000..162954bae09 --- /dev/null +++ b/deps/icu-small/source/i18n/numparse_utils.h @@ -0,0 +1,43 @@ +// © 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 __NUMPARSE_UTILS_H__ +#define __NUMPARSE_UTILS_H__ + +#include "numparse_types.h" +#include "unicode/uniset.h" + +U_NAMESPACE_BEGIN namespace numparse { +namespace impl { +namespace utils { + + +inline static void putLeadCodePoints(const UnicodeSet* input, UnicodeSet* output) { + for (int32_t i = 0; i < input->getRangeCount(); i++) { + output->add(input->getRangeStart(i), input->getRangeEnd(i)); + } + // TODO: ANDY: How to iterate over the strings in ICU4C UnicodeSet? +} + +inline static void putLeadCodePoint(const UnicodeString& input, UnicodeSet* output) { + if (!input.isEmpty()) { + output->add(input.char32At(0)); + } +} + +inline static void copyCurrencyCode(UChar* dest, const UChar* src) { + uprv_memcpy(dest, src, sizeof(UChar) * 3); + dest[3] = 0; +} + + +} // namespace utils +} // namespace impl +} // namespace numparse +U_NAMESPACE_END + +#endif //__NUMPARSE_UTILS_H__ +#endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/deps/icu-small/source/i18n/numparse_validators.cpp b/deps/icu-small/source/i18n/numparse_validators.cpp new file mode 100644 index 00000000000..12d3465c4ef --- /dev/null +++ b/deps/icu-small/source/i18n/numparse_validators.cpp @@ -0,0 +1,85 @@ +// © 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 "numparse_types.h" +#include "numparse_validators.h" +#include "static_unicode_sets.h" + +using namespace icu; +using namespace icu::numparse; +using namespace icu::numparse::impl; + + +void RequireAffixValidator::postProcess(ParsedNumber& result) const { + if (result.prefix.isBogus() || result.suffix.isBogus()) { + // We saw a prefix or a suffix but not both. Fail the parse. + result.flags |= FLAG_FAIL; + } +} + +UnicodeString RequireAffixValidator::toString() const { + return u""; +} + + +void RequireCurrencyValidator::postProcess(ParsedNumber& result) const { + if (result.currencyCode[0] == 0) { + result.flags |= FLAG_FAIL; + } +} + +UnicodeString RequireCurrencyValidator::toString() const { + return u""; +} + + +RequireDecimalSeparatorValidator::RequireDecimalSeparatorValidator(bool patternHasDecimalSeparator) + : fPatternHasDecimalSeparator(patternHasDecimalSeparator) { +} + +void RequireDecimalSeparatorValidator::postProcess(ParsedNumber& result) const { + bool parseHasDecimalSeparator = 0 != (result.flags & FLAG_HAS_DECIMAL_SEPARATOR); + if (parseHasDecimalSeparator != fPatternHasDecimalSeparator) { + result.flags |= FLAG_FAIL; + } +} + +UnicodeString RequireDecimalSeparatorValidator::toString() const { + return u""; +} + + +void RequireNumberValidator::postProcess(ParsedNumber& result) const { + // Require that a number is matched. + if (!result.seenNumber()) { + result.flags |= FLAG_FAIL; + } +} + +UnicodeString RequireNumberValidator::toString() const { + return u""; +} + +MultiplierParseHandler::MultiplierParseHandler(::icu::number::Scale multiplier) + : fMultiplier(std::move(multiplier)) {} + +void MultiplierParseHandler::postProcess(ParsedNumber& result) const { + if (!result.quantity.bogus) { + fMultiplier.applyReciprocalTo(result.quantity); + // NOTE: It is okay if the multiplier was negative. + } +} + +UnicodeString MultiplierParseHandler::toString() const { + return u""; +} + +#endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/deps/icu-small/source/i18n/numparse_validators.h b/deps/icu-small/source/i18n/numparse_validators.h new file mode 100644 index 00000000000..5d43b779d0b --- /dev/null +++ b/deps/icu-small/source/i18n/numparse_validators.h @@ -0,0 +1,95 @@ +// © 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_NUMPARSE_VALIDATORS_H__ +#define __SOURCE_NUMPARSE_VALIDATORS_H__ + +#include "numparse_types.h" +#include "static_unicode_sets.h" + +U_NAMESPACE_BEGIN namespace numparse { +namespace impl { + + +class ValidationMatcher : public NumberParseMatcher { + public: + bool match(StringSegment&, ParsedNumber&, UErrorCode&) const U_OVERRIDE { + // No-op + return false; + } + + bool smokeTest(const StringSegment&) const U_OVERRIDE { + // No-op + return false; + } + + void postProcess(ParsedNumber& result) const U_OVERRIDE = 0; +}; + + +class RequireAffixValidator : public ValidationMatcher, public UMemory { + public: + void postProcess(ParsedNumber& result) const U_OVERRIDE; + + UnicodeString toString() const U_OVERRIDE; +}; + + +class RequireCurrencyValidator : public ValidationMatcher, public UMemory { + public: + void postProcess(ParsedNumber& result) const U_OVERRIDE; + + UnicodeString toString() const U_OVERRIDE; +}; + + +class RequireDecimalSeparatorValidator : public ValidationMatcher, public UMemory { + public: + RequireDecimalSeparatorValidator() = default; // leaves instance in valid but undefined state + + RequireDecimalSeparatorValidator(bool patternHasDecimalSeparator); + + void postProcess(ParsedNumber& result) const U_OVERRIDE; + + UnicodeString toString() const U_OVERRIDE; + + private: + bool fPatternHasDecimalSeparator; +}; + + +class RequireNumberValidator : public ValidationMatcher, public UMemory { + public: + void postProcess(ParsedNumber& result) const U_OVERRIDE; + + UnicodeString toString() const U_OVERRIDE; +}; + + +/** + * Wraps a {@link Multiplier} for use in the number parsing pipeline. + */ +class MultiplierParseHandler : public ValidationMatcher, public UMemory { + public: + MultiplierParseHandler() = default; // leaves instance in valid but undefined state + + MultiplierParseHandler(::icu::number::Scale multiplier); + + void postProcess(ParsedNumber& result) const U_OVERRIDE; + + UnicodeString toString() const U_OVERRIDE; + + private: + ::icu::number::Scale fMultiplier; +}; + + +} // namespace impl +} // namespace numparse +U_NAMESPACE_END + +#endif //__SOURCE_NUMPARSE_VALIDATORS_H__ +#endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/deps/icu-small/source/i18n/pluralaffix.cpp b/deps/icu-small/source/i18n/pluralaffix.cpp deleted file mode 100644 index ea400206b38..00000000000 --- a/deps/icu-small/source/i18n/pluralaffix.cpp +++ /dev/null @@ -1,104 +0,0 @@ -// © 2016 and later: Unicode, Inc. and others. -// License & terms of use: http://www.unicode.org/copyright.html -/* - * Copyright (C) 2015, International Business Machines - * Corporation and others. All Rights Reserved. - * - * file name: pluralaffix.cpp - */ - -#include "unicode/utypes.h" - -#if !UCONFIG_NO_FORMATTING - -#include "cstring.h" -#include "digitaffix.h" -#include "pluralaffix.h" - -U_NAMESPACE_BEGIN - -UBool -PluralAffix::setVariant( - const char *variant, const UnicodeString &value, UErrorCode &status) { - DigitAffix *current = affixes.getMutable(variant, status); - if (U_FAILURE(status)) { - return FALSE; - } - current->remove(); - current->append(value); - return TRUE; -} - -void -PluralAffix::remove() { - affixes.clear(); -} - -void -PluralAffix::appendUChar( - const UChar value, int32_t fieldId) { - PluralMapBase::Category index = PluralMapBase::NONE; - for (DigitAffix *current = affixes.nextMutable(index); - current != NULL; current = affixes.nextMutable(index)) { - current->appendUChar(value, fieldId); - } -} - -void -PluralAffix::append( - const UnicodeString &value, int32_t fieldId) { - PluralMapBase::Category index = PluralMapBase::NONE; - for (DigitAffix *current = affixes.nextMutable(index); - current != NULL; current = affixes.nextMutable(index)) { - current->append(value, fieldId); - } -} - -void -PluralAffix::append( - const UChar *value, int32_t charCount, int32_t fieldId) { - PluralMapBase::Category index = PluralMapBase::NONE; - for (DigitAffix *current = affixes.nextMutable(index); - current != NULL; current = affixes.nextMutable(index)) { - current->append(value, charCount, fieldId); - } -} - -UBool -PluralAffix::append( - const PluralAffix &rhs, int32_t fieldId, UErrorCode &status) { - if (U_FAILURE(status)) { - return FALSE; - } - PluralMapBase::Category index = PluralMapBase::NONE; - while(rhs.affixes.next(index) != NULL) { - affixes.getMutableWithDefault(index, affixes.getOther(), status); - } - index = PluralMapBase::NONE; - for (DigitAffix *current = affixes.nextMutable(index); - current != NULL; current = affixes.nextMutable(index)) { - current->append(rhs.affixes.get(index).toString(), fieldId); - } - return TRUE; -} - -const DigitAffix & -PluralAffix::getByCategory(const char *category) const { - return affixes.get(category); -} - -const DigitAffix & -PluralAffix::getByCategory(const UnicodeString &category) const { - return affixes.get(category); -} - -UBool -PluralAffix::hasMultipleVariants() const { - // This works because OTHER is guaranteed to be the first enum value - PluralMapBase::Category index = PluralMapBase::OTHER; - return (affixes.next(index) != NULL); -} - -U_NAMESPACE_END - -#endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/deps/icu-small/source/i18n/pluralaffix.h b/deps/icu-small/source/i18n/pluralaffix.h deleted file mode 100644 index 94366ce4cf8..00000000000 --- a/deps/icu-small/source/i18n/pluralaffix.h +++ /dev/null @@ -1,177 +0,0 @@ -// © 2016 and later: Unicode, Inc. and others. -// License & terms of use: http://www.unicode.org/copyright.html -/* -******************************************************************************* -* Copyright (C) 2015, International Business Machines -* Corporation and others. All Rights Reserved. -******************************************************************************* -* pluralaffix.h -* -* created on: 2015jan06 -* created by: Travis Keep -*/ - -#ifndef __PLURALAFFIX_H__ -#define __PLURALAFFIX_H__ - -#include "unicode/utypes.h" - -#if !UCONFIG_NO_FORMATTING - -#include "unicode/unum.h" -#include "unicode/uobject.h" - -#include "digitaffix.h" -#include "pluralmap.h" - -U_NAMESPACE_BEGIN - -class FieldPositionHandler; - -// Export an explicit template instantiation. -// -// MSVC requires this, even though it should not be necessary. -// No direct access leaks out of the i18n library. -// -// Macintosh produces duplicate definition linker errors with the explicit template -// instantiation. -// -#if !U_PLATFORM_IS_DARWIN_BASED -template class U_I18N_API PluralMap; -#endif - - -/** - * A plural aware prefix or suffix of a formatted number. - * - * PluralAffix is essentially a map of DigitAffix objects keyed by plural - * category. The 'other' category is the default and always has some - * value. The rest of the categories are optional. Querying for a category that - * is not set always returns the DigitAffix stored in the 'other' category. - * - * To use one of these objects, build it up first using append() and - * setVariant() methods. Once built, leave unchanged and let multiple threads - * safely access. - * - * The following code is sample code for building up: - * one: US Dollar - - * other: US Dollars - - * - * and storing it in "negativeCurrencyPrefix" - * - * UErrorCode status = U_ZERO_ERROR; - * - * PluralAffix negativeCurrencyPrefix; - * - * PluralAffix currencyName; - * currencyName.setVariant("one", "US Dollar", status); - * currencyName.setVariant("other", "US Dollars", status); - * - * negativeCurrencyPrefix.append(currencyName, UNUM_CURRENCY_FIELD, status); - * negativeCurrencyPrefix.append(" "); - * negativeCurrencyPrefix.append("-", UNUM_SIGN_FIELD, status); - */ -class U_I18N_API PluralAffix : public UMemory { -public: - - /** - * Create empty PluralAffix. - */ - PluralAffix() : affixes() { } - - /** - * Create a PluralAffix where the 'other' variant is otherVariant. - */ - PluralAffix(const DigitAffix &otherVariant) : affixes(otherVariant) { } - - /** - * Sets a particular variant for a plural category while overwriting - * anything that may have been previously stored for that plural - * category. The set value has no field annotations. - * @param category "one", "two", "few", ... - * @param variant the variant to store under the particular category - * @param status Any error returned here. - */ - UBool setVariant( - const char *category, - const UnicodeString &variant, - UErrorCode &status); - /** - * Make the 'other' variant be the empty string with no field annotations - * and remove the variants for the rest of the plural categories. - */ - void remove(); - - /** - * Append value to all set plural categories. If fieldId present, value - * is that field type. - */ - void appendUChar(UChar value, int32_t fieldId=UNUM_FIELD_COUNT); - - /** - * Append value to all set plural categories. If fieldId present, value - * is that field type. - */ - void append(const UnicodeString &value, int32_t fieldId=UNUM_FIELD_COUNT); - - /** - * Append value to all set plural categories. If fieldId present, value - * is that field type. - */ - void append(const UChar *value, int32_t charCount, int32_t fieldId=UNUM_FIELD_COUNT); - - /** - * Append the value for each plural category in rhs to the corresponding - * plural category in this instance. Each value appended from rhs is - * of type fieldId. - */ - UBool append( - const PluralAffix &rhs, - int32_t fieldId, - UErrorCode &status); - /** - * Get the DigitAffix for a paricular category such as "zero", "one", ... - * If the particular category is not set, returns the 'other' category - * which is always set. - */ - const DigitAffix &getByCategory(const char *category) const; - - /** - * Get the DigitAffix for a paricular category such as "zero", "one", ... - * If the particular category is not set, returns the 'other' category - * which is always set. - */ - const DigitAffix &getByCategory(const UnicodeString &category) const; - - /** - * Get the DigitAffix for the other category which is always set. - */ - const DigitAffix &getOtherVariant() const { - return affixes.getOther(); - } - - /** - * Returns TRUE if this instance has variants stored besides the "other" - * variant. - */ - UBool hasMultipleVariants() const; - - /** - * Returns TRUE if this instance equals rhs. - */ - UBool equals(const PluralAffix &rhs) const { - return affixes.equals(rhs.affixes, &eq); - } - -private: - PluralMap affixes; - - static UBool eq(const DigitAffix &x, const DigitAffix &y) { - return x.equals(y); - } -}; - - -U_NAMESPACE_END -#endif /* #if !UCONFIG_NO_FORMATTING */ -#endif // __PLURALAFFIX_H__ diff --git a/deps/icu-small/source/i18n/plurfmt.cpp b/deps/icu-small/source/i18n/plurfmt.cpp index e14ef6d831e..2775766d32d 100644 --- a/deps/icu-small/source/i18n/plurfmt.cpp +++ b/deps/icu-small/source/i18n/plurfmt.cpp @@ -21,13 +21,16 @@ #include "plurrule_impl.h" #include "uassert.h" #include "uhash.h" -#include "precision.h" -#include "visibledigits.h" +#include "number_decimalquantity.h" +#include "number_utils.h" +#include "number_utypes.h" #if !UCONFIG_NO_FORMATTING U_NAMESPACE_BEGIN +using number::impl::DecimalQuantity; + static const UChar OTHER_STRING[] = { 0x6F, 0x74, 0x68, 0x65, 0x72, 0 // "other" }; @@ -258,45 +261,33 @@ PluralFormat::format(const Formattable& numberObject, double number, if (msgPattern.countParts() == 0) { return numberFormat->format(numberObject, appendTo, pos, status); } + // Get the appropriate sub-message. // Select it based on the formatted number-offset. double numberMinusOffset = number - offset; - UnicodeString numberString; - FieldPosition ignorePos; - FixedPrecision fp; - VisibleDigitsWithExponent dec; - fp.initVisibleDigitsWithExponent(numberMinusOffset, dec, status); - if (U_FAILURE(status)) { - return appendTo; - } + // Call NumberFormatter to get both the DecimalQuantity and the string. + // This call site needs to use more internal APIs than the Java equivalent. + number::impl::UFormattedNumberData data; if (offset == 0) { - DecimalFormat *decFmt = dynamic_cast(numberFormat); - if(decFmt != NULL) { - decFmt->initVisibleDigitsWithExponent( - numberObject, dec, status); - if (U_FAILURE(status)) { - return appendTo; - } - decFmt->format(dec, numberString, ignorePos, status); - } else { - numberFormat->format( - numberObject, numberString, ignorePos, status); // could be BigDecimal etc. - } + // could be BigDecimal etc. + numberObject.populateDecimalQuantity(data.quantity, status); } else { - DecimalFormat *decFmt = dynamic_cast(numberFormat); - if(decFmt != NULL) { - decFmt->initVisibleDigitsWithExponent( - numberMinusOffset, dec, status); - if (U_FAILURE(status)) { - return appendTo; - } - decFmt->format(dec, numberString, ignorePos, status); + data.quantity.setToDouble(numberMinusOffset); + } + UnicodeString numberString; + auto *decFmt = dynamic_cast(numberFormat); + if(decFmt != nullptr) { + decFmt->toNumberFormatter().formatImpl(&data, status); // mutates &data + numberString = data.string.toUnicodeString(); + } else { + if (offset == 0) { + numberFormat->format(numberObject, numberString, status); } else { - numberFormat->format( - numberMinusOffset, numberString, ignorePos, status); + numberFormat->format(numberMinusOffset, numberString, status); } } - int32_t partIndex = findSubMessage(msgPattern, 0, pluralRulesWrapper, &dec, number, status); + + int32_t partIndex = findSubMessage(msgPattern, 0, pluralRulesWrapper, &data.quantity, number, status); if (U_FAILURE(status)) { return appendTo; } // Replace syntactic # signs in the top level of this sub-message // (not in nested arguments) with the formatted number-offset. @@ -585,7 +576,7 @@ PluralFormat::PluralSelectorAdapter::~PluralSelectorAdapter() { UnicodeString PluralFormat::PluralSelectorAdapter::select(void *context, double number, UErrorCode& /*ec*/) const { (void)number; // unused except in the assertion - VisibleDigitsWithExponent *dec=static_cast(context); + IFixedDecimal *dec=static_cast(context); return pluralRules->select(*dec); } diff --git a/deps/icu-small/source/i18n/plurrule.cpp b/deps/icu-small/source/i18n/plurrule.cpp index 6733a23e003..9597e8eb00d 100644 --- a/deps/icu-small/source/i18n/plurrule.cpp +++ b/deps/icu-small/source/i18n/plurrule.cpp @@ -22,7 +22,6 @@ #include "charstr.h" #include "cmemory.h" #include "cstring.h" -#include "digitlst.h" #include "hash.h" #include "locutil.h" #include "mutex.h" @@ -35,13 +34,15 @@ #include "uvectr32.h" #include "sharedpluralrules.h" #include "unifiedcache.h" -#include "digitinterval.h" -#include "visibledigits.h" +#include "number_decimalquantity.h" #if !UCONFIG_NO_FORMATTING U_NAMESPACE_BEGIN +using namespace icu::pluralimpl; +using icu::number::impl::DecimalQuantity; + static const UChar PLURAL_KEYWORD_OTHER[]={LOW_O,LOW_T,LOW_H,LOW_E,LOW_R,0}; static const UChar PLURAL_DEFAULT_RULE[]={LOW_O,LOW_T,LOW_H,LOW_E,LOW_R,COLON,SPACE,LOW_N,0}; static const UChar PK_IN[]={LOW_I,LOW_N,0}; @@ -247,26 +248,6 @@ PluralRules::select(double number) const { return select(FixedDecimal(number)); } -UnicodeString -PluralRules::select(const Formattable& obj, const NumberFormat& fmt, UErrorCode& status) const { - if (U_SUCCESS(status)) { - const DecimalFormat *decFmt = dynamic_cast(&fmt); - if (decFmt != NULL) { - VisibleDigitsWithExponent digits; - decFmt->initVisibleDigitsWithExponent(obj, digits, status); - if (U_SUCCESS(status)) { - return select(digits); - } - } else { - double number = obj.getDouble(status); - if (U_SUCCESS(status)) { - return select(number); - } - } - } - return UnicodeString(); -} - UnicodeString PluralRules::select(const IFixedDecimal &number) const { if (mRules == NULL) { @@ -277,14 +258,6 @@ PluralRules::select(const IFixedDecimal &number) const { } } -UnicodeString -PluralRules::select(const VisibleDigitsWithExponent &number) const { - if (number.getExponent() != NULL) { - return UnicodeString(TRUE, PLURAL_DEFAULT_RULE, -1); - } - return select(FixedDecimal(number.getMantissa())); -} - StringEnumeration* @@ -1425,18 +1398,6 @@ PluralOperand tokenTypeToPluralOperand(tokenType tt) { } } -IFixedDecimal::~IFixedDecimal() = default; - -FixedDecimal::FixedDecimal(const VisibleDigits &digits) { - digits.getFixedDecimal( - source, intValue, decimalDigits, - decimalDigitsWithoutTrailingZeros, - visibleDecimalDigitCount, hasIntegerValue); - isNegative = digits.isNegative(); - _isNaN = digits.isNaN(); - _isInfinite = digits.isInfinite(); -} - FixedDecimal::FixedDecimal(double n, int32_t v, int64_t f) { init(n, v, f); // check values. TODO make into unit test. @@ -1474,14 +1435,14 @@ FixedDecimal::FixedDecimal() { FixedDecimal::FixedDecimal(const UnicodeString &num, UErrorCode &status) { CharString cs; cs.appendInvariantChars(num, status); - DigitList dl; - dl.set(cs.toStringPiece(), status); + DecimalQuantity dl; + dl.setToDecNumber(cs.toStringPiece(), status); if (U_FAILURE(status)) { init(0, 0, 0); return; } int32_t decimalPoint = num.indexOf(DOT); - double n = dl.getDouble(); + double n = dl.toDouble(); if (decimalPoint == -1) { init(n, 0, 0); } else { @@ -1497,7 +1458,7 @@ FixedDecimal::FixedDecimal(const FixedDecimal &other) { decimalDigits = other.decimalDigits; decimalDigitsWithoutTrailingZeros = other.decimalDigitsWithoutTrailingZeros; intValue = other.intValue; - hasIntegerValue = other.hasIntegerValue; + _hasIntegerValue = other._hasIntegerValue; isNegative = other.isNegative; _isNaN = other._isNaN; _isInfinite = other._isInfinite; @@ -1521,10 +1482,10 @@ void FixedDecimal::init(double n, int32_t v, int64_t f) { v = 0; f = 0; intValue = 0; - hasIntegerValue = FALSE; + _hasIntegerValue = FALSE; } else { intValue = (int64_t)source; - hasIntegerValue = (source == intValue); + _hasIntegerValue = (source == intValue); } visibleDecimalDigitCount = v; @@ -1658,6 +1619,10 @@ bool FixedDecimal::isInfinite() const { return _isInfinite; } +bool FixedDecimal::hasIntegerValue() const { + return _hasIntegerValue; +} + bool FixedDecimal::isNanOrInfinity() const { return _isNaN || _isInfinite; } diff --git a/deps/icu-small/source/i18n/plurrule_impl.h b/deps/icu-small/source/i18n/plurrule_impl.h index b93fc501bac..3ab445d5843 100644 --- a/deps/icu-small/source/i18n/plurrule_impl.h +++ b/deps/icu-small/source/i18n/plurrule_impl.h @@ -40,67 +40,73 @@ class DigitInterval; class PluralRules; class VisibleDigits; -static const UChar DOT = ((UChar)0x002E); -static const UChar SINGLE_QUOTE = ((UChar)0x0027); -static const UChar SLASH = ((UChar)0x002F); -static const UChar BACKSLASH = ((UChar)0x005C); -static const UChar SPACE = ((UChar)0x0020); -static const UChar EXCLAMATION = ((UChar)0x0021); -static const UChar QUOTATION_MARK = ((UChar)0x0022); -static const UChar NUMBER_SIGN = ((UChar)0x0023); -static const UChar PERCENT_SIGN = ((UChar)0x0025); -static const UChar ASTERISK = ((UChar)0x002A); -static const UChar COMMA = ((UChar)0x002C); -static const UChar HYPHEN = ((UChar)0x002D); -static const UChar U_ZERO = ((UChar)0x0030); -static const UChar U_ONE = ((UChar)0x0031); -static const UChar U_TWO = ((UChar)0x0032); -static const UChar U_THREE = ((UChar)0x0033); -static const UChar U_FOUR = ((UChar)0x0034); -static const UChar U_FIVE = ((UChar)0x0035); -static const UChar U_SIX = ((UChar)0x0036); -static const UChar U_SEVEN = ((UChar)0x0037); -static const UChar U_EIGHT = ((UChar)0x0038); -static const UChar U_NINE = ((UChar)0x0039); -static const UChar COLON = ((UChar)0x003A); -static const UChar SEMI_COLON = ((UChar)0x003B); -static const UChar EQUALS = ((UChar)0x003D); -static const UChar AT = ((UChar)0x0040); -static const UChar CAP_A = ((UChar)0x0041); -static const UChar CAP_B = ((UChar)0x0042); -static const UChar CAP_R = ((UChar)0x0052); -static const UChar CAP_Z = ((UChar)0x005A); -static const UChar LOWLINE = ((UChar)0x005F); -static const UChar LEFTBRACE = ((UChar)0x007B); -static const UChar RIGHTBRACE = ((UChar)0x007D); -static const UChar TILDE = ((UChar)0x007E); -static const UChar ELLIPSIS = ((UChar)0x2026); +namespace pluralimpl { -static const UChar LOW_A = ((UChar)0x0061); -static const UChar LOW_B = ((UChar)0x0062); -static const UChar LOW_C = ((UChar)0x0063); -static const UChar LOW_D = ((UChar)0x0064); -static const UChar LOW_E = ((UChar)0x0065); -static const UChar LOW_F = ((UChar)0x0066); -static const UChar LOW_G = ((UChar)0x0067); -static const UChar LOW_H = ((UChar)0x0068); -static const UChar LOW_I = ((UChar)0x0069); -static const UChar LOW_J = ((UChar)0x006a); -static const UChar LOW_K = ((UChar)0x006B); -static const UChar LOW_L = ((UChar)0x006C); -static const UChar LOW_M = ((UChar)0x006D); -static const UChar LOW_N = ((UChar)0x006E); -static const UChar LOW_O = ((UChar)0x006F); -static const UChar LOW_P = ((UChar)0x0070); -static const UChar LOW_Q = ((UChar)0x0071); -static const UChar LOW_R = ((UChar)0x0072); -static const UChar LOW_S = ((UChar)0x0073); -static const UChar LOW_T = ((UChar)0x0074); -static const UChar LOW_U = ((UChar)0x0075); -static const UChar LOW_V = ((UChar)0x0076); -static const UChar LOW_W = ((UChar)0x0077); -static const UChar LOW_Y = ((UChar)0x0079); -static const UChar LOW_Z = ((UChar)0x007A); +// TODO: Remove this and replace with u"" literals. Was for EBCDIC compatibility. + +static const UChar DOT = ((UChar) 0x002E); +static const UChar SINGLE_QUOTE = ((UChar) 0x0027); +static const UChar SLASH = ((UChar) 0x002F); +static const UChar BACKSLASH = ((UChar) 0x005C); +static const UChar SPACE = ((UChar) 0x0020); +static const UChar EXCLAMATION = ((UChar) 0x0021); +static const UChar QUOTATION_MARK = ((UChar) 0x0022); +static const UChar NUMBER_SIGN = ((UChar) 0x0023); +static const UChar PERCENT_SIGN = ((UChar) 0x0025); +static const UChar ASTERISK = ((UChar) 0x002A); +static const UChar COMMA = ((UChar) 0x002C); +static const UChar HYPHEN = ((UChar) 0x002D); +static const UChar U_ZERO = ((UChar) 0x0030); +static const UChar U_ONE = ((UChar) 0x0031); +static const UChar U_TWO = ((UChar) 0x0032); +static const UChar U_THREE = ((UChar) 0x0033); +static const UChar U_FOUR = ((UChar) 0x0034); +static const UChar U_FIVE = ((UChar) 0x0035); +static const UChar U_SIX = ((UChar) 0x0036); +static const UChar U_SEVEN = ((UChar) 0x0037); +static const UChar U_EIGHT = ((UChar) 0x0038); +static const UChar U_NINE = ((UChar) 0x0039); +static const UChar COLON = ((UChar) 0x003A); +static const UChar SEMI_COLON = ((UChar) 0x003B); +static const UChar EQUALS = ((UChar) 0x003D); +static const UChar AT = ((UChar) 0x0040); +static const UChar CAP_A = ((UChar) 0x0041); +static const UChar CAP_B = ((UChar) 0x0042); +static const UChar CAP_R = ((UChar) 0x0052); +static const UChar CAP_Z = ((UChar) 0x005A); +static const UChar LOWLINE = ((UChar) 0x005F); +static const UChar LEFTBRACE = ((UChar) 0x007B); +static const UChar RIGHTBRACE = ((UChar) 0x007D); +static const UChar TILDE = ((UChar) 0x007E); +static const UChar ELLIPSIS = ((UChar) 0x2026); + +static const UChar LOW_A = ((UChar) 0x0061); +static const UChar LOW_B = ((UChar) 0x0062); +static const UChar LOW_C = ((UChar) 0x0063); +static const UChar LOW_D = ((UChar) 0x0064); +static const UChar LOW_E = ((UChar) 0x0065); +static const UChar LOW_F = ((UChar) 0x0066); +static const UChar LOW_G = ((UChar) 0x0067); +static const UChar LOW_H = ((UChar) 0x0068); +static const UChar LOW_I = ((UChar) 0x0069); +static const UChar LOW_J = ((UChar) 0x006a); +static const UChar LOW_K = ((UChar) 0x006B); +static const UChar LOW_L = ((UChar) 0x006C); +static const UChar LOW_M = ((UChar) 0x006D); +static const UChar LOW_N = ((UChar) 0x006E); +static const UChar LOW_O = ((UChar) 0x006F); +static const UChar LOW_P = ((UChar) 0x0070); +static const UChar LOW_Q = ((UChar) 0x0071); +static const UChar LOW_R = ((UChar) 0x0072); +static const UChar LOW_S = ((UChar) 0x0073); +static const UChar LOW_T = ((UChar) 0x0074); +static const UChar LOW_U = ((UChar) 0x0075); +static const UChar LOW_V = ((UChar) 0x0076); +static const UChar LOW_W = ((UChar) 0x0077); +static const UChar LOW_Y = ((UChar) 0x0079); +static const UChar LOW_Z = ((UChar) 0x007A); + +} static const int32_t PLURAL_RANGE_HIGH = 0x7fffffff; @@ -244,6 +250,9 @@ class U_I18N_API IFixedDecimal { virtual bool isNaN() const = 0; virtual bool isInfinite() const = 0; + + /** Whether the number has no nonzero fraction digits. */ + virtual bool hasIntegerValue() const = 0; }; /** @@ -263,7 +272,6 @@ class U_I18N_API FixedDecimal: public IFixedDecimal, public UObject { FixedDecimal(double n, int32_t v, int64_t f); FixedDecimal(double n, int32_t); explicit FixedDecimal(double n); - explicit FixedDecimal(const VisibleDigits &n); FixedDecimal(); ~FixedDecimal() U_OVERRIDE; FixedDecimal(const UnicodeString &s, UErrorCode &ec); @@ -272,6 +280,7 @@ class U_I18N_API FixedDecimal: public IFixedDecimal, public UObject { double getPluralOperand(PluralOperand operand) const U_OVERRIDE; bool isNaN() const U_OVERRIDE; bool isInfinite() const U_OVERRIDE; + bool hasIntegerValue() const U_OVERRIDE; bool isNanOrInfinity() const; // used in decimfmtimpl.cpp @@ -290,7 +299,7 @@ class U_I18N_API FixedDecimal: public IFixedDecimal, public UObject { int64_t decimalDigits; int64_t decimalDigitsWithoutTrailingZeros; int64_t intValue; - UBool hasIntegerValue; + UBool _hasIntegerValue; UBool isNegative; UBool _isNaN; UBool _isInfinite; diff --git a/deps/icu-small/source/i18n/precision.cpp b/deps/icu-small/source/i18n/precision.cpp deleted file mode 100644 index 97dc13dc385..00000000000 --- a/deps/icu-small/source/i18n/precision.cpp +++ /dev/null @@ -1,444 +0,0 @@ -// © 2016 and later: Unicode, Inc. and others. -// License & terms of use: http://www.unicode.org/copyright.html -/* - * Copyright (C) 2015, International Business Machines - * Corporation and others. All Rights Reserved. - * - * file name: precisison.cpp - */ - -#include - -#include "unicode/utypes.h" - -#if !UCONFIG_NO_FORMATTING - -#include "digitlst.h" -#include "fmtableimp.h" -#include "precision.h" -#include "putilimp.h" -#include "visibledigits.h" - -U_NAMESPACE_BEGIN - -static const int32_t gPower10[] = {1, 10, 100, 1000}; - -FixedPrecision::FixedPrecision() - : fExactOnly(FALSE), fFailIfOverMax(FALSE), fRoundingMode(DecimalFormat::kRoundHalfEven) { - fMin.setIntDigitCount(1); - fMin.setFracDigitCount(0); -} - -UBool -FixedPrecision::isRoundingRequired( - int32_t upperExponent, int32_t lowerExponent) const { - int32_t leastSigAllowed = fMax.getLeastSignificantInclusive(); - int32_t maxSignificantDigits = fSignificant.getMax(); - int32_t roundDigit; - if (maxSignificantDigits == INT32_MAX) { - roundDigit = leastSigAllowed; - } else { - int32_t limitDigit = upperExponent - maxSignificantDigits; - roundDigit = - limitDigit > leastSigAllowed ? limitDigit : leastSigAllowed; - } - return (roundDigit > lowerExponent); -} - -DigitList & -FixedPrecision::round( - DigitList &value, int32_t exponent, UErrorCode &status) const { - if (U_FAILURE(status)) { - return value; - } - value .fContext.status &= ~DEC_Inexact; - if (!fRoundingIncrement.isZero()) { - if (exponent == 0) { - value.quantize(fRoundingIncrement, status); - } else { - DigitList adjustedIncrement(fRoundingIncrement); - adjustedIncrement.shiftDecimalRight(exponent); - value.quantize(adjustedIncrement, status); - } - if (U_FAILURE(status)) { - return value; - } - } - int32_t leastSig = fMax.getLeastSignificantInclusive(); - if (leastSig == INT32_MIN) { - value.round(fSignificant.getMax()); - } else { - value.roundAtExponent( - exponent + leastSig, - fSignificant.getMax()); - } - if (fExactOnly && (value.fContext.status & DEC_Inexact)) { - status = U_FORMAT_INEXACT_ERROR; - } else if (fFailIfOverMax) { - // Smallest interval for value stored in interval - DigitInterval interval; - value.getSmallestInterval(interval); - if (fMax.getIntDigitCount() < interval.getIntDigitCount()) { - status = U_ILLEGAL_ARGUMENT_ERROR; - } - } - return value; -} - -DigitInterval & -FixedPrecision::getIntervalForZero(DigitInterval &interval) const { - interval = fMin; - if (fSignificant.getMin() > 0) { - interval.expandToContainDigit(interval.getIntDigitCount() - fSignificant.getMin()); - } - interval.shrinkToFitWithin(fMax); - return interval; -} - -DigitInterval & -FixedPrecision::getInterval( - int32_t upperExponent, DigitInterval &interval) const { - if (fSignificant.getMin() > 0) { - interval.expandToContainDigit( - upperExponent - fSignificant.getMin()); - } - interval.expandToContain(fMin); - interval.shrinkToFitWithin(fMax); - return interval; -} - -DigitInterval & -FixedPrecision::getInterval( - const DigitList &value, DigitInterval &interval) const { - if (value.isZero()) { - interval = fMin; - if (fSignificant.getMin() > 0) { - interval.expandToContainDigit(interval.getIntDigitCount() - fSignificant.getMin()); - } - } else { - value.getSmallestInterval(interval); - if (fSignificant.getMin() > 0) { - interval.expandToContainDigit( - value.getUpperExponent() - fSignificant.getMin()); - } - interval.expandToContain(fMin); - } - interval.shrinkToFitWithin(fMax); - return interval; -} - -UBool -FixedPrecision::isFastFormattable() const { - return (fMin.getFracDigitCount() == 0 && fSignificant.isNoConstraints() && fRoundingIncrement.isZero() && !fFailIfOverMax); -} - -UBool -FixedPrecision::handleNonNumeric(DigitList &value, VisibleDigits &digits) { - if (value.isNaN()) { - digits.setNaN(); - return TRUE; - } - if (value.isInfinite()) { - digits.setInfinite(); - if (!value.isPositive()) { - digits.setNegative(); - } - return TRUE; - } - return FALSE; -} - -VisibleDigits & -FixedPrecision::initVisibleDigits( - DigitList &value, - VisibleDigits &digits, - UErrorCode &status) const { - if (U_FAILURE(status)) { - return digits; - } - digits.clear(); - if (handleNonNumeric(value, digits)) { - return digits; - } - if (!value.isPositive()) { - digits.setNegative(); - } - value.setRoundingMode(fRoundingMode); - round(value, 0, status); - getInterval(value, digits.fInterval); - digits.fExponent = value.getLowerExponent(); - value.appendDigitsTo(digits.fDigits, status); - return digits; -} - -VisibleDigits & -FixedPrecision::initVisibleDigits( - int64_t value, - VisibleDigits &digits, - UErrorCode &status) const { - if (U_FAILURE(status)) { - return digits; - } - if (!fRoundingIncrement.isZero()) { - // If we have round increment, use digit list. - DigitList digitList; - digitList.set(value); - return initVisibleDigits(digitList, digits, status); - } - // Try fast path - if (initVisibleDigits(value, 0, digits, status)) { - digits.fAbsDoubleValue = fabs((double) value); - digits.fAbsDoubleValueSet = U_SUCCESS(status) && !digits.isOverMaxDigits(); - return digits; - } - // Oops have to use digit list - DigitList digitList; - digitList.set(value); - return initVisibleDigits(digitList, digits, status); -} - -VisibleDigits & -FixedPrecision::initVisibleDigits( - double value, - VisibleDigits &digits, - UErrorCode &status) const { - if (U_FAILURE(status)) { - return digits; - } - digits.clear(); - if (uprv_isNaN(value)) { - digits.setNaN(); - return digits; - } - if (uprv_isPositiveInfinity(value)) { - digits.setInfinite(); - return digits; - } - if (uprv_isNegativeInfinity(value)) { - digits.setInfinite(); - digits.setNegative(); - return digits; - } - if (!fRoundingIncrement.isZero()) { - // If we have round increment, use digit list. - DigitList digitList; - digitList.set(value); - return initVisibleDigits(digitList, digits, status); - } - // Try to find n such that value * 10^n is an integer - int32_t n = -1; - double scaled; - for (int32_t i = 0; i < UPRV_LENGTHOF(gPower10); ++i) { - scaled = value * gPower10[i]; - if (scaled > MAX_INT64_IN_DOUBLE || scaled < -MAX_INT64_IN_DOUBLE) { - break; - } - if (scaled == floor(scaled)) { - n = i; - break; - } - } - // Try fast path - if (n >= 0 && initVisibleDigits(static_cast(scaled), -n, digits, status)) { - digits.fAbsDoubleValue = fabs(value); - digits.fAbsDoubleValueSet = U_SUCCESS(status) && !digits.isOverMaxDigits(); - // Adjust for negative 0 because when we cast to an int64, - // negative 0 becomes positive 0. - if (scaled == 0.0 && uprv_isNegative(scaled)) { - digits.setNegative(); - } - return digits; - } - - // Oops have to use digit list - DigitList digitList; - digitList.set(value); - return initVisibleDigits(digitList, digits, status); -} - -UBool -FixedPrecision::initVisibleDigits( - int64_t mantissa, - int32_t exponent, - VisibleDigits &digits, - UErrorCode &status) const { - if (U_FAILURE(status)) { - return TRUE; - } - digits.clear(); - - // Precompute fAbsIntValue if it is small enough, but we don't know yet - // if it will be valid. - UBool absIntValueComputed = FALSE; - if (mantissa > -1000000000000000000LL /* -1e18 */ - && mantissa < 1000000000000000000LL /* 1e18 */) { - digits.fAbsIntValue = mantissa; - if (digits.fAbsIntValue < 0) { - digits.fAbsIntValue = -digits.fAbsIntValue; - } - int32_t i = 0; - int32_t maxPower10Exp = UPRV_LENGTHOF(gPower10) - 1; - for (; i > exponent + maxPower10Exp; i -= maxPower10Exp) { - digits.fAbsIntValue /= gPower10[maxPower10Exp]; - } - digits.fAbsIntValue /= gPower10[i - exponent]; - absIntValueComputed = TRUE; - } - if (mantissa == 0) { - getIntervalForZero(digits.fInterval); - digits.fAbsIntValueSet = absIntValueComputed; - return TRUE; - } - // be sure least significant digit is non zero - while (mantissa % 10 == 0) { - mantissa /= 10; - ++exponent; - } - if (mantissa < 0) { - digits.fDigits.append((char) -(mantissa % -10), status); - mantissa /= -10; - digits.setNegative(); - } - while (mantissa) { - digits.fDigits.append((char) (mantissa % 10), status); - mantissa /= 10; - } - if (U_FAILURE(status)) { - return TRUE; - } - digits.fExponent = exponent; - int32_t upperExponent = exponent + digits.fDigits.length(); - if (fFailIfOverMax && upperExponent > fMax.getIntDigitCount()) { - status = U_ILLEGAL_ARGUMENT_ERROR; - return TRUE; - } - UBool roundingRequired = - isRoundingRequired(upperExponent, exponent); - if (roundingRequired) { - if (fExactOnly) { - status = U_FORMAT_INEXACT_ERROR; - return TRUE; - } - return FALSE; - } - digits.fInterval.setLeastSignificantInclusive(exponent); - digits.fInterval.setMostSignificantExclusive(upperExponent); - getInterval(upperExponent, digits.fInterval); - - // The intValue we computed above is only valid if our visible digits - // doesn't exceed the maximum integer digits allowed. - digits.fAbsIntValueSet = absIntValueComputed && !digits.isOverMaxDigits(); - return TRUE; -} - -VisibleDigitsWithExponent & -FixedPrecision::initVisibleDigitsWithExponent( - DigitList &value, - VisibleDigitsWithExponent &digits, - UErrorCode &status) const { - digits.clear(); - initVisibleDigits(value, digits.fMantissa, status); - return digits; -} - -VisibleDigitsWithExponent & -FixedPrecision::initVisibleDigitsWithExponent( - double value, - VisibleDigitsWithExponent &digits, - UErrorCode &status) const { - digits.clear(); - initVisibleDigits(value, digits.fMantissa, status); - return digits; -} - -VisibleDigitsWithExponent & -FixedPrecision::initVisibleDigitsWithExponent( - int64_t value, - VisibleDigitsWithExponent &digits, - UErrorCode &status) const { - digits.clear(); - initVisibleDigits(value, digits.fMantissa, status); - return digits; -} - -ScientificPrecision::ScientificPrecision() : fMinExponentDigits(1) { -} - -DigitList & -ScientificPrecision::round(DigitList &value, UErrorCode &status) const { - if (U_FAILURE(status)) { - return value; - } - int32_t exponent = value.getScientificExponent( - fMantissa.fMin.getIntDigitCount(), getMultiplier()); - return fMantissa.round(value, exponent, status); -} - -int32_t -ScientificPrecision::toScientific(DigitList &value) const { - return value.toScientific( - fMantissa.fMin.getIntDigitCount(), getMultiplier()); -} - -int32_t -ScientificPrecision::getMultiplier() const { - int32_t maxIntDigitCount = fMantissa.fMax.getIntDigitCount(); - if (maxIntDigitCount == INT32_MAX) { - return 1; - } - int32_t multiplier = - maxIntDigitCount - fMantissa.fMin.getIntDigitCount() + 1; - return (multiplier < 1 ? 1 : multiplier); -} - -VisibleDigitsWithExponent & -ScientificPrecision::initVisibleDigitsWithExponent( - DigitList &value, - VisibleDigitsWithExponent &digits, - UErrorCode &status) const { - if (U_FAILURE(status)) { - return digits; - } - digits.clear(); - if (FixedPrecision::handleNonNumeric(value, digits.fMantissa)) { - return digits; - } - value.setRoundingMode(fMantissa.fRoundingMode); - int64_t exponent = toScientific(round(value, status)); - fMantissa.initVisibleDigits(value, digits.fMantissa, status); - FixedPrecision exponentPrecision; - exponentPrecision.fMin.setIntDigitCount(fMinExponentDigits); - exponentPrecision.initVisibleDigits(exponent, digits.fExponent, status); - digits.fHasExponent = TRUE; - return digits; -} - -VisibleDigitsWithExponent & -ScientificPrecision::initVisibleDigitsWithExponent( - double value, - VisibleDigitsWithExponent &digits, - UErrorCode &status) const { - if (U_FAILURE(status)) { - return digits; - } - DigitList digitList; - digitList.set(value); - return initVisibleDigitsWithExponent(digitList, digits, status); -} - -VisibleDigitsWithExponent & -ScientificPrecision::initVisibleDigitsWithExponent( - int64_t value, - VisibleDigitsWithExponent &digits, - UErrorCode &status) const { - if (U_FAILURE(status)) { - return digits; - } - DigitList digitList; - digitList.set(value); - return initVisibleDigitsWithExponent(digitList, digits, status); -} - - -U_NAMESPACE_END -#endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/deps/icu-small/source/i18n/precision.h b/deps/icu-small/source/i18n/precision.h deleted file mode 100644 index 0598fa17d62..00000000000 --- a/deps/icu-small/source/i18n/precision.h +++ /dev/null @@ -1,323 +0,0 @@ -// © 2016 and later: Unicode, Inc. and others. -// License & terms of use: http://www.unicode.org/copyright.html -/* -******************************************************************************* -* Copyright (C) 2015, International Business Machines -* Corporation and others. All Rights Reserved. -******************************************************************************* -* precision.h -* -* created on: 2015jan06 -* created by: Travis Keep -*/ - -#ifndef __PRECISION_H__ -#define __PRECISION_H__ - -#include "unicode/uobject.h" - -#if !UCONFIG_NO_FORMATTING -#include "unicode/utypes.h" - -#include "digitinterval.h" -#include "digitlst.h" -#include "significantdigitinterval.h" - -U_NAMESPACE_BEGIN - -class VisibleDigits; -class VisibleDigitsWithExponent; - - -/** - * A precision manager for values to be formatted as fixed point. - * Handles rounding of number to prepare it for formatting. - */ -class U_I18N_API FixedPrecision : public UMemory { -public: - - /** - * The smallest format interval allowed. Default is 1 integer digit and no - * fraction digits. - */ - DigitInterval fMin; - - /** - * The largest format interval allowed. Must contain fMin. - * Default is all digits. - */ - DigitInterval fMax; - - /** - * Min and max significant digits allowed. The default is no constraints. - */ - SignificantDigitInterval fSignificant; - - /** - * The rounding increment or zero if there is no rounding increment. - * Default is zero. - */ - DigitList fRoundingIncrement; - - /** - * If set, causes round() to set status to U_FORMAT_INEXACT_ERROR if - * any rounding is done. Default is FALSE. - */ - UBool fExactOnly; - - /** - * If set, causes round() to set status to U_ILLEGAL_ARGUMENT_ERROR if - * rounded number has more than maximum integer digits. Default is FALSE. - */ - UBool fFailIfOverMax; - - /** - * Controls the rounding mode that initVisibleDigits uses. - * Default is DecimalFormat::kRoundHalfEven - */ - DecimalFormat::ERoundingMode fRoundingMode; - - FixedPrecision(); - - /** - * Returns TRUE if this object equals rhs. - */ - UBool equals(const FixedPrecision &rhs) const { - return (fMin.equals(rhs.fMin) && - fMax.equals(rhs.fMax) && - fSignificant.equals(rhs.fSignificant) && - (fRoundingIncrement == rhs.fRoundingIncrement) && - fExactOnly == rhs.fExactOnly && - fFailIfOverMax == rhs.fFailIfOverMax && - fRoundingMode == rhs.fRoundingMode); - } - - /** - * Rounds value in place to prepare it for formatting. - * @param value The value to be rounded. It is rounded in place. - * @param exponent Always pass 0 for fixed decimal formatting. scientific - * precision passes the exponent value. Essentially, it divides value by - * 10^exponent, rounds and then multiplies by 10^exponent. - * @param status error returned here. - * @return reference to value. - */ - DigitList &round(DigitList &value, int32_t exponent, UErrorCode &status) const; - - /** - * Returns the interval to use to format the rounded value. - * @param roundedValue the already rounded value to format. - * @param interval modified in place to be the interval to use to format - * the rounded value. - * @return a reference to interval. - */ - DigitInterval &getInterval( - const DigitList &roundedValue, DigitInterval &interval) const; - - /** - * Returns TRUE if this instance allows for fast formatting of integers. - */ - UBool isFastFormattable() const; - - /** - * Initializes a VisibleDigits. - * @param value value for VisibleDigits - * Caller must not assume that the value of this parameter will remain - * unchanged. - * @param digits This is the value that is initialized. - * @param status any error returned here. - * @return digits - */ - VisibleDigits &initVisibleDigits( - DigitList &value, - VisibleDigits &digits, - UErrorCode &status) const; - - /** - * Initializes a VisibleDigits. - * @param value value for VisibleDigits - * @param digits This is the value that is initialized. - * @param status any error returned here. - * @return digits - */ - VisibleDigits &initVisibleDigits( - double value, - VisibleDigits &digits, - UErrorCode &status) const; - - /** - * Initializes a VisibleDigits. - * @param value value for VisibleDigits - * @param digits This is the value that is initialized. - * @param status any error returned here. - * @return digits - */ - VisibleDigits &initVisibleDigits( - int64_t value, - VisibleDigits &digits, - UErrorCode &status) const; - - /** - * Initializes a VisibleDigitsWithExponent. - * @param value value for VisibleDigits - * Caller must not assume that the value of this parameter will remain - * unchanged. - * @param digits This is the value that is initialized. - * @param status any error returned here. - * @return digits - */ - VisibleDigitsWithExponent &initVisibleDigitsWithExponent( - DigitList &value, - VisibleDigitsWithExponent &digits, - UErrorCode &status) const; - - /** - * Initializes a VisibleDigitsWithExponent. - * @param value value for VisibleDigits - * @param digits This is the value that is initialized. - * @param status any error returned here. - * @return digits - */ - VisibleDigitsWithExponent &initVisibleDigitsWithExponent( - double value, - VisibleDigitsWithExponent &digits, - UErrorCode &status) const; - - /** - * Initializes a VisibleDigitsWithExponent. - * @param value value for VisibleDigits - * @param digits This is the value that is initialized. - * @param status any error returned here. - * @return digits - */ - VisibleDigitsWithExponent &initVisibleDigitsWithExponent( - int64_t value, - VisibleDigitsWithExponent &digits, - UErrorCode &status) const; - -private: - /** - * Attempts to initialize 'digits' using simple mod 10 arithmetic. - * Returns FALSE if this is not possible such as when rounding - * would change the value. Otherwise returns TRUE. - * - * If the method returns FALSE, caller should create a DigitList - * and use it to initialize 'digits'. If this method returns TRUE, - * caller should accept the value stored in 'digits'. If this - * method returns TRUE along with a non zero error, caller must accept - * the error and not try again with a DigitList. - * - * Before calling this method, caller must verify that this object - * has no rounding increment set. - * - * The value that 'digits' is initialized to is mantissa * 10^exponent. - * For example mantissa = 54700 and exponent = -3 means 54.7. The - * properties of this object (such as min and max fraction digits), - * not the number of trailing zeros in the mantissa, determine whether or - * not the result contains any trailing 0's after the decimal point. - * - * @param mantissa the digits. May be positive or negative. May contain - * trailing zeros. - * @param exponent must always be zero or negative. An exponent > 0 - * yields undefined results! - * @param digits result stored here. - * @param status any error returned here. - */ - UBool - initVisibleDigits( - int64_t mantissa, - int32_t exponent, - VisibleDigits &digits, - UErrorCode &status) const; - UBool isRoundingRequired( - int32_t upperExponent, int32_t lowerExponent) const; - DigitInterval &getIntervalForZero(DigitInterval &interval) const; - DigitInterval &getInterval( - int32_t upperExponent, DigitInterval &interval) const; - static UBool handleNonNumeric(DigitList &value, VisibleDigits &digits); - - friend class ScientificPrecision; -}; - -/** - * A precision manager for values to be expressed as scientific notation. - */ -class U_I18N_API ScientificPrecision : public UMemory { -public: - FixedPrecision fMantissa; - int32_t fMinExponentDigits; - - ScientificPrecision(); - - /** - * rounds value in place to prepare it for formatting. - * @param value The value to be rounded. It is rounded in place. - * @param status error returned here. - * @return reference to value. - */ - DigitList &round(DigitList &value, UErrorCode &status) const; - - /** - * Converts value to a mantissa and exponent. - * - * @param value modified in place to be the mantissa. Depending on - * the precision settings, the resulting mantissa may not fall - * between 1.0 and 10.0. - * @return the exponent of value. - */ - int32_t toScientific(DigitList &value) const; - - /** - * Returns TRUE if this object equals rhs. - */ - UBool equals(const ScientificPrecision &rhs) const { - return fMantissa.equals(rhs.fMantissa) && fMinExponentDigits == rhs.fMinExponentDigits; - } - - /** - * Initializes a VisibleDigitsWithExponent. - * @param value the value - * Caller must not assume that the value of this parameter will remain - * unchanged. - * @param digits This is the value that is initialized. - * @param status any error returned here. - * @return digits - */ - VisibleDigitsWithExponent &initVisibleDigitsWithExponent( - DigitList &value, - VisibleDigitsWithExponent &digits, - UErrorCode &status) const; - - /** - * Initializes a VisibleDigitsWithExponent. - * @param value the value - * @param digits This is the value that is initialized. - * @param status any error returned here. - * @return digits - */ - VisibleDigitsWithExponent &initVisibleDigitsWithExponent( - double value, - VisibleDigitsWithExponent &digits, - UErrorCode &status) const; - - /** - * Initializes a VisibleDigitsWithExponent. - * @param value the value - * @param digits This is the value that is initialized. - * @param status any error returned here. - * @return digits - */ - VisibleDigitsWithExponent &initVisibleDigitsWithExponent( - int64_t value, - VisibleDigitsWithExponent &digits, - UErrorCode &status) const; - -private: - int32_t getMultiplier() const; - -}; - - - -U_NAMESPACE_END -#endif // #if !UCONFIG_NO_FORMATTING -#endif // __PRECISION_H__ diff --git a/deps/icu-small/source/i18n/quantityformatter.cpp b/deps/icu-small/source/i18n/quantityformatter.cpp index 208e064700a..ba06ba06b97 100644 --- a/deps/icu-small/source/i18n/quantityformatter.cpp +++ b/deps/icu-small/source/i18n/quantityformatter.cpp @@ -23,8 +23,8 @@ #include "unicode/fmtable.h" #include "unicode/fieldpos.h" #include "standardplural.h" -#include "visibledigits.h" #include "uassert.h" +#include "number_decimalquantity.h" U_NAMESPACE_BEGIN @@ -149,15 +149,15 @@ StandardPlural::Form QuantityFormatter::selectPlural( return StandardPlural::OTHER; } UnicodeString pluralKeyword; - VisibleDigitsWithExponent digits; const DecimalFormat *decFmt = dynamic_cast(&fmt); if (decFmt != NULL) { - decFmt->initVisibleDigitsWithExponent(number, digits, status); + number::impl::DecimalQuantity dq; + decFmt->formatToDecimalQuantity(number, dq, status); if (U_FAILURE(status)) { return StandardPlural::OTHER; } - pluralKeyword = rules.select(digits); - decFmt->format(digits, formattedNumber, pos, status); + pluralKeyword = rules.select(dq); + decFmt->format(number, formattedNumber, pos, status); } else { if (number.getType() == Formattable::kDouble) { pluralKeyword = rules.select(number.getDouble()); diff --git a/deps/icu-small/source/i18n/rbnf.cpp b/deps/icu-small/source/i18n/rbnf.cpp index 3385f300b11..ab9ad15e8c7 100644 --- a/deps/icu-small/source/i18n/rbnf.cpp +++ b/deps/icu-small/source/i18n/rbnf.cpp @@ -34,7 +34,7 @@ #include "patternprops.h" #include "uresimp.h" #include "nfrs.h" -#include "digitlst.h" +#include "number_decimalquantity.h" // debugging // #define RBNF_DEBUG @@ -68,6 +68,8 @@ static const UChar gSemiPercent[] = U_NAMESPACE_BEGIN +using number::impl::DecimalQuantity; + UOBJECT_DEFINE_RTTI_IMPLEMENTATION(RuleBasedNumberFormat) /* @@ -1109,21 +1111,21 @@ RuleBasedNumberFormat::findRuleSet(const UnicodeString& name, UErrorCode& status } UnicodeString& -RuleBasedNumberFormat::format(const DigitList &number, +RuleBasedNumberFormat::format(const DecimalQuantity &number, UnicodeString &appendTo, FieldPositionIterator *posIter, UErrorCode &status) const { if (U_FAILURE(status)) { return appendTo; } - DigitList copy(number); - if (copy.fitsIntoInt64(false)) { - format(((DigitList &)number).getInt64(), appendTo, posIter, status); + DecimalQuantity copy(number); + if (copy.fitsInLong()) { + format(number.toLong(), appendTo, posIter, status); } else { - copy.roundAtExponent(0); - if (copy.fitsIntoInt64(false)) { - format(number.getDouble(), appendTo, posIter, status); + copy.roundToMagnitude(0, number::impl::RoundingMode::UNUM_ROUND_HALFEVEN, status); + if (copy.fitsInLong()) { + format(number.toDouble(), appendTo, posIter, status); } else { // We're outside of our normal range that this framework can handle. @@ -1132,7 +1134,7 @@ RuleBasedNumberFormat::format(const DigitList &number, // TODO this section should probably be optimized. The DecimalFormat is shared in ICU4J. NumberFormat *decimalFormat = NumberFormat::createInstance(locale, UNUM_DECIMAL, status); Formattable f; - f.adoptDigitList(new DigitList(number)); + f.adoptDecimalQuantity(new DecimalQuantity(number)); decimalFormat->format(f, appendTo, posIter, status); delete decimalFormat; } @@ -1142,21 +1144,21 @@ RuleBasedNumberFormat::format(const DigitList &number, UnicodeString& -RuleBasedNumberFormat::format(const DigitList &number, +RuleBasedNumberFormat::format(const DecimalQuantity &number, UnicodeString& appendTo, FieldPosition& pos, UErrorCode &status) const { if (U_FAILURE(status)) { return appendTo; } - DigitList copy(number); - if (copy.fitsIntoInt64(false)) { - format(((DigitList &)number).getInt64(), appendTo, pos, status); + DecimalQuantity copy(number); + if (copy.fitsInLong()) { + format(number.toLong(), appendTo, pos, status); } else { - copy.roundAtExponent(0); - if (copy.fitsIntoInt64(false)) { - format(number.getDouble(), appendTo, pos, status); + copy.roundToMagnitude(0, number::impl::RoundingMode::UNUM_ROUND_HALFEVEN, status); + if (copy.fitsInLong()) { + format(number.toDouble(), appendTo, pos, status); } else { // We're outside of our normal range that this framework can handle. @@ -1165,7 +1167,7 @@ RuleBasedNumberFormat::format(const DigitList &number, // TODO this section should probably be optimized. The DecimalFormat is shared in ICU4J. NumberFormat *decimalFormat = NumberFormat::createInstance(locale, UNUM_DECIMAL, status); Formattable f; - f.adoptDigitList(new DigitList(number)); + f.adoptDecimalQuantity(new DecimalQuantity(number)); decimalFormat->format(f, appendTo, pos, status); delete decimalFormat; } @@ -1270,11 +1272,13 @@ RuleBasedNumberFormat::format(double number, { int32_t startPos = toAppendTo.length(); if (getRoundingMode() != DecimalFormat::ERoundingMode::kRoundUnnecessary && !uprv_isNaN(number) && !uprv_isInfinite(number)) { - DigitList digitList; - digitList.set(number); - digitList.setRoundingMode(getRoundingMode()); - digitList.roundFixedPoint(getMaximumFractionDigits()); - number = digitList.getDouble(); + DecimalQuantity digitList; + digitList.setToDouble(number); + digitList.roundToMagnitude( + -getMaximumFractionDigits(), + static_cast(getRoundingMode()), + status); + number = digitList.toDouble(); } rs.format(number, toAppendTo, toAppendTo.length(), 0, status); adjustForCapitalizationContext(startPos, toAppendTo, status); @@ -1310,9 +1314,9 @@ RuleBasedNumberFormat::format(int64_t number, NFRuleSet *ruleSet, UnicodeString& NumberFormat *decimalFormat = NumberFormat::createInstance(locale, UNUM_DECIMAL, status); Formattable f; FieldPosition pos(FieldPosition::DONT_CARE); - DigitList *digitList = new DigitList(); - digitList->set(number); - f.adoptDigitList(digitList); + DecimalQuantity *digitList = new DecimalQuantity(); + digitList->setToLong(number); + f.adoptDecimalQuantity(digitList); decimalFormat->format(f, toAppendTo, pos, status); delete decimalFormat; } diff --git a/deps/icu-small/source/i18n/reldatefmt.cpp b/deps/icu-small/source/i18n/reldatefmt.cpp index 5cf053db9a9..42ede7ae4d9 100644 --- a/deps/icu-small/source/i18n/reldatefmt.cpp +++ b/deps/icu-small/source/i18n/reldatefmt.cpp @@ -14,6 +14,7 @@ #if !UCONFIG_NO_FORMATTING && !UCONFIG_NO_BREAK_ITERATION +#include #include "unicode/dtfmtsym.h" #include "unicode/ucasemap.h" #include "unicode/ureldatefmt.h" @@ -849,7 +850,7 @@ UnicodeString& RelativeDateTimeFormatter::formatNumeric( return appendTo; } UDateDirection direction = UDAT_DIRECTION_NEXT; - if (offset < 0) { + if (std::signbit(offset)) { // needed to handle -0.0 direction = UDAT_DIRECTION_LAST; offset = -offset; } diff --git a/deps/icu-small/source/i18n/scientificnumberformatter.cpp b/deps/icu-small/source/i18n/scientificnumberformatter.cpp index adf032d989d..03d98dd6e10 100644 --- a/deps/icu-small/source/i18n/scientificnumberformatter.cpp +++ b/deps/icu-small/source/i18n/scientificnumberformatter.cpp @@ -15,8 +15,8 @@ #include "unicode/fpositer.h" #include "unicode/utf16.h" #include "unicode/uniset.h" -#include "decfmtst.h" #include "unicode/decimfmt.h" +#include "static_unicode_sets.h" U_NAMESPACE_BEGIN @@ -129,7 +129,6 @@ UnicodeString &ScientificNumberFormatter::SuperscriptStyle::format( const UnicodeString &original, FieldPositionIterator &fpi, const UnicodeString &preExponent, - const DecimalFormatStaticSets &staticSets, UnicodeString &appendTo, UErrorCode &status) const { if (U_FAILURE(status)) { @@ -149,16 +148,17 @@ UnicodeString &ScientificNumberFormatter::SuperscriptStyle::format( break; case UNUM_EXPONENT_SIGN_FIELD: { + using namespace icu::numparse::impl; int32_t beginIndex = fp.getBeginIndex(); int32_t endIndex = fp.getEndIndex(); UChar32 aChar = original.char32At(beginIndex); - if (staticSets.fMinusSigns->contains(aChar)) { + if (unisets::get(unisets::MINUS_SIGN)->contains(aChar)) { appendTo.append( original, copyFromOffset, beginIndex - copyFromOffset); appendTo.append(kSuperscriptMinusSign); - } else if (staticSets.fPlusSigns->contains(aChar)) { + } else if (unisets::get(unisets::PLUS_SIGN)->contains(aChar)) { appendTo.append( original, copyFromOffset, @@ -203,7 +203,6 @@ UnicodeString &ScientificNumberFormatter::MarkupStyle::format( const UnicodeString &original, FieldPositionIterator &fpi, const UnicodeString &preExponent, - const DecimalFormatStaticSets & /*unusedDecimalFormatSets*/, UnicodeString &appendTo, UErrorCode &status) const { if (U_FAILURE(status)) { @@ -243,8 +242,7 @@ ScientificNumberFormatter::ScientificNumberFormatter( DecimalFormat *fmtToAdopt, Style *styleToAdopt, UErrorCode &status) : fPreExponent(), fDecimalFormat(fmtToAdopt), - fStyle(styleToAdopt), - fStaticSets(NULL) { + fStyle(styleToAdopt) { if (U_FAILURE(status)) { return; } @@ -258,7 +256,6 @@ ScientificNumberFormatter::ScientificNumberFormatter( return; } getPreExponent(*sym, fPreExponent); - fStaticSets = DecimalFormatStaticSets::getStaticSets(status); } ScientificNumberFormatter::ScientificNumberFormatter( @@ -266,8 +263,7 @@ ScientificNumberFormatter::ScientificNumberFormatter( : UObject(other), fPreExponent(other.fPreExponent), fDecimalFormat(NULL), - fStyle(NULL), - fStaticSets(other.fStaticSets) { + fStyle(NULL) { fDecimalFormat = static_cast( other.fDecimalFormat->clone()); fStyle = other.fStyle->clone(); @@ -292,7 +288,6 @@ UnicodeString &ScientificNumberFormatter::format( original, fpi, fPreExponent, - *fStaticSets, appendTo, status); } diff --git a/deps/icu-small/source/i18n/significantdigitinterval.h b/deps/icu-small/source/i18n/significantdigitinterval.h deleted file mode 100644 index fc23370de5b..00000000000 --- a/deps/icu-small/source/i18n/significantdigitinterval.h +++ /dev/null @@ -1,92 +0,0 @@ -// © 2016 and later: Unicode, Inc. and others. -// License & terms of use: http://www.unicode.org/copyright.html -/* -******************************************************************************* -* Copyright (C) 2015, International Business Machines -* Corporation and others. All Rights Reserved. -******************************************************************************* -* significantdigitinterval.h -* -* created on: 2015jan6 -* created by: Travis Keep -*/ - -#ifndef __SIGNIFICANTDIGITINTERVAL_H__ -#define __SIGNIFICANTDIGITINTERVAL_H__ - -#include "unicode/uobject.h" -#include "unicode/utypes.h" - -U_NAMESPACE_BEGIN - -/** - * An interval of allowed significant digit counts. - */ -class U_I18N_API SignificantDigitInterval : public UMemory { -public: - - /** - * No limits on significant digits. - */ - SignificantDigitInterval() - : fMax(INT32_MAX), fMin(0) { } - - /** - * Make this instance have no limit on significant digits. - */ - void clear() { - fMin = 0; - fMax = INT32_MAX; - } - - /** - * Returns TRUE if this object is equal to rhs. - */ - UBool equals(const SignificantDigitInterval &rhs) const { - return ((fMax == rhs.fMax) && (fMin == rhs.fMin)); - } - - /** - * Sets maximum significant digits. 0 or negative means no maximum. - */ - void setMax(int32_t count) { - fMax = count <= 0 ? INT32_MAX : count; - } - - /** - * Get maximum significant digits. INT32_MAX means no maximum. - */ - int32_t getMax() const { - return fMax; - } - - /** - * Sets minimum significant digits. 0 or negative means no minimum. - */ - void setMin(int32_t count) { - fMin = count <= 0 ? 0 : count; - } - - /** - * Get maximum significant digits. 0 means no minimum. - */ - int32_t getMin() const { - return fMin; - } - - /** - * Returns TRUE if this instance represents no constraints on significant - * digits. - */ - UBool isNoConstraints() const { - return fMin == 0 && fMax == INT32_MAX; - } - -private: - int32_t fMax; - int32_t fMin; -}; - -U_NAMESPACE_END - -#endif // __SIGNIFICANTDIGITINTERVAL_H__ diff --git a/deps/icu-small/source/i18n/smallintformatter.cpp b/deps/icu-small/source/i18n/smallintformatter.cpp deleted file mode 100644 index 0c56e38bd69..00000000000 --- a/deps/icu-small/source/i18n/smallintformatter.cpp +++ /dev/null @@ -1,2622 +0,0 @@ -// © 2016 and later: Unicode, Inc. and others. -// License & terms of use: http://www.unicode.org/copyright.html -/* - * Copyright (C) 2015, International Business Machines - * Corporation and others. All Rights Reserved. - * - * file name: smallintformatter.cpp - */ - -#include "unicode/unistr.h" - -#include "smallintformatter.h" - -static const int32_t gMaxFastInt = 4096; - -static const UChar gDigits[] = { - 0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x31, - 0x30,0x30,0x30,0x32,0x30,0x30,0x30,0x33, - 0x30,0x30,0x30,0x34,0x30,0x30,0x30,0x35, - 0x30,0x30,0x30,0x36,0x30,0x30,0x30,0x37, - 0x30,0x30,0x30,0x38,0x30,0x30,0x30,0x39, - 0x30,0x30,0x31,0x30,0x30,0x30,0x31,0x31, - 0x30,0x30,0x31,0x32,0x30,0x30,0x31,0x33, - 0x30,0x30,0x31,0x34,0x30,0x30,0x31,0x35, - 0x30,0x30,0x31,0x36,0x30,0x30,0x31,0x37, - 0x30,0x30,0x31,0x38,0x30,0x30,0x31,0x39, - 0x30,0x30,0x32,0x30,0x30,0x30,0x32,0x31, - 0x30,0x30,0x32,0x32,0x30,0x30,0x32,0x33, - 0x30,0x30,0x32,0x34,0x30,0x30,0x32,0x35, - 0x30,0x30,0x32,0x36,0x30,0x30,0x32,0x37, - 0x30,0x30,0x32,0x38,0x30,0x30,0x32,0x39, - 0x30,0x30,0x33,0x30,0x30,0x30,0x33,0x31, - 0x30,0x30,0x33,0x32,0x30,0x30,0x33,0x33, - 0x30,0x30,0x33,0x34,0x30,0x30,0x33,0x35, - 0x30,0x30,0x33,0x36,0x30,0x30,0x33,0x37, - 0x30,0x30,0x33,0x38,0x30,0x30,0x33,0x39, - 0x30,0x30,0x34,0x30,0x30,0x30,0x34,0x31, - 0x30,0x30,0x34,0x32,0x30,0x30,0x34,0x33, - 0x30,0x30,0x34,0x34,0x30,0x30,0x34,0x35, - 0x30,0x30,0x34,0x36,0x30,0x30,0x34,0x37, - 0x30,0x30,0x34,0x38,0x30,0x30,0x34,0x39, - 0x30,0x30,0x35,0x30,0x30,0x30,0x35,0x31, - 0x30,0x30,0x35,0x32,0x30,0x30,0x35,0x33, - 0x30,0x30,0x35,0x34,0x30,0x30,0x35,0x35, - 0x30,0x30,0x35,0x36,0x30,0x30,0x35,0x37, - 0x30,0x30,0x35,0x38,0x30,0x30,0x35,0x39, - 0x30,0x30,0x36,0x30,0x30,0x30,0x36,0x31, - 0x30,0x30,0x36,0x32,0x30,0x30,0x36,0x33, - 0x30,0x30,0x36,0x34,0x30,0x30,0x36,0x35, - 0x30,0x30,0x36,0x36,0x30,0x30,0x36,0x37, - 0x30,0x30,0x36,0x38,0x30,0x30,0x36,0x39, - 0x30,0x30,0x37,0x30,0x30,0x30,0x37,0x31, - 0x30,0x30,0x37,0x32,0x30,0x30,0x37,0x33, - 0x30,0x30,0x37,0x34,0x30,0x30,0x37,0x35, - 0x30,0x30,0x37,0x36,0x30,0x30,0x37,0x37, - 0x30,0x30,0x37,0x38,0x30,0x30,0x37,0x39, - 0x30,0x30,0x38,0x30,0x30,0x30,0x38,0x31, - 0x30,0x30,0x38,0x32,0x30,0x30,0x38,0x33, - 0x30,0x30,0x38,0x34,0x30,0x30,0x38,0x35, - 0x30,0x30,0x38,0x36,0x30,0x30,0x38,0x37, - 0x30,0x30,0x38,0x38,0x30,0x30,0x38,0x39, - 0x30,0x30,0x39,0x30,0x30,0x30,0x39,0x31, - 0x30,0x30,0x39,0x32,0x30,0x30,0x39,0x33, - 0x30,0x30,0x39,0x34,0x30,0x30,0x39,0x35, - 0x30,0x30,0x39,0x36,0x30,0x30,0x39,0x37, - 0x30,0x30,0x39,0x38,0x30,0x30,0x39,0x39, - 0x30,0x31,0x30,0x30,0x30,0x31,0x30,0x31, - 0x30,0x31,0x30,0x32,0x30,0x31,0x30,0x33, - 0x30,0x31,0x30,0x34,0x30,0x31,0x30,0x35, - 0x30,0x31,0x30,0x36,0x30,0x31,0x30,0x37, - 0x30,0x31,0x30,0x38,0x30,0x31,0x30,0x39, - 0x30,0x31,0x31,0x30,0x30,0x31,0x31,0x31, - 0x30,0x31,0x31,0x32,0x30,0x31,0x31,0x33, - 0x30,0x31,0x31,0x34,0x30,0x31,0x31,0x35, - 0x30,0x31,0x31,0x36,0x30,0x31,0x31,0x37, - 0x30,0x31,0x31,0x38,0x30,0x31,0x31,0x39, - 0x30,0x31,0x32,0x30,0x30,0x31,0x32,0x31, - 0x30,0x31,0x32,0x32,0x30,0x31,0x32,0x33, - 0x30,0x31,0x32,0x34,0x30,0x31,0x32,0x35, - 0x30,0x31,0x32,0x36,0x30,0x31,0x32,0x37, - 0x30,0x31,0x32,0x38,0x30,0x31,0x32,0x39, - 0x30,0x31,0x33,0x30,0x30,0x31,0x33,0x31, - 0x30,0x31,0x33,0x32,0x30,0x31,0x33,0x33, - 0x30,0x31,0x33,0x34,0x30,0x31,0x33,0x35, - 0x30,0x31,0x33,0x36,0x30,0x31,0x33,0x37, - 0x30,0x31,0x33,0x38,0x30,0x31,0x33,0x39, - 0x30,0x31,0x34,0x30,0x30,0x31,0x34,0x31, - 0x30,0x31,0x34,0x32,0x30,0x31,0x34,0x33, - 0x30,0x31,0x34,0x34,0x30,0x31,0x34,0x35, - 0x30,0x31,0x34,0x36,0x30,0x31,0x34,0x37, - 0x30,0x31,0x34,0x38,0x30,0x31,0x34,0x39, - 0x30,0x31,0x35,0x30,0x30,0x31,0x35,0x31, - 0x30,0x31,0x35,0x32,0x30,0x31,0x35,0x33, - 0x30,0x31,0x35,0x34,0x30,0x31,0x35,0x35, - 0x30,0x31,0x35,0x36,0x30,0x31,0x35,0x37, - 0x30,0x31,0x35,0x38,0x30,0x31,0x35,0x39, - 0x30,0x31,0x36,0x30,0x30,0x31,0x36,0x31, - 0x30,0x31,0x36,0x32,0x30,0x31,0x36,0x33, - 0x30,0x31,0x36,0x34,0x30,0x31,0x36,0x35, - 0x30,0x31,0x36,0x36,0x30,0x31,0x36,0x37, - 0x30,0x31,0x36,0x38,0x30,0x31,0x36,0x39, - 0x30,0x31,0x37,0x30,0x30,0x31,0x37,0x31, - 0x30,0x31,0x37,0x32,0x30,0x31,0x37,0x33, - 0x30,0x31,0x37,0x34,0x30,0x31,0x37,0x35, - 0x30,0x31,0x37,0x36,0x30,0x31,0x37,0x37, - 0x30,0x31,0x37,0x38,0x30,0x31,0x37,0x39, - 0x30,0x31,0x38,0x30,0x30,0x31,0x38,0x31, - 0x30,0x31,0x38,0x32,0x30,0x31,0x38,0x33, - 0x30,0x31,0x38,0x34,0x30,0x31,0x38,0x35, - 0x30,0x31,0x38,0x36,0x30,0x31,0x38,0x37, - 0x30,0x31,0x38,0x38,0x30,0x31,0x38,0x39, - 0x30,0x31,0x39,0x30,0x30,0x31,0x39,0x31, - 0x30,0x31,0x39,0x32,0x30,0x31,0x39,0x33, - 0x30,0x31,0x39,0x34,0x30,0x31,0x39,0x35, - 0x30,0x31,0x39,0x36,0x30,0x31,0x39,0x37, - 0x30,0x31,0x39,0x38,0x30,0x31,0x39,0x39, - 0x30,0x32,0x30,0x30,0x30,0x32,0x30,0x31, - 0x30,0x32,0x30,0x32,0x30,0x32,0x30,0x33, - 0x30,0x32,0x30,0x34,0x30,0x32,0x30,0x35, - 0x30,0x32,0x30,0x36,0x30,0x32,0x30,0x37, - 0x30,0x32,0x30,0x38,0x30,0x32,0x30,0x39, - 0x30,0x32,0x31,0x30,0x30,0x32,0x31,0x31, - 0x30,0x32,0x31,0x32,0x30,0x32,0x31,0x33, - 0x30,0x32,0x31,0x34,0x30,0x32,0x31,0x35, - 0x30,0x32,0x31,0x36,0x30,0x32,0x31,0x37, - 0x30,0x32,0x31,0x38,0x30,0x32,0x31,0x39, - 0x30,0x32,0x32,0x30,0x30,0x32,0x32,0x31, - 0x30,0x32,0x32,0x32,0x30,0x32,0x32,0x33, - 0x30,0x32,0x32,0x34,0x30,0x32,0x32,0x35, - 0x30,0x32,0x32,0x36,0x30,0x32,0x32,0x37, - 0x30,0x32,0x32,0x38,0x30,0x32,0x32,0x39, - 0x30,0x32,0x33,0x30,0x30,0x32,0x33,0x31, - 0x30,0x32,0x33,0x32,0x30,0x32,0x33,0x33, - 0x30,0x32,0x33,0x34,0x30,0x32,0x33,0x35, - 0x30,0x32,0x33,0x36,0x30,0x32,0x33,0x37, - 0x30,0x32,0x33,0x38,0x30,0x32,0x33,0x39, - 0x30,0x32,0x34,0x30,0x30,0x32,0x34,0x31, - 0x30,0x32,0x34,0x32,0x30,0x32,0x34,0x33, - 0x30,0x32,0x34,0x34,0x30,0x32,0x34,0x35, - 0x30,0x32,0x34,0x36,0x30,0x32,0x34,0x37, - 0x30,0x32,0x34,0x38,0x30,0x32,0x34,0x39, - 0x30,0x32,0x35,0x30,0x30,0x32,0x35,0x31, - 0x30,0x32,0x35,0x32,0x30,0x32,0x35,0x33, - 0x30,0x32,0x35,0x34,0x30,0x32,0x35,0x35, - 0x30,0x32,0x35,0x36,0x30,0x32,0x35,0x37, - 0x30,0x32,0x35,0x38,0x30,0x32,0x35,0x39, - 0x30,0x32,0x36,0x30,0x30,0x32,0x36,0x31, - 0x30,0x32,0x36,0x32,0x30,0x32,0x36,0x33, - 0x30,0x32,0x36,0x34,0x30,0x32,0x36,0x35, - 0x30,0x32,0x36,0x36,0x30,0x32,0x36,0x37, - 0x30,0x32,0x36,0x38,0x30,0x32,0x36,0x39, - 0x30,0x32,0x37,0x30,0x30,0x32,0x37,0x31, - 0x30,0x32,0x37,0x32,0x30,0x32,0x37,0x33, - 0x30,0x32,0x37,0x34,0x30,0x32,0x37,0x35, - 0x30,0x32,0x37,0x36,0x30,0x32,0x37,0x37, - 0x30,0x32,0x37,0x38,0x30,0x32,0x37,0x39, - 0x30,0x32,0x38,0x30,0x30,0x32,0x38,0x31, - 0x30,0x32,0x38,0x32,0x30,0x32,0x38,0x33, - 0x30,0x32,0x38,0x34,0x30,0x32,0x38,0x35, - 0x30,0x32,0x38,0x36,0x30,0x32,0x38,0x37, - 0x30,0x32,0x38,0x38,0x30,0x32,0x38,0x39, - 0x30,0x32,0x39,0x30,0x30,0x32,0x39,0x31, - 0x30,0x32,0x39,0x32,0x30,0x32,0x39,0x33, - 0x30,0x32,0x39,0x34,0x30,0x32,0x39,0x35, - 0x30,0x32,0x39,0x36,0x30,0x32,0x39,0x37, - 0x30,0x32,0x39,0x38,0x30,0x32,0x39,0x39, - 0x30,0x33,0x30,0x30,0x30,0x33,0x30,0x31, - 0x30,0x33,0x30,0x32,0x30,0x33,0x30,0x33, - 0x30,0x33,0x30,0x34,0x30,0x33,0x30,0x35, - 0x30,0x33,0x30,0x36,0x30,0x33,0x30,0x37, - 0x30,0x33,0x30,0x38,0x30,0x33,0x30,0x39, - 0x30,0x33,0x31,0x30,0x30,0x33,0x31,0x31, - 0x30,0x33,0x31,0x32,0x30,0x33,0x31,0x33, - 0x30,0x33,0x31,0x34,0x30,0x33,0x31,0x35, - 0x30,0x33,0x31,0x36,0x30,0x33,0x31,0x37, - 0x30,0x33,0x31,0x38,0x30,0x33,0x31,0x39, - 0x30,0x33,0x32,0x30,0x30,0x33,0x32,0x31, - 0x30,0x33,0x32,0x32,0x30,0x33,0x32,0x33, - 0x30,0x33,0x32,0x34,0x30,0x33,0x32,0x35, - 0x30,0x33,0x32,0x36,0x30,0x33,0x32,0x37, - 0x30,0x33,0x32,0x38,0x30,0x33,0x32,0x39, - 0x30,0x33,0x33,0x30,0x30,0x33,0x33,0x31, - 0x30,0x33,0x33,0x32,0x30,0x33,0x33,0x33, - 0x30,0x33,0x33,0x34,0x30,0x33,0x33,0x35, - 0x30,0x33,0x33,0x36,0x30,0x33,0x33,0x37, - 0x30,0x33,0x33,0x38,0x30,0x33,0x33,0x39, - 0x30,0x33,0x34,0x30,0x30,0x33,0x34,0x31, - 0x30,0x33,0x34,0x32,0x30,0x33,0x34,0x33, - 0x30,0x33,0x34,0x34,0x30,0x33,0x34,0x35, - 0x30,0x33,0x34,0x36,0x30,0x33,0x34,0x37, - 0x30,0x33,0x34,0x38,0x30,0x33,0x34,0x39, - 0x30,0x33,0x35,0x30,0x30,0x33,0x35,0x31, - 0x30,0x33,0x35,0x32,0x30,0x33,0x35,0x33, - 0x30,0x33,0x35,0x34,0x30,0x33,0x35,0x35, - 0x30,0x33,0x35,0x36,0x30,0x33,0x35,0x37, - 0x30,0x33,0x35,0x38,0x30,0x33,0x35,0x39, - 0x30,0x33,0x36,0x30,0x30,0x33,0x36,0x31, - 0x30,0x33,0x36,0x32,0x30,0x33,0x36,0x33, - 0x30,0x33,0x36,0x34,0x30,0x33,0x36,0x35, - 0x30,0x33,0x36,0x36,0x30,0x33,0x36,0x37, - 0x30,0x33,0x36,0x38,0x30,0x33,0x36,0x39, - 0x30,0x33,0x37,0x30,0x30,0x33,0x37,0x31, - 0x30,0x33,0x37,0x32,0x30,0x33,0x37,0x33, - 0x30,0x33,0x37,0x34,0x30,0x33,0x37,0x35, - 0x30,0x33,0x37,0x36,0x30,0x33,0x37,0x37, - 0x30,0x33,0x37,0x38,0x30,0x33,0x37,0x39, - 0x30,0x33,0x38,0x30,0x30,0x33,0x38,0x31, - 0x30,0x33,0x38,0x32,0x30,0x33,0x38,0x33, - 0x30,0x33,0x38,0x34,0x30,0x33,0x38,0x35, - 0x30,0x33,0x38,0x36,0x30,0x33,0x38,0x37, - 0x30,0x33,0x38,0x38,0x30,0x33,0x38,0x39, - 0x30,0x33,0x39,0x30,0x30,0x33,0x39,0x31, - 0x30,0x33,0x39,0x32,0x30,0x33,0x39,0x33, - 0x30,0x33,0x39,0x34,0x30,0x33,0x39,0x35, - 0x30,0x33,0x39,0x36,0x30,0x33,0x39,0x37, - 0x30,0x33,0x39,0x38,0x30,0x33,0x39,0x39, - 0x30,0x34,0x30,0x30,0x30,0x34,0x30,0x31, - 0x30,0x34,0x30,0x32,0x30,0x34,0x30,0x33, - 0x30,0x34,0x30,0x34,0x30,0x34,0x30,0x35, - 0x30,0x34,0x30,0x36,0x30,0x34,0x30,0x37, - 0x30,0x34,0x30,0x38,0x30,0x34,0x30,0x39, - 0x30,0x34,0x31,0x30,0x30,0x34,0x31,0x31, - 0x30,0x34,0x31,0x32,0x30,0x34,0x31,0x33, - 0x30,0x34,0x31,0x34,0x30,0x34,0x31,0x35, - 0x30,0x34,0x31,0x36,0x30,0x34,0x31,0x37, - 0x30,0x34,0x31,0x38,0x30,0x34,0x31,0x39, - 0x30,0x34,0x32,0x30,0x30,0x34,0x32,0x31, - 0x30,0x34,0x32,0x32,0x30,0x34,0x32,0x33, - 0x30,0x34,0x32,0x34,0x30,0x34,0x32,0x35, - 0x30,0x34,0x32,0x36,0x30,0x34,0x32,0x37, - 0x30,0x34,0x32,0x38,0x30,0x34,0x32,0x39, - 0x30,0x34,0x33,0x30,0x30,0x34,0x33,0x31, - 0x30,0x34,0x33,0x32,0x30,0x34,0x33,0x33, - 0x30,0x34,0x33,0x34,0x30,0x34,0x33,0x35, - 0x30,0x34,0x33,0x36,0x30,0x34,0x33,0x37, - 0x30,0x34,0x33,0x38,0x30,0x34,0x33,0x39, - 0x30,0x34,0x34,0x30,0x30,0x34,0x34,0x31, - 0x30,0x34,0x34,0x32,0x30,0x34,0x34,0x33, - 0x30,0x34,0x34,0x34,0x30,0x34,0x34,0x35, - 0x30,0x34,0x34,0x36,0x30,0x34,0x34,0x37, - 0x30,0x34,0x34,0x38,0x30,0x34,0x34,0x39, - 0x30,0x34,0x35,0x30,0x30,0x34,0x35,0x31, - 0x30,0x34,0x35,0x32,0x30,0x34,0x35,0x33, - 0x30,0x34,0x35,0x34,0x30,0x34,0x35,0x35, - 0x30,0x34,0x35,0x36,0x30,0x34,0x35,0x37, - 0x30,0x34,0x35,0x38,0x30,0x34,0x35,0x39, - 0x30,0x34,0x36,0x30,0x30,0x34,0x36,0x31, - 0x30,0x34,0x36,0x32,0x30,0x34,0x36,0x33, - 0x30,0x34,0x36,0x34,0x30,0x34,0x36,0x35, - 0x30,0x34,0x36,0x36,0x30,0x34,0x36,0x37, - 0x30,0x34,0x36,0x38,0x30,0x34,0x36,0x39, - 0x30,0x34,0x37,0x30,0x30,0x34,0x37,0x31, - 0x30,0x34,0x37,0x32,0x30,0x34,0x37,0x33, - 0x30,0x34,0x37,0x34,0x30,0x34,0x37,0x35, - 0x30,0x34,0x37,0x36,0x30,0x34,0x37,0x37, - 0x30,0x34,0x37,0x38,0x30,0x34,0x37,0x39, - 0x30,0x34,0x38,0x30,0x30,0x34,0x38,0x31, - 0x30,0x34,0x38,0x32,0x30,0x34,0x38,0x33, - 0x30,0x34,0x38,0x34,0x30,0x34,0x38,0x35, - 0x30,0x34,0x38,0x36,0x30,0x34,0x38,0x37, - 0x30,0x34,0x38,0x38,0x30,0x34,0x38,0x39, - 0x30,0x34,0x39,0x30,0x30,0x34,0x39,0x31, - 0x30,0x34,0x39,0x32,0x30,0x34,0x39,0x33, - 0x30,0x34,0x39,0x34,0x30,0x34,0x39,0x35, - 0x30,0x34,0x39,0x36,0x30,0x34,0x39,0x37, - 0x30,0x34,0x39,0x38,0x30,0x34,0x39,0x39, - 0x30,0x35,0x30,0x30,0x30,0x35,0x30,0x31, - 0x30,0x35,0x30,0x32,0x30,0x35,0x30,0x33, - 0x30,0x35,0x30,0x34,0x30,0x35,0x30,0x35, - 0x30,0x35,0x30,0x36,0x30,0x35,0x30,0x37, - 0x30,0x35,0x30,0x38,0x30,0x35,0x30,0x39, - 0x30,0x35,0x31,0x30,0x30,0x35,0x31,0x31, - 0x30,0x35,0x31,0x32,0x30,0x35,0x31,0x33, - 0x30,0x35,0x31,0x34,0x30,0x35,0x31,0x35, - 0x30,0x35,0x31,0x36,0x30,0x35,0x31,0x37, - 0x30,0x35,0x31,0x38,0x30,0x35,0x31,0x39, - 0x30,0x35,0x32,0x30,0x30,0x35,0x32,0x31, - 0x30,0x35,0x32,0x32,0x30,0x35,0x32,0x33, - 0x30,0x35,0x32,0x34,0x30,0x35,0x32,0x35, - 0x30,0x35,0x32,0x36,0x30,0x35,0x32,0x37, - 0x30,0x35,0x32,0x38,0x30,0x35,0x32,0x39, - 0x30,0x35,0x33,0x30,0x30,0x35,0x33,0x31, - 0x30,0x35,0x33,0x32,0x30,0x35,0x33,0x33, - 0x30,0x35,0x33,0x34,0x30,0x35,0x33,0x35, - 0x30,0x35,0x33,0x36,0x30,0x35,0x33,0x37, - 0x30,0x35,0x33,0x38,0x30,0x35,0x33,0x39, - 0x30,0x35,0x34,0x30,0x30,0x35,0x34,0x31, - 0x30,0x35,0x34,0x32,0x30,0x35,0x34,0x33, - 0x30,0x35,0x34,0x34,0x30,0x35,0x34,0x35, - 0x30,0x35,0x34,0x36,0x30,0x35,0x34,0x37, - 0x30,0x35,0x34,0x38,0x30,0x35,0x34,0x39, - 0x30,0x35,0x35,0x30,0x30,0x35,0x35,0x31, - 0x30,0x35,0x35,0x32,0x30,0x35,0x35,0x33, - 0x30,0x35,0x35,0x34,0x30,0x35,0x35,0x35, - 0x30,0x35,0x35,0x36,0x30,0x35,0x35,0x37, - 0x30,0x35,0x35,0x38,0x30,0x35,0x35,0x39, - 0x30,0x35,0x36,0x30,0x30,0x35,0x36,0x31, - 0x30,0x35,0x36,0x32,0x30,0x35,0x36,0x33, - 0x30,0x35,0x36,0x34,0x30,0x35,0x36,0x35, - 0x30,0x35,0x36,0x36,0x30,0x35,0x36,0x37, - 0x30,0x35,0x36,0x38,0x30,0x35,0x36,0x39, - 0x30,0x35,0x37,0x30,0x30,0x35,0x37,0x31, - 0x30,0x35,0x37,0x32,0x30,0x35,0x37,0x33, - 0x30,0x35,0x37,0x34,0x30,0x35,0x37,0x35, - 0x30,0x35,0x37,0x36,0x30,0x35,0x37,0x37, - 0x30,0x35,0x37,0x38,0x30,0x35,0x37,0x39, - 0x30,0x35,0x38,0x30,0x30,0x35,0x38,0x31, - 0x30,0x35,0x38,0x32,0x30,0x35,0x38,0x33, - 0x30,0x35,0x38,0x34,0x30,0x35,0x38,0x35, - 0x30,0x35,0x38,0x36,0x30,0x35,0x38,0x37, - 0x30,0x35,0x38,0x38,0x30,0x35,0x38,0x39, - 0x30,0x35,0x39,0x30,0x30,0x35,0x39,0x31, - 0x30,0x35,0x39,0x32,0x30,0x35,0x39,0x33, - 0x30,0x35,0x39,0x34,0x30,0x35,0x39,0x35, - 0x30,0x35,0x39,0x36,0x30,0x35,0x39,0x37, - 0x30,0x35,0x39,0x38,0x30,0x35,0x39,0x39, - 0x30,0x36,0x30,0x30,0x30,0x36,0x30,0x31, - 0x30,0x36,0x30,0x32,0x30,0x36,0x30,0x33, - 0x30,0x36,0x30,0x34,0x30,0x36,0x30,0x35, - 0x30,0x36,0x30,0x36,0x30,0x36,0x30,0x37, - 0x30,0x36,0x30,0x38,0x30,0x36,0x30,0x39, - 0x30,0x36,0x31,0x30,0x30,0x36,0x31,0x31, - 0x30,0x36,0x31,0x32,0x30,0x36,0x31,0x33, - 0x30,0x36,0x31,0x34,0x30,0x36,0x31,0x35, - 0x30,0x36,0x31,0x36,0x30,0x36,0x31,0x37, - 0x30,0x36,0x31,0x38,0x30,0x36,0x31,0x39, - 0x30,0x36,0x32,0x30,0x30,0x36,0x32,0x31, - 0x30,0x36,0x32,0x32,0x30,0x36,0x32,0x33, - 0x30,0x36,0x32,0x34,0x30,0x36,0x32,0x35, - 0x30,0x36,0x32,0x36,0x30,0x36,0x32,0x37, - 0x30,0x36,0x32,0x38,0x30,0x36,0x32,0x39, - 0x30,0x36,0x33,0x30,0x30,0x36,0x33,0x31, - 0x30,0x36,0x33,0x32,0x30,0x36,0x33,0x33, - 0x30,0x36,0x33,0x34,0x30,0x36,0x33,0x35, - 0x30,0x36,0x33,0x36,0x30,0x36,0x33,0x37, - 0x30,0x36,0x33,0x38,0x30,0x36,0x33,0x39, - 0x30,0x36,0x34,0x30,0x30,0x36,0x34,0x31, - 0x30,0x36,0x34,0x32,0x30,0x36,0x34,0x33, - 0x30,0x36,0x34,0x34,0x30,0x36,0x34,0x35, - 0x30,0x36,0x34,0x36,0x30,0x36,0x34,0x37, - 0x30,0x36,0x34,0x38,0x30,0x36,0x34,0x39, - 0x30,0x36,0x35,0x30,0x30,0x36,0x35,0x31, - 0x30,0x36,0x35,0x32,0x30,0x36,0x35,0x33, - 0x30,0x36,0x35,0x34,0x30,0x36,0x35,0x35, - 0x30,0x36,0x35,0x36,0x30,0x36,0x35,0x37, - 0x30,0x36,0x35,0x38,0x30,0x36,0x35,0x39, - 0x30,0x36,0x36,0x30,0x30,0x36,0x36,0x31, - 0x30,0x36,0x36,0x32,0x30,0x36,0x36,0x33, - 0x30,0x36,0x36,0x34,0x30,0x36,0x36,0x35, - 0x30,0x36,0x36,0x36,0x30,0x36,0x36,0x37, - 0x30,0x36,0x36,0x38,0x30,0x36,0x36,0x39, - 0x30,0x36,0x37,0x30,0x30,0x36,0x37,0x31, - 0x30,0x36,0x37,0x32,0x30,0x36,0x37,0x33, - 0x30,0x36,0x37,0x34,0x30,0x36,0x37,0x35, - 0x30,0x36,0x37,0x36,0x30,0x36,0x37,0x37, - 0x30,0x36,0x37,0x38,0x30,0x36,0x37,0x39, - 0x30,0x36,0x38,0x30,0x30,0x36,0x38,0x31, - 0x30,0x36,0x38,0x32,0x30,0x36,0x38,0x33, - 0x30,0x36,0x38,0x34,0x30,0x36,0x38,0x35, - 0x30,0x36,0x38,0x36,0x30,0x36,0x38,0x37, - 0x30,0x36,0x38,0x38,0x30,0x36,0x38,0x39, - 0x30,0x36,0x39,0x30,0x30,0x36,0x39,0x31, - 0x30,0x36,0x39,0x32,0x30,0x36,0x39,0x33, - 0x30,0x36,0x39,0x34,0x30,0x36,0x39,0x35, - 0x30,0x36,0x39,0x36,0x30,0x36,0x39,0x37, - 0x30,0x36,0x39,0x38,0x30,0x36,0x39,0x39, - 0x30,0x37,0x30,0x30,0x30,0x37,0x30,0x31, - 0x30,0x37,0x30,0x32,0x30,0x37,0x30,0x33, - 0x30,0x37,0x30,0x34,0x30,0x37,0x30,0x35, - 0x30,0x37,0x30,0x36,0x30,0x37,0x30,0x37, - 0x30,0x37,0x30,0x38,0x30,0x37,0x30,0x39, - 0x30,0x37,0x31,0x30,0x30,0x37,0x31,0x31, - 0x30,0x37,0x31,0x32,0x30,0x37,0x31,0x33, - 0x30,0x37,0x31,0x34,0x30,0x37,0x31,0x35, - 0x30,0x37,0x31,0x36,0x30,0x37,0x31,0x37, - 0x30,0x37,0x31,0x38,0x30,0x37,0x31,0x39, - 0x30,0x37,0x32,0x30,0x30,0x37,0x32,0x31, - 0x30,0x37,0x32,0x32,0x30,0x37,0x32,0x33, - 0x30,0x37,0x32,0x34,0x30,0x37,0x32,0x35, - 0x30,0x37,0x32,0x36,0x30,0x37,0x32,0x37, - 0x30,0x37,0x32,0x38,0x30,0x37,0x32,0x39, - 0x30,0x37,0x33,0x30,0x30,0x37,0x33,0x31, - 0x30,0x37,0x33,0x32,0x30,0x37,0x33,0x33, - 0x30,0x37,0x33,0x34,0x30,0x37,0x33,0x35, - 0x30,0x37,0x33,0x36,0x30,0x37,0x33,0x37, - 0x30,0x37,0x33,0x38,0x30,0x37,0x33,0x39, - 0x30,0x37,0x34,0x30,0x30,0x37,0x34,0x31, - 0x30,0x37,0x34,0x32,0x30,0x37,0x34,0x33, - 0x30,0x37,0x34,0x34,0x30,0x37,0x34,0x35, - 0x30,0x37,0x34,0x36,0x30,0x37,0x34,0x37, - 0x30,0x37,0x34,0x38,0x30,0x37,0x34,0x39, - 0x30,0x37,0x35,0x30,0x30,0x37,0x35,0x31, - 0x30,0x37,0x35,0x32,0x30,0x37,0x35,0x33, - 0x30,0x37,0x35,0x34,0x30,0x37,0x35,0x35, - 0x30,0x37,0x35,0x36,0x30,0x37,0x35,0x37, - 0x30,0x37,0x35,0x38,0x30,0x37,0x35,0x39, - 0x30,0x37,0x36,0x30,0x30,0x37,0x36,0x31, - 0x30,0x37,0x36,0x32,0x30,0x37,0x36,0x33, - 0x30,0x37,0x36,0x34,0x30,0x37,0x36,0x35, - 0x30,0x37,0x36,0x36,0x30,0x37,0x36,0x37, - 0x30,0x37,0x36,0x38,0x30,0x37,0x36,0x39, - 0x30,0x37,0x37,0x30,0x30,0x37,0x37,0x31, - 0x30,0x37,0x37,0x32,0x30,0x37,0x37,0x33, - 0x30,0x37,0x37,0x34,0x30,0x37,0x37,0x35, - 0x30,0x37,0x37,0x36,0x30,0x37,0x37,0x37, - 0x30,0x37,0x37,0x38,0x30,0x37,0x37,0x39, - 0x30,0x37,0x38,0x30,0x30,0x37,0x38,0x31, - 0x30,0x37,0x38,0x32,0x30,0x37,0x38,0x33, - 0x30,0x37,0x38,0x34,0x30,0x37,0x38,0x35, - 0x30,0x37,0x38,0x36,0x30,0x37,0x38,0x37, - 0x30,0x37,0x38,0x38,0x30,0x37,0x38,0x39, - 0x30,0x37,0x39,0x30,0x30,0x37,0x39,0x31, - 0x30,0x37,0x39,0x32,0x30,0x37,0x39,0x33, - 0x30,0x37,0x39,0x34,0x30,0x37,0x39,0x35, - 0x30,0x37,0x39,0x36,0x30,0x37,0x39,0x37, - 0x30,0x37,0x39,0x38,0x30,0x37,0x39,0x39, - 0x30,0x38,0x30,0x30,0x30,0x38,0x30,0x31, - 0x30,0x38,0x30,0x32,0x30,0x38,0x30,0x33, - 0x30,0x38,0x30,0x34,0x30,0x38,0x30,0x35, - 0x30,0x38,0x30,0x36,0x30,0x38,0x30,0x37, - 0x30,0x38,0x30,0x38,0x30,0x38,0x30,0x39, - 0x30,0x38,0x31,0x30,0x30,0x38,0x31,0x31, - 0x30,0x38,0x31,0x32,0x30,0x38,0x31,0x33, - 0x30,0x38,0x31,0x34,0x30,0x38,0x31,0x35, - 0x30,0x38,0x31,0x36,0x30,0x38,0x31,0x37, - 0x30,0x38,0x31,0x38,0x30,0x38,0x31,0x39, - 0x30,0x38,0x32,0x30,0x30,0x38,0x32,0x31, - 0x30,0x38,0x32,0x32,0x30,0x38,0x32,0x33, - 0x30,0x38,0x32,0x34,0x30,0x38,0x32,0x35, - 0x30,0x38,0x32,0x36,0x30,0x38,0x32,0x37, - 0x30,0x38,0x32,0x38,0x30,0x38,0x32,0x39, - 0x30,0x38,0x33,0x30,0x30,0x38,0x33,0x31, - 0x30,0x38,0x33,0x32,0x30,0x38,0x33,0x33, - 0x30,0x38,0x33,0x34,0x30,0x38,0x33,0x35, - 0x30,0x38,0x33,0x36,0x30,0x38,0x33,0x37, - 0x30,0x38,0x33,0x38,0x30,0x38,0x33,0x39, - 0x30,0x38,0x34,0x30,0x30,0x38,0x34,0x31, - 0x30,0x38,0x34,0x32,0x30,0x38,0x34,0x33, - 0x30,0x38,0x34,0x34,0x30,0x38,0x34,0x35, - 0x30,0x38,0x34,0x36,0x30,0x38,0x34,0x37, - 0x30,0x38,0x34,0x38,0x30,0x38,0x34,0x39, - 0x30,0x38,0x35,0x30,0x30,0x38,0x35,0x31, - 0x30,0x38,0x35,0x32,0x30,0x38,0x35,0x33, - 0x30,0x38,0x35,0x34,0x30,0x38,0x35,0x35, - 0x30,0x38,0x35,0x36,0x30,0x38,0x35,0x37, - 0x30,0x38,0x35,0x38,0x30,0x38,0x35,0x39, - 0x30,0x38,0x36,0x30,0x30,0x38,0x36,0x31, - 0x30,0x38,0x36,0x32,0x30,0x38,0x36,0x33, - 0x30,0x38,0x36,0x34,0x30,0x38,0x36,0x35, - 0x30,0x38,0x36,0x36,0x30,0x38,0x36,0x37, - 0x30,0x38,0x36,0x38,0x30,0x38,0x36,0x39, - 0x30,0x38,0x37,0x30,0x30,0x38,0x37,0x31, - 0x30,0x38,0x37,0x32,0x30,0x38,0x37,0x33, - 0x30,0x38,0x37,0x34,0x30,0x38,0x37,0x35, - 0x30,0x38,0x37,0x36,0x30,0x38,0x37,0x37, - 0x30,0x38,0x37,0x38,0x30,0x38,0x37,0x39, - 0x30,0x38,0x38,0x30,0x30,0x38,0x38,0x31, - 0x30,0x38,0x38,0x32,0x30,0x38,0x38,0x33, - 0x30,0x38,0x38,0x34,0x30,0x38,0x38,0x35, - 0x30,0x38,0x38,0x36,0x30,0x38,0x38,0x37, - 0x30,0x38,0x38,0x38,0x30,0x38,0x38,0x39, - 0x30,0x38,0x39,0x30,0x30,0x38,0x39,0x31, - 0x30,0x38,0x39,0x32,0x30,0x38,0x39,0x33, - 0x30,0x38,0x39,0x34,0x30,0x38,0x39,0x35, - 0x30,0x38,0x39,0x36,0x30,0x38,0x39,0x37, - 0x30,0x38,0x39,0x38,0x30,0x38,0x39,0x39, - 0x30,0x39,0x30,0x30,0x30,0x39,0x30,0x31, - 0x30,0x39,0x30,0x32,0x30,0x39,0x30,0x33, - 0x30,0x39,0x30,0x34,0x30,0x39,0x30,0x35, - 0x30,0x39,0x30,0x36,0x30,0x39,0x30,0x37, - 0x30,0x39,0x30,0x38,0x30,0x39,0x30,0x39, - 0x30,0x39,0x31,0x30,0x30,0x39,0x31,0x31, - 0x30,0x39,0x31,0x32,0x30,0x39,0x31,0x33, - 0x30,0x39,0x31,0x34,0x30,0x39,0x31,0x35, - 0x30,0x39,0x31,0x36,0x30,0x39,0x31,0x37, - 0x30,0x39,0x31,0x38,0x30,0x39,0x31,0x39, - 0x30,0x39,0x32,0x30,0x30,0x39,0x32,0x31, - 0x30,0x39,0x32,0x32,0x30,0x39,0x32,0x33, - 0x30,0x39,0x32,0x34,0x30,0x39,0x32,0x35, - 0x30,0x39,0x32,0x36,0x30,0x39,0x32,0x37, - 0x30,0x39,0x32,0x38,0x30,0x39,0x32,0x39, - 0x30,0x39,0x33,0x30,0x30,0x39,0x33,0x31, - 0x30,0x39,0x33,0x32,0x30,0x39,0x33,0x33, - 0x30,0x39,0x33,0x34,0x30,0x39,0x33,0x35, - 0x30,0x39,0x33,0x36,0x30,0x39,0x33,0x37, - 0x30,0x39,0x33,0x38,0x30,0x39,0x33,0x39, - 0x30,0x39,0x34,0x30,0x30,0x39,0x34,0x31, - 0x30,0x39,0x34,0x32,0x30,0x39,0x34,0x33, - 0x30,0x39,0x34,0x34,0x30,0x39,0x34,0x35, - 0x30,0x39,0x34,0x36,0x30,0x39,0x34,0x37, - 0x30,0x39,0x34,0x38,0x30,0x39,0x34,0x39, - 0x30,0x39,0x35,0x30,0x30,0x39,0x35,0x31, - 0x30,0x39,0x35,0x32,0x30,0x39,0x35,0x33, - 0x30,0x39,0x35,0x34,0x30,0x39,0x35,0x35, - 0x30,0x39,0x35,0x36,0x30,0x39,0x35,0x37, - 0x30,0x39,0x35,0x38,0x30,0x39,0x35,0x39, - 0x30,0x39,0x36,0x30,0x30,0x39,0x36,0x31, - 0x30,0x39,0x36,0x32,0x30,0x39,0x36,0x33, - 0x30,0x39,0x36,0x34,0x30,0x39,0x36,0x35, - 0x30,0x39,0x36,0x36,0x30,0x39,0x36,0x37, - 0x30,0x39,0x36,0x38,0x30,0x39,0x36,0x39, - 0x30,0x39,0x37,0x30,0x30,0x39,0x37,0x31, - 0x30,0x39,0x37,0x32,0x30,0x39,0x37,0x33, - 0x30,0x39,0x37,0x34,0x30,0x39,0x37,0x35, - 0x30,0x39,0x37,0x36,0x30,0x39,0x37,0x37, - 0x30,0x39,0x37,0x38,0x30,0x39,0x37,0x39, - 0x30,0x39,0x38,0x30,0x30,0x39,0x38,0x31, - 0x30,0x39,0x38,0x32,0x30,0x39,0x38,0x33, - 0x30,0x39,0x38,0x34,0x30,0x39,0x38,0x35, - 0x30,0x39,0x38,0x36,0x30,0x39,0x38,0x37, - 0x30,0x39,0x38,0x38,0x30,0x39,0x38,0x39, - 0x30,0x39,0x39,0x30,0x30,0x39,0x39,0x31, - 0x30,0x39,0x39,0x32,0x30,0x39,0x39,0x33, - 0x30,0x39,0x39,0x34,0x30,0x39,0x39,0x35, - 0x30,0x39,0x39,0x36,0x30,0x39,0x39,0x37, - 0x30,0x39,0x39,0x38,0x30,0x39,0x39,0x39, - 0x31,0x30,0x30,0x30,0x31,0x30,0x30,0x31, - 0x31,0x30,0x30,0x32,0x31,0x30,0x30,0x33, - 0x31,0x30,0x30,0x34,0x31,0x30,0x30,0x35, - 0x31,0x30,0x30,0x36,0x31,0x30,0x30,0x37, - 0x31,0x30,0x30,0x38,0x31,0x30,0x30,0x39, - 0x31,0x30,0x31,0x30,0x31,0x30,0x31,0x31, - 0x31,0x30,0x31,0x32,0x31,0x30,0x31,0x33, - 0x31,0x30,0x31,0x34,0x31,0x30,0x31,0x35, - 0x31,0x30,0x31,0x36,0x31,0x30,0x31,0x37, - 0x31,0x30,0x31,0x38,0x31,0x30,0x31,0x39, - 0x31,0x30,0x32,0x30,0x31,0x30,0x32,0x31, - 0x31,0x30,0x32,0x32,0x31,0x30,0x32,0x33, - 0x31,0x30,0x32,0x34,0x31,0x30,0x32,0x35, - 0x31,0x30,0x32,0x36,0x31,0x30,0x32,0x37, - 0x31,0x30,0x32,0x38,0x31,0x30,0x32,0x39, - 0x31,0x30,0x33,0x30,0x31,0x30,0x33,0x31, - 0x31,0x30,0x33,0x32,0x31,0x30,0x33,0x33, - 0x31,0x30,0x33,0x34,0x31,0x30,0x33,0x35, - 0x31,0x30,0x33,0x36,0x31,0x30,0x33,0x37, - 0x31,0x30,0x33,0x38,0x31,0x30,0x33,0x39, - 0x31,0x30,0x34,0x30,0x31,0x30,0x34,0x31, - 0x31,0x30,0x34,0x32,0x31,0x30,0x34,0x33, - 0x31,0x30,0x34,0x34,0x31,0x30,0x34,0x35, - 0x31,0x30,0x34,0x36,0x31,0x30,0x34,0x37, - 0x31,0x30,0x34,0x38,0x31,0x30,0x34,0x39, - 0x31,0x30,0x35,0x30,0x31,0x30,0x35,0x31, - 0x31,0x30,0x35,0x32,0x31,0x30,0x35,0x33, - 0x31,0x30,0x35,0x34,0x31,0x30,0x35,0x35, - 0x31,0x30,0x35,0x36,0x31,0x30,0x35,0x37, - 0x31,0x30,0x35,0x38,0x31,0x30,0x35,0x39, - 0x31,0x30,0x36,0x30,0x31,0x30,0x36,0x31, - 0x31,0x30,0x36,0x32,0x31,0x30,0x36,0x33, - 0x31,0x30,0x36,0x34,0x31,0x30,0x36,0x35, - 0x31,0x30,0x36,0x36,0x31,0x30,0x36,0x37, - 0x31,0x30,0x36,0x38,0x31,0x30,0x36,0x39, - 0x31,0x30,0x37,0x30,0x31,0x30,0x37,0x31, - 0x31,0x30,0x37,0x32,0x31,0x30,0x37,0x33, - 0x31,0x30,0x37,0x34,0x31,0x30,0x37,0x35, - 0x31,0x30,0x37,0x36,0x31,0x30,0x37,0x37, - 0x31,0x30,0x37,0x38,0x31,0x30,0x37,0x39, - 0x31,0x30,0x38,0x30,0x31,0x30,0x38,0x31, - 0x31,0x30,0x38,0x32,0x31,0x30,0x38,0x33, - 0x31,0x30,0x38,0x34,0x31,0x30,0x38,0x35, - 0x31,0x30,0x38,0x36,0x31,0x30,0x38,0x37, - 0x31,0x30,0x38,0x38,0x31,0x30,0x38,0x39, - 0x31,0x30,0x39,0x30,0x31,0x30,0x39,0x31, - 0x31,0x30,0x39,0x32,0x31,0x30,0x39,0x33, - 0x31,0x30,0x39,0x34,0x31,0x30,0x39,0x35, - 0x31,0x30,0x39,0x36,0x31,0x30,0x39,0x37, - 0x31,0x30,0x39,0x38,0x31,0x30,0x39,0x39, - 0x31,0x31,0x30,0x30,0x31,0x31,0x30,0x31, - 0x31,0x31,0x30,0x32,0x31,0x31,0x30,0x33, - 0x31,0x31,0x30,0x34,0x31,0x31,0x30,0x35, - 0x31,0x31,0x30,0x36,0x31,0x31,0x30,0x37, - 0x31,0x31,0x30,0x38,0x31,0x31,0x30,0x39, - 0x31,0x31,0x31,0x30,0x31,0x31,0x31,0x31, - 0x31,0x31,0x31,0x32,0x31,0x31,0x31,0x33, - 0x31,0x31,0x31,0x34,0x31,0x31,0x31,0x35, - 0x31,0x31,0x31,0x36,0x31,0x31,0x31,0x37, - 0x31,0x31,0x31,0x38,0x31,0x31,0x31,0x39, - 0x31,0x31,0x32,0x30,0x31,0x31,0x32,0x31, - 0x31,0x31,0x32,0x32,0x31,0x31,0x32,0x33, - 0x31,0x31,0x32,0x34,0x31,0x31,0x32,0x35, - 0x31,0x31,0x32,0x36,0x31,0x31,0x32,0x37, - 0x31,0x31,0x32,0x38,0x31,0x31,0x32,0x39, - 0x31,0x31,0x33,0x30,0x31,0x31,0x33,0x31, - 0x31,0x31,0x33,0x32,0x31,0x31,0x33,0x33, - 0x31,0x31,0x33,0x34,0x31,0x31,0x33,0x35, - 0x31,0x31,0x33,0x36,0x31,0x31,0x33,0x37, - 0x31,0x31,0x33,0x38,0x31,0x31,0x33,0x39, - 0x31,0x31,0x34,0x30,0x31,0x31,0x34,0x31, - 0x31,0x31,0x34,0x32,0x31,0x31,0x34,0x33, - 0x31,0x31,0x34,0x34,0x31,0x31,0x34,0x35, - 0x31,0x31,0x34,0x36,0x31,0x31,0x34,0x37, - 0x31,0x31,0x34,0x38,0x31,0x31,0x34,0x39, - 0x31,0x31,0x35,0x30,0x31,0x31,0x35,0x31, - 0x31,0x31,0x35,0x32,0x31,0x31,0x35,0x33, - 0x31,0x31,0x35,0x34,0x31,0x31,0x35,0x35, - 0x31,0x31,0x35,0x36,0x31,0x31,0x35,0x37, - 0x31,0x31,0x35,0x38,0x31,0x31,0x35,0x39, - 0x31,0x31,0x36,0x30,0x31,0x31,0x36,0x31, - 0x31,0x31,0x36,0x32,0x31,0x31,0x36,0x33, - 0x31,0x31,0x36,0x34,0x31,0x31,0x36,0x35, - 0x31,0x31,0x36,0x36,0x31,0x31,0x36,0x37, - 0x31,0x31,0x36,0x38,0x31,0x31,0x36,0x39, - 0x31,0x31,0x37,0x30,0x31,0x31,0x37,0x31, - 0x31,0x31,0x37,0x32,0x31,0x31,0x37,0x33, - 0x31,0x31,0x37,0x34,0x31,0x31,0x37,0x35, - 0x31,0x31,0x37,0x36,0x31,0x31,0x37,0x37, - 0x31,0x31,0x37,0x38,0x31,0x31,0x37,0x39, - 0x31,0x31,0x38,0x30,0x31,0x31,0x38,0x31, - 0x31,0x31,0x38,0x32,0x31,0x31,0x38,0x33, - 0x31,0x31,0x38,0x34,0x31,0x31,0x38,0x35, - 0x31,0x31,0x38,0x36,0x31,0x31,0x38,0x37, - 0x31,0x31,0x38,0x38,0x31,0x31,0x38,0x39, - 0x31,0x31,0x39,0x30,0x31,0x31,0x39,0x31, - 0x31,0x31,0x39,0x32,0x31,0x31,0x39,0x33, - 0x31,0x31,0x39,0x34,0x31,0x31,0x39,0x35, - 0x31,0x31,0x39,0x36,0x31,0x31,0x39,0x37, - 0x31,0x31,0x39,0x38,0x31,0x31,0x39,0x39, - 0x31,0x32,0x30,0x30,0x31,0x32,0x30,0x31, - 0x31,0x32,0x30,0x32,0x31,0x32,0x30,0x33, - 0x31,0x32,0x30,0x34,0x31,0x32,0x30,0x35, - 0x31,0x32,0x30,0x36,0x31,0x32,0x30,0x37, - 0x31,0x32,0x30,0x38,0x31,0x32,0x30,0x39, - 0x31,0x32,0x31,0x30,0x31,0x32,0x31,0x31, - 0x31,0x32,0x31,0x32,0x31,0x32,0x31,0x33, - 0x31,0x32,0x31,0x34,0x31,0x32,0x31,0x35, - 0x31,0x32,0x31,0x36,0x31,0x32,0x31,0x37, - 0x31,0x32,0x31,0x38,0x31,0x32,0x31,0x39, - 0x31,0x32,0x32,0x30,0x31,0x32,0x32,0x31, - 0x31,0x32,0x32,0x32,0x31,0x32,0x32,0x33, - 0x31,0x32,0x32,0x34,0x31,0x32,0x32,0x35, - 0x31,0x32,0x32,0x36,0x31,0x32,0x32,0x37, - 0x31,0x32,0x32,0x38,0x31,0x32,0x32,0x39, - 0x31,0x32,0x33,0x30,0x31,0x32,0x33,0x31, - 0x31,0x32,0x33,0x32,0x31,0x32,0x33,0x33, - 0x31,0x32,0x33,0x34,0x31,0x32,0x33,0x35, - 0x31,0x32,0x33,0x36,0x31,0x32,0x33,0x37, - 0x31,0x32,0x33,0x38,0x31,0x32,0x33,0x39, - 0x31,0x32,0x34,0x30,0x31,0x32,0x34,0x31, - 0x31,0x32,0x34,0x32,0x31,0x32,0x34,0x33, - 0x31,0x32,0x34,0x34,0x31,0x32,0x34,0x35, - 0x31,0x32,0x34,0x36,0x31,0x32,0x34,0x37, - 0x31,0x32,0x34,0x38,0x31,0x32,0x34,0x39, - 0x31,0x32,0x35,0x30,0x31,0x32,0x35,0x31, - 0x31,0x32,0x35,0x32,0x31,0x32,0x35,0x33, - 0x31,0x32,0x35,0x34,0x31,0x32,0x35,0x35, - 0x31,0x32,0x35,0x36,0x31,0x32,0x35,0x37, - 0x31,0x32,0x35,0x38,0x31,0x32,0x35,0x39, - 0x31,0x32,0x36,0x30,0x31,0x32,0x36,0x31, - 0x31,0x32,0x36,0x32,0x31,0x32,0x36,0x33, - 0x31,0x32,0x36,0x34,0x31,0x32,0x36,0x35, - 0x31,0x32,0x36,0x36,0x31,0x32,0x36,0x37, - 0x31,0x32,0x36,0x38,0x31,0x32,0x36,0x39, - 0x31,0x32,0x37,0x30,0x31,0x32,0x37,0x31, - 0x31,0x32,0x37,0x32,0x31,0x32,0x37,0x33, - 0x31,0x32,0x37,0x34,0x31,0x32,0x37,0x35, - 0x31,0x32,0x37,0x36,0x31,0x32,0x37,0x37, - 0x31,0x32,0x37,0x38,0x31,0x32,0x37,0x39, - 0x31,0x32,0x38,0x30,0x31,0x32,0x38,0x31, - 0x31,0x32,0x38,0x32,0x31,0x32,0x38,0x33, - 0x31,0x32,0x38,0x34,0x31,0x32,0x38,0x35, - 0x31,0x32,0x38,0x36,0x31,0x32,0x38,0x37, - 0x31,0x32,0x38,0x38,0x31,0x32,0x38,0x39, - 0x31,0x32,0x39,0x30,0x31,0x32,0x39,0x31, - 0x31,0x32,0x39,0x32,0x31,0x32,0x39,0x33, - 0x31,0x32,0x39,0x34,0x31,0x32,0x39,0x35, - 0x31,0x32,0x39,0x36,0x31,0x32,0x39,0x37, - 0x31,0x32,0x39,0x38,0x31,0x32,0x39,0x39, - 0x31,0x33,0x30,0x30,0x31,0x33,0x30,0x31, - 0x31,0x33,0x30,0x32,0x31,0x33,0x30,0x33, - 0x31,0x33,0x30,0x34,0x31,0x33,0x30,0x35, - 0x31,0x33,0x30,0x36,0x31,0x33,0x30,0x37, - 0x31,0x33,0x30,0x38,0x31,0x33,0x30,0x39, - 0x31,0x33,0x31,0x30,0x31,0x33,0x31,0x31, - 0x31,0x33,0x31,0x32,0x31,0x33,0x31,0x33, - 0x31,0x33,0x31,0x34,0x31,0x33,0x31,0x35, - 0x31,0x33,0x31,0x36,0x31,0x33,0x31,0x37, - 0x31,0x33,0x31,0x38,0x31,0x33,0x31,0x39, - 0x31,0x33,0x32,0x30,0x31,0x33,0x32,0x31, - 0x31,0x33,0x32,0x32,0x31,0x33,0x32,0x33, - 0x31,0x33,0x32,0x34,0x31,0x33,0x32,0x35, - 0x31,0x33,0x32,0x36,0x31,0x33,0x32,0x37, - 0x31,0x33,0x32,0x38,0x31,0x33,0x32,0x39, - 0x31,0x33,0x33,0x30,0x31,0x33,0x33,0x31, - 0x31,0x33,0x33,0x32,0x31,0x33,0x33,0x33, - 0x31,0x33,0x33,0x34,0x31,0x33,0x33,0x35, - 0x31,0x33,0x33,0x36,0x31,0x33,0x33,0x37, - 0x31,0x33,0x33,0x38,0x31,0x33,0x33,0x39, - 0x31,0x33,0x34,0x30,0x31,0x33,0x34,0x31, - 0x31,0x33,0x34,0x32,0x31,0x33,0x34,0x33, - 0x31,0x33,0x34,0x34,0x31,0x33,0x34,0x35, - 0x31,0x33,0x34,0x36,0x31,0x33,0x34,0x37, - 0x31,0x33,0x34,0x38,0x31,0x33,0x34,0x39, - 0x31,0x33,0x35,0x30,0x31,0x33,0x35,0x31, - 0x31,0x33,0x35,0x32,0x31,0x33,0x35,0x33, - 0x31,0x33,0x35,0x34,0x31,0x33,0x35,0x35, - 0x31,0x33,0x35,0x36,0x31,0x33,0x35,0x37, - 0x31,0x33,0x35,0x38,0x31,0x33,0x35,0x39, - 0x31,0x33,0x36,0x30,0x31,0x33,0x36,0x31, - 0x31,0x33,0x36,0x32,0x31,0x33,0x36,0x33, - 0x31,0x33,0x36,0x34,0x31,0x33,0x36,0x35, - 0x31,0x33,0x36,0x36,0x31,0x33,0x36,0x37, - 0x31,0x33,0x36,0x38,0x31,0x33,0x36,0x39, - 0x31,0x33,0x37,0x30,0x31,0x33,0x37,0x31, - 0x31,0x33,0x37,0x32,0x31,0x33,0x37,0x33, - 0x31,0x33,0x37,0x34,0x31,0x33,0x37,0x35, - 0x31,0x33,0x37,0x36,0x31,0x33,0x37,0x37, - 0x31,0x33,0x37,0x38,0x31,0x33,0x37,0x39, - 0x31,0x33,0x38,0x30,0x31,0x33,0x38,0x31, - 0x31,0x33,0x38,0x32,0x31,0x33,0x38,0x33, - 0x31,0x33,0x38,0x34,0x31,0x33,0x38,0x35, - 0x31,0x33,0x38,0x36,0x31,0x33,0x38,0x37, - 0x31,0x33,0x38,0x38,0x31,0x33,0x38,0x39, - 0x31,0x33,0x39,0x30,0x31,0x33,0x39,0x31, - 0x31,0x33,0x39,0x32,0x31,0x33,0x39,0x33, - 0x31,0x33,0x39,0x34,0x31,0x33,0x39,0x35, - 0x31,0x33,0x39,0x36,0x31,0x33,0x39,0x37, - 0x31,0x33,0x39,0x38,0x31,0x33,0x39,0x39, - 0x31,0x34,0x30,0x30,0x31,0x34,0x30,0x31, - 0x31,0x34,0x30,0x32,0x31,0x34,0x30,0x33, - 0x31,0x34,0x30,0x34,0x31,0x34,0x30,0x35, - 0x31,0x34,0x30,0x36,0x31,0x34,0x30,0x37, - 0x31,0x34,0x30,0x38,0x31,0x34,0x30,0x39, - 0x31,0x34,0x31,0x30,0x31,0x34,0x31,0x31, - 0x31,0x34,0x31,0x32,0x31,0x34,0x31,0x33, - 0x31,0x34,0x31,0x34,0x31,0x34,0x31,0x35, - 0x31,0x34,0x31,0x36,0x31,0x34,0x31,0x37, - 0x31,0x34,0x31,0x38,0x31,0x34,0x31,0x39, - 0x31,0x34,0x32,0x30,0x31,0x34,0x32,0x31, - 0x31,0x34,0x32,0x32,0x31,0x34,0x32,0x33, - 0x31,0x34,0x32,0x34,0x31,0x34,0x32,0x35, - 0x31,0x34,0x32,0x36,0x31,0x34,0x32,0x37, - 0x31,0x34,0x32,0x38,0x31,0x34,0x32,0x39, - 0x31,0x34,0x33,0x30,0x31,0x34,0x33,0x31, - 0x31,0x34,0x33,0x32,0x31,0x34,0x33,0x33, - 0x31,0x34,0x33,0x34,0x31,0x34,0x33,0x35, - 0x31,0x34,0x33,0x36,0x31,0x34,0x33,0x37, - 0x31,0x34,0x33,0x38,0x31,0x34,0x33,0x39, - 0x31,0x34,0x34,0x30,0x31,0x34,0x34,0x31, - 0x31,0x34,0x34,0x32,0x31,0x34,0x34,0x33, - 0x31,0x34,0x34,0x34,0x31,0x34,0x34,0x35, - 0x31,0x34,0x34,0x36,0x31,0x34,0x34,0x37, - 0x31,0x34,0x34,0x38,0x31,0x34,0x34,0x39, - 0x31,0x34,0x35,0x30,0x31,0x34,0x35,0x31, - 0x31,0x34,0x35,0x32,0x31,0x34,0x35,0x33, - 0x31,0x34,0x35,0x34,0x31,0x34,0x35,0x35, - 0x31,0x34,0x35,0x36,0x31,0x34,0x35,0x37, - 0x31,0x34,0x35,0x38,0x31,0x34,0x35,0x39, - 0x31,0x34,0x36,0x30,0x31,0x34,0x36,0x31, - 0x31,0x34,0x36,0x32,0x31,0x34,0x36,0x33, - 0x31,0x34,0x36,0x34,0x31,0x34,0x36,0x35, - 0x31,0x34,0x36,0x36,0x31,0x34,0x36,0x37, - 0x31,0x34,0x36,0x38,0x31,0x34,0x36,0x39, - 0x31,0x34,0x37,0x30,0x31,0x34,0x37,0x31, - 0x31,0x34,0x37,0x32,0x31,0x34,0x37,0x33, - 0x31,0x34,0x37,0x34,0x31,0x34,0x37,0x35, - 0x31,0x34,0x37,0x36,0x31,0x34,0x37,0x37, - 0x31,0x34,0x37,0x38,0x31,0x34,0x37,0x39, - 0x31,0x34,0x38,0x30,0x31,0x34,0x38,0x31, - 0x31,0x34,0x38,0x32,0x31,0x34,0x38,0x33, - 0x31,0x34,0x38,0x34,0x31,0x34,0x38,0x35, - 0x31,0x34,0x38,0x36,0x31,0x34,0x38,0x37, - 0x31,0x34,0x38,0x38,0x31,0x34,0x38,0x39, - 0x31,0x34,0x39,0x30,0x31,0x34,0x39,0x31, - 0x31,0x34,0x39,0x32,0x31,0x34,0x39,0x33, - 0x31,0x34,0x39,0x34,0x31,0x34,0x39,0x35, - 0x31,0x34,0x39,0x36,0x31,0x34,0x39,0x37, - 0x31,0x34,0x39,0x38,0x31,0x34,0x39,0x39, - 0x31,0x35,0x30,0x30,0x31,0x35,0x30,0x31, - 0x31,0x35,0x30,0x32,0x31,0x35,0x30,0x33, - 0x31,0x35,0x30,0x34,0x31,0x35,0x30,0x35, - 0x31,0x35,0x30,0x36,0x31,0x35,0x30,0x37, - 0x31,0x35,0x30,0x38,0x31,0x35,0x30,0x39, - 0x31,0x35,0x31,0x30,0x31,0x35,0x31,0x31, - 0x31,0x35,0x31,0x32,0x31,0x35,0x31,0x33, - 0x31,0x35,0x31,0x34,0x31,0x35,0x31,0x35, - 0x31,0x35,0x31,0x36,0x31,0x35,0x31,0x37, - 0x31,0x35,0x31,0x38,0x31,0x35,0x31,0x39, - 0x31,0x35,0x32,0x30,0x31,0x35,0x32,0x31, - 0x31,0x35,0x32,0x32,0x31,0x35,0x32,0x33, - 0x31,0x35,0x32,0x34,0x31,0x35,0x32,0x35, - 0x31,0x35,0x32,0x36,0x31,0x35,0x32,0x37, - 0x31,0x35,0x32,0x38,0x31,0x35,0x32,0x39, - 0x31,0x35,0x33,0x30,0x31,0x35,0x33,0x31, - 0x31,0x35,0x33,0x32,0x31,0x35,0x33,0x33, - 0x31,0x35,0x33,0x34,0x31,0x35,0x33,0x35, - 0x31,0x35,0x33,0x36,0x31,0x35,0x33,0x37, - 0x31,0x35,0x33,0x38,0x31,0x35,0x33,0x39, - 0x31,0x35,0x34,0x30,0x31,0x35,0x34,0x31, - 0x31,0x35,0x34,0x32,0x31,0x35,0x34,0x33, - 0x31,0x35,0x34,0x34,0x31,0x35,0x34,0x35, - 0x31,0x35,0x34,0x36,0x31,0x35,0x34,0x37, - 0x31,0x35,0x34,0x38,0x31,0x35,0x34,0x39, - 0x31,0x35,0x35,0x30,0x31,0x35,0x35,0x31, - 0x31,0x35,0x35,0x32,0x31,0x35,0x35,0x33, - 0x31,0x35,0x35,0x34,0x31,0x35,0x35,0x35, - 0x31,0x35,0x35,0x36,0x31,0x35,0x35,0x37, - 0x31,0x35,0x35,0x38,0x31,0x35,0x35,0x39, - 0x31,0x35,0x36,0x30,0x31,0x35,0x36,0x31, - 0x31,0x35,0x36,0x32,0x31,0x35,0x36,0x33, - 0x31,0x35,0x36,0x34,0x31,0x35,0x36,0x35, - 0x31,0x35,0x36,0x36,0x31,0x35,0x36,0x37, - 0x31,0x35,0x36,0x38,0x31,0x35,0x36,0x39, - 0x31,0x35,0x37,0x30,0x31,0x35,0x37,0x31, - 0x31,0x35,0x37,0x32,0x31,0x35,0x37,0x33, - 0x31,0x35,0x37,0x34,0x31,0x35,0x37,0x35, - 0x31,0x35,0x37,0x36,0x31,0x35,0x37,0x37, - 0x31,0x35,0x37,0x38,0x31,0x35,0x37,0x39, - 0x31,0x35,0x38,0x30,0x31,0x35,0x38,0x31, - 0x31,0x35,0x38,0x32,0x31,0x35,0x38,0x33, - 0x31,0x35,0x38,0x34,0x31,0x35,0x38,0x35, - 0x31,0x35,0x38,0x36,0x31,0x35,0x38,0x37, - 0x31,0x35,0x38,0x38,0x31,0x35,0x38,0x39, - 0x31,0x35,0x39,0x30,0x31,0x35,0x39,0x31, - 0x31,0x35,0x39,0x32,0x31,0x35,0x39,0x33, - 0x31,0x35,0x39,0x34,0x31,0x35,0x39,0x35, - 0x31,0x35,0x39,0x36,0x31,0x35,0x39,0x37, - 0x31,0x35,0x39,0x38,0x31,0x35,0x39,0x39, - 0x31,0x36,0x30,0x30,0x31,0x36,0x30,0x31, - 0x31,0x36,0x30,0x32,0x31,0x36,0x30,0x33, - 0x31,0x36,0x30,0x34,0x31,0x36,0x30,0x35, - 0x31,0x36,0x30,0x36,0x31,0x36,0x30,0x37, - 0x31,0x36,0x30,0x38,0x31,0x36,0x30,0x39, - 0x31,0x36,0x31,0x30,0x31,0x36,0x31,0x31, - 0x31,0x36,0x31,0x32,0x31,0x36,0x31,0x33, - 0x31,0x36,0x31,0x34,0x31,0x36,0x31,0x35, - 0x31,0x36,0x31,0x36,0x31,0x36,0x31,0x37, - 0x31,0x36,0x31,0x38,0x31,0x36,0x31,0x39, - 0x31,0x36,0x32,0x30,0x31,0x36,0x32,0x31, - 0x31,0x36,0x32,0x32,0x31,0x36,0x32,0x33, - 0x31,0x36,0x32,0x34,0x31,0x36,0x32,0x35, - 0x31,0x36,0x32,0x36,0x31,0x36,0x32,0x37, - 0x31,0x36,0x32,0x38,0x31,0x36,0x32,0x39, - 0x31,0x36,0x33,0x30,0x31,0x36,0x33,0x31, - 0x31,0x36,0x33,0x32,0x31,0x36,0x33,0x33, - 0x31,0x36,0x33,0x34,0x31,0x36,0x33,0x35, - 0x31,0x36,0x33,0x36,0x31,0x36,0x33,0x37, - 0x31,0x36,0x33,0x38,0x31,0x36,0x33,0x39, - 0x31,0x36,0x34,0x30,0x31,0x36,0x34,0x31, - 0x31,0x36,0x34,0x32,0x31,0x36,0x34,0x33, - 0x31,0x36,0x34,0x34,0x31,0x36,0x34,0x35, - 0x31,0x36,0x34,0x36,0x31,0x36,0x34,0x37, - 0x31,0x36,0x34,0x38,0x31,0x36,0x34,0x39, - 0x31,0x36,0x35,0x30,0x31,0x36,0x35,0x31, - 0x31,0x36,0x35,0x32,0x31,0x36,0x35,0x33, - 0x31,0x36,0x35,0x34,0x31,0x36,0x35,0x35, - 0x31,0x36,0x35,0x36,0x31,0x36,0x35,0x37, - 0x31,0x36,0x35,0x38,0x31,0x36,0x35,0x39, - 0x31,0x36,0x36,0x30,0x31,0x36,0x36,0x31, - 0x31,0x36,0x36,0x32,0x31,0x36,0x36,0x33, - 0x31,0x36,0x36,0x34,0x31,0x36,0x36,0x35, - 0x31,0x36,0x36,0x36,0x31,0x36,0x36,0x37, - 0x31,0x36,0x36,0x38,0x31,0x36,0x36,0x39, - 0x31,0x36,0x37,0x30,0x31,0x36,0x37,0x31, - 0x31,0x36,0x37,0x32,0x31,0x36,0x37,0x33, - 0x31,0x36,0x37,0x34,0x31,0x36,0x37,0x35, - 0x31,0x36,0x37,0x36,0x31,0x36,0x37,0x37, - 0x31,0x36,0x37,0x38,0x31,0x36,0x37,0x39, - 0x31,0x36,0x38,0x30,0x31,0x36,0x38,0x31, - 0x31,0x36,0x38,0x32,0x31,0x36,0x38,0x33, - 0x31,0x36,0x38,0x34,0x31,0x36,0x38,0x35, - 0x31,0x36,0x38,0x36,0x31,0x36,0x38,0x37, - 0x31,0x36,0x38,0x38,0x31,0x36,0x38,0x39, - 0x31,0x36,0x39,0x30,0x31,0x36,0x39,0x31, - 0x31,0x36,0x39,0x32,0x31,0x36,0x39,0x33, - 0x31,0x36,0x39,0x34,0x31,0x36,0x39,0x35, - 0x31,0x36,0x39,0x36,0x31,0x36,0x39,0x37, - 0x31,0x36,0x39,0x38,0x31,0x36,0x39,0x39, - 0x31,0x37,0x30,0x30,0x31,0x37,0x30,0x31, - 0x31,0x37,0x30,0x32,0x31,0x37,0x30,0x33, - 0x31,0x37,0x30,0x34,0x31,0x37,0x30,0x35, - 0x31,0x37,0x30,0x36,0x31,0x37,0x30,0x37, - 0x31,0x37,0x30,0x38,0x31,0x37,0x30,0x39, - 0x31,0x37,0x31,0x30,0x31,0x37,0x31,0x31, - 0x31,0x37,0x31,0x32,0x31,0x37,0x31,0x33, - 0x31,0x37,0x31,0x34,0x31,0x37,0x31,0x35, - 0x31,0x37,0x31,0x36,0x31,0x37,0x31,0x37, - 0x31,0x37,0x31,0x38,0x31,0x37,0x31,0x39, - 0x31,0x37,0x32,0x30,0x31,0x37,0x32,0x31, - 0x31,0x37,0x32,0x32,0x31,0x37,0x32,0x33, - 0x31,0x37,0x32,0x34,0x31,0x37,0x32,0x35, - 0x31,0x37,0x32,0x36,0x31,0x37,0x32,0x37, - 0x31,0x37,0x32,0x38,0x31,0x37,0x32,0x39, - 0x31,0x37,0x33,0x30,0x31,0x37,0x33,0x31, - 0x31,0x37,0x33,0x32,0x31,0x37,0x33,0x33, - 0x31,0x37,0x33,0x34,0x31,0x37,0x33,0x35, - 0x31,0x37,0x33,0x36,0x31,0x37,0x33,0x37, - 0x31,0x37,0x33,0x38,0x31,0x37,0x33,0x39, - 0x31,0x37,0x34,0x30,0x31,0x37,0x34,0x31, - 0x31,0x37,0x34,0x32,0x31,0x37,0x34,0x33, - 0x31,0x37,0x34,0x34,0x31,0x37,0x34,0x35, - 0x31,0x37,0x34,0x36,0x31,0x37,0x34,0x37, - 0x31,0x37,0x34,0x38,0x31,0x37,0x34,0x39, - 0x31,0x37,0x35,0x30,0x31,0x37,0x35,0x31, - 0x31,0x37,0x35,0x32,0x31,0x37,0x35,0x33, - 0x31,0x37,0x35,0x34,0x31,0x37,0x35,0x35, - 0x31,0x37,0x35,0x36,0x31,0x37,0x35,0x37, - 0x31,0x37,0x35,0x38,0x31,0x37,0x35,0x39, - 0x31,0x37,0x36,0x30,0x31,0x37,0x36,0x31, - 0x31,0x37,0x36,0x32,0x31,0x37,0x36,0x33, - 0x31,0x37,0x36,0x34,0x31,0x37,0x36,0x35, - 0x31,0x37,0x36,0x36,0x31,0x37,0x36,0x37, - 0x31,0x37,0x36,0x38,0x31,0x37,0x36,0x39, - 0x31,0x37,0x37,0x30,0x31,0x37,0x37,0x31, - 0x31,0x37,0x37,0x32,0x31,0x37,0x37,0x33, - 0x31,0x37,0x37,0x34,0x31,0x37,0x37,0x35, - 0x31,0x37,0x37,0x36,0x31,0x37,0x37,0x37, - 0x31,0x37,0x37,0x38,0x31,0x37,0x37,0x39, - 0x31,0x37,0x38,0x30,0x31,0x37,0x38,0x31, - 0x31,0x37,0x38,0x32,0x31,0x37,0x38,0x33, - 0x31,0x37,0x38,0x34,0x31,0x37,0x38,0x35, - 0x31,0x37,0x38,0x36,0x31,0x37,0x38,0x37, - 0x31,0x37,0x38,0x38,0x31,0x37,0x38,0x39, - 0x31,0x37,0x39,0x30,0x31,0x37,0x39,0x31, - 0x31,0x37,0x39,0x32,0x31,0x37,0x39,0x33, - 0x31,0x37,0x39,0x34,0x31,0x37,0x39,0x35, - 0x31,0x37,0x39,0x36,0x31,0x37,0x39,0x37, - 0x31,0x37,0x39,0x38,0x31,0x37,0x39,0x39, - 0x31,0x38,0x30,0x30,0x31,0x38,0x30,0x31, - 0x31,0x38,0x30,0x32,0x31,0x38,0x30,0x33, - 0x31,0x38,0x30,0x34,0x31,0x38,0x30,0x35, - 0x31,0x38,0x30,0x36,0x31,0x38,0x30,0x37, - 0x31,0x38,0x30,0x38,0x31,0x38,0x30,0x39, - 0x31,0x38,0x31,0x30,0x31,0x38,0x31,0x31, - 0x31,0x38,0x31,0x32,0x31,0x38,0x31,0x33, - 0x31,0x38,0x31,0x34,0x31,0x38,0x31,0x35, - 0x31,0x38,0x31,0x36,0x31,0x38,0x31,0x37, - 0x31,0x38,0x31,0x38,0x31,0x38,0x31,0x39, - 0x31,0x38,0x32,0x30,0x31,0x38,0x32,0x31, - 0x31,0x38,0x32,0x32,0x31,0x38,0x32,0x33, - 0x31,0x38,0x32,0x34,0x31,0x38,0x32,0x35, - 0x31,0x38,0x32,0x36,0x31,0x38,0x32,0x37, - 0x31,0x38,0x32,0x38,0x31,0x38,0x32,0x39, - 0x31,0x38,0x33,0x30,0x31,0x38,0x33,0x31, - 0x31,0x38,0x33,0x32,0x31,0x38,0x33,0x33, - 0x31,0x38,0x33,0x34,0x31,0x38,0x33,0x35, - 0x31,0x38,0x33,0x36,0x31,0x38,0x33,0x37, - 0x31,0x38,0x33,0x38,0x31,0x38,0x33,0x39, - 0x31,0x38,0x34,0x30,0x31,0x38,0x34,0x31, - 0x31,0x38,0x34,0x32,0x31,0x38,0x34,0x33, - 0x31,0x38,0x34,0x34,0x31,0x38,0x34,0x35, - 0x31,0x38,0x34,0x36,0x31,0x38,0x34,0x37, - 0x31,0x38,0x34,0x38,0x31,0x38,0x34,0x39, - 0x31,0x38,0x35,0x30,0x31,0x38,0x35,0x31, - 0x31,0x38,0x35,0x32,0x31,0x38,0x35,0x33, - 0x31,0x38,0x35,0x34,0x31,0x38,0x35,0x35, - 0x31,0x38,0x35,0x36,0x31,0x38,0x35,0x37, - 0x31,0x38,0x35,0x38,0x31,0x38,0x35,0x39, - 0x31,0x38,0x36,0x30,0x31,0x38,0x36,0x31, - 0x31,0x38,0x36,0x32,0x31,0x38,0x36,0x33, - 0x31,0x38,0x36,0x34,0x31,0x38,0x36,0x35, - 0x31,0x38,0x36,0x36,0x31,0x38,0x36,0x37, - 0x31,0x38,0x36,0x38,0x31,0x38,0x36,0x39, - 0x31,0x38,0x37,0x30,0x31,0x38,0x37,0x31, - 0x31,0x38,0x37,0x32,0x31,0x38,0x37,0x33, - 0x31,0x38,0x37,0x34,0x31,0x38,0x37,0x35, - 0x31,0x38,0x37,0x36,0x31,0x38,0x37,0x37, - 0x31,0x38,0x37,0x38,0x31,0x38,0x37,0x39, - 0x31,0x38,0x38,0x30,0x31,0x38,0x38,0x31, - 0x31,0x38,0x38,0x32,0x31,0x38,0x38,0x33, - 0x31,0x38,0x38,0x34,0x31,0x38,0x38,0x35, - 0x31,0x38,0x38,0x36,0x31,0x38,0x38,0x37, - 0x31,0x38,0x38,0x38,0x31,0x38,0x38,0x39, - 0x31,0x38,0x39,0x30,0x31,0x38,0x39,0x31, - 0x31,0x38,0x39,0x32,0x31,0x38,0x39,0x33, - 0x31,0x38,0x39,0x34,0x31,0x38,0x39,0x35, - 0x31,0x38,0x39,0x36,0x31,0x38,0x39,0x37, - 0x31,0x38,0x39,0x38,0x31,0x38,0x39,0x39, - 0x31,0x39,0x30,0x30,0x31,0x39,0x30,0x31, - 0x31,0x39,0x30,0x32,0x31,0x39,0x30,0x33, - 0x31,0x39,0x30,0x34,0x31,0x39,0x30,0x35, - 0x31,0x39,0x30,0x36,0x31,0x39,0x30,0x37, - 0x31,0x39,0x30,0x38,0x31,0x39,0x30,0x39, - 0x31,0x39,0x31,0x30,0x31,0x39,0x31,0x31, - 0x31,0x39,0x31,0x32,0x31,0x39,0x31,0x33, - 0x31,0x39,0x31,0x34,0x31,0x39,0x31,0x35, - 0x31,0x39,0x31,0x36,0x31,0x39,0x31,0x37, - 0x31,0x39,0x31,0x38,0x31,0x39,0x31,0x39, - 0x31,0x39,0x32,0x30,0x31,0x39,0x32,0x31, - 0x31,0x39,0x32,0x32,0x31,0x39,0x32,0x33, - 0x31,0x39,0x32,0x34,0x31,0x39,0x32,0x35, - 0x31,0x39,0x32,0x36,0x31,0x39,0x32,0x37, - 0x31,0x39,0x32,0x38,0x31,0x39,0x32,0x39, - 0x31,0x39,0x33,0x30,0x31,0x39,0x33,0x31, - 0x31,0x39,0x33,0x32,0x31,0x39,0x33,0x33, - 0x31,0x39,0x33,0x34,0x31,0x39,0x33,0x35, - 0x31,0x39,0x33,0x36,0x31,0x39,0x33,0x37, - 0x31,0x39,0x33,0x38,0x31,0x39,0x33,0x39, - 0x31,0x39,0x34,0x30,0x31,0x39,0x34,0x31, - 0x31,0x39,0x34,0x32,0x31,0x39,0x34,0x33, - 0x31,0x39,0x34,0x34,0x31,0x39,0x34,0x35, - 0x31,0x39,0x34,0x36,0x31,0x39,0x34,0x37, - 0x31,0x39,0x34,0x38,0x31,0x39,0x34,0x39, - 0x31,0x39,0x35,0x30,0x31,0x39,0x35,0x31, - 0x31,0x39,0x35,0x32,0x31,0x39,0x35,0x33, - 0x31,0x39,0x35,0x34,0x31,0x39,0x35,0x35, - 0x31,0x39,0x35,0x36,0x31,0x39,0x35,0x37, - 0x31,0x39,0x35,0x38,0x31,0x39,0x35,0x39, - 0x31,0x39,0x36,0x30,0x31,0x39,0x36,0x31, - 0x31,0x39,0x36,0x32,0x31,0x39,0x36,0x33, - 0x31,0x39,0x36,0x34,0x31,0x39,0x36,0x35, - 0x31,0x39,0x36,0x36,0x31,0x39,0x36,0x37, - 0x31,0x39,0x36,0x38,0x31,0x39,0x36,0x39, - 0x31,0x39,0x37,0x30,0x31,0x39,0x37,0x31, - 0x31,0x39,0x37,0x32,0x31,0x39,0x37,0x33, - 0x31,0x39,0x37,0x34,0x31,0x39,0x37,0x35, - 0x31,0x39,0x37,0x36,0x31,0x39,0x37,0x37, - 0x31,0x39,0x37,0x38,0x31,0x39,0x37,0x39, - 0x31,0x39,0x38,0x30,0x31,0x39,0x38,0x31, - 0x31,0x39,0x38,0x32,0x31,0x39,0x38,0x33, - 0x31,0x39,0x38,0x34,0x31,0x39,0x38,0x35, - 0x31,0x39,0x38,0x36,0x31,0x39,0x38,0x37, - 0x31,0x39,0x38,0x38,0x31,0x39,0x38,0x39, - 0x31,0x39,0x39,0x30,0x31,0x39,0x39,0x31, - 0x31,0x39,0x39,0x32,0x31,0x39,0x39,0x33, - 0x31,0x39,0x39,0x34,0x31,0x39,0x39,0x35, - 0x31,0x39,0x39,0x36,0x31,0x39,0x39,0x37, - 0x31,0x39,0x39,0x38,0x31,0x39,0x39,0x39, - 0x32,0x30,0x30,0x30,0x32,0x30,0x30,0x31, - 0x32,0x30,0x30,0x32,0x32,0x30,0x30,0x33, - 0x32,0x30,0x30,0x34,0x32,0x30,0x30,0x35, - 0x32,0x30,0x30,0x36,0x32,0x30,0x30,0x37, - 0x32,0x30,0x30,0x38,0x32,0x30,0x30,0x39, - 0x32,0x30,0x31,0x30,0x32,0x30,0x31,0x31, - 0x32,0x30,0x31,0x32,0x32,0x30,0x31,0x33, - 0x32,0x30,0x31,0x34,0x32,0x30,0x31,0x35, - 0x32,0x30,0x31,0x36,0x32,0x30,0x31,0x37, - 0x32,0x30,0x31,0x38,0x32,0x30,0x31,0x39, - 0x32,0x30,0x32,0x30,0x32,0x30,0x32,0x31, - 0x32,0x30,0x32,0x32,0x32,0x30,0x32,0x33, - 0x32,0x30,0x32,0x34,0x32,0x30,0x32,0x35, - 0x32,0x30,0x32,0x36,0x32,0x30,0x32,0x37, - 0x32,0x30,0x32,0x38,0x32,0x30,0x32,0x39, - 0x32,0x30,0x33,0x30,0x32,0x30,0x33,0x31, - 0x32,0x30,0x33,0x32,0x32,0x30,0x33,0x33, - 0x32,0x30,0x33,0x34,0x32,0x30,0x33,0x35, - 0x32,0x30,0x33,0x36,0x32,0x30,0x33,0x37, - 0x32,0x30,0x33,0x38,0x32,0x30,0x33,0x39, - 0x32,0x30,0x34,0x30,0x32,0x30,0x34,0x31, - 0x32,0x30,0x34,0x32,0x32,0x30,0x34,0x33, - 0x32,0x30,0x34,0x34,0x32,0x30,0x34,0x35, - 0x32,0x30,0x34,0x36,0x32,0x30,0x34,0x37, - 0x32,0x30,0x34,0x38,0x32,0x30,0x34,0x39, - 0x32,0x30,0x35,0x30,0x32,0x30,0x35,0x31, - 0x32,0x30,0x35,0x32,0x32,0x30,0x35,0x33, - 0x32,0x30,0x35,0x34,0x32,0x30,0x35,0x35, - 0x32,0x30,0x35,0x36,0x32,0x30,0x35,0x37, - 0x32,0x30,0x35,0x38,0x32,0x30,0x35,0x39, - 0x32,0x30,0x36,0x30,0x32,0x30,0x36,0x31, - 0x32,0x30,0x36,0x32,0x32,0x30,0x36,0x33, - 0x32,0x30,0x36,0x34,0x32,0x30,0x36,0x35, - 0x32,0x30,0x36,0x36,0x32,0x30,0x36,0x37, - 0x32,0x30,0x36,0x38,0x32,0x30,0x36,0x39, - 0x32,0x30,0x37,0x30,0x32,0x30,0x37,0x31, - 0x32,0x30,0x37,0x32,0x32,0x30,0x37,0x33, - 0x32,0x30,0x37,0x34,0x32,0x30,0x37,0x35, - 0x32,0x30,0x37,0x36,0x32,0x30,0x37,0x37, - 0x32,0x30,0x37,0x38,0x32,0x30,0x37,0x39, - 0x32,0x30,0x38,0x30,0x32,0x30,0x38,0x31, - 0x32,0x30,0x38,0x32,0x32,0x30,0x38,0x33, - 0x32,0x30,0x38,0x34,0x32,0x30,0x38,0x35, - 0x32,0x30,0x38,0x36,0x32,0x30,0x38,0x37, - 0x32,0x30,0x38,0x38,0x32,0x30,0x38,0x39, - 0x32,0x30,0x39,0x30,0x32,0x30,0x39,0x31, - 0x32,0x30,0x39,0x32,0x32,0x30,0x39,0x33, - 0x32,0x30,0x39,0x34,0x32,0x30,0x39,0x35, - 0x32,0x30,0x39,0x36,0x32,0x30,0x39,0x37, - 0x32,0x30,0x39,0x38,0x32,0x30,0x39,0x39, - 0x32,0x31,0x30,0x30,0x32,0x31,0x30,0x31, - 0x32,0x31,0x30,0x32,0x32,0x31,0x30,0x33, - 0x32,0x31,0x30,0x34,0x32,0x31,0x30,0x35, - 0x32,0x31,0x30,0x36,0x32,0x31,0x30,0x37, - 0x32,0x31,0x30,0x38,0x32,0x31,0x30,0x39, - 0x32,0x31,0x31,0x30,0x32,0x31,0x31,0x31, - 0x32,0x31,0x31,0x32,0x32,0x31,0x31,0x33, - 0x32,0x31,0x31,0x34,0x32,0x31,0x31,0x35, - 0x32,0x31,0x31,0x36,0x32,0x31,0x31,0x37, - 0x32,0x31,0x31,0x38,0x32,0x31,0x31,0x39, - 0x32,0x31,0x32,0x30,0x32,0x31,0x32,0x31, - 0x32,0x31,0x32,0x32,0x32,0x31,0x32,0x33, - 0x32,0x31,0x32,0x34,0x32,0x31,0x32,0x35, - 0x32,0x31,0x32,0x36,0x32,0x31,0x32,0x37, - 0x32,0x31,0x32,0x38,0x32,0x31,0x32,0x39, - 0x32,0x31,0x33,0x30,0x32,0x31,0x33,0x31, - 0x32,0x31,0x33,0x32,0x32,0x31,0x33,0x33, - 0x32,0x31,0x33,0x34,0x32,0x31,0x33,0x35, - 0x32,0x31,0x33,0x36,0x32,0x31,0x33,0x37, - 0x32,0x31,0x33,0x38,0x32,0x31,0x33,0x39, - 0x32,0x31,0x34,0x30,0x32,0x31,0x34,0x31, - 0x32,0x31,0x34,0x32,0x32,0x31,0x34,0x33, - 0x32,0x31,0x34,0x34,0x32,0x31,0x34,0x35, - 0x32,0x31,0x34,0x36,0x32,0x31,0x34,0x37, - 0x32,0x31,0x34,0x38,0x32,0x31,0x34,0x39, - 0x32,0x31,0x35,0x30,0x32,0x31,0x35,0x31, - 0x32,0x31,0x35,0x32,0x32,0x31,0x35,0x33, - 0x32,0x31,0x35,0x34,0x32,0x31,0x35,0x35, - 0x32,0x31,0x35,0x36,0x32,0x31,0x35,0x37, - 0x32,0x31,0x35,0x38,0x32,0x31,0x35,0x39, - 0x32,0x31,0x36,0x30,0x32,0x31,0x36,0x31, - 0x32,0x31,0x36,0x32,0x32,0x31,0x36,0x33, - 0x32,0x31,0x36,0x34,0x32,0x31,0x36,0x35, - 0x32,0x31,0x36,0x36,0x32,0x31,0x36,0x37, - 0x32,0x31,0x36,0x38,0x32,0x31,0x36,0x39, - 0x32,0x31,0x37,0x30,0x32,0x31,0x37,0x31, - 0x32,0x31,0x37,0x32,0x32,0x31,0x37,0x33, - 0x32,0x31,0x37,0x34,0x32,0x31,0x37,0x35, - 0x32,0x31,0x37,0x36,0x32,0x31,0x37,0x37, - 0x32,0x31,0x37,0x38,0x32,0x31,0x37,0x39, - 0x32,0x31,0x38,0x30,0x32,0x31,0x38,0x31, - 0x32,0x31,0x38,0x32,0x32,0x31,0x38,0x33, - 0x32,0x31,0x38,0x34,0x32,0x31,0x38,0x35, - 0x32,0x31,0x38,0x36,0x32,0x31,0x38,0x37, - 0x32,0x31,0x38,0x38,0x32,0x31,0x38,0x39, - 0x32,0x31,0x39,0x30,0x32,0x31,0x39,0x31, - 0x32,0x31,0x39,0x32,0x32,0x31,0x39,0x33, - 0x32,0x31,0x39,0x34,0x32,0x31,0x39,0x35, - 0x32,0x31,0x39,0x36,0x32,0x31,0x39,0x37, - 0x32,0x31,0x39,0x38,0x32,0x31,0x39,0x39, - 0x32,0x32,0x30,0x30,0x32,0x32,0x30,0x31, - 0x32,0x32,0x30,0x32,0x32,0x32,0x30,0x33, - 0x32,0x32,0x30,0x34,0x32,0x32,0x30,0x35, - 0x32,0x32,0x30,0x36,0x32,0x32,0x30,0x37, - 0x32,0x32,0x30,0x38,0x32,0x32,0x30,0x39, - 0x32,0x32,0x31,0x30,0x32,0x32,0x31,0x31, - 0x32,0x32,0x31,0x32,0x32,0x32,0x31,0x33, - 0x32,0x32,0x31,0x34,0x32,0x32,0x31,0x35, - 0x32,0x32,0x31,0x36,0x32,0x32,0x31,0x37, - 0x32,0x32,0x31,0x38,0x32,0x32,0x31,0x39, - 0x32,0x32,0x32,0x30,0x32,0x32,0x32,0x31, - 0x32,0x32,0x32,0x32,0x32,0x32,0x32,0x33, - 0x32,0x32,0x32,0x34,0x32,0x32,0x32,0x35, - 0x32,0x32,0x32,0x36,0x32,0x32,0x32,0x37, - 0x32,0x32,0x32,0x38,0x32,0x32,0x32,0x39, - 0x32,0x32,0x33,0x30,0x32,0x32,0x33,0x31, - 0x32,0x32,0x33,0x32,0x32,0x32,0x33,0x33, - 0x32,0x32,0x33,0x34,0x32,0x32,0x33,0x35, - 0x32,0x32,0x33,0x36,0x32,0x32,0x33,0x37, - 0x32,0x32,0x33,0x38,0x32,0x32,0x33,0x39, - 0x32,0x32,0x34,0x30,0x32,0x32,0x34,0x31, - 0x32,0x32,0x34,0x32,0x32,0x32,0x34,0x33, - 0x32,0x32,0x34,0x34,0x32,0x32,0x34,0x35, - 0x32,0x32,0x34,0x36,0x32,0x32,0x34,0x37, - 0x32,0x32,0x34,0x38,0x32,0x32,0x34,0x39, - 0x32,0x32,0x35,0x30,0x32,0x32,0x35,0x31, - 0x32,0x32,0x35,0x32,0x32,0x32,0x35,0x33, - 0x32,0x32,0x35,0x34,0x32,0x32,0x35,0x35, - 0x32,0x32,0x35,0x36,0x32,0x32,0x35,0x37, - 0x32,0x32,0x35,0x38,0x32,0x32,0x35,0x39, - 0x32,0x32,0x36,0x30,0x32,0x32,0x36,0x31, - 0x32,0x32,0x36,0x32,0x32,0x32,0x36,0x33, - 0x32,0x32,0x36,0x34,0x32,0x32,0x36,0x35, - 0x32,0x32,0x36,0x36,0x32,0x32,0x36,0x37, - 0x32,0x32,0x36,0x38,0x32,0x32,0x36,0x39, - 0x32,0x32,0x37,0x30,0x32,0x32,0x37,0x31, - 0x32,0x32,0x37,0x32,0x32,0x32,0x37,0x33, - 0x32,0x32,0x37,0x34,0x32,0x32,0x37,0x35, - 0x32,0x32,0x37,0x36,0x32,0x32,0x37,0x37, - 0x32,0x32,0x37,0x38,0x32,0x32,0x37,0x39, - 0x32,0x32,0x38,0x30,0x32,0x32,0x38,0x31, - 0x32,0x32,0x38,0x32,0x32,0x32,0x38,0x33, - 0x32,0x32,0x38,0x34,0x32,0x32,0x38,0x35, - 0x32,0x32,0x38,0x36,0x32,0x32,0x38,0x37, - 0x32,0x32,0x38,0x38,0x32,0x32,0x38,0x39, - 0x32,0x32,0x39,0x30,0x32,0x32,0x39,0x31, - 0x32,0x32,0x39,0x32,0x32,0x32,0x39,0x33, - 0x32,0x32,0x39,0x34,0x32,0x32,0x39,0x35, - 0x32,0x32,0x39,0x36,0x32,0x32,0x39,0x37, - 0x32,0x32,0x39,0x38,0x32,0x32,0x39,0x39, - 0x32,0x33,0x30,0x30,0x32,0x33,0x30,0x31, - 0x32,0x33,0x30,0x32,0x32,0x33,0x30,0x33, - 0x32,0x33,0x30,0x34,0x32,0x33,0x30,0x35, - 0x32,0x33,0x30,0x36,0x32,0x33,0x30,0x37, - 0x32,0x33,0x30,0x38,0x32,0x33,0x30,0x39, - 0x32,0x33,0x31,0x30,0x32,0x33,0x31,0x31, - 0x32,0x33,0x31,0x32,0x32,0x33,0x31,0x33, - 0x32,0x33,0x31,0x34,0x32,0x33,0x31,0x35, - 0x32,0x33,0x31,0x36,0x32,0x33,0x31,0x37, - 0x32,0x33,0x31,0x38,0x32,0x33,0x31,0x39, - 0x32,0x33,0x32,0x30,0x32,0x33,0x32,0x31, - 0x32,0x33,0x32,0x32,0x32,0x33,0x32,0x33, - 0x32,0x33,0x32,0x34,0x32,0x33,0x32,0x35, - 0x32,0x33,0x32,0x36,0x32,0x33,0x32,0x37, - 0x32,0x33,0x32,0x38,0x32,0x33,0x32,0x39, - 0x32,0x33,0x33,0x30,0x32,0x33,0x33,0x31, - 0x32,0x33,0x33,0x32,0x32,0x33,0x33,0x33, - 0x32,0x33,0x33,0x34,0x32,0x33,0x33,0x35, - 0x32,0x33,0x33,0x36,0x32,0x33,0x33,0x37, - 0x32,0x33,0x33,0x38,0x32,0x33,0x33,0x39, - 0x32,0x33,0x34,0x30,0x32,0x33,0x34,0x31, - 0x32,0x33,0x34,0x32,0x32,0x33,0x34,0x33, - 0x32,0x33,0x34,0x34,0x32,0x33,0x34,0x35, - 0x32,0x33,0x34,0x36,0x32,0x33,0x34,0x37, - 0x32,0x33,0x34,0x38,0x32,0x33,0x34,0x39, - 0x32,0x33,0x35,0x30,0x32,0x33,0x35,0x31, - 0x32,0x33,0x35,0x32,0x32,0x33,0x35,0x33, - 0x32,0x33,0x35,0x34,0x32,0x33,0x35,0x35, - 0x32,0x33,0x35,0x36,0x32,0x33,0x35,0x37, - 0x32,0x33,0x35,0x38,0x32,0x33,0x35,0x39, - 0x32,0x33,0x36,0x30,0x32,0x33,0x36,0x31, - 0x32,0x33,0x36,0x32,0x32,0x33,0x36,0x33, - 0x32,0x33,0x36,0x34,0x32,0x33,0x36,0x35, - 0x32,0x33,0x36,0x36,0x32,0x33,0x36,0x37, - 0x32,0x33,0x36,0x38,0x32,0x33,0x36,0x39, - 0x32,0x33,0x37,0x30,0x32,0x33,0x37,0x31, - 0x32,0x33,0x37,0x32,0x32,0x33,0x37,0x33, - 0x32,0x33,0x37,0x34,0x32,0x33,0x37,0x35, - 0x32,0x33,0x37,0x36,0x32,0x33,0x37,0x37, - 0x32,0x33,0x37,0x38,0x32,0x33,0x37,0x39, - 0x32,0x33,0x38,0x30,0x32,0x33,0x38,0x31, - 0x32,0x33,0x38,0x32,0x32,0x33,0x38,0x33, - 0x32,0x33,0x38,0x34,0x32,0x33,0x38,0x35, - 0x32,0x33,0x38,0x36,0x32,0x33,0x38,0x37, - 0x32,0x33,0x38,0x38,0x32,0x33,0x38,0x39, - 0x32,0x33,0x39,0x30,0x32,0x33,0x39,0x31, - 0x32,0x33,0x39,0x32,0x32,0x33,0x39,0x33, - 0x32,0x33,0x39,0x34,0x32,0x33,0x39,0x35, - 0x32,0x33,0x39,0x36,0x32,0x33,0x39,0x37, - 0x32,0x33,0x39,0x38,0x32,0x33,0x39,0x39, - 0x32,0x34,0x30,0x30,0x32,0x34,0x30,0x31, - 0x32,0x34,0x30,0x32,0x32,0x34,0x30,0x33, - 0x32,0x34,0x30,0x34,0x32,0x34,0x30,0x35, - 0x32,0x34,0x30,0x36,0x32,0x34,0x30,0x37, - 0x32,0x34,0x30,0x38,0x32,0x34,0x30,0x39, - 0x32,0x34,0x31,0x30,0x32,0x34,0x31,0x31, - 0x32,0x34,0x31,0x32,0x32,0x34,0x31,0x33, - 0x32,0x34,0x31,0x34,0x32,0x34,0x31,0x35, - 0x32,0x34,0x31,0x36,0x32,0x34,0x31,0x37, - 0x32,0x34,0x31,0x38,0x32,0x34,0x31,0x39, - 0x32,0x34,0x32,0x30,0x32,0x34,0x32,0x31, - 0x32,0x34,0x32,0x32,0x32,0x34,0x32,0x33, - 0x32,0x34,0x32,0x34,0x32,0x34,0x32,0x35, - 0x32,0x34,0x32,0x36,0x32,0x34,0x32,0x37, - 0x32,0x34,0x32,0x38,0x32,0x34,0x32,0x39, - 0x32,0x34,0x33,0x30,0x32,0x34,0x33,0x31, - 0x32,0x34,0x33,0x32,0x32,0x34,0x33,0x33, - 0x32,0x34,0x33,0x34,0x32,0x34,0x33,0x35, - 0x32,0x34,0x33,0x36,0x32,0x34,0x33,0x37, - 0x32,0x34,0x33,0x38,0x32,0x34,0x33,0x39, - 0x32,0x34,0x34,0x30,0x32,0x34,0x34,0x31, - 0x32,0x34,0x34,0x32,0x32,0x34,0x34,0x33, - 0x32,0x34,0x34,0x34,0x32,0x34,0x34,0x35, - 0x32,0x34,0x34,0x36,0x32,0x34,0x34,0x37, - 0x32,0x34,0x34,0x38,0x32,0x34,0x34,0x39, - 0x32,0x34,0x35,0x30,0x32,0x34,0x35,0x31, - 0x32,0x34,0x35,0x32,0x32,0x34,0x35,0x33, - 0x32,0x34,0x35,0x34,0x32,0x34,0x35,0x35, - 0x32,0x34,0x35,0x36,0x32,0x34,0x35,0x37, - 0x32,0x34,0x35,0x38,0x32,0x34,0x35,0x39, - 0x32,0x34,0x36,0x30,0x32,0x34,0x36,0x31, - 0x32,0x34,0x36,0x32,0x32,0x34,0x36,0x33, - 0x32,0x34,0x36,0x34,0x32,0x34,0x36,0x35, - 0x32,0x34,0x36,0x36,0x32,0x34,0x36,0x37, - 0x32,0x34,0x36,0x38,0x32,0x34,0x36,0x39, - 0x32,0x34,0x37,0x30,0x32,0x34,0x37,0x31, - 0x32,0x34,0x37,0x32,0x32,0x34,0x37,0x33, - 0x32,0x34,0x37,0x34,0x32,0x34,0x37,0x35, - 0x32,0x34,0x37,0x36,0x32,0x34,0x37,0x37, - 0x32,0x34,0x37,0x38,0x32,0x34,0x37,0x39, - 0x32,0x34,0x38,0x30,0x32,0x34,0x38,0x31, - 0x32,0x34,0x38,0x32,0x32,0x34,0x38,0x33, - 0x32,0x34,0x38,0x34,0x32,0x34,0x38,0x35, - 0x32,0x34,0x38,0x36,0x32,0x34,0x38,0x37, - 0x32,0x34,0x38,0x38,0x32,0x34,0x38,0x39, - 0x32,0x34,0x39,0x30,0x32,0x34,0x39,0x31, - 0x32,0x34,0x39,0x32,0x32,0x34,0x39,0x33, - 0x32,0x34,0x39,0x34,0x32,0x34,0x39,0x35, - 0x32,0x34,0x39,0x36,0x32,0x34,0x39,0x37, - 0x32,0x34,0x39,0x38,0x32,0x34,0x39,0x39, - 0x32,0x35,0x30,0x30,0x32,0x35,0x30,0x31, - 0x32,0x35,0x30,0x32,0x32,0x35,0x30,0x33, - 0x32,0x35,0x30,0x34,0x32,0x35,0x30,0x35, - 0x32,0x35,0x30,0x36,0x32,0x35,0x30,0x37, - 0x32,0x35,0x30,0x38,0x32,0x35,0x30,0x39, - 0x32,0x35,0x31,0x30,0x32,0x35,0x31,0x31, - 0x32,0x35,0x31,0x32,0x32,0x35,0x31,0x33, - 0x32,0x35,0x31,0x34,0x32,0x35,0x31,0x35, - 0x32,0x35,0x31,0x36,0x32,0x35,0x31,0x37, - 0x32,0x35,0x31,0x38,0x32,0x35,0x31,0x39, - 0x32,0x35,0x32,0x30,0x32,0x35,0x32,0x31, - 0x32,0x35,0x32,0x32,0x32,0x35,0x32,0x33, - 0x32,0x35,0x32,0x34,0x32,0x35,0x32,0x35, - 0x32,0x35,0x32,0x36,0x32,0x35,0x32,0x37, - 0x32,0x35,0x32,0x38,0x32,0x35,0x32,0x39, - 0x32,0x35,0x33,0x30,0x32,0x35,0x33,0x31, - 0x32,0x35,0x33,0x32,0x32,0x35,0x33,0x33, - 0x32,0x35,0x33,0x34,0x32,0x35,0x33,0x35, - 0x32,0x35,0x33,0x36,0x32,0x35,0x33,0x37, - 0x32,0x35,0x33,0x38,0x32,0x35,0x33,0x39, - 0x32,0x35,0x34,0x30,0x32,0x35,0x34,0x31, - 0x32,0x35,0x34,0x32,0x32,0x35,0x34,0x33, - 0x32,0x35,0x34,0x34,0x32,0x35,0x34,0x35, - 0x32,0x35,0x34,0x36,0x32,0x35,0x34,0x37, - 0x32,0x35,0x34,0x38,0x32,0x35,0x34,0x39, - 0x32,0x35,0x35,0x30,0x32,0x35,0x35,0x31, - 0x32,0x35,0x35,0x32,0x32,0x35,0x35,0x33, - 0x32,0x35,0x35,0x34,0x32,0x35,0x35,0x35, - 0x32,0x35,0x35,0x36,0x32,0x35,0x35,0x37, - 0x32,0x35,0x35,0x38,0x32,0x35,0x35,0x39, - 0x32,0x35,0x36,0x30,0x32,0x35,0x36,0x31, - 0x32,0x35,0x36,0x32,0x32,0x35,0x36,0x33, - 0x32,0x35,0x36,0x34,0x32,0x35,0x36,0x35, - 0x32,0x35,0x36,0x36,0x32,0x35,0x36,0x37, - 0x32,0x35,0x36,0x38,0x32,0x35,0x36,0x39, - 0x32,0x35,0x37,0x30,0x32,0x35,0x37,0x31, - 0x32,0x35,0x37,0x32,0x32,0x35,0x37,0x33, - 0x32,0x35,0x37,0x34,0x32,0x35,0x37,0x35, - 0x32,0x35,0x37,0x36,0x32,0x35,0x37,0x37, - 0x32,0x35,0x37,0x38,0x32,0x35,0x37,0x39, - 0x32,0x35,0x38,0x30,0x32,0x35,0x38,0x31, - 0x32,0x35,0x38,0x32,0x32,0x35,0x38,0x33, - 0x32,0x35,0x38,0x34,0x32,0x35,0x38,0x35, - 0x32,0x35,0x38,0x36,0x32,0x35,0x38,0x37, - 0x32,0x35,0x38,0x38,0x32,0x35,0x38,0x39, - 0x32,0x35,0x39,0x30,0x32,0x35,0x39,0x31, - 0x32,0x35,0x39,0x32,0x32,0x35,0x39,0x33, - 0x32,0x35,0x39,0x34,0x32,0x35,0x39,0x35, - 0x32,0x35,0x39,0x36,0x32,0x35,0x39,0x37, - 0x32,0x35,0x39,0x38,0x32,0x35,0x39,0x39, - 0x32,0x36,0x30,0x30,0x32,0x36,0x30,0x31, - 0x32,0x36,0x30,0x32,0x32,0x36,0x30,0x33, - 0x32,0x36,0x30,0x34,0x32,0x36,0x30,0x35, - 0x32,0x36,0x30,0x36,0x32,0x36,0x30,0x37, - 0x32,0x36,0x30,0x38,0x32,0x36,0x30,0x39, - 0x32,0x36,0x31,0x30,0x32,0x36,0x31,0x31, - 0x32,0x36,0x31,0x32,0x32,0x36,0x31,0x33, - 0x32,0x36,0x31,0x34,0x32,0x36,0x31,0x35, - 0x32,0x36,0x31,0x36,0x32,0x36,0x31,0x37, - 0x32,0x36,0x31,0x38,0x32,0x36,0x31,0x39, - 0x32,0x36,0x32,0x30,0x32,0x36,0x32,0x31, - 0x32,0x36,0x32,0x32,0x32,0x36,0x32,0x33, - 0x32,0x36,0x32,0x34,0x32,0x36,0x32,0x35, - 0x32,0x36,0x32,0x36,0x32,0x36,0x32,0x37, - 0x32,0x36,0x32,0x38,0x32,0x36,0x32,0x39, - 0x32,0x36,0x33,0x30,0x32,0x36,0x33,0x31, - 0x32,0x36,0x33,0x32,0x32,0x36,0x33,0x33, - 0x32,0x36,0x33,0x34,0x32,0x36,0x33,0x35, - 0x32,0x36,0x33,0x36,0x32,0x36,0x33,0x37, - 0x32,0x36,0x33,0x38,0x32,0x36,0x33,0x39, - 0x32,0x36,0x34,0x30,0x32,0x36,0x34,0x31, - 0x32,0x36,0x34,0x32,0x32,0x36,0x34,0x33, - 0x32,0x36,0x34,0x34,0x32,0x36,0x34,0x35, - 0x32,0x36,0x34,0x36,0x32,0x36,0x34,0x37, - 0x32,0x36,0x34,0x38,0x32,0x36,0x34,0x39, - 0x32,0x36,0x35,0x30,0x32,0x36,0x35,0x31, - 0x32,0x36,0x35,0x32,0x32,0x36,0x35,0x33, - 0x32,0x36,0x35,0x34,0x32,0x36,0x35,0x35, - 0x32,0x36,0x35,0x36,0x32,0x36,0x35,0x37, - 0x32,0x36,0x35,0x38,0x32,0x36,0x35,0x39, - 0x32,0x36,0x36,0x30,0x32,0x36,0x36,0x31, - 0x32,0x36,0x36,0x32,0x32,0x36,0x36,0x33, - 0x32,0x36,0x36,0x34,0x32,0x36,0x36,0x35, - 0x32,0x36,0x36,0x36,0x32,0x36,0x36,0x37, - 0x32,0x36,0x36,0x38,0x32,0x36,0x36,0x39, - 0x32,0x36,0x37,0x30,0x32,0x36,0x37,0x31, - 0x32,0x36,0x37,0x32,0x32,0x36,0x37,0x33, - 0x32,0x36,0x37,0x34,0x32,0x36,0x37,0x35, - 0x32,0x36,0x37,0x36,0x32,0x36,0x37,0x37, - 0x32,0x36,0x37,0x38,0x32,0x36,0x37,0x39, - 0x32,0x36,0x38,0x30,0x32,0x36,0x38,0x31, - 0x32,0x36,0x38,0x32,0x32,0x36,0x38,0x33, - 0x32,0x36,0x38,0x34,0x32,0x36,0x38,0x35, - 0x32,0x36,0x38,0x36,0x32,0x36,0x38,0x37, - 0x32,0x36,0x38,0x38,0x32,0x36,0x38,0x39, - 0x32,0x36,0x39,0x30,0x32,0x36,0x39,0x31, - 0x32,0x36,0x39,0x32,0x32,0x36,0x39,0x33, - 0x32,0x36,0x39,0x34,0x32,0x36,0x39,0x35, - 0x32,0x36,0x39,0x36,0x32,0x36,0x39,0x37, - 0x32,0x36,0x39,0x38,0x32,0x36,0x39,0x39, - 0x32,0x37,0x30,0x30,0x32,0x37,0x30,0x31, - 0x32,0x37,0x30,0x32,0x32,0x37,0x30,0x33, - 0x32,0x37,0x30,0x34,0x32,0x37,0x30,0x35, - 0x32,0x37,0x30,0x36,0x32,0x37,0x30,0x37, - 0x32,0x37,0x30,0x38,0x32,0x37,0x30,0x39, - 0x32,0x37,0x31,0x30,0x32,0x37,0x31,0x31, - 0x32,0x37,0x31,0x32,0x32,0x37,0x31,0x33, - 0x32,0x37,0x31,0x34,0x32,0x37,0x31,0x35, - 0x32,0x37,0x31,0x36,0x32,0x37,0x31,0x37, - 0x32,0x37,0x31,0x38,0x32,0x37,0x31,0x39, - 0x32,0x37,0x32,0x30,0x32,0x37,0x32,0x31, - 0x32,0x37,0x32,0x32,0x32,0x37,0x32,0x33, - 0x32,0x37,0x32,0x34,0x32,0x37,0x32,0x35, - 0x32,0x37,0x32,0x36,0x32,0x37,0x32,0x37, - 0x32,0x37,0x32,0x38,0x32,0x37,0x32,0x39, - 0x32,0x37,0x33,0x30,0x32,0x37,0x33,0x31, - 0x32,0x37,0x33,0x32,0x32,0x37,0x33,0x33, - 0x32,0x37,0x33,0x34,0x32,0x37,0x33,0x35, - 0x32,0x37,0x33,0x36,0x32,0x37,0x33,0x37, - 0x32,0x37,0x33,0x38,0x32,0x37,0x33,0x39, - 0x32,0x37,0x34,0x30,0x32,0x37,0x34,0x31, - 0x32,0x37,0x34,0x32,0x32,0x37,0x34,0x33, - 0x32,0x37,0x34,0x34,0x32,0x37,0x34,0x35, - 0x32,0x37,0x34,0x36,0x32,0x37,0x34,0x37, - 0x32,0x37,0x34,0x38,0x32,0x37,0x34,0x39, - 0x32,0x37,0x35,0x30,0x32,0x37,0x35,0x31, - 0x32,0x37,0x35,0x32,0x32,0x37,0x35,0x33, - 0x32,0x37,0x35,0x34,0x32,0x37,0x35,0x35, - 0x32,0x37,0x35,0x36,0x32,0x37,0x35,0x37, - 0x32,0x37,0x35,0x38,0x32,0x37,0x35,0x39, - 0x32,0x37,0x36,0x30,0x32,0x37,0x36,0x31, - 0x32,0x37,0x36,0x32,0x32,0x37,0x36,0x33, - 0x32,0x37,0x36,0x34,0x32,0x37,0x36,0x35, - 0x32,0x37,0x36,0x36,0x32,0x37,0x36,0x37, - 0x32,0x37,0x36,0x38,0x32,0x37,0x36,0x39, - 0x32,0x37,0x37,0x30,0x32,0x37,0x37,0x31, - 0x32,0x37,0x37,0x32,0x32,0x37,0x37,0x33, - 0x32,0x37,0x37,0x34,0x32,0x37,0x37,0x35, - 0x32,0x37,0x37,0x36,0x32,0x37,0x37,0x37, - 0x32,0x37,0x37,0x38,0x32,0x37,0x37,0x39, - 0x32,0x37,0x38,0x30,0x32,0x37,0x38,0x31, - 0x32,0x37,0x38,0x32,0x32,0x37,0x38,0x33, - 0x32,0x37,0x38,0x34,0x32,0x37,0x38,0x35, - 0x32,0x37,0x38,0x36,0x32,0x37,0x38,0x37, - 0x32,0x37,0x38,0x38,0x32,0x37,0x38,0x39, - 0x32,0x37,0x39,0x30,0x32,0x37,0x39,0x31, - 0x32,0x37,0x39,0x32,0x32,0x37,0x39,0x33, - 0x32,0x37,0x39,0x34,0x32,0x37,0x39,0x35, - 0x32,0x37,0x39,0x36,0x32,0x37,0x39,0x37, - 0x32,0x37,0x39,0x38,0x32,0x37,0x39,0x39, - 0x32,0x38,0x30,0x30,0x32,0x38,0x30,0x31, - 0x32,0x38,0x30,0x32,0x32,0x38,0x30,0x33, - 0x32,0x38,0x30,0x34,0x32,0x38,0x30,0x35, - 0x32,0x38,0x30,0x36,0x32,0x38,0x30,0x37, - 0x32,0x38,0x30,0x38,0x32,0x38,0x30,0x39, - 0x32,0x38,0x31,0x30,0x32,0x38,0x31,0x31, - 0x32,0x38,0x31,0x32,0x32,0x38,0x31,0x33, - 0x32,0x38,0x31,0x34,0x32,0x38,0x31,0x35, - 0x32,0x38,0x31,0x36,0x32,0x38,0x31,0x37, - 0x32,0x38,0x31,0x38,0x32,0x38,0x31,0x39, - 0x32,0x38,0x32,0x30,0x32,0x38,0x32,0x31, - 0x32,0x38,0x32,0x32,0x32,0x38,0x32,0x33, - 0x32,0x38,0x32,0x34,0x32,0x38,0x32,0x35, - 0x32,0x38,0x32,0x36,0x32,0x38,0x32,0x37, - 0x32,0x38,0x32,0x38,0x32,0x38,0x32,0x39, - 0x32,0x38,0x33,0x30,0x32,0x38,0x33,0x31, - 0x32,0x38,0x33,0x32,0x32,0x38,0x33,0x33, - 0x32,0x38,0x33,0x34,0x32,0x38,0x33,0x35, - 0x32,0x38,0x33,0x36,0x32,0x38,0x33,0x37, - 0x32,0x38,0x33,0x38,0x32,0x38,0x33,0x39, - 0x32,0x38,0x34,0x30,0x32,0x38,0x34,0x31, - 0x32,0x38,0x34,0x32,0x32,0x38,0x34,0x33, - 0x32,0x38,0x34,0x34,0x32,0x38,0x34,0x35, - 0x32,0x38,0x34,0x36,0x32,0x38,0x34,0x37, - 0x32,0x38,0x34,0x38,0x32,0x38,0x34,0x39, - 0x32,0x38,0x35,0x30,0x32,0x38,0x35,0x31, - 0x32,0x38,0x35,0x32,0x32,0x38,0x35,0x33, - 0x32,0x38,0x35,0x34,0x32,0x38,0x35,0x35, - 0x32,0x38,0x35,0x36,0x32,0x38,0x35,0x37, - 0x32,0x38,0x35,0x38,0x32,0x38,0x35,0x39, - 0x32,0x38,0x36,0x30,0x32,0x38,0x36,0x31, - 0x32,0x38,0x36,0x32,0x32,0x38,0x36,0x33, - 0x32,0x38,0x36,0x34,0x32,0x38,0x36,0x35, - 0x32,0x38,0x36,0x36,0x32,0x38,0x36,0x37, - 0x32,0x38,0x36,0x38,0x32,0x38,0x36,0x39, - 0x32,0x38,0x37,0x30,0x32,0x38,0x37,0x31, - 0x32,0x38,0x37,0x32,0x32,0x38,0x37,0x33, - 0x32,0x38,0x37,0x34,0x32,0x38,0x37,0x35, - 0x32,0x38,0x37,0x36,0x32,0x38,0x37,0x37, - 0x32,0x38,0x37,0x38,0x32,0x38,0x37,0x39, - 0x32,0x38,0x38,0x30,0x32,0x38,0x38,0x31, - 0x32,0x38,0x38,0x32,0x32,0x38,0x38,0x33, - 0x32,0x38,0x38,0x34,0x32,0x38,0x38,0x35, - 0x32,0x38,0x38,0x36,0x32,0x38,0x38,0x37, - 0x32,0x38,0x38,0x38,0x32,0x38,0x38,0x39, - 0x32,0x38,0x39,0x30,0x32,0x38,0x39,0x31, - 0x32,0x38,0x39,0x32,0x32,0x38,0x39,0x33, - 0x32,0x38,0x39,0x34,0x32,0x38,0x39,0x35, - 0x32,0x38,0x39,0x36,0x32,0x38,0x39,0x37, - 0x32,0x38,0x39,0x38,0x32,0x38,0x39,0x39, - 0x32,0x39,0x30,0x30,0x32,0x39,0x30,0x31, - 0x32,0x39,0x30,0x32,0x32,0x39,0x30,0x33, - 0x32,0x39,0x30,0x34,0x32,0x39,0x30,0x35, - 0x32,0x39,0x30,0x36,0x32,0x39,0x30,0x37, - 0x32,0x39,0x30,0x38,0x32,0x39,0x30,0x39, - 0x32,0x39,0x31,0x30,0x32,0x39,0x31,0x31, - 0x32,0x39,0x31,0x32,0x32,0x39,0x31,0x33, - 0x32,0x39,0x31,0x34,0x32,0x39,0x31,0x35, - 0x32,0x39,0x31,0x36,0x32,0x39,0x31,0x37, - 0x32,0x39,0x31,0x38,0x32,0x39,0x31,0x39, - 0x32,0x39,0x32,0x30,0x32,0x39,0x32,0x31, - 0x32,0x39,0x32,0x32,0x32,0x39,0x32,0x33, - 0x32,0x39,0x32,0x34,0x32,0x39,0x32,0x35, - 0x32,0x39,0x32,0x36,0x32,0x39,0x32,0x37, - 0x32,0x39,0x32,0x38,0x32,0x39,0x32,0x39, - 0x32,0x39,0x33,0x30,0x32,0x39,0x33,0x31, - 0x32,0x39,0x33,0x32,0x32,0x39,0x33,0x33, - 0x32,0x39,0x33,0x34,0x32,0x39,0x33,0x35, - 0x32,0x39,0x33,0x36,0x32,0x39,0x33,0x37, - 0x32,0x39,0x33,0x38,0x32,0x39,0x33,0x39, - 0x32,0x39,0x34,0x30,0x32,0x39,0x34,0x31, - 0x32,0x39,0x34,0x32,0x32,0x39,0x34,0x33, - 0x32,0x39,0x34,0x34,0x32,0x39,0x34,0x35, - 0x32,0x39,0x34,0x36,0x32,0x39,0x34,0x37, - 0x32,0x39,0x34,0x38,0x32,0x39,0x34,0x39, - 0x32,0x39,0x35,0x30,0x32,0x39,0x35,0x31, - 0x32,0x39,0x35,0x32,0x32,0x39,0x35,0x33, - 0x32,0x39,0x35,0x34,0x32,0x39,0x35,0x35, - 0x32,0x39,0x35,0x36,0x32,0x39,0x35,0x37, - 0x32,0x39,0x35,0x38,0x32,0x39,0x35,0x39, - 0x32,0x39,0x36,0x30,0x32,0x39,0x36,0x31, - 0x32,0x39,0x36,0x32,0x32,0x39,0x36,0x33, - 0x32,0x39,0x36,0x34,0x32,0x39,0x36,0x35, - 0x32,0x39,0x36,0x36,0x32,0x39,0x36,0x37, - 0x32,0x39,0x36,0x38,0x32,0x39,0x36,0x39, - 0x32,0x39,0x37,0x30,0x32,0x39,0x37,0x31, - 0x32,0x39,0x37,0x32,0x32,0x39,0x37,0x33, - 0x32,0x39,0x37,0x34,0x32,0x39,0x37,0x35, - 0x32,0x39,0x37,0x36,0x32,0x39,0x37,0x37, - 0x32,0x39,0x37,0x38,0x32,0x39,0x37,0x39, - 0x32,0x39,0x38,0x30,0x32,0x39,0x38,0x31, - 0x32,0x39,0x38,0x32,0x32,0x39,0x38,0x33, - 0x32,0x39,0x38,0x34,0x32,0x39,0x38,0x35, - 0x32,0x39,0x38,0x36,0x32,0x39,0x38,0x37, - 0x32,0x39,0x38,0x38,0x32,0x39,0x38,0x39, - 0x32,0x39,0x39,0x30,0x32,0x39,0x39,0x31, - 0x32,0x39,0x39,0x32,0x32,0x39,0x39,0x33, - 0x32,0x39,0x39,0x34,0x32,0x39,0x39,0x35, - 0x32,0x39,0x39,0x36,0x32,0x39,0x39,0x37, - 0x32,0x39,0x39,0x38,0x32,0x39,0x39,0x39, - 0x33,0x30,0x30,0x30,0x33,0x30,0x30,0x31, - 0x33,0x30,0x30,0x32,0x33,0x30,0x30,0x33, - 0x33,0x30,0x30,0x34,0x33,0x30,0x30,0x35, - 0x33,0x30,0x30,0x36,0x33,0x30,0x30,0x37, - 0x33,0x30,0x30,0x38,0x33,0x30,0x30,0x39, - 0x33,0x30,0x31,0x30,0x33,0x30,0x31,0x31, - 0x33,0x30,0x31,0x32,0x33,0x30,0x31,0x33, - 0x33,0x30,0x31,0x34,0x33,0x30,0x31,0x35, - 0x33,0x30,0x31,0x36,0x33,0x30,0x31,0x37, - 0x33,0x30,0x31,0x38,0x33,0x30,0x31,0x39, - 0x33,0x30,0x32,0x30,0x33,0x30,0x32,0x31, - 0x33,0x30,0x32,0x32,0x33,0x30,0x32,0x33, - 0x33,0x30,0x32,0x34,0x33,0x30,0x32,0x35, - 0x33,0x30,0x32,0x36,0x33,0x30,0x32,0x37, - 0x33,0x30,0x32,0x38,0x33,0x30,0x32,0x39, - 0x33,0x30,0x33,0x30,0x33,0x30,0x33,0x31, - 0x33,0x30,0x33,0x32,0x33,0x30,0x33,0x33, - 0x33,0x30,0x33,0x34,0x33,0x30,0x33,0x35, - 0x33,0x30,0x33,0x36,0x33,0x30,0x33,0x37, - 0x33,0x30,0x33,0x38,0x33,0x30,0x33,0x39, - 0x33,0x30,0x34,0x30,0x33,0x30,0x34,0x31, - 0x33,0x30,0x34,0x32,0x33,0x30,0x34,0x33, - 0x33,0x30,0x34,0x34,0x33,0x30,0x34,0x35, - 0x33,0x30,0x34,0x36,0x33,0x30,0x34,0x37, - 0x33,0x30,0x34,0x38,0x33,0x30,0x34,0x39, - 0x33,0x30,0x35,0x30,0x33,0x30,0x35,0x31, - 0x33,0x30,0x35,0x32,0x33,0x30,0x35,0x33, - 0x33,0x30,0x35,0x34,0x33,0x30,0x35,0x35, - 0x33,0x30,0x35,0x36,0x33,0x30,0x35,0x37, - 0x33,0x30,0x35,0x38,0x33,0x30,0x35,0x39, - 0x33,0x30,0x36,0x30,0x33,0x30,0x36,0x31, - 0x33,0x30,0x36,0x32,0x33,0x30,0x36,0x33, - 0x33,0x30,0x36,0x34,0x33,0x30,0x36,0x35, - 0x33,0x30,0x36,0x36,0x33,0x30,0x36,0x37, - 0x33,0x30,0x36,0x38,0x33,0x30,0x36,0x39, - 0x33,0x30,0x37,0x30,0x33,0x30,0x37,0x31, - 0x33,0x30,0x37,0x32,0x33,0x30,0x37,0x33, - 0x33,0x30,0x37,0x34,0x33,0x30,0x37,0x35, - 0x33,0x30,0x37,0x36,0x33,0x30,0x37,0x37, - 0x33,0x30,0x37,0x38,0x33,0x30,0x37,0x39, - 0x33,0x30,0x38,0x30,0x33,0x30,0x38,0x31, - 0x33,0x30,0x38,0x32,0x33,0x30,0x38,0x33, - 0x33,0x30,0x38,0x34,0x33,0x30,0x38,0x35, - 0x33,0x30,0x38,0x36,0x33,0x30,0x38,0x37, - 0x33,0x30,0x38,0x38,0x33,0x30,0x38,0x39, - 0x33,0x30,0x39,0x30,0x33,0x30,0x39,0x31, - 0x33,0x30,0x39,0x32,0x33,0x30,0x39,0x33, - 0x33,0x30,0x39,0x34,0x33,0x30,0x39,0x35, - 0x33,0x30,0x39,0x36,0x33,0x30,0x39,0x37, - 0x33,0x30,0x39,0x38,0x33,0x30,0x39,0x39, - 0x33,0x31,0x30,0x30,0x33,0x31,0x30,0x31, - 0x33,0x31,0x30,0x32,0x33,0x31,0x30,0x33, - 0x33,0x31,0x30,0x34,0x33,0x31,0x30,0x35, - 0x33,0x31,0x30,0x36,0x33,0x31,0x30,0x37, - 0x33,0x31,0x30,0x38,0x33,0x31,0x30,0x39, - 0x33,0x31,0x31,0x30,0x33,0x31,0x31,0x31, - 0x33,0x31,0x31,0x32,0x33,0x31,0x31,0x33, - 0x33,0x31,0x31,0x34,0x33,0x31,0x31,0x35, - 0x33,0x31,0x31,0x36,0x33,0x31,0x31,0x37, - 0x33,0x31,0x31,0x38,0x33,0x31,0x31,0x39, - 0x33,0x31,0x32,0x30,0x33,0x31,0x32,0x31, - 0x33,0x31,0x32,0x32,0x33,0x31,0x32,0x33, - 0x33,0x31,0x32,0x34,0x33,0x31,0x32,0x35, - 0x33,0x31,0x32,0x36,0x33,0x31,0x32,0x37, - 0x33,0x31,0x32,0x38,0x33,0x31,0x32,0x39, - 0x33,0x31,0x33,0x30,0x33,0x31,0x33,0x31, - 0x33,0x31,0x33,0x32,0x33,0x31,0x33,0x33, - 0x33,0x31,0x33,0x34,0x33,0x31,0x33,0x35, - 0x33,0x31,0x33,0x36,0x33,0x31,0x33,0x37, - 0x33,0x31,0x33,0x38,0x33,0x31,0x33,0x39, - 0x33,0x31,0x34,0x30,0x33,0x31,0x34,0x31, - 0x33,0x31,0x34,0x32,0x33,0x31,0x34,0x33, - 0x33,0x31,0x34,0x34,0x33,0x31,0x34,0x35, - 0x33,0x31,0x34,0x36,0x33,0x31,0x34,0x37, - 0x33,0x31,0x34,0x38,0x33,0x31,0x34,0x39, - 0x33,0x31,0x35,0x30,0x33,0x31,0x35,0x31, - 0x33,0x31,0x35,0x32,0x33,0x31,0x35,0x33, - 0x33,0x31,0x35,0x34,0x33,0x31,0x35,0x35, - 0x33,0x31,0x35,0x36,0x33,0x31,0x35,0x37, - 0x33,0x31,0x35,0x38,0x33,0x31,0x35,0x39, - 0x33,0x31,0x36,0x30,0x33,0x31,0x36,0x31, - 0x33,0x31,0x36,0x32,0x33,0x31,0x36,0x33, - 0x33,0x31,0x36,0x34,0x33,0x31,0x36,0x35, - 0x33,0x31,0x36,0x36,0x33,0x31,0x36,0x37, - 0x33,0x31,0x36,0x38,0x33,0x31,0x36,0x39, - 0x33,0x31,0x37,0x30,0x33,0x31,0x37,0x31, - 0x33,0x31,0x37,0x32,0x33,0x31,0x37,0x33, - 0x33,0x31,0x37,0x34,0x33,0x31,0x37,0x35, - 0x33,0x31,0x37,0x36,0x33,0x31,0x37,0x37, - 0x33,0x31,0x37,0x38,0x33,0x31,0x37,0x39, - 0x33,0x31,0x38,0x30,0x33,0x31,0x38,0x31, - 0x33,0x31,0x38,0x32,0x33,0x31,0x38,0x33, - 0x33,0x31,0x38,0x34,0x33,0x31,0x38,0x35, - 0x33,0x31,0x38,0x36,0x33,0x31,0x38,0x37, - 0x33,0x31,0x38,0x38,0x33,0x31,0x38,0x39, - 0x33,0x31,0x39,0x30,0x33,0x31,0x39,0x31, - 0x33,0x31,0x39,0x32,0x33,0x31,0x39,0x33, - 0x33,0x31,0x39,0x34,0x33,0x31,0x39,0x35, - 0x33,0x31,0x39,0x36,0x33,0x31,0x39,0x37, - 0x33,0x31,0x39,0x38,0x33,0x31,0x39,0x39, - 0x33,0x32,0x30,0x30,0x33,0x32,0x30,0x31, - 0x33,0x32,0x30,0x32,0x33,0x32,0x30,0x33, - 0x33,0x32,0x30,0x34,0x33,0x32,0x30,0x35, - 0x33,0x32,0x30,0x36,0x33,0x32,0x30,0x37, - 0x33,0x32,0x30,0x38,0x33,0x32,0x30,0x39, - 0x33,0x32,0x31,0x30,0x33,0x32,0x31,0x31, - 0x33,0x32,0x31,0x32,0x33,0x32,0x31,0x33, - 0x33,0x32,0x31,0x34,0x33,0x32,0x31,0x35, - 0x33,0x32,0x31,0x36,0x33,0x32,0x31,0x37, - 0x33,0x32,0x31,0x38,0x33,0x32,0x31,0x39, - 0x33,0x32,0x32,0x30,0x33,0x32,0x32,0x31, - 0x33,0x32,0x32,0x32,0x33,0x32,0x32,0x33, - 0x33,0x32,0x32,0x34,0x33,0x32,0x32,0x35, - 0x33,0x32,0x32,0x36,0x33,0x32,0x32,0x37, - 0x33,0x32,0x32,0x38,0x33,0x32,0x32,0x39, - 0x33,0x32,0x33,0x30,0x33,0x32,0x33,0x31, - 0x33,0x32,0x33,0x32,0x33,0x32,0x33,0x33, - 0x33,0x32,0x33,0x34,0x33,0x32,0x33,0x35, - 0x33,0x32,0x33,0x36,0x33,0x32,0x33,0x37, - 0x33,0x32,0x33,0x38,0x33,0x32,0x33,0x39, - 0x33,0x32,0x34,0x30,0x33,0x32,0x34,0x31, - 0x33,0x32,0x34,0x32,0x33,0x32,0x34,0x33, - 0x33,0x32,0x34,0x34,0x33,0x32,0x34,0x35, - 0x33,0x32,0x34,0x36,0x33,0x32,0x34,0x37, - 0x33,0x32,0x34,0x38,0x33,0x32,0x34,0x39, - 0x33,0x32,0x35,0x30,0x33,0x32,0x35,0x31, - 0x33,0x32,0x35,0x32,0x33,0x32,0x35,0x33, - 0x33,0x32,0x35,0x34,0x33,0x32,0x35,0x35, - 0x33,0x32,0x35,0x36,0x33,0x32,0x35,0x37, - 0x33,0x32,0x35,0x38,0x33,0x32,0x35,0x39, - 0x33,0x32,0x36,0x30,0x33,0x32,0x36,0x31, - 0x33,0x32,0x36,0x32,0x33,0x32,0x36,0x33, - 0x33,0x32,0x36,0x34,0x33,0x32,0x36,0x35, - 0x33,0x32,0x36,0x36,0x33,0x32,0x36,0x37, - 0x33,0x32,0x36,0x38,0x33,0x32,0x36,0x39, - 0x33,0x32,0x37,0x30,0x33,0x32,0x37,0x31, - 0x33,0x32,0x37,0x32,0x33,0x32,0x37,0x33, - 0x33,0x32,0x37,0x34,0x33,0x32,0x37,0x35, - 0x33,0x32,0x37,0x36,0x33,0x32,0x37,0x37, - 0x33,0x32,0x37,0x38,0x33,0x32,0x37,0x39, - 0x33,0x32,0x38,0x30,0x33,0x32,0x38,0x31, - 0x33,0x32,0x38,0x32,0x33,0x32,0x38,0x33, - 0x33,0x32,0x38,0x34,0x33,0x32,0x38,0x35, - 0x33,0x32,0x38,0x36,0x33,0x32,0x38,0x37, - 0x33,0x32,0x38,0x38,0x33,0x32,0x38,0x39, - 0x33,0x32,0x39,0x30,0x33,0x32,0x39,0x31, - 0x33,0x32,0x39,0x32,0x33,0x32,0x39,0x33, - 0x33,0x32,0x39,0x34,0x33,0x32,0x39,0x35, - 0x33,0x32,0x39,0x36,0x33,0x32,0x39,0x37, - 0x33,0x32,0x39,0x38,0x33,0x32,0x39,0x39, - 0x33,0x33,0x30,0x30,0x33,0x33,0x30,0x31, - 0x33,0x33,0x30,0x32,0x33,0x33,0x30,0x33, - 0x33,0x33,0x30,0x34,0x33,0x33,0x30,0x35, - 0x33,0x33,0x30,0x36,0x33,0x33,0x30,0x37, - 0x33,0x33,0x30,0x38,0x33,0x33,0x30,0x39, - 0x33,0x33,0x31,0x30,0x33,0x33,0x31,0x31, - 0x33,0x33,0x31,0x32,0x33,0x33,0x31,0x33, - 0x33,0x33,0x31,0x34,0x33,0x33,0x31,0x35, - 0x33,0x33,0x31,0x36,0x33,0x33,0x31,0x37, - 0x33,0x33,0x31,0x38,0x33,0x33,0x31,0x39, - 0x33,0x33,0x32,0x30,0x33,0x33,0x32,0x31, - 0x33,0x33,0x32,0x32,0x33,0x33,0x32,0x33, - 0x33,0x33,0x32,0x34,0x33,0x33,0x32,0x35, - 0x33,0x33,0x32,0x36,0x33,0x33,0x32,0x37, - 0x33,0x33,0x32,0x38,0x33,0x33,0x32,0x39, - 0x33,0x33,0x33,0x30,0x33,0x33,0x33,0x31, - 0x33,0x33,0x33,0x32,0x33,0x33,0x33,0x33, - 0x33,0x33,0x33,0x34,0x33,0x33,0x33,0x35, - 0x33,0x33,0x33,0x36,0x33,0x33,0x33,0x37, - 0x33,0x33,0x33,0x38,0x33,0x33,0x33,0x39, - 0x33,0x33,0x34,0x30,0x33,0x33,0x34,0x31, - 0x33,0x33,0x34,0x32,0x33,0x33,0x34,0x33, - 0x33,0x33,0x34,0x34,0x33,0x33,0x34,0x35, - 0x33,0x33,0x34,0x36,0x33,0x33,0x34,0x37, - 0x33,0x33,0x34,0x38,0x33,0x33,0x34,0x39, - 0x33,0x33,0x35,0x30,0x33,0x33,0x35,0x31, - 0x33,0x33,0x35,0x32,0x33,0x33,0x35,0x33, - 0x33,0x33,0x35,0x34,0x33,0x33,0x35,0x35, - 0x33,0x33,0x35,0x36,0x33,0x33,0x35,0x37, - 0x33,0x33,0x35,0x38,0x33,0x33,0x35,0x39, - 0x33,0x33,0x36,0x30,0x33,0x33,0x36,0x31, - 0x33,0x33,0x36,0x32,0x33,0x33,0x36,0x33, - 0x33,0x33,0x36,0x34,0x33,0x33,0x36,0x35, - 0x33,0x33,0x36,0x36,0x33,0x33,0x36,0x37, - 0x33,0x33,0x36,0x38,0x33,0x33,0x36,0x39, - 0x33,0x33,0x37,0x30,0x33,0x33,0x37,0x31, - 0x33,0x33,0x37,0x32,0x33,0x33,0x37,0x33, - 0x33,0x33,0x37,0x34,0x33,0x33,0x37,0x35, - 0x33,0x33,0x37,0x36,0x33,0x33,0x37,0x37, - 0x33,0x33,0x37,0x38,0x33,0x33,0x37,0x39, - 0x33,0x33,0x38,0x30,0x33,0x33,0x38,0x31, - 0x33,0x33,0x38,0x32,0x33,0x33,0x38,0x33, - 0x33,0x33,0x38,0x34,0x33,0x33,0x38,0x35, - 0x33,0x33,0x38,0x36,0x33,0x33,0x38,0x37, - 0x33,0x33,0x38,0x38,0x33,0x33,0x38,0x39, - 0x33,0x33,0x39,0x30,0x33,0x33,0x39,0x31, - 0x33,0x33,0x39,0x32,0x33,0x33,0x39,0x33, - 0x33,0x33,0x39,0x34,0x33,0x33,0x39,0x35, - 0x33,0x33,0x39,0x36,0x33,0x33,0x39,0x37, - 0x33,0x33,0x39,0x38,0x33,0x33,0x39,0x39, - 0x33,0x34,0x30,0x30,0x33,0x34,0x30,0x31, - 0x33,0x34,0x30,0x32,0x33,0x34,0x30,0x33, - 0x33,0x34,0x30,0x34,0x33,0x34,0x30,0x35, - 0x33,0x34,0x30,0x36,0x33,0x34,0x30,0x37, - 0x33,0x34,0x30,0x38,0x33,0x34,0x30,0x39, - 0x33,0x34,0x31,0x30,0x33,0x34,0x31,0x31, - 0x33,0x34,0x31,0x32,0x33,0x34,0x31,0x33, - 0x33,0x34,0x31,0x34,0x33,0x34,0x31,0x35, - 0x33,0x34,0x31,0x36,0x33,0x34,0x31,0x37, - 0x33,0x34,0x31,0x38,0x33,0x34,0x31,0x39, - 0x33,0x34,0x32,0x30,0x33,0x34,0x32,0x31, - 0x33,0x34,0x32,0x32,0x33,0x34,0x32,0x33, - 0x33,0x34,0x32,0x34,0x33,0x34,0x32,0x35, - 0x33,0x34,0x32,0x36,0x33,0x34,0x32,0x37, - 0x33,0x34,0x32,0x38,0x33,0x34,0x32,0x39, - 0x33,0x34,0x33,0x30,0x33,0x34,0x33,0x31, - 0x33,0x34,0x33,0x32,0x33,0x34,0x33,0x33, - 0x33,0x34,0x33,0x34,0x33,0x34,0x33,0x35, - 0x33,0x34,0x33,0x36,0x33,0x34,0x33,0x37, - 0x33,0x34,0x33,0x38,0x33,0x34,0x33,0x39, - 0x33,0x34,0x34,0x30,0x33,0x34,0x34,0x31, - 0x33,0x34,0x34,0x32,0x33,0x34,0x34,0x33, - 0x33,0x34,0x34,0x34,0x33,0x34,0x34,0x35, - 0x33,0x34,0x34,0x36,0x33,0x34,0x34,0x37, - 0x33,0x34,0x34,0x38,0x33,0x34,0x34,0x39, - 0x33,0x34,0x35,0x30,0x33,0x34,0x35,0x31, - 0x33,0x34,0x35,0x32,0x33,0x34,0x35,0x33, - 0x33,0x34,0x35,0x34,0x33,0x34,0x35,0x35, - 0x33,0x34,0x35,0x36,0x33,0x34,0x35,0x37, - 0x33,0x34,0x35,0x38,0x33,0x34,0x35,0x39, - 0x33,0x34,0x36,0x30,0x33,0x34,0x36,0x31, - 0x33,0x34,0x36,0x32,0x33,0x34,0x36,0x33, - 0x33,0x34,0x36,0x34,0x33,0x34,0x36,0x35, - 0x33,0x34,0x36,0x36,0x33,0x34,0x36,0x37, - 0x33,0x34,0x36,0x38,0x33,0x34,0x36,0x39, - 0x33,0x34,0x37,0x30,0x33,0x34,0x37,0x31, - 0x33,0x34,0x37,0x32,0x33,0x34,0x37,0x33, - 0x33,0x34,0x37,0x34,0x33,0x34,0x37,0x35, - 0x33,0x34,0x37,0x36,0x33,0x34,0x37,0x37, - 0x33,0x34,0x37,0x38,0x33,0x34,0x37,0x39, - 0x33,0x34,0x38,0x30,0x33,0x34,0x38,0x31, - 0x33,0x34,0x38,0x32,0x33,0x34,0x38,0x33, - 0x33,0x34,0x38,0x34,0x33,0x34,0x38,0x35, - 0x33,0x34,0x38,0x36,0x33,0x34,0x38,0x37, - 0x33,0x34,0x38,0x38,0x33,0x34,0x38,0x39, - 0x33,0x34,0x39,0x30,0x33,0x34,0x39,0x31, - 0x33,0x34,0x39,0x32,0x33,0x34,0x39,0x33, - 0x33,0x34,0x39,0x34,0x33,0x34,0x39,0x35, - 0x33,0x34,0x39,0x36,0x33,0x34,0x39,0x37, - 0x33,0x34,0x39,0x38,0x33,0x34,0x39,0x39, - 0x33,0x35,0x30,0x30,0x33,0x35,0x30,0x31, - 0x33,0x35,0x30,0x32,0x33,0x35,0x30,0x33, - 0x33,0x35,0x30,0x34,0x33,0x35,0x30,0x35, - 0x33,0x35,0x30,0x36,0x33,0x35,0x30,0x37, - 0x33,0x35,0x30,0x38,0x33,0x35,0x30,0x39, - 0x33,0x35,0x31,0x30,0x33,0x35,0x31,0x31, - 0x33,0x35,0x31,0x32,0x33,0x35,0x31,0x33, - 0x33,0x35,0x31,0x34,0x33,0x35,0x31,0x35, - 0x33,0x35,0x31,0x36,0x33,0x35,0x31,0x37, - 0x33,0x35,0x31,0x38,0x33,0x35,0x31,0x39, - 0x33,0x35,0x32,0x30,0x33,0x35,0x32,0x31, - 0x33,0x35,0x32,0x32,0x33,0x35,0x32,0x33, - 0x33,0x35,0x32,0x34,0x33,0x35,0x32,0x35, - 0x33,0x35,0x32,0x36,0x33,0x35,0x32,0x37, - 0x33,0x35,0x32,0x38,0x33,0x35,0x32,0x39, - 0x33,0x35,0x33,0x30,0x33,0x35,0x33,0x31, - 0x33,0x35,0x33,0x32,0x33,0x35,0x33,0x33, - 0x33,0x35,0x33,0x34,0x33,0x35,0x33,0x35, - 0x33,0x35,0x33,0x36,0x33,0x35,0x33,0x37, - 0x33,0x35,0x33,0x38,0x33,0x35,0x33,0x39, - 0x33,0x35,0x34,0x30,0x33,0x35,0x34,0x31, - 0x33,0x35,0x34,0x32,0x33,0x35,0x34,0x33, - 0x33,0x35,0x34,0x34,0x33,0x35,0x34,0x35, - 0x33,0x35,0x34,0x36,0x33,0x35,0x34,0x37, - 0x33,0x35,0x34,0x38,0x33,0x35,0x34,0x39, - 0x33,0x35,0x35,0x30,0x33,0x35,0x35,0x31, - 0x33,0x35,0x35,0x32,0x33,0x35,0x35,0x33, - 0x33,0x35,0x35,0x34,0x33,0x35,0x35,0x35, - 0x33,0x35,0x35,0x36,0x33,0x35,0x35,0x37, - 0x33,0x35,0x35,0x38,0x33,0x35,0x35,0x39, - 0x33,0x35,0x36,0x30,0x33,0x35,0x36,0x31, - 0x33,0x35,0x36,0x32,0x33,0x35,0x36,0x33, - 0x33,0x35,0x36,0x34,0x33,0x35,0x36,0x35, - 0x33,0x35,0x36,0x36,0x33,0x35,0x36,0x37, - 0x33,0x35,0x36,0x38,0x33,0x35,0x36,0x39, - 0x33,0x35,0x37,0x30,0x33,0x35,0x37,0x31, - 0x33,0x35,0x37,0x32,0x33,0x35,0x37,0x33, - 0x33,0x35,0x37,0x34,0x33,0x35,0x37,0x35, - 0x33,0x35,0x37,0x36,0x33,0x35,0x37,0x37, - 0x33,0x35,0x37,0x38,0x33,0x35,0x37,0x39, - 0x33,0x35,0x38,0x30,0x33,0x35,0x38,0x31, - 0x33,0x35,0x38,0x32,0x33,0x35,0x38,0x33, - 0x33,0x35,0x38,0x34,0x33,0x35,0x38,0x35, - 0x33,0x35,0x38,0x36,0x33,0x35,0x38,0x37, - 0x33,0x35,0x38,0x38,0x33,0x35,0x38,0x39, - 0x33,0x35,0x39,0x30,0x33,0x35,0x39,0x31, - 0x33,0x35,0x39,0x32,0x33,0x35,0x39,0x33, - 0x33,0x35,0x39,0x34,0x33,0x35,0x39,0x35, - 0x33,0x35,0x39,0x36,0x33,0x35,0x39,0x37, - 0x33,0x35,0x39,0x38,0x33,0x35,0x39,0x39, - 0x33,0x36,0x30,0x30,0x33,0x36,0x30,0x31, - 0x33,0x36,0x30,0x32,0x33,0x36,0x30,0x33, - 0x33,0x36,0x30,0x34,0x33,0x36,0x30,0x35, - 0x33,0x36,0x30,0x36,0x33,0x36,0x30,0x37, - 0x33,0x36,0x30,0x38,0x33,0x36,0x30,0x39, - 0x33,0x36,0x31,0x30,0x33,0x36,0x31,0x31, - 0x33,0x36,0x31,0x32,0x33,0x36,0x31,0x33, - 0x33,0x36,0x31,0x34,0x33,0x36,0x31,0x35, - 0x33,0x36,0x31,0x36,0x33,0x36,0x31,0x37, - 0x33,0x36,0x31,0x38,0x33,0x36,0x31,0x39, - 0x33,0x36,0x32,0x30,0x33,0x36,0x32,0x31, - 0x33,0x36,0x32,0x32,0x33,0x36,0x32,0x33, - 0x33,0x36,0x32,0x34,0x33,0x36,0x32,0x35, - 0x33,0x36,0x32,0x36,0x33,0x36,0x32,0x37, - 0x33,0x36,0x32,0x38,0x33,0x36,0x32,0x39, - 0x33,0x36,0x33,0x30,0x33,0x36,0x33,0x31, - 0x33,0x36,0x33,0x32,0x33,0x36,0x33,0x33, - 0x33,0x36,0x33,0x34,0x33,0x36,0x33,0x35, - 0x33,0x36,0x33,0x36,0x33,0x36,0x33,0x37, - 0x33,0x36,0x33,0x38,0x33,0x36,0x33,0x39, - 0x33,0x36,0x34,0x30,0x33,0x36,0x34,0x31, - 0x33,0x36,0x34,0x32,0x33,0x36,0x34,0x33, - 0x33,0x36,0x34,0x34,0x33,0x36,0x34,0x35, - 0x33,0x36,0x34,0x36,0x33,0x36,0x34,0x37, - 0x33,0x36,0x34,0x38,0x33,0x36,0x34,0x39, - 0x33,0x36,0x35,0x30,0x33,0x36,0x35,0x31, - 0x33,0x36,0x35,0x32,0x33,0x36,0x35,0x33, - 0x33,0x36,0x35,0x34,0x33,0x36,0x35,0x35, - 0x33,0x36,0x35,0x36,0x33,0x36,0x35,0x37, - 0x33,0x36,0x35,0x38,0x33,0x36,0x35,0x39, - 0x33,0x36,0x36,0x30,0x33,0x36,0x36,0x31, - 0x33,0x36,0x36,0x32,0x33,0x36,0x36,0x33, - 0x33,0x36,0x36,0x34,0x33,0x36,0x36,0x35, - 0x33,0x36,0x36,0x36,0x33,0x36,0x36,0x37, - 0x33,0x36,0x36,0x38,0x33,0x36,0x36,0x39, - 0x33,0x36,0x37,0x30,0x33,0x36,0x37,0x31, - 0x33,0x36,0x37,0x32,0x33,0x36,0x37,0x33, - 0x33,0x36,0x37,0x34,0x33,0x36,0x37,0x35, - 0x33,0x36,0x37,0x36,0x33,0x36,0x37,0x37, - 0x33,0x36,0x37,0x38,0x33,0x36,0x37,0x39, - 0x33,0x36,0x38,0x30,0x33,0x36,0x38,0x31, - 0x33,0x36,0x38,0x32,0x33,0x36,0x38,0x33, - 0x33,0x36,0x38,0x34,0x33,0x36,0x38,0x35, - 0x33,0x36,0x38,0x36,0x33,0x36,0x38,0x37, - 0x33,0x36,0x38,0x38,0x33,0x36,0x38,0x39, - 0x33,0x36,0x39,0x30,0x33,0x36,0x39,0x31, - 0x33,0x36,0x39,0x32,0x33,0x36,0x39,0x33, - 0x33,0x36,0x39,0x34,0x33,0x36,0x39,0x35, - 0x33,0x36,0x39,0x36,0x33,0x36,0x39,0x37, - 0x33,0x36,0x39,0x38,0x33,0x36,0x39,0x39, - 0x33,0x37,0x30,0x30,0x33,0x37,0x30,0x31, - 0x33,0x37,0x30,0x32,0x33,0x37,0x30,0x33, - 0x33,0x37,0x30,0x34,0x33,0x37,0x30,0x35, - 0x33,0x37,0x30,0x36,0x33,0x37,0x30,0x37, - 0x33,0x37,0x30,0x38,0x33,0x37,0x30,0x39, - 0x33,0x37,0x31,0x30,0x33,0x37,0x31,0x31, - 0x33,0x37,0x31,0x32,0x33,0x37,0x31,0x33, - 0x33,0x37,0x31,0x34,0x33,0x37,0x31,0x35, - 0x33,0x37,0x31,0x36,0x33,0x37,0x31,0x37, - 0x33,0x37,0x31,0x38,0x33,0x37,0x31,0x39, - 0x33,0x37,0x32,0x30,0x33,0x37,0x32,0x31, - 0x33,0x37,0x32,0x32,0x33,0x37,0x32,0x33, - 0x33,0x37,0x32,0x34,0x33,0x37,0x32,0x35, - 0x33,0x37,0x32,0x36,0x33,0x37,0x32,0x37, - 0x33,0x37,0x32,0x38,0x33,0x37,0x32,0x39, - 0x33,0x37,0x33,0x30,0x33,0x37,0x33,0x31, - 0x33,0x37,0x33,0x32,0x33,0x37,0x33,0x33, - 0x33,0x37,0x33,0x34,0x33,0x37,0x33,0x35, - 0x33,0x37,0x33,0x36,0x33,0x37,0x33,0x37, - 0x33,0x37,0x33,0x38,0x33,0x37,0x33,0x39, - 0x33,0x37,0x34,0x30,0x33,0x37,0x34,0x31, - 0x33,0x37,0x34,0x32,0x33,0x37,0x34,0x33, - 0x33,0x37,0x34,0x34,0x33,0x37,0x34,0x35, - 0x33,0x37,0x34,0x36,0x33,0x37,0x34,0x37, - 0x33,0x37,0x34,0x38,0x33,0x37,0x34,0x39, - 0x33,0x37,0x35,0x30,0x33,0x37,0x35,0x31, - 0x33,0x37,0x35,0x32,0x33,0x37,0x35,0x33, - 0x33,0x37,0x35,0x34,0x33,0x37,0x35,0x35, - 0x33,0x37,0x35,0x36,0x33,0x37,0x35,0x37, - 0x33,0x37,0x35,0x38,0x33,0x37,0x35,0x39, - 0x33,0x37,0x36,0x30,0x33,0x37,0x36,0x31, - 0x33,0x37,0x36,0x32,0x33,0x37,0x36,0x33, - 0x33,0x37,0x36,0x34,0x33,0x37,0x36,0x35, - 0x33,0x37,0x36,0x36,0x33,0x37,0x36,0x37, - 0x33,0x37,0x36,0x38,0x33,0x37,0x36,0x39, - 0x33,0x37,0x37,0x30,0x33,0x37,0x37,0x31, - 0x33,0x37,0x37,0x32,0x33,0x37,0x37,0x33, - 0x33,0x37,0x37,0x34,0x33,0x37,0x37,0x35, - 0x33,0x37,0x37,0x36,0x33,0x37,0x37,0x37, - 0x33,0x37,0x37,0x38,0x33,0x37,0x37,0x39, - 0x33,0x37,0x38,0x30,0x33,0x37,0x38,0x31, - 0x33,0x37,0x38,0x32,0x33,0x37,0x38,0x33, - 0x33,0x37,0x38,0x34,0x33,0x37,0x38,0x35, - 0x33,0x37,0x38,0x36,0x33,0x37,0x38,0x37, - 0x33,0x37,0x38,0x38,0x33,0x37,0x38,0x39, - 0x33,0x37,0x39,0x30,0x33,0x37,0x39,0x31, - 0x33,0x37,0x39,0x32,0x33,0x37,0x39,0x33, - 0x33,0x37,0x39,0x34,0x33,0x37,0x39,0x35, - 0x33,0x37,0x39,0x36,0x33,0x37,0x39,0x37, - 0x33,0x37,0x39,0x38,0x33,0x37,0x39,0x39, - 0x33,0x38,0x30,0x30,0x33,0x38,0x30,0x31, - 0x33,0x38,0x30,0x32,0x33,0x38,0x30,0x33, - 0x33,0x38,0x30,0x34,0x33,0x38,0x30,0x35, - 0x33,0x38,0x30,0x36,0x33,0x38,0x30,0x37, - 0x33,0x38,0x30,0x38,0x33,0x38,0x30,0x39, - 0x33,0x38,0x31,0x30,0x33,0x38,0x31,0x31, - 0x33,0x38,0x31,0x32,0x33,0x38,0x31,0x33, - 0x33,0x38,0x31,0x34,0x33,0x38,0x31,0x35, - 0x33,0x38,0x31,0x36,0x33,0x38,0x31,0x37, - 0x33,0x38,0x31,0x38,0x33,0x38,0x31,0x39, - 0x33,0x38,0x32,0x30,0x33,0x38,0x32,0x31, - 0x33,0x38,0x32,0x32,0x33,0x38,0x32,0x33, - 0x33,0x38,0x32,0x34,0x33,0x38,0x32,0x35, - 0x33,0x38,0x32,0x36,0x33,0x38,0x32,0x37, - 0x33,0x38,0x32,0x38,0x33,0x38,0x32,0x39, - 0x33,0x38,0x33,0x30,0x33,0x38,0x33,0x31, - 0x33,0x38,0x33,0x32,0x33,0x38,0x33,0x33, - 0x33,0x38,0x33,0x34,0x33,0x38,0x33,0x35, - 0x33,0x38,0x33,0x36,0x33,0x38,0x33,0x37, - 0x33,0x38,0x33,0x38,0x33,0x38,0x33,0x39, - 0x33,0x38,0x34,0x30,0x33,0x38,0x34,0x31, - 0x33,0x38,0x34,0x32,0x33,0x38,0x34,0x33, - 0x33,0x38,0x34,0x34,0x33,0x38,0x34,0x35, - 0x33,0x38,0x34,0x36,0x33,0x38,0x34,0x37, - 0x33,0x38,0x34,0x38,0x33,0x38,0x34,0x39, - 0x33,0x38,0x35,0x30,0x33,0x38,0x35,0x31, - 0x33,0x38,0x35,0x32,0x33,0x38,0x35,0x33, - 0x33,0x38,0x35,0x34,0x33,0x38,0x35,0x35, - 0x33,0x38,0x35,0x36,0x33,0x38,0x35,0x37, - 0x33,0x38,0x35,0x38,0x33,0x38,0x35,0x39, - 0x33,0x38,0x36,0x30,0x33,0x38,0x36,0x31, - 0x33,0x38,0x36,0x32,0x33,0x38,0x36,0x33, - 0x33,0x38,0x36,0x34,0x33,0x38,0x36,0x35, - 0x33,0x38,0x36,0x36,0x33,0x38,0x36,0x37, - 0x33,0x38,0x36,0x38,0x33,0x38,0x36,0x39, - 0x33,0x38,0x37,0x30,0x33,0x38,0x37,0x31, - 0x33,0x38,0x37,0x32,0x33,0x38,0x37,0x33, - 0x33,0x38,0x37,0x34,0x33,0x38,0x37,0x35, - 0x33,0x38,0x37,0x36,0x33,0x38,0x37,0x37, - 0x33,0x38,0x37,0x38,0x33,0x38,0x37,0x39, - 0x33,0x38,0x38,0x30,0x33,0x38,0x38,0x31, - 0x33,0x38,0x38,0x32,0x33,0x38,0x38,0x33, - 0x33,0x38,0x38,0x34,0x33,0x38,0x38,0x35, - 0x33,0x38,0x38,0x36,0x33,0x38,0x38,0x37, - 0x33,0x38,0x38,0x38,0x33,0x38,0x38,0x39, - 0x33,0x38,0x39,0x30,0x33,0x38,0x39,0x31, - 0x33,0x38,0x39,0x32,0x33,0x38,0x39,0x33, - 0x33,0x38,0x39,0x34,0x33,0x38,0x39,0x35, - 0x33,0x38,0x39,0x36,0x33,0x38,0x39,0x37, - 0x33,0x38,0x39,0x38,0x33,0x38,0x39,0x39, - 0x33,0x39,0x30,0x30,0x33,0x39,0x30,0x31, - 0x33,0x39,0x30,0x32,0x33,0x39,0x30,0x33, - 0x33,0x39,0x30,0x34,0x33,0x39,0x30,0x35, - 0x33,0x39,0x30,0x36,0x33,0x39,0x30,0x37, - 0x33,0x39,0x30,0x38,0x33,0x39,0x30,0x39, - 0x33,0x39,0x31,0x30,0x33,0x39,0x31,0x31, - 0x33,0x39,0x31,0x32,0x33,0x39,0x31,0x33, - 0x33,0x39,0x31,0x34,0x33,0x39,0x31,0x35, - 0x33,0x39,0x31,0x36,0x33,0x39,0x31,0x37, - 0x33,0x39,0x31,0x38,0x33,0x39,0x31,0x39, - 0x33,0x39,0x32,0x30,0x33,0x39,0x32,0x31, - 0x33,0x39,0x32,0x32,0x33,0x39,0x32,0x33, - 0x33,0x39,0x32,0x34,0x33,0x39,0x32,0x35, - 0x33,0x39,0x32,0x36,0x33,0x39,0x32,0x37, - 0x33,0x39,0x32,0x38,0x33,0x39,0x32,0x39, - 0x33,0x39,0x33,0x30,0x33,0x39,0x33,0x31, - 0x33,0x39,0x33,0x32,0x33,0x39,0x33,0x33, - 0x33,0x39,0x33,0x34,0x33,0x39,0x33,0x35, - 0x33,0x39,0x33,0x36,0x33,0x39,0x33,0x37, - 0x33,0x39,0x33,0x38,0x33,0x39,0x33,0x39, - 0x33,0x39,0x34,0x30,0x33,0x39,0x34,0x31, - 0x33,0x39,0x34,0x32,0x33,0x39,0x34,0x33, - 0x33,0x39,0x34,0x34,0x33,0x39,0x34,0x35, - 0x33,0x39,0x34,0x36,0x33,0x39,0x34,0x37, - 0x33,0x39,0x34,0x38,0x33,0x39,0x34,0x39, - 0x33,0x39,0x35,0x30,0x33,0x39,0x35,0x31, - 0x33,0x39,0x35,0x32,0x33,0x39,0x35,0x33, - 0x33,0x39,0x35,0x34,0x33,0x39,0x35,0x35, - 0x33,0x39,0x35,0x36,0x33,0x39,0x35,0x37, - 0x33,0x39,0x35,0x38,0x33,0x39,0x35,0x39, - 0x33,0x39,0x36,0x30,0x33,0x39,0x36,0x31, - 0x33,0x39,0x36,0x32,0x33,0x39,0x36,0x33, - 0x33,0x39,0x36,0x34,0x33,0x39,0x36,0x35, - 0x33,0x39,0x36,0x36,0x33,0x39,0x36,0x37, - 0x33,0x39,0x36,0x38,0x33,0x39,0x36,0x39, - 0x33,0x39,0x37,0x30,0x33,0x39,0x37,0x31, - 0x33,0x39,0x37,0x32,0x33,0x39,0x37,0x33, - 0x33,0x39,0x37,0x34,0x33,0x39,0x37,0x35, - 0x33,0x39,0x37,0x36,0x33,0x39,0x37,0x37, - 0x33,0x39,0x37,0x38,0x33,0x39,0x37,0x39, - 0x33,0x39,0x38,0x30,0x33,0x39,0x38,0x31, - 0x33,0x39,0x38,0x32,0x33,0x39,0x38,0x33, - 0x33,0x39,0x38,0x34,0x33,0x39,0x38,0x35, - 0x33,0x39,0x38,0x36,0x33,0x39,0x38,0x37, - 0x33,0x39,0x38,0x38,0x33,0x39,0x38,0x39, - 0x33,0x39,0x39,0x30,0x33,0x39,0x39,0x31, - 0x33,0x39,0x39,0x32,0x33,0x39,0x39,0x33, - 0x33,0x39,0x39,0x34,0x33,0x39,0x39,0x35, - 0x33,0x39,0x39,0x36,0x33,0x39,0x39,0x37, - 0x33,0x39,0x39,0x38,0x33,0x39,0x39,0x39, - 0x34,0x30,0x30,0x30,0x34,0x30,0x30,0x31, - 0x34,0x30,0x30,0x32,0x34,0x30,0x30,0x33, - 0x34,0x30,0x30,0x34,0x34,0x30,0x30,0x35, - 0x34,0x30,0x30,0x36,0x34,0x30,0x30,0x37, - 0x34,0x30,0x30,0x38,0x34,0x30,0x30,0x39, - 0x34,0x30,0x31,0x30,0x34,0x30,0x31,0x31, - 0x34,0x30,0x31,0x32,0x34,0x30,0x31,0x33, - 0x34,0x30,0x31,0x34,0x34,0x30,0x31,0x35, - 0x34,0x30,0x31,0x36,0x34,0x30,0x31,0x37, - 0x34,0x30,0x31,0x38,0x34,0x30,0x31,0x39, - 0x34,0x30,0x32,0x30,0x34,0x30,0x32,0x31, - 0x34,0x30,0x32,0x32,0x34,0x30,0x32,0x33, - 0x34,0x30,0x32,0x34,0x34,0x30,0x32,0x35, - 0x34,0x30,0x32,0x36,0x34,0x30,0x32,0x37, - 0x34,0x30,0x32,0x38,0x34,0x30,0x32,0x39, - 0x34,0x30,0x33,0x30,0x34,0x30,0x33,0x31, - 0x34,0x30,0x33,0x32,0x34,0x30,0x33,0x33, - 0x34,0x30,0x33,0x34,0x34,0x30,0x33,0x35, - 0x34,0x30,0x33,0x36,0x34,0x30,0x33,0x37, - 0x34,0x30,0x33,0x38,0x34,0x30,0x33,0x39, - 0x34,0x30,0x34,0x30,0x34,0x30,0x34,0x31, - 0x34,0x30,0x34,0x32,0x34,0x30,0x34,0x33, - 0x34,0x30,0x34,0x34,0x34,0x30,0x34,0x35, - 0x34,0x30,0x34,0x36,0x34,0x30,0x34,0x37, - 0x34,0x30,0x34,0x38,0x34,0x30,0x34,0x39, - 0x34,0x30,0x35,0x30,0x34,0x30,0x35,0x31, - 0x34,0x30,0x35,0x32,0x34,0x30,0x35,0x33, - 0x34,0x30,0x35,0x34,0x34,0x30,0x35,0x35, - 0x34,0x30,0x35,0x36,0x34,0x30,0x35,0x37, - 0x34,0x30,0x35,0x38,0x34,0x30,0x35,0x39, - 0x34,0x30,0x36,0x30,0x34,0x30,0x36,0x31, - 0x34,0x30,0x36,0x32,0x34,0x30,0x36,0x33, - 0x34,0x30,0x36,0x34,0x34,0x30,0x36,0x35, - 0x34,0x30,0x36,0x36,0x34,0x30,0x36,0x37, - 0x34,0x30,0x36,0x38,0x34,0x30,0x36,0x39, - 0x34,0x30,0x37,0x30,0x34,0x30,0x37,0x31, - 0x34,0x30,0x37,0x32,0x34,0x30,0x37,0x33, - 0x34,0x30,0x37,0x34,0x34,0x30,0x37,0x35, - 0x34,0x30,0x37,0x36,0x34,0x30,0x37,0x37, - 0x34,0x30,0x37,0x38,0x34,0x30,0x37,0x39, - 0x34,0x30,0x38,0x30,0x34,0x30,0x38,0x31, - 0x34,0x30,0x38,0x32,0x34,0x30,0x38,0x33, - 0x34,0x30,0x38,0x34,0x34,0x30,0x38,0x35, - 0x34,0x30,0x38,0x36,0x34,0x30,0x38,0x37, - 0x34,0x30,0x38,0x38,0x34,0x30,0x38,0x39, - 0x34,0x30,0x39,0x30,0x34,0x30,0x39,0x31, - 0x34,0x30,0x39,0x32,0x34,0x30,0x39,0x33, - 0x34,0x30,0x39,0x34,0x34,0x30,0x39,0x35}; - - static const int32_t gDigitCount[] = { - 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,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,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,2,2,2, - 2,2,2,2,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 3,3,3,3,3,3,3,3, - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 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, - 4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4}; - -U_NAMESPACE_BEGIN - - -IntDigitCountRange::IntDigitCountRange(int32_t min, int32_t max) { - fMin = min < 0 ? 0 : min; - fMax = max < fMin ? fMin : max; -} - -int32_t -IntDigitCountRange::pin(int32_t digitCount) const { - return digitCount < fMin ? fMin : (digitCount < fMax ? digitCount : fMax); -} - -int32_t -SmallIntFormatter::estimateDigitCount( - int32_t positiveValue, const IntDigitCountRange &range) { - if (positiveValue >= gMaxFastInt) { - return range.getMax(); - } - return range.pin(gDigitCount[positiveValue]); -} - -UBool -SmallIntFormatter::canFormat( - int32_t positiveValue, const IntDigitCountRange &range) { - return (positiveValue < gMaxFastInt && range.getMin() <= 4); -} - -UnicodeString & -SmallIntFormatter::format( - int32_t smallPositiveValue, - const IntDigitCountRange &range, - UnicodeString &appendTo) { - int32_t digits = range.pin(gDigitCount[smallPositiveValue]); - - // Always emit at least '0' - if (digits == 0) { - return appendTo.append((UChar) 0x30); - } - return appendTo.append(gDigits, ((smallPositiveValue + 1) << 2) - digits, digits); -} - -U_NAMESPACE_END diff --git a/deps/icu-small/source/i18n/smallintformatter.h b/deps/icu-small/source/i18n/smallintformatter.h deleted file mode 100644 index 3373a9c35ff..00000000000 --- a/deps/icu-small/source/i18n/smallintformatter.h +++ /dev/null @@ -1,90 +0,0 @@ -// © 2016 and later: Unicode, Inc. and others. -// License & terms of use: http://www.unicode.org/copyright.html -/* -******************************************************************************* -* Copyright (C) 2015, International Business Machines -* Corporation and others. All Rights Reserved. -******************************************************************************* -* smallintformatter.h -* -* created on: 2015jan06 -* created by: Travis Keep -*/ - -#ifndef __SMALLINTFORMATTER_H__ -#define __SMALLINTFORMATTER_H__ - -#include "unicode/uobject.h" -#include "unicode/utypes.h" - -U_NAMESPACE_BEGIN - -class UnicodeString; - -/** - * A representation an acceptable range of digit counts for integers. - */ -class U_I18N_API IntDigitCountRange : public UMemory { -public: - /** - * No constraints: 0 up to INT32_MAX - */ - IntDigitCountRange() : fMin(0), fMax(INT32_MAX) { } - IntDigitCountRange(int32_t min, int32_t max); - int32_t pin(int32_t digitCount) const; - int32_t getMax() const { return fMax; } - int32_t getMin() const { return fMin; } -private: - int32_t fMin; - int32_t fMax; -}; - - -/** - * A formatter for small, positive integers. - */ -class U_I18N_API SmallIntFormatter : public UMemory { -public: - /** - * Estimates the actual digit count needed to format positiveValue - * using the given range of digit counts. - * Returns a value that is at least the actual digit count needed. - * - * @param positiveValue the value to format - * @param range the acceptable range of digit counts. - */ - static int32_t estimateDigitCount( - int32_t positiveValue, const IntDigitCountRange &range); - - /** - * Returns TRUE if this class can format positiveValue using - * the given range of digit counts. - * - * @param positiveValue the value to format - * @param range the acceptable range of digit counts. - */ - static UBool canFormat( - int32_t positiveValue, const IntDigitCountRange &range); - - /** - * Formats positiveValue using the given range of digit counts. - * Always uses standard digits '0' through '9'. Formatted value is - * left padded with '0' as necessary to achieve minimum digit count. - * Does not produce any grouping separators or trailing decimal point. - * Calling format to format a value with a particular digit count range - * when canFormat indicates that the same value and digit count range - * cannot be formatted results in undefined behavior. - * - * @param positiveValue the value to format - * @param range the acceptable range of digit counts. - */ - static UnicodeString &format( - int32_t positiveValue, - const IntDigitCountRange &range, - UnicodeString &appendTo); - -}; - -U_NAMESPACE_END - -#endif // __SMALLINTFORMATTER_H__ diff --git a/deps/icu-small/source/i18n/smpdtfmt.cpp b/deps/icu-small/source/i18n/smpdtfmt.cpp index 27fbbd8f7a9..b1b90882fce 100644 --- a/deps/icu-small/source/i18n/smpdtfmt.cpp +++ b/deps/icu-small/source/i18n/smpdtfmt.cpp @@ -53,6 +53,7 @@ #include "unicode/vtzone.h" #include "unicode/udisplaycontext.h" #include "unicode/brkiter.h" +#include "unicode/rbnf.h" #include "uresimp.h" #include "olsontz.h" #include "patternprops.h" @@ -72,6 +73,7 @@ #include "cstr.h" #include "dayperiodrules.h" #include "tznames_impl.h" // ZONE_NAME_U16_MAX +#include "number_utypes.h" #if defined( U_DEBUG_CALSVC ) || defined (U_DEBUG_CAL) #include @@ -312,57 +314,6 @@ const NumberFormat *SimpleDateFormat::getNumberFormatByIndex( return &(**fSharedNumberFormatters[index]); } -class SimpleDateFormatMutableNFNode { - public: - const NumberFormat *key; - NumberFormat *value; - SimpleDateFormatMutableNFNode() - : key(NULL), value(NULL) { } - ~SimpleDateFormatMutableNFNode() { - delete value; - } - private: - SimpleDateFormatMutableNFNode(const SimpleDateFormatMutableNFNode &); - SimpleDateFormatMutableNFNode &operator=(const SimpleDateFormatMutableNFNode &); -}; - -// Single threaded cache of non const NumberFormats. Designed to be stack -// allocated and used for a single format call. -class SimpleDateFormatMutableNFs : public UMemory { - public: - SimpleDateFormatMutableNFs() { - } - - // Returns a non-const clone of nf which can be safely modified. - // Subsequent calls with same nf will return the same non-const clone. - // This object maintains ownership of all returned non-const - // NumberFormat objects. On memory allocation error returns NULL. - // Caller must check for NULL return value. - NumberFormat *get(const NumberFormat *nf) { - if (nf == NULL) { - return NULL; - } - int32_t idx = 0; - while (nodes[idx].value) { - if (nf == nodes[idx].key) { - return nodes[idx].value; - } - ++idx; - } - U_ASSERT(idx < UDAT_FIELD_COUNT); - nodes[idx].key = nf; - nodes[idx].value = (NumberFormat *) nf->clone(); - return nodes[idx].value; - } - private: - // +1 extra for sentinel. If each field had its own NumberFormat, this - // cache would have to allocate UDAT_FIELD_COUNT mutable versions worst - // case. - SimpleDateFormatMutableNFNode nodes[UDAT_FIELD_COUNT + 1]; - SimpleDateFormatMutableNFs(const SimpleDateFormatMutableNFs &); - SimpleDateFormatMutableNFs &operator=(const SimpleDateFormatMutableNFs &); -}; - //---------------------------------------------------------------------- SimpleDateFormat::~SimpleDateFormat() @@ -374,6 +325,7 @@ SimpleDateFormat::~SimpleDateFormat() if (fTimeZoneFormat) { delete fTimeZoneFormat; } + freeFastNumberFormatters(); #if !UCONFIG_NO_BREAK_ITERATION delete fCapitalizationBrkIter; @@ -659,6 +611,10 @@ SimpleDateFormat& SimpleDateFormat::operator=(const SimpleDateFormat& other) } } + UErrorCode localStatus = U_ZERO_ERROR; + freeFastNumberFormatters(); + initFastNumberFormatters(localStatus); + return *this; } @@ -908,7 +864,8 @@ SimpleDateFormat::initialize(const Locale& locale, fixNumberFormatForDates(*fNumberFormat); //fNumberFormat->setLenient(TRUE); // Java uses a custom DateNumberFormat to format/parse - initNumberFormatters(locale,status); + initNumberFormatters(locale, status); + initFastNumberFormatters(status); } else if (U_SUCCESS(status)) @@ -1023,11 +980,6 @@ SimpleDateFormat::_format(Calendar& cal, UnicodeString& appendTo, int32_t fieldNum = 0; UDisplayContext capitalizationContext = getContext(UDISPCTX_TYPE_CAPITALIZATION, status); - // Create temporary cache of mutable number format objects. This way - // subFormat won't have to clone the const NumberFormat for each field. - // if several fields share the same NumberFormat, which will almost - // always be the case, this is a big save. - SimpleDateFormatMutableNFs mutableNFs; // loop through the pattern string character by character for (int32_t i = 0; i < fPattern.length() && U_SUCCESS(status); ++i) { UChar ch = fPattern[i]; @@ -1035,7 +987,7 @@ SimpleDateFormat::_format(Calendar& cal, UnicodeString& appendTo, // Use subFormat() to format a repeated pattern character // when a different pattern or non-pattern character is seen if (ch != prevCh && count > 0) { - subFormat(appendTo, prevCh, count, capitalizationContext, fieldNum++, handler, *workCal, mutableNFs, status); + subFormat(appendTo, prevCh, count, capitalizationContext, fieldNum++, handler, *workCal, status); count = 0; } if (ch == QUOTE) { @@ -1062,7 +1014,7 @@ SimpleDateFormat::_format(Calendar& cal, UnicodeString& appendTo, // Format the last item in the pattern, if any if (count > 0) { - subFormat(appendTo, prevCh, count, capitalizationContext, fieldNum++, handler, *workCal, mutableNFs, status); + subFormat(appendTo, prevCh, count, capitalizationContext, fieldNum++, handler, *workCal, status); } if (calClone != NULL) { @@ -1257,6 +1209,43 @@ _appendSymbolWithMonthPattern(UnicodeString& dst, int32_t value, const UnicodeSt } //---------------------------------------------------------------------- + +static number::LocalizedNumberFormatter* +createFastFormatter(const DecimalFormat* df, int32_t minInt, int32_t maxInt) { + return new number::LocalizedNumberFormatter( + df->toNumberFormatter() + .integerWidth(number::IntegerWidth::zeroFillTo(minInt).truncateAt(maxInt))); +} + +void SimpleDateFormat::initFastNumberFormatters(UErrorCode& status) { + if (U_FAILURE(status)) { + return; + } + auto* df = dynamic_cast(fNumberFormat); + if (df == nullptr) { + return; + } + fFastNumberFormatters[SMPDTFMT_NF_1x10] = createFastFormatter(df, 1, 10); + fFastNumberFormatters[SMPDTFMT_NF_2x10] = createFastFormatter(df, 2, 10); + fFastNumberFormatters[SMPDTFMT_NF_3x10] = createFastFormatter(df, 3, 10); + fFastNumberFormatters[SMPDTFMT_NF_4x10] = createFastFormatter(df, 4, 10); + fFastNumberFormatters[SMPDTFMT_NF_2x2] = createFastFormatter(df, 2, 2); +} + +void SimpleDateFormat::freeFastNumberFormatters() { + delete fFastNumberFormatters[SMPDTFMT_NF_1x10]; + delete fFastNumberFormatters[SMPDTFMT_NF_2x10]; + delete fFastNumberFormatters[SMPDTFMT_NF_3x10]; + delete fFastNumberFormatters[SMPDTFMT_NF_4x10]; + delete fFastNumberFormatters[SMPDTFMT_NF_2x2]; + fFastNumberFormatters[SMPDTFMT_NF_1x10] = nullptr; + fFastNumberFormatters[SMPDTFMT_NF_2x10] = nullptr; + fFastNumberFormatters[SMPDTFMT_NF_3x10] = nullptr; + fFastNumberFormatters[SMPDTFMT_NF_4x10] = nullptr; + fFastNumberFormatters[SMPDTFMT_NF_2x2] = nullptr; +} + + void SimpleDateFormat::initNumberFormatters(const Locale &locale,UErrorCode &status) { if (U_FAILURE(status)) { @@ -1406,7 +1395,6 @@ SimpleDateFormat::subFormat(UnicodeString &appendTo, int32_t fieldNum, FieldPositionHandler& handler, Calendar& cal, - SimpleDateFormatMutableNFs &mutableNFs, UErrorCode& status) const { if (U_FAILURE(status)) { @@ -1419,7 +1407,7 @@ SimpleDateFormat::subFormat(UnicodeString &appendTo, UDateFormatField patternCharIndex = DateFormatSymbols::getPatternCharIndex(ch); const int32_t maxIntCount = 10; int32_t beginOffset = appendTo.length(); - NumberFormat *currentNumberFormat; + const NumberFormat *currentNumberFormat; DateFormatSymbols::ECapitalizationContextUsageType capContextUsageType = DateFormatSymbols::kCapContextUsageOther; UBool isHebrewCalendar = (uprv_strcmp(cal.getType(),"hebrew") == 0); @@ -1444,9 +1432,9 @@ SimpleDateFormat::subFormat(UnicodeString &appendTo, return; } - currentNumberFormat = mutableNFs.get(getNumberFormatByIndex(patternCharIndex)); + currentNumberFormat = getNumberFormatByIndex(patternCharIndex); if (currentNumberFormat == NULL) { - status = U_MEMORY_ALLOCATION_ERROR; + status = U_INTERNAL_PROGRAM_ERROR; return; } UnicodeString hebr("hebr", 4, US_INV); @@ -1566,18 +1554,15 @@ SimpleDateFormat::subFormat(UnicodeString &appendTo, case UDAT_FRACTIONAL_SECOND_FIELD: // Fractional seconds left-justify { - currentNumberFormat->setMinimumIntegerDigits((count > 3) ? 3 : count); - currentNumberFormat->setMaximumIntegerDigits(maxIntCount); + int32_t minDigits = (count > 3) ? 3 : count; if (count == 1) { value /= 100; } else if (count == 2) { value /= 10; } - FieldPosition p(FieldPosition::DONT_CARE); - currentNumberFormat->format(value, appendTo, p); + zeroPaddingNumber(currentNumberFormat, appendTo, value, minDigits, maxIntCount); if (count > 3) { - currentNumberFormat->setMinimumIntegerDigits(count - 3); - currentNumberFormat->format((int32_t)0, appendTo, p); + zeroPaddingNumber(currentNumberFormat, appendTo, 0, count - 3, maxIntCount); } } break; @@ -1695,100 +1680,101 @@ SimpleDateFormat::subFormat(UnicodeString &appendTo, UnicodeString zoneString(zsbuf, 0, UPRV_LENGTHOF(zsbuf)); const TimeZone& tz = cal.getTimeZone(); UDate date = cal.getTime(status); + const TimeZoneFormat *tzfmt = tzFormat(status); if (U_SUCCESS(status)) { if (patternCharIndex == UDAT_TIMEZONE_FIELD) { if (count < 4) { // "z", "zz", "zzz" - tzFormat()->format(UTZFMT_STYLE_SPECIFIC_SHORT, tz, date, zoneString); + tzfmt->format(UTZFMT_STYLE_SPECIFIC_SHORT, tz, date, zoneString); capContextUsageType = DateFormatSymbols::kCapContextUsageMetazoneShort; } else { // "zzzz" or longer - tzFormat()->format(UTZFMT_STYLE_SPECIFIC_LONG, tz, date, zoneString); + tzfmt->format(UTZFMT_STYLE_SPECIFIC_LONG, tz, date, zoneString); capContextUsageType = DateFormatSymbols::kCapContextUsageMetazoneLong; } } else if (patternCharIndex == UDAT_TIMEZONE_RFC_FIELD) { if (count < 4) { // "Z" - tzFormat()->format(UTZFMT_STYLE_ISO_BASIC_LOCAL_FULL, tz, date, zoneString); + tzfmt->format(UTZFMT_STYLE_ISO_BASIC_LOCAL_FULL, tz, date, zoneString); } else if (count == 5) { // "ZZZZZ" - tzFormat()->format(UTZFMT_STYLE_ISO_EXTENDED_FULL, tz, date, zoneString); + tzfmt->format(UTZFMT_STYLE_ISO_EXTENDED_FULL, tz, date, zoneString); } else { // "ZZ", "ZZZ", "ZZZZ" - tzFormat()->format(UTZFMT_STYLE_LOCALIZED_GMT, tz, date, zoneString); + tzfmt->format(UTZFMT_STYLE_LOCALIZED_GMT, tz, date, zoneString); } } else if (patternCharIndex == UDAT_TIMEZONE_GENERIC_FIELD) { if (count == 1) { // "v" - tzFormat()->format(UTZFMT_STYLE_GENERIC_SHORT, tz, date, zoneString); + tzfmt->format(UTZFMT_STYLE_GENERIC_SHORT, tz, date, zoneString); capContextUsageType = DateFormatSymbols::kCapContextUsageMetazoneShort; } else if (count == 4) { // "vvvv" - tzFormat()->format(UTZFMT_STYLE_GENERIC_LONG, tz, date, zoneString); + tzfmt->format(UTZFMT_STYLE_GENERIC_LONG, tz, date, zoneString); capContextUsageType = DateFormatSymbols::kCapContextUsageMetazoneLong; } } else if (patternCharIndex == UDAT_TIMEZONE_SPECIAL_FIELD) { if (count == 1) { // "V" - tzFormat()->format(UTZFMT_STYLE_ZONE_ID_SHORT, tz, date, zoneString); + tzfmt->format(UTZFMT_STYLE_ZONE_ID_SHORT, tz, date, zoneString); } else if (count == 2) { // "VV" - tzFormat()->format(UTZFMT_STYLE_ZONE_ID, tz, date, zoneString); + tzfmt->format(UTZFMT_STYLE_ZONE_ID, tz, date, zoneString); } else if (count == 3) { // "VVV" - tzFormat()->format(UTZFMT_STYLE_EXEMPLAR_LOCATION, tz, date, zoneString); + tzfmt->format(UTZFMT_STYLE_EXEMPLAR_LOCATION, tz, date, zoneString); } else if (count == 4) { // "VVVV" - tzFormat()->format(UTZFMT_STYLE_GENERIC_LOCATION, tz, date, zoneString); + tzfmt->format(UTZFMT_STYLE_GENERIC_LOCATION, tz, date, zoneString); capContextUsageType = DateFormatSymbols::kCapContextUsageZoneLong; } } else if (patternCharIndex == UDAT_TIMEZONE_LOCALIZED_GMT_OFFSET_FIELD) { if (count == 1) { // "O" - tzFormat()->format(UTZFMT_STYLE_LOCALIZED_GMT_SHORT, tz, date, zoneString); + tzfmt->format(UTZFMT_STYLE_LOCALIZED_GMT_SHORT, tz, date, zoneString); } else if (count == 4) { // "OOOO" - tzFormat()->format(UTZFMT_STYLE_LOCALIZED_GMT, tz, date, zoneString); + tzfmt->format(UTZFMT_STYLE_LOCALIZED_GMT, tz, date, zoneString); } } else if (patternCharIndex == UDAT_TIMEZONE_ISO_FIELD) { if (count == 1) { // "X" - tzFormat()->format(UTZFMT_STYLE_ISO_BASIC_SHORT, tz, date, zoneString); + tzfmt->format(UTZFMT_STYLE_ISO_BASIC_SHORT, tz, date, zoneString); } else if (count == 2) { // "XX" - tzFormat()->format(UTZFMT_STYLE_ISO_BASIC_FIXED, tz, date, zoneString); + tzfmt->format(UTZFMT_STYLE_ISO_BASIC_FIXED, tz, date, zoneString); } else if (count == 3) { // "XXX" - tzFormat()->format(UTZFMT_STYLE_ISO_EXTENDED_FIXED, tz, date, zoneString); + tzfmt->format(UTZFMT_STYLE_ISO_EXTENDED_FIXED, tz, date, zoneString); } else if (count == 4) { // "XXXX" - tzFormat()->format(UTZFMT_STYLE_ISO_BASIC_FULL, tz, date, zoneString); + tzfmt->format(UTZFMT_STYLE_ISO_BASIC_FULL, tz, date, zoneString); } else if (count == 5) { // "XXXXX" - tzFormat()->format(UTZFMT_STYLE_ISO_EXTENDED_FULL, tz, date, zoneString); + tzfmt->format(UTZFMT_STYLE_ISO_EXTENDED_FULL, tz, date, zoneString); } } else if (patternCharIndex == UDAT_TIMEZONE_ISO_LOCAL_FIELD) { if (count == 1) { // "x" - tzFormat()->format(UTZFMT_STYLE_ISO_BASIC_LOCAL_SHORT, tz, date, zoneString); + tzfmt->format(UTZFMT_STYLE_ISO_BASIC_LOCAL_SHORT, tz, date, zoneString); } else if (count == 2) { // "xx" - tzFormat()->format(UTZFMT_STYLE_ISO_BASIC_LOCAL_FIXED, tz, date, zoneString); + tzfmt->format(UTZFMT_STYLE_ISO_BASIC_LOCAL_FIXED, tz, date, zoneString); } else if (count == 3) { // "xxx" - tzFormat()->format(UTZFMT_STYLE_ISO_EXTENDED_LOCAL_FIXED, tz, date, zoneString); + tzfmt->format(UTZFMT_STYLE_ISO_EXTENDED_LOCAL_FIXED, tz, date, zoneString); } else if (count == 4) { // "xxxx" - tzFormat()->format(UTZFMT_STYLE_ISO_BASIC_LOCAL_FULL, tz, date, zoneString); + tzfmt->format(UTZFMT_STYLE_ISO_BASIC_LOCAL_FULL, tz, date, zoneString); } else if (count == 5) { // "xxxxx" - tzFormat()->format(UTZFMT_STYLE_ISO_EXTENDED_LOCAL_FULL, tz, date, zoneString); + tzfmt->format(UTZFMT_STYLE_ISO_EXTENDED_LOCAL_FULL, tz, date, zoneString); } } else { @@ -1855,7 +1841,7 @@ SimpleDateFormat::subFormat(UnicodeString &appendTo, if (toAppend == NULL || toAppend->isBogus()) { // Reformat with identical arguments except ch, now changed to 'a'. subFormat(appendTo, 0x61, count, capitalizationContext, fieldNum, - handler, cal, mutableNFs, status); + handler, cal, status); } else { appendTo += *toAppend; } @@ -1876,7 +1862,7 @@ SimpleDateFormat::subFormat(UnicodeString &appendTo, // Data doesn't exist for the locale we're looking for. // Falling back to am/pm. subFormat(appendTo, 0x61, count, capitalizationContext, fieldNum, - handler, cal, mutableNFs, status); + handler, cal, status); break; } @@ -1947,7 +1933,7 @@ SimpleDateFormat::subFormat(UnicodeString &appendTo, periodType == DayPeriodRules::DAYPERIOD_PM || toAppend->isBogus()) { subFormat(appendTo, 0x61, count, capitalizationContext, fieldNum, - handler, cal, mutableNFs, status); + handler, cal, status); } else { appendTo += *toAppend; @@ -2004,6 +1990,11 @@ void SimpleDateFormat::adoptNumberFormat(NumberFormat *formatToAdopt) { freeSharedNumberFormatters(fSharedNumberFormatters); fSharedNumberFormatters = NULL; } + + // Also re-compute the fast formatters. + UErrorCode localStatus = U_ZERO_ERROR; + freeFastNumberFormatters(); + initFastNumberFormatters(localStatus); } void SimpleDateFormat::adoptNumberFormat(const UnicodeString& fields, NumberFormat *formatToAdopt, UErrorCode &status){ @@ -2055,16 +2046,58 @@ SimpleDateFormat::getNumberFormatForField(UChar field) const { //---------------------------------------------------------------------- void SimpleDateFormat::zeroPaddingNumber( - NumberFormat *currentNumberFormat, + const NumberFormat *currentNumberFormat, UnicodeString &appendTo, int32_t value, int32_t minDigits, int32_t maxDigits) const { - if (currentNumberFormat!=NULL) { - FieldPosition pos(FieldPosition::DONT_CARE); + const number::LocalizedNumberFormatter* fastFormatter = nullptr; + // NOTE: This uses the heuristic that these five min/max int settings account for the vast majority + // of SimpleDateFormat number formatting cases at the time of writing (ICU 62). + if (currentNumberFormat == fNumberFormat) { + if (maxDigits == 10) { + if (minDigits == 1) { + fastFormatter = fFastNumberFormatters[SMPDTFMT_NF_1x10]; + } else if (minDigits == 2) { + fastFormatter = fFastNumberFormatters[SMPDTFMT_NF_2x10]; + } else if (minDigits == 3) { + fastFormatter = fFastNumberFormatters[SMPDTFMT_NF_3x10]; + } else if (minDigits == 4) { + fastFormatter = fFastNumberFormatters[SMPDTFMT_NF_4x10]; + } + } else if (maxDigits == 2) { + if (minDigits == 2) { + fastFormatter = fFastNumberFormatters[SMPDTFMT_NF_2x2]; + } + } + } + if (fastFormatter != nullptr) { + // Can use fast path + number::impl::UFormattedNumberData result; + result.quantity.setToInt(value); + UErrorCode localStatus = U_ZERO_ERROR; + fastFormatter->formatImpl(&result, localStatus); + if (U_FAILURE(localStatus)) { + return; + } + appendTo.append(result.string.toTempUnicodeString()); + return; + } - currentNumberFormat->setMinimumIntegerDigits(minDigits); - currentNumberFormat->setMaximumIntegerDigits(maxDigits); - currentNumberFormat->format(value, appendTo, pos); // 3rd arg is there to speed up processing + // Check for RBNF (no clone necessary) + auto* rbnf = dynamic_cast(currentNumberFormat); + if (rbnf != nullptr) { + FieldPosition pos(FieldPosition::DONT_CARE); + rbnf->format(value, appendTo, pos); // 3rd arg is there to speed up processing + return; + } + + // Fall back to slow path (clone and mutate the NumberFormat) + if (currentNumberFormat != nullptr) { + FieldPosition pos(FieldPosition::DONT_CARE); + LocalPointer nf(dynamic_cast(currentNumberFormat->clone())); + nf->setMinimumIntegerDigits(minDigits); + nf->setMaximumIntegerDigits(maxDigits); + nf->format(value, appendTo, pos); // 3rd arg is there to speed up processing } } @@ -2131,7 +2164,6 @@ SimpleDateFormat::parse(const UnicodeString& text, Calendar& cal, ParsePosition& int32_t saveHebrewMonth = -1; int32_t count = 0; UTimeZoneFormatTimeType tzTimeType = UTZFMT_TIME_TYPE_UNKNOWN; - SimpleDateFormatMutableNFs mutableNFs; // For parsing abutting numeric fields. 'abutPat' is the // offset into 'pattern' of the first of 2 or more abutting @@ -2225,7 +2257,7 @@ SimpleDateFormat::parse(const UnicodeString& text, Calendar& cal, ParsePosition& } pos = subParse(text, pos, ch, count, - TRUE, FALSE, ambiguousYear, saveHebrewMonth, *workCal, i, numericLeapMonthFormatter, &tzTimeType, mutableNFs); + TRUE, FALSE, ambiguousYear, saveHebrewMonth, *workCal, i, numericLeapMonthFormatter, &tzTimeType); // If the parse fails anywhere in the run, back up to the // start of the run and retry. @@ -2240,7 +2272,7 @@ SimpleDateFormat::parse(const UnicodeString& text, Calendar& cal, ParsePosition& // fields. else if (ch != 0x6C) { // pattern char 'l' (SMALL LETTER L) just gets ignored int32_t s = subParse(text, pos, ch, count, - FALSE, TRUE, ambiguousYear, saveHebrewMonth, *workCal, i, numericLeapMonthFormatter, &tzTimeType, mutableNFs, &dayPeriodInt); + FALSE, TRUE, ambiguousYear, saveHebrewMonth, *workCal, i, numericLeapMonthFormatter, &tzTimeType, &dayPeriodInt); if (s == -pos-1) { // era not present, in special cases allow this to continue @@ -2858,7 +2890,7 @@ SimpleDateFormat::set2DigitYearStart(UDate d, UErrorCode& status) */ int32_t SimpleDateFormat::subParse(const UnicodeString& text, int32_t& start, UChar ch, int32_t count, UBool obeyCount, UBool allowNegative, UBool ambiguousYear[], int32_t& saveHebrewMonth, Calendar& cal, - int32_t patLoc, MessageFormat * numericLeapMonthFormatter, UTimeZoneFormatTimeType *tzTimeType, SimpleDateFormatMutableNFs &mutableNFs, + int32_t patLoc, MessageFormat * numericLeapMonthFormatter, UTimeZoneFormatTimeType *tzTimeType, int32_t *dayPeriod) const { Formattable number; @@ -2868,7 +2900,7 @@ int32_t SimpleDateFormat::subParse(const UnicodeString& text, int32_t& start, UC UErrorCode status = U_ZERO_ERROR; ParsePosition pos(0); UDateFormatField patternCharIndex = DateFormatSymbols::getPatternCharIndex(ch); - NumberFormat *currentNumberFormat; + const NumberFormat *currentNumberFormat; UnicodeString temp; UBool gotNumber = FALSE; @@ -2880,7 +2912,7 @@ int32_t SimpleDateFormat::subParse(const UnicodeString& text, int32_t& start, UC return -start; } - currentNumberFormat = mutableNFs.get(getNumberFormatByIndex(patternCharIndex)); + currentNumberFormat = getNumberFormatByIndex(patternCharIndex); if (currentNumberFormat == NULL) { return -start; } @@ -3393,31 +3425,41 @@ int32_t SimpleDateFormat::subParse(const UnicodeString& text, int32_t& start, UC case UDAT_TIMEZONE_FIELD: // 'z' { UTimeZoneFormatStyle style = (count < 4) ? UTZFMT_STYLE_SPECIFIC_SHORT : UTZFMT_STYLE_SPECIFIC_LONG; - TimeZone *tz = tzFormat()->parse(style, text, pos, tzTimeType); - if (tz != NULL) { - cal.adoptTimeZone(tz); - return pos.getIndex(); + const TimeZoneFormat *tzfmt = tzFormat(status); + if (U_SUCCESS(status)) { + TimeZone *tz = tzfmt->parse(style, text, pos, tzTimeType); + if (tz != NULL) { + cal.adoptTimeZone(tz); + return pos.getIndex(); + } } - } + return -start; + } break; case UDAT_TIMEZONE_RFC_FIELD: // 'Z' { UTimeZoneFormatStyle style = (count < 4) ? UTZFMT_STYLE_ISO_BASIC_LOCAL_FULL : ((count == 5) ? UTZFMT_STYLE_ISO_EXTENDED_FULL: UTZFMT_STYLE_LOCALIZED_GMT); - TimeZone *tz = tzFormat()->parse(style, text, pos, tzTimeType); - if (tz != NULL) { - cal.adoptTimeZone(tz); - return pos.getIndex(); + const TimeZoneFormat *tzfmt = tzFormat(status); + if (U_SUCCESS(status)) { + TimeZone *tz = tzfmt->parse(style, text, pos, tzTimeType); + if (tz != NULL) { + cal.adoptTimeZone(tz); + return pos.getIndex(); + } } return -start; } case UDAT_TIMEZONE_GENERIC_FIELD: // 'v' { UTimeZoneFormatStyle style = (count < 4) ? UTZFMT_STYLE_GENERIC_SHORT : UTZFMT_STYLE_GENERIC_LONG; - TimeZone *tz = tzFormat()->parse(style, text, pos, tzTimeType); - if (tz != NULL) { - cal.adoptTimeZone(tz); - return pos.getIndex(); + const TimeZoneFormat *tzfmt = tzFormat(status); + if (U_SUCCESS(status)) { + TimeZone *tz = tzfmt->parse(style, text, pos, tzTimeType); + if (tz != NULL) { + cal.adoptTimeZone(tz); + return pos.getIndex(); + } } return -start; } @@ -3438,20 +3480,26 @@ int32_t SimpleDateFormat::subParse(const UnicodeString& text, int32_t& start, UC style = UTZFMT_STYLE_GENERIC_LOCATION; break; } - TimeZone *tz = tzFormat()->parse(style, text, pos, tzTimeType); - if (tz != NULL) { - cal.adoptTimeZone(tz); - return pos.getIndex(); + const TimeZoneFormat *tzfmt = tzFormat(status); + if (U_SUCCESS(status)) { + TimeZone *tz = tzfmt->parse(style, text, pos, tzTimeType); + if (tz != NULL) { + cal.adoptTimeZone(tz); + return pos.getIndex(); + } } return -start; } case UDAT_TIMEZONE_LOCALIZED_GMT_OFFSET_FIELD: // 'O' { UTimeZoneFormatStyle style = (count < 4) ? UTZFMT_STYLE_LOCALIZED_GMT_SHORT : UTZFMT_STYLE_LOCALIZED_GMT; - TimeZone *tz = tzFormat()->parse(style, text, pos, tzTimeType); - if (tz != NULL) { - cal.adoptTimeZone(tz); - return pos.getIndex(); + const TimeZoneFormat *tzfmt = tzFormat(status); + if (U_SUCCESS(status)) { + TimeZone *tz = tzfmt->parse(style, text, pos, tzTimeType); + if (tz != NULL) { + cal.adoptTimeZone(tz); + return pos.getIndex(); + } } return -start; } @@ -3475,10 +3523,13 @@ int32_t SimpleDateFormat::subParse(const UnicodeString& text, int32_t& start, UC style = UTZFMT_STYLE_ISO_EXTENDED_FULL; break; } - TimeZone *tz = tzFormat()->parse(style, text, pos, tzTimeType); - if (tz != NULL) { - cal.adoptTimeZone(tz); - return pos.getIndex(); + const TimeZoneFormat *tzfmt = tzFormat(status); + if (U_SUCCESS(status)) { + TimeZone *tz = tzfmt->parse(style, text, pos, tzTimeType); + if (tz != NULL) { + cal.adoptTimeZone(tz); + return pos.getIndex(); + } } return -start; } @@ -3502,10 +3553,13 @@ int32_t SimpleDateFormat::subParse(const UnicodeString& text, int32_t& start, UC style = UTZFMT_STYLE_ISO_EXTENDED_LOCAL_FULL; break; } - TimeZone *tz = tzFormat()->parse(style, text, pos, tzTimeType); - if (tz != NULL) { - cal.adoptTimeZone(tz); - return pos.getIndex(); + const TimeZoneFormat *tzfmt = tzFormat(status); + if (U_SUCCESS(status)) { + TimeZone *tz = tzfmt->parse(style, text, pos, tzTimeType); + if (tz != NULL) { + cal.adoptTimeZone(tz); + return pos.getIndex(); + } } return -start; } @@ -3539,7 +3593,7 @@ int32_t SimpleDateFormat::subParse(const UnicodeString& text, int32_t& start, UC U_ASSERT(dayPeriod != NULL); int32_t ampmStart = subParse(text, start, 0x61, count, obeyCount, allowNegative, ambiguousYear, saveHebrewMonth, cal, - patLoc, numericLeapMonthFormatter, tzTimeType, mutableNFs); + patLoc, numericLeapMonthFormatter, tzTimeType); if (ampmStart > 0) { return ampmStart; @@ -3686,7 +3740,7 @@ void SimpleDateFormat::parseInt(const UnicodeString& text, Formattable& number, ParsePosition& pos, UBool allowNegative, - NumberFormat *fmt) const { + const NumberFormat *fmt) const { parseInt(text, number, -1, pos, allowNegative,fmt); } @@ -3698,18 +3752,21 @@ void SimpleDateFormat::parseInt(const UnicodeString& text, int32_t maxDigits, ParsePosition& pos, UBool allowNegative, - NumberFormat *fmt) const { + const NumberFormat *fmt) const { UnicodeString oldPrefix; - DecimalFormat* df = NULL; - if (!allowNegative && (df = dynamic_cast(fmt)) != NULL) { - df->getNegativePrefix(oldPrefix); + auto* fmtAsDF = dynamic_cast(fmt); + LocalPointer df; + if (!allowNegative && fmtAsDF != nullptr) { + df.adoptInstead(dynamic_cast(fmtAsDF->clone())); + if (df.isNull()) { + // Memory allocation error + return; + } df->setNegativePrefix(UnicodeString(TRUE, SUPPRESS_NEGATIVE_PREFIX, -1)); + fmt = df.getAlias(); } int32_t oldPos = pos.getIndex(); fmt->parse(text, number, pos); - if (df != NULL) { - df->setNegativePrefix(oldPrefix); - } if (maxDigits > 0) { // adjust the result to fit into @@ -3856,7 +3913,13 @@ SimpleDateFormat::setDateFormatSymbols(const DateFormatSymbols& newFormatSymbols //---------------------------------------------------------------------- const TimeZoneFormat* SimpleDateFormat::getTimeZoneFormat(void) const { - return (const TimeZoneFormat*)tzFormat(); + // TimeZoneFormat initialization might fail when out of memory. + // If we always initialize TimeZoneFormat instance, we can return + // such status there. For now, this implementation lazily instantiates + // a TimeZoneFormat for performance optimization reasons, but cannot + // propagate such error (probably just out of memory case) to the caller. + UErrorCode status = U_ZERO_ERROR; + return (const TimeZoneFormat*)tzFormat(status); } //---------------------------------------------------------------------- @@ -4123,12 +4186,11 @@ SimpleDateFormat::skipUWhiteSpace(const UnicodeString& text, int32_t pos) const // Lazy TimeZoneFormat instantiation, semantically const. TimeZoneFormat * -SimpleDateFormat::tzFormat() const { +SimpleDateFormat::tzFormat(UErrorCode &status) const { if (fTimeZoneFormat == NULL) { umtx_lock(&LOCK); { if (fTimeZoneFormat == NULL) { - UErrorCode status = U_ZERO_ERROR; TimeZoneFormat *tzfmt = TimeZoneFormat::createInstance(fLocale, status); if (U_FAILURE(status)) { return NULL; diff --git a/deps/icu-small/source/i18n/timezone.cpp b/deps/icu-small/source/i18n/timezone.cpp index e662bf7674b..f7f45c7d3ee 100644 --- a/deps/icu-small/source/i18n/timezone.cpp +++ b/deps/icu-small/source/i18n/timezone.cpp @@ -739,8 +739,7 @@ private: len = mapLen; } - UBool getID(int32_t i) { - UErrorCode ec = U_ZERO_ERROR; + UBool getID(int32_t i, UErrorCode& ec) { int32_t idLen = 0; const UChar* id = NULL; UResourceBundle *top = ures_openDirect(0, kZONEINFO, &ec); @@ -930,7 +929,7 @@ public: virtual const UnicodeString* snext(UErrorCode& status) { if (U_SUCCESS(status) && map != NULL && pos < len) { - getID(map[pos]); + getID(map[pos], status); ++pos; return &unistr; } diff --git a/deps/icu-small/source/i18n/ucln_in.h b/deps/icu-small/source/i18n/ucln_in.h index 40a5c36d87a..318eafc143c 100644 --- a/deps/icu-small/source/i18n/ucln_in.h +++ b/deps/icu-small/source/i18n/ucln_in.h @@ -26,6 +26,7 @@ as the functions are suppose to be called. It's usually best to have child dependencies called first. */ typedef enum ECleanupI18NType { UCLN_I18N_START = -1, + UCLN_I18N_NUMBER_SKELETONS, UCLN_I18N_CURRENCY_SPACING, UCLN_I18N_SPOOF, UCLN_I18N_SPOOFDATA, diff --git a/deps/icu-small/source/i18n/unicode/compactdecimalformat.h b/deps/icu-small/source/i18n/unicode/compactdecimalformat.h index d682d2d0e74..7dc92f61006 100644 --- a/deps/icu-small/source/i18n/unicode/compactdecimalformat.h +++ b/deps/icu-small/source/i18n/unicode/compactdecimalformat.h @@ -84,7 +84,7 @@ public: * Destructor. * @stable ICU 51 */ - virtual ~CompactDecimalFormat(); + ~CompactDecimalFormat() U_OVERRIDE; /** * Assignment operator. @@ -101,245 +101,21 @@ public: * @return a polymorphic copy of this CompactDecimalFormat. * @stable ICU 51 */ - virtual Format* clone() const; - - /** - * Return TRUE if the given Format objects are semantically equal. - * Objects of different subclasses are considered unequal. - * - * @param other the object to be compared with. - * @return TRUE if the given Format objects are semantically equal. - * @stable ICU 51 - */ - virtual UBool operator==(const Format& other) const; - + Format* clone() const U_OVERRIDE; using DecimalFormat::format; /** - * Format a double or long number using base-10 representation. - * - * @param number The value to be formatted. - * @param appendTo Output parameter to receive result. - * Result is appended to existing contents. - * @param pos On input: an alignment field, if desired. - * On output: the offsets of the alignment field. - * @return Reference to 'appendTo' parameter. + * CompactDecimalFormat does not support parsing. This implementation + * does nothing. + * @param text Unused. + * @param result Does not change. + * @param parsePosition Does not change. + * @see Formattable * @stable ICU 51 */ - virtual UnicodeString& format(double number, - UnicodeString& appendTo, - FieldPosition& pos) const; - - /** - * Format a double or long number using base-10 representation. - * - * @param number The value to be formatted. - * @param appendTo Output parameter to receive result. - * 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 - * @return Reference to 'appendTo' parameter. - * @internal - */ - virtual UnicodeString& format(double number, - UnicodeString& appendTo, - FieldPosition& pos, - UErrorCode &status) const; - - /** - * Format a double or long number using base-10 representation. - * Currently sets status to U_UNSUPPORTED_ERROR. - * - * @param number The value to be formatted. - * @param appendTo Output parameter to receive result. - * Result is appended to existing contents. - * @param posIter On return, can be used to iterate over positions - * of fields generated by this format call. - * Can be NULL. - * @param status Output param filled with success/failure status. - * @return Reference to 'appendTo' parameter. - * @internal - */ - virtual UnicodeString& format(double number, - UnicodeString& appendTo, - FieldPositionIterator* posIter, - UErrorCode& status) const; - - /** - * Format a long number using base-10 representation. - * - * @param number The value to be formatted. - * @param appendTo Output parameter to receive result. - * Result is appended to existing contents. - * @param pos On input: an alignment field, if desired. - * On output: the offsets of the alignment field. - * @return Reference to 'appendTo' parameter. - * @stable ICU 56 - */ - virtual UnicodeString& format(int32_t number, - UnicodeString& appendTo, - FieldPosition& pos) const; - - /** - * Format a long number using base-10 representation. - * - * @param number The value to be formatted. - * @param appendTo Output parameter to receive result. - * Result is appended to existing contents. - * @param pos On input: an alignment field, if desired. - * On output: the offsets of the alignment field. - * @return Reference to 'appendTo' parameter. - * @internal - */ - virtual UnicodeString& format(int32_t number, - UnicodeString& appendTo, - FieldPosition& pos, - UErrorCode &status) const; - - /** - * Format a long number using base-10 representation. - * Currently sets status to U_UNSUPPORTED_ERROR - * - * @param number The value to be formatted. - * @param appendTo Output parameter to receive result. - * Result is appended to existing contents. - * @param posIter On return, can be used to iterate over positions - * of fields generated by this format call. - * Can be NULL. - * @param status Output param filled with success/failure status. - * @return Reference to 'appendTo' parameter. - * @internal - */ - virtual UnicodeString& format(int32_t number, - UnicodeString& appendTo, - FieldPositionIterator* posIter, - UErrorCode& status) const; - - /** - * Format an int64 number using base-10 representation. - * - * @param number The value to be formatted. - * @param appendTo Output parameter to receive result. - * Result is appended to existing contents. - * @param pos On input: an alignment field, if desired. - * On output: the offsets of the alignment field. - * @return Reference to 'appendTo' parameter. - * @stable ICU 51 - */ - virtual UnicodeString& format(int64_t number, - UnicodeString& appendTo, - FieldPosition& pos) const; - - /** - * Format an int64 number using base-10 representation. - * - * @param number The value to be formatted. - * @param appendTo Output parameter to receive result. - * Result is appended to existing contents. - * @param pos On input: an alignment field, if desired. - * On output: the offsets of the alignment field. - * @return Reference to 'appendTo' parameter. - * @internal - */ - virtual UnicodeString& format(int64_t number, - UnicodeString& appendTo, - FieldPosition& pos, - UErrorCode &status) const; - - /** - * Format an int64 number using base-10 representation. - * Currently sets status to U_UNSUPPORTED_ERROR - * - * @param number The value to be formatted. - * @param appendTo Output parameter to receive result. - * Result is appended to existing contents. - * @param posIter On return, can be used to iterate over positions - * of fields generated by this format call. - * Can be NULL. - * @param status Output param filled with success/failure status. - * @return Reference to 'appendTo' parameter. - * @internal - */ - virtual UnicodeString& format(int64_t number, - UnicodeString& appendTo, - FieldPositionIterator* posIter, - UErrorCode& status) const; - - /** - * Format a decimal number. Currently sets status to U_UNSUPPORTED_ERROR - * The syntax of the unformatted number is a "numeric string" - * as defined in the Decimal Arithmetic Specification, available at - * http://speleotrove.com/decimal - * - * @param number The unformatted number, as a string. - * @param appendTo Output parameter to receive result. - * Result is appended to existing contents. - * @param posIter On return, can be used to iterate over positions - * of fields generated by this format call. - * Can be NULL. - * @param status Output param filled with success/failure status. - * @return Reference to 'appendTo' parameter. - * @internal - */ - virtual UnicodeString& format(StringPiece number, - UnicodeString& appendTo, - FieldPositionIterator* posIter, - UErrorCode& status) const; - - /** - * Format a decimal number. Currently sets status to U_UNSUPPORTED_ERROR - * The number is a DigitList wrapper onto a floating point decimal number. - * The default implementation in NumberFormat converts the decimal number - * to a double and formats that. - * - * @param number The number, a DigitList format Decimal Floating Point. - * @param appendTo Output parameter to receive result. - * Result is appended to existing contents. - * @param posIter On return, can be used to iterate over positions - * of fields generated by this format call. - * @param status Output param filled with success/failure status. - * @return Reference to 'appendTo' parameter. - * @internal - */ - virtual UnicodeString& format(const DigitList &number, - UnicodeString& appendTo, - FieldPositionIterator* posIter, - UErrorCode& status) const; - - /** - * Format a decimal number. Currently sets status to U_UNSUPPORTED_ERROR. - * The number is a DigitList wrapper onto a floating point decimal number. - * The default implementation in NumberFormat converts the decimal number - * to a double and formats that. - * - * @param number The number, a DigitList format Decimal Floating Point. - * @param appendTo Output parameter to receive result. - * 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 - */ - virtual UnicodeString& format(const DigitList &number, - UnicodeString& appendTo, - FieldPosition& pos, - UErrorCode& status) const; - - /** - * CompactDecimalFormat does not support parsing. This implementation - * does nothing. - * @param text Unused. - * @param result Does not change. - * @param parsePosition Does not change. - * @see Formattable - * @stable ICU 51 - */ - virtual void parse(const UnicodeString& text, - Formattable& result, - ParsePosition& parsePosition) const; + void parse(const UnicodeString& text, Formattable& result, + ParsePosition& parsePosition) const U_OVERRIDE; /** * CompactDecimalFormat does not support parsing. This implementation @@ -350,10 +126,9 @@ public: * @param status Always set to U_UNSUPPORTED_ERROR. * @stable ICU 51 */ - virtual void parse(const UnicodeString& text, - Formattable& result, - UErrorCode& status) const; + void parse(const UnicodeString& text, Formattable& result, UErrorCode& status) const U_OVERRIDE; +#ifndef U_HIDE_INTERNAL_API /** * Parses text from the given string as a currency amount. Unlike * the parse() method, this method will attempt to parse a generic @@ -374,8 +149,8 @@ public: * the parsed currency; if parse fails, this is NULL. * @internal */ - virtual CurrencyAmount* parseCurrency(const UnicodeString& text, - ParsePosition& pos) const; + CurrencyAmount* parseCurrency(const UnicodeString& text, ParsePosition& pos) const U_OVERRIDE; +#endif /* U_HIDE_INTERNAL_API */ /** * Return the class ID for this class. This is useful only for @@ -401,18 +176,10 @@ public: * other classes have different class IDs. * @stable ICU 51 */ - virtual UClassID getDynamicClassID() const; + UClassID getDynamicClassID() const U_OVERRIDE; -private: - - const UHashtable* _unitsByVariant; - const double* _divisors; - PluralRules* _pluralRules; - - // Default constructor not implemented. - CompactDecimalFormat(const DecimalFormat &, const UHashtable* unitsByVariant, const double* divisors, PluralRules* pluralRules); - - UBool eqHelper(const CompactDecimalFormat& that) const; + private: + CompactDecimalFormat(const Locale& inLocale, UNumberCompactStyle style, UErrorCode& status); }; U_NAMESPACE_END diff --git a/deps/icu-small/source/i18n/unicode/currunit.h b/deps/icu-small/source/i18n/unicode/currunit.h index e7e0dc72da8..d5bc4aa6d6d 100644 --- a/deps/icu-small/source/i18n/unicode/currunit.h +++ b/deps/icu-small/source/i18n/unicode/currunit.h @@ -44,8 +44,9 @@ class U_I18N_API CurrencyUnit: public MeasureUnit { /** * Construct an object with the given ISO currency code. - * @param isoCode the 3-letter ISO 4217 currency code; must not be - * NULL and must have length 3 + * @param isoCode the 3-letter ISO 4217 currency code; must have + * length 3 and need not be NUL-terminated. If NULL, the currency + * is initialized to the unknown currency XXX. * @param ec input-output error code. If the isoCode is invalid, * then this will be set to a failing value. * @stable ICU 3.0 diff --git a/deps/icu-small/source/i18n/unicode/dcfmtsym.h b/deps/icu-small/source/i18n/unicode/dcfmtsym.h index e58befa31bd..2f824cec308 100644 --- a/deps/icu-small/source/i18n/unicode/dcfmtsym.h +++ b/deps/icu-small/source/i18n/unicode/dcfmtsym.h @@ -406,9 +406,12 @@ public: * 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. - * ### TODO markus 2002oct11: Consider proposing getConstSymbol() to be really public. * 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: + * http://bugs.icu-project.org/trac/ticket/13580 + * * @param symbol Constant to indicate a number format symbol. * @return the format symbol by the param 'symbol' * @internal @@ -422,6 +425,10 @@ public: * to accessing the symbol from getConstSymbol with the corresponding * key, such as kZeroDigitSymbol or kOneDigitSymbol. * + * 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: + * http://bugs.icu-project.org/trac/ticket/13580 + * * @param digit The digit, an integer between 0 and 9 inclusive. * If outside the range 0 to 9, the zero digit is returned. * @return the format symbol for the given digit. diff --git a/deps/icu-small/source/i18n/unicode/decimfmt.h b/deps/icu-small/source/i18n/unicode/decimfmt.h index b062208d9b1..3747f510f79 100644 --- a/deps/icu-small/source/i18n/unicode/decimfmt.h +++ b/deps/icu-small/source/i18n/unicode/decimfmt.h @@ -43,28 +43,25 @@ #include "unicode/curramt.h" #include "unicode/enumset.h" -#ifndef U_HIDE_INTERNAL_API -/** - * \def UNUM_DECIMALFORMAT_INTERNAL_SIZE - * @internal - */ -#if UCONFIG_FORMAT_FASTPATHS_49 -#define UNUM_DECIMALFORMAT_INTERNAL_SIZE 16 -#endif -#endif /* U_HIDE_INTERNAL_API */ - U_NAMESPACE_BEGIN -class DigitList; class CurrencyPluralInfo; -class Hashtable; -class UnicodeSet; -class FieldPositionHandler; -class DecimalFormatStaticSets; -class FixedDecimal; -class DecimalFormatImpl; -class PluralRules; -class VisibleDigitsWithExponent; +class CompactDecimalFormat; + +namespace number { +class LocalizedNumberFormatter; +class FormattedNumber; +namespace impl { +class DecimalQuantity; +struct DecimalFormatFields; +} +} + +namespace numparse { +namespace impl { +class NumberParserImpl; +} +} // explicit template instantiation. see digitlst.h // (When building DLLs for Windows this is required.) @@ -672,17 +669,14 @@ template class U_I18N_API EnumSet "123", and "123" -> 1.23 * @stable ICU 2.0 @@ -1362,12 +1320,52 @@ public: * (For Arabic, use arabic percent symbol). * For a permill, set the suffixes to have "\\u2031" and the multiplier to be 1000. * + * This method only supports integer multipliers. To multiply by a non-integer, pair this + * method with setMultiplierScale(). + * * @param newValue the new value of the multiplier for use in percent, permill, etc. * Examples: with 100, 1.23 -> "123", and "123" -> 1.23 * @stable ICU 2.0 */ virtual void setMultiplier(int32_t newValue); +#ifndef U_HIDE_DRAFT_API + /** + * Gets the power of ten by which number should be multiplied before formatting, which + * can be combined with setMultiplier() to multiply by any arbitrary decimal value. + * + * A multiplier scale of 2 corresponds to multiplication by 100, and a multiplier scale + * of -2 corresponds to multiplication by 0.01. + * + * This method is analogous to UNUM_SCALE in getAttribute. + * + * @return the current value of the power-of-ten multiplier. + * @draft ICU 62 + */ + int32_t getMultiplierScale(void) const; +#endif /* U_HIDE_DRAFT_API */ + + /** + * Sets a power of ten by which number should be multiplied before formatting, which + * can be combined with setMultiplier() to multiply by any arbitrary decimal value. + * + * A multiplier scale of 2 corresponds to multiplication by 100, and a multiplier scale + * of -2 corresponds to multiplication by 0.01. + * + * For example, to multiply numbers by 0.5 before formatting, you can do: + * + *

+     * df.setMultiplier(5);
+     * df.setMultiplierScale(-1);
+     * 
+ * + * This method is analogous to UNUM_SCALE in setAttribute. + * + * @param newValue the new value of the power-of-ten multiplier. + * @draft ICU 62 + */ + virtual void setMultiplierScale(int32_t newValue); + /** * Get the rounding increment. * @return A positive rounding increment, or 0.0 if a custom rounding @@ -1400,7 +1398,7 @@ public: * @see #setRoundingMode * @stable ICU 2.0 */ - virtual ERoundingMode getRoundingMode(void) const; + virtual ERoundingMode getRoundingMode(void) const U_OVERRIDE; /** * Set the rounding mode. @@ -1410,7 +1408,7 @@ public: * @see #getRoundingMode * @stable ICU 2.0 */ - virtual void setRoundingMode(ERoundingMode roundingMode); + virtual void setRoundingMode(ERoundingMode roundingMode) U_OVERRIDE; /** * Get the width to which the output of format() is padded. @@ -1469,7 +1467,7 @@ public: * @see #setPadPosition * @stable ICU 2.0 */ - virtual void setPadCharacter(const UnicodeString &padChar); + virtual void setPadCharacter(const UnicodeString& padChar); /** * Get the position at which padding will take place. This is the location @@ -1676,7 +1674,7 @@ public: #endif /* U_HIDE_INTERNAL_API */ - /* Cannot use #ifndef U_HIDE_INTERNAL_API for the following draft method since it is virtual. */ + /* Cannot use #ifndef U_HIDE_INTERNAL_API for the following draft method since it is virtual. */ /** * Sets the minimum grouping digits. Setting to a value less than or * equal to 1 turns off minimum grouping digits. @@ -1717,7 +1715,7 @@ public: UBool isDecimalPatternMatchRequired(void) const; /** - * Allows you to set the behavior of the pattern decimal mark. + * Allows you to set the parse behavior of the pattern decimal mark. * * if TRUE, the input must have a decimal mark if one was specified in the pattern. When * FALSE the decimal mark may be omitted from the input. @@ -1727,6 +1725,60 @@ public: */ virtual void setDecimalPatternMatchRequired(UBool newValue); + /** + * {@icu} Returns whether to ignore exponents when parsing. + * + * @see #setParseNoExponent + * @internal This API is a technical preview. It may change in an upcoming release. + */ + virtual UBool isParseNoExponent() const; + + /** + * {@icu} 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). + * + * @param value true to prevent exponents from being parsed; false to allow them to be parsed. + * @internal This API is a technical preview. It may change in an upcoming release. + */ + virtual void setParseNoExponent(UBool value); + + /** + * {@icu} 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. + */ + virtual UBool isParseCaseSensitive() const; + + /** + * {@icu} 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 + * mode, even though "US$1.00" parses. + * + * @internal This API is a technical preview. It may change in an upcoming release. + */ + virtual void setParseCaseSensitive(UBool value); + + /** + * {@icu} Returns whether truncation of high-order integer digits should result in an error. + * By default, setMaximumIntegerDigits truncates high-order digits silently. + * + * @see setFormatFailIfMoreThanMaxDigits + * @internal This API is a technical preview. It may change in an upcoming release. + */ + virtual UBool isFormatFailIfMoreThanMaxDigits() const; + + /** + * {@icu} 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. + */ + virtual void setFormatFailIfMoreThanMaxDigits(UBool value); + /** * Synthesizes a pattern string that represents the current state @@ -1781,9 +1833,8 @@ public: * set to a failure result. * @stable ICU 2.0 */ - virtual void applyPattern(const UnicodeString& pattern, - UParseError& parseError, - UErrorCode& status); + virtual void applyPattern(const UnicodeString& pattern, UParseError& parseError, UErrorCode& status); + /** * Sets the pattern. * @param pattern The pattern to be applied. @@ -1792,8 +1843,7 @@ public: * set to a failure result. * @stable ICU 2.0 */ - virtual void applyPattern(const UnicodeString& pattern, - UErrorCode& status); + virtual void applyPattern(const UnicodeString& pattern, UErrorCode& status); /** * Apply the given pattern to this Format object. The pattern @@ -1825,8 +1875,7 @@ public: * set to a failure result. * @stable ICU 2.0 */ - virtual void applyLocalizedPattern(const UnicodeString& pattern, - UParseError& parseError, + virtual void applyLocalizedPattern(const UnicodeString& pattern, UParseError& parseError, UErrorCode& status); /** @@ -1838,8 +1887,7 @@ public: * set to a failure result. * @stable ICU 2.0 */ - virtual void applyLocalizedPattern(const UnicodeString& pattern, - UErrorCode& status); + virtual void applyLocalizedPattern(const UnicodeString& pattern, UErrorCode& status); /** @@ -1851,7 +1899,7 @@ public: * @see NumberFormat#setMaximumIntegerDigits * @stable ICU 2.0 */ - virtual void setMaximumIntegerDigits(int32_t newValue); + void setMaximumIntegerDigits(int32_t newValue) U_OVERRIDE; /** * Sets the minimum number of digits allowed in the integer portion of a @@ -1862,7 +1910,7 @@ public: * @see NumberFormat#setMinimumIntegerDigits * @stable ICU 2.0 */ - virtual void setMinimumIntegerDigits(int32_t newValue); + void setMinimumIntegerDigits(int32_t newValue) U_OVERRIDE; /** * Sets the maximum number of digits allowed in the fraction portion of a @@ -1873,7 +1921,7 @@ public: * @see NumberFormat#setMaximumFractionDigits * @stable ICU 2.0 */ - virtual void setMaximumFractionDigits(int32_t newValue); + void setMaximumFractionDigits(int32_t newValue) U_OVERRIDE; /** * Sets the minimum number of digits allowed in the fraction portion of a @@ -1884,7 +1932,7 @@ public: * @see NumberFormat#setMinimumFractionDigits * @stable ICU 2.0 */ - virtual void setMinimumFractionDigits(int32_t newValue); + void setMinimumFractionDigits(int32_t newValue) U_OVERRIDE; /** * Returns the minimum number of significant digits that will be @@ -1947,7 +1995,6 @@ public: */ void setSignificantDigitsUsed(UBool useSignificantDigits); - public: /** * Sets the currency used to display currency * amounts. This takes effect immediately, if this format is a @@ -1960,7 +2007,7 @@ public: * @param ec input-output error code * @stable ICU 3.0 */ - virtual void setCurrency(const char16_t* theCurrency, UErrorCode& ec); + void setCurrency(const char16_t* theCurrency, UErrorCode& ec) U_OVERRIDE; /** * Sets the currency used to display currency amounts. See @@ -1984,78 +2031,53 @@ public: */ UCurrencyUsage getCurrencyUsage() const; - -#ifndef U_HIDE_DEPRECATED_API - /** - * The resource tags we use to retrieve decimal format data from - * locale resource bundles. - * @deprecated ICU 3.4. This string has no public purpose. Please don't use it. - */ - static const char fgNumberPatterns[]; -#endif // U_HIDE_DEPRECATED_API - #ifndef U_HIDE_INTERNAL_API + /** - * Get a FixedDecimal corresponding to a double as it would be + * Format a number and save it into the given DecimalQuantity. + * Internal, not intended for public use. + * @internal + */ + void formatToDecimalQuantity(double number, number::impl::DecimalQuantity& output, + UErrorCode& status) const; + + /** + * Get a DecimalQuantity corresponding to a formattable as it would be * formatted by this DecimalFormat. * Internal, not intended for public use. * @internal */ - FixedDecimal getFixedDecimal(double number, UErrorCode &status) const; + void formatToDecimalQuantity(const Formattable& number, number::impl::DecimalQuantity& output, + UErrorCode& status) const; +#endif + +#ifndef U_HIDE_DRAFT_API /** - * Get a FixedDecimal corresponding to a formattable as it would be - * formatted by this DecimalFormat. - * Internal, not intended for public use. - * @internal + * Converts this DecimalFormat to a NumberFormatter. Starting in ICU 60, + * NumberFormatter is the recommended way to format numbers. + * + * NOTE: The returned LocalizedNumberFormatter is owned by this DecimalFormat. + * If a non-const method is called on the DecimalFormat, or if the DecimalFormat + * is deleted, the object becomes invalid. If you plan to keep the return value + * beyond the lifetime of the DecimalFormat, copy it to a local variable: + * + *
+     * LocalizedNumberFormatter f = df->toNumberFormatter();
+     * 
+ * + * It is, however, safe to use the return value for chaining: + * + *
+     * 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 */ - FixedDecimal getFixedDecimal(const Formattable &number, UErrorCode &status) const; - - /** - * Get a FixedDecimal corresponding to a DigitList as it would be - * formatted by this DecimalFormat. Note: the DigitList may be modified. - * Internal, not intended for public use. - * @internal - */ - FixedDecimal getFixedDecimal(DigitList &number, UErrorCode &status) const; - - /** - * Get a VisibleDigitsWithExponent corresponding to a double - * as it would be formatted by this DecimalFormat. - * Internal, not intended for public use. - * @internal - */ - VisibleDigitsWithExponent &initVisibleDigitsWithExponent( - double number, - VisibleDigitsWithExponent &digits, - UErrorCode &status) const; - - /** - * Get a VisibleDigitsWithExponent corresponding to a formattable - * as it would be formatted by this DecimalFormat. - * Internal, not intended for public use. - * @internal - */ - VisibleDigitsWithExponent &initVisibleDigitsWithExponent( - const Formattable &number, - VisibleDigitsWithExponent &digits, - UErrorCode &status) const; - - /** - * Get a VisibleDigitsWithExponent corresponding to a DigitList - * as it would be formatted by this DecimalFormat. - * Note: the DigitList may be modified. - * Internal, not intended for public use. - * @internal - */ - VisibleDigitsWithExponent &initVisibleDigitsWithExponent( - DigitList &number, - VisibleDigitsWithExponent &digits, - UErrorCode &status) const; - -#endif /* U_HIDE_INTERNAL_API */ - -public: + const number::LocalizedNumberFormatter& toNumberFormatter() const; +#endif /* U_HIDE_DRAFT_API */ /** * Return the class ID for this class. This is useful only for @@ -2081,217 +2103,57 @@ public: * other classes have different class IDs. * @stable ICU 2.0 */ - virtual UClassID getDynamicClassID(void) const; + UClassID getDynamicClassID(void) const U_OVERRIDE; -private: + private: - DecimalFormat(); // default constructor not implemented + /** Rebuilds the formatter object from the property bag. */ + void touch(UErrorCode& status); + + /** Rebuilds the formatter object, hiding the error code. */ + void touchNoError(); /** - * Initialize all fields of a new DecimalFormatter to a safe default value. - * Common code for use by constructors. + * Updates the property bag with settings from the given pattern. + * + * @param pattern The pattern string to parse. + * @param ignoreRounding Whether to leave out rounding information (minFrac, maxFrac, and rounding + * increment) when parsing the pattern. This may be desirable if a custom rounding mode, such + * as CurrencyUsage, is to be used instead. One of {@link + * PatternStringParser#IGNORE_ROUNDING_ALWAYS}, {@link PatternStringParser#IGNORE_ROUNDING_IF_CURRENCY}, + * or {@link PatternStringParser#IGNORE_ROUNDING_NEVER}. + * @see PatternAndPropertyUtils#parseToExistingProperties */ - void init(); + void setPropertiesFromPattern(const UnicodeString& pattern, int32_t ignoreRounding, + UErrorCode& status); - /** - * Do real work of constructing a new DecimalFormat. - */ - void construct(UErrorCode& status, - UParseError& parseErr, - const UnicodeString* pattern = 0, - DecimalFormatSymbols* symbolsToAdopt = 0 - ); + const numparse::impl::NumberParserImpl* getParser(UErrorCode& status) const; - void handleCurrencySignInPattern(UErrorCode& status); + const numparse::impl::NumberParserImpl* getCurrencyParser(UErrorCode& status) const; - void parse(const UnicodeString& text, - Formattable& result, - ParsePosition& pos, - char16_t* currency) const; + static void fieldPositionHelper(const number::FormattedNumber& formatted, FieldPosition& fieldPosition, + int32_t offset, UErrorCode& status); - enum { - fgStatusInfinite, - fgStatusLength // Leave last in list. - } StatusFlags; + static void fieldPositionIteratorHelper(const number::FormattedNumber& formatted, + FieldPositionIterator* fpi, int32_t offset, UErrorCode& status); - UBool subparse(const UnicodeString& text, - const UnicodeString* negPrefix, - const UnicodeString* negSuffix, - const UnicodeString* posPrefix, - const UnicodeString* posSuffix, - UBool complexCurrencyParsing, - int8_t type, - ParsePosition& parsePosition, - DigitList& digits, UBool* status, - char16_t* currency) const; + void setupFastFormat(); - // Mixed style parsing for currency. - // It parses against the current currency pattern - // using complex affix comparison - // parses against the currency plural patterns using complex affix comparison, - // and parses against the current pattern using simple affix comparison. - UBool parseForCurrency(const UnicodeString& text, - ParsePosition& parsePosition, - DigitList& digits, - UBool* status, - char16_t* currency) const; + bool fastFormatDouble(double input, UnicodeString& output) const; - int32_t skipPadding(const UnicodeString& text, int32_t position) const; + bool fastFormatInt64(int64_t input, UnicodeString& output) const; - int32_t compareAffix(const UnicodeString& input, - int32_t pos, - UBool isNegative, - UBool isPrefix, - const UnicodeString* affixPat, - UBool complexCurrencyParsing, - int8_t type, - char16_t* currency) const; + void doFastFormatInt32(int32_t input, bool isNegative, UnicodeString& output) const; - static UnicodeString& trimMarksFromAffix(const UnicodeString& affix, UnicodeString& trimmedAffix); + //=====================================================================================// + // INSTANCE FIELDS // + //=====================================================================================// - UBool equalWithSignCompatibility(UChar32 lhs, UChar32 rhs) const; + // Only one instance field: keep all fields inside of an implementation class defined in number_mapper.h + number::impl::DecimalFormatFields* fields; - int32_t compareSimpleAffix(const UnicodeString& affix, - const UnicodeString& input, - int32_t pos, - UBool lenient) const; - - static int32_t skipPatternWhiteSpace(const UnicodeString& text, int32_t pos); - - static int32_t skipUWhiteSpace(const UnicodeString& text, int32_t pos); - - static int32_t skipUWhiteSpaceAndMarks(const UnicodeString& text, int32_t pos); - - static int32_t skipBidiMarks(const UnicodeString& text, int32_t pos); - - int32_t compareComplexAffix(const UnicodeString& affixPat, - const UnicodeString& input, - int32_t pos, - int8_t type, - char16_t* currency) const; - - static int32_t match(const UnicodeString& text, int32_t pos, UChar32 ch); - - static int32_t match(const UnicodeString& text, int32_t pos, const UnicodeString& str); - - static UBool matchSymbol(const UnicodeString &text, int32_t position, int32_t length, const UnicodeString &symbol, - UnicodeSet *sset, UChar32 schar); - - static UBool matchDecimal(UChar32 symbolChar, - UBool sawDecimal, UChar32 sawDecimalChar, - const UnicodeSet *sset, UChar32 schar); - - static UBool matchGrouping(UChar32 groupingChar, - UBool sawGrouping, UChar32 sawGroupingChar, - const UnicodeSet *sset, - UChar32 decimalChar, const UnicodeSet *decimalSet, - UChar32 schar); - - // set up currency affix patterns for mix parsing. - // The patterns saved here are the affix patterns of default currency - // pattern and the unique affix patterns of the plural currency patterns. - // Those patterns are used by parseForCurrency(). - void setupCurrencyAffixPatterns(UErrorCode& status); - - // get the currency rounding with respect to currency usage - double getCurrencyRounding(const char16_t* currency, - UErrorCode* ec) const; - - // get the currency fraction with respect to currency usage - int getCurrencyFractionDigits(const char16_t* currency, - UErrorCode* ec) const; - - // hashtable operations - Hashtable* initHashForAffixPattern(UErrorCode& status); - - void deleteHashForAffixPattern(); - - void copyHashForAffixPattern(const Hashtable* source, - Hashtable* target, UErrorCode& status); - - DecimalFormatImpl *fImpl; - - /** - * Constants. - */ - - - EnumSet - fBoolFlags; - - - // style is only valid when decimal formatter is constructed by - // DecimalFormat(pattern, decimalFormatSymbol, style) - int fStyle; - - - // Affix pattern set for currency. - // It is a set of AffixPatternsForCurrency, - // each element of the set saves the negative prefix pattern, - // negative suffix pattern, positive prefix pattern, - // and positive suffix pattern of a pattern. - // It is used for currency mixed style parsing. - // It is actually is a set. - // The set contains the default currency pattern from the locale, - // and the currency plural patterns. - // Since it is a set, it does not contain duplicated items. - // For example, if 2 currency plural patterns are the same, only one pattern - // is included in the set. When parsing, we do not check whether the plural - // count match or not. - Hashtable* fAffixPatternsForCurrency; - - // Information needed for DecimalFormat to format/parse currency plural. - CurrencyPluralInfo* fCurrencyPluralInfo; - -#if UCONFIG_HAVE_PARSEALLINPUT - UNumberFormatAttributeValue fParseAllInput; -#endif - - // Decimal Format Static Sets singleton. - const DecimalFormatStaticSets *fStaticSets; - -protected: - -#ifndef U_HIDE_INTERNAL_API - /** - * Rounds a value according to the rules of this object. - * @internal - */ - DigitList& _round(const DigitList& number, DigitList& adjustedNum, UBool& isNegative, UErrorCode& status) const; -#endif /* U_HIDE_INTERNAL_API */ - - /** - * Returns the currency in effect for this formatter. Subclasses - * should override this method as needed. Unlike getCurrency(), - * this method should never return "". - * @result output parameter for null-terminated result, which must - * have a capacity of at least 4 - * @internal - */ - virtual void getEffectiveCurrency(char16_t* result, UErrorCode& ec) const; - - /** number of integer digits - * @stable ICU 2.4 - */ - static const int32_t kDoubleIntegerDigits; - /** number of fraction digits - * @stable ICU 2.4 - */ - static const int32_t kDoubleFractionDigits; - - /** - * When someone turns on scientific mode, we assume that more than this - * number of digits is due to flipping from some other mode that didn't - * restrict the maximum, and so we force 1 integer digit. We don't bother - * to track and see if someone is using exponential notation with more than - * this number, it wouldn't make sense anyway, and this is just to make sure - * that someone turning on scientific mode with default settings doesn't - * end up with lots of zeroes. - * @stable ICU 2.8 - */ - static const int32_t kMaxScientificIntegerDigits; + // Allow child class CompactDecimalFormat to access fProperties: + friend class CompactDecimalFormat; }; diff --git a/deps/icu-small/source/i18n/unicode/fmtable.h b/deps/icu-small/source/i18n/unicode/fmtable.h index 766a71969de..2359b61d461 100644 --- a/deps/icu-small/source/i18n/unicode/fmtable.h +++ b/deps/icu-small/source/i18n/unicode/fmtable.h @@ -33,17 +33,11 @@ U_NAMESPACE_BEGIN class CharString; -class DigitList; - -/** - * \def UNUM_INTERNAL_STACKARRAY_SIZE - * @internal - */ -#if U_PLATFORM == U_PF_OS400 -#define UNUM_INTERNAL_STACKARRAY_SIZE 144 -#else -#define UNUM_INTERNAL_STACKARRAY_SIZE 128 -#endif +namespace number { +namespace impl { +class DecimalQuantity; +} +} /** * Formattable objects can be passed to the Format class or @@ -649,24 +643,25 @@ public: * Internal function, do not use. * TODO: figure out how to make this be non-public. * NumberFormat::format(Formattable, ... - * needs to get at the DigitList, if it exists, for + * needs to get at the DecimalQuantity, if it exists, for * big decimal formatting. * @internal */ - DigitList *getDigitList() const { return fDecimalNum;} + number::impl::DecimalQuantity *getDecimalQuantity() const { return fDecimalQuantity;} /** - * @internal + * Export the value of this Formattable to a DecimalQuantity. + * @internal */ - DigitList *getInternalDigitList(); + void populateDecimalQuantity(number::impl::DecimalQuantity& output, UErrorCode& status) const; /** - * Adopt, and set value from, a DigitList + * Adopt, and set value from, a DecimalQuantity * Internal Function, do not use. - * @param dl the Digit List to be adopted + * @param dl the DecimalQuantity to be adopted * @internal */ - void adoptDigitList(DigitList *dl); + void adoptDecimalQuantity(number::impl::DecimalQuantity *dq); /** * Internal function to return the CharString pointer. @@ -706,9 +701,7 @@ private: CharString *fDecimalStr; - DigitList *fDecimalNum; - - char fStackData[UNUM_INTERNAL_STACKARRAY_SIZE]; // must be big enough for DigitList + number::impl::DecimalQuantity *fDecimalQuantity; Type fType; UnicodeString fBogus; // Bogus string when it's needed. diff --git a/deps/icu-small/source/i18n/unicode/fpositer.h b/deps/icu-small/source/i18n/unicode/fpositer.h index 8e9d69c547f..81091f0ffad 100644 --- a/deps/icu-small/source/i18n/unicode/fpositer.h +++ b/deps/icu-small/source/i18n/unicode/fpositer.h @@ -47,13 +47,6 @@ U_NAMESPACE_BEGIN class UVector32; -// Forward declaration for number formatting: -namespace number { -namespace impl { -class NumberStringBuilder; -} -} - /** * FieldPositionIterator returns the field ids and their start/limit positions generated * by a call to Format::format. See Format, NumberFormat, DecimalFormat. @@ -114,7 +107,6 @@ private: void setData(UVector32 *adopt, UErrorCode& status); friend class FieldPositionIteratorHandler; - friend class number::impl::NumberStringBuilder; UVector32 *data; int32_t pos; diff --git a/deps/icu-small/source/i18n/unicode/measunit.h b/deps/icu-small/source/i18n/unicode/measunit.h index f7ddb4e20c5..f552253544f 100644 --- a/deps/icu-small/source/i18n/unicode/measunit.h +++ b/deps/icu-small/source/i18n/unicode/measunit.h @@ -400,14 +400,6 @@ class U_I18N_API MeasureUnit: public UObject { */ static MeasureUnit *createMilePerGallonImperial(UErrorCode &status); - /* - * The following were draft ICU 58, but have been withdrawn: - * static MeasureUnit *createEast(UErrorCode &status); - * static MeasureUnit *createNorth(UErrorCode &status); - * static MeasureUnit *createSouth(UErrorCode &status); - * static MeasureUnit *createWest(UErrorCode &status); - */ - /** * Returns unit of digital: bit. * Caller owns returned value and must free it. diff --git a/deps/icu-small/source/i18n/unicode/nounit.h b/deps/icu-small/source/i18n/unicode/nounit.h index 290e77e8806..288f268d66d 100644 --- a/deps/icu-small/source/i18n/unicode/nounit.h +++ b/deps/icu-small/source/i18n/unicode/nounit.h @@ -61,6 +61,12 @@ public: */ NoUnit(const NoUnit& other); + /** + * Destructor. + * @draft ICU 60 + */ + virtual ~NoUnit(); + /** * Return a polymorphic clone of this object. The result will * have the same class as returned by getDynamicClassID(). @@ -86,12 +92,6 @@ public: */ static UClassID U_EXPORT2 getStaticClassID(); - /** - * Destructor. - * @draft ICU 60 - */ - virtual ~NoUnit(); - private: /** * Constructor diff --git a/deps/icu-small/source/i18n/unicode/numberformatter.h b/deps/icu-small/source/i18n/unicode/numberformatter.h index 3fbb33cceea..3ab08319f73 100644 --- a/deps/icu-small/source/i18n/unicode/numberformatter.h +++ b/deps/icu-small/source/i18n/unicode/numberformatter.h @@ -17,6 +17,8 @@ #include "unicode/plurrule.h" #include "unicode/ucurr.h" #include "unicode/unum.h" +#include "unicode/unumberformatter.h" +#include "unicode/uobject.h" #ifndef U_HIDE_DRAFT_API @@ -31,11 +33,11 @@ * // Most basic usage: * NumberFormatter::withLocale(...).format(123).toString(); // 1,234 in en-US * - * // Custom notation, unit, and rounding strategy: + * // Custom notation, unit, and rounding precision: * NumberFormatter::with() * .notation(Notation::compactShort()) * .unit(CurrencyUnit("EUR", status)) - * .rounding(Rounder::maxDigits(2)) + * .precision(Precision::maxDigits(2)) * .locale(...) * .format(1234) * .toString(); // €1.2K in en-US @@ -43,7 +45,7 @@ * // Create a formatter in a singleton for use later: * static const LocalizedNumberFormatter formatter = NumberFormatter::withLocale(...) * .unit(NoUnit::percent()) - * .rounding(Rounder::fixedFraction(3)); + * .precision(Precision::fixedFraction(3)); * formatter.format(5.9831).toString(); // 5.983% in en-US * * // Create a "template" in a singleton but without setting a locale until the call site: @@ -63,7 +65,7 @@ * *
  * UnlocalizedNumberFormatter formatter = UnlocalizedNumberFormatter::with().notation(Notation::scientific());
- * formatter.rounding(Rounder.maxFraction(2)); // does nothing!
+ * formatter.precision(Precision.maxFraction(2)); // does nothing!
  * formatter.locale(Locale.getEnglish()).format(9.8765).toString(); // prints "9.8765E0", not "9.88E0"
  * 
* @@ -74,321 +76,23 @@ * @author Shane Carr */ -/** - * An enum declaring how to render units, including currencies. Example outputs when formatting 123 USD and 123 - * meters in en-CA: - * - *

- *

    - *
  • NARROW*: "$123.00" and "123 m" - *
  • SHORT: "US$ 123.00" and "123 m" - *
  • FULL_NAME: "123.00 US dollars" and "123 meters" - *
  • ISO_CODE: "USD 123.00" and undefined behavior - *
  • HIDDEN: "123.00" and "123" - *
- * - *

- * This enum is similar to {@link com.ibm.icu.text.MeasureFormat.FormatWidth}. - * - * @draft ICU 60 - */ -typedef enum UNumberUnitWidth { - /** - * Print an abbreviated version of the unit name. Similar to SHORT, but always use the shortest available - * abbreviation or symbol. This option can be used when the context hints at the identity of the unit. For more - * information on the difference between NARROW and SHORT, see SHORT. - * - *

- * In CLDR, this option corresponds to the "Narrow" format for measure units and the "¤¤¤¤¤" placeholder for - * currencies. - * - * @draft ICU 60 - */ - UNUM_UNIT_WIDTH_NARROW, +U_NAMESPACE_BEGIN - /** - * Print an abbreviated version of the unit name. Similar to NARROW, but use a slightly wider abbreviation or - * symbol when there may be ambiguity. This is the default behavior. - * - *

- * For example, in es-US, the SHORT form for Fahrenheit is "{0} °F", but the NARROW form is "{0}°", - * since Fahrenheit is the customary unit for temperature in that locale. - * - *

- * In CLDR, this option corresponds to the "Short" format for measure units and the "¤" placeholder for - * currencies. - * - * @draft ICU 60 - */ - UNUM_UNIT_WIDTH_SHORT, +// Forward declarations: +class IFixedDecimal; +class FieldPositionIteratorHandler; - /** - * Print the full name of the unit, without any abbreviations. - * - *

- * In CLDR, this option corresponds to the default format for measure units and the "¤¤¤" placeholder for - * currencies. - * - * @draft ICU 60 - */ - UNUM_UNIT_WIDTH_FULL_NAME, +namespace numparse { +namespace impl { - /** - * Use the three-digit ISO XXX code in place of the symbol for displaying currencies. The behavior of this - * option is currently undefined for use with measure units. - * - *

- * In CLDR, this option corresponds to the "¤¤" placeholder for currencies. - * - * @draft ICU 60 - */ - UNUM_UNIT_WIDTH_ISO_CODE, +// Forward declarations: +class NumberParserImpl; +class MultiplierParseHandler; - /** - * Format the number according to the specified unit, but do not display the unit. For currencies, apply - * monetary symbols and formats as with SHORT, but omit the currency symbol. For measure units, the behavior is - * equivalent to not specifying the unit at all. - * - * @draft ICU 60 - */ - UNUM_UNIT_WIDTH_HIDDEN +} +} -#ifndef U_HIDE_INTERNAL_API - , - /** - * One more than the highest UNumberUnitWidth value. - * - * @internal ICU 60: The numeric value may change over time; see ICU ticket #12420. - */ - UNUM_UNIT_WIDTH_COUNT -#endif // U_HIDE_INTERNAL_API -} UNumberUnitWidth; - -/** - * An enum declaring the strategy for when and how to display grouping separators (i.e., the - * separator, often a comma or period, after every 2-3 powers of ten). The choices are several - * pre-built strategies for different use cases that employ locale data whenever possible. Example - * outputs for 1234 and 1234567 in en-IN: - * - *

    - *
  • OFF: 1234 and 12345 - *
  • MIN2: 1234 and 12,34,567 - *
  • AUTO: 1,234 and 12,34,567 - *
  • ON_ALIGNED: 1,234 and 12,34,567 - *
  • THOUSANDS: 1,234 and 1,234,567 - *
- * - *

- * The default is AUTO, which displays grouping separators unless the locale data says that grouping - * is not customary. To force grouping for all numbers greater than 1000 consistently across locales, - * use ON_ALIGNED. On the other hand, to display grouping less frequently than the default, use MIN2 - * or OFF. See the docs of each option for details. - * - *

- * 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 - */ -typedef enum UGroupingStrategy { - /** - * Do not display grouping separators in any locale. - * - * @draft ICU 61 - */ - UNUM_GROUPING_OFF, - - /** - * Display grouping using locale defaults, except do not show grouping on values smaller than - * 10000 (such that there is a minimum of two digits before the first separator). - * - *

- * Note that locales may restrict grouping separators to be displayed only on 1 million or - * greater (for example, ee and hu) or disable grouping altogether (for example, bg currency). - * - *

- * Locale data is used to determine whether to separate larger numbers into groups of 2 - * (customary in South Asia) or groups of 3 (customary in Europe and the Americas). - * - * @draft ICU 61 - */ - UNUM_GROUPING_MIN2, - - /** - * Display grouping using the default strategy for all locales. This is the default behavior. - * - *

- * Note that locales may restrict grouping separators to be displayed only on 1 million or - * greater (for example, ee and hu) or disable grouping altogether (for example, bg currency). - * - *

- * Locale data is used to determine whether to separate larger numbers into groups of 2 - * (customary in South Asia) or groups of 3 (customary in Europe and the Americas). - * - * @draft ICU 61 - */ - UNUM_GROUPING_AUTO, - - /** - * Always display the grouping separator on values of at least 1000. - * - *

- * This option ignores the locale data that restricts or disables grouping, described in MIN2 and - * AUTO. This option may be useful to normalize the alignment of numbers, such as in a - * spreadsheet. - * - *

- * Locale data is used to determine whether to separate larger numbers into groups of 2 - * (customary in South Asia) or groups of 3 (customary in Europe and the Americas). - * - * @draft ICU 61 - */ - UNUM_GROUPING_ON_ALIGNED, - - /** - * Use the Western defaults: groups of 3 and enabled for all numbers 1000 or greater. Do not use - * locale data for determining the grouping strategy. - * - * @draft ICU 61 - */ - UNUM_GROUPING_THOUSANDS - -} UGroupingStrategy; - -/** - * An enum declaring how to denote positive and negative numbers. Example outputs when formatting - * 123, 0, and -123 in en-US: - * - *

    - *
  • AUTO: "123", "0", and "-123" - *
  • ALWAYS: "+123", "+0", and "-123" - *
  • NEVER: "123", "0", and "123" - *
  • ACCOUNTING: "$123", "$0", and "($123)" - *
  • ACCOUNTING_ALWAYS: "+$123", "+$0", and "($123)" - *
  • EXCEPT_ZERO: "+123", "0", and "-123" - *
  • ACCOUNTING_EXCEPT_ZERO: "+$123", "$0", and "($123)" - *
- * - *

- * The exact format, including the position and the code point of the sign, differ by locale. - * - * @draft ICU 60 - */ -typedef enum UNumberSignDisplay { - /** - * Show the minus sign on negative numbers, and do not show the sign on positive numbers. This is the default - * behavior. - * - * @draft ICU 60 - */ - UNUM_SIGN_AUTO, - - /** - * Show the minus sign on negative numbers and the plus sign on positive numbers, including zero. - * To hide the sign on zero, see {@link UNUM_SIGN_EXCEPT_ZERO}. - * - * @draft ICU 60 - */ - UNUM_SIGN_ALWAYS, - - /** - * Do not show the sign on positive or negative numbers. - * - * @draft ICU 60 - */ - UNUM_SIGN_NEVER, - - /** - * Use the locale-dependent accounting format on negative numbers, and do not show the sign on positive numbers. - * - *

- * The accounting format is defined in CLDR and varies by locale; in many Western locales, the format is a pair - * of parentheses around the number. - * - *

- * Note: Since CLDR defines the accounting format in the monetary context only, this option falls back to the - * AUTO sign display strategy when formatting without a currency unit. This limitation may be lifted in the - * future. - * - * @draft ICU 60 - */ - UNUM_SIGN_ACCOUNTING, - - /** - * Use the locale-dependent accounting format on negative numbers, and show the plus sign on - * positive numbers, including zero. For more information on the accounting format, see the - * ACCOUNTING sign display strategy. To hide the sign on zero, see - * {@link UNUM_SIGN_ACCOUNTING_EXCEPT_ZERO}. - * - * @draft ICU 60 - */ - UNUM_SIGN_ACCOUNTING_ALWAYS, - - /** - * Show the minus sign on negative numbers and the plus sign on positive numbers. Do not show a - * sign on zero. - * - * @draft ICU 61 - */ - UNUM_SIGN_EXCEPT_ZERO, - - /** - * Use the locale-dependent accounting format on negative numbers, and show the plus sign on - * positive numbers. Do not show a sign on zero. For more information on the accounting format, - * see the ACCOUNTING sign display strategy. - * - * @draft ICU 61 - */ - UNUM_SIGN_ACCOUNTING_EXCEPT_ZERO - -#ifndef U_HIDE_INTERNAL_API - , - /** - * One more than the highest UNumberSignDisplay value. - * - * @internal ICU 60: The numeric value may change over time; see ICU ticket #12420. - */ - UNUM_SIGN_COUNT -#endif // U_HIDE_INTERNAL_API -} UNumberSignDisplay; - -/** - * An enum declaring how to render the decimal separator. - * - *

- *

    - *
  • UNUM_DECIMAL_SEPARATOR_AUTO: "1", "1.1" - *
  • UNUM_DECIMAL_SEPARATOR_ALWAYS: "1.", "1.1" - *
- */ -typedef enum UNumberDecimalSeparatorDisplay { - /** - * Show the decimal separator when there are one or more digits to display after the separator, and do not show - * it otherwise. This is the default behavior. - * - * @draft ICU 60 - */ - UNUM_DECIMAL_SEPARATOR_AUTO, - - /** - * Always show the decimal separator, even if there are no digits to display after the separator. - * - * @draft ICU 60 - */ - UNUM_DECIMAL_SEPARATOR_ALWAYS - -#ifndef U_HIDE_INTERNAL_API - , - /** - * One more than the highest UNumberDecimalSeparatorDisplay value. - * - * @internal ICU 60: The numeric value may change over time; see ICU ticket #12420. - */ - UNUM_DECIMAL_SEPARATOR_COUNT -#endif // U_HIDE_INTERNAL_API -} UNumberDecimalMarkDisplay; - -U_NAMESPACE_BEGIN namespace number { // icu::number +namespace number { // icu::number // Forward declarations: class UnlocalizedNumberFormatter; @@ -396,15 +100,14 @@ class LocalizedNumberFormatter; class FormattedNumber; class Notation; class ScientificNotation; -class Rounder; -class FractionRounder; -class CurrencyRounder; -class IncrementRounder; +class Precision; +class FractionPrecision; +class CurrencyPrecision; +class IncrementPrecision; class IntegerWidth; namespace impl { -#ifndef U_HIDE_INTERNAL_API /** * Datatype for minimum/maximum fraction digits. Must be able to hold kMaxIntFracSig. * @@ -419,24 +122,28 @@ typedef int16_t digits_t; * @internal */ static constexpr int32_t DEFAULT_THRESHOLD = 3; -#endif // U_HIDE_INTERNAL_API // Forward declarations: class Padder; struct MacroProps; struct MicroProps; class DecimalQuantity; -struct NumberFormatterResults; +struct UFormattedNumberData; class NumberFormatterImpl; struct ParsedPatternInfo; class ScientificModifier; class MultiplierProducer; -class MutablePatternModifier; -class LongNameHandler; +class RoundingImpl; class ScientificHandler; -class CompactHandler; class Modifier; class NumberStringBuilder; +class AffixPatternProvider; +class NumberPropertyMapper; +struct DecimalFormatProperties; +class MultiplierFormatHandler; +class CurrencySymbols; +class GeneratorHelpers; +class DecNum; } // namespace impl @@ -530,13 +237,13 @@ class U_I18N_API Notation : public UMemory { * * *

- * When compact notation is specified without an explicit rounding strategy, numbers are rounded off to the closest + * When compact notation is specified without an explicit rounding precision, numbers are rounded off to the closest * integer after scaling the number by the corresponding power of 10, but with a digit shown after the decimal - * separator if there is only one digit before the decimal separator. The default compact notation rounding strategy + * separator if there is only one digit before the decimal separator. The default compact notation rounding precision * is equivalent to: * *

-     * Rounder.integer().withMinDigits(2)
+     * Precision::integer().withMinDigits(2)
      * 
* * @return A CompactNotation for passing to the NumberFormatter notation() setter. @@ -641,6 +348,9 @@ class U_I18N_API Notation : public UMemory { friend class impl::NumberFormatterImpl; friend class impl::ScientificModifier; friend class impl::ScientificHandler; + + // To allow access to the skeleton generation code: + friend class impl::GeneratorHelpers; }; /** @@ -687,21 +397,36 @@ class U_I18N_API ScientificNotation : public Notation { // Inherit constructor using Notation::Notation; + // Raw constructor for NumberPropertyMapper + ScientificNotation(int8_t fEngineeringInterval, bool fRequireMinInt, impl::digits_t fMinExponentDigits, + UNumberSignDisplay fExponentSignDisplay); + friend class Notation; + + // So that NumberPropertyMapper can create instances + friend class impl::NumberPropertyMapper; }; // Reserve extra names in case they are added as classes in the future: -typedef Rounder DigitRounder; +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 +typedef Precision Rounder; +typedef FractionPrecision FractionRounder; +typedef IncrementPrecision IncrementRounder; +typedef CurrencyPrecision CurrencyRounder; /** - * A class that defines the rounding strategy to be used when formatting numbers in NumberFormatter. + * A class that defines the rounding precision to be used when formatting numbers in NumberFormatter. * *

- * To create a Rounder, use one of the factory methods. + * To create a Precision, use one of the factory methods. * * @draft ICU 60 */ -class U_I18N_API Rounder : public UMemory { +class U_I18N_API Precision : public UMemory { public: /** @@ -717,18 +442,18 @@ class U_I18N_API Rounder : public UMemory { *

* http://www.serpentine.com/blog/2011/06/29/here-be-dragons-advances-in-problems-you-didnt-even-know-you-had/ * - * @return A Rounder for chaining or passing to the NumberFormatter rounding() setter. + * @return A Precision for chaining or passing to the NumberFormatter precision() setter. * @draft ICU 60 */ - static Rounder unlimited(); + static Precision unlimited(); /** * Show numbers rounded if necessary to the nearest integer. * - * @return A FractionRounder for chaining or passing to the NumberFormatter rounding() setter. + * @return A FractionPrecision for chaining or passing to the NumberFormatter precision() setter. * @draft ICU 60 */ - static FractionRounder integer(); + static FractionPrecision integer(); /** * Show numbers rounded if necessary to a certain number of fraction places (numerals after the decimal separator). @@ -754,10 +479,10 @@ class U_I18N_API Rounder : public UMemory { * @param minMaxFractionPlaces * The minimum and maximum number of numerals to display after the decimal separator (rounding if too * long or padding with zeros if too short). - * @return A FractionRounder for chaining or passing to the NumberFormatter rounding() setter. + * @return A FractionPrecision for chaining or passing to the NumberFormatter precision() setter. * @draft ICU 60 */ - static FractionRounder fixedFraction(int32_t minMaxFractionPlaces); + static FractionPrecision fixedFraction(int32_t minMaxFractionPlaces); /** * Always show at least a certain number of fraction places after the decimal separator, padding with zeros if @@ -769,10 +494,10 @@ class U_I18N_API Rounder : public UMemory { * @param minFractionPlaces * The minimum number of numerals to display after the decimal separator (padding with zeros if * necessary). - * @return A FractionRounder for chaining or passing to the NumberFormatter rounding() setter. + * @return A FractionPrecision for chaining or passing to the NumberFormatter precision() setter. * @draft ICU 60 */ - static FractionRounder minFraction(int32_t minFractionPlaces); + static FractionPrecision minFraction(int32_t minFractionPlaces); /** * Show numbers rounded if necessary to a certain number of fraction places (numerals after the decimal separator). @@ -781,10 +506,10 @@ class U_I18N_API Rounder : public UMemory { * * @param maxFractionPlaces * The maximum number of numerals to display after the decimal mark (rounding if necessary). - * @return A FractionRounder for chaining or passing to the NumberFormatter rounding() setter. + * @return A FractionPrecision for chaining or passing to the NumberFormatter precision() setter. * @draft ICU 60 */ - static FractionRounder maxFraction(int32_t maxFractionPlaces); + static FractionPrecision maxFraction(int32_t maxFractionPlaces); /** * Show numbers rounded if necessary to a certain number of fraction places (numerals after the decimal separator); @@ -796,10 +521,10 @@ class U_I18N_API Rounder : public UMemory { * necessary). * @param maxFractionPlaces * The maximum number of numerals to display after the decimal separator (rounding if necessary). - * @return A FractionRounder for chaining or passing to the NumberFormatter rounding() setter. + * @return A FractionPrecision for chaining or passing to the NumberFormatter precision() setter. * @draft ICU 60 */ - static FractionRounder minMaxFraction(int32_t minFractionPlaces, int32_t maxFractionPlaces); + static FractionPrecision minMaxFraction(int32_t minFractionPlaces, int32_t maxFractionPlaces); /** * Show numbers rounded if necessary to a certain number of significant digits or significant figures. Additionally, @@ -811,10 +536,10 @@ class U_I18N_API Rounder : public UMemory { * @param minMaxSignificantDigits * The minimum and maximum number of significant digits to display (rounding if too long or padding with * zeros if too short). - * @return A Rounder for chaining or passing to the NumberFormatter rounding() setter. - * @draft ICU 60 + * @return A precision for chaining or passing to the NumberFormatter precision() setter. + * @draft ICU 62 */ - static DigitRounder fixedDigits(int32_t minMaxSignificantDigits); + static SignificantDigitsPrecision fixedSignificantDigits(int32_t minMaxSignificantDigits); /** * Always show at least a certain number of significant digits/figures, padding with zeros if necessary. Do not @@ -825,20 +550,20 @@ class U_I18N_API Rounder : public UMemory { * * @param minSignificantDigits * The minimum number of significant digits to display (padding with zeros if too short). - * @return A Rounder for chaining or passing to the NumberFormatter rounding() setter. - * @draft ICU 60 + * @return A precision for chaining or passing to the NumberFormatter precision() setter. + * @draft ICU 62 */ - static DigitRounder minDigits(int32_t minSignificantDigits); + static SignificantDigitsPrecision minSignificantDigits(int32_t minSignificantDigits); /** * Show numbers rounded if necessary to a certain number of significant digits/figures. * * @param maxSignificantDigits * The maximum number of significant digits to display (rounding if too long). - * @return A Rounder for chaining or passing to the NumberFormatter rounding() setter. - * @draft ICU 60 + * @return A precision for chaining or passing to the NumberFormatter precision() setter. + * @draft ICU 62 */ - static DigitRounder maxDigits(int32_t maxSignificantDigits); + static SignificantDigitsPrecision maxSignificantDigits(int32_t maxSignificantDigits); /** * Show numbers rounded if necessary to a certain number of significant digits/figures; in addition, always show at @@ -848,10 +573,36 @@ class U_I18N_API Rounder : public UMemory { * The minimum number of significant digits to display (padding with zeros if necessary). * @param maxSignificantDigits * The maximum number of significant digits to display (rounding if necessary). - * @return A Rounder for chaining or passing to the NumberFormatter rounding() setter. - * @draft ICU 60 + * @return A precision for chaining or passing to the NumberFormatter precision() setter. + * @draft ICU 62 */ - static DigitRounder minMaxDigits(int32_t minSignificantDigits, int32_t maxSignificantDigits); + static SignificantDigitsPrecision minMaxSignificantDigits(int32_t minSignificantDigits, + int32_t maxSignificantDigits); + +#ifndef U_HIDE_DEPRECATED_API + // Compatiblity methods that will be removed in ICU 64. + // See http://bugs.icu-project.org/trac/ticket/13746 + + /** @deprecated ICU 62 */ + static inline SignificantDigitsPrecision fixedDigits(int32_t a) { + return fixedSignificantDigits(a); + } + + /** @deprecated ICU 62 */ + static inline SignificantDigitsPrecision minDigits(int32_t a) { + return minSignificantDigits(a); + } + + /** @deprecated ICU 62 */ + static inline SignificantDigitsPrecision maxDigits(int32_t a) { + return maxSignificantDigits(a); + } + + /** @deprecated ICU 62 */ + static inline SignificantDigitsPrecision minMaxDigits(int32_t a, int32_t b) { + return minMaxSignificantDigits(a, b); + } +#endif /* U_HIDE_DEPRECATED_API */ /** * Show numbers rounded if necessary to the closest multiple of a certain rounding increment. For example, if the @@ -864,20 +615,21 @@ class U_I18N_API Rounder : public UMemory { * decimal separator (to display 1.2 as "1.00" and 1.3 as "1.50"), you can run: * *

-     * Rounder::increment(0.5).withMinFraction(2)
+     * Precision::increment(0.5).withMinFraction(2)
      * 
* * @param roundingIncrement * The increment to which to round numbers. - * @return A Rounder for chaining or passing to the NumberFormatter rounding() setter. + * @return A precision for chaining or passing to the NumberFormatter precision() setter. * @draft ICU 60 */ - static IncrementRounder increment(double roundingIncrement); + static IncrementPrecision increment(double roundingIncrement); /** - * Show numbers rounded and padded according to the rules for the currency unit. The most common rounding settings - * for currencies include Rounder.fixedFraction(2), Rounder.integer(), and - * Rounder.increment(0.05) for cash transactions ("nickel rounding"). + * Show numbers rounded and padded according to the rules for the currency unit. The most common + * rounding precision settings for currencies include Precision::fixedFraction(2), + * Precision::integer(), and Precision::increment(0.05) for cash transactions + * ("nickel rounding"). * *

* The exact rounding details will be resolved at runtime based on the currency unit specified in the @@ -887,24 +639,28 @@ class U_I18N_API Rounder : public UMemory { * @param currencyUsage * Either STANDARD (for digital transactions) or CASH (for transactions where the rounding increment may * be limited by the available denominations of cash or coins). - * @return A CurrencyRounder for chaining or passing to the NumberFormatter rounding() setter. + * @return A CurrencyPrecision for chaining or passing to the NumberFormatter precision() setter. * @draft ICU 60 */ - static CurrencyRounder currency(UCurrencyUsage currencyUsage); + static CurrencyPrecision currency(UCurrencyUsage currencyUsage); +#ifndef U_HIDE_DEPRECATED_API /** * Sets the rounding mode to use when picking the direction to round (up or down). Common values * include HALF_EVEN, HALF_UP, and FLOOR. The default is HALF_EVEN. * * @param roundingMode * The RoundingMode to use. - * @return A Rounder for passing to the NumberFormatter rounding() setter. - * @draft ICU 60 + * @return A Precision for passing to the NumberFormatter precision() setter. + * @deprecated ICU 62 Use the top-level roundingMode() setting instead. + * This method will be removed in ICU 64. + * See http://bugs.icu-project.org/trac/ticket/13746 */ - Rounder withMode(UNumberFormatRoundingMode roundingMode) const; + Precision withMode(UNumberFormatRoundingMode roundingMode) const; +#endif /* U_HIDE_DEPRECATED_API */ private: - enum RounderType { + enum PrecisionType { RND_BOGUS, RND_NONE, RND_FRACTION, @@ -912,11 +668,10 @@ class U_I18N_API Rounder : public UMemory { RND_FRACTION_SIGNIFICANT, RND_INCREMENT, RND_CURRENCY, - RND_PASS_THROUGH, RND_ERROR } fType; - union RounderUnion { + union PrecisionUnion { struct FractionSignificantSettings { // For RND_FRACTION, RND_SIGNIFICANT, and RND_FRACTION_SIGNIFICANT impl::digits_t fMinFrac; @@ -927,24 +682,27 @@ class U_I18N_API Rounder : public UMemory { struct IncrementSettings { double fIncrement; impl::digits_t fMinFrac; + impl::digits_t fMaxFrac; } increment; // For RND_INCREMENT UCurrencyUsage currencyUsage; // For RND_CURRENCY UErrorCode errorCode; // For RND_ERROR } fUnion; - typedef RounderUnion::FractionSignificantSettings FractionSignificantSettings; - typedef RounderUnion::IncrementSettings IncrementSettings; + typedef PrecisionUnion::FractionSignificantSettings FractionSignificantSettings; + typedef PrecisionUnion::IncrementSettings IncrementSettings; + /** The Precision encapsulates the RoundingMode when used within the implementation. */ UNumberFormatRoundingMode fRoundingMode; - Rounder(const RounderType &type, const RounderUnion &union_, UNumberFormatRoundingMode roundingMode) + Precision(const PrecisionType& type, const PrecisionUnion& union_, + UNumberFormatRoundingMode roundingMode) : fType(type), fUnion(union_), fRoundingMode(roundingMode) {} - Rounder(UErrorCode errorCode) : fType(RND_ERROR) { + Precision(UErrorCode errorCode) : fType(RND_ERROR) { fUnion.errorCode = errorCode; } - Rounder() : fType(RND_BOGUS) {} + Precision() : fType(RND_BOGUS) {} bool isBogus() const { return fType == RND_BOGUS; @@ -958,47 +716,21 @@ class U_I18N_API Rounder : public UMemory { return FALSE; } - // On the parent type so that this method can be called internally on Rounder instances. - Rounder withCurrency(const CurrencyUnit ¤cy, UErrorCode &status) const; + // On the parent type so that this method can be called internally on Precision instances. + Precision withCurrency(const CurrencyUnit ¤cy, UErrorCode &status) const; - /** NON-CONST: mutates the current instance. */ - void setLocaleData(const CurrencyUnit ¤cy, UErrorCode &status); + static FractionPrecision constructFraction(int32_t minFrac, int32_t maxFrac); - void apply(impl::DecimalQuantity &value, UErrorCode &status) const; + static Precision constructSignificant(int32_t minSig, int32_t maxSig); - /** Version of {@link #apply} that obeys minInt constraints. Used for scientific notation compatibility mode. */ - void apply(impl::DecimalQuantity &value, int32_t minInt, UErrorCode status); + static Precision + constructFractionSignificant(const FractionPrecision &base, int32_t minSig, int32_t maxSig); - /** - * Rounding endpoint used by Engineering and Compact notation. Chooses the most appropriate multiplier (magnitude - * adjustment), applies the adjustment, rounds, and returns the chosen multiplier. - * - *

- * In most cases, this is simple. However, when rounding the number causes it to cross a multiplier boundary, we - * need to re-do the rounding. For example, to display 999,999 in Engineering notation with 2 sigfigs, first you - * guess the multiplier to be -3. However, then you end up getting 1000E3, which is not the correct output. You then - * change your multiplier to be -6, and you get 1.0E6, which is correct. - * - * @param input The quantity to process. - * @param producer Function to call to return a multiplier based on a magnitude. - * @return The number of orders of magnitude the input was adjusted by this method. - */ - int32_t - chooseMultiplierAndApply(impl::DecimalQuantity &input, const impl::MultiplierProducer &producer, - UErrorCode &status); + static IncrementPrecision constructIncrement(double increment, int32_t minFrac); - static FractionRounder constructFraction(int32_t minFrac, int32_t maxFrac); + static CurrencyPrecision constructCurrency(UCurrencyUsage usage); - static Rounder constructSignificant(int32_t minSig, int32_t maxSig); - - static Rounder - constructFractionSignificant(const FractionRounder &base, int32_t minSig, int32_t maxSig); - - static IncrementRounder constructIncrement(double increment, int32_t minFrac); - - static CurrencyRounder constructCurrency(UCurrencyUsage usage); - - static Rounder constructPassThrough(); + static Precision constructPassThrough(); // To allow MacroProps/MicroProps to initialize bogus instances: friend struct impl::MacroProps; @@ -1007,28 +739,31 @@ class U_I18N_API Rounder : public UMemory { // To allow NumberFormatterImpl to access isBogus() and other internal methods: friend class impl::NumberFormatterImpl; - // To give access to apply() and chooseMultiplierAndApply(): - friend class impl::MutablePatternModifier; - friend class impl::LongNameHandler; - friend class impl::ScientificHandler; - friend class impl::CompactHandler; + // To allow NumberPropertyMapper to create instances from DecimalFormatProperties: + friend class impl::NumberPropertyMapper; + + // To allow access to the main implementation class: + friend class impl::RoundingImpl; // To allow child classes to call private methods: - friend class FractionRounder; - friend class CurrencyRounder; - friend class IncrementRounder; + friend class FractionPrecision; + friend class CurrencyPrecision; + friend class IncrementPrecision; + + // To allow access to the skeleton generation code: + friend class impl::GeneratorHelpers; }; /** - * A class that defines a rounding strategy based on a number of fraction places and optionally significant digits to be + * A class that defines a rounding precision based on a number of fraction places and optionally significant digits to be * used when formatting numbers in NumberFormatter. * *

- * To create a FractionRounder, use one of the factory methods on Rounder. + * To create a FractionPrecision, use one of the factory methods on Precision. * * @draft ICU 60 */ -class U_I18N_API FractionRounder : public Rounder { +class U_I18N_API FractionPrecision : public Precision { public: /** * Ensure that no less than this number of significant digits are retained when rounding according to fraction @@ -1043,10 +778,10 @@ class U_I18N_API FractionRounder : public Rounder { * * @param minSignificantDigits * The number of significant figures to guarantee. - * @return A Rounder for chaining or passing to the NumberFormatter rounding() setter. + * @return A precision for chaining or passing to the NumberFormatter precision() setter. * @draft ICU 60 */ - Rounder withMinDigits(int32_t minSignificantDigits) const; + Precision withMinDigits(int32_t minSignificantDigits) const; /** * Ensure that no more than this number of significant digits are retained when rounding according to fraction @@ -1062,36 +797,36 @@ class U_I18N_API FractionRounder : public Rounder { * * @param maxSignificantDigits * Round the number to no more than this number of significant figures. - * @return A Rounder for chaining or passing to the NumberFormatter rounding() setter. + * @return A precision for chaining or passing to the NumberFormatter precision() setter. * @draft ICU 60 */ - Rounder withMaxDigits(int32_t maxSignificantDigits) const; + Precision withMaxDigits(int32_t maxSignificantDigits) const; private: // Inherit constructor - using Rounder::Rounder; + using Precision::Precision; // To allow parent class to call this class's constructor: - friend class Rounder; + friend class Precision; }; /** - * A class that defines a rounding strategy parameterized by a currency to be used when formatting numbers in + * A class that defines a rounding precision parameterized by a currency to be used when formatting numbers in * NumberFormatter. * *

- * To create a CurrencyRounder, use one of the factory methods on Rounder. + * To create a CurrencyPrecision, use one of the factory methods on Precision. * * @draft ICU 60 */ -class U_I18N_API CurrencyRounder : public Rounder { +class U_I18N_API CurrencyPrecision : public Precision { public: /** - * Associates a currency with this rounding strategy. + * Associates a currency with this rounding precision. * *

* Calling this method is not required, because the currency specified in unit() - * is automatically applied to currency rounding strategies. However, + * is automatically applied to currency rounding precisions. However, * this method enables you to override that automatic association. * *

@@ -1099,30 +834,30 @@ class U_I18N_API CurrencyRounder : public Rounder { * currency format. * * @param currency - * The currency to associate with this rounding strategy. - * @return A Rounder for chaining or passing to the NumberFormatter rounding() setter. + * The currency to associate with this rounding precision. + * @return A precision for chaining or passing to the NumberFormatter precision() setter. * @draft ICU 60 */ - Rounder withCurrency(const CurrencyUnit ¤cy) const; + Precision withCurrency(const CurrencyUnit ¤cy) const; private: // Inherit constructor - using Rounder::Rounder; + using Precision::Precision; // To allow parent class to call this class's constructor: - friend class Rounder; + friend class Precision; }; /** - * A class that defines a rounding strategy parameterized by a rounding increment to be used when formatting numbers in + * A class that defines a rounding precision parameterized by a rounding increment to be used when formatting numbers in * NumberFormatter. * *

- * To create an IncrementRounder, use one of the factory methods on Rounder. + * To create an IncrementPrecision, use one of the factory methods on Precision. * * @draft ICU 60 */ -class U_I18N_API IncrementRounder : public Rounder { +class U_I18N_API IncrementPrecision : public Precision { public: /** * Specifies the minimum number of fraction digits to render after the decimal separator, padding with zeros if @@ -1136,17 +871,17 @@ class U_I18N_API IncrementRounder : public Rounder { * Note: In ICU4J, this functionality is accomplished via the scale of the BigDecimal rounding increment. * * @param minFrac The minimum number of digits after the decimal separator. - * @return A Rounder for chaining or passing to the NumberFormatter rounding() setter. + * @return A precision for chaining or passing to the NumberFormatter precision() setter. * @draft ICU 60 */ - Rounder withMinFraction(int32_t minFrac) const; + Precision withMinFraction(int32_t minFrac) const; private: // Inherit constructor - using Rounder::Rounder; + using Precision::Precision; // To allow parent class to call this class's constructor: - friend class Rounder; + friend class Precision; }; /** @@ -1170,7 +905,6 @@ class U_I18N_API IntegerWidth : public UMemory { * The minimum number of places before the decimal separator. * @return An IntegerWidth for chaining or passing to the NumberFormatter integerWidth() setter. * @draft ICU 60 - * @see NumberFormatter */ static IntegerWidth zeroFillTo(int32_t minInt); @@ -1184,7 +918,6 @@ class U_I18N_API IntegerWidth : public UMemory { * truncation. * @return An IntegerWidth for passing to the NumberFormatter integerWidth() setter. * @draft ICU 60 - * @see NumberFormatter */ IntegerWidth truncateAt(int32_t maxInt); @@ -1193,12 +926,13 @@ class U_I18N_API IntegerWidth : public UMemory { struct { impl::digits_t fMinInt; impl::digits_t fMaxInt; + bool fFormatFailIfMoreThanMaxDigits; } minMaxInt; UErrorCode errorCode; } fUnion; bool fHasError = false; - IntegerWidth(impl::digits_t minInt, impl::digits_t maxInt); + IntegerWidth(impl::digits_t minInt, impl::digits_t maxInt, bool formatFailIfMoreThanMaxDigits); IntegerWidth(UErrorCode errorCode) { // NOLINT fUnion.errorCode = errorCode; @@ -1209,6 +943,11 @@ class U_I18N_API IntegerWidth : public UMemory { fUnion.minMaxInt.fMinInt = -1; } + /** Returns the default instance. */ + static IntegerWidth standard() { + return IntegerWidth::zeroFillTo(1); + } + bool isBogus() const { return !fHasError && fUnion.minMaxInt.fMinInt == -1; } @@ -1223,12 +962,148 @@ class U_I18N_API IntegerWidth : public UMemory { void apply(impl::DecimalQuantity &quantity, UErrorCode &status) const; + bool operator==(const IntegerWidth& other) const; + // To allow MacroProps/MicroProps to initialize empty instances: friend struct impl::MacroProps; friend struct impl::MicroProps; // To allow NumberFormatterImpl to access isBogus() and perform other operations: friend class impl::NumberFormatterImpl; + + // So that NumberPropertyMapper can create instances + friend class impl::NumberPropertyMapper; + + // To allow access to the skeleton generation code: + friend class impl::GeneratorHelpers; +}; + +/** + * A class that defines a quantity by which a number should be multiplied when formatting. + * + *

+ * To create a Scale, use one of the factory methods. + * + * @draft ICU 62 + */ +class U_I18N_API Scale : public UMemory { + public: + /** + * Do not change the value of numbers when formatting or parsing. + * + * @return A Scale to prevent any multiplication. + * @draft ICU 62 + */ + static Scale none(); + + /** + * Multiply numbers by a power of ten before formatting. Useful for combining with a percent unit: + * + *

+     * NumberFormatter::with().unit(NoUnit::percent()).multiplier(Scale::powerOfTen(2))
+     * 
+ * + * @return A Scale for passing to the setter in NumberFormatter. + * @draft ICU 62 + */ + static Scale powerOfTen(int32_t power); + + /** + * Multiply numbers by an arbitrary value before formatting. Useful for unit conversions. + * + * This method takes a string in a decimal number format with syntax + * as defined in the Decimal Arithmetic Specification, available at + * http://speleotrove.com/decimal + * + * Also see the version of this method that takes a double. + * + * @return A Scale for passing to the setter in NumberFormatter. + * @draft ICU 62 + */ + static Scale byDecimal(StringPiece multiplicand); + + /** + * Multiply numbers by an arbitrary value before formatting. Useful for unit conversions. + * + * This method takes a double; also see the version of this method that takes an exact decimal. + * + * @return A Scale for passing to the setter in NumberFormatter. + * @draft ICU 62 + */ + static Scale byDouble(double multiplicand); + + /** + * Multiply a number by both a power of ten and by an arbitrary double value. + * + * @return A Scale for passing to the setter in NumberFormatter. + * @draft ICU 62 + */ + static Scale byDoubleAndPowerOfTen(double multiplicand, int32_t power); + + // We need a custom destructor for the DecNum, which means we need to declare + // the copy/move constructor/assignment quartet. + + /** @draft ICU 62 */ + Scale(const Scale& other); + + /** @draft ICU 62 */ + Scale& operator=(const Scale& other); + + /** @draft ICU 62 */ + Scale(Scale&& src) U_NOEXCEPT; + + /** @draft ICU 62 */ + Scale& operator=(Scale&& src) U_NOEXCEPT; + + /** @draft ICU 62 */ + ~Scale(); + +#ifndef U_HIDE_INTERNAL_API + /** @internal */ + Scale(int32_t magnitude, impl::DecNum* arbitraryToAdopt); +#endif /* U_HIDE_INTERNAL_API */ + + private: + int32_t fMagnitude; + impl::DecNum* fArbitrary; + UErrorCode fError; + + Scale(UErrorCode error) : fMagnitude(0), fArbitrary(nullptr), fError(error) {} + + Scale() : fMagnitude(0), fArbitrary(nullptr), fError(U_ZERO_ERROR) {} + + bool isValid() const { + return fMagnitude != 0 || fArbitrary != nullptr; + } + + UBool copyErrorTo(UErrorCode &status) const { + if (fError != U_ZERO_ERROR) { + status = fError; + return TRUE; + } + return FALSE; + } + + void applyTo(impl::DecimalQuantity& quantity) const; + + void applyReciprocalTo(impl::DecimalQuantity& quantity) const; + + // To allow MacroProps/MicroProps to initialize empty instances: + friend struct impl::MacroProps; + friend struct impl::MicroProps; + + // To allow NumberFormatterImpl to access isBogus() and perform other operations: + friend class impl::NumberFormatterImpl; + + // To allow the helper class MultiplierFormatHandler access to private fields: + friend class impl::MultiplierFormatHandler; + + // To allow access to the skeleton generation code: + friend class impl::GeneratorHelpers; + + // To allow access to parsing code: + friend class ::icu::numparse::impl::NumberParserImpl; + friend class ::icu::numparse::impl::MultiplierParseHandler; }; namespace impl { @@ -1243,13 +1118,20 @@ class U_I18N_API SymbolsWrapper : public UMemory { /** @internal */ SymbolsWrapper(const SymbolsWrapper &other); - /** @internal */ - ~SymbolsWrapper(); - /** @internal */ SymbolsWrapper &operator=(const SymbolsWrapper &other); + /** @internal */ + SymbolsWrapper(SymbolsWrapper&& src) U_NOEXCEPT; + + /** @internal */ + SymbolsWrapper &operator=(SymbolsWrapper&& src) U_NOEXCEPT; + + /** @internal */ + ~SymbolsWrapper(); + #ifndef U_HIDE_INTERNAL_API + /** * The provided object is copied, but we do not adopt it. * @internal @@ -1286,6 +1168,8 @@ class U_I18N_API SymbolsWrapper : public UMemory { */ const NumberingSystem *getNumberingSystem() const; +#endif // U_HIDE_INTERNAL_API + /** @internal */ UBool copyErrorTo(UErrorCode &status) const { if (fType == SYMPTR_DFS && fPtr.dfs == nullptr) { @@ -1297,7 +1181,6 @@ class U_I18N_API SymbolsWrapper : public UMemory { } return FALSE; } -#endif // U_HIDE_INTERNAL_API private: enum SymbolsPointerType { @@ -1311,6 +1194,8 @@ class U_I18N_API SymbolsWrapper : public UMemory { void doCopyFrom(const SymbolsWrapper &other); + void doMoveFrom(SymbolsWrapper&& src); + void doCleanup(); }; @@ -1322,13 +1207,28 @@ class U_I18N_API Grouper : public UMemory { /** @internal */ static Grouper forStrategy(UGroupingStrategy grouping); + /** + * Resolve the values in Properties to a Grouper object. + * @internal + */ + static Grouper forProperties(const DecimalFormatProperties& properties); + // Future: static Grouper forProperties(DecimalFormatProperties& properties); /** @internal */ - Grouper(int16_t grouping1, int16_t grouping2, int16_t minGrouping) - : fGrouping1(grouping1), fGrouping2(grouping2), fMinGrouping(minGrouping) {} + Grouper(int16_t grouping1, int16_t grouping2, int16_t minGrouping, UGroupingStrategy strategy) + : fGrouping1(grouping1), + fGrouping2(grouping2), + fMinGrouping(minGrouping), + fStrategy(strategy) {} #endif // U_HIDE_INTERNAL_API + /** @internal */ + int16_t getPrimary() const; + + /** @internal */ + int16_t getSecondary() const; + private: /** * The grouping sizes, with the following special values: @@ -1342,7 +1242,7 @@ class U_I18N_API Grouper : public UMemory { int16_t fGrouping2; /** - * The minimum gropuing size, with the following special values: + * The minimum grouping size, with the following special values: *
    *
  • -2 = needs locale data *
  • -3 = no less than 2 @@ -1350,6 +1250,12 @@ 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. + */ + UGroupingStrategy fStrategy; + Grouper() : fGrouping1(-3) {}; bool isBogus() const { @@ -1367,6 +1273,12 @@ class U_I18N_API Grouper : public UMemory { // To allow NumberFormatterImpl to access isBogus() and perform other operations: friend class NumberFormatterImpl; + + // To allow NumberParserImpl to perform setLocaleData(): + friend class ::icu::numparse::impl::NumberParserImpl; + + // To allow access to the skeleton generation code: + friend class impl::GeneratorHelpers; }; // Do not enclose entire Padder with #ifndef U_HIDE_INTERNAL_API, needed for a protected field @@ -1381,6 +1293,9 @@ class U_I18N_API Padder : public UMemory { static Padder codePoints(UChar32 cp, int32_t targetWidth, UNumberFormatPadPosition position); #endif // U_HIDE_INTERNAL_API + /** @internal */ + static Padder forProperties(const DecimalFormatProperties& properties); + private: UChar32 fWidth; // -3 = error; -2 = bogus; -1 = no padding union { @@ -1427,6 +1342,9 @@ class U_I18N_API Padder : public UMemory { // To allow NumberFormatterImpl to access isBogus() and perform other operations: friend class impl::NumberFormatterImpl; + + // To allow access to the skeleton generation code: + friend class impl::GeneratorHelpers; }; // Do not enclose entire MacroProps with #ifndef U_HIDE_INTERNAL_API, needed for a protected field @@ -1442,7 +1360,10 @@ struct U_I18N_API MacroProps : public UMemory { MeasureUnit perUnit; // = NoUnit::base(); /** @internal */ - Rounder rounder; // = Rounder(); (bogus) + Precision precision; // = Precision(); (bogus) + + /** @internal */ + UNumberFormatRoundingMode roundingMode = UNUM_ROUND_HALFEVEN; /** @internal */ Grouper grouper; // = Grouper(); (bogus) @@ -1468,20 +1389,33 @@ struct U_I18N_API MacroProps : public UMemory { UNumberDecimalSeparatorDisplay decimal = UNUM_DECIMAL_SEPARATOR_COUNT; /** @internal */ - PluralRules *rules = nullptr; // no ownership + Scale scale; // = Scale(); (benign value) + + /** @internal */ + const AffixPatternProvider* affixProvider = nullptr; // no ownership + + /** @internal */ + const PluralRules* rules = nullptr; // no ownership + + /** @internal */ + const CurrencySymbols* currencySymbols = nullptr; // no ownership /** @internal */ int32_t threshold = DEFAULT_THRESHOLD; + + /** @internal */ Locale locale; + // NOTE: Uses default copy and move constructors. + /** * Check all members for errors. * @internal */ bool copyErrorTo(UErrorCode &status) const { - return notation.copyErrorTo(status) || rounder.copyErrorTo(status) || + return notation.copyErrorTo(status) || precision.copyErrorTo(status) || padder.copyErrorTo(status) || integerWidth.copyErrorTo(status) || - symbols.copyErrorTo(status); + symbols.copyErrorTo(status) || scale.copyErrorTo(status); } }; @@ -1505,7 +1439,7 @@ class U_I18N_API NumberFormatterSettings { * *

    * All notation styles will be properly localized with locale data, and all notation styles are compatible with - * units, rounding strategies, and other number formatter settings. + * units, rounding precisions, and other number formatter settings. * *

    * Pass this method the return value of a {@link Notation} factory method. For example: @@ -1522,7 +1456,18 @@ class U_I18N_API NumberFormatterSettings { * @see Notation * @draft ICU 60 */ - Derived notation(const Notation ¬ation) const; + Derived notation(const Notation ¬ation) const &; + + /** + * Overload of notation() for use on an rvalue reference. + * + * @param notation + * The notation strategy to use. + * @return The fluent chain. + * @see #notation + * @draft ICU 62 + */ + Derived notation(const Notation ¬ation) &&; /** * Specifies the unit (unit of measure, currency, or percent) to associate with rendered numbers. @@ -1534,7 +1479,7 @@ class U_I18N_API NumberFormatterSettings { *

* * All units will be properly localized with locale data, and all units are compatible with notation styles, - * rounding strategies, and other number formatter settings. + * rounding precisions, and other number formatter settings. * * Pass this method any instance of {@link MeasureUnit}. For units of measure (which often involve the * factory methods that return a pointer): @@ -1568,7 +1513,18 @@ class U_I18N_API NumberFormatterSettings { * @see #perUnit * @draft ICU 60 */ - Derived unit(const icu::MeasureUnit &unit) const; + Derived unit(const icu::MeasureUnit &unit) const &; + + /** + * Overload of unit() for use on an rvalue reference. + * + * @param unit + * The unit to render. + * @return The fluent chain. + * @see #unit + * @draft ICU 62 + */ + Derived unit(const icu::MeasureUnit &unit) &&; /** * Like unit(), but takes ownership of a pointer. Convenient for use with the MeasureFormat factory @@ -1585,7 +1541,18 @@ class U_I18N_API NumberFormatterSettings { * @see MeasureUnit * @draft ICU 60 */ - Derived adoptUnit(icu::MeasureUnit *unit) const; + Derived adoptUnit(icu::MeasureUnit *unit) const &; + + /** + * Overload of adoptUnit() for use on an rvalue reference. + * + * @param unit + * The unit to render. + * @return The fluent chain. + * @see #adoptUnit + * @draft ICU 62 + */ + Derived adoptUnit(icu::MeasureUnit *unit) &&; /** * Sets a unit to be used in the denominator. For example, to format "3 m/s", pass METER to the unit and SECOND to @@ -1604,7 +1571,18 @@ class U_I18N_API NumberFormatterSettings { * @see #unit * @draft ICU 61 */ - Derived perUnit(const icu::MeasureUnit &perUnit) const; + Derived perUnit(const icu::MeasureUnit &perUnit) const &; + + /** + * Overload of perUnit() for use on an rvalue reference. + * + * @param perUnit + * The unit to render in the denominator. + * @return The fluent chain. + * @see #perUnit + * @draft ICU 62 + */ + Derived perUnit(const icu::MeasureUnit &perUnit) &&; /** * Like perUnit(), but takes ownership of a pointer. Convenient for use with the MeasureFormat factory @@ -1623,10 +1601,21 @@ class U_I18N_API NumberFormatterSettings { * @see MeasureUnit * @draft ICU 61 */ - Derived adoptPerUnit(icu::MeasureUnit *perUnit) const; + Derived adoptPerUnit(icu::MeasureUnit *perUnit) const &; /** - * Specifies the rounding strategy to use when formatting numbers. + * Overload of adoptPerUnit() for use on an rvalue reference. + * + * @param perUnit + * The unit to render in the denominator. + * @return The fluent chain. + * @see #adoptPerUnit + * @draft ICU 62 + */ + Derived adoptPerUnit(icu::MeasureUnit *perUnit) &&; + + /** + * Specifies the rounding precision to use when formatting numbers. * *
    *
  • Round to 3 decimal places: "3.142" @@ -1636,27 +1625,77 @@ class U_I18N_API NumberFormatterSettings { *
* *

- * Pass this method the return value of one of the factory methods on {@link Rounder}. For example: + * Pass this method the return value of one of the factory methods on {@link Precision}. For example: * *

-     * NumberFormatter::with().rounding(Rounder::fixedFraction(2))
+     * NumberFormatter::with().precision(Precision::fixedFraction(2))
      * 
* *

* In most cases, the default rounding strategy is to round to 6 fraction places; i.e., - * Rounder.maxFraction(6). The exceptions are if compact notation is being used, then the compact + * Precision.maxFraction(6). The exceptions are if compact notation is being used, then the compact * notation rounding strategy is used (see {@link Notation#compactShort} for details), or if the unit is a currency, - * then standard currency rounding is used, which varies from currency to currency (see {@link Rounder#currency} for + * then standard currency rounding is used, which varies from currency to currency (see {@link Precision#currency} for * details). * - * @param rounder - * The rounding strategy to use. + * @param precision + * The rounding precision to use. * @return The fluent chain. - * @see Rounder - * @provisional This API might change or be removed in a future release. - * @draft ICU 60 + * @see Precision + * @draft ICU 62 */ - Derived rounding(const Rounder &rounder) const; + Derived precision(const Precision& precision) const &; + + /** + * Overload of precision() for use on an rvalue reference. + * + * @param precision + * The rounding precision to use. + * @return The fluent chain. + * @see #precision + * @draft ICU 62 + */ + Derived precision(const Precision& precision) &&; + +#ifndef U_HIDE_DEPRECATED_API + // Compatibility method that will be removed in ICU 64. + // Use precision() instead. + // See http://bugs.icu-project.org/trac/ticket/13746 + /** @deprecated ICU 62 */ + Derived rounding(const Rounder& rounder) const & { + return precision(rounder); + } +#endif /* U_HIDE_DEPRECATED_API */ + + /** + * Specifies how to determine the direction to round a number when it has more digits than fit in the + * desired precision. When formatting 1.235: + * + *

    + *
  • Ceiling rounding mode with integer precision: "2" + *
  • Half-down rounding mode with 2 fixed fraction digits: "1.23" + *
  • Half-up rounding mode with 2 fixed fraction digits: "1.24" + *
+ * + * The default is HALF_EVEN. For more information on rounding mode, see the ICU userguide here: + * + * http://userguide.icu-project.org/formatparse/numbers/rounding-modes + * + * @param roundingMode The rounding mode to use. + * @return The fluent chain. + * @draft ICU 62 + */ + Derived roundingMode(UNumberFormatRoundingMode roundingMode) const &; + + /** + * Overload of roundingMode() for use on an rvalue reference. + * + * @param roundingMode The rounding mode to use. + * @return The fluent chain. + * @see #roundingMode + * @draft ICU 62 + */ + Derived roundingMode(UNumberFormatRoundingMode roundingMode) &&; /** * Specifies the grouping strategy to use when formatting numbers. @@ -1685,7 +1724,19 @@ class U_I18N_API NumberFormatterSettings { * @return The fluent chain. * @draft ICU 61 */ - Derived grouping(const UGroupingStrategy &strategy) const; + Derived grouping(UGroupingStrategy strategy) const &; + + /** + * Overload of grouping() for use on an rvalue reference. + * + * @param strategy + * 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) &&; /** * Specifies the minimum and maximum number of digits to render before the decimal mark. @@ -1711,7 +1762,18 @@ class U_I18N_API NumberFormatterSettings { * @see IntegerWidth * @draft ICU 60 */ - Derived integerWidth(const IntegerWidth &style) const; + Derived integerWidth(const IntegerWidth &style) const &; + + /** + * Overload of integerWidth() for use on an rvalue reference. + * + * @param style + * The integer width to use. + * @return The fluent chain. + * @see #integerWidth + * @draft ICU 62 + */ + Derived integerWidth(const IntegerWidth &style) &&; /** * Specifies the symbols (decimal separator, grouping separator, percent sign, numerals, etc.) to use when rendering @@ -1741,8 +1803,8 @@ class U_I18N_API NumberFormatterSettings { * after passing it into the fluent chain will not be seen. * *

- * Note: Calling this method will override the NumberingSystem previously specified in - * {@link #symbols(NumberingSystem)}. + * Note: Calling this method will override any previously specified DecimalFormatSymbols + * or NumberingSystem. * *

* The default is to choose the symbols based on the locale specified in the fluent chain. @@ -1753,7 +1815,18 @@ class U_I18N_API NumberFormatterSettings { * @see DecimalFormatSymbols * @draft ICU 60 */ - Derived symbols(const DecimalFormatSymbols &symbols) const; + Derived symbols(const DecimalFormatSymbols &symbols) const &; + + /** + * Overload of symbols() for use on an rvalue reference. + * + * @param symbols + * The DecimalFormatSymbols to use. + * @return The fluent chain. + * @see #symbols + * @draft ICU 62 + */ + Derived symbols(const DecimalFormatSymbols &symbols) &&; /** * Specifies that the given numbering system should be used when fetching symbols. @@ -1773,8 +1846,8 @@ class U_I18N_API NumberFormatterSettings { * * *

- * Note: Calling this method will override the DecimalFormatSymbols previously specified in - * {@link #symbols(DecimalFormatSymbols)}. + * Note: Calling this method will override any previously specified DecimalFormatSymbols + * or NumberingSystem. * *

* The default is to choose the best numbering system for the locale. @@ -1788,7 +1861,18 @@ class U_I18N_API NumberFormatterSettings { * @see NumberingSystem * @draft ICU 60 */ - Derived adoptSymbols(NumberingSystem *symbols) const; + Derived adoptSymbols(NumberingSystem *symbols) const &; + + /** + * Overload of adoptSymbols() for use on an rvalue reference. + * + * @param symbols + * The NumberingSystem to use. + * @return The fluent chain. + * @see #adoptSymbols + * @draft ICU 62 + */ + Derived adoptSymbols(NumberingSystem *symbols) &&; /** * Sets the width of the unit (measure unit or currency). Most common values: @@ -1815,7 +1899,18 @@ class U_I18N_API NumberFormatterSettings { * @see UNumberUnitWidth * @draft ICU 60 */ - Derived unitWidth(const UNumberUnitWidth &width) const; + Derived unitWidth(UNumberUnitWidth width) const &; + + /** + * Overload of unitWidth() for use on an rvalue reference. + * + * @param width + * The width to use when rendering numbers. + * @return The fluent chain. + * @see #unitWidth + * @draft ICU 62 + */ + Derived unitWidth(UNumberUnitWidth width) &&; /** * Sets the plus/minus sign display strategy. Most common values: @@ -1836,14 +1931,24 @@ class U_I18N_API NumberFormatterSettings { *

* The default is AUTO sign display. * - * @param width + * @param style * The sign display strategy to use when rendering numbers. * @return The fluent chain * @see UNumberSignDisplay - * @provisional This API might change or be removed in a future release. * @draft ICU 60 */ - Derived sign(const UNumberSignDisplay &width) const; + Derived sign(UNumberSignDisplay style) const &; + + /** + * Overload of sign() for use on an rvalue reference. + * + * @param style + * The sign display strategy to use when rendering numbers. + * @return The fluent chain. + * @see #sign + * @draft ICU 62 + */ + Derived sign(UNumberSignDisplay style) &&; /** * Sets the decimal separator display strategy. This affects integer numbers with no fraction part. Most common @@ -1864,23 +1969,73 @@ class U_I18N_API NumberFormatterSettings { *

* The default is AUTO decimal separator display. * - * @param width + * @param style * The decimal separator display strategy to use when rendering numbers. * @return The fluent chain * @see UNumberDecimalSeparatorDisplay - * @provisional This API might change or be removed in a future release. * @draft ICU 60 */ - Derived decimal(const UNumberDecimalSeparatorDisplay &width) const; + Derived decimal(UNumberDecimalSeparatorDisplay style) const &; + + /** + * Overload of decimal() for use on an rvalue reference. + * + * @param style + * The decimal separator display strategy to use when rendering numbers. + * @return The fluent chain. + * @see #decimal + * @draft ICU 62 + */ + Derived decimal(UNumberDecimalSeparatorDisplay style) &&; + + /** + * Sets a scale (multiplier) to be used to scale the number by an arbitrary amount before formatting. + * Most common values: + * + *

    + *
  • Multiply by 100: useful for percentages. + *
  • Multiply by an arbitrary value: useful for unit conversions. + *
+ * + *

+ * Pass an element from a {@link Scale} factory method to this setter. For example: + * + *

+     * NumberFormatter::with().scale(Scale::powerOfTen(2))
+     * 
+ * + *

+ * The default is to not apply any multiplier. + * + * @param scale + * The scale to apply when rendering numbers. + * @return The fluent chain + * @draft ICU 62 + */ + Derived scale(const Scale &scale) const &; + + /** + * Overload of scale() for use on an rvalue reference. + * + * @param scale + * The scale to apply when rendering numbers. + * @return The fluent chain. + * @see #scale + * @draft ICU 62 + */ + Derived scale(const Scale &scale) &&; #ifndef U_HIDE_INTERNAL_API /** - * Set the padding strategy. May be added to ICU 61; see #13338. + * Set the padding strategy. May be added in the future; see #13338. * * @internal ICU 60: This API is ICU internal only. */ - Derived padding(const impl::Padder &padder) const; + Derived padding(const impl::Padder &padder) const &; + + /** @internal */ + Derived padding(const impl::Padder &padder) &&; /** * Internal fluent setter to support a custom regulation threshold. A threshold of 1 causes the data structures to @@ -1888,10 +2043,45 @@ class U_I18N_API NumberFormatterSettings { * * @internal ICU 60: This API is ICU internal only. */ - Derived threshold(int32_t threshold) const; + Derived threshold(int32_t threshold) const &; + + /** @internal */ + Derived threshold(int32_t threshold) &&; + + /** + * Internal fluent setter to overwrite the entire macros object. + * + * @internal ICU 60: This API is ICU internal only. + */ + Derived macros(const impl::MacroProps& macros) const &; + + /** @internal */ + Derived macros(const impl::MacroProps& macros) &&; + + /** @internal */ + Derived macros(impl::MacroProps&& macros) const &; + + /** @internal */ + Derived macros(impl::MacroProps&& macros) &&; #endif /* U_HIDE_INTERNAL_API */ + /** + * Creates a skeleton string representation of this number formatter. A skeleton string is a + * locale-agnostic serialized form of a number formatter. + * + * Not all options are capable of being represented in the skeleton string; for example, a + * DecimalFormatSymbols object. If any such option is encountered, the error code is set to + * U_UNSUPPORTED_ERROR. + * + * The returned skeleton is in normalized form, such that two number formatters with equivalent + * behavior should produce the same skeleton. + * + * @return A number skeleton string with behavior corresponding to this number formatter. + * @draft ICU 62 + */ + UnicodeString toSkeleton(UErrorCode& status) const; + /** * Sets the UErrorCode if an error occurred in the fluent chain. * Preserves older error codes in the outErrorCode. @@ -1905,7 +2095,9 @@ class U_I18N_API NumberFormatterSettings { } fMacros.copyErrorTo(outErrorCode); return U_FAILURE(outErrorCode); - } + }; + + // NOTE: Uses default copy and move constructors. protected: impl::MacroProps fMacros; @@ -1944,21 +2136,58 @@ class U_I18N_API UnlocalizedNumberFormatter * @return The fluent chain. * @draft ICU 60 */ - LocalizedNumberFormatter locale(const icu::Locale &locale) const; + LocalizedNumberFormatter 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 62 + */ + LocalizedNumberFormatter locale(const icu::Locale &locale) &&; + + /** + * Default constructor: puts the formatter into a valid but undefined state. + * + * @draft ICU 62 + */ + UnlocalizedNumberFormatter() = default; // Make default copy constructor call the NumberFormatterSettings copy constructor. /** * Returns a copy of this UnlocalizedNumberFormatter. * @draft ICU 60 */ - UnlocalizedNumberFormatter(const UnlocalizedNumberFormatter &other) : UnlocalizedNumberFormatter( - static_cast &>(other)) {} + UnlocalizedNumberFormatter(const UnlocalizedNumberFormatter &other); + + /** + * Move constructor: + * The source UnlocalizedNumberFormatter will be left in a valid but undefined state. + * @draft ICU 62 + */ + UnlocalizedNumberFormatter(UnlocalizedNumberFormatter&& src) U_NOEXCEPT; + + /** + * Copy assignment operator. + * @draft ICU 62 + */ + UnlocalizedNumberFormatter& operator=(const UnlocalizedNumberFormatter& other); + + /** + * Move assignment operator: + * The source UnlocalizedNumberFormatter will be left in a valid but undefined state. + * @draft ICU 62 + */ + UnlocalizedNumberFormatter& operator=(UnlocalizedNumberFormatter&& src) U_NOEXCEPT; private: - UnlocalizedNumberFormatter() = default; + explicit UnlocalizedNumberFormatter(const NumberFormatterSettings& other); explicit UnlocalizedNumberFormatter( - const NumberFormatterSettings &other); + NumberFormatterSettings&& src) U_NOEXCEPT; // To give the fluent setters access to this class's constructor: friend class NumberFormatterSettings; @@ -2016,31 +2245,84 @@ class U_I18N_API LocalizedNumberFormatter * @return A FormattedNumber object; call .toString() to get the string. * @draft ICU 60 */ - FormattedNumber formatDecimal(StringPiece value, UErrorCode &status) const; + FormattedNumber formatDecimal(StringPiece value, UErrorCode& status) const; + +#ifndef U_HIDE_INTERNAL_API + + /** Internal method. + * @internal + */ + FormattedNumber formatDecimalQuantity(const impl::DecimalQuantity& dq, UErrorCode& status) const; + + /** Internal method for DecimalFormat compatibility. + * @internal + */ + void getAffixImpl(bool isPrefix, bool isNegative, UnicodeString& result, UErrorCode& status) const; + + /** + * Internal method for testing. + * @internal + */ + const impl::NumberFormatterImpl* getCompiled() const; + + /** + * Internal method for testing. + * @internal + */ + int32_t getCallCount() const; + +#endif + + /** + * Creates a representation of this LocalizedNumberFormat as an icu::Format, enabling the use + * of this number formatter with APIs that need an object of that type, such as MessageFormat. + * + * This API is not intended to be used other than for enabling API compatibility. The formatDouble, + * formatInt, and formatDecimal methods should normally be used when formatting numbers, not the Format + * object returned by this method. + * + * The caller owns the returned object and must delete it when finished. + * + * @return A Format wrapping this LocalizedNumberFormatter. + * @draft ICU 62 + */ + Format* toFormat(UErrorCode& status) const; + + /** + * Default constructor: puts the formatter into a valid but undefined state. + * + * @draft ICU 62 + */ + LocalizedNumberFormatter() = default; // Make default copy constructor call the NumberFormatterSettings copy constructor. /** * Returns a copy of this LocalizedNumberFormatter. * @draft ICU 60 */ - LocalizedNumberFormatter(const LocalizedNumberFormatter &other) : LocalizedNumberFormatter( - static_cast &>(other)) {} + LocalizedNumberFormatter(const LocalizedNumberFormatter &other); /** - * Destruct this LocalizedNumberFormatter, cleaning up any memory it might own. - * @draft ICU 60 + * Move constructor: + * The source LocalizedNumberFormatter will be left in a valid but undefined state. + * @draft ICU 62 */ - ~LocalizedNumberFormatter(); + LocalizedNumberFormatter(LocalizedNumberFormatter&& src) U_NOEXCEPT; - private: - const impl::NumberFormatterImpl* fCompiled {nullptr}; - char fUnsafeCallCount[8] {}; // internally cast to u_atomic_int32_t + /** + * Copy assignment operator. + * @draft ICU 62 + */ + LocalizedNumberFormatter& operator=(const LocalizedNumberFormatter& other); - LocalizedNumberFormatter() = default; + /** + * Move assignment operator: + * The source LocalizedNumberFormatter will be left in a valid but undefined state. + * @draft ICU 62 + */ + LocalizedNumberFormatter& operator=(LocalizedNumberFormatter&& src) U_NOEXCEPT; - explicit LocalizedNumberFormatter(const NumberFormatterSettings &other); - - LocalizedNumberFormatter(const impl::MacroProps ¯os, const Locale &locale); +#ifndef U_HIDE_INTERNAL_API /** * This is the core entrypoint to the number formatting pipeline. It performs self-regulation: a static code path @@ -2050,10 +2332,39 @@ class U_I18N_API LocalizedNumberFormatter * This function is very hot, being called in every call to the number formatting pipeline. * * @param results - * The results object. This method takes ownership. - * @return The formatted number result. + * The results object. This method will mutate it to save the results. + * @internal */ - FormattedNumber formatImpl(impl::NumberFormatterResults *results, UErrorCode &status) const; + void formatImpl(impl::UFormattedNumberData *results, UErrorCode &status) const; + +#endif + + /** + * Destruct this LocalizedNumberFormatter, cleaning up any memory it might own. + * @draft ICU 60 + */ + ~LocalizedNumberFormatter(); + + private: + // Note: fCompiled can't be a LocalPointer because impl::NumberFormatterImpl is defined in an internal + // header, and LocalPointer needs the full class definition in order to delete the instance. + const impl::NumberFormatterImpl* fCompiled {nullptr}; + char fUnsafeCallCount[8] {}; // internally cast to u_atomic_int32_t + + explicit LocalizedNumberFormatter(const NumberFormatterSettings& other); + + explicit LocalizedNumberFormatter(NumberFormatterSettings&& src) U_NOEXCEPT; + + LocalizedNumberFormatter(const impl::MacroProps ¯os, const Locale &locale); + + LocalizedNumberFormatter(impl::MacroProps &¯os, const Locale &locale); + + void lnfMoveHelper(LocalizedNumberFormatter&& src); + + /** + * @return true if the compiled formatter is available. + */ + bool computeCompiled(UErrorCode& status) const; // To give the fluent setters access to this class's constructor: friend class NumberFormatterSettings; @@ -2071,25 +2382,57 @@ class U_I18N_API LocalizedNumberFormatter */ class U_I18N_API FormattedNumber : public UMemory { public: +#ifndef U_HIDE_DEPRECATED_API /** * Returns a UnicodeString representation of the formatted number. * * @return a UnicodeString containing the localized number. - * @draft ICU 60 + * @deprecated ICU 62 Use the version of this method with an error code instead. + * This method was never @stable and will be removed in a future release. + * See http://bugs.icu-project.org/trac/ticket/13746 */ UnicodeString toString() const; +#endif /* U_HIDE_DEPRECATED_API */ + /** + * Returns a UnicodeString representation of the formatted number. + * + * @param status + * Set if an error occurs while formatting the number to the UnicodeString. + * @return a UnicodeString containing the localized number. + * @draft ICU 62 + */ + UnicodeString toString(UErrorCode& status) const; + +#ifndef U_HIDE_DEPRECATED_API /** * Appends the formatted number to an Appendable. * * @param appendable * The Appendable to which to append the formatted number string. * @return The same Appendable, for chaining. - * @draft ICU 60 + * @deprecated ICU 62 Use the version of this method with an error code instead. + * This method was never @stable and will be removed in a future release. + * See http://bugs.icu-project.org/trac/ticket/13746 * @see Appendable */ Appendable &appendTo(Appendable &appendable); +#endif /* U_HIDE_DEPRECATED_API */ + /** + * Appends the formatted number to an Appendable. + * + * @param appendable + * The Appendable to which to append the formatted number string. + * @param status + * Set if an error occurs while formatting the number to the Appendable. + * @return The same Appendable, for chaining. + * @draft ICU 62 + * @see Appendable + */ + Appendable &appendTo(Appendable &appendable, UErrorCode& status); + +#ifndef U_HIDE_DEPRECATED_API /** * Determine the start and end indices of the first occurrence of the given field in the output string. * This allows you to determine the locations of the integer part, fraction part, and sign. @@ -2106,11 +2449,47 @@ class U_I18N_API FormattedNumber : public UMemory { * The FieldPosition to populate with the start and end indices of the desired field. * @param status * Set if an error occurs while populating the FieldPosition. - * @draft ICU 60 + * @deprecated ICU 62 Use {@link #nextFieldPosition} instead. This method will be removed in a future + * release. See http://bugs.icu-project.org/trac/ticket/13746 * @see UNumberFormatFields */ void populateFieldPosition(FieldPosition &fieldPosition, UErrorCode &status); +#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. + * + * 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_GROUPING_SEPARATOR_FIELD);
+     * while (formattedNumber.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. 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 + * 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 + * Set if an error occurs while populating the FieldPosition. + * @return TRUE if a new occurrence of the field was found; FALSE otherwise. + * @draft ICU 62 + * @see UNumberFormatFields + */ + UBool nextFieldPosition(FieldPosition& fieldPosition, UErrorCode& status) const; + +#ifndef U_HIDE_DEPRECATED_API /** * Export the formatted number 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. @@ -2122,10 +2501,67 @@ class U_I18N_API FormattedNumber : public UMemory { * 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 60 + * @deprecated ICU 62 Use {@link #getAllFieldPositions} instead. This method will be removed in a + * future release. See http://bugs.icu-project.org/trac/ticket/13746 * @see UNumberFormatFields */ void populateFieldPositionIterator(FieldPositionIterator &iterator, UErrorCode &status); +#endif /* U_HIDE_DEPRECATED_API */ + + /** + * Export the formatted number 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 62 + * @see UNumberFormatFields + */ + void getAllFieldPositions(FieldPositionIterator &iterator, UErrorCode &status) const; + +#ifndef U_HIDE_INTERNAL_API + + /** + * Gets the raw DecimalQuantity for plural rule selection. + * @internal + */ + void getDecimalQuantity(impl::DecimalQuantity& output, UErrorCode& status) const; + + /** + * Populates the mutable builder type FieldPositionIteratorHandler. + * @internal + */ + void getAllFieldPositionsImpl(FieldPositionIteratorHandler& fpih, UErrorCode& status) const; + +#endif + + /** + * Copying not supported; use move constructor instead. + */ + FormattedNumber(const FormattedNumber&) = delete; + + /** + * Copying not supported; use move assignment instead. + */ + FormattedNumber& operator=(const FormattedNumber&) = delete; + + /** + * Move constructor: + * Leaves the source FormattedNumber in an undefined state. + * @draft ICU 62 + */ + FormattedNumber(FormattedNumber&& src) U_NOEXCEPT; + + /** + * Move assignment: + * Leaves the source FormattedNumber in an undefined state. + * @draft ICU 62 + */ + FormattedNumber& operator=(FormattedNumber&& src) U_NOEXCEPT; /** * Destruct an instance of FormattedNumber, cleaning up any memory it might own. @@ -2134,13 +2570,17 @@ class U_I18N_API FormattedNumber : public UMemory { ~FormattedNumber(); private: - // Can't use LocalPointer because NumberFormatterResults is forward-declared - const impl::NumberFormatterResults *fResults; + // Can't use LocalPointer because UFormattedNumberData is forward-declared + const impl::UFormattedNumberData *fResults; // Error code for the terminal methods UErrorCode fErrorCode; - explicit FormattedNumber(impl::NumberFormatterResults *results) + /** + * Internal constructor from data type. Adopts the data pointer. + * @internal + */ + explicit FormattedNumber(impl::UFormattedNumberData *results) : fResults(results), fErrorCode(U_ZERO_ERROR) {}; explicit FormattedNumber(UErrorCode errorCode) @@ -2177,9 +2617,21 @@ class U_I18N_API NumberFormatter final { */ static LocalizedNumberFormatter withLocale(const Locale &locale); + /** + * Call this method at the beginning of a NumberFormatter fluent chain to create an instance based + * on a given number skeleton string. + * + * @param skeleton + * The skeleton string off of which to base this NumberFormatter. + * @param status + * Set to U_NUMBER_SKELETON_SYNTAX_ERROR if the skeleton was invalid. + * @return An UnlocalizedNumberFormatter, to be used for chaining. + * @draft ICU 62 + */ + static UnlocalizedNumberFormatter forSkeleton(const UnicodeString& skeleton, UErrorCode& status); + /** * Use factory methods instead of the constructor to create a NumberFormatter. - * @draft ICU 60 */ NumberFormatter() = delete; }; diff --git a/deps/icu-small/source/i18n/unicode/numfmt.h b/deps/icu-small/source/i18n/unicode/numfmt.h index 1332f525662..572e6afc71b 100644 --- a/deps/icu-small/source/i18n/unicode/numfmt.h +++ b/deps/icu-small/source/i18n/unicode/numfmt.h @@ -555,16 +555,18 @@ public: UnicodeString& appendTo, FieldPositionIterator* posIter, UErrorCode& status) const; -public: + +// Can't use #ifndef U_HIDE_INTERNAL_API because these are virtual methods + /** * Format a decimal number. - * The number is a DigitList wrapper onto a floating point decimal number. + * The number is a DecimalQuantity wrapper onto a floating point decimal number. * The default implementation in NumberFormat converts the decimal number * to a double and formats that. Subclasses of NumberFormat that want * to specifically handle big decimal numbers must override this method. * class DecimalFormat does so. * - * @param number The number, a DigitList format Decimal Floating Point. + * @param number The number, a DecimalQuantity format Decimal Floating Point. * @param appendTo Output parameter to receive result. * Result is appended to existing contents. * @param posIter On return, can be used to iterate over positions @@ -573,20 +575,20 @@ public: * @return Reference to 'appendTo' parameter. * @internal */ - virtual UnicodeString& format(const DigitList &number, + virtual UnicodeString& format(const number::impl::DecimalQuantity &number, UnicodeString& appendTo, FieldPositionIterator* posIter, UErrorCode& status) const; /** * Format a decimal number. - * The number is a DigitList wrapper onto a floating point decimal number. + * The number is a DecimalQuantity wrapper onto a floating point decimal number. * The default implementation in NumberFormat converts the decimal number * to a double and formats that. Subclasses of NumberFormat that want * to specifically handle big decimal numbers must override this method. * class DecimalFormat does so. * - * @param number The number, a DigitList format Decimal Floating Point. + * @param number The number, a DecimalQuantity format Decimal Floating Point. * @param appendTo Output parameter to receive result. * Result is appended to existing contents. * @param pos On input: an alignment field, if desired. @@ -595,13 +597,11 @@ public: * @return Reference to 'appendTo' parameter. * @internal */ - virtual UnicodeString& format(const DigitList &number, + virtual UnicodeString& format(const number::impl::DecimalQuantity &number, UnicodeString& appendTo, FieldPosition& pos, UErrorCode& status) const; -public: - /** * Return a long if possible (e.g. within range LONG_MAX, * LONG_MAX], and with no decimals), otherwise a double. If diff --git a/deps/icu-small/source/i18n/unicode/plurrule.h b/deps/icu-small/source/i18n/unicode/plurrule.h index d372d79c845..03dea3f1b92 100644 --- a/deps/icu-small/source/i18n/unicode/plurrule.h +++ b/deps/icu-small/source/i18n/unicode/plurrule.h @@ -44,7 +44,6 @@ U_NAMESPACE_BEGIN class Hashtable; class IFixedDecimal; -class VisibleDigitsWithExponent; class RuleChain; class PluralRuleParser; class PluralKeywordEnumeration; @@ -348,30 +347,10 @@ public: UnicodeString select(double number) const; #ifndef U_HIDE_INTERNAL_API - /** - * Given a number and a format, returns the keyword of the first applicable - * rule for this PluralRules object. - * Note: This internal preview interface may be removed in the future if - * an architecturally cleaner solution reaches stable status. - * @param obj The numeric object for which the rule should be determined. - * @param fmt The NumberFormat specifying how the number will be formatted - * (this can affect the plural form, e.g. "1 dollar" vs "1.0 dollars"). - * @param status Input/output parameter. If at entry this indicates a - * failure status, the method returns immediately; otherwise - * this is set to indicate the outcome of the call. - * @return The keyword of the selected rule. Undefined in the case of an error. - * @internal ICU 59 technology preview, may be removed in the future - */ - UnicodeString select(const Formattable& obj, const NumberFormat& fmt, UErrorCode& status) const; - /** * @internal */ UnicodeString select(const IFixedDecimal &number) const; - /** - * @internal - */ - UnicodeString select(const VisibleDigitsWithExponent &number) const; #endif /* U_HIDE_INTERNAL_API */ /** diff --git a/deps/icu-small/source/i18n/unicode/rbnf.h b/deps/icu-small/source/i18n/unicode/rbnf.h index d8d33420c2a..2d284909f8a 100644 --- a/deps/icu-small/source/i18n/unicode/rbnf.h +++ b/deps/icu-small/source/i18n/unicode/rbnf.h @@ -884,7 +884,7 @@ protected: * @return Reference to 'appendTo' parameter. * @internal */ - virtual UnicodeString& format(const DigitList &number, + virtual UnicodeString& format(const number::impl::DecimalQuantity &number, UnicodeString& appendTo, FieldPositionIterator* posIter, UErrorCode& status) const; @@ -906,7 +906,7 @@ protected: * @return Reference to 'appendTo' parameter. * @internal */ - virtual UnicodeString& format(const DigitList &number, + virtual UnicodeString& format(const number::impl::DecimalQuantity &number, UnicodeString& appendTo, FieldPosition& pos, UErrorCode& status) const; diff --git a/deps/icu-small/source/i18n/unicode/scientificnumberformatter.h b/deps/icu-small/source/i18n/unicode/scientificnumberformatter.h index 30edee7ecce..6c99a246625 100644 --- a/deps/icu-small/source/i18n/unicode/scientificnumberformatter.h +++ b/deps/icu-small/source/i18n/unicode/scientificnumberformatter.h @@ -24,7 +24,6 @@ U_NAMESPACE_BEGIN class FieldPositionIterator; -class DecimalFormatStaticSets; class DecimalFormatSymbols; class DecimalFormat; class Formattable; @@ -150,7 +149,6 @@ public: const UnicodeString &original, FieldPositionIterator &fpi, const UnicodeString &preExponent, - const DecimalFormatStaticSets &decimalFormatSets, UnicodeString &appendTo, UErrorCode &status) const = 0; private: @@ -165,7 +163,6 @@ public: const UnicodeString &original, FieldPositionIterator &fpi, const UnicodeString &preExponent, - const DecimalFormatStaticSets &decimalFormatSets, UnicodeString &appendTo, UErrorCode &status) const; }; @@ -184,7 +181,6 @@ public: const UnicodeString &original, FieldPositionIterator &fpi, const UnicodeString &preExponent, - const DecimalFormatStaticSets &decimalFormatSets, UnicodeString &appendTo, UErrorCode &status) const; private: @@ -211,7 +207,6 @@ public: UnicodeString fPreExponent; DecimalFormat *fDecimalFormat; Style *fStyle; - const DecimalFormatStaticSets *fStaticSets; }; diff --git a/deps/icu-small/source/i18n/unicode/smpdtfmt.h b/deps/icu-small/source/i18n/unicode/smpdtfmt.h index 9801b29bdb7..305412b8d15 100644 --- a/deps/icu-small/source/i18n/unicode/smpdtfmt.h +++ b/deps/icu-small/source/i18n/unicode/smpdtfmt.h @@ -50,6 +50,10 @@ class TimeZoneFormat; class SharedNumberFormat; class SimpleDateFormatMutableNFs; +namespace number { +class LocalizedNumberFormatter; +} + /** * * SimpleDateFormat is a concrete class for formatting and parsing dates in a @@ -1268,7 +1272,6 @@ private: int32_t fieldNum, FieldPositionHandler& handler, Calendar& cal, - SimpleDateFormatMutableNFs &mutableNFs, UErrorCode& status) const; // in case of illegal argument /** @@ -1284,7 +1287,7 @@ private: * @param minDigits Minimum number of digits the result should have * @param maxDigits Maximum number of digits the result should have */ - void zeroPaddingNumber(NumberFormat *currentNumberFormat, + void zeroPaddingNumber(const NumberFormat *currentNumberFormat, UnicodeString &appendTo, int32_t value, int32_t minDigits, @@ -1414,21 +1417,21 @@ private: */ int32_t subParse(const UnicodeString& text, int32_t& start, char16_t ch, int32_t count, UBool obeyCount, UBool allowNegative, UBool ambiguousYear[], int32_t& saveHebrewMonth, Calendar& cal, - int32_t patLoc, MessageFormat * numericLeapMonthFormatter, UTimeZoneFormatTimeType *tzTimeType, SimpleDateFormatMutableNFs &mutableNFs, + int32_t patLoc, MessageFormat * numericLeapMonthFormatter, UTimeZoneFormatTimeType *tzTimeType, int32_t *dayPeriod=NULL) const; void parseInt(const UnicodeString& text, Formattable& number, ParsePosition& pos, UBool allowNegative, - NumberFormat *fmt) const; + const NumberFormat *fmt) const; void parseInt(const UnicodeString& text, Formattable& number, int32_t maxDigits, ParsePosition& pos, UBool allowNegative, - NumberFormat *fmt) const; + const NumberFormat *fmt) const; int32_t checkIntSuffix(const UnicodeString& text, int32_t start, int32_t patLoc, UBool isNegative) const; @@ -1495,6 +1498,16 @@ private: */ int32_t skipUWhiteSpace(const UnicodeString& text, int32_t pos) const; + /** + * Initialize LocalizedNumberFormatter instances used for speedup. + */ + void initFastNumberFormatters(UErrorCode& status); + + /** + * Delete the LocalizedNumberFormatter instances used for speedup. + */ + void freeFastNumberFormatters(); + /** * Initialize NumberFormat instances used for numbering system overrides. */ @@ -1518,7 +1531,7 @@ private: /** * Lazy TimeZoneFormat instantiation, semantically const */ - TimeZoneFormat *tzFormat() const; + TimeZoneFormat *tzFormat(UErrorCode &status) const; const NumberFormat* getNumberFormatByIndex(UDateFormatField index) const; @@ -1611,6 +1624,20 @@ private: */ const SharedNumberFormat **fSharedNumberFormatters; + enum NumberFormatterKey { + SMPDTFMT_NF_1x10, + SMPDTFMT_NF_2x10, + SMPDTFMT_NF_3x10, + SMPDTFMT_NF_4x10, + SMPDTFMT_NF_2x2, + SMPDTFMT_NF_COUNT + }; + + /** + * Number formatters pre-allocated for fast performance on the most common integer lengths. + */ + const number::LocalizedNumberFormatter* fFastNumberFormatters[SMPDTFMT_NF_COUNT] = {}; + UBool fHaveDefaultCentury; BreakIterator* fCapitalizationBrkIter; diff --git a/deps/icu-small/source/i18n/unicode/timezone.h b/deps/icu-small/source/i18n/unicode/timezone.h index d4cd7cb36d3..bbbb6b958e4 100644 --- a/deps/icu-small/source/i18n/unicode/timezone.h +++ b/deps/icu-small/source/i18n/unicode/timezone.h @@ -284,6 +284,8 @@ public: * and may return a different TimeZone from the one returned by * TimeZone::createDefault(). * + *

This function is not thread safe.

+ * * @return A new instance of TimeZone detected from the current host system * configuration. * @stable ICU 55 diff --git a/deps/icu-small/source/i18n/unicode/unum.h b/deps/icu-small/source/i18n/unicode/unum.h index 0e7b9fffbab..8b76014b168 100644 --- a/deps/icu-small/source/i18n/unicode/unum.h +++ b/deps/icu-small/source/i18n/unicode/unum.h @@ -29,12 +29,13 @@ /** * \file - * \brief C API: NumberFormat + * \brief C API: Compatibility APIs for number formatting. * *

Number Format C API

* - *

IMPORTANT: New users with C++ capabilities are - * strongly encouraged to see if numberformatter.h fits their use case. + *

IMPORTANT: New users with are strongly encouraged to + * see if unumberformatter.h fits their use case. Although not deprecated, + * this header is provided for backwards compatibility only. * * Number Format C API Provides functions for * formatting and parsing a number. Also provides methods for @@ -399,6 +400,10 @@ typedef enum UNumberFormatFields { * number format is opened using the given pattern, which must conform * to the syntax described in DecimalFormat or RuleBasedNumberFormat, * respectively. + * + *

NOTE:: New users with are strongly encouraged to + * use unumf_openWithSkeletonAndLocale instead of unum_open. + * * @param pattern A pattern specifying the format to use. * This parameter is ignored unless the style is * UNUM_PATTERN_DECIMAL or UNUM_PATTERN_RULEBASED. @@ -1013,6 +1018,8 @@ typedef enum UNumberFormatAttribute { *

Example: setting the scale to 3, 123 formats as "123,000" *

Example: setting the scale to -4, 123 formats as "0.0123" * + * This setting is analogous to getMultiplierScale() and setMultiplierScale() in decimfmt.h. + * * @stable ICU 51 */ UNUM_SCALE = 21, #ifndef U_HIDE_INTERNAL_API @@ -1052,7 +1059,7 @@ typedef enum UNumberFormatAttribute { * Default: 0 (unset) * @stable ICU 50 */ - UNUM_PARSE_NO_EXPONENT, + UNUM_PARSE_NO_EXPONENT = 0x1001, /** * if this attribute is set to 1, specifies that, if the pattern contains a @@ -1067,7 +1074,21 @@ typedef enum UNumberFormatAttribute { /* The following cannot be #ifndef U_HIDE_INTERNAL_API, needed in .h file variable declararions */ /** Limit of boolean attributes. * @internal */ - UNUM_LIMIT_BOOLEAN_ATTRIBUTE = 0x1003 + UNUM_LIMIT_BOOLEAN_ATTRIBUTE = 0x1003, + + /** + * Whether parsing is sensitive to case (lowercase/uppercase). + * TODO: Add to the test suite. + * @internal This API is a technical preview. It may change in an upcoming release. + */ + UNUM_PARSE_CASE_SENSITIVE = 0x1004, + + /** + * Formatting: whether to show the plus sign on non-negative numbers. + * TODO: Add to the test suite. + * @internal This API is a technical preview. It may change in an upcoming release. + */ + UNUM_SIGN_ALWAYS_SHOWN = 0x1005, } UNumberFormatAttribute; /** diff --git a/deps/icu-small/source/i18n/unicode/unumberformatter.h b/deps/icu-small/source/i18n/unicode/unumberformatter.h new file mode 100644 index 00000000000..b37f80c503a --- /dev/null +++ b/deps/icu-small/source/i18n/unicode/unumberformatter.h @@ -0,0 +1,666 @@ +// © 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 __UNUMBERFORMATTER_H__ +#define __UNUMBERFORMATTER_H__ + +#include "unicode/ufieldpositer.h" +#include "unicode/umisc.h" + + +/** + * \file + * \brief C-compatible API for localized number formatting; not recommended for C++. + * + * This is the C-compatible version of the NumberFormatter API introduced in ICU 60. C++ users should + * include unicode/numberformatter.h and use the proper C++ APIs. + * + * The C API accepts a number skeleton string for specifying the settings for formatting, which covers a + * very large subset of all possible number formatting features. For more information on number skeleton + * strings, see unicode/numberformatter.h. + * + * When using UNumberFormatter, which is treated as immutable, the results are exported to a mutable + * UFormattedNumber object, which you subsequently use for populating your string buffer or iterating over + * the fields. + * + * Example code: + *

+ * // Setup:
+ * UErrorCode ec = U_ZERO_ERROR;
+ * UNumberFormatter* uformatter = unumf_openForSkeletonAndLocale(u"precision-integer", -1, "en", &ec);
+ * UFormattedNumber* uresult = unumf_openResult(&ec);
+ * if (U_FAILURE(ec)) { return; }
+ *
+ * // Format a double:
+ * unumf_formatDouble(uformatter, 5142.3, uresult, &ec);
+ * if (U_FAILURE(ec)) { return; }
+ *
+ * // Export the string to a malloc'd buffer:
+ * int32_t len = unumf_resultToString(uresult, NULL, 0, &ec);
+ * // at this point, ec == U_BUFFER_OVERFLOW_ERROR
+ * ec = U_ZERO_ERROR;
+ * UChar* buffer = (UChar*) malloc((len+1)*sizeof(UChar));
+ * unumf_resultToString(uresult, buffer, len+1, &ec);
+ * if (U_FAILURE(ec)) { return; }
+ * // buffer should equal "5,142"
+ *
+ * // Cleanup:
+ * unumf_close(uformatter);
+ * unumf_closeResult(uresult);
+ * free(buffer);
+ * 
+ * + * If you are a C++ user linking against the C libraries, you can use the LocalPointer versions of these + * APIs. The following example uses LocalPointer with the decimal number and field position APIs: + * + *
+ * // Setup:
+ * LocalUNumberFormatterPointer uformatter(unumf_openForSkeletonAndLocale(u"percent", -1, "en", &ec));
+ * LocalUFormattedNumberPointer uresult(unumf_openResult(&ec));
+ * if (U_FAILURE(ec)) { return; }
+ *
+ * // Format a decimal number:
+ * unumf_formatDecimal(uformatter.getAlias(), "9.87E-3", -1, uresult.getAlias(), &ec);
+ * if (U_FAILURE(ec)) { return; }
+ *
+ * // Get the location of the percent sign:
+ * UFieldPosition ufpos = {UNUM_PERCENT_FIELD, 0, 0};
+ * unumf_resultNextFieldPosition(uresult.getAlias(), &ufpos, &ec);
+ * // ufpos should contain beginIndex=7 and endIndex=8 since the string is "0.00987%"
+ *
+ * // No need to do any cleanup since we are using LocalPointer.
+ * 
+ */ + + +#ifndef U_HIDE_DRAFT_API +/** + * An enum declaring how to render units, including currencies. Example outputs when formatting 123 USD and 123 + * meters in en-CA: + * + *

+ *

    + *
  • NARROW*: "$123.00" and "123 m" + *
  • SHORT: "US$ 123.00" and "123 m" + *
  • FULL_NAME: "123.00 US dollars" and "123 meters" + *
  • ISO_CODE: "USD 123.00" and undefined behavior + *
  • HIDDEN: "123.00" and "123" + *
+ * + *

+ * This enum is similar to {@link com.ibm.icu.text.MeasureFormat.FormatWidth}. + * + * @draft ICU 60 + */ +typedef enum UNumberUnitWidth { + /** + * Print an abbreviated version of the unit name. Similar to SHORT, but always use the shortest available + * abbreviation or symbol. This option can be used when the context hints at the identity of the unit. For more + * information on the difference between NARROW and SHORT, see SHORT. + * + *

+ * In CLDR, this option corresponds to the "Narrow" format for measure units and the "¤¤¤¤¤" placeholder for + * currencies. + * + * @draft ICU 60 + */ + UNUM_UNIT_WIDTH_NARROW, + + /** + * Print an abbreviated version of the unit name. Similar to NARROW, but use a slightly wider abbreviation or + * symbol when there may be ambiguity. This is the default behavior. + * + *

+ * For example, in es-US, the SHORT form for Fahrenheit is "{0} °F", but the NARROW form is "{0}°", + * since Fahrenheit is the customary unit for temperature in that locale. + * + *

+ * In CLDR, this option corresponds to the "Short" format for measure units and the "¤" placeholder for + * currencies. + * + * @draft ICU 60 + */ + UNUM_UNIT_WIDTH_SHORT, + + /** + * Print the full name of the unit, without any abbreviations. + * + *

+ * In CLDR, this option corresponds to the default format for measure units and the "¤¤¤" placeholder for + * currencies. + * + * @draft ICU 60 + */ + UNUM_UNIT_WIDTH_FULL_NAME, + + /** + * Use the three-digit ISO XXX code in place of the symbol for displaying currencies. The behavior of this + * option is currently undefined for use with measure units. + * + *

+ * In CLDR, this option corresponds to the "¤¤" placeholder for currencies. + * + * @draft ICU 60 + */ + UNUM_UNIT_WIDTH_ISO_CODE, + + /** + * Format the number according to the specified unit, but do not display the unit. For currencies, apply + * monetary symbols and formats as with SHORT, but omit the currency symbol. For measure units, the behavior is + * equivalent to not specifying the unit at all. + * + * @draft ICU 60 + */ + UNUM_UNIT_WIDTH_HIDDEN, + + /** + * One more than the highest UNumberUnitWidth value. + * + * @internal ICU 60: The numeric value may change over time; see ICU ticket #12420. + */ + UNUM_UNIT_WIDTH_COUNT +} UNumberUnitWidth; +#endif /* U_HIDE_DRAFT_API */ + +#ifndef U_HIDE_DRAFT_API +/** + * An enum declaring the strategy for when and how to display grouping separators (i.e., the + * separator, often a comma or period, after every 2-3 powers of ten). The choices are several + * pre-built strategies for different use cases that employ locale data whenever possible. Example + * outputs for 1234 and 1234567 in en-IN: + * + *

    + *
  • OFF: 1234 and 12345 + *
  • MIN2: 1234 and 12,34,567 + *
  • AUTO: 1,234 and 12,34,567 + *
  • ON_ALIGNED: 1,234 and 12,34,567 + *
  • THOUSANDS: 1,234 and 1,234,567 + *
+ * + *

+ * The default is AUTO, which displays grouping separators unless the locale data says that grouping + * is not customary. To force grouping for all numbers greater than 1000 consistently across locales, + * use ON_ALIGNED. On the other hand, to display grouping less frequently than the default, use MIN2 + * or OFF. See the docs of each option for details. + * + *

+ * 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. + */ +typedef enum UGroupingStrategy { + /** + * Do not display grouping separators in any locale. + * + * @draft ICU 61 + */ + UNUM_GROUPING_OFF, + + /** + * Display grouping using locale defaults, except do not show grouping on values smaller than + * 10000 (such that there is a minimum of two digits before the first separator). + * + *

+ * Note that locales may restrict grouping separators to be displayed only on 1 million or + * greater (for example, ee and hu) or disable grouping altogether (for example, bg currency). + * + *

+ * Locale data is used to determine whether to separate larger numbers into groups of 2 + * (customary in South Asia) or groups of 3 (customary in Europe and the Americas). + * + * @draft ICU 61 + */ + UNUM_GROUPING_MIN2, + + /** + * Display grouping using the default strategy for all locales. This is the default behavior. + * + *

+ * Note that locales may restrict grouping separators to be displayed only on 1 million or + * greater (for example, ee and hu) or disable grouping altogether (for example, bg currency). + * + *

+ * Locale data is used to determine whether to separate larger numbers into groups of 2 + * (customary in South Asia) or groups of 3 (customary in Europe and the Americas). + * + * @draft ICU 61 + */ + UNUM_GROUPING_AUTO, + + /** + * Always display the grouping separator on values of at least 1000. + * + *

+ * This option ignores the locale data that restricts or disables grouping, described in MIN2 and + * AUTO. This option may be useful to normalize the alignment of numbers, such as in a + * spreadsheet. + * + *

+ * Locale data is used to determine whether to separate larger numbers into groups of 2 + * (customary in South Asia) or groups of 3 (customary in Europe and the Americas). + * + * @draft ICU 61 + */ + UNUM_GROUPING_ON_ALIGNED, + + /** + * Use the Western defaults: groups of 3 and enabled for all numbers 1000 or greater. Do not use + * locale data for determining the grouping strategy. + * + * @draft ICU 61 + */ + UNUM_GROUPING_THOUSANDS, + + /** + * One more than the highest UGroupingStrategy value. + * + * @internal ICU 62: The numeric value may change over time; see ICU ticket #12420. + */ + UNUM_GROUPING_COUNT + +} UGroupingStrategy; +#endif /* U_HIDE_DRAFT_API */ + +#ifndef U_HIDE_DRAFT_API +/** + * An enum declaring how to denote positive and negative numbers. Example outputs when formatting + * 123, 0, and -123 in en-US: + * + *

    + *
  • AUTO: "123", "0", and "-123" + *
  • ALWAYS: "+123", "+0", and "-123" + *
  • NEVER: "123", "0", and "123" + *
  • ACCOUNTING: "$123", "$0", and "($123)" + *
  • ACCOUNTING_ALWAYS: "+$123", "+$0", and "($123)" + *
  • EXCEPT_ZERO: "+123", "0", and "-123" + *
  • ACCOUNTING_EXCEPT_ZERO: "+$123", "$0", and "($123)" + *
+ * + *

+ * The exact format, including the position and the code point of the sign, differ by locale. + * + * @draft ICU 60 + */ +typedef enum UNumberSignDisplay { + /** + * Show the minus sign on negative numbers, and do not show the sign on positive numbers. This is the default + * behavior. + * + * @draft ICU 60 + */ + UNUM_SIGN_AUTO, + + /** + * Show the minus sign on negative numbers and the plus sign on positive numbers, including zero. + * To hide the sign on zero, see {@link UNUM_SIGN_EXCEPT_ZERO}. + * + * @draft ICU 60 + */ + UNUM_SIGN_ALWAYS, + + /** + * Do not show the sign on positive or negative numbers. + * + * @draft ICU 60 + */ + UNUM_SIGN_NEVER, + + /** + * Use the locale-dependent accounting format on negative numbers, and do not show the sign on positive numbers. + * + *

+ * The accounting format is defined in CLDR and varies by locale; in many Western locales, the format is a pair + * of parentheses around the number. + * + *

+ * Note: Since CLDR defines the accounting format in the monetary context only, this option falls back to the + * AUTO sign display strategy when formatting without a currency unit. This limitation may be lifted in the + * future. + * + * @draft ICU 60 + */ + UNUM_SIGN_ACCOUNTING, + + /** + * Use the locale-dependent accounting format on negative numbers, and show the plus sign on + * positive numbers, including zero. For more information on the accounting format, see the + * ACCOUNTING sign display strategy. To hide the sign on zero, see + * {@link UNUM_SIGN_ACCOUNTING_EXCEPT_ZERO}. + * + * @draft ICU 60 + */ + UNUM_SIGN_ACCOUNTING_ALWAYS, + + /** + * Show the minus sign on negative numbers and the plus sign on positive numbers. Do not show a + * sign on zero. + * + * @draft ICU 61 + */ + UNUM_SIGN_EXCEPT_ZERO, + + /** + * Use the locale-dependent accounting format on negative numbers, and show the plus sign on + * positive numbers. Do not show a sign on zero. For more information on the accounting format, + * see the ACCOUNTING sign display strategy. + * + * @draft ICU 61 + */ + UNUM_SIGN_ACCOUNTING_EXCEPT_ZERO, + + /** + * One more than the highest UNumberSignDisplay value. + * + * @internal ICU 60: The numeric value may change over time; see ICU ticket #12420. + */ + UNUM_SIGN_COUNT +} UNumberSignDisplay; +#endif /* U_HIDE_DRAFT_API */ + +#ifndef U_HIDE_DRAFT_API +/** + * An enum declaring how to render the decimal separator. + * + *

+ *

    + *
  • UNUM_DECIMAL_SEPARATOR_AUTO: "1", "1.1" + *
  • UNUM_DECIMAL_SEPARATOR_ALWAYS: "1.", "1.1" + *
+ */ +typedef enum UNumberDecimalSeparatorDisplay { + /** + * Show the decimal separator when there are one or more digits to display after the separator, and do not show + * it otherwise. This is the default behavior. + * + * @draft ICU 60 + */ + UNUM_DECIMAL_SEPARATOR_AUTO, + + /** + * Always show the decimal separator, even if there are no digits to display after the separator. + * + * @draft ICU 60 + */ + UNUM_DECIMAL_SEPARATOR_ALWAYS, + + /** + * One more than the highest UNumberDecimalSeparatorDisplay value. + * + * @internal ICU 60: The numeric value may change over time; see ICU ticket #12420. + */ + UNUM_DECIMAL_SEPARATOR_COUNT +} UNumberDecimalSeparatorDisplay; +#endif /* U_HIDE_DRAFT_API */ + +#ifndef U_HIDE_DRAFT_API +/** + * C-compatible version of icu::number::LocalizedNumberFormatter. + * + * NOTE: This is a C-compatible API; C++ users should build against numberformatter.h instead. + * + * @draft ICU 62 + */ +struct UNumberFormatter; +typedef struct UNumberFormatter UNumberFormatter; + + +/** + * C-compatible version of icu::number::FormattedNumber. + * + * NOTE: This is a C-compatible API; C++ users should build against numberformatter.h instead. + * + * @draft ICU 62 + */ +struct UFormattedNumber; +typedef struct UFormattedNumber UFormattedNumber; + + +/** + * Creates a new UNumberFormatter for the given skeleton string and locale. This is currently the only + * method for creating a new UNumberFormatter. + * + * Objects of type UNumberFormatter returned by this method are threadsafe. + * + * For more details on skeleton strings, see the documentation in numberformatter.h. For more details on + * the usage of this API, see the documentation at the top of unumberformatter.h. + * + * NOTE: This is a C-compatible API; C++ users should build against numberformatter.h instead. + * + * @param skeleton The skeleton string, like u"percent precision-integer" + * @param skeletonLen The number of UChars in the skeleton string, or -1 it it is NUL-terminated. + * @param locale The NUL-terminated locale ID. + * @param ec Set if an error occurs. + * @draft ICU 62 + */ +U_DRAFT UNumberFormatter* U_EXPORT2 +unumf_openForSkeletonAndLocale(const UChar* skeleton, int32_t skeletonLen, const char* locale, + UErrorCode* ec); + + +/** + * Creates a new UFormattedNumber for holding the result of a number formatting operation. + * + * Objects of type UFormattedNumber are not guaranteed to be threadsafe. + * + * NOTE: This is a C-compatible API; C++ users should build against numberformatter.h instead. + * + * @param ec Set if an error occurs. + * @draft ICU 62 + */ +U_DRAFT UFormattedNumber* U_EXPORT2 +unumf_openResult(UErrorCode* ec); + + +/** + * Uses a UNumberFormatter to format an integer to a UFormattedNumber. A string, field position, and other + * information can be retrieved from the UFormattedNumber. + * + * The UNumberFormatter can be shared between threads. Each thread should have its own local + * UFormattedNumber, however, for storing the result of the formatting operation. + * + * NOTE: This is a C-compatible API; C++ users should build against numberformatter.h instead. + * + * @param uformatter A formatter object created by unumf_openForSkeletonAndLocale or similar. + * @param value The number to be formatted. + * @param uresult The object that will be mutated to store the result; see unumf_openResult. + * @param ec Set if an error occurs. + * @draft ICU 62 + */ +U_DRAFT void U_EXPORT2 +unumf_formatInt(const UNumberFormatter* uformatter, int64_t value, UFormattedNumber* uresult, + UErrorCode* ec); + + +/** + * Uses a UNumberFormatter to format a double to a UFormattedNumber. A string, field position, and other + * information can be retrieved from the UFormattedNumber. + * + * The UNumberFormatter can be shared between threads. Each thread should have its own local + * UFormattedNumber, however, for storing the result of the formatting operation. + * + * NOTE: This is a C-compatible API; C++ users should build against numberformatter.h instead. + * + * @param uformatter A formatter object created by unumf_openForSkeletonAndLocale or similar. + * @param value The number to be formatted. + * @param uresult The object that will be mutated to store the result; see unumf_openResult. + * @param ec Set if an error occurs. + * @draft ICU 62 + */ +U_DRAFT void U_EXPORT2 +unumf_formatDouble(const UNumberFormatter* uformatter, double value, UFormattedNumber* uresult, + UErrorCode* ec); + + +/** + * Uses a UNumberFormatter to format a decimal number to a UFormattedNumber. A string, field position, and + * other information can be retrieved from the UFormattedNumber. + * + * The UNumberFormatter can be shared between threads. Each thread should have its own local + * UFormattedNumber, however, for storing the result of the formatting operation. + * + * The syntax of the unformatted number is a "numeric string" as defined in the Decimal Arithmetic + * Specification, available at http://speleotrove.com/decimal + * + * NOTE: This is a C-compatible API; C++ users should build against numberformatter.h instead. + * + * @param uformatter A formatter object created by unumf_openForSkeletonAndLocale or similar. + * @param value The numeric string to be formatted. + * @param valueLen The length of the numeric string, or -1 if it is NUL-terminated. + * @param uresult The object that will be mutated to store the result; see unumf_openResult. + * @param ec Set if an error occurs. + * @draft ICU 62 + */ +U_DRAFT void U_EXPORT2 +unumf_formatDecimal(const UNumberFormatter* uformatter, const char* value, int32_t valueLen, + UFormattedNumber* uresult, UErrorCode* ec); + + +/** + * Extracts the result number string out of a UFormattedNumber to a UChar buffer if possible. + * If bufferCapacity is greater than the required length, a terminating NUL is written. + * If bufferCapacity is less than the required length, an error code is set. + * + * NOTE: This is a C-compatible API; C++ users should build against numberformatter.h instead. + * + * @param uresult The object containing the formatted number. + * @param buffer Where to save the string output. + * @param bufferCapacity The number of UChars available in the buffer. + * @param ec Set if an error occurs. + * @return The required length. + * @draft ICU 62 + */ +U_DRAFT int32_t U_EXPORT2 +unumf_resultToString(const UFormattedNumber* uresult, UChar* buffer, int32_t bufferCapacity, + UErrorCode* ec); + + +/** + * 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. + * + * 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: + * + *
+ * UFieldPosition ufpos = {UNUM_GROUPING_SEPARATOR_FIELD, 0, 0};
+ * while (unumf_resultNextFieldPosition(uresult, ufpos, &ec)) {
+ *   // do something with ufpos.
+ * }
+ * 
+ * + * This method is useful if you know which field to query. If you want all available field position + * information, use unumf_resultGetAllFieldPositions(). + * + * NOTE: All fields of the UFieldPosition must be initialized before calling this method. + * + * @param fieldPosition + * 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 + * input "endIndex", and "endIndex" is set to the end of that occurrence of the field + * (exclusive index). If a field position is not found, the FieldPosition is not changed and + * the method returns FALSE. + * @param ec Set if an error occurs. + * @draft ICU 62 + */ +U_DRAFT UBool U_EXPORT2 +unumf_resultNextFieldPosition(const UFormattedNumber* uresult, UFieldPosition* ufpos, UErrorCode* ec); + + +/** + * Populates the given iterator with all fields in the formatted output string. This allows you to + * determine the locations of the integer part, fraction part, and sign. + * + * If you need information on only one field, use unumf_resultNextFieldPosition(). + * + * @param uresult The object containing the formatted number. + * @param fpositer + * 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 + * and indexes returned by {@link #ufieldpositer_next} represent fields denoted by + * the UNumberFormatFields enum. Fields are not returned in a guaranteed order. Fields cannot + * overlap, but they may nest. For example, 1234 could format as "1,234" which might consist of a + * grouping separator field for ',' and an integer field encompassing the entire string. + * @param ec Set if an error occurs. + * @draft ICU 62 + */ +U_DRAFT void U_EXPORT2 +unumf_resultGetAllFieldPositions(const UFormattedNumber* uresult, UFieldPositionIterator* ufpositer, + UErrorCode* ec); + + +/** + * Releases the UNumberFormatter created by unumf_openForSkeletonAndLocale(). + * + * NOTE: This is a C-compatible API; C++ users should build against numberformatter.h instead. + * + * @param uformatter An object created by unumf_openForSkeletonAndLocale(). + * @draft ICU 62 + */ +U_DRAFT void U_EXPORT2 +unumf_close(UNumberFormatter* uformatter); + + +/** + * Releases the UFormattedNumber created by unumf_openResult(). + * + * NOTE: This is a C-compatible API; C++ users should build against numberformatter.h instead. + * + * @param uresult An object created by unumf_openResult(). + * @draft ICU 62 + */ +U_DRAFT void U_EXPORT2 +unumf_closeResult(UFormattedNumber* uresult); + + +#if U_SHOW_CPLUSPLUS_API +U_NAMESPACE_BEGIN + +/** + * \class LocalUNumberFormatterPointer + * "Smart pointer" class; closes a UNumberFormatter via unumf_close(). + * For most methods see the LocalPointerBase base class. + * + * Usage: + *
+ * LocalUNumberFormatterPointer uformatter(unumf_openForSkeletonAndLocale(...));
+ * // no need to explicitly call unumf_close()
+ * 
+ * + * @see LocalPointerBase + * @see LocalPointer + * @draft ICU 62 + */ +U_DEFINE_LOCAL_OPEN_POINTER(LocalUNumberFormatterPointer, UNumberFormatter, unumf_close); + +/** + * \class LocalUNumberFormatterPointer + * "Smart pointer" class; closes a UFormattedNumber via unumf_closeResult(). + * For most methods see the LocalPointerBase base class. + * + * Usage: + *
+ * LocalUFormattedNumberPointer uformatter(unumf_openResult(...));
+ * // no need to explicitly call unumf_closeResult()
+ * 
+ * + * @see LocalPointerBase + * @see LocalPointer + * @draft ICU 62 + */ +U_DEFINE_LOCAL_OPEN_POINTER(LocalUFormattedNumberPointer, UFormattedNumber, unumf_closeResult); + +U_NAMESPACE_END +#endif // U_SHOW_CPLUSPLUS_API + +#endif /* U_HIDE_DRAFT_API */ + +#endif //__UNUMBERFORMATTER_H__ +#endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/deps/icu-small/source/i18n/unicode/uspoof.h b/deps/icu-small/source/i18n/unicode/uspoof.h index 9fcfcd3ede8..781a88247fe 100644 --- a/deps/icu-small/source/i18n/unicode/uspoof.h +++ b/deps/icu-small/source/i18n/unicode/uspoof.h @@ -477,7 +477,7 @@ typedef enum USpoofChecks { */ USPOOF_CHAR_LIMIT = 64, - /** + /** * Check that an identifier does not mix numbers from different numbering systems. * For more information, see UTS 39 section 5.3. * @@ -485,6 +485,29 @@ typedef enum USpoofChecks { */ USPOOF_MIXED_NUMBERS = 128, +#ifndef U_HIDE_DRAFT_API + /** + * Check that an identifier does not have a combining character following a character in which that + * combining character would be hidden; for example 'i' followed by a U+0307 combining dot. + * + * More specifically, the following characters are forbidden from preceding a U+0307: + *
    + *
  • Those with the Soft_Dotted Unicode property (which includes 'i' and 'j')
  • + *
  • Latin lowercase letter 'l'
  • + *
  • Dotless 'i' and 'j' ('ı' and 'ȷ', U+0131 and U+0237)
  • + *
  • Any character whose confusable prototype ends with such a character + * (Soft_Dotted, 'l', 'ı', or 'ȷ')
  • + *
+ * In addition, combining characters are allowed between the above characters and U+0307 except those + * with combining class 0 or combining class "Above" (230, same class as U+0307). + * + * This list and the number of combing characters considered by this check may grow over time. + * + * @draft ICU 62 + */ + USPOOF_HIDDEN_OVERLAY = 256, +#endif /* U_HIDE_DRAFT_API */ + /** * Enable all spoof checks. * diff --git a/deps/icu-small/source/i18n/upluralrules.cpp b/deps/icu-small/source/i18n/upluralrules.cpp index 24e74e3ee22..bba6dfe3101 100644 --- a/deps/icu-small/source/i18n/upluralrules.cpp +++ b/deps/icu-small/source/i18n/upluralrules.cpp @@ -17,9 +17,44 @@ #include "unicode/unistr.h" #include "unicode/unum.h" #include "unicode/numfmt.h" +#include "number_decimalquantity.h" U_NAMESPACE_USE +namespace { + +/** + * Given a number and a format, returns the keyword of the first applicable + * rule for the PluralRules object. + * @param rules The plural rules. + * @param obj The numeric object for which the rule should be determined. + * @param fmt The NumberFormat specifying how the number will be formatted + * (this can affect the plural form, e.g. "1 dollar" vs "1.0 dollars"). + * @param status Input/output parameter. If at entry this indicates a + * failure status, the method returns immediately; otherwise + * this is set to indicate the outcome of the call. + * @return The keyword of the selected rule. Undefined in the case of an error. + */ +UnicodeString select(const PluralRules &rules, const Formattable& obj, const NumberFormat& fmt, UErrorCode& status) { + if (U_SUCCESS(status)) { + const DecimalFormat *decFmt = dynamic_cast(&fmt); + if (decFmt != NULL) { + number::impl::DecimalQuantity dq; + decFmt->formatToDecimalQuantity(obj, dq, status); + if (U_SUCCESS(status)) { + return rules.select(dq); + } + } else { + double number = obj.getDouble(status); + if (U_SUCCESS(status)) { + return rules.select(number); + } + } + } + return UnicodeString(); +} + +} // namespace U_CAPI UPluralRules* U_EXPORT2 uplrules_open(const char *locale, UErrorCode *status) @@ -73,7 +108,7 @@ uplrules_selectWithFormat(const UPluralRules *uplrules, return 0; } Formattable obj(number); - UnicodeString result = plrules->select(obj, *nf, *status); + UnicodeString result = select(*plrules, obj, *nf, *status); return result.extract(keyword, capacity, *status); } diff --git a/deps/icu-small/source/i18n/uspoof.cpp b/deps/icu-small/source/i18n/uspoof.cpp index 019819b11cd..710adcd08da 100644 --- a/deps/icu-small/source/i18n/uspoof.cpp +++ b/deps/icu-small/source/i18n/uspoof.cpp @@ -55,75 +55,96 @@ uspoof_cleanup(void) { } static void U_CALLCONV initializeStatics(UErrorCode &status) { - static const char *inclusionPat = - "['\\-.\\:\\u00B7\\u0375\\u058A\\u05F3\\u05F4\\u06FD\\u06FE\\u0F0B\\u200C\\u200D\\u2010\\u" - "2019\\u2027\\u30A0\\u30FB]"; - gInclusionSet = new UnicodeSet(UnicodeString(inclusionPat, -1, US_INV), status); + static const char16_t *inclusionPat = + u"['\\-.\\:\\u00B7\\u0375\\u058A\\u05F3\\u05F4\\u06FD\\u06FE\\u0F0B\\u200C" + u"\\u200D\\u2010\\u2019\\u2027\\u30A0\\u30FB]"; + gInclusionSet = new UnicodeSet(UnicodeString(inclusionPat), status); + if (gInclusionSet == NULL) { + status = U_MEMORY_ALLOCATION_ERROR; + return; + } gInclusionSet->freeze(); - // Note: data from http://unicode.org/Public/security/9.0.0/IdentifierStatus.txt + // Note: data from IdentifierStatus.txt & IdentifierType.txt // There is tooling to generate this constant in the unicodetools project: // org.unicode.text.tools.RecommendedSetGenerator // It will print the Java and C++ code to the console for easy copy-paste into this file. // Note: concatenated string constants do not work with UNICODE_STRING_SIMPLE on all platforms. - static const char *recommendedPat = - "[0-9A-Z_a-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u0131\\u0134-\\u013E\\u0141-\\u014" - "8\\u014A-\\u017E\\u018F\\u01A0\\u01A1\\u01AF\\u01B0\\u01CD-\\u01DC\\u01DE-\\u01E3\\u01E" - "6-\\u01F0\\u01F4\\u01F5\\u01F8-\\u021B\\u021E\\u021F\\u0226-\\u0233\\u0259\\u02BB\\u02B" - "C\\u02EC\\u0300-\\u0304\\u0306-\\u030C\\u030F-\\u0311\\u0313\\u0314\\u031B\\u0323-\\u03" - "28\\u032D\\u032E\\u0330\\u0331\\u0335\\u0338\\u0339\\u0342\\u0345\\u037B-\\u037D\\u0386" - "\\u0388-\\u038A\\u038C\\u038E-\\u03A1\\u03A3-\\u03CE\\u03FC-\\u045F\\u048A-\\u0529\\u05" - "2E\\u052F\\u0531-\\u0556\\u0559\\u0561-\\u0586\\u05B4\\u05D0-\\u05EA\\u05F0-\\u05F2\\u0" - "620-\\u063F\\u0641-\\u0655\\u0660-\\u0669\\u0670-\\u0672\\u0674\\u0679-\\u068D\\u068F-" - "\\u06D3\\u06D5\\u06E5\\u06E6\\u06EE-\\u06FC\\u06FF\\u0750-\\u07B1\\u08A0-\\u08AC\\u08B2" - "\\u08B6-\\u08BD\\u0901-\\u094D\\u094F\\u0950\\u0956\\u0957\\u0960-\\u0963\\u0966-\\u096" - "F\\u0971-\\u0977\\u0979-\\u097F\\u0981-\\u0983\\u0985-\\u098C\\u098F\\u0990\\u0993-\\u0" - "9A8\\u09AA-\\u09B0\\u09B2\\u09B6-\\u09B9\\u09BC-\\u09C4\\u09C7\\u09C8\\u09CB-\\u09CE\\u" - "09D7\\u09E0-\\u09E3\\u09E6-\\u09F1\\u0A01-\\u0A03\\u0A05-\\u0A0A\\u0A0F\\u0A10\\u0A13-" - "\\u0A28\\u0A2A-\\u0A30\\u0A32\\u0A35\\u0A38\\u0A39\\u0A3C\\u0A3E-\\u0A42\\u0A47\\u0A48\\" - "u0A4B-\\u0A4D\\u0A5C\\u0A66-\\u0A74\\u0A81-\\u0A83\\u0A85-\\u0A8D\\u0A8F-\\u0A91\\u0A9" - "3-\\u0AA8\\u0AAA-\\u0AB0\\u0AB2\\u0AB3\\u0AB5-\\u0AB9\\u0ABC-\\u0AC5\\u0AC7-\\u0AC9\\u0" - "ACB-\\u0ACD\\u0AD0\\u0AE0-\\u0AE3\\u0AE6-\\u0AEF\\u0B01-\\u0B03\\u0B05-\\u0B0C\\u0B0F\\" - "u0B10\\u0B13-\\u0B28\\u0B2A-\\u0B30\\u0B32\\u0B33\\u0B35-\\u0B39\\u0B3C-\\u0B43\\u0B47" - "\\u0B48\\u0B4B-\\u0B4D\\u0B56\\u0B57\\u0B5F-\\u0B61\\u0B66-\\u0B6F\\u0B71\\u0B82\\u0B83" - "\\u0B85-\\u0B8A\\u0B8E-\\u0B90\\u0B92-\\u0B95\\u0B99\\u0B9A\\u0B9C\\u0B9E\\u0B9F\\u0BA3" - "\\u0BA4\\u0BA8-\\u0BAA\\u0BAE-\\u0BB9\\u0BBE-\\u0BC2\\u0BC6-\\u0BC8\\u0BCA-\\u0BCD\\u0B" - "D0\\u0BD7\\u0BE6-\\u0BEF\\u0C01-\\u0C03\\u0C05-\\u0C0C\\u0C0E-\\u0C10\\u0C12-\\u0C28\\u" - "0C2A-\\u0C33\\u0C35-\\u0C39\\u0C3D-\\u0C44\\u0C46-\\u0C48\\u0C4A-\\u0C4D\\u0C55\\u0C56" - "\\u0C60\\u0C61\\u0C66-\\u0C6F\\u0C80\\u0C82\\u0C83\\u0C85-\\u0C8C\\u0C8E-\\u0C90\\u0C92" - "-\\u0CA8\\u0CAA-\\u0CB3\\u0CB5-\\u0CB9\\u0CBC-\\u0CC4\\u0CC6-\\u0CC8\\u0CCA-\\u0CCD\\u0" - "CD5\\u0CD6\\u0CE0-\\u0CE3\\u0CE6-\\u0CEF\\u0CF1\\u0CF2\\u0D02\\u0D03\\u0D05-\\u0D0C\\u0" - "D0E-\\u0D10\\u0D12-\\u0D3A\\u0D3D-\\u0D43\\u0D46-\\u0D48\\u0D4A-\\u0D4E\\u0D54-\\u0D57" - "\\u0D60\\u0D61\\u0D66-\\u0D6F\\u0D7A-\\u0D7F\\u0D82\\u0D83\\u0D85-\\u0D8E\\u0D91-\\u0D9" - "6\\u0D9A-\\u0DA5\\u0DA7-\\u0DB1\\u0DB3-\\u0DBB\\u0DBD\\u0DC0-\\u0DC6\\u0DCA\\u0DCF-\\u0" - "DD4\\u0DD6\\u0DD8-\\u0DDE\\u0DF2\\u0E01-\\u0E32\\u0E34-\\u0E3A\\u0E40-\\u0E4E\\u0E50-\\" - "u0E59\\u0E81\\u0E82\\u0E84\\u0E87\\u0E88\\u0E8A\\u0E8D\\u0E94-\\u0E97\\u0E99-\\u0E9F\\u" - "0EA1-\\u0EA3\\u0EA5\\u0EA7\\u0EAA\\u0EAB\\u0EAD-\\u0EB2\\u0EB4-\\u0EB9\\u0EBB-\\u0EBD\\" - "u0EC0-\\u0EC4\\u0EC6\\u0EC8-\\u0ECD\\u0ED0-\\u0ED9\\u0EDE\\u0EDF\\u0F00\\u0F20-\\u0F29" - "\\u0F35\\u0F37\\u0F3E-\\u0F42\\u0F44-\\u0F47\\u0F49-\\u0F4C\\u0F4E-\\u0F51\\u0F53-\\u0F" - "56\\u0F58-\\u0F5B\\u0F5D-\\u0F68\\u0F6A-\\u0F6C\\u0F71\\u0F72\\u0F74\\u0F7A-\\u0F80\\u0" - "F82-\\u0F84\\u0F86-\\u0F92\\u0F94-\\u0F97\\u0F99-\\u0F9C\\u0F9E-\\u0FA1\\u0FA3-\\u0FA6" - "\\u0FA8-\\u0FAB\\u0FAD-\\u0FB8\\u0FBA-\\u0FBC\\u0FC6\\u1000-\\u1049\\u1050-\\u109D\\u10" - "C7\\u10CD\\u10D0-\\u10F0\\u10F7-\\u10FA\\u10FD-\\u10FF\\u1200-\\u1248\\u124A-\\u124D\\u" - "1250-\\u1256\\u1258\\u125A-\\u125D\\u1260-\\u1288\\u128A-\\u128D\\u1290-\\u12B0\\u12B2" - "-\\u12B5\\u12B8-\\u12BE\\u12C0\\u12C2-\\u12C5\\u12C8-\\u12D6\\u12D8-\\u1310\\u1312-\\u1" - "315\\u1318-\\u135A\\u135D-\\u135F\\u1380-\\u138F\\u1780-\\u17A2\\u17A5-\\u17A7\\u17A9-" - "\\u17B3\\u17B6-\\u17CA\\u17D2\\u17D7\\u17DC\\u17E0-\\u17E9\\u1C80-\\u1C88\\u1E00-\\u1E9" - "9\\u1E9E\\u1EA0-\\u1EF9\\u1F00-\\u1F15\\u1F18-\\u1F1D\\u1F20-\\u1F45\\u1F48-\\u1F4D\\u1" - "F50-\\u1F57\\u1F59\\u1F5B\\u1F5D\\u1F5F-\\u1F70\\u1F72\\u1F74\\u1F76\\u1F78\\u1F7A\\u1F" - "7C\\u1F80-\\u1FB4\\u1FB6-\\u1FBA\\u1FBC\\u1FC2-\\u1FC4\\u1FC6-\\u1FC8\\u1FCA\\u1FCC\\u1" - "FD0-\\u1FD2\\u1FD6-\\u1FDA\\u1FE0-\\u1FE2\\u1FE4-\\u1FEA\\u1FEC\\u1FF2-\\u1FF4\\u1FF6-" - "\\u1FF8\\u1FFA\\u1FFC\\u2D27\\u2D2D\\u2D80-\\u2D96\\u2DA0-\\u2DA6\\u2DA8-\\u2DAE\\u2DB0" - "-\\u2DB6\\u2DB8-\\u2DBE\\u2DC0-\\u2DC6\\u2DC8-\\u2DCE\\u2DD0-\\u2DD6\\u2DD8-\\u2DDE\\u3" - "005-\\u3007\\u3041-\\u3096\\u3099\\u309A\\u309D\\u309E\\u30A1-\\u30FA\\u30FC-\\u30FE\\u" - "3105-\\u312D\\u31A0-\\u31BA\\u3400-\\u4DB5\\u4E00-\\u9FD5\\uA660\\uA661\\uA674-\\uA67B" - "\\uA67F\\uA69F\\uA717-\\uA71F\\uA788\\uA78D\\uA78E\\uA790-\\uA793\\uA7A0-\\uA7AA\\uA7AE" - "\\uA7FA\\uA9E7-\\uA9FE\\uAA60-\\uAA76\\uAA7A-\\uAA7F\\uAB01-\\uAB06\\uAB09-\\uAB0E\\uAB" - "11-\\uAB16\\uAB20-\\uAB26\\uAB28-\\uAB2E\\uAC00-\\uD7A3\\uFA0E\\uFA0F\\uFA11\\uFA13\\uF" - "A14\\uFA1F\\uFA21\\uFA23\\uFA24\\uFA27-\\uFA29\\U00020000-\\U0002A6D6\\U0002A700-\\U0" - "002B734\\U0002B740-\\U0002B81D\\U0002B820-\\U0002CEA1]"; + static const char16_t *recommendedPat = + u"[0-9A-Z_a-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u0131\\u0134-\\u013E" + u"\\u0141-\\u0148\\u014A-\\u017E\\u018F\\u01A0\\u01A1\\u01AF\\u01B0\\u01CD-" + u"\\u01DC\\u01DE-\\u01E3\\u01E6-\\u01F0\\u01F4\\u01F5\\u01F8-\\u021B\\u021E" + u"\\u021F\\u0226-\\u0233\\u0259\\u02BB\\u02BC\\u02EC\\u0300-\\u0304\\u0306-" + u"\\u030C\\u030F-\\u0311\\u0313\\u0314\\u031B\\u0323-\\u0328\\u032D\\u032E" + u"\\u0330\\u0331\\u0335\\u0338\\u0339\\u0342\\u0345\\u037B-\\u037D\\u0386" + u"\\u0388-\\u038A\\u038C\\u038E-\\u03A1\\u03A3-\\u03CE\\u03FC-\\u045F\\u048A-" + u"\\u0529\\u052E\\u052F\\u0531-\\u0556\\u0559\\u0560-\\u0586\\u0588\\u05B4" + u"\\u05D0-\\u05EA\\u05EF-\\u05F2\\u0620-\\u063F\\u0641-\\u0655\\u0660-\\u0669" + u"\\u0670-\\u0672\\u0674\\u0679-\\u068D\\u068F-\\u06D3\\u06D5\\u06E5\\u06E6" + u"\\u06EE-\\u06FC\\u06FF\\u0750-\\u07B1\\u08A0-\\u08AC\\u08B2\\u08B6-\\u08BD" + u"\\u0901-\\u094D\\u094F\\u0950\\u0956\\u0957\\u0960-\\u0963\\u0966-\\u096F" + u"\\u0971-\\u0977\\u0979-\\u097F\\u0981-\\u0983\\u0985-\\u098C\\u098F\\u0990" + u"\\u0993-\\u09A8\\u09AA-\\u09B0\\u09B2\\u09B6-\\u09B9\\u09BC-\\u09C4\\u09C7" + u"\\u09C8\\u09CB-\\u09CE\\u09D7\\u09E0-\\u09E3\\u09E6-\\u09F1\\u09FC\\u09FE" + u"\\u0A01-\\u0A03\\u0A05-\\u0A0A\\u0A0F\\u0A10\\u0A13-\\u0A28\\u0A2A-\\u0A30" + u"\\u0A32\\u0A35\\u0A38\\u0A39\\u0A3C\\u0A3E-\\u0A42\\u0A47\\u0A48\\u0A4B-" + u"\\u0A4D\\u0A5C\\u0A66-\\u0A74\\u0A81-\\u0A83\\u0A85-\\u0A8D\\u0A8F-\\u0A91" + u"\\u0A93-\\u0AA8\\u0AAA-\\u0AB0\\u0AB2\\u0AB3\\u0AB5-\\u0AB9\\u0ABC-\\u0AC5" + u"\\u0AC7-\\u0AC9\\u0ACB-\\u0ACD\\u0AD0\\u0AE0-\\u0AE3\\u0AE6-\\u0AEF\\u0AFA-" + u"\\u0AFF\\u0B01-\\u0B03\\u0B05-\\u0B0C\\u0B0F\\u0B10\\u0B13-\\u0B28\\u0B2A-" + u"\\u0B30\\u0B32\\u0B33\\u0B35-\\u0B39\\u0B3C-\\u0B43\\u0B47\\u0B48\\u0B4B-" + u"\\u0B4D\\u0B56\\u0B57\\u0B5F-\\u0B61\\u0B66-\\u0B6F\\u0B71\\u0B82\\u0B83" + u"\\u0B85-\\u0B8A\\u0B8E-\\u0B90\\u0B92-\\u0B95\\u0B99\\u0B9A\\u0B9C\\u0B9E" + u"\\u0B9F\\u0BA3\\u0BA4\\u0BA8-\\u0BAA\\u0BAE-\\u0BB9\\u0BBE-\\u0BC2\\u0BC6-" + u"\\u0BC8\\u0BCA-\\u0BCD\\u0BD0\\u0BD7\\u0BE6-\\u0BEF\\u0C01-\\u0C0C\\u0C0E-" + u"\\u0C10\\u0C12-\\u0C28\\u0C2A-\\u0C33\\u0C35-\\u0C39\\u0C3D-\\u0C44\\u0C46-" + u"\\u0C48\\u0C4A-\\u0C4D\\u0C55\\u0C56\\u0C60\\u0C61\\u0C66-\\u0C6F\\u0C80" + u"\\u0C82\\u0C83\\u0C85-\\u0C8C\\u0C8E-\\u0C90\\u0C92-\\u0CA8\\u0CAA-\\u0CB3" + u"\\u0CB5-\\u0CB9\\u0CBC-\\u0CC4\\u0CC6-\\u0CC8\\u0CCA-\\u0CCD\\u0CD5\\u0CD6" + u"\\u0CE0-\\u0CE3\\u0CE6-\\u0CEF\\u0CF1\\u0CF2\\u0D00\\u0D02\\u0D03\\u0D05-" + u"\\u0D0C\\u0D0E-\\u0D10\\u0D12-\\u0D43\\u0D46-\\u0D48\\u0D4A-\\u0D4E\\u0D54-" + u"\\u0D57\\u0D60\\u0D61\\u0D66-\\u0D6F\\u0D7A-\\u0D7F\\u0D82\\u0D83\\u0D85-" + u"\\u0D8E\\u0D91-\\u0D96\\u0D9A-\\u0DA5\\u0DA7-\\u0DB1\\u0DB3-\\u0DBB\\u0DBD" + u"\\u0DC0-\\u0DC6\\u0DCA\\u0DCF-\\u0DD4\\u0DD6\\u0DD8-\\u0DDE\\u0DF2\\u0E01-" + u"\\u0E32\\u0E34-\\u0E3A\\u0E40-\\u0E4E\\u0E50-\\u0E59\\u0E81\\u0E82\\u0E84" + u"\\u0E87\\u0E88\\u0E8A\\u0E8D\\u0E94-\\u0E97\\u0E99-\\u0E9F\\u0EA1-\\u0EA3" + u"\\u0EA5\\u0EA7\\u0EAA\\u0EAB\\u0EAD-\\u0EB2\\u0EB4-\\u0EB9\\u0EBB-\\u0EBD" + u"\\u0EC0-\\u0EC4\\u0EC6\\u0EC8-\\u0ECD\\u0ED0-\\u0ED9\\u0EDE\\u0EDF\\u0F00" + u"\\u0F20-\\u0F29\\u0F35\\u0F37\\u0F3E-\\u0F42\\u0F44-\\u0F47\\u0F49-\\u0F4C" + u"\\u0F4E-\\u0F51\\u0F53-\\u0F56\\u0F58-\\u0F5B\\u0F5D-\\u0F68\\u0F6A-\\u0F6C" + u"\\u0F71\\u0F72\\u0F74\\u0F7A-\\u0F80\\u0F82-\\u0F84\\u0F86-\\u0F92\\u0F94-" + u"\\u0F97\\u0F99-\\u0F9C\\u0F9E-\\u0FA1\\u0FA3-\\u0FA6\\u0FA8-\\u0FAB\\u0FAD-" + u"\\u0FB8\\u0FBA-\\u0FBC\\u0FC6\\u1000-\\u1049\\u1050-\\u109D\\u10C7\\u10CD" + u"\\u10D0-\\u10F0\\u10F7-\\u10FA\\u10FD-\\u10FF\\u1200-\\u1248\\u124A-\\u124D" + u"\\u1250-\\u1256\\u1258\\u125A-\\u125D\\u1260-\\u1288\\u128A-\\u128D\\u1290-" + u"\\u12B0\\u12B2-\\u12B5\\u12B8-\\u12BE\\u12C0\\u12C2-\\u12C5\\u12C8-\\u12D6" + u"\\u12D8-\\u1310\\u1312-\\u1315\\u1318-\\u135A\\u135D-\\u135F\\u1380-\\u138F" + u"\\u1780-\\u17A2\\u17A5-\\u17A7\\u17A9-\\u17B3\\u17B6-\\u17CA\\u17D2\\u17D7" + u"\\u17DC\\u17E0-\\u17E9\\u1C80-\\u1C88\\u1C90-\\u1CBA\\u1CBD-\\u1CBF\\u1E00-" + u"\\u1E99\\u1E9E\\u1EA0-\\u1EF9\\u1F00-\\u1F15\\u1F18-\\u1F1D\\u1F20-\\u1F45" + u"\\u1F48-\\u1F4D\\u1F50-\\u1F57\\u1F59\\u1F5B\\u1F5D\\u1F5F-\\u1F70\\u1F72" + u"\\u1F74\\u1F76\\u1F78\\u1F7A\\u1F7C\\u1F80-\\u1FB4\\u1FB6-\\u1FBA\\u1FBC" + u"\\u1FC2-\\u1FC4\\u1FC6-\\u1FC8\\u1FCA\\u1FCC\\u1FD0-\\u1FD2\\u1FD6-\\u1FDA" + u"\\u1FE0-\\u1FE2\\u1FE4-\\u1FEA\\u1FEC\\u1FF2-\\u1FF4\\u1FF6-\\u1FF8\\u1FFA" + u"\\u1FFC\\u2D27\\u2D2D\\u2D80-\\u2D96\\u2DA0-\\u2DA6\\u2DA8-\\u2DAE\\u2DB0-" + u"\\u2DB6\\u2DB8-\\u2DBE\\u2DC0-\\u2DC6\\u2DC8-\\u2DCE\\u2DD0-\\u2DD6\\u2DD8-" + u"\\u2DDE\\u3005-\\u3007\\u3041-\\u3096\\u3099\\u309A\\u309D\\u309E\\u30A1-" + u"\\u30FA\\u30FC-\\u30FE\\u3105-\\u312F\\u31A0-\\u31BA\\u3400-\\u4DB5\\u4E00-" + u"\\u9FEF\\uA660\\uA661\\uA674-\\uA67B\\uA67F\\uA69F\\uA717-\\uA71F\\uA788" + u"\\uA78D\\uA78E\\uA790-\\uA793\\uA7A0-\\uA7AA\\uA7AE\\uA7AF\\uA7B8\\uA7B9" + u"\\uA7FA\\uA9E7-\\uA9FE\\uAA60-\\uAA76\\uAA7A-\\uAA7F\\uAB01-\\uAB06\\uAB09-" + u"\\uAB0E\\uAB11-\\uAB16\\uAB20-\\uAB26\\uAB28-\\uAB2E\\uAC00-\\uD7A3\\uFA0E" + u"\\uFA0F\\uFA11\\uFA13\\uFA14\\uFA1F\\uFA21\\uFA23\\uFA24\\uFA27-\\uFA29" + u"\\U0001133B\\U0001B002-\\U0001B11E\\U00020000-\\U0002A6D6\\U0002A700-" + u"\\U0002B734\\U0002B740-\\U0002B81D\\U0002B820-\\U0002CEA1\\U0002CEB0-" + u"\\U0002EBE0]"; - gRecommendedSet = new UnicodeSet(UnicodeString(recommendedPat, -1, US_INV), status); + gRecommendedSet = new UnicodeSet(UnicodeString(recommendedPat), status); + if (gRecommendedSet == NULL) { + status = U_MEMORY_ALLOCATION_ERROR; + delete gInclusionSet; + return; + } gRecommendedSet->freeze(); gNfdNormalizer = Normalizer2::getNFDInstance(status); ucln_i18n_registerCleanup(UCLN_I18N_SPOOF, uspoof_cleanup); @@ -140,12 +161,13 @@ uspoof_open(UErrorCode *status) { return NULL; } SpoofImpl *si = new SpoofImpl(*status); - if (U_SUCCESS(*status) && si == NULL) { + if (si == NULL) { *status = U_MEMORY_ALLOCATION_ERROR; + return NULL; } if (U_FAILURE(*status)) { delete si; - si = NULL; + return NULL; } return si->asUSpoofChecker(); } @@ -157,18 +179,38 @@ uspoof_openFromSerialized(const void *data, int32_t length, int32_t *pActualLeng if (U_FAILURE(*status)) { return NULL; } - umtx_initOnce(gSpoofInitStaticsOnce, &initializeStatics, *status); - SpoofData *sd = new SpoofData(data, length, *status); - SpoofImpl *si = new SpoofImpl(sd, *status); - if (U_FAILURE(*status)) { - delete sd; - delete si; + + if (data == NULL) { + *status = U_ILLEGAL_ARGUMENT_ERROR; return NULL; } - if (sd == NULL || si == NULL) { + + umtx_initOnce(gSpoofInitStaticsOnce, &initializeStatics, *status); + if (U_FAILURE(*status)) + { + return NULL; + } + + SpoofData *sd = new SpoofData(data, length, *status); + if (sd == NULL) { *status = U_MEMORY_ALLOCATION_ERROR; + return NULL; + } + + if (U_FAILURE(*status)) { delete sd; - delete si; + return NULL; + } + + SpoofImpl *si = new SpoofImpl(sd, *status); + if (si == NULL) { + *status = U_MEMORY_ALLOCATION_ERROR; + delete sd; // explicit delete as the destructor for si won't be called. + return NULL; + } + + if (U_FAILURE(*status)) { + delete si; // no delete for sd, as the si destructor will delete it. return NULL; } @@ -186,6 +228,10 @@ uspoof_clone(const USpoofChecker *sc, UErrorCode *status) { return NULL; } SpoofImpl *result = new SpoofImpl(*src, *status); // copy constructor + if (result == NULL) { + *status = U_MEMORY_ALLOCATION_ERROR; + return NULL; + } if (U_FAILURE(*status)) { delete result; result = NULL; @@ -524,6 +570,13 @@ int32_t checkImpl(const SpoofImpl* This, const UnicodeString& id, CheckResult* c checkResult->fNumerics = numerics; // UnicodeSet::operator= } + if (0 != (This->fChecks & USPOOF_HIDDEN_OVERLAY)) { + int32_t index = This->findHiddenOverlay(id, *status); + if (index != -1) { + result |= USPOOF_HIDDEN_OVERLAY; + } + } + if (0 != (This->fChecks & USPOOF_CHAR_LIMIT)) { int32_t i; diff --git a/deps/icu-small/source/i18n/uspoof_build.cpp b/deps/icu-small/source/i18n/uspoof_build.cpp index 7d2440e5af6..7087c1ce596 100644 --- a/deps/icu-small/source/i18n/uspoof_build.cpp +++ b/deps/icu-small/source/i18n/uspoof_build.cpp @@ -71,8 +71,29 @@ uspoof_openFromSource(const char *confusables, int32_t confusablesLen, // Set up a shell of a spoof detector, with empty data. SpoofData *newSpoofData = new SpoofData(*status); + + if (newSpoofData == NULL) { + *status = U_MEMORY_ALLOCATION_ERROR; + return NULL; + } + + if (U_FAILURE(*status)) { + delete newSpoofData; + return NULL; + } SpoofImpl *This = new SpoofImpl(newSpoofData, *status); + if (This == NULL) { + *status = U_MEMORY_ALLOCATION_ERROR; + delete newSpoofData; // explicit delete as the destructor for SpoofImpl won't be called. + return NULL; + } + + if (U_FAILURE(*status)) { + delete This; // no delete for newSpoofData, as the SpoofImpl destructor will delete it. + return NULL; + } + // Compile the binary data from the source (text) format. ConfusabledataBuilder::buildConfusableData(This, confusables, confusablesLen, errorType, pe, *status); diff --git a/deps/icu-small/source/i18n/uspoof_conf.cpp b/deps/icu-small/source/i18n/uspoof_conf.cpp index 3a061d9dfcf..672b3e0a6c8 100644 --- a/deps/icu-small/source/i18n/uspoof_conf.cpp +++ b/deps/icu-small/source/i18n/uspoof_conf.cpp @@ -76,6 +76,10 @@ SPUString::~SPUString() { SPUStringPool::SPUStringPool(UErrorCode &status) : fVec(NULL), fHash(NULL) { fVec = new UVector(status); + if (fVec == NULL) { + status = U_MEMORY_ALLOCATION_ERROR; + return; + } fHash = uhash_open(uhash_hashUnicodeString, // key hash function uhash_compareUnicodeString, // Key Comparator NULL, // Value Comparator @@ -136,6 +140,10 @@ SPUString *SPUStringPool::addString(UnicodeString *src, UErrorCode &status) { delete src; } else { hashedString = new SPUString(src); + if (hashedString == NULL) { + status = U_MEMORY_ALLOCATION_ERROR; + return NULL; + } uhash_put(fHash, src, hashedString, &status); fVec->addElement(hashedString, status); } @@ -160,11 +168,32 @@ ConfusabledataBuilder::ConfusabledataBuilder(SpoofImpl *spImpl, UErrorCode &stat if (U_FAILURE(status)) { return; } - fTable = uhash_open(uhash_hashLong, uhash_compareLong, NULL, &status); - fKeySet = new UnicodeSet(); - fKeyVec = new UVector(status); - fValueVec = new UVector(status); + + fTable = uhash_open(uhash_hashLong, uhash_compareLong, NULL, &status); + + fKeySet = new UnicodeSet(); + if (fKeySet == NULL) { + status = U_MEMORY_ALLOCATION_ERROR; + return; + } + + fKeyVec = new UVector(status); + if (fKeyVec == NULL) { + status = U_MEMORY_ALLOCATION_ERROR; + return; + } + + fValueVec = new UVector(status); + if (fValueVec == NULL) { + status = U_MEMORY_ALLOCATION_ERROR; + return; + } + stringPool = new SPUStringPool(status); + if (stringPool == NULL) { + status = U_MEMORY_ALLOCATION_ERROR; + return; + } } diff --git a/deps/icu-small/source/i18n/uspoof_impl.cpp b/deps/icu-small/source/i18n/uspoof_impl.cpp index 0ca85c00a98..c1034c2e53f 100644 --- a/deps/icu-small/source/i18n/uspoof_impl.cpp +++ b/deps/icu-small/source/i18n/uspoof_impl.cpp @@ -377,6 +377,43 @@ URestrictionLevel SpoofImpl::getRestrictionLevel(const UnicodeString& input, UEr return USPOOF_MINIMALLY_RESTRICTIVE; } +int32_t SpoofImpl::findHiddenOverlay(const UnicodeString& input, UErrorCode&) const { + bool sawLeadCharacter = false; + for (int32_t i=0; iconfusableLookup(cp, skelStr); + UChar32 finalCp = skelStr.char32At(skelStr.moveIndex32(skelStr.length(), -1)); + if (finalCp != cp && isIllegalCombiningDotLeadCharacterNoLookup(finalCp)) { + return true; + } + return false; +} + // Convert a text format hex number. Utility function used by builder code. Static. @@ -532,24 +569,25 @@ uspoof_cleanupDefaultData(void) { if (gDefaultSpoofData) { // Will delete, assuming all user-level spoof checkers were closed. gDefaultSpoofData->removeReference(); - gDefaultSpoofData = NULL; + gDefaultSpoofData = nullptr; gSpoofInitDefaultOnce.reset(); } return TRUE; } static void U_CALLCONV uspoof_loadDefaultData(UErrorCode& status) { - UDataMemory *udm = udata_openChoice(NULL, "cfu", "confusables", + UDataMemory *udm = udata_openChoice(nullptr, "cfu", "confusables", spoofDataIsAcceptable, - NULL, // context, would receive dataVersion if supplied. + nullptr, // context, would receive dataVersion if supplied. &status); if (U_FAILURE(status)) { return; } gDefaultSpoofData = new SpoofData(udm, status); if (U_FAILURE(status)) { delete gDefaultSpoofData; + gDefaultSpoofData = nullptr; return; } - if (gDefaultSpoofData == NULL) { + if (gDefaultSpoofData == nullptr) { status = U_MEMORY_ALLOCATION_ERROR; return; } @@ -590,6 +628,10 @@ SpoofData::SpoofData(const void *data, int32_t length, UErrorCode &status) status = U_INVALID_FORMAT_ERROR; return; } + if (data == NULL) { + status = U_ILLEGAL_ARGUMENT_ERROR; + return; + } void *ncData = const_cast(data); fRawData = static_cast(ncData); if (length < fRawData->fLength) { diff --git a/deps/icu-small/source/i18n/uspoof_impl.h b/deps/icu-small/source/i18n/uspoof_impl.h index 1184b8d9060..470a31f2c97 100644 --- a/deps/icu-small/source/i18n/uspoof_impl.h +++ b/deps/icu-small/source/i18n/uspoof_impl.h @@ -83,6 +83,9 @@ public: void getNumerics(const UnicodeString& input, UnicodeSet& result, UErrorCode& status) const; URestrictionLevel getRestrictionLevel(const UnicodeString& input, UErrorCode& status) const; + int32_t findHiddenOverlay(const UnicodeString& input, UErrorCode& status) const; + bool isIllegalCombiningDotLeadCharacter(UChar32 cp) const; + /** parse a hex number. Untility used by the builders. */ static UChar32 ScanHex(const UChar *s, int32_t start, int32_t limit, UErrorCode &status); diff --git a/deps/icu-small/source/i18n/valueformatter.cpp b/deps/icu-small/source/i18n/valueformatter.cpp deleted file mode 100644 index e769f369d48..00000000000 --- a/deps/icu-small/source/i18n/valueformatter.cpp +++ /dev/null @@ -1,223 +0,0 @@ -// © 2016 and later: Unicode, Inc. and others. -// License & terms of use: http://www.unicode.org/copyright.html -/* -******************************************************************************* -* Copyright (C) 2015, International Business Machines Corporation and -* others. All Rights Reserved. -******************************************************************************* -*/ - -#include "unicode/plurrule.h" -#include "unicode/unistr.h" -#include "unicode/utypes.h" - -#if !UCONFIG_NO_FORMATTING - -#include "digitformatter.h" -#include "digitgrouping.h" -#include "digitinterval.h" -#include "digitlst.h" -#include "precision.h" -#include "plurrule_impl.h" -#include "smallintformatter.h" -#include "uassert.h" -#include "valueformatter.h" -#include "visibledigits.h" - -U_NAMESPACE_BEGIN - -ValueFormatter::~ValueFormatter() {} - -VisibleDigitsWithExponent & -ValueFormatter::toVisibleDigitsWithExponent( - int64_t value, - VisibleDigitsWithExponent &digits, - UErrorCode &status) const { - switch (fType) { - case kFixedDecimal: - return fFixedPrecision->initVisibleDigitsWithExponent( - value, digits, status); - break; - case kScientificNotation: - return fScientificPrecision->initVisibleDigitsWithExponent( - value, digits, status); - break; - default: - U_ASSERT(FALSE); - break; - } - return digits; -} - -VisibleDigitsWithExponent & -ValueFormatter::toVisibleDigitsWithExponent( - DigitList &value, - VisibleDigitsWithExponent &digits, - UErrorCode &status) const { - switch (fType) { - case kFixedDecimal: - return fFixedPrecision->initVisibleDigitsWithExponent( - value, digits, status); - break; - case kScientificNotation: - return fScientificPrecision->initVisibleDigitsWithExponent( - value, digits, status); - break; - default: - U_ASSERT(FALSE); - break; - } - return digits; -} - -static UBool isNoGrouping( - const DigitGrouping &grouping, - int32_t value, - const FixedPrecision &precision) { - IntDigitCountRange range( - precision.fMin.getIntDigitCount(), - precision.fMax.getIntDigitCount()); - return grouping.isNoGrouping(value, range); -} - -UBool -ValueFormatter::isFastFormattable(int32_t value) const { - switch (fType) { - case kFixedDecimal: - { - if (value == INT32_MIN) { - return FALSE; - } - if (value < 0) { - value = -value; - } - return fFixedPrecision->isFastFormattable() && fFixedOptions->isFastFormattable() && isNoGrouping(*fGrouping, value, *fFixedPrecision); - } - case kScientificNotation: - return FALSE; - default: - U_ASSERT(FALSE); - break; - } - return FALSE; -} - -DigitList & -ValueFormatter::round(DigitList &value, UErrorCode &status) const { - if (value.isNaN() || value.isInfinite()) { - return value; - } - switch (fType) { - case kFixedDecimal: - return fFixedPrecision->round(value, 0, status); - case kScientificNotation: - return fScientificPrecision->round(value, status); - default: - U_ASSERT(FALSE); - break; - } - return value; -} - -UnicodeString & -ValueFormatter::formatInt32( - int32_t value, - FieldPositionHandler &handler, - UnicodeString &appendTo) const { - switch (fType) { - case kFixedDecimal: - { - IntDigitCountRange range( - fFixedPrecision->fMin.getIntDigitCount(), - fFixedPrecision->fMax.getIntDigitCount()); - return fDigitFormatter->formatPositiveInt32( - value, - range, - handler, - appendTo); - } - break; - case kScientificNotation: - default: - U_ASSERT(FALSE); - break; - } - return appendTo; -} - -UnicodeString & -ValueFormatter::format( - const VisibleDigitsWithExponent &value, - FieldPositionHandler &handler, - UnicodeString &appendTo) const { - switch (fType) { - case kFixedDecimal: - return fDigitFormatter->format( - value.getMantissa(), - *fGrouping, - *fFixedOptions, - handler, - appendTo); - break; - case kScientificNotation: - return fDigitFormatter->format( - value, - *fScientificOptions, - handler, - appendTo); - break; - default: - U_ASSERT(FALSE); - break; - } - return appendTo; -} - -int32_t -ValueFormatter::countChar32(const VisibleDigitsWithExponent &value) const { - switch (fType) { - case kFixedDecimal: - return fDigitFormatter->countChar32( - value.getMantissa(), - *fGrouping, - *fFixedOptions); - break; - case kScientificNotation: - return fDigitFormatter->countChar32( - value, - *fScientificOptions); - break; - default: - U_ASSERT(FALSE); - break; - } - return 0; -} - -void -ValueFormatter::prepareFixedDecimalFormatting( - const DigitFormatter &formatter, - const DigitGrouping &grouping, - const FixedPrecision &precision, - const DigitFormatterOptions &options) { - fType = kFixedDecimal; - fDigitFormatter = &formatter; - fGrouping = &grouping; - fFixedPrecision = &precision; - fFixedOptions = &options; -} - -void -ValueFormatter::prepareScientificFormatting( - const DigitFormatter &formatter, - const ScientificPrecision &precision, - const SciFormatterOptions &options) { - fType = kScientificNotation; - fDigitFormatter = &formatter; - fScientificPrecision = &precision; - fScientificOptions = &options; -} - -U_NAMESPACE_END - -#endif /* !UCONFIG_NO_FORMATTING */ diff --git a/deps/icu-small/source/i18n/valueformatter.h b/deps/icu-small/source/i18n/valueformatter.h deleted file mode 100644 index 836a05b17c5..00000000000 --- a/deps/icu-small/source/i18n/valueformatter.h +++ /dev/null @@ -1,161 +0,0 @@ -// © 2016 and later: Unicode, Inc. and others. -// License & terms of use: http://www.unicode.org/copyright.html -/* -******************************************************************************* -* Copyright (C) 2015, International Business Machines Corporation and * -* others. All Rights Reserved. * -******************************************************************************* -*/ - -#ifndef VALUEFORMATTER_H -#define VALUEFORMATTER_H - -#if !UCONFIG_NO_FORMATTING - -#include "unicode/uobject.h" -#include "unicode/utypes.h" - - - -U_NAMESPACE_BEGIN - -class UnicodeString; -class DigitList; -class FieldPositionHandler; -class DigitGrouping; -class PluralRules; -class FixedPrecision; -class DigitFormatter; -class DigitFormatterOptions; -class ScientificPrecision; -class SciFormatterOptions; -class FixedDecimal; -class VisibleDigitsWithExponent; - - -/** - * A closure around rounding and formatting a value. As these instances are - * designed to be short lived (they only exist while formatting a value), they - * do not own their own attributes. Rather the caller maintains ownership of - * all attributes. A caller first calls a prepareXXX method on an instance - * to share its data before using that instance. Using an - * instance without first calling a prepareXXX method results in an - * assertion error and a program crash. - */ -class U_I18N_API ValueFormatter : public UObject { -public: - ValueFormatter() : fType(kFormatTypeCount) { - } - - virtual ~ValueFormatter(); - - /** - * This function is here only to support the protected round() method - * in DecimalFormat. It serves no ther purpose than that. - * - * @param value this value is rounded in place. - * @param status any error returned here. - */ - DigitList &round(DigitList &value, UErrorCode &status) const; - - /** - * Returns TRUE if the absolute value of value can be fast formatted - * using ValueFormatter::formatInt32. - */ - UBool isFastFormattable(int32_t value) const; - - /** - * Converts value to a VisibleDigitsWithExponent. - * Result may be fixed point or scientific. - */ - VisibleDigitsWithExponent &toVisibleDigitsWithExponent( - int64_t value, - VisibleDigitsWithExponent &digits, - UErrorCode &status) const; - - /** - * Converts value to a VisibleDigitsWithExponent. - * Result may be fixed point or scientific. - */ - VisibleDigitsWithExponent &toVisibleDigitsWithExponent( - DigitList &value, - VisibleDigitsWithExponent &digits, - UErrorCode &status) const; - - /** - * formats positiveValue and appends to appendTo. Returns appendTo. - * @param positiveValue If negative, no negative sign is formatted. - * @param handler stores the field positions - * @param appendTo formatted value appended here. - */ - UnicodeString &format( - const VisibleDigitsWithExponent &positiveValue, - FieldPositionHandler &handler, - UnicodeString &appendTo) const; - - - /** - * formats positiveValue and appends to appendTo. Returns appendTo. - * value must be positive. Calling formatInt32 to format a value when - * isFastFormattable indicates that the value cannot be fast formatted - * results in undefined behavior. - */ - UnicodeString &formatInt32( - int32_t positiveValue, - FieldPositionHandler &handler, - UnicodeString &appendTo) const; - - /** - * Returns the number of code points needed to format. - * @param positiveValue if negative, the negative sign is not included - * in count. - */ - int32_t countChar32( - const VisibleDigitsWithExponent &positiveValue) const; - - /** - * Prepares this instance for fixed decimal formatting. - */ - void prepareFixedDecimalFormatting( - const DigitFormatter &formatter, - const DigitGrouping &grouping, - const FixedPrecision &precision, - const DigitFormatterOptions &options); - - /** - * Prepares this instance for scientific formatting. - */ - void prepareScientificFormatting( - const DigitFormatter &formatter, - const ScientificPrecision &precision, - const SciFormatterOptions &options); - -private: - ValueFormatter(const ValueFormatter &); - ValueFormatter &operator=(const ValueFormatter &); - enum FormatType { - kFixedDecimal, - kScientificNotation, - kFormatTypeCount - }; - - FormatType fType; - - // for fixed decimal and scientific formatting - const DigitFormatter *fDigitFormatter; - - // for fixed decimal formatting - const FixedPrecision *fFixedPrecision; - const DigitFormatterOptions *fFixedOptions; - const DigitGrouping *fGrouping; - - // for scientific formatting - const ScientificPrecision *fScientificPrecision; - const SciFormatterOptions *fScientificOptions; -}; - -U_NAMESPACE_END - -#endif /* !UCONFIG_NO_FORMATTING */ - -#endif /* VALUEFORMATTER_H */ diff --git a/deps/icu-small/source/i18n/visibledigits.cpp b/deps/icu-small/source/i18n/visibledigits.cpp deleted file mode 100644 index 03cfc68d255..00000000000 --- a/deps/icu-small/source/i18n/visibledigits.cpp +++ /dev/null @@ -1,186 +0,0 @@ -// © 2016 and later: Unicode, Inc. and others. -// License & terms of use: http://www.unicode.org/copyright.html -/* - * Copyright (C) 2016, International Business Machines - * Corporation and others. All Rights Reserved. - * - * file name: visibledigits.cpp - */ - -#include - -#include "unicode/utypes.h" - -#if !UCONFIG_NO_FORMATTING - -#include "cstring.h" -#include "decNumber.h" -#include "digitlst.h" -#include "uassert.h" -#include "visibledigits.h" - -static const int32_t kNegative = 1; -static const int32_t kInfinite = 2; -static const int32_t kNaN = 4; - -U_NAMESPACE_BEGIN - -void VisibleDigits::setNegative() { - fFlags |= kNegative; -} - -void VisibleDigits::setNaN() { - fFlags |= kNaN; -} - -void VisibleDigits::setInfinite() { - fFlags |= kInfinite; -} - -void VisibleDigits::clear() { - fInterval.clear(); - fDigits.clear(); - fExponent = 0; - fFlags = 0; - fAbsIntValue = 0LL; - fAbsIntValueSet = FALSE; - fAbsDoubleValue = 0.0; - fAbsDoubleValueSet = FALSE; -} - -UBool VisibleDigits::isNegative() const { - return (fFlags & kNegative); -} - -UBool VisibleDigits::isNaN() const { - return (fFlags & kNaN); -} - -UBool VisibleDigits::isInfinite() const { - return (fFlags & kInfinite); -} - -int32_t VisibleDigits::getDigitByExponent(int32_t digitPos) const { - if (digitPos < fExponent || digitPos >= fExponent + fDigits.length()) { - return 0; - } - const char *ptr = fDigits.data(); - return ptr[digitPos - fExponent]; -} - -UBool VisibleDigits::isOverMaxDigits() const { - return (fExponent + fDigits.length() > fInterval.getMostSignificantExclusive()); -} - -UBool VisibleDigits::isNaNOrInfinity() const { - return (fFlags & (kInfinite | kNaN)) != 0; -} - -double VisibleDigits::computeAbsDoubleValue() const { - // Take care of NaN and infinity - if (isNaN()) { - return uprv_getNaN(); - } - if (isInfinite()) { - return uprv_getInfinity(); - } - - // stack allocate a decNumber to hold MAX_DBL_DIGITS+3 significant digits - struct { - decNumber decNum; - char digits[MAX_DBL_DIGITS+3]; - } decNumberWithStorage; - decNumber *numberPtr = &decNumberWithStorage.decNum; - - int32_t mostSig = fInterval.getMostSignificantExclusive(); - int32_t mostSigNonZero = fExponent + fDigits.length(); - int32_t end = mostSig > mostSigNonZero ? mostSigNonZero : mostSig; - int32_t leastSig = fInterval.getLeastSignificantInclusive(); - int32_t start = leastSig > fExponent ? leastSig : fExponent; - if (end <= start) { - return 0.0; - } - if (start < end - (MAX_DBL_DIGITS+3)) { - start = end - (MAX_DBL_DIGITS+3); - } - uint8_t *pos = numberPtr->lsu; - const char *src = &(fDigits.data()[start - fExponent]); - for (int32_t i = start; i < end; ++i) { - *pos++ = (uint8_t) (*src++); - } - numberPtr->exponent = start; - numberPtr->bits = 0; - numberPtr->digits = end - start; - char str[MAX_DBL_DIGITS+18]; - uprv_decNumberToString(numberPtr, str); - U_ASSERT(uprv_strlen(str) < MAX_DBL_DIGITS+18); - char *unused = NULL; - return DigitList::decimalStrToDouble(str, &unused); -} - -void VisibleDigits::getFixedDecimal( - double &source, int64_t &intValue, int64_t &f, int64_t &t, int32_t &v, UBool &hasIntValue) const { - source = 0.0; - intValue = 0; - f = 0; - t = 0; - v = 0; - hasIntValue = FALSE; - if (isNaNOrInfinity()) { - return; - } - - // source - if (fAbsDoubleValueSet) { - source = fAbsDoubleValue; - } else { - source = computeAbsDoubleValue(); - } - - // visible decimal digits - v = fInterval.getFracDigitCount(); - - // intValue - - // If we initialized from an int64 just use that instead of - // calculating - if (fAbsIntValueSet) { - intValue = fAbsIntValue; - } else { - int32_t startPos = fInterval.getMostSignificantExclusive(); - if (startPos > 18) { - startPos = 18; - } - // process the integer digits - for (int32_t i = startPos - 1; i >= 0; --i) { - intValue = intValue * 10LL + getDigitByExponent(i); - } - if (intValue == 0LL && startPos > 0) { - intValue = 100000000000000000LL; - } - } - - // f (decimal digits) - // skip over any leading 0's in fraction digits. - int32_t idx = -1; - for (; idx >= -v && getDigitByExponent(idx) == 0; --idx) - ; - - // Only process up to first 18 non zero fraction digits for decimalDigits - // since that is all we can fit into an int64. - for (int32_t i = idx; i >= -v && i > idx - 18; --i) { - f = f * 10LL + getDigitByExponent(i); - } - - // If we have no decimal digits, we don't have an integer value - hasIntValue = (f == 0LL); - - // t (decimal digits without trailing zeros) - t = f; - while (t > 0 && t % 10LL == 0) { - t /= 10; - } -} - -U_NAMESPACE_END -#endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/deps/icu-small/source/i18n/visibledigits.h b/deps/icu-small/source/i18n/visibledigits.h deleted file mode 100644 index 03c8013e393..00000000000 --- a/deps/icu-small/source/i18n/visibledigits.h +++ /dev/null @@ -1,162 +0,0 @@ -// © 2016 and later: Unicode, Inc. and others. -// License & terms of use: http://www.unicode.org/copyright.html -/* -******************************************************************************* * Copyright (C) 2015, International Business Machines -* Corporation and others. All Rights Reserved. -******************************************************************************* -* visibledigits.h -* -* created on: 2015jun20 -* created by: Travis Keep -*/ - -#ifndef __VISIBLEDIGITS_H__ -#define __VISIBLEDIGITS_H__ - -#include "unicode/utypes.h" - -#if !UCONFIG_NO_FORMATTING - -#include "unicode/uobject.h" - -#include "charstr.h" -#include "digitinterval.h" - -U_NAMESPACE_BEGIN - -class DigitList; - -/** - * VisibleDigits represents the digits visible for formatting. - * Once initialized using a FixedPrecision instance, VisibleDigits instances - * remain unchanged until they are initialized again. A VisibleDigits with - * a numeric value equal to 3.0 could be "3", "3.0", "3.00" or even "003.0" - * depending on settings of the FixedPrecision instance used to initialize it. - */ -class U_I18N_API VisibleDigits : public UMemory { -public: - VisibleDigits() : fExponent(0), fFlags(0), fAbsIntValue(0), fAbsIntValueSet(FALSE), fAbsDoubleValue(0.0), fAbsDoubleValueSet(FALSE) { } - - UBool isNegative() const; - UBool isNaN() const; - UBool isInfinite() const; - UBool isNaNOrInfinity() const; - - /** - * Gets the digit at particular exponent, if number is 987.6, then - * getDigit(2) == 9 and gitDigit(0) == 7 and gitDigit(-1) == 6. - * If isNaN() or isInfinity() return TRUE, then the result of this - * function is undefined. - */ - int32_t getDigitByExponent(int32_t digitPos) const; - - /** - * Returns the digit interval which indicates the leftmost and rightmost - * position of this instance. - * If isNaN() or isInfinity() return TRUE, then the result of this - * function is undefined. - */ - const DigitInterval &getInterval() const { return fInterval; } - - /** - * Gets the parameters needed to create a FixedDecimal. - */ - void getFixedDecimal(double &source, int64_t &intValue, int64_t &f, int64_t &t, int32_t &v, UBool &hasIntValue) const; - - -private: - /** - * The digits, least significant first. Both the least and most - * significant digit in this list are non-zero; however, digits in the - * middle may be zero. This field contains values between (char) 0, and - * (char) 9 inclusive. - */ - CharString fDigits; - - /** - * The range of displayable digits. This field is needed to account for - * any leading and trailing zeros which are not stored in fDigits. - */ - DigitInterval fInterval; - - /** - * The exponent value of the least significant digit in fDigits. For - * example, fExponent = 2 and fDigits = {7, 8, 5} represents 58700. - */ - int32_t fExponent; - - /** - * Contains flags such as NaN, Inf, and negative. - */ - int32_t fFlags; - - /** - * Contains the absolute value of the digits left of the decimal place - * if fAbsIntValueSet is TRUE - */ - int64_t fAbsIntValue; - - /** - * Indicates whether or not fAbsIntValue is set. - */ - UBool fAbsIntValueSet; - - /** - * Contains the absolute value of the value this instance represents - * if fAbsDoubleValueSet is TRUE - */ - double fAbsDoubleValue; - - /** - * Indicates whether or not fAbsDoubleValue is set. - */ - UBool fAbsDoubleValueSet; - - void setNegative(); - void setNaN(); - void setInfinite(); - void clear(); - double computeAbsDoubleValue() const; - UBool isOverMaxDigits() const; - - VisibleDigits(const VisibleDigits &); - VisibleDigits &operator=(const VisibleDigits &); - - friend class FixedPrecision; - friend class VisibleDigitsWithExponent; -}; - -/** - * A VisibleDigits with a possible exponent. - */ -class U_I18N_API VisibleDigitsWithExponent : public UMemory { -public: - VisibleDigitsWithExponent() : fHasExponent(FALSE) { } - const VisibleDigits &getMantissa() const { return fMantissa; } - const VisibleDigits *getExponent() const { - return fHasExponent ? &fExponent : NULL; - } - void clear() { - fMantissa.clear(); - fExponent.clear(); - fHasExponent = FALSE; - } - UBool isNegative() const { return fMantissa.isNegative(); } - UBool isNaN() const { return fMantissa.isNaN(); } - UBool isInfinite() const { return fMantissa.isInfinite(); } -private: - VisibleDigitsWithExponent(const VisibleDigitsWithExponent &); - VisibleDigitsWithExponent &operator=( - const VisibleDigitsWithExponent &); - VisibleDigits fMantissa; - VisibleDigits fExponent; - UBool fHasExponent; - - friend class ScientificPrecision; - friend class FixedPrecision; -}; - - -U_NAMESPACE_END -#endif /* #if !UCONFIG_NO_FORMATTING */ -#endif // __VISIBLEDIGITS_H__ diff --git a/deps/icu-small/source/i18n/windtfmt.cpp b/deps/icu-small/source/i18n/windtfmt.cpp index e8e32abd3ff..983fd46c122 100644 --- a/deps/icu-small/source/i18n/windtfmt.cpp +++ b/deps/icu-small/source/i18n/windtfmt.cpp @@ -385,7 +385,8 @@ UnicodeString Win32DateFormat::setTimeZoneInfo(TIME_ZONE_INFORMATION *tzi, const for (int z = 0; z < ec; z += 1) { UnicodeString equiv = TimeZone::getEquivalentID(icuid, z); - if (found = uprv_getWindowsTimeZoneInfo(tzi, equiv.getBuffer(), equiv.length())) { + found = uprv_getWindowsTimeZoneInfo(tzi, equiv.getBuffer(), equiv.length()); + if (found) { break; } } diff --git a/deps/icu-small/source/i18n/zonemeta.cpp b/deps/icu-small/source/i18n/zonemeta.cpp index c386b0cae5e..02562048a52 100644 --- a/deps/icu-small/source/i18n/zonemeta.cpp +++ b/deps/icu-small/source/i18n/zonemeta.cpp @@ -690,6 +690,7 @@ ZoneMeta::createMetazoneMappings(const UnicodeString &tzid) { mzMappings = new UVector(deleteOlsonToMetaMappingEntry, NULL, status); if (U_FAILURE(status)) { delete mzMappings; + mzMappings = NULL; uprv_free(entry); break; } diff --git a/deps/icu-small/source/tools/toolutil/swapimpl.cpp b/deps/icu-small/source/tools/toolutil/swapimpl.cpp index a64a6a1703f..f3f333a005e 100644 --- a/deps/icu-small/source/tools/toolutil/swapimpl.cpp +++ b/deps/icu-small/source/tools/toolutil/swapimpl.cpp @@ -336,7 +336,7 @@ ucase_swap(const UDataSwapper *ds, ((pInfo->formatVersion[0]==1 && pInfo->formatVersion[2]==UTRIE_SHIFT && pInfo->formatVersion[3]==UTRIE_INDEX_SHIFT) || - pInfo->formatVersion[0]==2 || pInfo->formatVersion[0]==3) + 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], diff --git a/deps/icu-small/source/tools/toolutil/udbgutil.cpp b/deps/icu-small/source/tools/toolutil/udbgutil.cpp index 446e11aaf90..dcc80ebe069 100644 --- a/deps/icu-small/source/tools/toolutil/udbgutil.cpp +++ b/deps/icu-small/source/tools/toolutil/udbgutil.cpp @@ -554,7 +554,6 @@ static const USystemParams systemParams[] = { #endif { "uconfig.internal_digitlist", paramInteger, "b", 1}, /* always 1 */ { "uconfig.have_parseallinput", paramInteger, "b", UCONFIG_HAVE_PARSEALLINPUT}, - { "uconfig.format_fastpaths_49",paramInteger, "b", UCONFIG_FORMAT_FASTPATHS_49}, };