summaryrefslogtreecommitdiff
path: root/Build/source/libs/icu/icu-src/source/i18n
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/libs/icu/icu-src/source/i18n')
-rw-r--r--Build/source/libs/icu/icu-src/source/i18n/Makefile.in4
-rw-r--r--Build/source/libs/icu/icu-src/source/i18n/alphaindex.cpp13
-rw-r--r--Build/source/libs/icu/icu-src/source/i18n/calendar.cpp8
-rw-r--r--Build/source/libs/icu/icu-src/source/i18n/collationiterator.h6
-rw-r--r--Build/source/libs/icu/icu-src/source/i18n/dcfmtsym.cpp23
-rw-r--r--Build/source/libs/icu/icu-src/source/i18n/decNumber.cpp4
-rw-r--r--Build/source/libs/icu/icu-src/source/i18n/decimalformatpattern.cpp10
-rw-r--r--Build/source/libs/icu/icu-src/source/i18n/digitlst.cpp50
-rw-r--r--Build/source/libs/icu/icu-src/source/i18n/double-conversion-bignum-dtoa.cpp659
-rw-r--r--Build/source/libs/icu/icu-src/source/i18n/double-conversion-bignum-dtoa.h102
-rw-r--r--Build/source/libs/icu/icu-src/source/i18n/double-conversion-bignum.cpp784
-rw-r--r--Build/source/libs/icu/icu-src/source/i18n/double-conversion-bignum.h162
-rw-r--r--Build/source/libs/icu/icu-src/source/i18n/double-conversion-cached-powers.cpp193
-rw-r--r--Build/source/libs/icu/icu-src/source/i18n/double-conversion-cached-powers.h82
-rw-r--r--Build/source/libs/icu/icu-src/source/i18n/double-conversion-diy-fp.cpp74
-rw-r--r--Build/source/libs/icu/icu-src/source/i18n/double-conversion-diy-fp.h136
-rw-r--r--Build/source/libs/icu/icu-src/source/i18n/double-conversion-fast-dtoa.cpp683
-rw-r--r--Build/source/libs/icu/icu-src/source/i18n/double-conversion-fast-dtoa.h106
-rw-r--r--Build/source/libs/icu/icu-src/source/i18n/double-conversion-ieee.h420
-rw-r--r--Build/source/libs/icu/icu-src/source/i18n/double-conversion-utils.h358
-rw-r--r--Build/source/libs/icu/icu-src/source/i18n/double-conversion.cpp1005
-rw-r--r--Build/source/libs/icu/icu-src/source/i18n/double-conversion.h566
-rw-r--r--Build/source/libs/icu/icu-src/source/i18n/dtptngen.cpp90
-rw-r--r--Build/source/libs/icu/icu-src/source/i18n/i18n.vcxproj1328
-rw-r--r--Build/source/libs/icu/icu-src/source/i18n/i18n.vcxproj.filters110
-rw-r--r--Build/source/libs/icu/icu-src/source/i18n/i18n_uwp.vcxproj443
-rw-r--r--Build/source/libs/icu/icu-src/source/i18n/islamcal.cpp2
-rw-r--r--Build/source/libs/icu/icu-src/source/i18n/measfmt.cpp13
-rw-r--r--Build/source/libs/icu/icu-src/source/i18n/measunit.cpp11
-rw-r--r--Build/source/libs/icu/icu-src/source/i18n/nfrs.cpp11
-rw-r--r--Build/source/libs/icu/icu-src/source/i18n/nfrs.h2
-rw-r--r--Build/source/libs/icu/icu-src/source/i18n/nfrule.cpp6
-rw-r--r--Build/source/libs/icu/icu-src/source/i18n/nfrule.h2
-rw-r--r--Build/source/libs/icu/icu-src/source/i18n/nfsubs.cpp21
-rw-r--r--Build/source/libs/icu/icu-src/source/i18n/nfsubs.h1
-rw-r--r--Build/source/libs/icu/icu-src/source/i18n/number_affixutils.cpp1
-rw-r--r--Build/source/libs/icu/icu-src/source/i18n/number_compact.cpp7
-rw-r--r--Build/source/libs/icu/icu-src/source/i18n/number_compact.h1
-rw-r--r--Build/source/libs/icu/icu-src/source/i18n/number_decimalquantity.cpp67
-rw-r--r--Build/source/libs/icu/icu-src/source/i18n/number_decimalquantity.h5
-rw-r--r--Build/source/libs/icu/icu-src/source/i18n/number_decimfmtprops.h4
-rw-r--r--Build/source/libs/icu/icu-src/source/i18n/number_fluent.cpp31
-rw-r--r--Build/source/libs/icu/icu-src/source/i18n/number_formatimpl.cpp109
-rw-r--r--Build/source/libs/icu/icu-src/source/i18n/number_grouping.cpp60
-rw-r--r--Build/source/libs/icu/icu-src/source/i18n/number_integerwidth.cpp15
-rw-r--r--Build/source/libs/icu/icu-src/source/i18n/number_longnames.cpp150
-rw-r--r--Build/source/libs/icu/icu-src/source/i18n/number_longnames.h12
-rw-r--r--Build/source/libs/icu/icu-src/source/i18n/number_modifiers.cpp76
-rw-r--r--Build/source/libs/icu/icu-src/source/i18n/number_modifiers.h47
-rw-r--r--Build/source/libs/icu/icu-src/source/i18n/number_notation.cpp6
-rw-r--r--Build/source/libs/icu/icu-src/source/i18n/number_padding.cpp2
-rw-r--r--Build/source/libs/icu/icu-src/source/i18n/number_patternmodifier.cpp72
-rw-r--r--Build/source/libs/icu/icu-src/source/i18n/number_patternmodifier.h16
-rw-r--r--Build/source/libs/icu/icu-src/source/i18n/number_patternstring.cpp4
-rw-r--r--Build/source/libs/icu/icu-src/source/i18n/number_patternstring.h2
-rw-r--r--Build/source/libs/icu/icu-src/source/i18n/number_rounding.cpp96
-rw-r--r--Build/source/libs/icu/icu-src/source/i18n/number_stringbuilder.cpp37
-rw-r--r--Build/source/libs/icu/icu-src/source/i18n/number_stringbuilder.h5
-rw-r--r--Build/source/libs/icu/icu-src/source/i18n/number_types.h24
-rw-r--r--Build/source/libs/icu/icu-src/source/i18n/rbnf.cpp2
-rw-r--r--Build/source/libs/icu/icu-src/source/i18n/regexcmp.cpp6
-rw-r--r--Build/source/libs/icu/icu-src/source/i18n/rematch.cpp11
-rw-r--r--Build/source/libs/icu/icu-src/source/i18n/simpletz.cpp4
-rw-r--r--Build/source/libs/icu/icu-src/source/i18n/ucol.cpp1
-rw-r--r--Build/source/libs/icu/icu-src/source/i18n/ucol_res.cpp1
-rw-r--r--Build/source/libs/icu/icu-src/source/i18n/udatpg.cpp19
-rw-r--r--Build/source/libs/icu/icu-src/source/i18n/unicode/compactdecimalformat.h10
-rw-r--r--Build/source/libs/icu/icu-src/source/i18n/unicode/datefmt.h3
-rw-r--r--Build/source/libs/icu/icu-src/source/i18n/unicode/dcfmtsym.h67
-rw-r--r--Build/source/libs/icu/icu-src/source/i18n/unicode/decimfmt.h27
-rw-r--r--Build/source/libs/icu/icu-src/source/i18n/unicode/dtptngen.h30
-rw-r--r--Build/source/libs/icu/icu-src/source/i18n/unicode/measfmt.h19
-rw-r--r--Build/source/libs/icu/icu-src/source/i18n/unicode/measunit.h8
-rw-r--r--Build/source/libs/icu/icu-src/source/i18n/unicode/nounit.h10
-rw-r--r--Build/source/libs/icu/icu-src/source/i18n/unicode/numberformatter.h418
-rw-r--r--Build/source/libs/icu/icu-src/source/i18n/unicode/numfmt.h37
-rw-r--r--Build/source/libs/icu/icu-src/source/i18n/unicode/simpletz.h6
-rw-r--r--Build/source/libs/icu/icu-src/source/i18n/unicode/udatpg.h53
-rw-r--r--Build/source/libs/icu/icu-src/source/i18n/unicode/unum.h9
-rw-r--r--Build/source/libs/icu/icu-src/source/i18n/unicode/upluralrules.h6
-rw-r--r--Build/source/libs/icu/icu-src/source/i18n/unicode/utrans.h4
-rw-r--r--Build/source/libs/icu/icu-src/source/i18n/uregex.cpp6
-rw-r--r--Build/source/libs/icu/icu-src/source/i18n/utrans.cpp10
83 files changed, 6941 insertions, 2163 deletions
diff --git a/Build/source/libs/icu/icu-src/source/i18n/Makefile.in b/Build/source/libs/icu/icu-src/source/i18n/Makefile.in
index dda6050af53..e52be377e04 100644
--- a/Build/source/libs/icu/icu-src/source/i18n/Makefile.in
+++ b/Build/source/libs/icu/icu-src/source/i18n/Makefile.in
@@ -107,7 +107,9 @@ number_affixutils.o number_compact.o number_decimalquantity.o \
number_decimfmtprops.o number_fluent.o number_formatimpl.o number_grouping.o \
number_integerwidth.o number_longnames.o number_modifiers.o number_notation.o \
number_padding.o number_patternmodifier.o number_patternstring.o \
-number_rounding.o number_scientific.o number_stringbuilder.o
+number_rounding.o number_scientific.o number_stringbuilder.o \
+double-conversion.o double-conversion-bignum-dtoa.o double-conversion-bignum.o \
+double-conversion-cached-powers.o double-conversion-diy-fp.o double-conversion-fast-dtoa.o
## Header files to install
diff --git a/Build/source/libs/icu/icu-src/source/i18n/alphaindex.cpp b/Build/source/libs/icu/icu-src/source/i18n/alphaindex.cpp
index d877cb2a991..d36a2cc6de3 100644
--- a/Build/source/libs/icu/icu-src/source/i18n/alphaindex.cpp
+++ b/Build/source/libs/icu/icu-src/source/i18n/alphaindex.cpp
@@ -725,7 +725,7 @@ void AlphabeticIndex::addIndexExemplars(const Locale &locale, UErrorCode &status
}
// question: should we add auxiliary exemplars?
- if (exemplars.containsSome(0x61, 0x7A) /* a-z */ || exemplars.size() == 0) {
+ if (exemplars.containsSome(0x61, 0x7A) /* a-z */ || exemplars.isEmpty()) {
exemplars.add(0x61, 0x7A);
}
if (exemplars.containsSome(0xAC00, 0xD7A3)) { // Hangul syllables
@@ -740,14 +740,9 @@ void AlphabeticIndex::addIndexExemplars(const Locale &locale, UErrorCode &status
// cut down to small list
// make use of the fact that Ethiopic is allocated in 8's, where
// the base is 0 mod 8.
- UnicodeSet ethiopic(
- UNICODE_STRING_SIMPLE("[[:Block=Ethiopic:]&[:Script=Ethiopic:]]"), status);
- UnicodeSetIterator it(ethiopic);
- while (it.next() && !it.isString()) {
- if ((it.getCodepoint() & 0x7) != 0) {
- exemplars.remove(it.getCodepoint());
- }
- }
+ UnicodeSet ethiopic(UnicodeString(u"[ሀለሐመሠረሰሸቀቈቐቘበቨተቸኀኈነኘአከኰኸዀወዐዘዠየደዸጀገጐጘጠጨጰጸፀፈፐፘ]"), status);
+ ethiopic.retainAll(exemplars);
+ exemplars.remove(u'ሀ', 0x137F).addAll(ethiopic);
}
// Upper-case any that aren't already so.
diff --git a/Build/source/libs/icu/icu-src/source/i18n/calendar.cpp b/Build/source/libs/icu/icu-src/source/i18n/calendar.cpp
index 092dc4c1d9e..526a5a70b4a 100644
--- a/Build/source/libs/icu/icu-src/source/i18n/calendar.cpp
+++ b/Build/source/libs/icu/icu-src/source/i18n/calendar.cpp
@@ -3223,14 +3223,14 @@ int32_t Calendar::handleComputeJulianDay(UCalendarDateFields bestField) {
bestField == UCAL_DAY_OF_WEEK_IN_MONTH);
int32_t year;
- if (bestField == UCAL_WEEK_OF_YEAR) {
- year = internalGet(UCAL_YEAR_WOY, handleGetExtendedYear());
- internalSet(UCAL_EXTENDED_YEAR, year);
+ if (bestField == UCAL_WEEK_OF_YEAR && newerField(UCAL_YEAR_WOY, UCAL_YEAR) == UCAL_YEAR_WOY) {
+ year = internalGet(UCAL_YEAR_WOY);
} else {
year = handleGetExtendedYear();
- internalSet(UCAL_EXTENDED_YEAR, year);
}
+ internalSet(UCAL_EXTENDED_YEAR, year);
+
#if defined (U_DEBUG_CAL)
fprintf(stderr, "%s:%d: bestField= %s - y=%d\n", __FILE__, __LINE__, fldName(bestField), year);
#endif
diff --git a/Build/source/libs/icu/icu-src/source/i18n/collationiterator.h b/Build/source/libs/icu/icu-src/source/i18n/collationiterator.h
index ff6e5ecea8e..12e05b4482f 100644
--- a/Build/source/libs/icu/icu-src/source/i18n/collationiterator.h
+++ b/Build/source/libs/icu/icu-src/source/i18n/collationiterator.h
@@ -34,12 +34,12 @@ class UVector32;
// Export an explicit template instantiation of the MaybeStackArray that
// is used as a data member of CEBuffer.
//
-// MSVC requires this, even though it should not be necessary.
-// No direct access to the MaybeStackArray leaks out of the i18n library.
+// 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 defined (_MSC_VER)
+#if U_PF_WINDOWS <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN
template class U_I18N_API MaybeStackArray<int64_t, CEBUFFER_INITIAL_CAPACITY>;
#endif
diff --git a/Build/source/libs/icu/icu-src/source/i18n/dcfmtsym.cpp b/Build/source/libs/icu/icu-src/source/i18n/dcfmtsym.cpp
index d321a82f8a9..a2cc58c4151 100644
--- a/Build/source/libs/icu/icu-src/source/i18n/dcfmtsym.cpp
+++ b/Build/source/libs/icu/icu-src/source/i18n/dcfmtsym.cpp
@@ -38,6 +38,7 @@
#include "uresimp.h"
#include "ureslocs.h"
#include "charstr.h"
+#include "uassert.h"
// *****************************************************************************
// class DecimalFormatSymbols
@@ -165,6 +166,7 @@ DecimalFormatSymbols::operator=(const DecimalFormatSymbols& rhs)
uprv_strcpy(actualLocale, rhs.actualLocale);
fIsCustomCurrencySymbol = rhs.fIsCustomCurrencySymbol;
fIsCustomIntlCurrencySymbol = rhs.fIsCustomIntlCurrencySymbol;
+ fCodePointZero = rhs.fCodePointZero;
}
return *this;
}
@@ -196,6 +198,7 @@ DecimalFormatSymbols::operator==(const DecimalFormatSymbols& that) const
return FALSE;
}
}
+ // No need to check fCodePointZero since it is based on fSymbols
return locale == that.locale &&
uprv_strcmp(validLocale, that.validLocale) == 0 &&
uprv_strcmp(actualLocale, that.actualLocale) == 0;
@@ -433,6 +436,24 @@ DecimalFormatSymbols::initialize(const Locale& loc, UErrorCode& status,
// Let the monetary number separators equal the default number separators if necessary.
sink.resolveMissingMonetarySeparators(fSymbols);
+ // Resolve codePointZero
+ UChar32 tempCodePointZero;
+ for (int32_t i=0; i<=9; i++) {
+ const UnicodeString& stringDigit = getConstDigitSymbol(i);
+ if (stringDigit.countChar32() != 1) {
+ tempCodePointZero = -1;
+ break;
+ }
+ UChar32 cp = stringDigit.char32At(0);
+ if (i == 0) {
+ tempCodePointZero = cp;
+ } else if (cp != tempCodePointZero + i) {
+ tempCodePointZero = -1;
+ break;
+ }
+ }
+ fCodePointZero = tempCodePointZero;
+
// Obtain currency data from the currency API. This is strictly
// for backward compatibility; we don't use DecimalFormatSymbols
// for currency data anymore.
@@ -530,6 +551,8 @@ DecimalFormatSymbols::initialize() {
fSymbols[kExponentMultiplicationSymbol] = (UChar)0xd7; // 'x' multiplication symbol for exponents
fIsCustomCurrencySymbol = FALSE;
fIsCustomIntlCurrencySymbol = FALSE;
+ fCodePointZero = 0x30;
+ U_ASSERT(fCodePointZero == fSymbols[kZeroDigitSymbol].char32At(0));
}
diff --git a/Build/source/libs/icu/icu-src/source/i18n/decNumber.cpp b/Build/source/libs/icu/icu-src/source/i18n/decNumber.cpp
index 149062e0921..cee2f8e9498 100644
--- a/Build/source/libs/icu/icu-src/source/i18n/decNumber.cpp
+++ b/Build/source/libs/icu/icu-src/source/i18n/decNumber.cpp
@@ -627,10 +627,12 @@ U_CAPI decNumber * U_EXPORT2 uprv_decNumberFromString(decNumber *dn, const char
for (; *c=='0' && *(c+1)!='\0';) c++; /* strip insignificant zeros */
firstexp=c; /* save exponent digit place */
+ uInt uexponent = 0; /* Avoid undefined behavior on signed int overflow */
for (; ;c++) {
if (*c<'0' || *c>'9') break; /* not a digit */
- exponent=X10(exponent)+(Int)*c-(Int)'0';
+ uexponent=X10(uexponent)+(uInt)*c-(uInt)'0';
} /* c */
+ exponent = (Int)uexponent;
/* if not now on a '\0', *c must not be a digit */
if (*c!='\0') break;
diff --git a/Build/source/libs/icu/icu-src/source/i18n/decimalformatpattern.cpp b/Build/source/libs/icu/icu-src/source/i18n/decimalformatpattern.cpp
index b07bcdd3ccf..4ee5e334411 100644
--- a/Build/source/libs/icu/icu-src/source/i18n/decimalformatpattern.cpp
+++ b/Build/source/libs/icu/icu-src/source/i18n/decimalformatpattern.cpp
@@ -50,10 +50,12 @@ static void syntaxError(const UnicodeString& pattern,
parseError.preContext[stop-start] = 0;
//for post-context
- start = pos+1;
- stop = ((pos+U_PARSE_CONTEXT_LEN)<=pattern.length()) ? (pos+(U_PARSE_CONTEXT_LEN-1)) :
- pattern.length();
- pattern.extract(start,stop-start,parseError.postContext,0);
+ 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;
}
diff --git a/Build/source/libs/icu/icu-src/source/i18n/digitlst.cpp b/Build/source/libs/icu/icu-src/source/i18n/digitlst.cpp
index 8e86fa77ecf..978bb60004f 100644
--- a/Build/source/libs/icu/icu-src/source/i18n/digitlst.cpp
+++ b/Build/source/libs/icu/icu-src/source/i18n/digitlst.cpp
@@ -44,12 +44,15 @@
#include "digitinterval.h"
#include "ucln_in.h"
#include "umutex.h"
+#include "double-conversion.h"
#include <stdlib.h>
#include <limits.h>
#include <string.h>
#include <stdio.h>
#include <limits>
+using icu::double_conversion::DoubleToStringConverter;
+
#if !defined(U_USE_STRTOD_L)
# if U_PLATFORM_USES_ONLY_WIN32_API
# define U_USE_STRTOD_L 1
@@ -850,8 +853,53 @@ DigitList::set(double source)
} else {
uprv_strcpy(rep,"inf");
}
+ } else if (uprv_isNaN(source)) {
+ uprv_strcpy(rep, "NaN");
} else {
- sprintf(rep, "%+1.*e", MAX_DBL_DIGITS - 1, source);
+ 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));
diff --git a/Build/source/libs/icu/icu-src/source/i18n/double-conversion-bignum-dtoa.cpp b/Build/source/libs/icu/icu-src/source/i18n/double-conversion-bignum-dtoa.cpp
new file mode 100644
index 00000000000..07d0b0eb0f8
--- /dev/null
+++ b/Build/source/libs/icu/icu-src/source/i18n/double-conversion-bignum-dtoa.cpp
@@ -0,0 +1,659 @@
+// © 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 <math.h>
+
+// ICU PATCH: Customize header file paths for ICU.
+
+#include "double-conversion-bignum-dtoa.h"
+
+#include "double-conversion-bignum.h"
+#include "double-conversion-ieee.h"
+
+// ICU PATCH: Wrap in ICU namespace
+U_NAMESPACE_BEGIN
+
+namespace double_conversion {
+
+static int NormalizedExponent(uint64_t significand, int exponent) {
+ ASSERT(significand != 0);
+ while ((significand & Double::kHiddenBit) == 0) {
+ significand = significand << 1;
+ exponent = exponent - 1;
+ }
+ return exponent;
+}
+
+
+// Forward declarations:
+// Returns an estimation of k such that 10^(k-1) <= v < 10^k.
+static int EstimatePower(int exponent);
+// Computes v / 10^estimated_power exactly, as a ratio of two bignums, numerator
+// and denominator.
+static void InitialScaledStartValues(uint64_t significand,
+ int exponent,
+ bool lower_boundary_is_closer,
+ int estimated_power,
+ bool need_boundary_deltas,
+ Bignum* numerator,
+ Bignum* denominator,
+ Bignum* delta_minus,
+ Bignum* delta_plus);
+// Multiplies numerator/denominator so that its values lies in the range 1-10.
+// Returns decimal_point s.t.
+// v = numerator'/denominator' * 10^(decimal_point-1)
+// where numerator' and denominator' are the values of numerator and
+// denominator after the call to this function.
+static void FixupMultiply10(int estimated_power, bool is_even,
+ int* decimal_point,
+ Bignum* numerator, Bignum* denominator,
+ Bignum* delta_minus, Bignum* delta_plus);
+// Generates digits from the left to the right and stops when the generated
+// digits yield the shortest decimal representation of v.
+static void GenerateShortestDigits(Bignum* numerator, Bignum* denominator,
+ Bignum* delta_minus, Bignum* delta_plus,
+ bool is_even,
+ Vector<char> buffer, int* length);
+// Generates 'requested_digits' after the decimal point.
+static void BignumToFixed(int requested_digits, int* decimal_point,
+ Bignum* numerator, Bignum* denominator,
+ Vector<char>(buffer), int* length);
+// Generates 'count' digits of numerator/denominator.
+// Once 'count' digits have been produced rounds the result depending on the
+// remainder (remainders of exactly .5 round upwards). Might update the
+// decimal_point when rounding up (for example for 0.9999).
+static void GenerateCountedDigits(int count, int* decimal_point,
+ Bignum* numerator, Bignum* denominator,
+ Vector<char>(buffer), int* length);
+
+
+void BignumDtoa(double v, BignumDtoaMode mode, int requested_digits,
+ Vector<char> buffer, int* length, int* decimal_point) {
+ ASSERT(v > 0);
+ ASSERT(!Double(v).IsSpecial());
+ uint64_t significand;
+ int exponent;
+ bool lower_boundary_is_closer;
+ if (mode == BIGNUM_DTOA_SHORTEST_SINGLE) {
+ float f = static_cast<float>(v);
+ ASSERT(f == v);
+ significand = Single(f).Significand();
+ exponent = Single(f).Exponent();
+ lower_boundary_is_closer = Single(f).LowerBoundaryIsCloser();
+ } else {
+ significand = Double(v).Significand();
+ exponent = Double(v).Exponent();
+ lower_boundary_is_closer = Double(v).LowerBoundaryIsCloser();
+ }
+ bool need_boundary_deltas =
+ (mode == BIGNUM_DTOA_SHORTEST || mode == BIGNUM_DTOA_SHORTEST_SINGLE);
+
+ bool is_even = (significand & 1) == 0;
+ int normalized_exponent = NormalizedExponent(significand, exponent);
+ // estimated_power might be too low by 1.
+ int estimated_power = EstimatePower(normalized_exponent);
+
+ // Shortcut for Fixed.
+ // The requested digits correspond to the digits after the point. If the
+ // number is much too small, then there is no need in trying to get any
+ // digits.
+ if (mode == BIGNUM_DTOA_FIXED && -estimated_power - 1 > requested_digits) {
+ buffer[0] = '\0';
+ *length = 0;
+ // Set decimal-point to -requested_digits. This is what Gay does.
+ // Note that it should not have any effect anyways since the string is
+ // empty.
+ *decimal_point = -requested_digits;
+ return;
+ }
+
+ Bignum numerator;
+ Bignum denominator;
+ Bignum delta_minus;
+ Bignum delta_plus;
+ // Make sure the bignum can grow large enough. The smallest double equals
+ // 4e-324. In this case the denominator needs fewer than 324*4 binary digits.
+ // The maximum double is 1.7976931348623157e308 which needs fewer than
+ // 308*4 binary digits.
+ ASSERT(Bignum::kMaxSignificantBits >= 324*4);
+ InitialScaledStartValues(significand, exponent, lower_boundary_is_closer,
+ estimated_power, need_boundary_deltas,
+ &numerator, &denominator,
+ &delta_minus, &delta_plus);
+ // We now have v = (numerator / denominator) * 10^estimated_power.
+ FixupMultiply10(estimated_power, is_even, decimal_point,
+ &numerator, &denominator,
+ &delta_minus, &delta_plus);
+ // We now have v = (numerator / denominator) * 10^(decimal_point-1), and
+ // 1 <= (numerator + delta_plus) / denominator < 10
+ switch (mode) {
+ case BIGNUM_DTOA_SHORTEST:
+ case BIGNUM_DTOA_SHORTEST_SINGLE:
+ GenerateShortestDigits(&numerator, &denominator,
+ &delta_minus, &delta_plus,
+ is_even, buffer, length);
+ break;
+ case BIGNUM_DTOA_FIXED:
+ BignumToFixed(requested_digits, decimal_point,
+ &numerator, &denominator,
+ buffer, length);
+ break;
+ case BIGNUM_DTOA_PRECISION:
+ GenerateCountedDigits(requested_digits, decimal_point,
+ &numerator, &denominator,
+ buffer, length);
+ break;
+ default:
+ UNREACHABLE();
+ }
+ buffer[*length] = '\0';
+}
+
+
+// The procedure starts generating digits from the left to the right and stops
+// when the generated digits yield the shortest decimal representation of v. A
+// decimal representation of v is a number lying closer to v than to any other
+// double, so it converts to v when read.
+//
+// This is true if d, the decimal representation, is between m- and m+, the
+// upper and lower boundaries. d must be strictly between them if !is_even.
+// m- := (numerator - delta_minus) / denominator
+// m+ := (numerator + delta_plus) / denominator
+//
+// Precondition: 0 <= (numerator+delta_plus) / denominator < 10.
+// If 1 <= (numerator+delta_plus) / denominator < 10 then no leading 0 digit
+// will be produced. This should be the standard precondition.
+static void GenerateShortestDigits(Bignum* numerator, Bignum* denominator,
+ Bignum* delta_minus, Bignum* delta_plus,
+ bool is_even,
+ Vector<char> buffer, int* length) {
+ // Small optimization: if delta_minus and delta_plus are the same just reuse
+ // one of the two bignums.
+ if (Bignum::Equal(*delta_minus, *delta_plus)) {
+ delta_plus = delta_minus;
+ }
+ *length = 0;
+ for (;;) {
+ uint16_t digit;
+ digit = numerator->DivideModuloIntBignum(*denominator);
+ ASSERT(digit <= 9); // digit is a uint16_t and therefore always positive.
+ // digit = numerator / denominator (integer division).
+ // numerator = numerator % denominator.
+ buffer[(*length)++] = static_cast<char>(digit + '0');
+
+ // Can we stop already?
+ // If the remainder of the division is less than the distance to the lower
+ // boundary we can stop. In this case we simply round down (discarding the
+ // remainder).
+ // Similarly we test if we can round up (using the upper boundary).
+ bool in_delta_room_minus;
+ bool in_delta_room_plus;
+ if (is_even) {
+ in_delta_room_minus = Bignum::LessEqual(*numerator, *delta_minus);
+ } else {
+ in_delta_room_minus = Bignum::Less(*numerator, *delta_minus);
+ }
+ if (is_even) {
+ in_delta_room_plus =
+ Bignum::PlusCompare(*numerator, *delta_plus, *denominator) >= 0;
+ } else {
+ in_delta_room_plus =
+ Bignum::PlusCompare(*numerator, *delta_plus, *denominator) > 0;
+ }
+ if (!in_delta_room_minus && !in_delta_room_plus) {
+ // Prepare for next iteration.
+ numerator->Times10();
+ delta_minus->Times10();
+ // We optimized delta_plus to be equal to delta_minus (if they share the
+ // same value). So don't multiply delta_plus if they point to the same
+ // object.
+ if (delta_minus != delta_plus) {
+ delta_plus->Times10();
+ }
+ } else if (in_delta_room_minus && in_delta_room_plus) {
+ // Let's see if 2*numerator < denominator.
+ // If yes, then the next digit would be < 5 and we can round down.
+ int compare = Bignum::PlusCompare(*numerator, *numerator, *denominator);
+ if (compare < 0) {
+ // Remaining digits are less than .5. -> Round down (== do nothing).
+ } else if (compare > 0) {
+ // Remaining digits are more than .5 of denominator. -> Round up.
+ // Note that the last digit could not be a '9' as otherwise the whole
+ // loop would have stopped earlier.
+ // We still have an assert here in case the preconditions were not
+ // satisfied.
+ ASSERT(buffer[(*length) - 1] != '9');
+ buffer[(*length) - 1]++;
+ } else {
+ // Halfway case.
+ // TODO(floitsch): need a way to solve half-way cases.
+ // For now let's round towards even (since this is what Gay seems to
+ // do).
+
+ if ((buffer[(*length) - 1] - '0') % 2 == 0) {
+ // Round down => Do nothing.
+ } else {
+ ASSERT(buffer[(*length) - 1] != '9');
+ buffer[(*length) - 1]++;
+ }
+ }
+ return;
+ } else if (in_delta_room_minus) {
+ // Round down (== do nothing).
+ return;
+ } else { // in_delta_room_plus
+ // Round up.
+ // Note again that the last digit could not be '9' since this would have
+ // stopped the loop earlier.
+ // We still have an ASSERT here, in case the preconditions were not
+ // satisfied.
+ ASSERT(buffer[(*length) -1] != '9');
+ buffer[(*length) - 1]++;
+ return;
+ }
+ }
+}
+
+
+// Let v = numerator / denominator < 10.
+// Then we generate 'count' digits of d = x.xxxxx... (without the decimal point)
+// from left to right. Once 'count' digits have been produced we decide wether
+// to round up or down. Remainders of exactly .5 round upwards. Numbers such
+// as 9.999999 propagate a carry all the way, and change the
+// exponent (decimal_point), when rounding upwards.
+static void GenerateCountedDigits(int count, int* decimal_point,
+ Bignum* numerator, Bignum* denominator,
+ Vector<char> buffer, int* length) {
+ ASSERT(count >= 0);
+ for (int i = 0; i < count - 1; ++i) {
+ uint16_t digit;
+ digit = numerator->DivideModuloIntBignum(*denominator);
+ ASSERT(digit <= 9); // digit is a uint16_t and therefore always positive.
+ // digit = numerator / denominator (integer division).
+ // numerator = numerator % denominator.
+ buffer[i] = static_cast<char>(digit + '0');
+ // Prepare for next iteration.
+ numerator->Times10();
+ }
+ // Generate the last digit.
+ uint16_t digit;
+ digit = numerator->DivideModuloIntBignum(*denominator);
+ if (Bignum::PlusCompare(*numerator, *numerator, *denominator) >= 0) {
+ digit++;
+ }
+ ASSERT(digit <= 10);
+ buffer[count - 1] = static_cast<char>(digit + '0');
+ // Correct bad digits (in case we had a sequence of '9's). Propagate the
+ // carry until we hat a non-'9' or til we reach the first digit.
+ for (int i = count - 1; i > 0; --i) {
+ if (buffer[i] != '0' + 10) break;
+ buffer[i] = '0';
+ buffer[i - 1]++;
+ }
+ if (buffer[0] == '0' + 10) {
+ // Propagate a carry past the top place.
+ buffer[0] = '1';
+ (*decimal_point)++;
+ }
+ *length = count;
+}
+
+
+// Generates 'requested_digits' after the decimal point. It might omit
+// trailing '0's. If the input number is too small then no digits at all are
+// generated (ex.: 2 fixed digits for 0.00001).
+//
+// Input verifies: 1 <= (numerator + delta) / denominator < 10.
+static void BignumToFixed(int requested_digits, int* decimal_point,
+ Bignum* numerator, Bignum* denominator,
+ Vector<char>(buffer), int* length) {
+ // Note that we have to look at more than just the requested_digits, since
+ // a number could be rounded up. Example: v=0.5 with requested_digits=0.
+ // Even though the power of v equals 0 we can't just stop here.
+ if (-(*decimal_point) > requested_digits) {
+ // The number is definitively too small.
+ // Ex: 0.001 with requested_digits == 1.
+ // Set decimal-point to -requested_digits. This is what Gay does.
+ // Note that it should not have any effect anyways since the string is
+ // empty.
+ *decimal_point = -requested_digits;
+ *length = 0;
+ return;
+ } else if (-(*decimal_point) == requested_digits) {
+ // We only need to verify if the number rounds down or up.
+ // Ex: 0.04 and 0.06 with requested_digits == 1.
+ ASSERT(*decimal_point == -requested_digits);
+ // Initially the fraction lies in range (1, 10]. Multiply the denominator
+ // by 10 so that we can compare more easily.
+ denominator->Times10();
+ if (Bignum::PlusCompare(*numerator, *numerator, *denominator) >= 0) {
+ // If the fraction is >= 0.5 then we have to include the rounded
+ // digit.
+ buffer[0] = '1';
+ *length = 1;
+ (*decimal_point)++;
+ } else {
+ // Note that we caught most of similar cases earlier.
+ *length = 0;
+ }
+ return;
+ } else {
+ // The requested digits correspond to the digits after the point.
+ // The variable 'needed_digits' includes the digits before the point.
+ int needed_digits = (*decimal_point) + requested_digits;
+ GenerateCountedDigits(needed_digits, decimal_point,
+ numerator, denominator,
+ buffer, length);
+ }
+}
+
+
+// Returns an estimation of k such that 10^(k-1) <= v < 10^k where
+// v = f * 2^exponent and 2^52 <= f < 2^53.
+// v is hence a normalized double with the given exponent. The output is an
+// approximation for the exponent of the decimal approimation .digits * 10^k.
+//
+// The result might undershoot by 1 in which case 10^k <= v < 10^k+1.
+// Note: this property holds for v's upper boundary m+ too.
+// 10^k <= m+ < 10^k+1.
+// (see explanation below).
+//
+// Examples:
+// EstimatePower(0) => 16
+// EstimatePower(-52) => 0
+//
+// Note: e >= 0 => EstimatedPower(e) > 0. No similar claim can be made for e<0.
+static int EstimatePower(int exponent) {
+ // This function estimates log10 of v where v = f*2^e (with e == exponent).
+ // Note that 10^floor(log10(v)) <= v, but v <= 10^ceil(log10(v)).
+ // Note that f is bounded by its container size. Let p = 53 (the double's
+ // significand size). Then 2^(p-1) <= f < 2^p.
+ //
+ // Given that log10(v) == log2(v)/log2(10) and e+(len(f)-1) is quite close
+ // to log2(v) the function is simplified to (e+(len(f)-1)/log2(10)).
+ // The computed number undershoots by less than 0.631 (when we compute log3
+ // and not log10).
+ //
+ // Optimization: since we only need an approximated result this computation
+ // can be performed on 64 bit integers. On x86/x64 architecture the speedup is
+ // not really measurable, though.
+ //
+ // Since we want to avoid overshooting we decrement by 1e10 so that
+ // floating-point imprecisions don't affect us.
+ //
+ // Explanation for v's boundary m+: the computation takes advantage of
+ // the fact that 2^(p-1) <= f < 2^p. Boundaries still satisfy this requirement
+ // (even for denormals where the delta can be much more important).
+
+ const double k1Log10 = 0.30102999566398114; // 1/lg(10)
+
+ // For doubles len(f) == 53 (don't forget the hidden bit).
+ const int kSignificandSize = Double::kSignificandSize;
+ double estimate = ceil((exponent + kSignificandSize - 1) * k1Log10 - 1e-10);
+ return static_cast<int>(estimate);
+}
+
+
+// See comments for InitialScaledStartValues.
+static void InitialScaledStartValuesPositiveExponent(
+ uint64_t significand, int exponent,
+ int estimated_power, bool need_boundary_deltas,
+ Bignum* numerator, Bignum* denominator,
+ Bignum* delta_minus, Bignum* delta_plus) {
+ // A positive exponent implies a positive power.
+ ASSERT(estimated_power >= 0);
+ // Since the estimated_power is positive we simply multiply the denominator
+ // by 10^estimated_power.
+
+ // numerator = v.
+ numerator->AssignUInt64(significand);
+ numerator->ShiftLeft(exponent);
+ // denominator = 10^estimated_power.
+ denominator->AssignPowerUInt16(10, estimated_power);
+
+ if (need_boundary_deltas) {
+ // Introduce a common denominator so that the deltas to the boundaries are
+ // integers.
+ denominator->ShiftLeft(1);
+ numerator->ShiftLeft(1);
+ // Let v = f * 2^e, then m+ - v = 1/2 * 2^e; With the common
+ // denominator (of 2) delta_plus equals 2^e.
+ delta_plus->AssignUInt16(1);
+ delta_plus->ShiftLeft(exponent);
+ // Same for delta_minus. The adjustments if f == 2^p-1 are done later.
+ delta_minus->AssignUInt16(1);
+ delta_minus->ShiftLeft(exponent);
+ }
+}
+
+
+// See comments for InitialScaledStartValues
+static void InitialScaledStartValuesNegativeExponentPositivePower(
+ uint64_t significand, int exponent,
+ int estimated_power, bool need_boundary_deltas,
+ Bignum* numerator, Bignum* denominator,
+ Bignum* delta_minus, Bignum* delta_plus) {
+ // v = f * 2^e with e < 0, and with estimated_power >= 0.
+ // This means that e is close to 0 (have a look at how estimated_power is
+ // computed).
+
+ // numerator = significand
+ // since v = significand * 2^exponent this is equivalent to
+ // numerator = v * / 2^-exponent
+ numerator->AssignUInt64(significand);
+ // denominator = 10^estimated_power * 2^-exponent (with exponent < 0)
+ denominator->AssignPowerUInt16(10, estimated_power);
+ denominator->ShiftLeft(-exponent);
+
+ if (need_boundary_deltas) {
+ // Introduce a common denominator so that the deltas to the boundaries are
+ // integers.
+ denominator->ShiftLeft(1);
+ numerator->ShiftLeft(1);
+ // Let v = f * 2^e, then m+ - v = 1/2 * 2^e; With the common
+ // denominator (of 2) delta_plus equals 2^e.
+ // Given that the denominator already includes v's exponent the distance
+ // to the boundaries is simply 1.
+ delta_plus->AssignUInt16(1);
+ // Same for delta_minus. The adjustments if f == 2^p-1 are done later.
+ delta_minus->AssignUInt16(1);
+ }
+}
+
+
+// See comments for InitialScaledStartValues
+static void InitialScaledStartValuesNegativeExponentNegativePower(
+ uint64_t significand, int exponent,
+ int estimated_power, bool need_boundary_deltas,
+ Bignum* numerator, Bignum* denominator,
+ Bignum* delta_minus, Bignum* delta_plus) {
+ // Instead of multiplying the denominator with 10^estimated_power we
+ // multiply all values (numerator and deltas) by 10^-estimated_power.
+
+ // Use numerator as temporary container for power_ten.
+ Bignum* power_ten = numerator;
+ power_ten->AssignPowerUInt16(10, -estimated_power);
+
+ if (need_boundary_deltas) {
+ // Since power_ten == numerator we must make a copy of 10^estimated_power
+ // before we complete the computation of the numerator.
+ // delta_plus = delta_minus = 10^estimated_power
+ delta_plus->AssignBignum(*power_ten);
+ delta_minus->AssignBignum(*power_ten);
+ }
+
+ // numerator = significand * 2 * 10^-estimated_power
+ // since v = significand * 2^exponent this is equivalent to
+ // numerator = v * 10^-estimated_power * 2 * 2^-exponent.
+ // Remember: numerator has been abused as power_ten. So no need to assign it
+ // to itself.
+ ASSERT(numerator == power_ten);
+ numerator->MultiplyByUInt64(significand);
+
+ // denominator = 2 * 2^-exponent with exponent < 0.
+ denominator->AssignUInt16(1);
+ denominator->ShiftLeft(-exponent);
+
+ if (need_boundary_deltas) {
+ // Introduce a common denominator so that the deltas to the boundaries are
+ // integers.
+ numerator->ShiftLeft(1);
+ denominator->ShiftLeft(1);
+ // With this shift the boundaries have their correct value, since
+ // delta_plus = 10^-estimated_power, and
+ // delta_minus = 10^-estimated_power.
+ // These assignments have been done earlier.
+ // The adjustments if f == 2^p-1 (lower boundary is closer) are done later.
+ }
+}
+
+
+// Let v = significand * 2^exponent.
+// Computes v / 10^estimated_power exactly, as a ratio of two bignums, numerator
+// and denominator. The functions GenerateShortestDigits and
+// GenerateCountedDigits will then convert this ratio to its decimal
+// representation d, with the required accuracy.
+// Then d * 10^estimated_power is the representation of v.
+// (Note: the fraction and the estimated_power might get adjusted before
+// generating the decimal representation.)
+//
+// The initial start values consist of:
+// - a scaled numerator: s.t. numerator/denominator == v / 10^estimated_power.
+// - a scaled (common) denominator.
+// optionally (used by GenerateShortestDigits to decide if it has the shortest
+// decimal converting back to v):
+// - v - m-: the distance to the lower boundary.
+// - m+ - v: the distance to the upper boundary.
+//
+// v, m+, m-, and therefore v - m- and m+ - v all share the same denominator.
+//
+// Let ep == estimated_power, then the returned values will satisfy:
+// v / 10^ep = numerator / denominator.
+// v's boundarys m- and m+:
+// m- / 10^ep == v / 10^ep - delta_minus / denominator
+// m+ / 10^ep == v / 10^ep + delta_plus / denominator
+// Or in other words:
+// m- == v - delta_minus * 10^ep / denominator;
+// m+ == v + delta_plus * 10^ep / denominator;
+//
+// Since 10^(k-1) <= v < 10^k (with k == estimated_power)
+// or 10^k <= v < 10^(k+1)
+// we then have 0.1 <= numerator/denominator < 1
+// or 1 <= numerator/denominator < 10
+//
+// It is then easy to kickstart the digit-generation routine.
+//
+// The boundary-deltas are only filled if the mode equals BIGNUM_DTOA_SHORTEST
+// or BIGNUM_DTOA_SHORTEST_SINGLE.
+
+static void InitialScaledStartValues(uint64_t significand,
+ int exponent,
+ bool lower_boundary_is_closer,
+ int estimated_power,
+ bool need_boundary_deltas,
+ Bignum* numerator,
+ Bignum* denominator,
+ Bignum* delta_minus,
+ Bignum* delta_plus) {
+ if (exponent >= 0) {
+ InitialScaledStartValuesPositiveExponent(
+ significand, exponent, estimated_power, need_boundary_deltas,
+ numerator, denominator, delta_minus, delta_plus);
+ } else if (estimated_power >= 0) {
+ InitialScaledStartValuesNegativeExponentPositivePower(
+ significand, exponent, estimated_power, need_boundary_deltas,
+ numerator, denominator, delta_minus, delta_plus);
+ } else {
+ InitialScaledStartValuesNegativeExponentNegativePower(
+ significand, exponent, estimated_power, need_boundary_deltas,
+ numerator, denominator, delta_minus, delta_plus);
+ }
+
+ if (need_boundary_deltas && lower_boundary_is_closer) {
+ // The lower boundary is closer at half the distance of "normal" numbers.
+ // Increase the common denominator and adapt all but the delta_minus.
+ denominator->ShiftLeft(1); // *2
+ numerator->ShiftLeft(1); // *2
+ delta_plus->ShiftLeft(1); // *2
+ }
+}
+
+
+// This routine multiplies numerator/denominator so that its values lies in the
+// range 1-10. That is after a call to this function we have:
+// 1 <= (numerator + delta_plus) /denominator < 10.
+// Let numerator the input before modification and numerator' the argument
+// after modification, then the output-parameter decimal_point is such that
+// numerator / denominator * 10^estimated_power ==
+// numerator' / denominator' * 10^(decimal_point - 1)
+// In some cases estimated_power was too low, and this is already the case. We
+// then simply adjust the power so that 10^(k-1) <= v < 10^k (with k ==
+// estimated_power) but do not touch the numerator or denominator.
+// Otherwise the routine multiplies the numerator and the deltas by 10.
+static void FixupMultiply10(int estimated_power, bool is_even,
+ int* decimal_point,
+ Bignum* numerator, Bignum* denominator,
+ Bignum* delta_minus, Bignum* delta_plus) {
+ bool in_range;
+ if (is_even) {
+ // For IEEE doubles half-way cases (in decimal system numbers ending with 5)
+ // are rounded to the closest floating-point number with even significand.
+ in_range = Bignum::PlusCompare(*numerator, *delta_plus, *denominator) >= 0;
+ } else {
+ in_range = Bignum::PlusCompare(*numerator, *delta_plus, *denominator) > 0;
+ }
+ if (in_range) {
+ // Since numerator + delta_plus >= denominator we already have
+ // 1 <= numerator/denominator < 10. Simply update the estimated_power.
+ *decimal_point = estimated_power + 1;
+ } else {
+ *decimal_point = estimated_power;
+ numerator->Times10();
+ if (Bignum::Equal(*delta_minus, *delta_plus)) {
+ delta_minus->Times10();
+ delta_plus->AssignBignum(*delta_minus);
+ } else {
+ delta_minus->Times10();
+ delta_plus->Times10();
+ }
+ }
+}
+
+} // namespace double_conversion
+
+// ICU PATCH: Close ICU namespace
+U_NAMESPACE_END
+#endif // ICU PATCH: close #if !UCONFIG_NO_FORMATTING
diff --git a/Build/source/libs/icu/icu-src/source/i18n/double-conversion-bignum-dtoa.h b/Build/source/libs/icu/icu-src/source/i18n/double-conversion-bignum-dtoa.h
new file mode 100644
index 00000000000..edc21b0f2e4
--- /dev/null
+++ b/Build/source/libs/icu/icu-src/source/i18n/double-conversion-bignum-dtoa.h
@@ -0,0 +1,102 @@
+// © 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_BIGNUM_DTOA_H_
+#define DOUBLE_CONVERSION_BIGNUM_DTOA_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 {
+
+enum BignumDtoaMode {
+ // Return the shortest correct representation.
+ // For example the output of 0.299999999999999988897 is (the less accurate but
+ // correct) 0.3.
+ BIGNUM_DTOA_SHORTEST,
+ // Same as BIGNUM_DTOA_SHORTEST but for single-precision floats.
+ BIGNUM_DTOA_SHORTEST_SINGLE,
+ // Return a fixed number of digits after the decimal point.
+ // For instance fixed(0.1, 4) becomes 0.1000
+ // If the input number is big, the output will be big.
+ BIGNUM_DTOA_FIXED,
+ // Return a fixed number of digits, no matter what the exponent is.
+ BIGNUM_DTOA_PRECISION
+};
+
+// Converts the given double 'v' to ascii.
+// The result should be interpreted as buffer * 10^(point-length).
+// The buffer will be null-terminated.
+//
+// The input v must be > 0 and different from NaN, and Infinity.
+//
+// The output depends on the given mode:
+// - SHORTEST: produce the least amount of digits for which the internal
+// identity requirement is still satisfied. If the digits are printed
+// (together with the correct exponent) then reading this number will give
+// 'v' again. The buffer will choose the representation that is closest to
+// 'v'. If there are two at the same distance, than the number is round up.
+// In this mode the 'requested_digits' parameter is ignored.
+// - FIXED: produces digits necessary to print a given number with
+// 'requested_digits' digits after the decimal point. The produced digits
+// might be too short in which case the caller has to fill the gaps with '0's.
+// Example: toFixed(0.001, 5) is allowed to return buffer="1", point=-2.
+// Halfway cases are rounded up. The call toFixed(0.15, 2) thus returns
+// buffer="2", point=0.
+// Note: the length of the returned buffer has no meaning wrt the significance
+// of its digits. That is, just because it contains '0's does not mean that
+// any other digit would not satisfy the internal identity requirement.
+// - PRECISION: produces 'requested_digits' where the first digit is not '0'.
+// Even though the length of produced digits usually equals
+// 'requested_digits', the function is allowed to return fewer digits, in
+// which case the caller has to fill the missing digits with '0's.
+// Halfway cases are again rounded up.
+// 'BignumDtoa' expects the given buffer to be big enough to hold all digits
+// and a terminating null-character.
+void BignumDtoa(double v, BignumDtoaMode mode, int requested_digits,
+ Vector<char> buffer, int* length, int* point);
+
+} // namespace double_conversion
+
+// ICU PATCH: Close ICU namespace
+U_NAMESPACE_END
+
+#endif // DOUBLE_CONVERSION_BIGNUM_DTOA_H_
+#endif // ICU PATCH: close #if !UCONFIG_NO_FORMATTING
diff --git a/Build/source/libs/icu/icu-src/source/i18n/double-conversion-bignum.cpp b/Build/source/libs/icu/icu-src/source/i18n/double-conversion-bignum.cpp
new file mode 100644
index 00000000000..d5682af35f8
--- /dev/null
+++ b/Build/source/libs/icu/icu-src/source/i18n/double-conversion-bignum.cpp
@@ -0,0 +1,784 @@
+// © 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
+
+// ICU PATCH: Customize header file paths for ICU.
+
+#include "double-conversion-bignum.h"
+#include "double-conversion-utils.h"
+
+// ICU PATCH: Wrap in ICU namespace
+U_NAMESPACE_BEGIN
+
+namespace double_conversion {
+
+Bignum::Bignum()
+ : bigits_(bigits_buffer_, kBigitCapacity), used_digits_(0), exponent_(0) {
+ for (int i = 0; i < kBigitCapacity; ++i) {
+ bigits_[i] = 0;
+ }
+}
+
+
+template<typename S>
+static int BitSize(S value) {
+ (void) value; // Mark variable as used.
+ return 8 * sizeof(value);
+}
+
+// Guaranteed to lie in one Bigit.
+void Bignum::AssignUInt16(uint16_t value) {
+ ASSERT(kBigitSize >= BitSize(value));
+ Zero();
+ if (value == 0) return;
+
+ EnsureCapacity(1);
+ bigits_[0] = value;
+ used_digits_ = 1;
+}
+
+
+void Bignum::AssignUInt64(uint64_t value) {
+ const int kUInt64Size = 64;
+
+ Zero();
+ if (value == 0) return;
+
+ int needed_bigits = kUInt64Size / kBigitSize + 1;
+ EnsureCapacity(needed_bigits);
+ for (int i = 0; i < needed_bigits; ++i) {
+ bigits_[i] = value & kBigitMask;
+ value = value >> kBigitSize;
+ }
+ used_digits_ = needed_bigits;
+ Clamp();
+}
+
+
+void Bignum::AssignBignum(const Bignum& other) {
+ exponent_ = other.exponent_;
+ for (int i = 0; i < other.used_digits_; ++i) {
+ bigits_[i] = other.bigits_[i];
+ }
+ // Clear the excess digits (if there were any).
+ for (int i = other.used_digits_; i < used_digits_; ++i) {
+ bigits_[i] = 0;
+ }
+ used_digits_ = other.used_digits_;
+}
+
+
+static uint64_t ReadUInt64(Vector<const char> buffer,
+ int from,
+ int digits_to_read) {
+ uint64_t result = 0;
+ for (int i = from; i < from + digits_to_read; ++i) {
+ int digit = buffer[i] - '0';
+ ASSERT(0 <= digit && digit <= 9);
+ result = result * 10 + digit;
+ }
+ return result;
+}
+
+
+void Bignum::AssignDecimalString(Vector<const char> value) {
+ // 2^64 = 18446744073709551616 > 10^19
+ const int kMaxUint64DecimalDigits = 19;
+ Zero();
+ int length = value.length();
+ unsigned int pos = 0;
+ // Let's just say that each digit needs 4 bits.
+ while (length >= kMaxUint64DecimalDigits) {
+ uint64_t digits = ReadUInt64(value, pos, kMaxUint64DecimalDigits);
+ pos += kMaxUint64DecimalDigits;
+ length -= kMaxUint64DecimalDigits;
+ MultiplyByPowerOfTen(kMaxUint64DecimalDigits);
+ AddUInt64(digits);
+ }
+ uint64_t digits = ReadUInt64(value, pos, length);
+ MultiplyByPowerOfTen(length);
+ AddUInt64(digits);
+ Clamp();
+}
+
+
+static int HexCharValue(char c) {
+ if ('0' <= c && c <= '9') return c - '0';
+ if ('a' <= c && c <= 'f') return 10 + c - 'a';
+ ASSERT('A' <= c && c <= 'F');
+ return 10 + c - 'A';
+}
+
+
+void Bignum::AssignHexString(Vector<const char> value) {
+ Zero();
+ int length = value.length();
+
+ int needed_bigits = length * 4 / kBigitSize + 1;
+ EnsureCapacity(needed_bigits);
+ int string_index = length - 1;
+ for (int i = 0; i < needed_bigits - 1; ++i) {
+ // These bigits are guaranteed to be "full".
+ Chunk current_bigit = 0;
+ for (int j = 0; j < kBigitSize / 4; j++) {
+ current_bigit += HexCharValue(value[string_index--]) << (j * 4);
+ }
+ bigits_[i] = current_bigit;
+ }
+ used_digits_ = needed_bigits - 1;
+
+ Chunk most_significant_bigit = 0; // Could be = 0;
+ for (int j = 0; j <= string_index; ++j) {
+ most_significant_bigit <<= 4;
+ most_significant_bigit += HexCharValue(value[j]);
+ }
+ if (most_significant_bigit != 0) {
+ bigits_[used_digits_] = most_significant_bigit;
+ used_digits_++;
+ }
+ Clamp();
+}
+
+
+void Bignum::AddUInt64(uint64_t operand) {
+ if (operand == 0) return;
+ Bignum other;
+ other.AssignUInt64(operand);
+ AddBignum(other);
+}
+
+
+void Bignum::AddBignum(const Bignum& other) {
+ ASSERT(IsClamped());
+ ASSERT(other.IsClamped());
+
+ // If this has a greater exponent than other append zero-bigits to this.
+ // After this call exponent_ <= other.exponent_.
+ Align(other);
+
+ // There are two possibilities:
+ // aaaaaaaaaaa 0000 (where the 0s represent a's exponent)
+ // bbbbb 00000000
+ // ----------------
+ // ccccccccccc 0000
+ // or
+ // aaaaaaaaaa 0000
+ // bbbbbbbbb 0000000
+ // -----------------
+ // cccccccccccc 0000
+ // In both cases we might need a carry bigit.
+
+ EnsureCapacity(1 + Max(BigitLength(), other.BigitLength()) - exponent_);
+ Chunk carry = 0;
+ int bigit_pos = other.exponent_ - exponent_;
+ ASSERT(bigit_pos >= 0);
+ for (int i = 0; i < other.used_digits_; ++i) {
+ Chunk sum = bigits_[bigit_pos] + other.bigits_[i] + carry;
+ bigits_[bigit_pos] = sum & kBigitMask;
+ carry = sum >> kBigitSize;
+ bigit_pos++;
+ }
+
+ while (carry != 0) {
+ Chunk sum = bigits_[bigit_pos] + carry;
+ bigits_[bigit_pos] = sum & kBigitMask;
+ carry = sum >> kBigitSize;
+ bigit_pos++;
+ }
+ used_digits_ = Max(bigit_pos, used_digits_);
+ ASSERT(IsClamped());
+}
+
+
+void Bignum::SubtractBignum(const Bignum& other) {
+ ASSERT(IsClamped());
+ ASSERT(other.IsClamped());
+ // We require this to be bigger than other.
+ ASSERT(LessEqual(other, *this));
+
+ Align(other);
+
+ int offset = other.exponent_ - exponent_;
+ Chunk borrow = 0;
+ int i;
+ for (i = 0; i < other.used_digits_; ++i) {
+ ASSERT((borrow == 0) || (borrow == 1));
+ Chunk difference = bigits_[i + offset] - other.bigits_[i] - borrow;
+ bigits_[i + offset] = difference & kBigitMask;
+ borrow = difference >> (kChunkSize - 1);
+ }
+ while (borrow != 0) {
+ Chunk difference = bigits_[i + offset] - borrow;
+ bigits_[i + offset] = difference & kBigitMask;
+ borrow = difference >> (kChunkSize - 1);
+ ++i;
+ }
+ Clamp();
+}
+
+
+void Bignum::ShiftLeft(int shift_amount) {
+ if (used_digits_ == 0) return;
+ exponent_ += shift_amount / kBigitSize;
+ int local_shift = shift_amount % kBigitSize;
+ EnsureCapacity(used_digits_ + 1);
+ BigitsShiftLeft(local_shift);
+}
+
+
+void Bignum::MultiplyByUInt32(uint32_t factor) {
+ if (factor == 1) return;
+ if (factor == 0) {
+ Zero();
+ return;
+ }
+ if (used_digits_ == 0) return;
+
+ // The product of a bigit with the factor is of size kBigitSize + 32.
+ // Assert that this number + 1 (for the carry) fits into double chunk.
+ ASSERT(kDoubleChunkSize >= kBigitSize + 32 + 1);
+ DoubleChunk carry = 0;
+ for (int i = 0; i < used_digits_; ++i) {
+ DoubleChunk product = static_cast<DoubleChunk>(factor) * bigits_[i] + carry;
+ bigits_[i] = static_cast<Chunk>(product & kBigitMask);
+ carry = (product >> kBigitSize);
+ }
+ while (carry != 0) {
+ EnsureCapacity(used_digits_ + 1);
+ bigits_[used_digits_] = carry & kBigitMask;
+ used_digits_++;
+ carry >>= kBigitSize;
+ }
+}
+
+
+void Bignum::MultiplyByUInt64(uint64_t factor) {
+ if (factor == 1) return;
+ if (factor == 0) {
+ Zero();
+ return;
+ }
+ ASSERT(kBigitSize < 32);
+ uint64_t carry = 0;
+ uint64_t low = factor & 0xFFFFFFFF;
+ uint64_t high = factor >> 32;
+ for (int i = 0; i < used_digits_; ++i) {
+ uint64_t product_low = low * bigits_[i];
+ uint64_t product_high = high * bigits_[i];
+ uint64_t tmp = (carry & kBigitMask) + product_low;
+ bigits_[i] = tmp & kBigitMask;
+ carry = (carry >> kBigitSize) + (tmp >> kBigitSize) +
+ (product_high << (32 - kBigitSize));
+ }
+ while (carry != 0) {
+ EnsureCapacity(used_digits_ + 1);
+ bigits_[used_digits_] = carry & kBigitMask;
+ used_digits_++;
+ carry >>= kBigitSize;
+ }
+}
+
+
+void Bignum::MultiplyByPowerOfTen(int exponent) {
+ const uint64_t kFive27 = UINT64_2PART_C(0x6765c793, fa10079d);
+ const uint16_t kFive1 = 5;
+ const uint16_t kFive2 = kFive1 * 5;
+ const uint16_t kFive3 = kFive2 * 5;
+ const uint16_t kFive4 = kFive3 * 5;
+ const uint16_t kFive5 = kFive4 * 5;
+ const uint16_t kFive6 = kFive5 * 5;
+ const uint32_t kFive7 = kFive6 * 5;
+ const uint32_t kFive8 = kFive7 * 5;
+ const uint32_t kFive9 = kFive8 * 5;
+ const uint32_t kFive10 = kFive9 * 5;
+ const uint32_t kFive11 = kFive10 * 5;
+ const uint32_t kFive12 = kFive11 * 5;
+ const uint32_t kFive13 = kFive12 * 5;
+ const uint32_t kFive1_to_12[] =
+ { kFive1, kFive2, kFive3, kFive4, kFive5, kFive6,
+ kFive7, kFive8, kFive9, kFive10, kFive11, kFive12 };
+
+ ASSERT(exponent >= 0);
+ if (exponent == 0) return;
+ if (used_digits_ == 0) return;
+
+ // We shift by exponent at the end just before returning.
+ int remaining_exponent = exponent;
+ while (remaining_exponent >= 27) {
+ MultiplyByUInt64(kFive27);
+ remaining_exponent -= 27;
+ }
+ while (remaining_exponent >= 13) {
+ MultiplyByUInt32(kFive13);
+ remaining_exponent -= 13;
+ }
+ if (remaining_exponent > 0) {
+ MultiplyByUInt32(kFive1_to_12[remaining_exponent - 1]);
+ }
+ ShiftLeft(exponent);
+}
+
+
+void Bignum::Square() {
+ ASSERT(IsClamped());
+ int product_length = 2 * used_digits_;
+ EnsureCapacity(product_length);
+
+ // Comba multiplication: compute each column separately.
+ // Example: r = a2a1a0 * b2b1b0.
+ // r = 1 * a0b0 +
+ // 10 * (a1b0 + a0b1) +
+ // 100 * (a2b0 + a1b1 + a0b2) +
+ // 1000 * (a2b1 + a1b2) +
+ // 10000 * a2b2
+ //
+ // In the worst case we have to accumulate nb-digits products of digit*digit.
+ //
+ // Assert that the additional number of bits in a DoubleChunk are enough to
+ // sum up used_digits of Bigit*Bigit.
+ if ((1 << (2 * (kChunkSize - kBigitSize))) <= used_digits_) {
+ UNIMPLEMENTED();
+ }
+ DoubleChunk accumulator = 0;
+ // First shift the digits so we don't overwrite them.
+ int copy_offset = used_digits_;
+ for (int i = 0; i < used_digits_; ++i) {
+ bigits_[copy_offset + i] = bigits_[i];
+ }
+ // We have two loops to avoid some 'if's in the loop.
+ for (int i = 0; i < used_digits_; ++i) {
+ // Process temporary digit i with power i.
+ // The sum of the two indices must be equal to i.
+ int bigit_index1 = i;
+ int bigit_index2 = 0;
+ // Sum all of the sub-products.
+ while (bigit_index1 >= 0) {
+ Chunk chunk1 = bigits_[copy_offset + bigit_index1];
+ Chunk chunk2 = bigits_[copy_offset + bigit_index2];
+ accumulator += static_cast<DoubleChunk>(chunk1) * chunk2;
+ bigit_index1--;
+ bigit_index2++;
+ }
+ bigits_[i] = static_cast<Chunk>(accumulator) & kBigitMask;
+ accumulator >>= kBigitSize;
+ }
+ for (int i = used_digits_; i < product_length; ++i) {
+ int bigit_index1 = used_digits_ - 1;
+ int bigit_index2 = i - bigit_index1;
+ // Invariant: sum of both indices is again equal to i.
+ // Inner loop runs 0 times on last iteration, emptying accumulator.
+ while (bigit_index2 < used_digits_) {
+ Chunk chunk1 = bigits_[copy_offset + bigit_index1];
+ Chunk chunk2 = bigits_[copy_offset + bigit_index2];
+ accumulator += static_cast<DoubleChunk>(chunk1) * chunk2;
+ bigit_index1--;
+ bigit_index2++;
+ }
+ // The overwritten bigits_[i] will never be read in further loop iterations,
+ // because bigit_index1 and bigit_index2 are always greater
+ // than i - used_digits_.
+ bigits_[i] = static_cast<Chunk>(accumulator) & kBigitMask;
+ accumulator >>= kBigitSize;
+ }
+ // Since the result was guaranteed to lie inside the number the
+ // accumulator must be 0 now.
+ ASSERT(accumulator == 0);
+
+ // Don't forget to update the used_digits and the exponent.
+ used_digits_ = product_length;
+ exponent_ *= 2;
+ Clamp();
+}
+
+
+void Bignum::AssignPowerUInt16(uint16_t base, int power_exponent) {
+ ASSERT(base != 0);
+ ASSERT(power_exponent >= 0);
+ if (power_exponent == 0) {
+ AssignUInt16(1);
+ return;
+ }
+ Zero();
+ int shifts = 0;
+ // We expect base to be in range 2-32, and most often to be 10.
+ // It does not make much sense to implement different algorithms for counting
+ // the bits.
+ while ((base & 1) == 0) {
+ base >>= 1;
+ shifts++;
+ }
+ int bit_size = 0;
+ int tmp_base = base;
+ while (tmp_base != 0) {
+ tmp_base >>= 1;
+ bit_size++;
+ }
+ int final_size = bit_size * power_exponent;
+ // 1 extra bigit for the shifting, and one for rounded final_size.
+ EnsureCapacity(final_size / kBigitSize + 2);
+
+ // Left to Right exponentiation.
+ int mask = 1;
+ while (power_exponent >= mask) mask <<= 1;
+
+ // The mask is now pointing to the bit above the most significant 1-bit of
+ // power_exponent.
+ // Get rid of first 1-bit;
+ mask >>= 2;
+ uint64_t this_value = base;
+
+ bool delayed_multipliciation = false;
+ const uint64_t max_32bits = 0xFFFFFFFF;
+ while (mask != 0 && this_value <= max_32bits) {
+ this_value = this_value * this_value;
+ // Verify that there is enough space in this_value to perform the
+ // multiplication. The first bit_size bits must be 0.
+ if ((power_exponent & mask) != 0) {
+ uint64_t base_bits_mask =
+ ~((static_cast<uint64_t>(1) << (64 - bit_size)) - 1);
+ bool high_bits_zero = (this_value & base_bits_mask) == 0;
+ if (high_bits_zero) {
+ this_value *= base;
+ } else {
+ delayed_multipliciation = true;
+ }
+ }
+ mask >>= 1;
+ }
+ AssignUInt64(this_value);
+ if (delayed_multipliciation) {
+ MultiplyByUInt32(base);
+ }
+
+ // Now do the same thing as a bignum.
+ while (mask != 0) {
+ Square();
+ if ((power_exponent & mask) != 0) {
+ MultiplyByUInt32(base);
+ }
+ mask >>= 1;
+ }
+
+ // And finally add the saved shifts.
+ ShiftLeft(shifts * power_exponent);
+}
+
+
+// Precondition: this/other < 16bit.
+uint16_t Bignum::DivideModuloIntBignum(const Bignum& other) {
+ ASSERT(IsClamped());
+ ASSERT(other.IsClamped());
+ ASSERT(other.used_digits_ > 0);
+
+ // Easy case: if we have less digits than the divisor than the result is 0.
+ // Note: this handles the case where this == 0, too.
+ if (BigitLength() < other.BigitLength()) {
+ return 0;
+ }
+
+ Align(other);
+
+ uint16_t result = 0;
+
+ // Start by removing multiples of 'other' until both numbers have the same
+ // number of digits.
+ while (BigitLength() > other.BigitLength()) {
+ // This naive approach is extremely inefficient if `this` divided by other
+ // is big. This function is implemented for doubleToString where
+ // the result should be small (less than 10).
+ ASSERT(other.bigits_[other.used_digits_ - 1] >= ((1 << kBigitSize) / 16));
+ ASSERT(bigits_[used_digits_ - 1] < 0x10000);
+ // Remove the multiples of the first digit.
+ // Example this = 23 and other equals 9. -> Remove 2 multiples.
+ result += static_cast<uint16_t>(bigits_[used_digits_ - 1]);
+ SubtractTimes(other, bigits_[used_digits_ - 1]);
+ }
+
+ ASSERT(BigitLength() == other.BigitLength());
+
+ // Both bignums are at the same length now.
+ // Since other has more than 0 digits we know that the access to
+ // bigits_[used_digits_ - 1] is safe.
+ Chunk this_bigit = bigits_[used_digits_ - 1];
+ Chunk other_bigit = other.bigits_[other.used_digits_ - 1];
+
+ if (other.used_digits_ == 1) {
+ // Shortcut for easy (and common) case.
+ int quotient = this_bigit / other_bigit;
+ bigits_[used_digits_ - 1] = this_bigit - other_bigit * quotient;
+ ASSERT(quotient < 0x10000);
+ result += static_cast<uint16_t>(quotient);
+ Clamp();
+ return result;
+ }
+
+ int division_estimate = this_bigit / (other_bigit + 1);
+ ASSERT(division_estimate < 0x10000);
+ result += static_cast<uint16_t>(division_estimate);
+ SubtractTimes(other, division_estimate);
+
+ if (other_bigit * (division_estimate + 1) > this_bigit) {
+ // No need to even try to subtract. Even if other's remaining digits were 0
+ // another subtraction would be too much.
+ return result;
+ }
+
+ while (LessEqual(other, *this)) {
+ SubtractBignum(other);
+ result++;
+ }
+ return result;
+}
+
+
+template<typename S>
+static int SizeInHexChars(S number) {
+ ASSERT(number > 0);
+ int result = 0;
+ while (number != 0) {
+ number >>= 4;
+ result++;
+ }
+ return result;
+}
+
+
+static char HexCharOfValue(int value) {
+ ASSERT(0 <= value && value <= 16);
+ if (value < 10) return static_cast<char>(value + '0');
+ return static_cast<char>(value - 10 + 'A');
+}
+
+
+bool Bignum::ToHexString(char* buffer, int buffer_size) const {
+ ASSERT(IsClamped());
+ // Each bigit must be printable as separate hex-character.
+ ASSERT(kBigitSize % 4 == 0);
+ const int kHexCharsPerBigit = kBigitSize / 4;
+
+ if (used_digits_ == 0) {
+ if (buffer_size < 2) return false;
+ buffer[0] = '0';
+ buffer[1] = '\0';
+ return true;
+ }
+ // We add 1 for the terminating '\0' character.
+ int needed_chars = (BigitLength() - 1) * kHexCharsPerBigit +
+ SizeInHexChars(bigits_[used_digits_ - 1]) + 1;
+ if (needed_chars > buffer_size) return false;
+ int string_index = needed_chars - 1;
+ buffer[string_index--] = '\0';
+ for (int i = 0; i < exponent_; ++i) {
+ for (int j = 0; j < kHexCharsPerBigit; ++j) {
+ buffer[string_index--] = '0';
+ }
+ }
+ for (int i = 0; i < used_digits_ - 1; ++i) {
+ Chunk current_bigit = bigits_[i];
+ for (int j = 0; j < kHexCharsPerBigit; ++j) {
+ buffer[string_index--] = HexCharOfValue(current_bigit & 0xF);
+ current_bigit >>= 4;
+ }
+ }
+ // And finally the last bigit.
+ Chunk most_significant_bigit = bigits_[used_digits_ - 1];
+ while (most_significant_bigit != 0) {
+ buffer[string_index--] = HexCharOfValue(most_significant_bigit & 0xF);
+ most_significant_bigit >>= 4;
+ }
+ return true;
+}
+
+
+Bignum::Chunk Bignum::BigitAt(int index) const {
+ if (index >= BigitLength()) return 0;
+ if (index < exponent_) return 0;
+ return bigits_[index - exponent_];
+}
+
+
+int Bignum::Compare(const Bignum& a, const Bignum& b) {
+ ASSERT(a.IsClamped());
+ ASSERT(b.IsClamped());
+ int bigit_length_a = a.BigitLength();
+ int bigit_length_b = b.BigitLength();
+ if (bigit_length_a < bigit_length_b) return -1;
+ if (bigit_length_a > bigit_length_b) return +1;
+ for (int i = bigit_length_a - 1; i >= Min(a.exponent_, b.exponent_); --i) {
+ Chunk bigit_a = a.BigitAt(i);
+ Chunk bigit_b = b.BigitAt(i);
+ if (bigit_a < bigit_b) return -1;
+ if (bigit_a > bigit_b) return +1;
+ // Otherwise they are equal up to this digit. Try the next digit.
+ }
+ return 0;
+}
+
+
+int Bignum::PlusCompare(const Bignum& a, const Bignum& b, const Bignum& c) {
+ ASSERT(a.IsClamped());
+ ASSERT(b.IsClamped());
+ ASSERT(c.IsClamped());
+ if (a.BigitLength() < b.BigitLength()) {
+ return PlusCompare(b, a, c);
+ }
+ if (a.BigitLength() + 1 < c.BigitLength()) return -1;
+ if (a.BigitLength() > c.BigitLength()) return +1;
+ // The exponent encodes 0-bigits. So if there are more 0-digits in 'a' than
+ // 'b' has digits, then the bigit-length of 'a'+'b' must be equal to the one
+ // of 'a'.
+ if (a.exponent_ >= b.BigitLength() && a.BigitLength() < c.BigitLength()) {
+ return -1;
+ }
+
+ Chunk borrow = 0;
+ // Starting at min_exponent all digits are == 0. So no need to compare them.
+ int min_exponent = Min(Min(a.exponent_, b.exponent_), c.exponent_);
+ for (int i = c.BigitLength() - 1; i >= min_exponent; --i) {
+ Chunk chunk_a = a.BigitAt(i);
+ Chunk chunk_b = b.BigitAt(i);
+ Chunk chunk_c = c.BigitAt(i);
+ Chunk sum = chunk_a + chunk_b;
+ if (sum > chunk_c + borrow) {
+ return +1;
+ } else {
+ borrow = chunk_c + borrow - sum;
+ if (borrow > 1) return -1;
+ borrow <<= kBigitSize;
+ }
+ }
+ if (borrow == 0) return 0;
+ return -1;
+}
+
+
+void Bignum::Clamp() {
+ while (used_digits_ > 0 && bigits_[used_digits_ - 1] == 0) {
+ used_digits_--;
+ }
+ if (used_digits_ == 0) {
+ // Zero.
+ exponent_ = 0;
+ }
+}
+
+
+bool Bignum::IsClamped() const {
+ return used_digits_ == 0 || bigits_[used_digits_ - 1] != 0;
+}
+
+
+void Bignum::Zero() {
+ for (int i = 0; i < used_digits_; ++i) {
+ bigits_[i] = 0;
+ }
+ used_digits_ = 0;
+ exponent_ = 0;
+}
+
+
+void Bignum::Align(const Bignum& other) {
+ if (exponent_ > other.exponent_) {
+ // If "X" represents a "hidden" digit (by the exponent) then we are in the
+ // following case (a == this, b == other):
+ // a: aaaaaaXXXX or a: aaaaaXXX
+ // b: bbbbbbX b: bbbbbbbbXX
+ // We replace some of the hidden digits (X) of a with 0 digits.
+ // a: aaaaaa000X or a: aaaaa0XX
+ int zero_digits = exponent_ - other.exponent_;
+ EnsureCapacity(used_digits_ + zero_digits);
+ for (int i = used_digits_ - 1; i >= 0; --i) {
+ bigits_[i + zero_digits] = bigits_[i];
+ }
+ for (int i = 0; i < zero_digits; ++i) {
+ bigits_[i] = 0;
+ }
+ used_digits_ += zero_digits;
+ exponent_ -= zero_digits;
+ ASSERT(used_digits_ >= 0);
+ ASSERT(exponent_ >= 0);
+ }
+}
+
+
+void Bignum::BigitsShiftLeft(int shift_amount) {
+ ASSERT(shift_amount < kBigitSize);
+ ASSERT(shift_amount >= 0);
+ Chunk carry = 0;
+ for (int i = 0; i < used_digits_; ++i) {
+ Chunk new_carry = bigits_[i] >> (kBigitSize - shift_amount);
+ bigits_[i] = ((bigits_[i] << shift_amount) + carry) & kBigitMask;
+ carry = new_carry;
+ }
+ if (carry != 0) {
+ bigits_[used_digits_] = carry;
+ used_digits_++;
+ }
+}
+
+
+void Bignum::SubtractTimes(const Bignum& other, int factor) {
+ ASSERT(exponent_ <= other.exponent_);
+ if (factor < 3) {
+ for (int i = 0; i < factor; ++i) {
+ SubtractBignum(other);
+ }
+ return;
+ }
+ Chunk borrow = 0;
+ int exponent_diff = other.exponent_ - exponent_;
+ for (int i = 0; i < other.used_digits_; ++i) {
+ DoubleChunk product = static_cast<DoubleChunk>(factor) * other.bigits_[i];
+ DoubleChunk remove = borrow + product;
+ Chunk difference = bigits_[i + exponent_diff] - (remove & kBigitMask);
+ bigits_[i + exponent_diff] = difference & kBigitMask;
+ borrow = static_cast<Chunk>((difference >> (kChunkSize - 1)) +
+ (remove >> kBigitSize));
+ }
+ for (int i = other.used_digits_ + exponent_diff; i < used_digits_; ++i) {
+ if (borrow == 0) return;
+ Chunk difference = bigits_[i] - borrow;
+ bigits_[i] = difference & kBigitMask;
+ borrow = difference >> (kChunkSize - 1);
+ }
+ Clamp();
+}
+
+
+} // namespace double_conversion
+
+// ICU PATCH: Close ICU namespace
+U_NAMESPACE_END
+#endif // ICU PATCH: close #if !UCONFIG_NO_FORMATTING
diff --git a/Build/source/libs/icu/icu-src/source/i18n/double-conversion-bignum.h b/Build/source/libs/icu/icu-src/source/i18n/double-conversion-bignum.h
new file mode 100644
index 00000000000..d1af3bf5e77
--- /dev/null
+++ b/Build/source/libs/icu/icu-src/source/i18n/double-conversion-bignum.h
@@ -0,0 +1,162 @@
+// © 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_BIGNUM_H_
+#define DOUBLE_CONVERSION_BIGNUM_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 {
+
+class Bignum {
+ public:
+ // 3584 = 128 * 28. We can represent 2^3584 > 10^1000 accurately.
+ // This bignum can encode much bigger numbers, since it contains an
+ // exponent.
+ static const int kMaxSignificantBits = 3584;
+
+ Bignum();
+ void AssignUInt16(uint16_t value);
+ void AssignUInt64(uint64_t value);
+ void AssignBignum(const Bignum& other);
+
+ void AssignDecimalString(Vector<const char> value);
+ void AssignHexString(Vector<const char> value);
+
+ void AssignPowerUInt16(uint16_t base, int exponent);
+
+ void AddUInt64(uint64_t operand);
+ void AddBignum(const Bignum& other);
+ // Precondition: this >= other.
+ void SubtractBignum(const Bignum& other);
+
+ void Square();
+ void ShiftLeft(int shift_amount);
+ void MultiplyByUInt32(uint32_t factor);
+ void MultiplyByUInt64(uint64_t factor);
+ void MultiplyByPowerOfTen(int exponent);
+ void Times10() { return MultiplyByUInt32(10); }
+ // Pseudocode:
+ // int result = this / other;
+ // this = this % other;
+ // In the worst case this function is in O(this/other).
+ uint16_t DivideModuloIntBignum(const Bignum& other);
+
+ bool ToHexString(char* buffer, int buffer_size) const;
+
+ // Returns
+ // -1 if a < b,
+ // 0 if a == b, and
+ // +1 if a > b.
+ static int Compare(const Bignum& a, const Bignum& b);
+ static bool Equal(const Bignum& a, const Bignum& b) {
+ return Compare(a, b) == 0;
+ }
+ static bool LessEqual(const Bignum& a, const Bignum& b) {
+ return Compare(a, b) <= 0;
+ }
+ static bool Less(const Bignum& a, const Bignum& b) {
+ return Compare(a, b) < 0;
+ }
+ // Returns Compare(a + b, c);
+ static int PlusCompare(const Bignum& a, const Bignum& b, const Bignum& c);
+ // Returns a + b == c
+ static bool PlusEqual(const Bignum& a, const Bignum& b, const Bignum& c) {
+ return PlusCompare(a, b, c) == 0;
+ }
+ // Returns a + b <= c
+ static bool PlusLessEqual(const Bignum& a, const Bignum& b, const Bignum& c) {
+ return PlusCompare(a, b, c) <= 0;
+ }
+ // Returns a + b < c
+ static bool PlusLess(const Bignum& a, const Bignum& b, const Bignum& c) {
+ return PlusCompare(a, b, c) < 0;
+ }
+ private:
+ typedef uint32_t Chunk;
+ typedef uint64_t DoubleChunk;
+
+ static const int kChunkSize = sizeof(Chunk) * 8;
+ static const int kDoubleChunkSize = sizeof(DoubleChunk) * 8;
+ // With bigit size of 28 we loose some bits, but a double still fits easily
+ // into two chunks, and more importantly we can use the Comba multiplication.
+ static const int kBigitSize = 28;
+ static const Chunk kBigitMask = (1 << kBigitSize) - 1;
+ // Every instance allocates kBigitLength chunks on the stack. Bignums cannot
+ // grow. There are no checks if the stack-allocated space is sufficient.
+ static const int kBigitCapacity = kMaxSignificantBits / kBigitSize;
+
+ void EnsureCapacity(int size) {
+ if (size > kBigitCapacity) {
+ UNREACHABLE();
+ }
+ }
+ void Align(const Bignum& other);
+ void Clamp();
+ bool IsClamped() const;
+ void Zero();
+ // Requires this to have enough capacity (no tests done).
+ // Updates used_digits_ if necessary.
+ // shift_amount must be < kBigitSize.
+ void BigitsShiftLeft(int shift_amount);
+ // BigitLength includes the "hidden" digits encoded in the exponent.
+ int BigitLength() const { return used_digits_ + exponent_; }
+ Chunk BigitAt(int index) const;
+ void SubtractTimes(const Bignum& other, int factor);
+
+ Chunk bigits_buffer_[kBigitCapacity];
+ // A vector backed by bigits_buffer_. This way accesses to the array are
+ // checked for out-of-bounds errors.
+ Vector<Chunk> bigits_;
+ int used_digits_;
+ // The Bignum's value equals value(bigits_) * 2^(exponent_ * kBigitSize).
+ int exponent_;
+
+ DISALLOW_COPY_AND_ASSIGN(Bignum);
+};
+
+} // namespace double_conversion
+
+// ICU PATCH: Close ICU namespace
+U_NAMESPACE_END
+
+#endif // DOUBLE_CONVERSION_BIGNUM_H_
+#endif // ICU PATCH: close #if !UCONFIG_NO_FORMATTING
diff --git a/Build/source/libs/icu/icu-src/source/i18n/double-conversion-cached-powers.cpp b/Build/source/libs/icu/icu-src/source/i18n/double-conversion-cached-powers.cpp
new file mode 100644
index 00000000000..e49700444c6
--- /dev/null
+++ b/Build/source/libs/icu/icu-src/source/i18n/double-conversion-cached-powers.cpp
@@ -0,0 +1,193 @@
+// © 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 2006-2008 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 <stdarg.h>
+#include <limits.h>
+#include <math.h>
+
+// ICU PATCH: Customize header file paths for ICU.
+
+#include "double-conversion-utils.h"
+
+#include "double-conversion-cached-powers.h"
+
+// ICU PATCH: Wrap in ICU namespace
+U_NAMESPACE_BEGIN
+
+namespace double_conversion {
+
+struct CachedPower {
+ uint64_t significand;
+ int16_t binary_exponent;
+ int16_t decimal_exponent;
+};
+
+static const CachedPower kCachedPowers[] = {
+ {UINT64_2PART_C(0xfa8fd5a0, 081c0288), -1220, -348},
+ {UINT64_2PART_C(0xbaaee17f, a23ebf76), -1193, -340},
+ {UINT64_2PART_C(0x8b16fb20, 3055ac76), -1166, -332},
+ {UINT64_2PART_C(0xcf42894a, 5dce35ea), -1140, -324},
+ {UINT64_2PART_C(0x9a6bb0aa, 55653b2d), -1113, -316},
+ {UINT64_2PART_C(0xe61acf03, 3d1a45df), -1087, -308},
+ {UINT64_2PART_C(0xab70fe17, c79ac6ca), -1060, -300},
+ {UINT64_2PART_C(0xff77b1fc, bebcdc4f), -1034, -292},
+ {UINT64_2PART_C(0xbe5691ef, 416bd60c), -1007, -284},
+ {UINT64_2PART_C(0x8dd01fad, 907ffc3c), -980, -276},
+ {UINT64_2PART_C(0xd3515c28, 31559a83), -954, -268},
+ {UINT64_2PART_C(0x9d71ac8f, ada6c9b5), -927, -260},
+ {UINT64_2PART_C(0xea9c2277, 23ee8bcb), -901, -252},
+ {UINT64_2PART_C(0xaecc4991, 4078536d), -874, -244},
+ {UINT64_2PART_C(0x823c1279, 5db6ce57), -847, -236},
+ {UINT64_2PART_C(0xc2109436, 4dfb5637), -821, -228},
+ {UINT64_2PART_C(0x9096ea6f, 3848984f), -794, -220},
+ {UINT64_2PART_C(0xd77485cb, 25823ac7), -768, -212},
+ {UINT64_2PART_C(0xa086cfcd, 97bf97f4), -741, -204},
+ {UINT64_2PART_C(0xef340a98, 172aace5), -715, -196},
+ {UINT64_2PART_C(0xb23867fb, 2a35b28e), -688, -188},
+ {UINT64_2PART_C(0x84c8d4df, d2c63f3b), -661, -180},
+ {UINT64_2PART_C(0xc5dd4427, 1ad3cdba), -635, -172},
+ {UINT64_2PART_C(0x936b9fce, bb25c996), -608, -164},
+ {UINT64_2PART_C(0xdbac6c24, 7d62a584), -582, -156},
+ {UINT64_2PART_C(0xa3ab6658, 0d5fdaf6), -555, -148},
+ {UINT64_2PART_C(0xf3e2f893, dec3f126), -529, -140},
+ {UINT64_2PART_C(0xb5b5ada8, aaff80b8), -502, -132},
+ {UINT64_2PART_C(0x87625f05, 6c7c4a8b), -475, -124},
+ {UINT64_2PART_C(0xc9bcff60, 34c13053), -449, -116},
+ {UINT64_2PART_C(0x964e858c, 91ba2655), -422, -108},
+ {UINT64_2PART_C(0xdff97724, 70297ebd), -396, -100},
+ {UINT64_2PART_C(0xa6dfbd9f, b8e5b88f), -369, -92},
+ {UINT64_2PART_C(0xf8a95fcf, 88747d94), -343, -84},
+ {UINT64_2PART_C(0xb9447093, 8fa89bcf), -316, -76},
+ {UINT64_2PART_C(0x8a08f0f8, bf0f156b), -289, -68},
+ {UINT64_2PART_C(0xcdb02555, 653131b6), -263, -60},
+ {UINT64_2PART_C(0x993fe2c6, d07b7fac), -236, -52},
+ {UINT64_2PART_C(0xe45c10c4, 2a2b3b06), -210, -44},
+ {UINT64_2PART_C(0xaa242499, 697392d3), -183, -36},
+ {UINT64_2PART_C(0xfd87b5f2, 8300ca0e), -157, -28},
+ {UINT64_2PART_C(0xbce50864, 92111aeb), -130, -20},
+ {UINT64_2PART_C(0x8cbccc09, 6f5088cc), -103, -12},
+ {UINT64_2PART_C(0xd1b71758, e219652c), -77, -4},
+ {UINT64_2PART_C(0x9c400000, 00000000), -50, 4},
+ {UINT64_2PART_C(0xe8d4a510, 00000000), -24, 12},
+ {UINT64_2PART_C(0xad78ebc5, ac620000), 3, 20},
+ {UINT64_2PART_C(0x813f3978, f8940984), 30, 28},
+ {UINT64_2PART_C(0xc097ce7b, c90715b3), 56, 36},
+ {UINT64_2PART_C(0x8f7e32ce, 7bea5c70), 83, 44},
+ {UINT64_2PART_C(0xd5d238a4, abe98068), 109, 52},
+ {UINT64_2PART_C(0x9f4f2726, 179a2245), 136, 60},
+ {UINT64_2PART_C(0xed63a231, d4c4fb27), 162, 68},
+ {UINT64_2PART_C(0xb0de6538, 8cc8ada8), 189, 76},
+ {UINT64_2PART_C(0x83c7088e, 1aab65db), 216, 84},
+ {UINT64_2PART_C(0xc45d1df9, 42711d9a), 242, 92},
+ {UINT64_2PART_C(0x924d692c, a61be758), 269, 100},
+ {UINT64_2PART_C(0xda01ee64, 1a708dea), 295, 108},
+ {UINT64_2PART_C(0xa26da399, 9aef774a), 322, 116},
+ {UINT64_2PART_C(0xf209787b, b47d6b85), 348, 124},
+ {UINT64_2PART_C(0xb454e4a1, 79dd1877), 375, 132},
+ {UINT64_2PART_C(0x865b8692, 5b9bc5c2), 402, 140},
+ {UINT64_2PART_C(0xc83553c5, c8965d3d), 428, 148},
+ {UINT64_2PART_C(0x952ab45c, fa97a0b3), 455, 156},
+ {UINT64_2PART_C(0xde469fbd, 99a05fe3), 481, 164},
+ {UINT64_2PART_C(0xa59bc234, db398c25), 508, 172},
+ {UINT64_2PART_C(0xf6c69a72, a3989f5c), 534, 180},
+ {UINT64_2PART_C(0xb7dcbf53, 54e9bece), 561, 188},
+ {UINT64_2PART_C(0x88fcf317, f22241e2), 588, 196},
+ {UINT64_2PART_C(0xcc20ce9b, d35c78a5), 614, 204},
+ {UINT64_2PART_C(0x98165af3, 7b2153df), 641, 212},
+ {UINT64_2PART_C(0xe2a0b5dc, 971f303a), 667, 220},
+ {UINT64_2PART_C(0xa8d9d153, 5ce3b396), 694, 228},
+ {UINT64_2PART_C(0xfb9b7cd9, a4a7443c), 720, 236},
+ {UINT64_2PART_C(0xbb764c4c, a7a44410), 747, 244},
+ {UINT64_2PART_C(0x8bab8eef, b6409c1a), 774, 252},
+ {UINT64_2PART_C(0xd01fef10, a657842c), 800, 260},
+ {UINT64_2PART_C(0x9b10a4e5, e9913129), 827, 268},
+ {UINT64_2PART_C(0xe7109bfb, a19c0c9d), 853, 276},
+ {UINT64_2PART_C(0xac2820d9, 623bf429), 880, 284},
+ {UINT64_2PART_C(0x80444b5e, 7aa7cf85), 907, 292},
+ {UINT64_2PART_C(0xbf21e440, 03acdd2d), 933, 300},
+ {UINT64_2PART_C(0x8e679c2f, 5e44ff8f), 960, 308},
+ {UINT64_2PART_C(0xd433179d, 9c8cb841), 986, 316},
+ {UINT64_2PART_C(0x9e19db92, b4e31ba9), 1013, 324},
+ {UINT64_2PART_C(0xeb96bf6e, badf77d9), 1039, 332},
+ {UINT64_2PART_C(0xaf87023b, 9bf0ee6b), 1066, 340},
+};
+
+static const int kCachedPowersOffset = 348; // -1 * the first decimal_exponent.
+static const double kD_1_LOG2_10 = 0.30102999566398114; // 1 / lg(10)
+// Difference between the decimal exponents in the table above.
+const int PowersOfTenCache::kDecimalExponentDistance = 8;
+const int PowersOfTenCache::kMinDecimalExponent = -348;
+const int PowersOfTenCache::kMaxDecimalExponent = 340;
+
+void PowersOfTenCache::GetCachedPowerForBinaryExponentRange(
+ int min_exponent,
+ int max_exponent,
+ DiyFp* power,
+ int* decimal_exponent) {
+ int kQ = DiyFp::kSignificandSize;
+ double k = ceil((min_exponent + kQ - 1) * kD_1_LOG2_10);
+ int foo = kCachedPowersOffset;
+ int index =
+ (foo + static_cast<int>(k) - 1) / kDecimalExponentDistance + 1;
+ ASSERT(0 <= index && index < static_cast<int>(ARRAY_SIZE(kCachedPowers)));
+ CachedPower cached_power = kCachedPowers[index];
+ ASSERT(min_exponent <= cached_power.binary_exponent);
+ (void) max_exponent; // Mark variable as used.
+ ASSERT(cached_power.binary_exponent <= max_exponent);
+ *decimal_exponent = cached_power.decimal_exponent;
+ *power = DiyFp(cached_power.significand, cached_power.binary_exponent);
+}
+
+
+void PowersOfTenCache::GetCachedPowerForDecimalExponent(int requested_exponent,
+ DiyFp* power,
+ int* found_exponent) {
+ ASSERT(kMinDecimalExponent <= requested_exponent);
+ ASSERT(requested_exponent < kMaxDecimalExponent + kDecimalExponentDistance);
+ int index =
+ (requested_exponent + kCachedPowersOffset) / kDecimalExponentDistance;
+ CachedPower cached_power = kCachedPowers[index];
+ *power = DiyFp(cached_power.significand, cached_power.binary_exponent);
+ *found_exponent = cached_power.decimal_exponent;
+ ASSERT(*found_exponent <= requested_exponent);
+ ASSERT(requested_exponent < *found_exponent + kDecimalExponentDistance);
+}
+
+} // namespace double_conversion
+
+// ICU PATCH: Close ICU namespace
+U_NAMESPACE_END
+#endif // ICU PATCH: close #if !UCONFIG_NO_FORMATTING
diff --git a/Build/source/libs/icu/icu-src/source/i18n/double-conversion-cached-powers.h b/Build/source/libs/icu/icu-src/source/i18n/double-conversion-cached-powers.h
new file mode 100644
index 00000000000..438746b1432
--- /dev/null
+++ b/Build/source/libs/icu/icu-src/source/i18n/double-conversion-cached-powers.h
@@ -0,0 +1,82 @@
+// © 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_CACHED_POWERS_H_
+#define DOUBLE_CONVERSION_CACHED_POWERS_H_
+
+// ICU PATCH: Customize header file paths for ICU.
+
+#include "double-conversion-diy-fp.h"
+
+// ICU PATCH: Wrap in ICU namespace
+U_NAMESPACE_BEGIN
+
+namespace double_conversion {
+
+class PowersOfTenCache {
+ public:
+
+ // Not all powers of ten are cached. The decimal exponent of two neighboring
+ // cached numbers will differ by kDecimalExponentDistance.
+ static const int kDecimalExponentDistance;
+
+ static const int kMinDecimalExponent;
+ static const int kMaxDecimalExponent;
+
+ // Returns a cached power-of-ten with a binary exponent in the range
+ // [min_exponent; max_exponent] (boundaries included).
+ static void GetCachedPowerForBinaryExponentRange(int min_exponent,
+ int max_exponent,
+ DiyFp* power,
+ int* decimal_exponent);
+
+ // Returns a cached power of ten x ~= 10^k such that
+ // k <= decimal_exponent < k + kCachedPowersDecimalDistance.
+ // The given decimal_exponent must satisfy
+ // kMinDecimalExponent <= requested_exponent, and
+ // requested_exponent < kMaxDecimalExponent + kDecimalExponentDistance.
+ static void GetCachedPowerForDecimalExponent(int requested_exponent,
+ DiyFp* power,
+ int* found_exponent);
+};
+
+} // namespace double_conversion
+
+// ICU PATCH: Close ICU namespace
+U_NAMESPACE_END
+
+#endif // DOUBLE_CONVERSION_CACHED_POWERS_H_
+#endif // ICU PATCH: close #if !UCONFIG_NO_FORMATTING
diff --git a/Build/source/libs/icu/icu-src/source/i18n/double-conversion-diy-fp.cpp b/Build/source/libs/icu/icu-src/source/i18n/double-conversion-diy-fp.cpp
new file mode 100644
index 00000000000..f38430c6c3c
--- /dev/null
+++ b/Build/source/libs/icu/icu-src/source/i18n/double-conversion-diy-fp.cpp
@@ -0,0 +1,74 @@
+// © 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
+
+// ICU PATCH: Customize header file paths for ICU.
+
+#include "double-conversion-diy-fp.h"
+#include "double-conversion-utils.h"
+
+// ICU PATCH: Wrap in ICU namespace
+U_NAMESPACE_BEGIN
+
+namespace double_conversion {
+
+void DiyFp::Multiply(const DiyFp& other) {
+ // Simply "emulates" a 128 bit multiplication.
+ // However: the resulting number only contains 64 bits. The least
+ // significant 64 bits are only used for rounding the most significant 64
+ // bits.
+ const uint64_t kM32 = 0xFFFFFFFFU;
+ uint64_t a = f_ >> 32;
+ uint64_t b = f_ & kM32;
+ uint64_t c = other.f_ >> 32;
+ uint64_t d = other.f_ & kM32;
+ uint64_t ac = a * c;
+ uint64_t bc = b * c;
+ uint64_t ad = a * d;
+ uint64_t bd = b * d;
+ uint64_t tmp = (bd >> 32) + (ad & kM32) + (bc & kM32);
+ // By adding 1U << 31 to tmp we round the final result.
+ // Halfway cases will be round up.
+ tmp += 1U << 31;
+ uint64_t result_f = ac + (ad >> 32) + (bc >> 32) + (tmp >> 32);
+ e_ += other.e_ + 64;
+ f_ = result_f;
+}
+
+} // namespace double_conversion
+
+// ICU PATCH: Close ICU namespace
+U_NAMESPACE_END
+#endif // ICU PATCH: close #if !UCONFIG_NO_FORMATTING
diff --git a/Build/source/libs/icu/icu-src/source/i18n/double-conversion-diy-fp.h b/Build/source/libs/icu/icu-src/source/i18n/double-conversion-diy-fp.h
new file mode 100644
index 00000000000..21896851d22
--- /dev/null
+++ b/Build/source/libs/icu/icu-src/source/i18n/double-conversion-diy-fp.h
@@ -0,0 +1,136 @@
+// © 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_DIY_FP_H_
+#define DOUBLE_CONVERSION_DIY_FP_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 {
+
+// This "Do It Yourself Floating Point" class implements a floating-point number
+// with a uint64 significand and an int exponent. Normalized DiyFp numbers will
+// have the most significant bit of the significand set.
+// Multiplication and Subtraction do not normalize their results.
+// DiyFp are not designed to contain special doubles (NaN and Infinity).
+class DiyFp {
+ public:
+ static const int kSignificandSize = 64;
+
+ DiyFp() : f_(0), e_(0) {}
+ DiyFp(uint64_t significand, int exponent) : f_(significand), e_(exponent) {}
+
+ // this = this - other.
+ // The exponents of both numbers must be the same and the significand of this
+ // must be bigger than the significand of other.
+ // The result will not be normalized.
+ void Subtract(const DiyFp& other) {
+ ASSERT(e_ == other.e_);
+ ASSERT(f_ >= other.f_);
+ f_ -= other.f_;
+ }
+
+ // Returns a - b.
+ // The exponents of both numbers must be the same and this must be bigger
+ // than other. The result will not be normalized.
+ static DiyFp Minus(const DiyFp& a, const DiyFp& b) {
+ DiyFp result = a;
+ result.Subtract(b);
+ return result;
+ }
+
+
+ // this = this * other.
+ void Multiply(const DiyFp& other);
+
+ // returns a * b;
+ static DiyFp Times(const DiyFp& a, const DiyFp& b) {
+ DiyFp result = a;
+ result.Multiply(b);
+ return result;
+ }
+
+ void Normalize() {
+ ASSERT(f_ != 0);
+ uint64_t significand = f_;
+ int exponent = e_;
+
+ // This method is mainly called for normalizing boundaries. In general
+ // boundaries need to be shifted by 10 bits. We thus optimize for this case.
+ const uint64_t k10MSBits = UINT64_2PART_C(0xFFC00000, 00000000);
+ while ((significand & k10MSBits) == 0) {
+ significand <<= 10;
+ exponent -= 10;
+ }
+ while ((significand & kUint64MSB) == 0) {
+ significand <<= 1;
+ exponent--;
+ }
+ f_ = significand;
+ e_ = exponent;
+ }
+
+ static DiyFp Normalize(const DiyFp& a) {
+ DiyFp result = a;
+ result.Normalize();
+ return result;
+ }
+
+ uint64_t f() const { return f_; }
+ int e() const { return e_; }
+
+ void set_f(uint64_t new_value) { f_ = new_value; }
+ void set_e(int new_value) { e_ = new_value; }
+
+ private:
+ static const uint64_t kUint64MSB = UINT64_2PART_C(0x80000000, 00000000);
+
+ uint64_t f_;
+ int e_;
+};
+
+} // namespace double_conversion
+
+// ICU PATCH: Close ICU namespace
+U_NAMESPACE_END
+
+#endif // DOUBLE_CONVERSION_DIY_FP_H_
+#endif // ICU PATCH: close #if !UCONFIG_NO_FORMATTING
diff --git a/Build/source/libs/icu/icu-src/source/i18n/double-conversion-fast-dtoa.cpp b/Build/source/libs/icu/icu-src/source/i18n/double-conversion-fast-dtoa.cpp
new file mode 100644
index 00000000000..8d1499a79b4
--- /dev/null
+++ b/Build/source/libs/icu/icu-src/source/i18n/double-conversion-fast-dtoa.cpp
@@ -0,0 +1,683 @@
+// © 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 2012 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
+
+// ICU PATCH: Customize header file paths for ICU.
+
+#include "double-conversion-fast-dtoa.h"
+
+#include "double-conversion-cached-powers.h"
+#include "double-conversion-diy-fp.h"
+#include "double-conversion-ieee.h"
+
+// ICU PATCH: Wrap in ICU namespace
+U_NAMESPACE_BEGIN
+
+namespace double_conversion {
+
+// The minimal and maximal target exponent define the range of w's binary
+// exponent, where 'w' is the result of multiplying the input by a cached power
+// of ten.
+//
+// A different range might be chosen on a different platform, to optimize digit
+// generation, but a smaller range requires more powers of ten to be cached.
+static const int kMinimalTargetExponent = -60;
+static const int kMaximalTargetExponent = -32;
+
+
+// Adjusts the last digit of the generated number, and screens out generated
+// solutions that may be inaccurate. A solution may be inaccurate if it is
+// outside the safe interval, or if we cannot prove that it is closer to the
+// input than a neighboring representation of the same length.
+//
+// Input: * buffer containing the digits of too_high / 10^kappa
+// * the buffer's length
+// * distance_too_high_w == (too_high - w).f() * unit
+// * unsafe_interval == (too_high - too_low).f() * unit
+// * rest = (too_high - buffer * 10^kappa).f() * unit
+// * ten_kappa = 10^kappa * unit
+// * unit = the common multiplier
+// Output: returns true if the buffer is guaranteed to contain the closest
+// representable number to the input.
+// Modifies the generated digits in the buffer to approach (round towards) w.
+static bool RoundWeed(Vector<char> buffer,
+ int length,
+ uint64_t distance_too_high_w,
+ uint64_t unsafe_interval,
+ uint64_t rest,
+ uint64_t ten_kappa,
+ uint64_t unit) {
+ uint64_t small_distance = distance_too_high_w - unit;
+ uint64_t big_distance = distance_too_high_w + unit;
+ // Let w_low = too_high - big_distance, and
+ // w_high = too_high - small_distance.
+ // Note: w_low < w < w_high
+ //
+ // The real w (* unit) must lie somewhere inside the interval
+ // ]w_low; w_high[ (often written as "(w_low; w_high)")
+
+ // Basically the buffer currently contains a number in the unsafe interval
+ // ]too_low; too_high[ with too_low < w < too_high
+ //
+ // too_high - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ // ^v 1 unit ^ ^ ^ ^
+ // boundary_high --------------------- . . . .
+ // ^v 1 unit . . . .
+ // - - - - - - - - - - - - - - - - - - - + - - + - - - - - - . .
+ // . . ^ . .
+ // . big_distance . . .
+ // . . . . rest
+ // small_distance . . . .
+ // v . . . .
+ // w_high - - - - - - - - - - - - - - - - - - . . . .
+ // ^v 1 unit . . . .
+ // w ---------------------------------------- . . . .
+ // ^v 1 unit v . . .
+ // w_low - - - - - - - - - - - - - - - - - - - - - . . .
+ // . . v
+ // buffer --------------------------------------------------+-------+--------
+ // . .
+ // safe_interval .
+ // v .
+ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - .
+ // ^v 1 unit .
+ // boundary_low ------------------------- unsafe_interval
+ // ^v 1 unit v
+ // too_low - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ //
+ //
+ // Note that the value of buffer could lie anywhere inside the range too_low
+ // to too_high.
+ //
+ // boundary_low, boundary_high and w are approximations of the real boundaries
+ // and v (the input number). They are guaranteed to be precise up to one unit.
+ // In fact the error is guaranteed to be strictly less than one unit.
+ //
+ // Anything that lies outside the unsafe interval is guaranteed not to round
+ // to v when read again.
+ // Anything that lies inside the safe interval is guaranteed to round to v
+ // when read again.
+ // If the number inside the buffer lies inside the unsafe interval but not
+ // inside the safe interval then we simply do not know and bail out (returning
+ // false).
+ //
+ // Similarly we have to take into account the imprecision of 'w' when finding
+ // the closest representation of 'w'. If we have two potential
+ // representations, and one is closer to both w_low and w_high, then we know
+ // it is closer to the actual value v.
+ //
+ // By generating the digits of too_high we got the largest (closest to
+ // too_high) buffer that is still in the unsafe interval. In the case where
+ // w_high < buffer < too_high we try to decrement the buffer.
+ // This way the buffer approaches (rounds towards) w.
+ // There are 3 conditions that stop the decrementation process:
+ // 1) the buffer is already below w_high
+ // 2) decrementing the buffer would make it leave the unsafe interval
+ // 3) decrementing the buffer would yield a number below w_high and farther
+ // away than the current number. In other words:
+ // (buffer{-1} < w_high) && w_high - buffer{-1} > buffer - w_high
+ // Instead of using the buffer directly we use its distance to too_high.
+ // Conceptually rest ~= too_high - buffer
+ // We need to do the following tests in this order to avoid over- and
+ // underflows.
+ ASSERT(rest <= unsafe_interval);
+ while (rest < small_distance && // Negated condition 1
+ unsafe_interval - rest >= ten_kappa && // Negated condition 2
+ (rest + ten_kappa < small_distance || // buffer{-1} > w_high
+ small_distance - rest >= rest + ten_kappa - small_distance)) {
+ buffer[length - 1]--;
+ rest += ten_kappa;
+ }
+
+ // We have approached w+ as much as possible. We now test if approaching w-
+ // would require changing the buffer. If yes, then we have two possible
+ // representations close to w, but we cannot decide which one is closer.
+ if (rest < big_distance &&
+ unsafe_interval - rest >= ten_kappa &&
+ (rest + ten_kappa < big_distance ||
+ big_distance - rest > rest + ten_kappa - big_distance)) {
+ return false;
+ }
+
+ // Weeding test.
+ // The safe interval is [too_low + 2 ulp; too_high - 2 ulp]
+ // Since too_low = too_high - unsafe_interval this is equivalent to
+ // [too_high - unsafe_interval + 4 ulp; too_high - 2 ulp]
+ // Conceptually we have: rest ~= too_high - buffer
+ return (2 * unit <= rest) && (rest <= unsafe_interval - 4 * unit);
+}
+
+
+// Rounds the buffer upwards if the result is closer to v by possibly adding
+// 1 to the buffer. If the precision of the calculation is not sufficient to
+// round correctly, return false.
+// The rounding might shift the whole buffer in which case the kappa is
+// adjusted. For example "99", kappa = 3 might become "10", kappa = 4.
+//
+// If 2*rest > ten_kappa then the buffer needs to be round up.
+// rest can have an error of +/- 1 unit. This function accounts for the
+// imprecision and returns false, if the rounding direction cannot be
+// unambiguously determined.
+//
+// Precondition: rest < ten_kappa.
+static bool RoundWeedCounted(Vector<char> buffer,
+ int length,
+ uint64_t rest,
+ uint64_t ten_kappa,
+ uint64_t unit,
+ int* kappa) {
+ ASSERT(rest < ten_kappa);
+ // The following tests are done in a specific order to avoid overflows. They
+ // will work correctly with any uint64 values of rest < ten_kappa and unit.
+ //
+ // If the unit is too big, then we don't know which way to round. For example
+ // a unit of 50 means that the real number lies within rest +/- 50. If
+ // 10^kappa == 40 then there is no way to tell which way to round.
+ if (unit >= ten_kappa) return false;
+ // Even if unit is just half the size of 10^kappa we are already completely
+ // lost. (And after the previous test we know that the expression will not
+ // over/underflow.)
+ if (ten_kappa - unit <= unit) return false;
+ // If 2 * (rest + unit) <= 10^kappa we can safely round down.
+ if ((ten_kappa - rest > rest) && (ten_kappa - 2 * rest >= 2 * unit)) {
+ return true;
+ }
+ // If 2 * (rest - unit) >= 10^kappa, then we can safely round up.
+ if ((rest > unit) && (ten_kappa - (rest - unit) <= (rest - unit))) {
+ // Increment the last digit recursively until we find a non '9' digit.
+ buffer[length - 1]++;
+ for (int i = length - 1; i > 0; --i) {
+ if (buffer[i] != '0' + 10) break;
+ buffer[i] = '0';
+ buffer[i - 1]++;
+ }
+ // If the first digit is now '0'+ 10 we had a buffer with all '9's. With the
+ // exception of the first digit all digits are now '0'. Simply switch the
+ // first digit to '1' and adjust the kappa. Example: "99" becomes "10" and
+ // the power (the kappa) is increased.
+ if (buffer[0] == '0' + 10) {
+ buffer[0] = '1';
+ (*kappa) += 1;
+ }
+ return true;
+ }
+ return false;
+}
+
+// Returns the biggest power of ten that is less than or equal to the given
+// number. We furthermore receive the maximum number of bits 'number' has.
+//
+// Returns power == 10^(exponent_plus_one-1) such that
+// power <= number < power * 10.
+// If number_bits == 0 then 0^(0-1) is returned.
+// The number of bits must be <= 32.
+// Precondition: number < (1 << (number_bits + 1)).
+
+// Inspired by the method for finding an integer log base 10 from here:
+// http://graphics.stanford.edu/~seander/bithacks.html#IntegerLog10
+static unsigned int const kSmallPowersOfTen[] =
+ {0, 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000,
+ 1000000000};
+
+static void BiggestPowerTen(uint32_t number,
+ int number_bits,
+ uint32_t* power,
+ int* exponent_plus_one) {
+ ASSERT(number < (1u << (number_bits + 1)));
+ // 1233/4096 is approximately 1/lg(10).
+ int exponent_plus_one_guess = ((number_bits + 1) * 1233 >> 12);
+ // We increment to skip over the first entry in the kPowersOf10 table.
+ // Note: kPowersOf10[i] == 10^(i-1).
+ exponent_plus_one_guess++;
+ // We don't have any guarantees that 2^number_bits <= number.
+ if (number < kSmallPowersOfTen[exponent_plus_one_guess]) {
+ exponent_plus_one_guess--;
+ }
+ *power = kSmallPowersOfTen[exponent_plus_one_guess];
+ *exponent_plus_one = exponent_plus_one_guess;
+}
+
+// Generates the digits of input number w.
+// w is a floating-point number (DiyFp), consisting of a significand and an
+// exponent. Its exponent is bounded by kMinimalTargetExponent and
+// kMaximalTargetExponent.
+// Hence -60 <= w.e() <= -32.
+//
+// Returns false if it fails, in which case the generated digits in the buffer
+// should not be used.
+// Preconditions:
+// * low, w and high are correct up to 1 ulp (unit in the last place). That
+// is, their error must be less than a unit of their last digits.
+// * low.e() == w.e() == high.e()
+// * low < w < high, and taking into account their error: low~ <= high~
+// * kMinimalTargetExponent <= w.e() <= kMaximalTargetExponent
+// Postconditions: returns false if procedure fails.
+// otherwise:
+// * buffer is not null-terminated, but len contains the number of digits.
+// * buffer contains the shortest possible decimal digit-sequence
+// such that LOW < buffer * 10^kappa < HIGH, where LOW and HIGH are the
+// correct values of low and high (without their error).
+// * if more than one decimal representation gives the minimal number of
+// decimal digits then the one closest to W (where W is the correct value
+// of w) is chosen.
+// Remark: this procedure takes into account the imprecision of its input
+// numbers. If the precision is not enough to guarantee all the postconditions
+// then false is returned. This usually happens rarely (~0.5%).
+//
+// Say, for the sake of example, that
+// w.e() == -48, and w.f() == 0x1234567890abcdef
+// w's value can be computed by w.f() * 2^w.e()
+// We can obtain w's integral digits by simply shifting w.f() by -w.e().
+// -> w's integral part is 0x1234
+// w's fractional part is therefore 0x567890abcdef.
+// Printing w's integral part is easy (simply print 0x1234 in decimal).
+// In order to print its fraction we repeatedly multiply the fraction by 10 and
+// get each digit. Example the first digit after the point would be computed by
+// (0x567890abcdef * 10) >> 48. -> 3
+// The whole thing becomes slightly more complicated because we want to stop
+// once we have enough digits. That is, once the digits inside the buffer
+// represent 'w' we can stop. Everything inside the interval low - high
+// represents w. However we have to pay attention to low, high and w's
+// imprecision.
+static bool DigitGen(DiyFp low,
+ DiyFp w,
+ DiyFp high,
+ Vector<char> buffer,
+ int* length,
+ int* kappa) {
+ ASSERT(low.e() == w.e() && w.e() == high.e());
+ ASSERT(low.f() + 1 <= high.f() - 1);
+ ASSERT(kMinimalTargetExponent <= w.e() && w.e() <= kMaximalTargetExponent);
+ // low, w and high are imprecise, but by less than one ulp (unit in the last
+ // place).
+ // If we remove (resp. add) 1 ulp from low (resp. high) we are certain that
+ // the new numbers are outside of the interval we want the final
+ // representation to lie in.
+ // Inversely adding (resp. removing) 1 ulp from low (resp. high) would yield
+ // numbers that are certain to lie in the interval. We will use this fact
+ // later on.
+ // We will now start by generating the digits within the uncertain
+ // interval. Later we will weed out representations that lie outside the safe
+ // interval and thus _might_ lie outside the correct interval.
+ uint64_t unit = 1;
+ DiyFp too_low = DiyFp(low.f() - unit, low.e());
+ DiyFp too_high = DiyFp(high.f() + unit, high.e());
+ // too_low and too_high are guaranteed to lie outside the interval we want the
+ // generated number in.
+ DiyFp unsafe_interval = DiyFp::Minus(too_high, too_low);
+ // We now cut the input number into two parts: the integral digits and the
+ // fractionals. We will not write any decimal separator though, but adapt
+ // kappa instead.
+ // Reminder: we are currently computing the digits (stored inside the buffer)
+ // such that: too_low < buffer * 10^kappa < too_high
+ // We use too_high for the digit_generation and stop as soon as possible.
+ // If we stop early we effectively round down.
+ DiyFp one = DiyFp(static_cast<uint64_t>(1) << -w.e(), w.e());
+ // Division by one is a shift.
+ uint32_t integrals = static_cast<uint32_t>(too_high.f() >> -one.e());
+ // Modulo by one is an and.
+ uint64_t fractionals = too_high.f() & (one.f() - 1);
+ uint32_t divisor;
+ int divisor_exponent_plus_one;
+ BiggestPowerTen(integrals, DiyFp::kSignificandSize - (-one.e()),
+ &divisor, &divisor_exponent_plus_one);
+ *kappa = divisor_exponent_plus_one;
+ *length = 0;
+ // Loop invariant: buffer = too_high / 10^kappa (integer division)
+ // The invariant holds for the first iteration: kappa has been initialized
+ // with the divisor exponent + 1. And the divisor is the biggest power of ten
+ // that is smaller than integrals.
+ while (*kappa > 0) {
+ int digit = integrals / divisor;
+ ASSERT(digit <= 9);
+ buffer[*length] = static_cast<char>('0' + digit);
+ (*length)++;
+ integrals %= divisor;
+ (*kappa)--;
+ // Note that kappa now equals the exponent of the divisor and that the
+ // invariant thus holds again.
+ uint64_t rest =
+ (static_cast<uint64_t>(integrals) << -one.e()) + fractionals;
+ // Invariant: too_high = buffer * 10^kappa + DiyFp(rest, one.e())
+ // Reminder: unsafe_interval.e() == one.e()
+ if (rest < unsafe_interval.f()) {
+ // Rounding down (by not emitting the remaining digits) yields a number
+ // that lies within the unsafe interval.
+ return RoundWeed(buffer, *length, DiyFp::Minus(too_high, w).f(),
+ unsafe_interval.f(), rest,
+ static_cast<uint64_t>(divisor) << -one.e(), unit);
+ }
+ divisor /= 10;
+ }
+
+ // The integrals have been generated. We are at the point of the decimal
+ // separator. In the following loop we simply multiply the remaining digits by
+ // 10 and divide by one. We just need to pay attention to multiply associated
+ // data (like the interval or 'unit'), too.
+ // Note that the multiplication by 10 does not overflow, because w.e >= -60
+ // and thus one.e >= -60.
+ ASSERT(one.e() >= -60);
+ ASSERT(fractionals < one.f());
+ ASSERT(UINT64_2PART_C(0xFFFFFFFF, FFFFFFFF) / 10 >= one.f());
+ for (;;) {
+ fractionals *= 10;
+ unit *= 10;
+ unsafe_interval.set_f(unsafe_interval.f() * 10);
+ // Integer division by one.
+ int digit = static_cast<int>(fractionals >> -one.e());
+ ASSERT(digit <= 9);
+ buffer[*length] = static_cast<char>('0' + digit);
+ (*length)++;
+ fractionals &= one.f() - 1; // Modulo by one.
+ (*kappa)--;
+ if (fractionals < unsafe_interval.f()) {
+ return RoundWeed(buffer, *length, DiyFp::Minus(too_high, w).f() * unit,
+ unsafe_interval.f(), fractionals, one.f(), unit);
+ }
+ }
+}
+
+
+
+// Generates (at most) requested_digits digits of input number w.
+// w is a floating-point number (DiyFp), consisting of a significand and an
+// exponent. Its exponent is bounded by kMinimalTargetExponent and
+// kMaximalTargetExponent.
+// Hence -60 <= w.e() <= -32.
+//
+// Returns false if it fails, in which case the generated digits in the buffer
+// should not be used.
+// Preconditions:
+// * w is correct up to 1 ulp (unit in the last place). That
+// is, its error must be strictly less than a unit of its last digit.
+// * kMinimalTargetExponent <= w.e() <= kMaximalTargetExponent
+//
+// Postconditions: returns false if procedure fails.
+// otherwise:
+// * buffer is not null-terminated, but length contains the number of
+// digits.
+// * the representation in buffer is the most precise representation of
+// requested_digits digits.
+// * buffer contains at most requested_digits digits of w. If there are less
+// than requested_digits digits then some trailing '0's have been removed.
+// * kappa is such that
+// w = buffer * 10^kappa + eps with |eps| < 10^kappa / 2.
+//
+// Remark: This procedure takes into account the imprecision of its input
+// numbers. If the precision is not enough to guarantee all the postconditions
+// then false is returned. This usually happens rarely, but the failure-rate
+// increases with higher requested_digits.
+static bool DigitGenCounted(DiyFp w,
+ int requested_digits,
+ Vector<char> buffer,
+ int* length,
+ int* kappa) {
+ ASSERT(kMinimalTargetExponent <= w.e() && w.e() <= kMaximalTargetExponent);
+ ASSERT(kMinimalTargetExponent >= -60);
+ ASSERT(kMaximalTargetExponent <= -32);
+ // w is assumed to have an error less than 1 unit. Whenever w is scaled we
+ // also scale its error.
+ uint64_t w_error = 1;
+ // We cut the input number into two parts: the integral digits and the
+ // fractional digits. We don't emit any decimal separator, but adapt kappa
+ // instead. Example: instead of writing "1.2" we put "12" into the buffer and
+ // increase kappa by 1.
+ DiyFp one = DiyFp(static_cast<uint64_t>(1) << -w.e(), w.e());
+ // Division by one is a shift.
+ uint32_t integrals = static_cast<uint32_t>(w.f() >> -one.e());
+ // Modulo by one is an and.
+ uint64_t fractionals = w.f() & (one.f() - 1);
+ uint32_t divisor;
+ int divisor_exponent_plus_one;
+ BiggestPowerTen(integrals, DiyFp::kSignificandSize - (-one.e()),
+ &divisor, &divisor_exponent_plus_one);
+ *kappa = divisor_exponent_plus_one;
+ *length = 0;
+
+ // Loop invariant: buffer = w / 10^kappa (integer division)
+ // The invariant holds for the first iteration: kappa has been initialized
+ // with the divisor exponent + 1. And the divisor is the biggest power of ten
+ // that is smaller than 'integrals'.
+ while (*kappa > 0) {
+ int digit = integrals / divisor;
+ ASSERT(digit <= 9);
+ buffer[*length] = static_cast<char>('0' + digit);
+ (*length)++;
+ requested_digits--;
+ integrals %= divisor;
+ (*kappa)--;
+ // Note that kappa now equals the exponent of the divisor and that the
+ // invariant thus holds again.
+ if (requested_digits == 0) break;
+ divisor /= 10;
+ }
+
+ if (requested_digits == 0) {
+ uint64_t rest =
+ (static_cast<uint64_t>(integrals) << -one.e()) + fractionals;
+ return RoundWeedCounted(buffer, *length, rest,
+ static_cast<uint64_t>(divisor) << -one.e(), w_error,
+ kappa);
+ }
+
+ // The integrals have been generated. We are at the point of the decimal
+ // separator. In the following loop we simply multiply the remaining digits by
+ // 10 and divide by one. We just need to pay attention to multiply associated
+ // data (the 'unit'), too.
+ // Note that the multiplication by 10 does not overflow, because w.e >= -60
+ // and thus one.e >= -60.
+ ASSERT(one.e() >= -60);
+ ASSERT(fractionals < one.f());
+ ASSERT(UINT64_2PART_C(0xFFFFFFFF, FFFFFFFF) / 10 >= one.f());
+ while (requested_digits > 0 && fractionals > w_error) {
+ fractionals *= 10;
+ w_error *= 10;
+ // Integer division by one.
+ int digit = static_cast<int>(fractionals >> -one.e());
+ ASSERT(digit <= 9);
+ buffer[*length] = static_cast<char>('0' + digit);
+ (*length)++;
+ requested_digits--;
+ fractionals &= one.f() - 1; // Modulo by one.
+ (*kappa)--;
+ }
+ if (requested_digits != 0) return false;
+ return RoundWeedCounted(buffer, *length, fractionals, one.f(), w_error,
+ kappa);
+}
+
+
+// Provides a decimal representation of v.
+// Returns true if it succeeds, otherwise the result cannot be trusted.
+// There will be *length digits inside the buffer (not null-terminated).
+// If the function returns true then
+// v == (double) (buffer * 10^decimal_exponent).
+// The digits in the buffer are the shortest representation possible: no
+// 0.09999999999999999 instead of 0.1. The shorter representation will even be
+// chosen even if the longer one would be closer to v.
+// The last digit will be closest to the actual v. That is, even if several
+// digits might correctly yield 'v' when read again, the closest will be
+// computed.
+static bool Grisu3(double v,
+ FastDtoaMode mode,
+ Vector<char> buffer,
+ int* length,
+ int* decimal_exponent) {
+ DiyFp w = Double(v).AsNormalizedDiyFp();
+ // boundary_minus and boundary_plus are the boundaries between v and its
+ // closest floating-point neighbors. Any number strictly between
+ // boundary_minus and boundary_plus will round to v when convert to a double.
+ // Grisu3 will never output representations that lie exactly on a boundary.
+ DiyFp boundary_minus, boundary_plus;
+ if (mode == FAST_DTOA_SHORTEST) {
+ Double(v).NormalizedBoundaries(&boundary_minus, &boundary_plus);
+ } else {
+ ASSERT(mode == FAST_DTOA_SHORTEST_SINGLE);
+ float single_v = static_cast<float>(v);
+ Single(single_v).NormalizedBoundaries(&boundary_minus, &boundary_plus);
+ }
+ ASSERT(boundary_plus.e() == w.e());
+ DiyFp ten_mk; // Cached power of ten: 10^-k
+ int mk; // -k
+ int ten_mk_minimal_binary_exponent =
+ kMinimalTargetExponent - (w.e() + DiyFp::kSignificandSize);
+ int ten_mk_maximal_binary_exponent =
+ kMaximalTargetExponent - (w.e() + DiyFp::kSignificandSize);
+ PowersOfTenCache::GetCachedPowerForBinaryExponentRange(
+ ten_mk_minimal_binary_exponent,
+ ten_mk_maximal_binary_exponent,
+ &ten_mk, &mk);
+ ASSERT((kMinimalTargetExponent <= w.e() + ten_mk.e() +
+ DiyFp::kSignificandSize) &&
+ (kMaximalTargetExponent >= w.e() + ten_mk.e() +
+ DiyFp::kSignificandSize));
+ // Note that ten_mk is only an approximation of 10^-k. A DiyFp only contains a
+ // 64 bit significand and ten_mk is thus only precise up to 64 bits.
+
+ // The DiyFp::Times procedure rounds its result, and ten_mk is approximated
+ // too. The variable scaled_w (as well as scaled_boundary_minus/plus) are now
+ // off by a small amount.
+ // In fact: scaled_w - w*10^k < 1ulp (unit in the last place) of scaled_w.
+ // In other words: let f = scaled_w.f() and e = scaled_w.e(), then
+ // (f-1) * 2^e < w*10^k < (f+1) * 2^e
+ DiyFp scaled_w = DiyFp::Times(w, ten_mk);
+ ASSERT(scaled_w.e() ==
+ boundary_plus.e() + ten_mk.e() + DiyFp::kSignificandSize);
+ // In theory it would be possible to avoid some recomputations by computing
+ // the difference between w and boundary_minus/plus (a power of 2) and to
+ // compute scaled_boundary_minus/plus by subtracting/adding from
+ // scaled_w. However the code becomes much less readable and the speed
+ // enhancements are not terriffic.
+ DiyFp scaled_boundary_minus = DiyFp::Times(boundary_minus, ten_mk);
+ DiyFp scaled_boundary_plus = DiyFp::Times(boundary_plus, ten_mk);
+
+ // DigitGen will generate the digits of scaled_w. Therefore we have
+ // v == (double) (scaled_w * 10^-mk).
+ // Set decimal_exponent == -mk and pass it to DigitGen. If scaled_w is not an
+ // integer than it will be updated. For instance if scaled_w == 1.23 then
+ // the buffer will be filled with "123" und the decimal_exponent will be
+ // decreased by 2.
+ int kappa;
+ bool result = DigitGen(scaled_boundary_minus, scaled_w, scaled_boundary_plus,
+ buffer, length, &kappa);
+ *decimal_exponent = -mk + kappa;
+ return result;
+}
+
+
+// The "counted" version of grisu3 (see above) only generates requested_digits
+// number of digits. This version does not generate the shortest representation,
+// and with enough requested digits 0.1 will at some point print as 0.9999999...
+// Grisu3 is too imprecise for real halfway cases (1.5 will not work) and
+// therefore the rounding strategy for halfway cases is irrelevant.
+static bool Grisu3Counted(double v,
+ int requested_digits,
+ Vector<char> buffer,
+ int* length,
+ int* decimal_exponent) {
+ DiyFp w = Double(v).AsNormalizedDiyFp();
+ DiyFp ten_mk; // Cached power of ten: 10^-k
+ int mk; // -k
+ int ten_mk_minimal_binary_exponent =
+ kMinimalTargetExponent - (w.e() + DiyFp::kSignificandSize);
+ int ten_mk_maximal_binary_exponent =
+ kMaximalTargetExponent - (w.e() + DiyFp::kSignificandSize);
+ PowersOfTenCache::GetCachedPowerForBinaryExponentRange(
+ ten_mk_minimal_binary_exponent,
+ ten_mk_maximal_binary_exponent,
+ &ten_mk, &mk);
+ ASSERT((kMinimalTargetExponent <= w.e() + ten_mk.e() +
+ DiyFp::kSignificandSize) &&
+ (kMaximalTargetExponent >= w.e() + ten_mk.e() +
+ DiyFp::kSignificandSize));
+ // Note that ten_mk is only an approximation of 10^-k. A DiyFp only contains a
+ // 64 bit significand and ten_mk is thus only precise up to 64 bits.
+
+ // The DiyFp::Times procedure rounds its result, and ten_mk is approximated
+ // too. The variable scaled_w (as well as scaled_boundary_minus/plus) are now
+ // off by a small amount.
+ // In fact: scaled_w - w*10^k < 1ulp (unit in the last place) of scaled_w.
+ // In other words: let f = scaled_w.f() and e = scaled_w.e(), then
+ // (f-1) * 2^e < w*10^k < (f+1) * 2^e
+ DiyFp scaled_w = DiyFp::Times(w, ten_mk);
+
+ // We now have (double) (scaled_w * 10^-mk).
+ // DigitGen will generate the first requested_digits digits of scaled_w and
+ // return together with a kappa such that scaled_w ~= buffer * 10^kappa. (It
+ // will not always be exactly the same since DigitGenCounted only produces a
+ // limited number of digits.)
+ int kappa;
+ bool result = DigitGenCounted(scaled_w, requested_digits,
+ buffer, length, &kappa);
+ *decimal_exponent = -mk + kappa;
+ return result;
+}
+
+
+bool FastDtoa(double v,
+ FastDtoaMode mode,
+ int requested_digits,
+ Vector<char> buffer,
+ int* length,
+ int* decimal_point) {
+ ASSERT(v > 0);
+ ASSERT(!Double(v).IsSpecial());
+
+ bool result = false;
+ int decimal_exponent = 0;
+ switch (mode) {
+ case FAST_DTOA_SHORTEST:
+ case FAST_DTOA_SHORTEST_SINGLE:
+ result = Grisu3(v, mode, buffer, length, &decimal_exponent);
+ break;
+ case FAST_DTOA_PRECISION:
+ result = Grisu3Counted(v, requested_digits,
+ buffer, length, &decimal_exponent);
+ break;
+ default:
+ UNREACHABLE();
+ }
+ if (result) {
+ *decimal_point = *length + decimal_exponent;
+ buffer[*length] = '\0';
+ }
+ return result;
+}
+
+} // namespace double_conversion
+
+// ICU PATCH: Close ICU namespace
+U_NAMESPACE_END
+#endif // ICU PATCH: close #if !UCONFIG_NO_FORMATTING
diff --git a/Build/source/libs/icu/icu-src/source/i18n/double-conversion-fast-dtoa.h b/Build/source/libs/icu/icu-src/source/i18n/double-conversion-fast-dtoa.h
new file mode 100644
index 00000000000..58a6470052c
--- /dev/null
+++ b/Build/source/libs/icu/icu-src/source/i18n/double-conversion-fast-dtoa.h
@@ -0,0 +1,106 @@
+// © 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_FAST_DTOA_H_
+#define DOUBLE_CONVERSION_FAST_DTOA_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 {
+
+enum FastDtoaMode {
+ // Computes the shortest representation of the given input. The returned
+ // result will be the most accurate number of this length. Longer
+ // representations might be more accurate.
+ FAST_DTOA_SHORTEST,
+ // Same as FAST_DTOA_SHORTEST but for single-precision floats.
+ FAST_DTOA_SHORTEST_SINGLE,
+ // Computes a representation where the precision (number of digits) is
+ // given as input. The precision is independent of the decimal point.
+ FAST_DTOA_PRECISION
+};
+
+// FastDtoa will produce at most kFastDtoaMaximalLength digits. This does not
+// include the terminating '\0' character.
+static const int kFastDtoaMaximalLength = 17;
+// Same for single-precision numbers.
+static const int kFastDtoaMaximalSingleLength = 9;
+
+// Provides a decimal representation of v.
+// The result should be interpreted as buffer * 10^(point - length).
+//
+// Precondition:
+// * v must be a strictly positive finite double.
+//
+// Returns true if it succeeds, otherwise the result can not be trusted.
+// There will be *length digits inside the buffer followed by a null terminator.
+// If the function returns true and mode equals
+// - FAST_DTOA_SHORTEST, then
+// the parameter requested_digits is ignored.
+// The result satisfies
+// v == (double) (buffer * 10^(point - length)).
+// The digits in the buffer are the shortest representation possible. E.g.
+// if 0.099999999999 and 0.1 represent the same double then "1" is returned
+// with point = 0.
+// The last digit will be closest to the actual v. That is, even if several
+// digits might correctly yield 'v' when read again, the buffer will contain
+// the one closest to v.
+// - FAST_DTOA_PRECISION, then
+// the buffer contains requested_digits digits.
+// the difference v - (buffer * 10^(point-length)) is closest to zero for
+// all possible representations of requested_digits digits.
+// If there are two values that are equally close, then FastDtoa returns
+// false.
+// For both modes the buffer must be large enough to hold the result.
+bool FastDtoa(double d,
+ FastDtoaMode mode,
+ int requested_digits,
+ Vector<char> buffer,
+ int* length,
+ int* decimal_point);
+
+} // namespace double_conversion
+
+// ICU PATCH: Close ICU namespace
+U_NAMESPACE_END
+
+#endif // DOUBLE_CONVERSION_FAST_DTOA_H_
+#endif // ICU PATCH: close #if !UCONFIG_NO_FORMATTING
diff --git a/Build/source/libs/icu/icu-src/source/i18n/double-conversion-ieee.h b/Build/source/libs/icu/icu-src/source/i18n/double-conversion-ieee.h
new file mode 100644
index 00000000000..952bcea27f6
--- /dev/null
+++ b/Build/source/libs/icu/icu-src/source/i18n/double-conversion-ieee.h
@@ -0,0 +1,420 @@
+// © 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 2012 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_DOUBLE_H_
+#define DOUBLE_CONVERSION_DOUBLE_H_
+
+// ICU PATCH: Customize header file paths for ICU.
+
+#include "double-conversion-diy-fp.h"
+
+// ICU PATCH: Wrap in ICU namespace
+U_NAMESPACE_BEGIN
+
+namespace double_conversion {
+
+// We assume that doubles and uint64_t have the same endianness.
+static uint64_t double_to_uint64(double d) { return BitCast<uint64_t>(d); }
+static double uint64_to_double(uint64_t d64) { return BitCast<double>(d64); }
+static uint32_t float_to_uint32(float f) { return BitCast<uint32_t>(f); }
+static float uint32_to_float(uint32_t d32) { return BitCast<float>(d32); }
+
+// Helper functions for doubles.
+class Double {
+ public:
+ static const uint64_t kSignMask = UINT64_2PART_C(0x80000000, 00000000);
+ static const uint64_t kExponentMask = UINT64_2PART_C(0x7FF00000, 00000000);
+ static const uint64_t kSignificandMask = UINT64_2PART_C(0x000FFFFF, FFFFFFFF);
+ static const uint64_t kHiddenBit = UINT64_2PART_C(0x00100000, 00000000);
+ static const int kPhysicalSignificandSize = 52; // Excludes the hidden bit.
+ static const int kSignificandSize = 53;
+
+ Double() : d64_(0) {}
+ explicit Double(double d) : d64_(double_to_uint64(d)) {}
+ explicit Double(uint64_t d64) : d64_(d64) {}
+ explicit Double(DiyFp diy_fp)
+ : d64_(DiyFpToUint64(diy_fp)) {}
+
+ // The value encoded by this Double must be greater or equal to +0.0.
+ // It must not be special (infinity, or NaN).
+ DiyFp AsDiyFp() const {
+ ASSERT(Sign() > 0);
+ ASSERT(!IsSpecial());
+ return DiyFp(Significand(), Exponent());
+ }
+
+ // The value encoded by this Double must be strictly greater than 0.
+ DiyFp AsNormalizedDiyFp() const {
+ ASSERT(value() > 0.0);
+ uint64_t f = Significand();
+ int e = Exponent();
+
+ // The current double could be a denormal.
+ while ((f & kHiddenBit) == 0) {
+ f <<= 1;
+ e--;
+ }
+ // Do the final shifts in one go.
+ f <<= DiyFp::kSignificandSize - kSignificandSize;
+ e -= DiyFp::kSignificandSize - kSignificandSize;
+ return DiyFp(f, e);
+ }
+
+ // Returns the double's bit as uint64.
+ uint64_t AsUint64() const {
+ return d64_;
+ }
+
+ // Returns the next greater double. Returns +infinity on input +infinity.
+ double NextDouble() const {
+ if (d64_ == kInfinity) return Double(kInfinity).value();
+ if (Sign() < 0 && Significand() == 0) {
+ // -0.0
+ return 0.0;
+ }
+ if (Sign() < 0) {
+ return Double(d64_ - 1).value();
+ } else {
+ return Double(d64_ + 1).value();
+ }
+ }
+
+ double PreviousDouble() const {
+ if (d64_ == (kInfinity | kSignMask)) return -Infinity();
+ if (Sign() < 0) {
+ return Double(d64_ + 1).value();
+ } else {
+ if (Significand() == 0) return -0.0;
+ return Double(d64_ - 1).value();
+ }
+ }
+
+ int Exponent() const {
+ if (IsDenormal()) return kDenormalExponent;
+
+ uint64_t d64 = AsUint64();
+ int biased_e =
+ static_cast<int>((d64 & kExponentMask) >> kPhysicalSignificandSize);
+ return biased_e - kExponentBias;
+ }
+
+ uint64_t Significand() const {
+ uint64_t d64 = AsUint64();
+ uint64_t significand = d64 & kSignificandMask;
+ if (!IsDenormal()) {
+ return significand + kHiddenBit;
+ } else {
+ return significand;
+ }
+ }
+
+ // Returns true if the double is a denormal.
+ bool IsDenormal() const {
+ uint64_t d64 = AsUint64();
+ return (d64 & kExponentMask) == 0;
+ }
+
+ // We consider denormals not to be special.
+ // Hence only Infinity and NaN are special.
+ bool IsSpecial() const {
+ uint64_t d64 = AsUint64();
+ return (d64 & kExponentMask) == kExponentMask;
+ }
+
+ bool IsNan() const {
+ uint64_t d64 = AsUint64();
+ return ((d64 & kExponentMask) == kExponentMask) &&
+ ((d64 & kSignificandMask) != 0);
+ }
+
+ bool IsInfinite() const {
+ uint64_t d64 = AsUint64();
+ return ((d64 & kExponentMask) == kExponentMask) &&
+ ((d64 & kSignificandMask) == 0);
+ }
+
+ int Sign() const {
+ uint64_t d64 = AsUint64();
+ return (d64 & kSignMask) == 0? 1: -1;
+ }
+
+ // Precondition: the value encoded by this Double must be greater or equal
+ // than +0.0.
+ DiyFp UpperBoundary() const {
+ ASSERT(Sign() > 0);
+ return DiyFp(Significand() * 2 + 1, Exponent() - 1);
+ }
+
+ // Computes the two boundaries of this.
+ // The bigger boundary (m_plus) is normalized. The lower boundary has the same
+ // exponent as m_plus.
+ // Precondition: the value encoded by this Double must be greater than 0.
+ void NormalizedBoundaries(DiyFp* out_m_minus, DiyFp* out_m_plus) const {
+ ASSERT(value() > 0.0);
+ DiyFp v = this->AsDiyFp();
+ DiyFp m_plus = DiyFp::Normalize(DiyFp((v.f() << 1) + 1, v.e() - 1));
+ DiyFp m_minus;
+ if (LowerBoundaryIsCloser()) {
+ m_minus = DiyFp((v.f() << 2) - 1, v.e() - 2);
+ } else {
+ m_minus = DiyFp((v.f() << 1) - 1, v.e() - 1);
+ }
+ m_minus.set_f(m_minus.f() << (m_minus.e() - m_plus.e()));
+ m_minus.set_e(m_plus.e());
+ *out_m_plus = m_plus;
+ *out_m_minus = m_minus;
+ }
+
+ bool LowerBoundaryIsCloser() const {
+ // The boundary is closer if the significand is of the form f == 2^p-1 then
+ // the lower boundary is closer.
+ // Think of v = 1000e10 and v- = 9999e9.
+ // Then the boundary (== (v - v-)/2) is not just at a distance of 1e9 but
+ // at a distance of 1e8.
+ // The only exception is for the smallest normal: the largest denormal is
+ // at the same distance as its successor.
+ // Note: denormals have the same exponent as the smallest normals.
+ bool physical_significand_is_zero = ((AsUint64() & kSignificandMask) == 0);
+ return physical_significand_is_zero && (Exponent() != kDenormalExponent);
+ }
+
+ double value() const { return uint64_to_double(d64_); }
+
+ // Returns the significand size for a given order of magnitude.
+ // If v = f*2^e with 2^p-1 <= f <= 2^p then p+e is v's order of magnitude.
+ // This function returns the number of significant binary digits v will have
+ // once it's encoded into a double. In almost all cases this is equal to
+ // kSignificandSize. The only exceptions are denormals. They start with
+ // leading zeroes and their effective significand-size is hence smaller.
+ static int SignificandSizeForOrderOfMagnitude(int order) {
+ if (order >= (kDenormalExponent + kSignificandSize)) {
+ return kSignificandSize;
+ }
+ if (order <= kDenormalExponent) return 0;
+ return order - kDenormalExponent;
+ }
+
+ static double Infinity() {
+ return Double(kInfinity).value();
+ }
+
+ static double NaN() {
+ return Double(kNaN).value();
+ }
+
+ private:
+ static const int kExponentBias = 0x3FF + kPhysicalSignificandSize;
+ static const int kDenormalExponent = -kExponentBias + 1;
+ static const int kMaxExponent = 0x7FF - kExponentBias;
+ static const uint64_t kInfinity = UINT64_2PART_C(0x7FF00000, 00000000);
+ static const uint64_t kNaN = UINT64_2PART_C(0x7FF80000, 00000000);
+
+ const uint64_t d64_;
+
+ static uint64_t DiyFpToUint64(DiyFp diy_fp) {
+ uint64_t significand = diy_fp.f();
+ int exponent = diy_fp.e();
+ while (significand > kHiddenBit + kSignificandMask) {
+ significand >>= 1;
+ exponent++;
+ }
+ if (exponent >= kMaxExponent) {
+ return kInfinity;
+ }
+ if (exponent < kDenormalExponent) {
+ return 0;
+ }
+ while (exponent > kDenormalExponent && (significand & kHiddenBit) == 0) {
+ significand <<= 1;
+ exponent--;
+ }
+ uint64_t biased_exponent;
+ if (exponent == kDenormalExponent && (significand & kHiddenBit) == 0) {
+ biased_exponent = 0;
+ } else {
+ biased_exponent = static_cast<uint64_t>(exponent + kExponentBias);
+ }
+ return (significand & kSignificandMask) |
+ (biased_exponent << kPhysicalSignificandSize);
+ }
+
+ DISALLOW_COPY_AND_ASSIGN(Double);
+};
+
+class Single {
+ public:
+ static const uint32_t kSignMask = 0x80000000;
+ static const uint32_t kExponentMask = 0x7F800000;
+ static const uint32_t kSignificandMask = 0x007FFFFF;
+ static const uint32_t kHiddenBit = 0x00800000;
+ static const int kPhysicalSignificandSize = 23; // Excludes the hidden bit.
+ static const int kSignificandSize = 24;
+
+ Single() : d32_(0) {}
+ explicit Single(float f) : d32_(float_to_uint32(f)) {}
+ explicit Single(uint32_t d32) : d32_(d32) {}
+
+ // The value encoded by this Single must be greater or equal to +0.0.
+ // It must not be special (infinity, or NaN).
+ DiyFp AsDiyFp() const {
+ ASSERT(Sign() > 0);
+ ASSERT(!IsSpecial());
+ return DiyFp(Significand(), Exponent());
+ }
+
+ // Returns the single's bit as uint64.
+ uint32_t AsUint32() const {
+ return d32_;
+ }
+
+ int Exponent() const {
+ if (IsDenormal()) return kDenormalExponent;
+
+ uint32_t d32 = AsUint32();
+ int biased_e =
+ static_cast<int>((d32 & kExponentMask) >> kPhysicalSignificandSize);
+ return biased_e - kExponentBias;
+ }
+
+ uint32_t Significand() const {
+ uint32_t d32 = AsUint32();
+ uint32_t significand = d32 & kSignificandMask;
+ if (!IsDenormal()) {
+ return significand + kHiddenBit;
+ } else {
+ return significand;
+ }
+ }
+
+ // Returns true if the single is a denormal.
+ bool IsDenormal() const {
+ uint32_t d32 = AsUint32();
+ return (d32 & kExponentMask) == 0;
+ }
+
+ // We consider denormals not to be special.
+ // Hence only Infinity and NaN are special.
+ bool IsSpecial() const {
+ uint32_t d32 = AsUint32();
+ return (d32 & kExponentMask) == kExponentMask;
+ }
+
+ bool IsNan() const {
+ uint32_t d32 = AsUint32();
+ return ((d32 & kExponentMask) == kExponentMask) &&
+ ((d32 & kSignificandMask) != 0);
+ }
+
+ bool IsInfinite() const {
+ uint32_t d32 = AsUint32();
+ return ((d32 & kExponentMask) == kExponentMask) &&
+ ((d32 & kSignificandMask) == 0);
+ }
+
+ int Sign() const {
+ uint32_t d32 = AsUint32();
+ return (d32 & kSignMask) == 0? 1: -1;
+ }
+
+ // Computes the two boundaries of this.
+ // The bigger boundary (m_plus) is normalized. The lower boundary has the same
+ // exponent as m_plus.
+ // Precondition: the value encoded by this Single must be greater than 0.
+ void NormalizedBoundaries(DiyFp* out_m_minus, DiyFp* out_m_plus) const {
+ ASSERT(value() > 0.0);
+ DiyFp v = this->AsDiyFp();
+ DiyFp m_plus = DiyFp::Normalize(DiyFp((v.f() << 1) + 1, v.e() - 1));
+ DiyFp m_minus;
+ if (LowerBoundaryIsCloser()) {
+ m_minus = DiyFp((v.f() << 2) - 1, v.e() - 2);
+ } else {
+ m_minus = DiyFp((v.f() << 1) - 1, v.e() - 1);
+ }
+ m_minus.set_f(m_minus.f() << (m_minus.e() - m_plus.e()));
+ m_minus.set_e(m_plus.e());
+ *out_m_plus = m_plus;
+ *out_m_minus = m_minus;
+ }
+
+ // Precondition: the value encoded by this Single must be greater or equal
+ // than +0.0.
+ DiyFp UpperBoundary() const {
+ ASSERT(Sign() > 0);
+ return DiyFp(Significand() * 2 + 1, Exponent() - 1);
+ }
+
+ bool LowerBoundaryIsCloser() const {
+ // The boundary is closer if the significand is of the form f == 2^p-1 then
+ // the lower boundary is closer.
+ // Think of v = 1000e10 and v- = 9999e9.
+ // Then the boundary (== (v - v-)/2) is not just at a distance of 1e9 but
+ // at a distance of 1e8.
+ // The only exception is for the smallest normal: the largest denormal is
+ // at the same distance as its successor.
+ // Note: denormals have the same exponent as the smallest normals.
+ bool physical_significand_is_zero = ((AsUint32() & kSignificandMask) == 0);
+ return physical_significand_is_zero && (Exponent() != kDenormalExponent);
+ }
+
+ float value() const { return uint32_to_float(d32_); }
+
+ static float Infinity() {
+ return Single(kInfinity).value();
+ }
+
+ static float NaN() {
+ return Single(kNaN).value();
+ }
+
+ private:
+ static const int kExponentBias = 0x7F + kPhysicalSignificandSize;
+ static const int kDenormalExponent = -kExponentBias + 1;
+ static const int kMaxExponent = 0xFF - kExponentBias;
+ static const uint32_t kInfinity = 0x7F800000;
+ static const uint32_t kNaN = 0x7FC00000;
+
+ const uint32_t d32_;
+
+ DISALLOW_COPY_AND_ASSIGN(Single);
+};
+
+} // namespace double_conversion
+
+// ICU PATCH: Close ICU namespace
+U_NAMESPACE_END
+
+#endif // DOUBLE_CONVERSION_DOUBLE_H_
+#endif // ICU PATCH: close #if !UCONFIG_NO_FORMATTING
diff --git a/Build/source/libs/icu/icu-src/source/i18n/double-conversion-utils.h b/Build/source/libs/icu/icu-src/source/i18n/double-conversion-utils.h
new file mode 100644
index 00000000000..02795b4bc56
--- /dev/null
+++ b/Build/source/libs/icu/icu-src/source/i18n/double-conversion-utils.h
@@ -0,0 +1,358 @@
+// © 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_UTILS_H_
+#define DOUBLE_CONVERSION_UTILS_H_
+
+#include <stdlib.h>
+#include <string.h>
+
+// ICU PATCH: Use U_ASSERT instead of <assert.h>
+#include "uassert.h"
+#define ASSERT U_ASSERT
+
+#ifndef UNIMPLEMENTED
+#define UNIMPLEMENTED() (abort())
+#endif
+#ifndef DOUBLE_CONVERSION_NO_RETURN
+#ifdef _MSC_VER
+#define DOUBLE_CONVERSION_NO_RETURN __declspec(noreturn)
+#else
+#define DOUBLE_CONVERSION_NO_RETURN __attribute__((noreturn))
+#endif
+#endif
+#ifndef UNREACHABLE
+#ifdef _MSC_VER
+void DOUBLE_CONVERSION_NO_RETURN abort_noreturn();
+inline void abort_noreturn() { abort(); }
+#define UNREACHABLE() (abort_noreturn())
+#else
+#define UNREACHABLE() (abort())
+#endif
+#endif
+
+
+// Double operations detection based on target architecture.
+// Linux uses a 80bit wide floating point stack on x86. This induces double
+// rounding, which in turn leads to wrong results.
+// An easy way to test if the floating-point operations are correct is to
+// evaluate: 89255.0/1e22. If the floating-point stack is 64 bits wide then
+// the result is equal to 89255e-22.
+// The best way to test this, is to create a division-function and to compare
+// 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)'.
+#if defined(_M_X64) || defined(__x86_64__) || \
+ defined(__ARMEL__) || defined(__avr32__) || defined(_M_ARM) || \
+ defined(__hppa__) || defined(__ia64__) || \
+ defined(__mips__) || \
+ defined(__powerpc__) || defined(__ppc__) || defined(__ppc64__) || \
+ defined(_POWER) || defined(_ARCH_PPC) || defined(_ARCH_PPC64) || \
+ defined(__sparc__) || defined(__sparc) || defined(__s390__) || \
+ defined(__SH4__) || defined(__alpha__) || \
+ defined(_MIPS_ARCH_MIPS32R2) || \
+ defined(__AARCH64EL__) || defined(__aarch64__) || \
+ defined(__riscv)
+#define DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS 1
+#elif defined(__mc68000__)
+#undef DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS
+#elif defined(_M_IX86) || defined(__i386__) || defined(__i386)
+#if defined(_WIN32)
+// Windows uses a 64bit wide floating point stack.
+#define DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS 1
+#else
+#undef DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS
+#endif // _WIN32
+#else
+#error Target architecture was not detected as supported by Double-Conversion.
+#endif
+
+#if defined(__GNUC__)
+#define DOUBLE_CONVERSION_UNUSED __attribute__((unused))
+#else
+#define DOUBLE_CONVERSION_UNUSED
+#endif
+
+#if defined(_WIN32) && !defined(__MINGW32__)
+
+typedef signed char int8_t;
+typedef unsigned char uint8_t;
+typedef short int16_t; // NOLINT
+typedef unsigned short uint16_t; // NOLINT
+typedef int int32_t;
+typedef unsigned int uint32_t;
+typedef __int64 int64_t;
+typedef unsigned __int64 uint64_t;
+// intptr_t and friends are defined in crtdefs.h through stdio.h.
+
+#else
+
+#include <stdint.h>
+
+#endif
+
+typedef uint16_t uc16;
+
+// The following macro works on both 32 and 64-bit platforms.
+// Usage: instead of writing 0x1234567890123456
+// write UINT64_2PART_C(0x12345678,90123456);
+#define UINT64_2PART_C(a, b) (((static_cast<uint64_t>(a) << 32) + 0x##b##u))
+
+
+// The expression ARRAY_SIZE(a) is a compile-time constant of type
+// size_t which represents the number of elements of the given
+// array. You should only use ARRAY_SIZE on statically allocated
+// arrays.
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(a) \
+ ((sizeof(a) / sizeof(*(a))) / \
+ static_cast<size_t>(!(sizeof(a) % sizeof(*(a)))))
+#endif
+
+// A macro to disallow the evil copy constructor and operator= functions
+// This should be used in the private: declarations for a class
+#ifndef DISALLOW_COPY_AND_ASSIGN
+#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
+ TypeName(const TypeName&); \
+ void operator=(const TypeName&)
+#endif
+
+// A macro to disallow all the implicit constructors, namely the
+// default constructor, copy constructor and operator= functions.
+//
+// This should be used in the private: declarations for a class
+// that wants to prevent anyone from instantiating it. This is
+// especially useful for classes containing only static methods.
+#ifndef DISALLOW_IMPLICIT_CONSTRUCTORS
+#define DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \
+ TypeName(); \
+ DISALLOW_COPY_AND_ASSIGN(TypeName)
+#endif
+
+// ICU PATCH: Wrap in ICU namespace
+U_NAMESPACE_BEGIN
+
+namespace double_conversion {
+
+static const int kCharSize = sizeof(char);
+
+// Returns the maximum of the two parameters.
+template <typename T>
+static T Max(T a, T b) {
+ return a < b ? b : a;
+}
+
+
+// Returns the minimum of the two parameters.
+template <typename T>
+static T Min(T a, T b) {
+ return a < b ? a : b;
+}
+
+
+inline int StrLength(const char* string) {
+ size_t length = strlen(string);
+ ASSERT(length == static_cast<size_t>(static_cast<int>(length)));
+ return static_cast<int>(length);
+}
+
+// This is a simplified version of V8's Vector class.
+template <typename T>
+class Vector {
+ public:
+ Vector() : start_(NULL), length_(0) {}
+ Vector(T* data, int len) : start_(data), length_(len) {
+ ASSERT(len == 0 || (len > 0 && data != NULL));
+ }
+
+ // Returns a vector using the same backing storage as this one,
+ // spanning from and including 'from', to but not including 'to'.
+ Vector<T> SubVector(int from, int to) {
+ ASSERT(to <= length_);
+ ASSERT(from < to);
+ ASSERT(0 <= from);
+ return Vector<T>(start() + from, to - from);
+ }
+
+ // Returns the length of the vector.
+ int length() const { return length_; }
+
+ // Returns whether or not the vector is empty.
+ bool is_empty() const { return length_ == 0; }
+
+ // Returns the pointer to the start of the data in the vector.
+ T* start() const { return start_; }
+
+ // Access individual vector elements - checks bounds in debug mode.
+ T& operator[](int index) const {
+ ASSERT(0 <= index && index < length_);
+ return start_[index];
+ }
+
+ T& first() { return start_[0]; }
+
+ T& last() { return start_[length_ - 1]; }
+
+ private:
+ T* start_;
+ int length_;
+};
+
+
+// Helper class for building result strings in a character buffer. The
+// purpose of the class is to use safe operations that checks the
+// buffer bounds on all operations in debug mode.
+class StringBuilder {
+ public:
+ StringBuilder(char* buffer, int buffer_size)
+ : buffer_(buffer, buffer_size), position_(0) { }
+
+ ~StringBuilder() { if (!is_finalized()) Finalize(); }
+
+ int size() const { return buffer_.length(); }
+
+ // Get the current position in the builder.
+ int position() const {
+ ASSERT(!is_finalized());
+ return position_;
+ }
+
+ // Reset the position.
+ void Reset() { position_ = 0; }
+
+ // Add a single character to the builder. It is not allowed to add
+ // 0-characters; use the Finalize() method to terminate the string
+ // instead.
+ void AddCharacter(char c) {
+ ASSERT(c != '\0');
+ ASSERT(!is_finalized() && position_ < buffer_.length());
+ buffer_[position_++] = c;
+ }
+
+ // Add an entire string to the builder. Uses strlen() internally to
+ // compute the length of the input string.
+ void AddString(const char* s) {
+ AddSubstring(s, StrLength(s));
+ }
+
+ // Add the first 'n' characters of the given string 's' to the
+ // builder. The input string must have enough characters.
+ void AddSubstring(const char* s, int n) {
+ ASSERT(!is_finalized() && position_ + n < buffer_.length());
+ ASSERT(static_cast<size_t>(n) <= strlen(s));
+ memmove(&buffer_[position_], s, n * kCharSize);
+ position_ += n;
+ }
+
+
+ // Add character padding to the builder. If count is non-positive,
+ // nothing is added to the builder.
+ void AddPadding(char c, int count) {
+ for (int i = 0; i < count; i++) {
+ AddCharacter(c);
+ }
+ }
+
+ // Finalize the string by 0-terminating it and returning the buffer.
+ char* Finalize() {
+ ASSERT(!is_finalized() && position_ < buffer_.length());
+ buffer_[position_] = '\0';
+ // Make sure nobody managed to add a 0-character to the
+ // buffer while building the string.
+ ASSERT(strlen(buffer_.start()) == static_cast<size_t>(position_));
+ position_ = -1;
+ ASSERT(is_finalized());
+ return buffer_.start();
+ }
+
+ private:
+ Vector<char> buffer_;
+ int position_;
+
+ bool is_finalized() const { return position_ < 0; }
+
+ DISALLOW_IMPLICIT_CONSTRUCTORS(StringBuilder);
+};
+
+// The type-based aliasing rule allows the compiler to assume that pointers of
+// different types (for some definition of different) never alias each other.
+// Thus the following code does not work:
+//
+// float f = foo();
+// int fbits = *(int*)(&f);
+//
+// The compiler 'knows' that the int pointer can't refer to f since the types
+// don't match, so the compiler may cache f in a register, leaving random data
+// in fbits. Using C++ style casts makes no difference, however a pointer to
+// char data is assumed to alias any other pointer. This is the 'memcpy
+// exception'.
+//
+// Bit_cast uses the memcpy exception to move the bits from a variable of one
+// type of a variable of another type. Of course the end result is likely to
+// be implementation dependent. Most compilers (gcc-4.2 and MSVC 2005)
+// will completely optimize BitCast away.
+//
+// There is an additional use for BitCast.
+// Recent gccs will warn when they see casts that may result in breakage due to
+// the type-based aliasing rule. If you have checked that there is no breakage
+// you can use BitCast to cast one pointer type to another. This confuses gcc
+// enough that it can no longer see that you have cast one pointer type to
+// another thus avoiding the warning.
+template <class Dest, class Source>
+inline Dest BitCast(const Source& source) {
+ // Compile time assertion: sizeof(Dest) == sizeof(Source)
+ // A compile error here means your Dest and Source have different sizes.
+ DOUBLE_CONVERSION_UNUSED
+ typedef char VerifySizesAreEqual[sizeof(Dest) == sizeof(Source) ? 1 : -1];
+
+ Dest dest;
+ memmove(&dest, &source, sizeof(dest));
+ return dest;
+}
+
+template <class Dest, class Source>
+inline Dest BitCast(Source* source) {
+ return BitCast<Dest>(reinterpret_cast<uintptr_t>(source));
+}
+
+} // namespace double_conversion
+
+// ICU PATCH: Close ICU namespace
+U_NAMESPACE_END
+
+#endif // DOUBLE_CONVERSION_UTILS_H_
+#endif // ICU PATCH: close #if !UCONFIG_NO_FORMATTING
diff --git a/Build/source/libs/icu/icu-src/source/i18n/double-conversion.cpp b/Build/source/libs/icu/icu-src/source/i18n/double-conversion.cpp
new file mode 100644
index 00000000000..8629284aa0e
--- /dev/null
+++ b/Build/source/libs/icu/icu-src/source/i18n/double-conversion.cpp
@@ -0,0 +1,1005 @@
+// © 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 <limits.h>
+#include <math.h>
+
+// ICU PATCH: Customize header file paths for ICU.
+// The files fixed-dtoa.h and strtod.h are 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-utils.h"
+
+// ICU PATCH: Wrap in ICU namespace
+U_NAMESPACE_BEGIN
+
+namespace double_conversion {
+
+#if 0 // not needed for ICU
+const DoubleToStringConverter& DoubleToStringConverter::EcmaScriptConverter() {
+ int flags = UNIQUE_ZERO | EMIT_POSITIVE_EXPONENT_SIGN;
+ static DoubleToStringConverter converter(flags,
+ "Infinity",
+ "NaN",
+ 'e',
+ -6, 21,
+ 6, 0);
+ return converter;
+}
+
+
+bool DoubleToStringConverter::HandleSpecialValues(
+ double value,
+ StringBuilder* result_builder) const {
+ Double double_inspect(value);
+ if (double_inspect.IsInfinite()) {
+ if (infinity_symbol_ == NULL) return false;
+ if (value < 0) {
+ result_builder->AddCharacter('-');
+ }
+ result_builder->AddString(infinity_symbol_);
+ return true;
+ }
+ if (double_inspect.IsNan()) {
+ if (nan_symbol_ == NULL) return false;
+ result_builder->AddString(nan_symbol_);
+ return true;
+ }
+ return false;
+}
+
+
+void DoubleToStringConverter::CreateExponentialRepresentation(
+ const char* decimal_digits,
+ int length,
+ int exponent,
+ StringBuilder* result_builder) const {
+ ASSERT(length != 0);
+ result_builder->AddCharacter(decimal_digits[0]);
+ if (length != 1) {
+ result_builder->AddCharacter('.');
+ result_builder->AddSubstring(&decimal_digits[1], length-1);
+ }
+ result_builder->AddCharacter(exponent_character_);
+ if (exponent < 0) {
+ result_builder->AddCharacter('-');
+ exponent = -exponent;
+ } else {
+ if ((flags_ & EMIT_POSITIVE_EXPONENT_SIGN) != 0) {
+ result_builder->AddCharacter('+');
+ }
+ }
+ if (exponent == 0) {
+ result_builder->AddCharacter('0');
+ return;
+ }
+ ASSERT(exponent < 1e4);
+ const int kMaxExponentLength = 5;
+ char buffer[kMaxExponentLength + 1];
+ buffer[kMaxExponentLength] = '\0';
+ int first_char_pos = kMaxExponentLength;
+ while (exponent > 0) {
+ buffer[--first_char_pos] = '0' + (exponent % 10);
+ exponent /= 10;
+ }
+ result_builder->AddSubstring(&buffer[first_char_pos],
+ kMaxExponentLength - first_char_pos);
+}
+
+
+void DoubleToStringConverter::CreateDecimalRepresentation(
+ const char* decimal_digits,
+ int length,
+ int decimal_point,
+ int digits_after_point,
+ StringBuilder* result_builder) const {
+ // Create a representation that is padded with zeros if needed.
+ if (decimal_point <= 0) {
+ // "0.00000decimal_rep" or "0.000decimal_rep00".
+ result_builder->AddCharacter('0');
+ if (digits_after_point > 0) {
+ result_builder->AddCharacter('.');
+ result_builder->AddPadding('0', -decimal_point);
+ ASSERT(length <= digits_after_point - (-decimal_point));
+ result_builder->AddSubstring(decimal_digits, length);
+ int remaining_digits = digits_after_point - (-decimal_point) - length;
+ result_builder->AddPadding('0', remaining_digits);
+ }
+ } else if (decimal_point >= length) {
+ // "decimal_rep0000.00000" or "decimal_rep.0000".
+ result_builder->AddSubstring(decimal_digits, length);
+ result_builder->AddPadding('0', decimal_point - length);
+ if (digits_after_point > 0) {
+ result_builder->AddCharacter('.');
+ result_builder->AddPadding('0', digits_after_point);
+ }
+ } else {
+ // "decima.l_rep000".
+ ASSERT(digits_after_point > 0);
+ result_builder->AddSubstring(decimal_digits, decimal_point);
+ result_builder->AddCharacter('.');
+ ASSERT(length - decimal_point <= digits_after_point);
+ result_builder->AddSubstring(&decimal_digits[decimal_point],
+ length - decimal_point);
+ int remaining_digits = digits_after_point - (length - decimal_point);
+ result_builder->AddPadding('0', remaining_digits);
+ }
+ if (digits_after_point == 0) {
+ if ((flags_ & EMIT_TRAILING_DECIMAL_POINT) != 0) {
+ result_builder->AddCharacter('.');
+ }
+ if ((flags_ & EMIT_TRAILING_ZERO_AFTER_POINT) != 0) {
+ result_builder->AddCharacter('0');
+ }
+ }
+}
+
+
+bool DoubleToStringConverter::ToShortestIeeeNumber(
+ double value,
+ StringBuilder* result_builder,
+ DoubleToStringConverter::DtoaMode mode) const {
+ ASSERT(mode == SHORTEST || mode == SHORTEST_SINGLE);
+ if (Double(value).IsSpecial()) {
+ return HandleSpecialValues(value, result_builder);
+ }
+
+ int decimal_point;
+ bool sign;
+ const int kDecimalRepCapacity = kBase10MaximalLength + 1;
+ char decimal_rep[kDecimalRepCapacity];
+ int decimal_rep_length;
+
+ DoubleToAscii(value, mode, 0, decimal_rep, kDecimalRepCapacity,
+ &sign, &decimal_rep_length, &decimal_point);
+
+ bool unique_zero = (flags_ & UNIQUE_ZERO) != 0;
+ if (sign && (value != 0.0 || !unique_zero)) {
+ result_builder->AddCharacter('-');
+ }
+
+ int exponent = decimal_point - 1;
+ if ((decimal_in_shortest_low_ <= exponent) &&
+ (exponent < decimal_in_shortest_high_)) {
+ CreateDecimalRepresentation(decimal_rep, decimal_rep_length,
+ decimal_point,
+ Max(0, decimal_rep_length - decimal_point),
+ result_builder);
+ } else {
+ CreateExponentialRepresentation(decimal_rep, decimal_rep_length, exponent,
+ result_builder);
+ }
+ return true;
+}
+
+
+bool DoubleToStringConverter::ToFixed(double value,
+ int requested_digits,
+ StringBuilder* result_builder) const {
+ ASSERT(kMaxFixedDigitsBeforePoint == 60);
+ const double kFirstNonFixed = 1e60;
+
+ if (Double(value).IsSpecial()) {
+ return HandleSpecialValues(value, result_builder);
+ }
+
+ if (requested_digits > kMaxFixedDigitsAfterPoint) return false;
+ if (value >= kFirstNonFixed || value <= -kFirstNonFixed) return false;
+
+ // Find a sufficiently precise decimal representation of n.
+ int decimal_point;
+ bool sign;
+ // Add space for the '\0' byte.
+ const int kDecimalRepCapacity =
+ kMaxFixedDigitsBeforePoint + kMaxFixedDigitsAfterPoint + 1;
+ char decimal_rep[kDecimalRepCapacity];
+ int decimal_rep_length;
+ DoubleToAscii(value, FIXED, requested_digits,
+ decimal_rep, kDecimalRepCapacity,
+ &sign, &decimal_rep_length, &decimal_point);
+
+ bool unique_zero = ((flags_ & UNIQUE_ZERO) != 0);
+ if (sign && (value != 0.0 || !unique_zero)) {
+ result_builder->AddCharacter('-');
+ }
+
+ CreateDecimalRepresentation(decimal_rep, decimal_rep_length, decimal_point,
+ requested_digits, result_builder);
+ return true;
+}
+
+
+bool DoubleToStringConverter::ToExponential(
+ double value,
+ int requested_digits,
+ StringBuilder* result_builder) const {
+ if (Double(value).IsSpecial()) {
+ return HandleSpecialValues(value, result_builder);
+ }
+
+ if (requested_digits < -1) return false;
+ if (requested_digits > kMaxExponentialDigits) return false;
+
+ int decimal_point;
+ bool sign;
+ // Add space for digit before the decimal point and the '\0' character.
+ const int kDecimalRepCapacity = kMaxExponentialDigits + 2;
+ ASSERT(kDecimalRepCapacity > kBase10MaximalLength);
+ char decimal_rep[kDecimalRepCapacity];
+ int decimal_rep_length;
+
+ if (requested_digits == -1) {
+ DoubleToAscii(value, SHORTEST, 0,
+ decimal_rep, kDecimalRepCapacity,
+ &sign, &decimal_rep_length, &decimal_point);
+ } else {
+ DoubleToAscii(value, PRECISION, requested_digits + 1,
+ decimal_rep, kDecimalRepCapacity,
+ &sign, &decimal_rep_length, &decimal_point);
+ ASSERT(decimal_rep_length <= requested_digits + 1);
+
+ for (int i = decimal_rep_length; i < requested_digits + 1; ++i) {
+ decimal_rep[i] = '0';
+ }
+ decimal_rep_length = requested_digits + 1;
+ }
+
+ bool unique_zero = ((flags_ & UNIQUE_ZERO) != 0);
+ if (sign && (value != 0.0 || !unique_zero)) {
+ result_builder->AddCharacter('-');
+ }
+
+ int exponent = decimal_point - 1;
+ CreateExponentialRepresentation(decimal_rep,
+ decimal_rep_length,
+ exponent,
+ result_builder);
+ return true;
+}
+
+
+bool DoubleToStringConverter::ToPrecision(double value,
+ int precision,
+ StringBuilder* result_builder) const {
+ if (Double(value).IsSpecial()) {
+ return HandleSpecialValues(value, result_builder);
+ }
+
+ if (precision < kMinPrecisionDigits || precision > kMaxPrecisionDigits) {
+ return false;
+ }
+
+ // Find a sufficiently precise decimal representation of n.
+ int decimal_point;
+ bool sign;
+ // Add one for the terminating null character.
+ const int kDecimalRepCapacity = kMaxPrecisionDigits + 1;
+ char decimal_rep[kDecimalRepCapacity];
+ int decimal_rep_length;
+
+ DoubleToAscii(value, PRECISION, precision,
+ decimal_rep, kDecimalRepCapacity,
+ &sign, &decimal_rep_length, &decimal_point);
+ ASSERT(decimal_rep_length <= precision);
+
+ bool unique_zero = ((flags_ & UNIQUE_ZERO) != 0);
+ if (sign && (value != 0.0 || !unique_zero)) {
+ result_builder->AddCharacter('-');
+ }
+
+ // The exponent if we print the number as x.xxeyyy. That is with the
+ // decimal point after the first digit.
+ int exponent = decimal_point - 1;
+
+ int extra_zero = ((flags_ & EMIT_TRAILING_ZERO_AFTER_POINT) != 0) ? 1 : 0;
+ if ((-decimal_point + 1 > max_leading_padding_zeroes_in_precision_mode_) ||
+ (decimal_point - precision + extra_zero >
+ max_trailing_padding_zeroes_in_precision_mode_)) {
+ // Fill buffer to contain 'precision' digits.
+ // Usually the buffer is already at the correct length, but 'DoubleToAscii'
+ // is allowed to return less characters.
+ for (int i = decimal_rep_length; i < precision; ++i) {
+ decimal_rep[i] = '0';
+ }
+
+ CreateExponentialRepresentation(decimal_rep,
+ precision,
+ exponent,
+ result_builder);
+ } else {
+ CreateDecimalRepresentation(decimal_rep, decimal_rep_length, decimal_point,
+ Max(0, precision - decimal_point),
+ result_builder);
+ }
+ return true;
+}
+#endif // not needed for ICU
+
+
+static BignumDtoaMode DtoaToBignumDtoaMode(
+ DoubleToStringConverter::DtoaMode dtoa_mode) {
+ switch (dtoa_mode) {
+ case DoubleToStringConverter::SHORTEST: return BIGNUM_DTOA_SHORTEST;
+ case DoubleToStringConverter::SHORTEST_SINGLE:
+ return BIGNUM_DTOA_SHORTEST_SINGLE;
+ case DoubleToStringConverter::FIXED: return BIGNUM_DTOA_FIXED;
+ case DoubleToStringConverter::PRECISION: return BIGNUM_DTOA_PRECISION;
+ default:
+ UNREACHABLE();
+ }
+}
+
+
+void DoubleToStringConverter::DoubleToAscii(double v,
+ DtoaMode mode,
+ int requested_digits,
+ char* buffer,
+ int buffer_length,
+ bool* sign,
+ int* length,
+ int* point) {
+ Vector<char> vector(buffer, buffer_length);
+ ASSERT(!Double(v).IsSpecial());
+ ASSERT(mode == SHORTEST || mode == SHORTEST_SINGLE || requested_digits >= 0);
+
+ if (Double(v).Sign() < 0) {
+ *sign = true;
+ v = -v;
+ } else {
+ *sign = false;
+ }
+
+ if (mode == PRECISION && requested_digits == 0) {
+ vector[0] = '\0';
+ *length = 0;
+ return;
+ }
+
+ if (v == 0) {
+ vector[0] = '0';
+ vector[1] = '\0';
+ *length = 1;
+ *point = 1;
+ return;
+ }
+
+ bool fast_worked;
+ switch (mode) {
+ case SHORTEST:
+ fast_worked = FastDtoa(v, FAST_DTOA_SHORTEST, 0, vector, length, point);
+ break;
+#if 0 // not needed for ICU
+ case SHORTEST_SINGLE:
+ fast_worked = FastDtoa(v, FAST_DTOA_SHORTEST_SINGLE, 0,
+ vector, length, point);
+ break;
+ case FIXED:
+ fast_worked = FastFixedDtoa(v, requested_digits, vector, length, point);
+ break;
+ case PRECISION:
+ fast_worked = FastDtoa(v, FAST_DTOA_PRECISION, requested_digits,
+ vector, length, point);
+ break;
+#endif // not needed for ICU
+ default:
+ fast_worked = false;
+ UNREACHABLE();
+ }
+ if (fast_worked) return;
+
+ // If the fast dtoa didn't succeed use the slower bignum version.
+ BignumDtoaMode bignum_mode = DtoaToBignumDtoaMode(mode);
+ BignumDtoa(v, bignum_mode, requested_digits, vector, length, point);
+ vector[*length] = '\0';
+}
+
+
+#if 0 // not needed for ICU
+// Consumes the given substring from the iterator.
+// Returns false, if the substring does not match.
+template <class Iterator>
+static bool ConsumeSubString(Iterator* current,
+ Iterator end,
+ const char* substring) {
+ ASSERT(**current == *substring);
+ for (substring++; *substring != '\0'; substring++) {
+ ++*current;
+ if (*current == end || **current != *substring) return false;
+ }
+ ++*current;
+ return true;
+}
+
+
+// Maximum number of significant digits in decimal representation.
+// The longest possible double in decimal representation is
+// (2^53 - 1) * 2 ^ -1074 that is (2 ^ 53 - 1) * 5 ^ 1074 / 10 ^ 1074
+// (768 digits). If we parse a number whose first digits are equal to a
+// mean of 2 adjacent doubles (that could have up to 769 digits) the result
+// must be rounded to the bigger one unless the tail consists of zeros, so
+// we don't need to preserve all the digits.
+const int kMaxSignificantDigits = 772;
+
+
+static const char kWhitespaceTable7[] = { 32, 13, 10, 9, 11, 12 };
+static const int kWhitespaceTable7Length = ARRAY_SIZE(kWhitespaceTable7);
+
+
+static const uc16 kWhitespaceTable16[] = {
+ 160, 8232, 8233, 5760, 6158, 8192, 8193, 8194, 8195,
+ 8196, 8197, 8198, 8199, 8200, 8201, 8202, 8239, 8287, 12288, 65279
+};
+static const int kWhitespaceTable16Length = ARRAY_SIZE(kWhitespaceTable16);
+
+
+static bool isWhitespace(int x) {
+ if (x < 128) {
+ for (int i = 0; i < kWhitespaceTable7Length; i++) {
+ if (kWhitespaceTable7[i] == x) return true;
+ }
+ } else {
+ for (int i = 0; i < kWhitespaceTable16Length; i++) {
+ if (kWhitespaceTable16[i] == x) return true;
+ }
+ }
+ return false;
+}
+
+
+// Returns true if a nonspace found and false if the end has reached.
+template <class Iterator>
+static inline bool AdvanceToNonspace(Iterator* current, Iterator end) {
+ while (*current != end) {
+ if (!isWhitespace(**current)) return true;
+ ++*current;
+ }
+ return false;
+}
+
+
+static bool isDigit(int x, int radix) {
+ return (x >= '0' && x <= '9' && x < '0' + radix)
+ || (radix > 10 && x >= 'a' && x < 'a' + radix - 10)
+ || (radix > 10 && x >= 'A' && x < 'A' + radix - 10);
+}
+
+
+static double SignedZero(bool sign) {
+ return sign ? -0.0 : 0.0;
+}
+
+
+// Returns true if 'c' is a decimal digit that is valid for the given radix.
+//
+// The function is small and could be inlined, but VS2012 emitted a warning
+// because it constant-propagated the radix and concluded that the last
+// condition was always true. By moving it into a separate function the
+// compiler wouldn't warn anymore.
+#if _MSC_VER
+#pragma optimize("",off)
+static bool IsDecimalDigitForRadix(int c, int radix) {
+ return '0' <= c && c <= '9' && (c - '0') < radix;
+}
+#pragma optimize("",on)
+#else
+static bool inline IsDecimalDigitForRadix(int c, int radix) {
+ return '0' <= c && c <= '9' && (c - '0') < radix;
+}
+#endif
+// Returns true if 'c' is a character digit that is valid for the given radix.
+// The 'a_character' should be 'a' or 'A'.
+//
+// The function is small and could be inlined, but VS2012 emitted a warning
+// because it constant-propagated the radix and concluded that the first
+// condition was always false. By moving it into a separate function the
+// compiler wouldn't warn anymore.
+static bool IsCharacterDigitForRadix(int c, int radix, char a_character) {
+ return radix > 10 && c >= a_character && c < a_character + radix - 10;
+}
+
+
+// Parsing integers with radix 2, 4, 8, 16, 32. Assumes current != end.
+template <int radix_log_2, class Iterator>
+static double RadixStringToIeee(Iterator* current,
+ Iterator end,
+ bool sign,
+ bool allow_trailing_junk,
+ double junk_string_value,
+ bool read_as_double,
+ bool* result_is_junk) {
+ ASSERT(*current != end);
+
+ const int kDoubleSize = Double::kSignificandSize;
+ const int kSingleSize = Single::kSignificandSize;
+ const int kSignificandSize = read_as_double? kDoubleSize: kSingleSize;
+
+ *result_is_junk = true;
+
+ // Skip leading 0s.
+ while (**current == '0') {
+ ++(*current);
+ if (*current == end) {
+ *result_is_junk = false;
+ return SignedZero(sign);
+ }
+ }
+
+ int64_t number = 0;
+ int exponent = 0;
+ const int radix = (1 << radix_log_2);
+
+ do {
+ int digit;
+ if (IsDecimalDigitForRadix(**current, radix)) {
+ digit = static_cast<char>(**current) - '0';
+ } else if (IsCharacterDigitForRadix(**current, radix, 'a')) {
+ digit = static_cast<char>(**current) - 'a' + 10;
+ } else if (IsCharacterDigitForRadix(**current, radix, 'A')) {
+ digit = static_cast<char>(**current) - 'A' + 10;
+ } else {
+ if (allow_trailing_junk || !AdvanceToNonspace(current, end)) {
+ break;
+ } else {
+ return junk_string_value;
+ }
+ }
+
+ number = number * radix + digit;
+ int overflow = static_cast<int>(number >> kSignificandSize);
+ if (overflow != 0) {
+ // Overflow occurred. Need to determine which direction to round the
+ // result.
+ int overflow_bits_count = 1;
+ while (overflow > 1) {
+ overflow_bits_count++;
+ overflow >>= 1;
+ }
+
+ int dropped_bits_mask = ((1 << overflow_bits_count) - 1);
+ int dropped_bits = static_cast<int>(number) & dropped_bits_mask;
+ number >>= overflow_bits_count;
+ exponent = overflow_bits_count;
+
+ bool zero_tail = true;
+ for (;;) {
+ ++(*current);
+ if (*current == end || !isDigit(**current, radix)) break;
+ zero_tail = zero_tail && **current == '0';
+ exponent += radix_log_2;
+ }
+
+ if (!allow_trailing_junk && AdvanceToNonspace(current, end)) {
+ return junk_string_value;
+ }
+
+ int middle_value = (1 << (overflow_bits_count - 1));
+ if (dropped_bits > middle_value) {
+ number++; // Rounding up.
+ } else if (dropped_bits == middle_value) {
+ // Rounding to even to consistency with decimals: half-way case rounds
+ // up if significant part is odd and down otherwise.
+ if ((number & 1) != 0 || !zero_tail) {
+ number++; // Rounding up.
+ }
+ }
+
+ // Rounding up may cause overflow.
+ if ((number & ((int64_t)1 << kSignificandSize)) != 0) {
+ exponent++;
+ number >>= 1;
+ }
+ break;
+ }
+ ++(*current);
+ } while (*current != end);
+
+ ASSERT(number < ((int64_t)1 << kSignificandSize));
+ ASSERT(static_cast<int64_t>(static_cast<double>(number)) == number);
+
+ *result_is_junk = false;
+
+ if (exponent == 0) {
+ if (sign) {
+ if (number == 0) return -0.0;
+ number = -number;
+ }
+ return static_cast<double>(number);
+ }
+
+ ASSERT(number != 0);
+ return Double(DiyFp(number, exponent)).value();
+}
+
+
+template <class Iterator>
+double StringToDoubleConverter::StringToIeee(
+ Iterator input,
+ int length,
+ bool read_as_double,
+ int* processed_characters_count) const {
+ Iterator current = input;
+ Iterator end = input + length;
+
+ *processed_characters_count = 0;
+
+ const bool allow_trailing_junk = (flags_ & ALLOW_TRAILING_JUNK) != 0;
+ const bool allow_leading_spaces = (flags_ & ALLOW_LEADING_SPACES) != 0;
+ const bool allow_trailing_spaces = (flags_ & ALLOW_TRAILING_SPACES) != 0;
+ const bool allow_spaces_after_sign = (flags_ & ALLOW_SPACES_AFTER_SIGN) != 0;
+
+ // To make sure that iterator dereferencing is valid the following
+ // convention is used:
+ // 1. Each '++current' statement is followed by check for equality to 'end'.
+ // 2. If AdvanceToNonspace returned false then current == end.
+ // 3. If 'current' becomes equal to 'end' the function returns or goes to
+ // 'parsing_done'.
+ // 4. 'current' is not dereferenced after the 'parsing_done' label.
+ // 5. Code before 'parsing_done' may rely on 'current != end'.
+ if (current == end) return empty_string_value_;
+
+ if (allow_leading_spaces || allow_trailing_spaces) {
+ if (!AdvanceToNonspace(&current, end)) {
+ *processed_characters_count = static_cast<int>(current - input);
+ return empty_string_value_;
+ }
+ if (!allow_leading_spaces && (input != current)) {
+ // No leading spaces allowed, but AdvanceToNonspace moved forward.
+ return junk_string_value_;
+ }
+ }
+
+ // The longest form of simplified number is: "-<significant digits>.1eXXX\0".
+ const int kBufferSize = kMaxSignificantDigits + 10;
+ char buffer[kBufferSize]; // NOLINT: size is known at compile time.
+ int buffer_pos = 0;
+
+ // Exponent will be adjusted if insignificant digits of the integer part
+ // or insignificant leading zeros of the fractional part are dropped.
+ int exponent = 0;
+ int significant_digits = 0;
+ int insignificant_digits = 0;
+ bool nonzero_digit_dropped = false;
+
+ bool sign = false;
+
+ if (*current == '+' || *current == '-') {
+ sign = (*current == '-');
+ ++current;
+ Iterator next_non_space = current;
+ // Skip following spaces (if allowed).
+ if (!AdvanceToNonspace(&next_non_space, end)) return junk_string_value_;
+ if (!allow_spaces_after_sign && (current != next_non_space)) {
+ return junk_string_value_;
+ }
+ current = next_non_space;
+ }
+
+ if (infinity_symbol_ != NULL) {
+ if (*current == infinity_symbol_[0]) {
+ if (!ConsumeSubString(&current, end, infinity_symbol_)) {
+ return junk_string_value_;
+ }
+
+ if (!(allow_trailing_spaces || allow_trailing_junk) && (current != end)) {
+ return junk_string_value_;
+ }
+ if (!allow_trailing_junk && AdvanceToNonspace(&current, end)) {
+ return junk_string_value_;
+ }
+
+ ASSERT(buffer_pos == 0);
+ *processed_characters_count = static_cast<int>(current - input);
+ return sign ? -Double::Infinity() : Double::Infinity();
+ }
+ }
+
+ if (nan_symbol_ != NULL) {
+ if (*current == nan_symbol_[0]) {
+ if (!ConsumeSubString(&current, end, nan_symbol_)) {
+ return junk_string_value_;
+ }
+
+ if (!(allow_trailing_spaces || allow_trailing_junk) && (current != end)) {
+ return junk_string_value_;
+ }
+ if (!allow_trailing_junk && AdvanceToNonspace(&current, end)) {
+ return junk_string_value_;
+ }
+
+ ASSERT(buffer_pos == 0);
+ *processed_characters_count = static_cast<int>(current - input);
+ return sign ? -Double::NaN() : Double::NaN();
+ }
+ }
+
+ bool leading_zero = false;
+ if (*current == '0') {
+ ++current;
+ if (current == end) {
+ *processed_characters_count = static_cast<int>(current - input);
+ return SignedZero(sign);
+ }
+
+ leading_zero = true;
+
+ // It could be hexadecimal value.
+ if ((flags_ & ALLOW_HEX) && (*current == 'x' || *current == 'X')) {
+ ++current;
+ if (current == end || !isDigit(*current, 16)) {
+ return junk_string_value_; // "0x".
+ }
+
+ bool result_is_junk;
+ double result = RadixStringToIeee<4>(&current,
+ end,
+ sign,
+ allow_trailing_junk,
+ junk_string_value_,
+ read_as_double,
+ &result_is_junk);
+ if (!result_is_junk) {
+ if (allow_trailing_spaces) AdvanceToNonspace(&current, end);
+ *processed_characters_count = static_cast<int>(current - input);
+ }
+ return result;
+ }
+
+ // Ignore leading zeros in the integer part.
+ while (*current == '0') {
+ ++current;
+ if (current == end) {
+ *processed_characters_count = static_cast<int>(current - input);
+ return SignedZero(sign);
+ }
+ }
+ }
+
+ bool octal = leading_zero && (flags_ & ALLOW_OCTALS) != 0;
+
+ // Copy significant digits of the integer part (if any) to the buffer.
+ while (*current >= '0' && *current <= '9') {
+ if (significant_digits < kMaxSignificantDigits) {
+ ASSERT(buffer_pos < kBufferSize);
+ buffer[buffer_pos++] = static_cast<char>(*current);
+ significant_digits++;
+ // Will later check if it's an octal in the buffer.
+ } else {
+ insignificant_digits++; // Move the digit into the exponential part.
+ nonzero_digit_dropped = nonzero_digit_dropped || *current != '0';
+ }
+ octal = octal && *current < '8';
+ ++current;
+ if (current == end) goto parsing_done;
+ }
+
+ if (significant_digits == 0) {
+ octal = false;
+ }
+
+ if (*current == '.') {
+ if (octal && !allow_trailing_junk) return junk_string_value_;
+ if (octal) goto parsing_done;
+
+ ++current;
+ if (current == end) {
+ if (significant_digits == 0 && !leading_zero) {
+ return junk_string_value_;
+ } else {
+ goto parsing_done;
+ }
+ }
+
+ if (significant_digits == 0) {
+ // octal = false;
+ // Integer part consists of 0 or is absent. Significant digits start after
+ // leading zeros (if any).
+ while (*current == '0') {
+ ++current;
+ if (current == end) {
+ *processed_characters_count = static_cast<int>(current - input);
+ return SignedZero(sign);
+ }
+ exponent--; // Move this 0 into the exponent.
+ }
+ }
+
+ // There is a fractional part.
+ // We don't emit a '.', but adjust the exponent instead.
+ while (*current >= '0' && *current <= '9') {
+ if (significant_digits < kMaxSignificantDigits) {
+ ASSERT(buffer_pos < kBufferSize);
+ buffer[buffer_pos++] = static_cast<char>(*current);
+ significant_digits++;
+ exponent--;
+ } else {
+ // Ignore insignificant digits in the fractional part.
+ nonzero_digit_dropped = nonzero_digit_dropped || *current != '0';
+ }
+ ++current;
+ if (current == end) goto parsing_done;
+ }
+ }
+
+ if (!leading_zero && exponent == 0 && significant_digits == 0) {
+ // If leading_zeros is true then the string contains zeros.
+ // If exponent < 0 then string was [+-]\.0*...
+ // If significant_digits != 0 the string is not equal to 0.
+ // Otherwise there are no digits in the string.
+ return junk_string_value_;
+ }
+
+ // Parse exponential part.
+ if (*current == 'e' || *current == 'E') {
+ if (octal && !allow_trailing_junk) return junk_string_value_;
+ if (octal) goto parsing_done;
+ ++current;
+ if (current == end) {
+ if (allow_trailing_junk) {
+ goto parsing_done;
+ } else {
+ return junk_string_value_;
+ }
+ }
+ char exponen_sign = '+';
+ if (*current == '+' || *current == '-') {
+ exponen_sign = static_cast<char>(*current);
+ ++current;
+ if (current == end) {
+ if (allow_trailing_junk) {
+ goto parsing_done;
+ } else {
+ return junk_string_value_;
+ }
+ }
+ }
+
+ if (current == end || *current < '0' || *current > '9') {
+ if (allow_trailing_junk) {
+ goto parsing_done;
+ } else {
+ return junk_string_value_;
+ }
+ }
+
+ const int max_exponent = INT_MAX / 2;
+ ASSERT(-max_exponent / 2 <= exponent && exponent <= max_exponent / 2);
+ int num = 0;
+ do {
+ // Check overflow.
+ int digit = *current - '0';
+ if (num >= max_exponent / 10
+ && !(num == max_exponent / 10 && digit <= max_exponent % 10)) {
+ num = max_exponent;
+ } else {
+ num = num * 10 + digit;
+ }
+ ++current;
+ } while (current != end && *current >= '0' && *current <= '9');
+
+ exponent += (exponen_sign == '-' ? -num : num);
+ }
+
+ if (!(allow_trailing_spaces || allow_trailing_junk) && (current != end)) {
+ return junk_string_value_;
+ }
+ if (!allow_trailing_junk && AdvanceToNonspace(&current, end)) {
+ return junk_string_value_;
+ }
+ if (allow_trailing_spaces) {
+ AdvanceToNonspace(&current, end);
+ }
+
+ parsing_done:
+ exponent += insignificant_digits;
+
+ if (octal) {
+ double result;
+ bool result_is_junk;
+ char* start = buffer;
+ result = RadixStringToIeee<3>(&start,
+ buffer + buffer_pos,
+ sign,
+ allow_trailing_junk,
+ junk_string_value_,
+ read_as_double,
+ &result_is_junk);
+ ASSERT(!result_is_junk);
+ *processed_characters_count = static_cast<int>(current - input);
+ return result;
+ }
+
+ if (nonzero_digit_dropped) {
+ buffer[buffer_pos++] = '1';
+ exponent--;
+ }
+
+ ASSERT(buffer_pos < kBufferSize);
+ buffer[buffer_pos] = '\0';
+
+ double converted;
+ if (read_as_double) {
+ converted = Strtod(Vector<const char>(buffer, buffer_pos), exponent);
+ } else {
+ converted = Strtof(Vector<const char>(buffer, buffer_pos), exponent);
+ }
+ *processed_characters_count = static_cast<int>(current - input);
+ return sign? -converted: converted;
+}
+
+
+double StringToDoubleConverter::StringToDouble(
+ const char* buffer,
+ int length,
+ int* processed_characters_count) const {
+ return StringToIeee(buffer, length, true, processed_characters_count);
+}
+
+
+double StringToDoubleConverter::StringToDouble(
+ const uc16* buffer,
+ int length,
+ int* processed_characters_count) const {
+ return StringToIeee(buffer, length, true, processed_characters_count);
+}
+
+
+float StringToDoubleConverter::StringToFloat(
+ const char* buffer,
+ int length,
+ int* processed_characters_count) const {
+ return static_cast<float>(StringToIeee(buffer, length, false,
+ processed_characters_count));
+}
+
+
+float StringToDoubleConverter::StringToFloat(
+ const uc16* buffer,
+ int length,
+ int* processed_characters_count) const {
+ return static_cast<float>(StringToIeee(buffer, length, false,
+ processed_characters_count));
+}
+#endif // not needed for ICU
+
+} // namespace double_conversion
+
+// ICU PATCH: Close ICU namespace
+U_NAMESPACE_END
+#endif // ICU PATCH: close #if !UCONFIG_NO_FORMATTING
diff --git a/Build/source/libs/icu/icu-src/source/i18n/double-conversion.h b/Build/source/libs/icu/icu-src/source/i18n/double-conversion.h
new file mode 100644
index 00000000000..0939412734a
--- /dev/null
+++ b/Build/source/libs/icu/icu-src/source/i18n/double-conversion.h
@@ -0,0 +1,566 @@
+// © 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 2012 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_DOUBLE_CONVERSION_H_
+#define DOUBLE_CONVERSION_DOUBLE_CONVERSION_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 {
+
+class DoubleToStringConverter {
+ public:
+#if 0 // not needed for ICU
+ // When calling ToFixed with a double > 10^kMaxFixedDigitsBeforePoint
+ // or a requested_digits parameter > kMaxFixedDigitsAfterPoint then the
+ // function returns false.
+ static const int kMaxFixedDigitsBeforePoint = 60;
+ static const int kMaxFixedDigitsAfterPoint = 60;
+
+ // When calling ToExponential with a requested_digits
+ // parameter > kMaxExponentialDigits then the function returns false.
+ static const int kMaxExponentialDigits = 120;
+
+ // When calling ToPrecision with a requested_digits
+ // parameter < kMinPrecisionDigits or requested_digits > kMaxPrecisionDigits
+ // then the function returns false.
+ static const int kMinPrecisionDigits = 1;
+ static const int kMaxPrecisionDigits = 120;
+
+ enum Flags {
+ NO_FLAGS = 0,
+ EMIT_POSITIVE_EXPONENT_SIGN = 1,
+ EMIT_TRAILING_DECIMAL_POINT = 2,
+ EMIT_TRAILING_ZERO_AFTER_POINT = 4,
+ UNIQUE_ZERO = 8
+ };
+
+ // Flags should be a bit-or combination of the possible Flags-enum.
+ // - NO_FLAGS: no special flags.
+ // - EMIT_POSITIVE_EXPONENT_SIGN: when the number is converted into exponent
+ // form, emits a '+' for positive exponents. Example: 1.2e+2.
+ // - EMIT_TRAILING_DECIMAL_POINT: when the input number is an integer and is
+ // converted into decimal format then a trailing decimal point is appended.
+ // Example: 2345.0 is converted to "2345.".
+ // - EMIT_TRAILING_ZERO_AFTER_POINT: in addition to a trailing decimal point
+ // emits a trailing '0'-character. This flag requires the
+ // EXMIT_TRAILING_DECIMAL_POINT flag.
+ // Example: 2345.0 is converted to "2345.0".
+ // - UNIQUE_ZERO: "-0.0" is converted to "0.0".
+ //
+ // Infinity symbol and nan_symbol provide the string representation for these
+ // special values. If the string is NULL and the special value is encountered
+ // then the conversion functions return false.
+ //
+ // The exponent_character is used in exponential representations. It is
+ // usually 'e' or 'E'.
+ //
+ // When converting to the shortest representation the converter will
+ // represent input numbers in decimal format if they are in the interval
+ // [10^decimal_in_shortest_low; 10^decimal_in_shortest_high[
+ // (lower boundary included, greater boundary excluded).
+ // Example: with decimal_in_shortest_low = -6 and
+ // decimal_in_shortest_high = 21:
+ // ToShortest(0.000001) -> "0.000001"
+ // ToShortest(0.0000001) -> "1e-7"
+ // ToShortest(111111111111111111111.0) -> "111111111111111110000"
+ // ToShortest(100000000000000000000.0) -> "100000000000000000000"
+ // ToShortest(1111111111111111111111.0) -> "1.1111111111111111e+21"
+ //
+ // When converting to precision mode the converter may add
+ // max_leading_padding_zeroes before returning the number in exponential
+ // format.
+ // Example with max_leading_padding_zeroes_in_precision_mode = 6.
+ // ToPrecision(0.0000012345, 2) -> "0.0000012"
+ // ToPrecision(0.00000012345, 2) -> "1.2e-7"
+ // Similarily the converter may add up to
+ // max_trailing_padding_zeroes_in_precision_mode in precision mode to avoid
+ // returning an exponential representation. A zero added by the
+ // EMIT_TRAILING_ZERO_AFTER_POINT flag is counted for this limit.
+ // Examples for max_trailing_padding_zeroes_in_precision_mode = 1:
+ // ToPrecision(230.0, 2) -> "230"
+ // ToPrecision(230.0, 2) -> "230." with EMIT_TRAILING_DECIMAL_POINT.
+ // ToPrecision(230.0, 2) -> "2.3e2" with EMIT_TRAILING_ZERO_AFTER_POINT.
+ DoubleToStringConverter(int flags,
+ const char* infinity_symbol,
+ const char* nan_symbol,
+ char exponent_character,
+ int decimal_in_shortest_low,
+ int decimal_in_shortest_high,
+ int max_leading_padding_zeroes_in_precision_mode,
+ int max_trailing_padding_zeroes_in_precision_mode)
+ : flags_(flags),
+ infinity_symbol_(infinity_symbol),
+ nan_symbol_(nan_symbol),
+ exponent_character_(exponent_character),
+ decimal_in_shortest_low_(decimal_in_shortest_low),
+ decimal_in_shortest_high_(decimal_in_shortest_high),
+ max_leading_padding_zeroes_in_precision_mode_(
+ max_leading_padding_zeroes_in_precision_mode),
+ max_trailing_padding_zeroes_in_precision_mode_(
+ max_trailing_padding_zeroes_in_precision_mode) {
+ // When 'trailing zero after the point' is set, then 'trailing point'
+ // must be set too.
+ ASSERT(((flags & EMIT_TRAILING_DECIMAL_POINT) != 0) ||
+ !((flags & EMIT_TRAILING_ZERO_AFTER_POINT) != 0));
+ }
+
+ // Returns a converter following the EcmaScript specification.
+ static const DoubleToStringConverter& EcmaScriptConverter();
+
+ // Computes the shortest string of digits that correctly represent the input
+ // number. Depending on decimal_in_shortest_low and decimal_in_shortest_high
+ // (see constructor) it then either returns a decimal representation, or an
+ // exponential representation.
+ // Example with decimal_in_shortest_low = -6,
+ // decimal_in_shortest_high = 21,
+ // EMIT_POSITIVE_EXPONENT_SIGN activated, and
+ // EMIT_TRAILING_DECIMAL_POINT deactived:
+ // ToShortest(0.000001) -> "0.000001"
+ // ToShortest(0.0000001) -> "1e-7"
+ // ToShortest(111111111111111111111.0) -> "111111111111111110000"
+ // ToShortest(100000000000000000000.0) -> "100000000000000000000"
+ // ToShortest(1111111111111111111111.0) -> "1.1111111111111111e+21"
+ //
+ // Note: the conversion may round the output if the returned string
+ // is accurate enough to uniquely identify the input-number.
+ // For example the most precise representation of the double 9e59 equals
+ // "899999999999999918767229449717619953810131273674690656206848", but
+ // the converter will return the shorter (but still correct) "9e59".
+ //
+ // Returns true if the conversion succeeds. The conversion always succeeds
+ // except when the input value is special and no infinity_symbol or
+ // nan_symbol has been given to the constructor.
+ bool ToShortest(double value, StringBuilder* result_builder) const {
+ return ToShortestIeeeNumber(value, result_builder, SHORTEST);
+ }
+
+ // Same as ToShortest, but for single-precision floats.
+ bool ToShortestSingle(float value, StringBuilder* result_builder) const {
+ return ToShortestIeeeNumber(value, result_builder, SHORTEST_SINGLE);
+ }
+
+
+ // Computes a decimal representation with a fixed number of digits after the
+ // decimal point. The last emitted digit is rounded.
+ //
+ // Examples:
+ // ToFixed(3.12, 1) -> "3.1"
+ // ToFixed(3.1415, 3) -> "3.142"
+ // ToFixed(1234.56789, 4) -> "1234.5679"
+ // ToFixed(1.23, 5) -> "1.23000"
+ // ToFixed(0.1, 4) -> "0.1000"
+ // ToFixed(1e30, 2) -> "1000000000000000019884624838656.00"
+ // ToFixed(0.1, 30) -> "0.100000000000000005551115123126"
+ // ToFixed(0.1, 17) -> "0.10000000000000001"
+ //
+ // If requested_digits equals 0, then the tail of the result depends on
+ // the EMIT_TRAILING_DECIMAL_POINT and EMIT_TRAILING_ZERO_AFTER_POINT.
+ // Examples, for requested_digits == 0,
+ // let EMIT_TRAILING_DECIMAL_POINT and EMIT_TRAILING_ZERO_AFTER_POINT be
+ // - false and false: then 123.45 -> 123
+ // 0.678 -> 1
+ // - true and false: then 123.45 -> 123.
+ // 0.678 -> 1.
+ // - true and true: then 123.45 -> 123.0
+ // 0.678 -> 1.0
+ //
+ // Returns true if the conversion succeeds. The conversion always succeeds
+ // except for the following cases:
+ // - the input value is special and no infinity_symbol or nan_symbol has
+ // been provided to the constructor,
+ // - 'value' > 10^kMaxFixedDigitsBeforePoint, or
+ // - 'requested_digits' > kMaxFixedDigitsAfterPoint.
+ // The last two conditions imply that the result will never contain more than
+ // 1 + kMaxFixedDigitsBeforePoint + 1 + kMaxFixedDigitsAfterPoint characters
+ // (one additional character for the sign, and one for the decimal point).
+ bool ToFixed(double value,
+ int requested_digits,
+ StringBuilder* result_builder) const;
+
+ // Computes a representation in exponential format with requested_digits
+ // after the decimal point. The last emitted digit is rounded.
+ // If requested_digits equals -1, then the shortest exponential representation
+ // is computed.
+ //
+ // Examples with EMIT_POSITIVE_EXPONENT_SIGN deactivated, and
+ // exponent_character set to 'e'.
+ // ToExponential(3.12, 1) -> "3.1e0"
+ // ToExponential(5.0, 3) -> "5.000e0"
+ // ToExponential(0.001, 2) -> "1.00e-3"
+ // ToExponential(3.1415, -1) -> "3.1415e0"
+ // ToExponential(3.1415, 4) -> "3.1415e0"
+ // ToExponential(3.1415, 3) -> "3.142e0"
+ // ToExponential(123456789000000, 3) -> "1.235e14"
+ // ToExponential(1000000000000000019884624838656.0, -1) -> "1e30"
+ // ToExponential(1000000000000000019884624838656.0, 32) ->
+ // "1.00000000000000001988462483865600e30"
+ // ToExponential(1234, 0) -> "1e3"
+ //
+ // Returns true if the conversion succeeds. The conversion always succeeds
+ // except for the following cases:
+ // - the input value is special and no infinity_symbol or nan_symbol has
+ // been provided to the constructor,
+ // - 'requested_digits' > kMaxExponentialDigits.
+ // The last condition implies that the result will never contain more than
+ // kMaxExponentialDigits + 8 characters (the sign, the digit before the
+ // decimal point, the decimal point, the exponent character, the
+ // exponent's sign, and at most 3 exponent digits).
+ bool ToExponential(double value,
+ int requested_digits,
+ StringBuilder* result_builder) const;
+
+ // Computes 'precision' leading digits of the given 'value' and returns them
+ // either in exponential or decimal format, depending on
+ // max_{leading|trailing}_padding_zeroes_in_precision_mode (given to the
+ // constructor).
+ // The last computed digit is rounded.
+ //
+ // Example with max_leading_padding_zeroes_in_precision_mode = 6.
+ // ToPrecision(0.0000012345, 2) -> "0.0000012"
+ // ToPrecision(0.00000012345, 2) -> "1.2e-7"
+ // Similarily the converter may add up to
+ // max_trailing_padding_zeroes_in_precision_mode in precision mode to avoid
+ // returning an exponential representation. A zero added by the
+ // EMIT_TRAILING_ZERO_AFTER_POINT flag is counted for this limit.
+ // Examples for max_trailing_padding_zeroes_in_precision_mode = 1:
+ // ToPrecision(230.0, 2) -> "230"
+ // ToPrecision(230.0, 2) -> "230." with EMIT_TRAILING_DECIMAL_POINT.
+ // ToPrecision(230.0, 2) -> "2.3e2" with EMIT_TRAILING_ZERO_AFTER_POINT.
+ // Examples for max_trailing_padding_zeroes_in_precision_mode = 3, and no
+ // EMIT_TRAILING_ZERO_AFTER_POINT:
+ // ToPrecision(123450.0, 6) -> "123450"
+ // ToPrecision(123450.0, 5) -> "123450"
+ // ToPrecision(123450.0, 4) -> "123500"
+ // ToPrecision(123450.0, 3) -> "123000"
+ // ToPrecision(123450.0, 2) -> "1.2e5"
+ //
+ // Returns true if the conversion succeeds. The conversion always succeeds
+ // except for the following cases:
+ // - the input value is special and no infinity_symbol or nan_symbol has
+ // been provided to the constructor,
+ // - precision < kMinPericisionDigits
+ // - precision > kMaxPrecisionDigits
+ // The last condition implies that the result will never contain more than
+ // kMaxPrecisionDigits + 7 characters (the sign, the decimal point, the
+ // exponent character, the exponent's sign, and at most 3 exponent digits).
+ bool ToPrecision(double value,
+ int precision,
+ StringBuilder* result_builder) const;
+#endif // not needed for ICU
+
+ enum DtoaMode {
+ // Produce the shortest correct representation.
+ // For example the output of 0.299999999999999988897 is (the less accurate
+ // but correct) 0.3.
+ SHORTEST,
+ // Same as SHORTEST, but for single-precision floats.
+ SHORTEST_SINGLE,
+ // Produce a fixed number of digits after the decimal point.
+ // For instance fixed(0.1, 4) becomes 0.1000
+ // If the input number is big, the output will be big.
+ FIXED,
+ // Fixed number of digits (independent of the decimal point).
+ PRECISION
+ };
+
+ // The maximal number of digits that are needed to emit a double in base 10.
+ // A higher precision can be achieved by using more digits, but the shortest
+ // accurate representation of any double will never use more digits than
+ // kBase10MaximalLength.
+ // Note that DoubleToAscii null-terminates its input. So the given buffer
+ // should be at least kBase10MaximalLength + 1 characters long.
+ static const int kBase10MaximalLength = 17;
+
+ // Converts the given double 'v' to ascii. 'v' must not be NaN, +Infinity, or
+ // -Infinity. In SHORTEST_SINGLE-mode this restriction also applies to 'v'
+ // after it has been casted to a single-precision float. That is, in this
+ // mode static_cast<float>(v) must not be NaN, +Infinity or -Infinity.
+ //
+ // The result should be interpreted as buffer * 10^(point-length).
+ //
+ // The output depends on the given mode:
+ // - SHORTEST: produce the least amount of digits for which the internal
+ // identity requirement is still satisfied. If the digits are printed
+ // (together with the correct exponent) then reading this number will give
+ // 'v' again. The buffer will choose the representation that is closest to
+ // 'v'. If there are two at the same distance, than the one farther away
+ // from 0 is chosen (halfway cases - ending with 5 - are rounded up).
+ // In this mode the 'requested_digits' parameter is ignored.
+ // - SHORTEST_SINGLE: same as SHORTEST but with single-precision.
+ // - FIXED: produces digits necessary to print a given number with
+ // 'requested_digits' digits after the decimal point. The produced digits
+ // might be too short in which case the caller has to fill the remainder
+ // with '0's.
+ // Example: toFixed(0.001, 5) is allowed to return buffer="1", point=-2.
+ // Halfway cases are rounded towards +/-Infinity (away from 0). The call
+ // toFixed(0.15, 2) thus returns buffer="2", point=0.
+ // The returned buffer may contain digits that would be truncated from the
+ // shortest representation of the input.
+ // - PRECISION: produces 'requested_digits' where the first digit is not '0'.
+ // Even though the length of produced digits usually equals
+ // 'requested_digits', the function is allowed to return fewer digits, in
+ // which case the caller has to fill the missing digits with '0's.
+ // Halfway cases are again rounded away from 0.
+ // DoubleToAscii expects the given buffer to be big enough to hold all
+ // digits and a terminating null-character. In SHORTEST-mode it expects a
+ // buffer of at least kBase10MaximalLength + 1. In all other modes the
+ // requested_digits parameter and the padding-zeroes limit the size of the
+ // output. Don't forget the decimal point, the exponent character and the
+ // terminating null-character when computing the maximal output size.
+ // The given length is only used in debug mode to ensure the buffer is big
+ // enough.
+ // ICU PATCH: Export this as U_I18N_API for unit tests.
+ static void U_I18N_API DoubleToAscii(double v,
+ DtoaMode mode,
+ int requested_digits,
+ char* buffer,
+ int buffer_length,
+ bool* sign,
+ int* length,
+ int* point);
+
+#if 0 // not needed for ICU
+ private:
+ // Implementation for ToShortest and ToShortestSingle.
+ bool ToShortestIeeeNumber(double value,
+ StringBuilder* result_builder,
+ DtoaMode mode) const;
+
+ // If the value is a special value (NaN or Infinity) constructs the
+ // corresponding string using the configured infinity/nan-symbol.
+ // If either of them is NULL or the value is not special then the
+ // function returns false.
+ bool HandleSpecialValues(double value, StringBuilder* result_builder) const;
+ // Constructs an exponential representation (i.e. 1.234e56).
+ // The given exponent assumes a decimal point after the first decimal digit.
+ void CreateExponentialRepresentation(const char* decimal_digits,
+ int length,
+ int exponent,
+ StringBuilder* result_builder) const;
+ // Creates a decimal representation (i.e 1234.5678).
+ void CreateDecimalRepresentation(const char* decimal_digits,
+ int length,
+ int decimal_point,
+ int digits_after_point,
+ StringBuilder* result_builder) const;
+
+ const int flags_;
+ const char* const infinity_symbol_;
+ const char* const nan_symbol_;
+ const char exponent_character_;
+ const int decimal_in_shortest_low_;
+ const int decimal_in_shortest_high_;
+ const int max_leading_padding_zeroes_in_precision_mode_;
+ const int max_trailing_padding_zeroes_in_precision_mode_;
+
+ DISALLOW_IMPLICIT_CONSTRUCTORS(DoubleToStringConverter);
+};
+
+
+class StringToDoubleConverter {
+ public:
+ // Enumeration for allowing octals and ignoring junk when converting
+ // strings to numbers.
+ enum Flags {
+ NO_FLAGS = 0,
+ ALLOW_HEX = 1,
+ ALLOW_OCTALS = 2,
+ ALLOW_TRAILING_JUNK = 4,
+ ALLOW_LEADING_SPACES = 8,
+ ALLOW_TRAILING_SPACES = 16,
+ ALLOW_SPACES_AFTER_SIGN = 32
+ };
+
+ // Flags should be a bit-or combination of the possible Flags-enum.
+ // - NO_FLAGS: no special flags.
+ // - ALLOW_HEX: recognizes the prefix "0x". Hex numbers may only be integers.
+ // Ex: StringToDouble("0x1234") -> 4660.0
+ // In StringToDouble("0x1234.56") the characters ".56" are trailing
+ // junk. The result of the call is hence dependent on
+ // the ALLOW_TRAILING_JUNK flag and/or the junk value.
+ // With this flag "0x" is a junk-string. Even with ALLOW_TRAILING_JUNK,
+ // the string will not be parsed as "0" followed by junk.
+ //
+ // - ALLOW_OCTALS: recognizes the prefix "0" for octals:
+ // If a sequence of octal digits starts with '0', then the number is
+ // read as octal integer. Octal numbers may only be integers.
+ // Ex: StringToDouble("01234") -> 668.0
+ // StringToDouble("012349") -> 12349.0 // Not a sequence of octal
+ // // digits.
+ // In StringToDouble("01234.56") the characters ".56" are trailing
+ // junk. The result of the call is hence dependent on
+ // the ALLOW_TRAILING_JUNK flag and/or the junk value.
+ // In StringToDouble("01234e56") the characters "e56" are trailing
+ // junk, too.
+ // - ALLOW_TRAILING_JUNK: ignore trailing characters that are not part of
+ // a double literal.
+ // - ALLOW_LEADING_SPACES: skip over leading whitespace, including spaces,
+ // new-lines, and tabs.
+ // - ALLOW_TRAILING_SPACES: ignore trailing whitespace.
+ // - ALLOW_SPACES_AFTER_SIGN: ignore whitespace after the sign.
+ // Ex: StringToDouble("- 123.2") -> -123.2.
+ // StringToDouble("+ 123.2") -> 123.2
+ //
+ // empty_string_value is returned when an empty string is given as input.
+ // If ALLOW_LEADING_SPACES or ALLOW_TRAILING_SPACES are set, then a string
+ // containing only spaces is converted to the 'empty_string_value', too.
+ //
+ // junk_string_value is returned when
+ // a) ALLOW_TRAILING_JUNK is not set, and a junk character (a character not
+ // part of a double-literal) is found.
+ // b) ALLOW_TRAILING_JUNK is set, but the string does not start with a
+ // double literal.
+ //
+ // infinity_symbol and nan_symbol are strings that are used to detect
+ // inputs that represent infinity and NaN. They can be null, in which case
+ // they are ignored.
+ // The conversion routine first reads any possible signs. Then it compares the
+ // following character of the input-string with the first character of
+ // the infinity, and nan-symbol. If either matches, the function assumes, that
+ // a match has been found, and expects the following input characters to match
+ // the remaining characters of the special-value symbol.
+ // This means that the following restrictions apply to special-value symbols:
+ // - they must not start with signs ('+', or '-'),
+ // - they must not have the same first character.
+ // - they must not start with digits.
+ //
+ // Examples:
+ // flags = ALLOW_HEX | ALLOW_TRAILING_JUNK,
+ // empty_string_value = 0.0,
+ // junk_string_value = NaN,
+ // infinity_symbol = "infinity",
+ // nan_symbol = "nan":
+ // StringToDouble("0x1234") -> 4660.0.
+ // StringToDouble("0x1234K") -> 4660.0.
+ // StringToDouble("") -> 0.0 // empty_string_value.
+ // StringToDouble(" ") -> NaN // junk_string_value.
+ // StringToDouble(" 1") -> NaN // junk_string_value.
+ // StringToDouble("0x") -> NaN // junk_string_value.
+ // StringToDouble("-123.45") -> -123.45.
+ // StringToDouble("--123.45") -> NaN // junk_string_value.
+ // StringToDouble("123e45") -> 123e45.
+ // StringToDouble("123E45") -> 123e45.
+ // StringToDouble("123e+45") -> 123e45.
+ // StringToDouble("123E-45") -> 123e-45.
+ // StringToDouble("123e") -> 123.0 // trailing junk ignored.
+ // StringToDouble("123e-") -> 123.0 // trailing junk ignored.
+ // StringToDouble("+NaN") -> NaN // NaN string literal.
+ // StringToDouble("-infinity") -> -inf. // infinity literal.
+ // StringToDouble("Infinity") -> NaN // junk_string_value.
+ //
+ // flags = ALLOW_OCTAL | ALLOW_LEADING_SPACES,
+ // empty_string_value = 0.0,
+ // junk_string_value = NaN,
+ // infinity_symbol = NULL,
+ // nan_symbol = NULL:
+ // StringToDouble("0x1234") -> NaN // junk_string_value.
+ // StringToDouble("01234") -> 668.0.
+ // StringToDouble("") -> 0.0 // empty_string_value.
+ // StringToDouble(" ") -> 0.0 // empty_string_value.
+ // StringToDouble(" 1") -> 1.0
+ // StringToDouble("0x") -> NaN // junk_string_value.
+ // StringToDouble("0123e45") -> NaN // junk_string_value.
+ // StringToDouble("01239E45") -> 1239e45.
+ // StringToDouble("-infinity") -> NaN // junk_string_value.
+ // StringToDouble("NaN") -> NaN // junk_string_value.
+ StringToDoubleConverter(int flags,
+ double empty_string_value,
+ double junk_string_value,
+ const char* infinity_symbol,
+ const char* nan_symbol)
+ : flags_(flags),
+ empty_string_value_(empty_string_value),
+ junk_string_value_(junk_string_value),
+ infinity_symbol_(infinity_symbol),
+ nan_symbol_(nan_symbol) {
+ }
+
+ // Performs the conversion.
+ // The output parameter 'processed_characters_count' is set to the number
+ // of characters that have been processed to read the number.
+ // Spaces than are processed with ALLOW_{LEADING|TRAILING}_SPACES are included
+ // in the 'processed_characters_count'. Trailing junk is never included.
+ double StringToDouble(const char* buffer,
+ int length,
+ int* processed_characters_count) const;
+
+ // Same as StringToDouble above but for 16 bit characters.
+ double StringToDouble(const uc16* buffer,
+ int length,
+ int* processed_characters_count) const;
+
+ // Same as StringToDouble but reads a float.
+ // Note that this is not equivalent to static_cast<float>(StringToDouble(...))
+ // due to potential double-rounding.
+ float StringToFloat(const char* buffer,
+ int length,
+ int* processed_characters_count) const;
+
+ // Same as StringToFloat above but for 16 bit characters.
+ float StringToFloat(const uc16* buffer,
+ int length,
+ int* processed_characters_count) const;
+
+ private:
+ const int flags_;
+ const double empty_string_value_;
+ const double junk_string_value_;
+ const char* const infinity_symbol_;
+ const char* const nan_symbol_;
+
+ template <class Iterator>
+ double StringToIeee(Iterator start_pointer,
+ int length,
+ bool read_as_double,
+ int* processed_characters_count) const;
+
+ DISALLOW_IMPLICIT_CONSTRUCTORS(StringToDoubleConverter);
+#endif // not needed for ICU
+};
+
+} // namespace double_conversion
+
+// ICU PATCH: Close ICU namespace
+U_NAMESPACE_END
+
+#endif // DOUBLE_CONVERSION_DOUBLE_CONVERSION_H_
+#endif // ICU PATCH: close #if !UCONFIG_NO_FORMATTING
diff --git a/Build/source/libs/icu/icu-src/source/i18n/dtptngen.cpp b/Build/source/libs/icu/icu-src/source/i18n/dtptngen.cpp
index 187342e4af2..aefd70464eb 100644
--- a/Build/source/libs/icu/icu-src/source/i18n/dtptngen.cpp
+++ b/Build/source/libs/icu/icu-src/source/i18n/dtptngen.cpp
@@ -261,12 +261,21 @@ static const char* const CLDR_FIELD_APPEND[] = {
"Hour", "Minute", "Second", "*", "Timezone"
};
-static const char* const CLDR_FIELD_NAME[] = {
+static const char* const CLDR_FIELD_NAME[UDATPG_FIELD_COUNT] = {
"era", "year", "quarter", "month", "week", "weekOfMonth", "weekday",
"dayOfYear", "weekdayOfMonth", "day", "dayperiod", // The UDATPG_x_FIELD constants and these fields have a different order than in ICU4J
"hour", "minute", "second", "*", "zone"
};
+static const char* const CLDR_FIELD_WIDTH[] = { // [UDATPG_WIDTH_COUNT]
+ "", "-short", "-narrow"
+};
+
+// TODO(ticket:13619): remove when definition uncommented in dtptngen.h.
+static const int32_t UDATPG_WIDTH_COUNT = UDATPG_NARROW + 1;
+static constexpr UDateTimePGDisplayWidth UDATPG_WIDTH_APPENDITEM = UDATPG_WIDE;
+static constexpr int32_t UDATPG_FIELD_KEY_MAX = 24; // max length of CLDR field tag (type + width)
+
// For appendItems
static const UChar UDATPG_ItemFormat[]= {0x7B, 0x30, 0x7D, 0x20, 0x251C, 0x7B, 0x32, 0x7D, 0x3A,
0x20, 0x7B, 0x31, 0x7D, 0x2524, 0}; // {0} \u251C{2}: {1}\u2524
@@ -379,10 +388,11 @@ DateTimePatternGenerator::operator=(const DateTimePatternGenerator& other) {
}
for (int32_t i=0; i< UDATPG_FIELD_COUNT; ++i ) {
appendItemFormats[i] = other.appendItemFormats[i];
- appendItemNames[i] = other.appendItemNames[i];
- // NUL-terminate for the C API.
- appendItemFormats[i].getTerminatedBuffer();
- appendItemNames[i].getTerminatedBuffer();
+ appendItemFormats[i].getTerminatedBuffer(); // NUL-terminate for the C API.
+ for (int32_t j=0; j< UDATPG_WIDTH_COUNT; ++j ) {
+ fieldDisplayNames[i][j] = other.fieldDisplayNames[i][j];
+ fieldDisplayNames[i][j].getTerminatedBuffer(); // NUL-terminate for the C API.
+ }
}
UErrorCode status = U_ZERO_ERROR;
patternMap->copyFrom(*other.patternMap, status);
@@ -399,10 +409,14 @@ DateTimePatternGenerator::operator==(const DateTimePatternGenerator& other) cons
if ((pLocale==other.pLocale) && (patternMap->equals(*other.patternMap)) &&
(dateTimeFormat==other.dateTimeFormat) && (decimal==other.decimal)) {
for ( int32_t i=0 ; i<UDATPG_FIELD_COUNT; ++i ) {
- if ((appendItemFormats[i] != other.appendItemFormats[i]) ||
- (appendItemNames[i] != other.appendItemNames[i]) ) {
- return FALSE;
- }
+ if (appendItemFormats[i] != other.appendItemFormats[i]) {
+ return FALSE;
+ }
+ for (int32_t j=0; j< UDATPG_WIDTH_COUNT; ++j ) {
+ if (fieldDisplayNames[i][j] != other.fieldDisplayNames[i][j]) {
+ return FALSE;
+ }
+ }
}
return TRUE;
}
@@ -824,15 +838,16 @@ struct DateTimePatternGenerator::AppendItemNamesSink : public ResourceSink {
ResourceTable itemsTable = value.getTable(errorCode);
if (U_FAILURE(errorCode)) { return; }
for (int32_t i = 0; itemsTable.getKeyAndValue(i, key, value); ++i) {
- UDateTimePatternField field = dtpg.getAppendNameNumber(key);
+ UDateTimePGDisplayWidth width;
+ UDateTimePatternField field = dtpg.getFieldAndWidthIndices(key, &width);
if (field == UDATPG_FIELD_COUNT) { continue; }
ResourceTable detailsTable = value.getTable(errorCode);
if (U_FAILURE(errorCode)) { return; }
for (int32_t j = 0; detailsTable.getKeyAndValue(j, key, value); ++j) {
if (uprv_strcmp(key, "dn") != 0) { continue; }
const UnicodeString& valueStr = value.getUnicodeString(errorCode);
- if (dtpg.getAppendItemName(field).isEmpty() && !valueStr.isEmpty()) {
- dtpg.setAppendItemName(field, valueStr);
+ if (dtpg.getFieldDisplayName(field,width).isEmpty() && !valueStr.isEmpty()) {
+ dtpg.setFieldDisplayName(field,width,valueStr);
}
break;
}
@@ -841,8 +856,7 @@ struct DateTimePatternGenerator::AppendItemNamesSink : public ResourceSink {
void fillInMissing() {
for (int32_t i = 0; i < UDATPG_FIELD_COUNT; i++) {
- UDateTimePatternField field = (UDateTimePatternField)i;
- UnicodeString& valueStr = dtpg.getMutableAppendItemName(field);
+ UnicodeString& valueStr = dtpg.getMutableFieldDisplayName((UDateTimePatternField)i, UDATPG_WIDE);
if (valueStr.isEmpty()) {
valueStr = CAP_F;
U_ASSERT(i < 20);
@@ -857,6 +871,12 @@ struct DateTimePatternGenerator::AppendItemNamesSink : public ResourceSink {
// NUL-terminate for the C API.
valueStr.getTerminatedBuffer();
}
+ for (int32_t j = 1; j < UDATPG_WIDTH_COUNT; j++) {
+ UnicodeString& valueStr = dtpg.getMutableFieldDisplayName((UDateTimePatternField)i, (UDateTimePGDisplayWidth)j);
+ if (valueStr.isEmpty()) {
+ valueStr = dtpg.getFieldDisplayName((UDateTimePatternField)i, (UDateTimePGDisplayWidth)(j-1));
+ }
+ }
}
}
};
@@ -969,25 +989,35 @@ DateTimePatternGenerator::getAppendItemFormat(UDateTimePatternField field) const
void
DateTimePatternGenerator::setAppendItemName(UDateTimePatternField field, const UnicodeString& value) {
- appendItemNames[field] = value;
- // NUL-terminate for the C API.
- appendItemNames[field].getTerminatedBuffer();
+ setFieldDisplayName(field, UDATPG_WIDTH_APPENDITEM, value);
}
const UnicodeString&
DateTimePatternGenerator::getAppendItemName(UDateTimePatternField field) const {
- return appendItemNames[field];
+ return fieldDisplayNames[field][UDATPG_WIDTH_APPENDITEM];
+}
+
+void
+DateTimePatternGenerator::setFieldDisplayName(UDateTimePatternField field, UDateTimePGDisplayWidth width, const UnicodeString& value) {
+ fieldDisplayNames[field][width] = value;
+ // NUL-terminate for the C API.
+ fieldDisplayNames[field][width].getTerminatedBuffer();
+}
+
+UnicodeString
+DateTimePatternGenerator::getFieldDisplayName(UDateTimePatternField field, UDateTimePGDisplayWidth width) const {
+ return fieldDisplayNames[field][width];
}
UnicodeString&
-DateTimePatternGenerator::getMutableAppendItemName(UDateTimePatternField field) {
- return appendItemNames[field];
+DateTimePatternGenerator::getMutableFieldDisplayName(UDateTimePatternField field, UDateTimePGDisplayWidth width) {
+ return fieldDisplayNames[field][width];
}
void
DateTimePatternGenerator::getAppendName(UDateTimePatternField field, UnicodeString& value) {
value = SINGLE_QUOTE;
- value += appendItemNames[field];
+ value += fieldDisplayNames[field][UDATPG_WIDTH_APPENDITEM];
value += SINGLE_QUOTE;
}
@@ -1312,9 +1342,23 @@ DateTimePatternGenerator::getAppendFormatNumber(const char* field) const {
}
UDateTimePatternField
-DateTimePatternGenerator::getAppendNameNumber(const char* field) const {
+DateTimePatternGenerator::getFieldAndWidthIndices(const char* key, UDateTimePGDisplayWidth* widthP) const {
+ char cldrFieldKey[UDATPG_FIELD_KEY_MAX + 1];
+ uprv_strncpy(cldrFieldKey, key, UDATPG_FIELD_KEY_MAX);
+ cldrFieldKey[UDATPG_FIELD_KEY_MAX]=0; // ensure termination
+ *widthP = UDATPG_WIDE;
+ char* hyphenPtr = uprv_strchr(cldrFieldKey, '-');
+ if (hyphenPtr) {
+ for (int32_t i=UDATPG_WIDTH_COUNT-1; i>0; --i) {
+ if (uprv_strcmp(CLDR_FIELD_WIDTH[i], hyphenPtr)==0) {
+ *widthP=(UDateTimePGDisplayWidth)i;
+ break;
+ }
+ }
+ *hyphenPtr = 0; // now delete width portion of key
+ }
for (int32_t i=0; i<UDATPG_FIELD_COUNT; ++i ) {
- if (uprv_strcmp(CLDR_FIELD_NAME[i],field)==0) {
+ if (uprv_strcmp(CLDR_FIELD_NAME[i],cldrFieldKey)==0) {
return (UDateTimePatternField)i;
}
}
diff --git a/Build/source/libs/icu/icu-src/source/i18n/i18n.vcxproj b/Build/source/libs/icu/icu-src/source/i18n/i18n.vcxproj
index 3dd3378a521..aa15d5133b8 100644
--- a/Build/source/libs/icu/icu-src/source/i18n/i18n.vcxproj
+++ b/Build/source/libs/icu/icu-src/source/i18n/i18n.vcxproj
@@ -1,51 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <ItemGroup Label="ProjectConfigurations">
- <ProjectConfiguration Include="Debug|Win32">
- <Configuration>Debug</Configuration>
- <Platform>Win32</Platform>
- </ProjectConfiguration>
- <ProjectConfiguration Include="Debug|x64">
- <Configuration>Debug</Configuration>
- <Platform>x64</Platform>
- </ProjectConfiguration>
- <ProjectConfiguration Include="Release|Win32">
- <Configuration>Release</Configuration>
- <Platform>Win32</Platform>
- </ProjectConfiguration>
- <ProjectConfiguration Include="Release|x64">
- <Configuration>Release</Configuration>
- <Platform>x64</Platform>
- </ProjectConfiguration>
- </ItemGroup>
+ <!-- The following import will include the 'default' configuration options for VS projects. -->
+ <Import Project="..\allinone\Build.Windows.ProjectConfiguration.props" />
<PropertyGroup Label="Globals">
<ProjectGuid>{0178B127-6269-407D-B112-93877BB62776}</ProjectGuid>
- <WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
- <ConfigurationType>DynamicLibrary</ConfigurationType>
- <UseOfMfc>false</UseOfMfc>
- <CharacterSet>MultiByte</CharacterSet>
- <PlatformToolset>v140</PlatformToolset>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
- <ConfigurationType>DynamicLibrary</ConfigurationType>
- <UseOfMfc>false</UseOfMfc>
- <CharacterSet>MultiByte</CharacterSet>
- <PlatformToolset>v140</PlatformToolset>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
- <ConfigurationType>DynamicLibrary</ConfigurationType>
- <UseOfMfc>false</UseOfMfc>
- <CharacterSet>MultiByte</CharacterSet>
- <PlatformToolset>v140</PlatformToolset>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <PropertyGroup Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseOfMfc>false</UseOfMfc>
<CharacterSet>MultiByte</CharacterSet>
- <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
@@ -82,42 +46,56 @@
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">.\x64\Debug\</IntDir>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</LinkIncremental>
</PropertyGroup>
+ <!-- Options that are common to *all* "i18n" project configurations -->
+ <ItemDefinitionGroup>
+ <ClCompile>
+ <PreprocessorDefinitions>U_ATTRIBUTE_DEPRECATED=;U_I18N_IMPLEMENTATION;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <DisableLanguageExtensions>false</DisableLanguageExtensions>
+ <WarningLevel>Level3</WarningLevel>
+ <AdditionalIncludeDirectories>..\..\include;..\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>Default</CompileAs>
+ </ClCompile>
+ <ResourceCompile>
+ <AdditionalIncludeDirectories>../common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Link>
+ <BaseAddress>0x4a900000</BaseAddress>
+ </Link>
+ </ItemDefinitionGroup>
+ <!-- Options that are common to all 'Debug' project configurations -->
+ <ItemDefinitionGroup Condition="'$(Configuration)'=='Debug'">
+ <ClCompile>
+ <BrowseInformation>true</BrowseInformation>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>icuucd.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <!-- Options that are common to all 'Release' project configurations -->
+ <ItemDefinitionGroup Condition="'$(Configuration)'=='Release'">
+ <ClCompile>
+ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ </ClCompile>
+ <Link>
+ <AdditionalDependencies>icuuc.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Midl>
- <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <MkTypLibCompatible>true</MkTypLibCompatible>
- <SuppressStartupBanner>true</SuppressStartupBanner>
- <TargetEnvironment>Win32</TargetEnvironment>
<TypeLibraryName>.\..\..\lib\icuin.tlb</TypeLibraryName>
</Midl>
<ClCompile>
- <AdditionalIncludeDirectories>..\..\include;..\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>U_ATTRIBUTE_DEPRECATED=;WIN32;NDEBUG;_CRT_SECURE_NO_DEPRECATE;U_I18N_IMPLEMENTATION;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <StringPooling>true</StringPooling>
- <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
- <FunctionLevelLinking>true</FunctionLevelLinking>
- <DisableLanguageExtensions>false</DisableLanguageExtensions>
- <TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
<PrecompiledHeaderOutputFile>.\x86\Release/i18n.pch</PrecompiledHeaderOutputFile>
<AssemblerListingLocation>.\x86\Release/</AssemblerListingLocation>
<ObjectFileName>.\x86\Release/</ObjectFileName>
<ProgramDataBaseFileName>.\x86\Release/</ProgramDataBaseFileName>
- <WarningLevel>Level3</WarningLevel>
- <SuppressStartupBanner>true</SuppressStartupBanner>
- <CompileAs>Default</CompileAs>
- <AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
- <ResourceCompile>
- <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <Culture>0x0409</Culture>
- <AdditionalIncludeDirectories>../common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- </ResourceCompile>
<Link>
- <OutputFile>..\..\bin\icuin60.dll</OutputFile>
- <SuppressStartupBanner>true</SuppressStartupBanner>
+ <OutputFile>..\..\bin\icuin61.dll</OutputFile>
+ <AdditionalLibraryDirectories>.\..\..\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<ProgramDatabaseFile>.\..\..\lib\icuin.pdb</ProgramDatabaseFile>
- <EnableCOMDATFolding>true</EnableCOMDATFolding>
- <BaseAddress>0x4a900000</BaseAddress>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
@@ -126,43 +104,20 @@
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Midl>
- <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <MkTypLibCompatible>true</MkTypLibCompatible>
- <SuppressStartupBanner>true</SuppressStartupBanner>
- <TargetEnvironment>Win32</TargetEnvironment>
<TypeLibraryName>.\..\..\lib\icuind.tlb</TypeLibraryName>
</Midl>
<ClCompile>
- <Optimization>Disabled</Optimization>
- <AdditionalIncludeDirectories>..\..\include;..\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>U_ATTRIBUTE_DEPRECATED=;WIN32;_DEBUG;_CRT_SECURE_NO_DEPRECATE;U_I18N_IMPLEMENTATION;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
- <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
- <BufferSecurityCheck>true</BufferSecurityCheck>
- <DisableLanguageExtensions>false</DisableLanguageExtensions>
- <TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
<PrecompiledHeaderOutputFile>.\x86\Debug/i18n.pch</PrecompiledHeaderOutputFile>
<AssemblerListingLocation>.\x86\Debug/</AssemblerListingLocation>
<ObjectFileName>.\x86\Debug/</ObjectFileName>
<ProgramDataBaseFileName>.\x86\Debug/</ProgramDataBaseFileName>
<BrowseInformation>true</BrowseInformation>
- <WarningLevel>Level3</WarningLevel>
- <SuppressStartupBanner>true</SuppressStartupBanner>
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
- <CompileAs>Default</CompileAs>
- <AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
- <ResourceCompile>
- <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <Culture>0x0409</Culture>
- <AdditionalIncludeDirectories>../common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- </ResourceCompile>
<Link>
- <OutputFile>..\..\bin\icuin60d.dll</OutputFile>
- <SuppressStartupBanner>true</SuppressStartupBanner>
- <GenerateDebugInformation>true</GenerateDebugInformation>
+ <OutputFile>..\..\bin\icuin61d.dll</OutputFile>
+ <AdditionalLibraryDirectories>.\..\..\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<ProgramDatabaseFile>.\..\..\lib\icuind.pdb</ProgramDatabaseFile>
- <BaseAddress>0x4a900000</BaseAddress>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
@@ -171,85 +126,37 @@
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Midl>
- <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <MkTypLibCompatible>true</MkTypLibCompatible>
- <SuppressStartupBanner>true</SuppressStartupBanner>
- <TargetEnvironment>X64</TargetEnvironment>
<TypeLibraryName>.\..\..\lib64\icuin.tlb</TypeLibraryName>
</Midl>
<ClCompile>
- <AdditionalIncludeDirectories>..\..\include;..\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>U_ATTRIBUTE_DEPRECATED=;WIN64;WIN32;NDEBUG;_CRT_SECURE_NO_DEPRECATE;U_I18N_IMPLEMENTATION;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <StringPooling>true</StringPooling>
- <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
- <FunctionLevelLinking>true</FunctionLevelLinking>
- <DisableLanguageExtensions>false</DisableLanguageExtensions>
- <TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
<PrecompiledHeaderOutputFile>.\x64\Release/i18n.pch</PrecompiledHeaderOutputFile>
<AssemblerListingLocation>.\x64\Release/</AssemblerListingLocation>
<ObjectFileName>.\x64\Release/</ObjectFileName>
<ProgramDataBaseFileName>.\x64\Release/</ProgramDataBaseFileName>
- <WarningLevel>Level3</WarningLevel>
- <SuppressStartupBanner>true</SuppressStartupBanner>
- <CompileAs>Default</CompileAs>
- <AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
- <ResourceCompile>
- <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <Culture>0x0409</Culture>
- <AdditionalIncludeDirectories>../common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- </ResourceCompile>
<Link>
- <OutputFile>..\..\bin64\icuin60.dll</OutputFile>
- <SuppressStartupBanner>true</SuppressStartupBanner>
+ <OutputFile>..\..\bin64\icuin61.dll</OutputFile>
+ <AdditionalLibraryDirectories>.\..\..\lib64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<ProgramDatabaseFile>.\..\..\lib64\icuin.pdb</ProgramDatabaseFile>
- <EnableCOMDATFolding>true</EnableCOMDATFolding>
- <BaseAddress>0x4a900000</BaseAddress>
<ImportLibrary>..\..\lib64\icuin.lib</ImportLibrary>
- <TargetMachine>MachineX64</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Midl>
- <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <MkTypLibCompatible>true</MkTypLibCompatible>
- <SuppressStartupBanner>true</SuppressStartupBanner>
- <TargetEnvironment>X64</TargetEnvironment>
<TypeLibraryName>.\..\..\lib64\icuind.tlb</TypeLibraryName>
</Midl>
<ClCompile>
- <Optimization>Disabled</Optimization>
- <AdditionalIncludeDirectories>..\..\include;..\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>U_ATTRIBUTE_DEPRECATED=;WIN64;WIN32;_DEBUG;_CRT_SECURE_NO_DEPRECATE;U_I18N_IMPLEMENTATION;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
- <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
- <BufferSecurityCheck>true</BufferSecurityCheck>
- <DisableLanguageExtensions>false</DisableLanguageExtensions>
- <TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
<PrecompiledHeaderOutputFile>.\x64\Debug/i18n.pch</PrecompiledHeaderOutputFile>
<AssemblerListingLocation>.\x64\Debug/</AssemblerListingLocation>
<ObjectFileName>.\x64\Debug/</ObjectFileName>
<ProgramDataBaseFileName>.\x64\Debug/</ProgramDataBaseFileName>
- <BrowseInformation>true</BrowseInformation>
- <WarningLevel>Level3</WarningLevel>
- <SuppressStartupBanner>true</SuppressStartupBanner>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
- <CompileAs>Default</CompileAs>
- <AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
- <ResourceCompile>
- <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <Culture>0x0409</Culture>
- <AdditionalIncludeDirectories>../common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- </ResourceCompile>
<Link>
- <OutputFile>..\..\bin64\icuin60d.dll</OutputFile>
- <SuppressStartupBanner>true</SuppressStartupBanner>
- <GenerateDebugInformation>true</GenerateDebugInformation>
+ <OutputFile>..\..\bin64\icuin61d.dll</OutputFile>
+ <AdditionalLibraryDirectories>.\..\..\lib64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<ProgramDatabaseFile>.\..\..\lib64\icuind.pdb</ProgramDatabaseFile>
- <BaseAddress>0x4a900000</BaseAddress>
<ImportLibrary>..\..\lib64\icuind.lib</ImportLibrary>
- <TargetMachine>MachineX64</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
@@ -327,6 +234,12 @@
<ClCompile Include="decimfmt.cpp" />
<ClCompile Include="decNumber.cpp" />
<ClCompile Include="digitlst.cpp" />
+ <ClCompile Include="double-conversion-bignum-dtoa.cpp" />
+ <ClCompile Include="double-conversion-bignum.cpp" />
+ <ClCompile Include="double-conversion-cached-powers.cpp" />
+ <ClCompile Include="double-conversion-diy-fp.cpp" />
+ <ClCompile Include="double-conversion-fast-dtoa.cpp" />
+ <ClCompile Include="double-conversion.cpp" />
<ClCompile Include="dtfmtsym.cpp" />
<ClCompile Include="dtitvfmt.cpp" />
<ClCompile Include="dtitvinf.cpp" />
@@ -413,30 +326,13 @@
<ClCompile Include="utmscale.cpp" />
<ClCompile Include="vtzone.cpp" />
<ClCompile Include="vzone.cpp" />
- <ClCompile Include="windtfmt.cpp">
- <DisableLanguageExtensions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</DisableLanguageExtensions>
- <DisableLanguageExtensions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</DisableLanguageExtensions>
- <DisableLanguageExtensions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</DisableLanguageExtensions>
- <DisableLanguageExtensions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</DisableLanguageExtensions>
- </ClCompile>
- <ClCompile Include="winnmfmt.cpp">
- <DisableLanguageExtensions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</DisableLanguageExtensions>
- <DisableLanguageExtensions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</DisableLanguageExtensions>
- <DisableLanguageExtensions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</DisableLanguageExtensions>
- <DisableLanguageExtensions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</DisableLanguageExtensions>
- </ClCompile>
- <ClCompile Include="wintzimpl.cpp">
- <DisableLanguageExtensions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</DisableLanguageExtensions>
- <DisableLanguageExtensions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</DisableLanguageExtensions>
- <DisableLanguageExtensions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</DisableLanguageExtensions>
- <DisableLanguageExtensions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</DisableLanguageExtensions>
- </ClCompile>
+ <ClCompile Include="windtfmt.cpp" />
+ <ClCompile Include="winnmfmt.cpp" />
+ <ClCompile Include="wintzimpl.cpp" />
<ClCompile Include="zonemeta.cpp" />
<ClCompile Include="zrule.cpp" />
<ClCompile Include="ztrans.cpp" />
- <ClCompile Include="ucln_in.cpp">
- <DisableLanguageExtensions>false</DisableLanguageExtensions>
- </ClCompile>
+ <ClCompile Include="ucln_in.cpp" />
<ClCompile Include="regexcmp.cpp" />
<ClCompile Include="regeximp.cpp" />
<ClCompile Include="regexst.cpp" />
@@ -488,119 +384,7 @@
<ClCompile Include="uspoof_impl.cpp" />
</ItemGroup>
<ItemGroup>
- <CustomBuild Include="unicode\alphaindex.h">
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
<ClInclude Include="bocsu.h" />
- <CustomBuild Include="unicode\coleitr.h">
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\coll.h">
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\search.h">
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\sortkey.h">
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\stsearch.h">
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\tblcoll.h">
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\ucol.h">
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
<ClInclude Include="affixpatternparser.h" />
<ClInclude Include="decimalformatpatternimpl.h" />
<ClInclude Include="decimfmtimpl.h" />
@@ -642,548 +426,46 @@
<ClInclude Include="tzgnames.h" />
<ClInclude Include="tznames_impl.h" />
<ClInclude Include="ucol_imp.h" />
- <CustomBuild Include="unicode\ucoleitr.h">
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\usearch.h">
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\tzfmt.h">
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">copy "%(FullPath)" ..\..\include\unicode</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">copy "%(FullPath)" ..\..\include\unicode</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">copy "%(FullPath)" ..\..\include\unicode</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">copy "%(FullPath)" ..\..\include\unicode</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\tznames.h">
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">copy "%(FullPath)" ..\..\include\unicode</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">copy "%(FullPath)" ..\..\include\unicode</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">copy "%(FullPath)" ..\..\include\unicode</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">copy "%(FullPath)" ..\..\include\unicode</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
<ClInclude Include="uitercollationiterator.h" />
- <CustomBuild Include="unicode\region.h">
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\uregion.h">
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
<ClInclude Include="usrchimp.h" />
<ClInclude Include="astro.h" />
- <CustomBuild Include="unicode\basictz.h">
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
<ClInclude Include="buddhcal.h" />
- <CustomBuild Include="unicode\calendar.h">
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
<ClInclude Include="cecal.h" />
<ClInclude Include="chnsecal.h" />
- <CustomBuild Include="unicode\choicfmt.h">
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\compactdecimalformat.h">
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
<ClInclude Include="coptccal.h" />
- <CustomBuild Include="unicode\curramt.h">
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
<ClInclude Include="currfmt.h" />
- <CustomBuild Include="unicode\currpinf.h">
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\currunit.h">
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
<ClInclude Include="dangical.h" />
- <CustomBuild Include="unicode\datefmt.h">
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\dcfmtsym.h">
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
<ClInclude Include="decContext.h" />
<ClInclude Include="decfmtst.h" />
<ClInclude Include="decimalformatpattern.h" />
- <CustomBuild Include="unicode\decimfmt.h">
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
<ClInclude Include="decNumber.h" />
<ClInclude Include="decNumberLocal.h" />
<ClInclude Include="digitlst.h" />
+ <ClInclude Include="double-conversion-bignum-dtoa.h" />
+ <ClInclude Include="double-conversion-bignum.h" />
+ <ClInclude Include="double-conversion-cached-powers.h" />
+ <ClInclude Include="double-conversion-diy-fp.h" />
+ <ClInclude Include="double-conversion-fast-dtoa.h" />
+ <ClInclude Include="double-conversion-ieee.h" />
+ <ClInclude Include="double-conversion-utils.h" />
+ <ClInclude Include="double-conversion.h" />
<ClInclude Include="dt_impl.h" />
- <CustomBuild Include="unicode\dtfmtsym.h">
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
<ClInclude Include="dtitv_impl.h" />
- <CustomBuild Include="unicode\dtitvfmt.h">
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\dtitvinf.h">
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\dtptngen.h">
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
<ClInclude Include="dtptngen_impl.h" />
- <CustomBuild Include="unicode\dtrule.h">
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
<ClInclude Include="ethpccal.h" />
- <CustomBuild Include="unicode\fieldpos.h">
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\fmtable.h">
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\uformattable.h">
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\format.h">
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
<ClInclude Include="fphdlimp.h" />
- <CustomBuild Include="unicode\fpositer.h">
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\gender.h">
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\ugender.h">
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\gregocal.h">
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
<ClInclude Include="gregoimp.h" />
<ClInclude Include="hebrwcal.h" />
<ClInclude Include="indiancal.h" />
<ClInclude Include="islamcal.h" />
<ClInclude Include="japancal.h" />
- <CustomBuild Include="unicode\measfmt.h">
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\measunit.h">
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\measure.h">
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\msgfmt.h">
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
<ClInclude Include="msgfmt_impl.h" />
<ClInclude Include="nfrlist.h" />
<ClInclude Include="nfrs.h" />
<ClInclude Include="nfrule.h" />
<ClInclude Include="nfsubs.h" />
- <CustomBuild Include="unicode\numfmt.h">
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\numsys.h">
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
<ClInclude Include="olsontz.h" />
<ClInclude Include="persncal.h" />
- <CustomBuild Include="unicode\plurfmt.h">
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\plurrule.h">
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
<ClInclude Include="plurrule_impl.h" />
<ClInclude Include="quantityformatter.h" />
<ClInclude Include="sharedbreakiterator.h" />
@@ -1191,375 +473,11 @@
<ClInclude Include="shareddateformatsymbols.h" />
<ClInclude Include="sharednumberformat.h" />
<ClInclude Include="sharedpluralrules.h" />
- <CustomBuild Include="unicode\rbnf.h">
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\rbtz.h">
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\reldatefmt.h">
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
<ClInclude Include="reldtfmt.h" />
- <CustomBuild Include="unicode\scientificnumberformatter.h">
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\selfmt.h">
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\simpletz.h">
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\smpdtfmt.h">
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
<ClInclude Include="smpdtfst.h" />
<ClInclude Include="standardplural.h" />
<ClInclude Include="taiwncal.h" />
- <CustomBuild Include="unicode\timezone.h">
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\tmunit.h">
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\tmutamt.h">
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\tmutfmt.h">
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\tzrule.h">
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\tztrans.h">
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\ucal.h">
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\udat.h">
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\udateintervalformat.h">
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\udatpg.h">
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\ufieldpositer.h">
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\ulocdata.h">
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\umsg.h">
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
<ClInclude Include="umsg_imp.h" />
- <CustomBuild Include="unicode\unum.h">
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\unumsys.h">
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\upluralrules.h">
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\ureldatefmt.h">
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\utmscale.h">
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\vtzone.h">
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
<ClInclude Include="utf16collationiterator.h" />
<ClInclude Include="utf8collationiterator.h" />
<ClInclude Include="vzone.h" />
@@ -1570,39 +488,11 @@
<ClInclude Include="zrule.h" />
<ClInclude Include="ztrans.h" />
<ClInclude Include="ucln_in.h" />
- <CustomBuild Include="unicode\regex.h">
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
<ClInclude Include="regexcmp.h" />
<ClInclude Include="regexcst.h" />
<ClInclude Include="regeximp.h" />
<ClInclude Include="regexst.h" />
<ClInclude Include="regextxt.h" />
- <CustomBuild Include="unicode\uregex.h">
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
<ClInclude Include="anytrans.h" />
<ClInclude Include="brktrans.h" />
<ClInclude Include="casetrn.h" />
@@ -1624,52 +514,10 @@
<ClInclude Include="titletrn.h" />
<ClInclude Include="tolowtrn.h" />
<ClInclude Include="toupptrn.h" />
- <CustomBuild Include="unicode\translit.h">
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
<ClInclude Include="transreg.h" />
<ClInclude Include="tridpars.h" />
<ClInclude Include="unesctrn.h" />
<ClInclude Include="uni2name.h" />
- <CustomBuild Include="unicode\unirepl.h">
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\utrans.h">
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
<ClInclude Include="csdetect.h" />
<ClInclude Include="csmatch.h" />
<ClInclude Include="csr2022.h" />
@@ -1679,34 +527,6 @@
<ClInclude Include="csrucode.h" />
<ClInclude Include="csrutf8.h" />
<ClInclude Include="inputext.h" />
- <CustomBuild Include="unicode\ucsdet.h">
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\uspoof.h">
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
<ClInclude Include="scriptset.h" />
<ClInclude Include="uspoof_conf.h" />
<ClInclude Include="uspoof_impl.h" />
@@ -1724,25 +544,13 @@
<ClInclude Include="number_stringbuilder.h" />
<ClInclude Include="number_types.h" />
<ClInclude Include="number_utils.h" />
- <CustomBuild Include="unicode\nounit.h">
- <Command>copy "%(FullPath)" ..\..\include\unicode </Command>
- <Outputs>..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\numberformatter.h">
- <Command>copy "%(FullPath)" ..\..\include\unicode </Command>
- <Outputs>..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="i18n.rc" />
</ItemGroup>
- <ItemGroup>
- <ProjectReference Include="..\common\common.vcxproj">
- <Project>{73c0a65b-d1f2-4de1-b3a6-15dad2c23f3d}</Project>
- <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
- </ProjectReference>
- </ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <!-- The following import will copy all of the header files from this projects 'unicode' folder. -->
+ <Import Project="$(SolutionDir)\Windows.CopyUnicodeHeaderFiles.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
-</Project>
+</Project> \ No newline at end of file
diff --git a/Build/source/libs/icu/icu-src/source/i18n/i18n.vcxproj.filters b/Build/source/libs/icu/icu-src/source/i18n/i18n.vcxproj.filters
index 134cd21f7ef..f9759133b90 100644
--- a/Build/source/libs/icu/icu-src/source/i18n/i18n.vcxproj.filters
+++ b/Build/source/libs/icu/icu-src/source/i18n/i18n.vcxproj.filters
@@ -156,6 +156,24 @@
<ClCompile Include="digitlst.cpp">
<Filter>formatting</Filter>
</ClCompile>
+ <ClCompile Include="double-conversion-bignum-dtoa.cpp">
+ <Filter>formatting</Filter>
+ </ClCompile>
+ <ClCompile Include="double-conversion-bignum.cpp">
+ <Filter>formatting</Filter>
+ </ClCompile>
+ <ClCompile Include="double-conversion-cached-powers.cpp">
+ <Filter>formatting</Filter>
+ </ClCompile>
+ <ClCompile Include="double-conversion-diy-fp.cpp">
+ <Filter>formatting</Filter>
+ </ClCompile>
+ <ClCompile Include="double-conversion-fast-dtoa.cpp">
+ <Filter>formatting</Filter>
+ </ClCompile>
+ <ClCompile Include="double-conversion.cpp">
+ <Filter>formatting</Filter>
+ </ClCompile>
<ClCompile Include="dtfmtsym.cpp">
<Filter>formatting</Filter>
</ClCompile>
@@ -540,6 +558,60 @@
<ClCompile Include="uregion.cpp">
<Filter>formatting</Filter>
</ClCompile>
+ <ClCompile Include="number_stringbuilder.cpp">
+ <Filter>formatting</Filter>
+ </ClCompile>
+ <ClCompile Include="number_affixutils.cpp">
+ <Filter>formatting</Filter>
+ </ClCompile>
+ <ClCompile Include="number_compact.cpp">
+ <Filter>formatting</Filter>
+ </ClCompile>
+ <ClCompile Include="number_decimalquantity.cpp">
+ <Filter>formatting</Filter>
+ </ClCompile>
+ <ClCompile Include="number_decimfmtprops.cpp">
+ <Filter>formatting</Filter>
+ </ClCompile>
+ <ClCompile Include="number_fluent.cpp">
+ <Filter>formatting</Filter>
+ </ClCompile>
+ <ClCompile Include="number_formatimpl.cpp">
+ <Filter>formatting</Filter>
+ </ClCompile>
+ <ClCompile Include="number_grouping.cpp">
+ <Filter>formatting</Filter>
+ </ClCompile>
+ <ClCompile Include="number_integerwidth.cpp">
+ <Filter>formatting</Filter>
+ </ClCompile>
+ <ClCompile Include="number_longnames.cpp">
+ <Filter>formatting</Filter>
+ </ClCompile>
+ <ClCompile Include="number_modifiers.cpp">
+ <Filter>formatting</Filter>
+ </ClCompile>
+ <ClCompile Include="number_notation.cpp">
+ <Filter>formatting</Filter>
+ </ClCompile>
+ <ClCompile Include="number_padding.cpp">
+ <Filter>formatting</Filter>
+ </ClCompile>
+ <ClCompile Include="number_patternmodifier.cpp">
+ <Filter>formatting</Filter>
+ </ClCompile>
+ <ClCompile Include="number_patternstring.cpp">
+ <Filter>formatting</Filter>
+ </ClCompile>
+ <ClCompile Include="number_rounding.cpp">
+ <Filter>formatting</Filter>
+ </ClCompile>
+ <ClCompile Include="number_scientific.cpp">
+ <Filter>formatting</Filter>
+ </ClCompile>
+ <ClCompile Include="nounit.cpp">
+ <Filter>misc</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<ClCompile Include="bocsu.cpp">
@@ -707,6 +779,30 @@
<ClInclude Include="digitlst.h">
<Filter>formatting</Filter>
</ClInclude>
+ <ClInclude Include="double-conversion-bignum-dtoa.h">
+ <Filter>formatting</Filter>
+ </ClInclude>
+ <ClInclude Include="double-conversion-bignum.h">
+ <Filter>formatting</Filter>
+ </ClInclude>
+ <ClInclude Include="double-conversion-cached-powers.h">
+ <Filter>formatting</Filter>
+ </ClInclude>
+ <ClInclude Include="double-conversion-diy-fp.h">
+ <Filter>formatting</Filter>
+ </ClInclude>
+ <ClInclude Include="double-conversion-fast-dtoa.h">
+ <Filter>formatting</Filter>
+ </ClInclude>
+ <ClInclude Include="double-conversion-ieee.h">
+ <Filter>formatting</Filter>
+ </ClInclude>
+ <ClInclude Include="double-conversion-utils.h">
+ <Filter>formatting</Filter>
+ </ClInclude>
+ <ClInclude Include="double-conversion.h">
+ <Filter>formatting</Filter>
+ </ClInclude>
<ClInclude Include="dt_impl.h">
<Filter>formatting</Filter>
</ClInclude>
@@ -1173,12 +1269,6 @@
<CustomBuild Include="unicode\msgfmt.h">
<Filter>formatting</Filter>
</CustomBuild>
- <CustomBuild Include="unicode/nounit.h">
- <Filter>formatting</Filter>
- </CustomBuild>
- <CustomBuild Include="/numberformatter.h">
- <Filter>formatting</Filter>
- </CustomBuild>
<CustomBuild Include="unicode\numfmt.h">
<Filter>formatting</Filter>
</CustomBuild>
@@ -1317,5 +1407,11 @@
<CustomBuild Include="unicode\uformattable.h">
<Filter>formatting</Filter>
</CustomBuild>
+ <CustomBuild Include="unicode\nounit.h">
+ <Filter>misc</Filter>
+ </CustomBuild>
+ <CustomBuild Include="unicode\numberformatter.h">
+ <Filter>formatting</Filter>
+ </CustomBuild>
</ItemGroup>
-</Project>
+</Project> \ No newline at end of file
diff --git a/Build/source/libs/icu/icu-src/source/i18n/i18n_uwp.vcxproj b/Build/source/libs/icu/icu-src/source/i18n/i18n_uwp.vcxproj
index 7090c833d0c..21d5032132b 100644
--- a/Build/source/libs/icu/icu-src/source/i18n/i18n_uwp.vcxproj
+++ b/Build/source/libs/icu/icu-src/source/i18n/i18n_uwp.vcxproj
@@ -1,5 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <!-- The following import will include the 'default' configuration options for VS UWP projects. -->
+ <Import Project="..\allinone\Build.Windows.UWP.ProjectConfiguration.props" />
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
@@ -30,19 +32,12 @@
<ProjectGuid>{6786C051-383B-47E0-9E82-B8B994E06A25}</ProjectGuid>
<Keyword>DynamicLibrary</Keyword>
<DefaultLanguage>en-US</DefaultLanguage>
- <MinimumVisualStudioVersion>14.0</MinimumVisualStudioVersion>
- <AppContainerApplication>true</AppContainerApplication>
- <ApplicationType>Windows Store</ApplicationType>
- <WindowsTargetPlatformVersion>10.0.10586.0</WindowsTargetPlatformVersion>
- <WindowsTargetPlatformMinVersion>10.0.10240.0</WindowsTargetPlatformMinVersion>
- <ApplicationTypeRevision>10.0</ApplicationTypeRevision>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseOfMfc>false</UseOfMfc>
<CharacterSet>MultiByte</CharacterSet>
- <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
@@ -71,7 +66,6 @@
</PropertyGroup>
<ItemDefinitionGroup>
<Midl>
- <PreprocessorDefinitions>U_PLATFORM_HAS_WINUWP_API=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MkTypLibCompatible>true</MkTypLibCompatible>
<SuppressStartupBanner>true</SuppressStartupBanner>
</Midl>
@@ -79,7 +73,7 @@
<AdditionalIncludeDirectories>..\..\include;..\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<!-- U_DISABLE_RENAMING -->
<!-- U_HIDE_DRAFT_API & U_HIDE_DEPRECATED_API -->
- <PreprocessorDefinitions>U_PLATFORM_HAS_WINUWP_API=1;U_ATTRIBUTE_DEPRECATED=;_CRT_SECURE_NO_DEPRECATE;U_I18N_IMPLEMENTATION;U_PLATFORM_USES_ONLY_WIN32_API=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>U_ATTRIBUTE_DEPRECATED=;_CRT_SECURE_NO_DEPRECATE;U_I18N_IMPLEMENTATION;U_PLATFORM_USES_ONLY_WIN32_API=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<ExceptionHandling>
</ExceptionHandling>
@@ -93,8 +87,7 @@
<CompileAsWinRT>false</CompileAsWinRT>
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
- <ResourceCompile>
- <PreprocessorDefinitions>U_PLATFORM_HAS_WINUWP_API=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <ResourceCompile>
<Culture>0x0409</Culture>
<AdditionalIncludeDirectories>../common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ResourceCompile>
@@ -182,7 +175,7 @@
<ProgramDataBaseFileName>.\x86\ReleaseUWP/</ProgramDataBaseFileName>
</ClCompile>
<Link>
- <OutputFile>..\..\bin32uwp\icuin60.dll</OutputFile>
+ <OutputFile>..\..\bin32uwp\icuin61.dll</OutputFile>
<ProgramDatabaseFile>.\..\..\lib32uwp\icuin.pdb</ProgramDatabaseFile>
<ImportLibrary>..\..\lib32uwp\icuin.lib</ImportLibrary>
<AdditionalDependencies>..\..\lib32uwp\icuuc.lib;%(AdditionalDependencies)</AdditionalDependencies>
@@ -199,7 +192,7 @@
<ProgramDataBaseFileName>.\x86\DebugUWP/</ProgramDataBaseFileName>
</ClCompile>
<Link>
- <OutputFile>..\..\bin32uwp\icuin60d.dll</OutputFile>
+ <OutputFile>..\..\bin32uwp\icuin61d.dll</OutputFile>
<ProgramDatabaseFile>.\..\..\lib32uwp\icuind.pdb</ProgramDatabaseFile>
<ImportLibrary>..\..\lib32uwp\icuind.lib</ImportLibrary>
<AdditionalDependencies>..\..\lib32uwp\icuucd.lib;%(AdditionalDependencies)</AdditionalDependencies>
@@ -216,7 +209,7 @@
<ProgramDataBaseFileName>.\x64\ReleaseUWP/</ProgramDataBaseFileName>
</ClCompile>
<Link>
- <OutputFile>..\..\bin64uwp\icuin60.dll</OutputFile>
+ <OutputFile>..\..\bin64uwp\icuin61.dll</OutputFile>
<ProgramDatabaseFile>.\..\..\lib64uwp\icuin.pdb</ProgramDatabaseFile>
<ImportLibrary>..\..\lib64uwp\icuin.lib</ImportLibrary>
<AdditionalDependencies>..\..\lib64uwp\icuuc.lib;%(AdditionalDependencies)</AdditionalDependencies>
@@ -233,7 +226,7 @@
<ProgramDataBaseFileName>.\x64\DebugUWP/</ProgramDataBaseFileName>
</ClCompile>
<Link>
- <OutputFile>..\..\bin64uwp\icuin60d.dll</OutputFile>
+ <OutputFile>..\..\bin64uwp\icuin61d.dll</OutputFile>
<ProgramDatabaseFile>.\..\..\lib64uwp\icuind.pdb</ProgramDatabaseFile>
<ImportLibrary>..\..\lib64uwp\icuind.lib</ImportLibrary>
<AdditionalDependencies>..\..\lib64uwp\icuucd.lib;%(AdditionalDependencies)</AdditionalDependencies>
@@ -250,7 +243,7 @@
<ProgramDataBaseFileName>.\ARM\ReleaseUWP/</ProgramDataBaseFileName>
</ClCompile>
<Link>
- <OutputFile>..\..\binARMuwp\icuin60.dll</OutputFile>
+ <OutputFile>..\..\binARMuwp\icuin61.dll</OutputFile>
<ProgramDatabaseFile>.\..\..\libARMuwp\icuin.pdb</ProgramDatabaseFile>
<ImportLibrary>..\..\libARMuwp\icuin.lib</ImportLibrary>
<AdditionalDependencies>..\..\libARMuwp\icuuc.lib;%(AdditionalDependencies)</AdditionalDependencies>
@@ -267,7 +260,7 @@
<ProgramDataBaseFileName>.\ARM\DebugUWP/</ProgramDataBaseFileName>
</ClCompile>
<Link>
- <OutputFile>..\..\binARMuwp\icuin60d.dll</OutputFile>
+ <OutputFile>..\..\binARMuwp\icuin61d.dll</OutputFile>
<ProgramDatabaseFile>.\..\..\libARMuwp\icuind.pdb</ProgramDatabaseFile>
<ImportLibrary>..\..\libARMuwp\icuind.lib</ImportLibrary>
<AdditionalDependencies>..\..\libARMuwp\icuucd.lib;%(AdditionalDependencies)</AdditionalDependencies>
@@ -348,6 +341,12 @@
<ClCompile Include="decimfmt.cpp" />
<ClCompile Include="decNumber.cpp" />
<ClCompile Include="digitlst.cpp" />
+ <ClCompile Include="double-conversion-bignum-dtoa.cpp" />
+ <ClCompile Include="double-conversion-bignum.cpp" />
+ <ClCompile Include="double-conversion-cached-powers.cpp" />
+ <ClCompile Include="double-conversion-diy-fp.cpp" />
+ <ClCompile Include="double-conversion-fast-dtoa.cpp" />
+ <ClCompile Include="double-conversion.cpp" />
<ClCompile Include="dtfmtsym.cpp" />
<ClCompile Include="dtitvfmt.cpp" />
<ClCompile Include="dtitvinf.cpp" />
@@ -490,47 +489,7 @@
<ClCompile Include="uspoof_impl.cpp" />
</ItemGroup>
<ItemGroup>
- <CustomBuild Include="unicode\alphaindex.h">
- <Command>copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs>..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
<ClInclude Include="bocsu.h" />
- <CustomBuild Include="unicode\coleitr.h">
- <Command>copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs>..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\coll.h">
- <Command>copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs>..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\search.h">
- <Command>copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs>..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\sortkey.h">
- <Command>copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs>..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\stsearch.h">
- <Command>copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs>..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\tblcoll.h">
- <Command>copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs>..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\ucol.h">
- <Command>copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs>..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
<ClInclude Include="affixpatternparser.h" />
<ClInclude Include="decimalformatpatternimpl.h" />
<ClInclude Include="decimfmtimpl.h" />
@@ -572,221 +531,46 @@
<ClInclude Include="tzgnames.h" />
<ClInclude Include="tznames_impl.h" />
<ClInclude Include="ucol_imp.h" />
- <CustomBuild Include="unicode\ucoleitr.h">
- <Command>copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs>..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\usearch.h">
- <Command>copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs>..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\tzfmt.h">
- <Command>copy "%(FullPath)" ..\..\include\unicode</Command>
- <Outputs>..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\tznames.h">
- <Command>copy "%(FullPath)" ..\..\include\unicode</Command>
- <Outputs>..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
<ClInclude Include="uitercollationiterator.h" />
- <CustomBuild Include="unicode\region.h">
- <Command>copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs>..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\uregion.h">
- <Command>copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs>..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
<ClInclude Include="usrchimp.h" />
<ClInclude Include="astro.h" />
- <CustomBuild Include="unicode\basictz.h">
- <Command>copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs>..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
<ClInclude Include="buddhcal.h" />
- <CustomBuild Include="unicode\calendar.h">
- <Command>copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs>..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
<ClInclude Include="cecal.h" />
<ClInclude Include="chnsecal.h" />
- <CustomBuild Include="unicode\choicfmt.h">
- <Command>copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs>..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\compactdecimalformat.h">
- <Command>copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs>..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
<ClInclude Include="coptccal.h" />
- <CustomBuild Include="unicode\curramt.h">
- <Command>copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs>..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
<ClInclude Include="currfmt.h" />
- <CustomBuild Include="unicode\currpinf.h">
- <Command>copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs>..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\currunit.h">
- <Command>copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs>..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
<ClInclude Include="dangical.h" />
- <CustomBuild Include="unicode\datefmt.h">
- <Command>copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs>..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\dcfmtsym.h">
- <Command>copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs>..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
<ClInclude Include="decContext.h" />
<ClInclude Include="decfmtst.h" />
<ClInclude Include="decimalformatpattern.h" />
- <CustomBuild Include="unicode\decimfmt.h">
- <Command>copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs>..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
<ClInclude Include="decNumber.h" />
<ClInclude Include="decNumberLocal.h" />
<ClInclude Include="digitlst.h" />
+ <ClInclude Include="double-conversion-bignum-dtoa.h" />
+ <ClInclude Include="double-conversion-bignum.h" />
+ <ClInclude Include="double-conversion-cached-powers.h" />
+ <ClInclude Include="double-conversion-diy-fp.h" />
+ <ClInclude Include="double-conversion-fast-dtoa.h" />
+ <ClInclude Include="double-conversion-ieee.h" />
+ <ClInclude Include="double-conversion-utils.h" />
+ <ClInclude Include="double-conversion.h" />
<ClInclude Include="dt_impl.h" />
- <CustomBuild Include="unicode\dtfmtsym.h">
- <Command>copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs>..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
<ClInclude Include="dtitv_impl.h" />
- <CustomBuild Include="unicode\dtitvfmt.h">
- <Command>copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs>..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\dtitvinf.h">
- <Command>copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs>..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\dtptngen.h">
- <Command>copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs>..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
<ClInclude Include="dtptngen_impl.h" />
- <CustomBuild Include="unicode\dtrule.h">
- <Command>copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs>..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
<ClInclude Include="ethpccal.h" />
- <CustomBuild Include="unicode\fieldpos.h">
- <Command>copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs>..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\fmtable.h">
- <Command>copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs>..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\uformattable.h">
- <Command>copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs>..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\format.h">
- <Command>copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs>..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
<ClInclude Include="fphdlimp.h" />
- <CustomBuild Include="unicode\fpositer.h">
- <Command>copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs>..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\gender.h">
- <Command>copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs>..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\ugender.h">
- <Command>copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs>..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\gregocal.h">
- <Command>copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs>..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
<ClInclude Include="gregoimp.h" />
<ClInclude Include="hebrwcal.h" />
<ClInclude Include="indiancal.h" />
<ClInclude Include="islamcal.h" />
<ClInclude Include="japancal.h" />
- <CustomBuild Include="unicode\measfmt.h">
- <Command>copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs>..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\measunit.h">
- <Command>copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs>..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\measure.h">
- <Command>copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs>..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\msgfmt.h">
- <Command>copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs>..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
<ClInclude Include="msgfmt_impl.h" />
<ClInclude Include="nfrlist.h" />
<ClInclude Include="nfrs.h" />
<ClInclude Include="nfrule.h" />
<ClInclude Include="nfsubs.h" />
- <CustomBuild Include="unicode\numfmt.h">
- <Command>copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs>..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\numsys.h">
- <Command>copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs>..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
<ClInclude Include="olsontz.h" />
<ClInclude Include="persncal.h" />
- <CustomBuild Include="unicode\plurfmt.h">
- <Command>copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs>..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\plurrule.h">
- <Command>copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs>..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
<ClInclude Include="plurrule_impl.h" />
<ClInclude Include="quantityformatter.h" />
<ClInclude Include="sharedbreakiterator.h" />
@@ -794,141 +578,11 @@
<ClInclude Include="shareddateformatsymbols.h" />
<ClInclude Include="sharednumberformat.h" />
<ClInclude Include="sharedpluralrules.h" />
- <CustomBuild Include="unicode\rbnf.h">
- <Command>copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs>..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\rbtz.h">
- <Command>copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs>..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\reldatefmt.h">
- <Command>copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs>..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
<ClInclude Include="reldtfmt.h" />
- <CustomBuild Include="unicode\scientificnumberformatter.h">
- <Command>copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs>..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\selfmt.h">
- <Command>copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs>..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\simpletz.h">
- <Command>copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs>..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\smpdtfmt.h">
- <Command>copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs>..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
<ClInclude Include="smpdtfst.h" />
<ClInclude Include="standardplural.h" />
<ClInclude Include="taiwncal.h" />
- <CustomBuild Include="unicode\timezone.h">
- <Command>copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs>..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\tmunit.h">
- <Command>copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs>..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\tmutamt.h">
- <Command>copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs>..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\tmutfmt.h">
- <Command>copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs>..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\tzrule.h">
- <Command>copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs>..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\tztrans.h">
- <Command>copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs>..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\ucal.h">
- <Command>copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs>..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\udat.h">
- <Command>copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs>..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\udateintervalformat.h">
- <Command>copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs>..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\udatpg.h">
- <Command>copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs>..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\ufieldpositer.h">
- <Command>copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs>..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\ulocdata.h">
- <Command>copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs>..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\umsg.h">
- <Command>copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs>..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
<ClInclude Include="umsg_imp.h" />
- <CustomBuild Include="unicode\unum.h">
- <Command>copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs>..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\unumsys.h">
- <Command>copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs>..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\upluralrules.h">
- <Command>copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs>..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\ureldatefmt.h">
- <Command>copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs>..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\utmscale.h">
- <Command>copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs>..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\vtzone.h">
- <Command>copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs>..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
<ClInclude Include="utf16collationiterator.h" />
<ClInclude Include="utf8collationiterator.h" />
<ClInclude Include="vzone.h" />
@@ -939,21 +593,11 @@
<ClInclude Include="zrule.h" />
<ClInclude Include="ztrans.h" />
<ClInclude Include="ucln_in.h" />
- <CustomBuild Include="unicode\regex.h">
- <Command>copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs>..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
<ClInclude Include="regexcmp.h" />
<ClInclude Include="regexcst.h" />
<ClInclude Include="regeximp.h" />
<ClInclude Include="regexst.h" />
<ClInclude Include="regextxt.h" />
- <CustomBuild Include="unicode\uregex.h">
- <Command>copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs>..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
<ClInclude Include="anytrans.h" />
<ClInclude Include="brktrans.h" />
<ClInclude Include="casetrn.h" />
@@ -975,25 +619,10 @@
<ClInclude Include="titletrn.h" />
<ClInclude Include="tolowtrn.h" />
<ClInclude Include="toupptrn.h" />
- <CustomBuild Include="unicode\translit.h">
- <Command>copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs>..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
<ClInclude Include="transreg.h" />
<ClInclude Include="tridpars.h" />
<ClInclude Include="unesctrn.h" />
<ClInclude Include="uni2name.h" />
- <CustomBuild Include="unicode\unirepl.h">
- <Command>copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs>..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\utrans.h">
- <Command>copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs>..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
<ClInclude Include="csdetect.h" />
<ClInclude Include="csmatch.h" />
<ClInclude Include="csr2022.h" />
@@ -1003,16 +632,6 @@
<ClInclude Include="csrucode.h" />
<ClInclude Include="csrutf8.h" />
<ClInclude Include="inputext.h" />
- <CustomBuild Include="unicode\ucsdet.h">
- <Command>copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs>..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\uspoof.h">
- <Command>copy "%(FullPath)" ..\..\include\unicode
-</Command>
- <Outputs>..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
<ClInclude Include="scriptset.h" />
<ClInclude Include="uspoof_conf.h" />
<ClInclude Include="uspoof_impl.h" />
@@ -1030,24 +649,10 @@
<ClInclude Include="number_stringbuilder.h" />
<ClInclude Include="number_types.h" />
<ClInclude Include="number_utils.h" />
- <CustomBuild Include="unicode\nounit.h">
- <Command>copy "%(FullPath)" ..\..\include\unicode </Command>
- <Outputs>..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
- <CustomBuild Include="unicode\numberformatter.h">
- <Command>copy "%(FullPath)" ..\..\include\unicode </Command>
- <Outputs>..\..\include\unicode\%(Filename)%(Extension);%(Outputs)</Outputs>
- </CustomBuild>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="i18n.rc" />
</ItemGroup>
- <ItemGroup>
- <ProjectReference Include="..\common\common_uwp.vcxproj">
- <Project>{C10CF34B-3F79-430E-AD38-5A32DC0589C2}</Project>
- <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
- </ProjectReference>
- </ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
diff --git a/Build/source/libs/icu/icu-src/source/i18n/islamcal.cpp b/Build/source/libs/icu/icu-src/source/i18n/islamcal.cpp
index 4fd0e07d920..b84bedfa091 100644
--- a/Build/source/libs/icu/icu-src/source/i18n/islamcal.cpp
+++ b/Build/source/libs/icu/icu-src/source/i18n/islamcal.cpp
@@ -614,7 +614,7 @@ void IslamicCalendar::handleComputeFields(int32_t julianDay, UErrorCode &status)
days = julianDay - ASTRONOMICAL_EPOC;
}
// Use the civil calendar approximation, which is just arithmetic
- year = (int)ClockMath::floorDivide( (double)(30 * days + 10646) , 10631.0 );
+ year = (int32_t)ClockMath::floorDivide(30 * (int64_t)days + 10646, (int64_t)10631);
month = (int32_t)uprv_ceil((days - 29 - yearStart(year)) / 29.5 );
month = month<11?month:11;
startDate = monthStart(year, month);
diff --git a/Build/source/libs/icu/icu-src/source/i18n/measfmt.cpp b/Build/source/libs/icu/icu-src/source/i18n/measfmt.cpp
index 2ef53295458..5970262de1a 100644
--- a/Build/source/libs/icu/icu-src/source/i18n/measfmt.cpp
+++ b/Build/source/libs/icu/icu-src/source/i18n/measfmt.cpp
@@ -764,10 +764,11 @@ UnicodeString &MeasureFormat::formatMeasurePerUnit(
if (U_FAILURE(status)) {
return appendTo;
}
- MeasureUnit *resolvedUnit =
- MeasureUnit::resolveUnitPerUnit(measure.getUnit(), perUnit);
- if (resolvedUnit != NULL) {
- Measure newMeasure(measure.getNumber(), resolvedUnit, status);
+ bool isResolved = false;
+ MeasureUnit resolvedUnit =
+ MeasureUnit::resolveUnitPerUnit(measure.getUnit(), perUnit, &isResolved);
+ if (isResolved) {
+ Measure newMeasure(measure.getNumber(), new MeasureUnit(resolvedUnit), status);
return formatMeasure(
newMeasure, **numberFormat, appendTo, pos, status);
}
@@ -1061,9 +1062,13 @@ UnicodeString &MeasureFormat::formatNumeric(
}
// Format time. draft becomes something like '5:30:45'
+ // #13606: DateFormat is not thread-safe, but MeasureFormat advertises itself as thread-safe.
FieldPosition smallestFieldPosition(smallestField);
UnicodeString draft;
+ static UMutex dateFmtMutex = U_MUTEX_INITIALIZER;
+ umtx_lock(&dateFmtMutex);
dateFmt.format(date, draft, smallestFieldPosition, status);
+ umtx_unlock(&dateFmtMutex);
// If we find field for smallest amount replace it with the formatted
// smallest amount from above taking care to replace the integer part
diff --git a/Build/source/libs/icu/icu-src/source/i18n/measunit.cpp b/Build/source/libs/icu/icu-src/source/i18n/measunit.cpp
index e9e141789ea..43221345424 100644
--- a/Build/source/libs/icu/icu-src/source/i18n/measunit.cpp
+++ b/Build/source/libs/icu/icu-src/source/i18n/measunit.cpp
@@ -1211,8 +1211,8 @@ int32_t MeasureUnit::internalGetIndexForTypeAndSubtype(const char *type, const c
return gIndexes[t] + st - gOffsets[t];
}
-MeasureUnit *MeasureUnit::resolveUnitPerUnit(
- const MeasureUnit &unit, const MeasureUnit &perUnit) {
+MeasureUnit MeasureUnit::resolveUnitPerUnit(
+ const MeasureUnit &unit, const MeasureUnit &perUnit, bool* isResolved) {
int32_t unitOffset = unit.getOffset();
int32_t perUnitOffset = perUnit.getOffset();
@@ -1233,10 +1233,13 @@ MeasureUnit *MeasureUnit::resolveUnitPerUnit(
} else {
// We found a resolution for our unit / per-unit combo
// return it.
- return new MeasureUnit(midRow[2], midRow[3]);
+ *isResolved = true;
+ return MeasureUnit(midRow[2], midRow[3]);
}
}
- return NULL;
+
+ *isResolved = false;
+ return MeasureUnit();
}
MeasureUnit *MeasureUnit::create(int typeId, int subTypeId, UErrorCode &status) {
diff --git a/Build/source/libs/icu/icu-src/source/i18n/nfrs.cpp b/Build/source/libs/icu/icu-src/source/i18n/nfrs.cpp
index 769fad353fb..e7b17b46c3a 100644
--- a/Build/source/libs/icu/icu-src/source/i18n/nfrs.cpp
+++ b/Build/source/libs/icu/icu-src/source/i18n/nfrs.cpp
@@ -681,7 +681,7 @@ static void dumpUS(FILE* f, const UnicodeString& us) {
#endif
UBool
-NFRuleSet::parse(const UnicodeString& text, ParsePosition& pos, double upperBound, Formattable& result) const
+NFRuleSet::parse(const UnicodeString& text, ParsePosition& pos, double upperBound, uint32_t nonNumericalExecutedRuleMask, Formattable& result) const
{
// try matching each rule in the rule set against the text being
// parsed. Whichever one matches the most characters is the one
@@ -707,9 +707,12 @@ NFRuleSet::parse(const UnicodeString& text, ParsePosition& pos, double upperBoun
#endif
// Try each of the negative rules, fraction rules, infinity rules and NaN rules
for (int i = 0; i < NON_NUMERICAL_RULE_LENGTH; i++) {
- if (nonNumericalRules[i]) {
+ if (nonNumericalRules[i] && ((nonNumericalExecutedRuleMask >> i) & 1) == 0) {
+ // Mark this rule as being executed so that we don't try to execute it again.
+ nonNumericalExecutedRuleMask |= 1 << i;
+
Formattable tempResult;
- UBool success = nonNumericalRules[i]->doParse(text, workingPos, 0, upperBound, tempResult);
+ UBool success = nonNumericalRules[i]->doParse(text, workingPos, 0, upperBound, nonNumericalExecutedRuleMask, tempResult);
if (success && (workingPos.getIndex() > highWaterMark.getIndex())) {
result = tempResult;
highWaterMark = workingPos;
@@ -748,7 +751,7 @@ NFRuleSet::parse(const UnicodeString& text, ParsePosition& pos, double upperBoun
continue;
}
Formattable tempResult;
- UBool success = rules[i]->doParse(text, workingPos, fIsFractionRuleSet, upperBound, tempResult);
+ UBool success = rules[i]->doParse(text, workingPos, fIsFractionRuleSet, upperBound, nonNumericalExecutedRuleMask, tempResult);
if (success && workingPos.getIndex() > highWaterMark.getIndex()) {
result = tempResult;
highWaterMark = workingPos;
diff --git a/Build/source/libs/icu/icu-src/source/i18n/nfrs.h b/Build/source/libs/icu/icu-src/source/i18n/nfrs.h
index 1e39b289b4d..db03c9039de 100644
--- a/Build/source/libs/icu/icu-src/source/i18n/nfrs.h
+++ b/Build/source/libs/icu/icu-src/source/i18n/nfrs.h
@@ -55,7 +55,7 @@ public:
void format(int64_t number, UnicodeString& toAppendTo, int32_t pos, int32_t recursionCount, UErrorCode& status) const;
void format(double number, UnicodeString& toAppendTo, int32_t pos, int32_t recursionCount, UErrorCode& status) const;
- UBool parse(const UnicodeString& text, ParsePosition& pos, double upperBound, Formattable& result) const;
+ UBool parse(const UnicodeString& text, ParsePosition& pos, double upperBound, uint32_t nonNumericalExecutedRuleMask, Formattable& result) const;
void appendRules(UnicodeString& result) const; // toString
diff --git a/Build/source/libs/icu/icu-src/source/i18n/nfrule.cpp b/Build/source/libs/icu/icu-src/source/i18n/nfrule.cpp
index f24be11bcdc..c75ecf06705 100644
--- a/Build/source/libs/icu/icu-src/source/i18n/nfrule.cpp
+++ b/Build/source/libs/icu/icu-src/source/i18n/nfrule.cpp
@@ -900,6 +900,7 @@ NFRule::doParse(const UnicodeString& text,
ParsePosition& parsePosition,
UBool isFractionRule,
double upperBound,
+ uint32_t nonNumericalExecutedRuleMask,
Formattable& resVal) const
{
// internally we operate on a copy of the string being parsed
@@ -1002,6 +1003,7 @@ NFRule::doParse(const UnicodeString& text,
temp.setTo(ruleText, sub1Pos, sub2Pos - sub1Pos);
double partialResult = matchToDelimiter(workText, start, tempBaseValue,
temp, pp, sub1,
+ nonNumericalExecutedRuleMask,
upperBound);
// if we got a successful match (or were trying to match a
@@ -1022,6 +1024,7 @@ NFRule::doParse(const UnicodeString& text,
temp.setTo(ruleText, sub2Pos, ruleText.length() - sub2Pos);
partialResult = matchToDelimiter(workText2, 0, partialResult,
temp, pp2, sub2,
+ nonNumericalExecutedRuleMask,
upperBound);
// if we got a successful match on this second
@@ -1158,6 +1161,7 @@ NFRule::matchToDelimiter(const UnicodeString& text,
const UnicodeString& delimiter,
ParsePosition& pp,
const NFSubstitution* sub,
+ uint32_t nonNumericalExecutedRuleMask,
double upperBound) const
{
UErrorCode status = U_ZERO_ERROR;
@@ -1191,6 +1195,7 @@ NFRule::matchToDelimiter(const UnicodeString& text,
#else
formatter->isLenient(),
#endif
+ nonNumericalExecutedRuleMask,
result);
// if the substitution could match all the text up to
@@ -1244,6 +1249,7 @@ NFRule::matchToDelimiter(const UnicodeString& text,
#else
formatter->isLenient(),
#endif
+ nonNumericalExecutedRuleMask,
result);
if (success && (tempPP.getIndex() != 0)) {
// if there's a successful match (or it's a null
diff --git a/Build/source/libs/icu/icu-src/source/i18n/nfrule.h b/Build/source/libs/icu/icu-src/source/i18n/nfrule.h
index 809119ca6c6..698b75bb637 100644
--- a/Build/source/libs/icu/icu-src/source/i18n/nfrule.h
+++ b/Build/source/libs/icu/icu-src/source/i18n/nfrule.h
@@ -74,6 +74,7 @@ public:
ParsePosition& pos,
UBool isFractional,
double upperBound,
+ uint32_t nonNumericalExecutedRuleMask,
Formattable& result) const;
UBool shouldRollBack(int64_t number) const;
@@ -94,6 +95,7 @@ private:
int32_t indexOfAnyRulePrefix() const;
double matchToDelimiter(const UnicodeString& text, int32_t startPos, double baseValue,
const UnicodeString& delimiter, ParsePosition& pp, const NFSubstitution* sub,
+ uint32_t nonNumericalExecutedRuleMask,
double upperBound) const;
void stripPrefix(UnicodeString& text, const UnicodeString& prefix, ParsePosition& pp) const;
diff --git a/Build/source/libs/icu/icu-src/source/i18n/nfsubs.cpp b/Build/source/libs/icu/icu-src/source/i18n/nfsubs.cpp
index b5da9821d55..4c17aa28186 100644
--- a/Build/source/libs/icu/icu-src/source/i18n/nfsubs.cpp
+++ b/Build/source/libs/icu/icu-src/source/i18n/nfsubs.cpp
@@ -155,6 +155,7 @@ public:
double baseValue,
double upperBound,
UBool lenientParse,
+ uint32_t nonNumericalExecutedRuleMask,
Formattable& result) const;
virtual double composeRuleValue(double newRuleValue, double oldRuleValue) const {
@@ -221,6 +222,7 @@ public:
double baseValue,
double upperBound,
UBool lenientParse,
+ uint32_t nonNumericalExecutedRuleMask,
Formattable& result) const;
virtual double composeRuleValue(double newRuleValue, double oldRuleValue) const { return newRuleValue + oldRuleValue; }
@@ -292,6 +294,7 @@ public:
double baseValue,
double upperBound,
UBool /*lenientParse*/,
+ uint32_t nonNumericalExecutedRuleMask,
Formattable& result) const;
virtual double composeRuleValue(double newRuleValue, double oldRuleValue) const { return newRuleValue / oldRuleValue; }
@@ -689,6 +692,7 @@ NFSubstitution::doParse(const UnicodeString& text,
double baseValue,
double upperBound,
UBool lenientParse,
+ uint32_t nonNumericalExecutedRuleMask,
Formattable& result) const
{
#ifdef RBNF_DEBUG
@@ -709,7 +713,7 @@ NFSubstitution::doParse(const UnicodeString& text,
// on), then also try parsing the text using a default-
// constructed NumberFormat
if (ruleSet != NULL) {
- ruleSet->parse(text, parsePosition, upperBound, result);
+ ruleSet->parse(text, parsePosition, upperBound, nonNumericalExecutedRuleMask, result);
if (lenientParse && !ruleSet->isFractionRuleSet() && parsePosition.getIndex() == 0) {
UErrorCode status = U_ZERO_ERROR;
NumberFormat* fmt = NumberFormat::createInstance(status);
@@ -931,18 +935,19 @@ ModulusSubstitution::doParse(const UnicodeString& text,
double baseValue,
double upperBound,
UBool lenientParse,
+ uint32_t nonNumericalExecutedRuleMask,
Formattable& result) const
{
// if this isn't a >>> substitution, we can just use the
// inherited parse() routine to do the parsing
if (ruleToUse == NULL) {
- return NFSubstitution::doParse(text, parsePosition, baseValue, upperBound, lenientParse, result);
+ return NFSubstitution::doParse(text, parsePosition, baseValue, upperBound, lenientParse, nonNumericalExecutedRuleMask, result);
// but if it IS a >>> substitution, we have to do it here: we
// use the specific rule's doParse() method, and then we have to
// do some of the other work of NFRuleSet.parse()
} else {
- ruleToUse->doParse(text, parsePosition, FALSE, upperBound, result);
+ ruleToUse->doParse(text, parsePosition, FALSE, upperBound, nonNumericalExecutedRuleMask, result);
if (parsePosition.getIndex() != 0) {
UErrorCode status = U_ZERO_ERROR;
@@ -1118,12 +1123,13 @@ FractionalPartSubstitution::doParse(const UnicodeString& text,
double baseValue,
double /*upperBound*/,
UBool lenientParse,
+ uint32_t nonNumericalExecutedRuleMask,
Formattable& resVal) const
{
// if we're not in byDigits mode, we can just use the inherited
// doParse()
if (!byDigits) {
- return NFSubstitution::doParse(text, parsePosition, baseValue, 0, lenientParse, resVal);
+ return NFSubstitution::doParse(text, parsePosition, baseValue, 0, lenientParse, nonNumericalExecutedRuleMask, resVal);
// if we ARE in byDigits mode, parse the text one digit at a time
// using this substitution's owning rule set (we do this by setting
@@ -1141,7 +1147,7 @@ FractionalPartSubstitution::doParse(const UnicodeString& text,
while (workText.length() > 0 && workPos.getIndex() != 0) {
workPos.setIndex(0);
Formattable temp;
- getRuleSet()->parse(workText, workPos, 10, temp);
+ getRuleSet()->parse(workText, workPos, 10, nonNumericalExecutedRuleMask, temp);
UErrorCode status = U_ZERO_ERROR;
digit = temp.getLong(status);
// digit = temp.getType() == Formattable::kLong ?
@@ -1249,6 +1255,7 @@ NumeratorSubstitution::doParse(const UnicodeString& text,
double baseValue,
double upperBound,
UBool /*lenientParse*/,
+ uint32_t nonNumericalExecutedRuleMask,
Formattable& result) const
{
// we don't have to do anything special to do the parsing here,
@@ -1267,7 +1274,7 @@ NumeratorSubstitution::doParse(const UnicodeString& text,
while (workText.length() > 0 && workPos.getIndex() != 0) {
workPos.setIndex(0);
- getRuleSet()->parse(workText, workPos, 1, temp); // parse zero or nothing at all
+ getRuleSet()->parse(workText, workPos, 1, nonNumericalExecutedRuleMask, temp); // parse zero or nothing at all
if (workPos.getIndex() == 0) {
// we failed, either there were no more zeros, or the number was formatted with digits
// either way, we're done
@@ -1289,7 +1296,7 @@ NumeratorSubstitution::doParse(const UnicodeString& text,
}
// we've parsed off the zeros, now let's parse the rest from our current position
- NFSubstitution::doParse(workText, parsePosition, withZeros ? 1 : baseValue, upperBound, FALSE, result);
+ NFSubstitution::doParse(workText, parsePosition, withZeros ? 1 : baseValue, upperBound, FALSE, nonNumericalExecutedRuleMask, result);
if (withZeros) {
// any base value will do in this case. is there a way to
diff --git a/Build/source/libs/icu/icu-src/source/i18n/nfsubs.h b/Build/source/libs/icu/icu-src/source/i18n/nfsubs.h
index e8b259137ed..948627c0cc9 100644
--- a/Build/source/libs/icu/icu-src/source/i18n/nfsubs.h
+++ b/Build/source/libs/icu/icu-src/source/i18n/nfsubs.h
@@ -191,6 +191,7 @@ public:
double baseValue,
double upperBound,
UBool lenientParse,
+ uint32_t nonNumericalExecutedRuleMask,
Formattable& result) const;
/**
diff --git a/Build/source/libs/icu/icu-src/source/i18n/number_affixutils.cpp b/Build/source/libs/icu/icu-src/source/i18n/number_affixutils.cpp
index 4dfdbc7ab70..df4b267af5a 100644
--- a/Build/source/libs/icu/icu-src/source/i18n/number_affixutils.cpp
+++ b/Build/source/libs/icu/icu-src/source/i18n/number_affixutils.cpp
@@ -70,6 +70,7 @@ int32_t AffixUtils::estimateLength(const CharSequence &patternString, UErrorCode
case STATE_FIRST_QUOTE:
case STATE_INSIDE_QUOTE:
status = U_ILLEGAL_ARGUMENT_ERROR;
+ break;
default:
break;
}
diff --git a/Build/source/libs/icu/icu-src/source/i18n/number_compact.cpp b/Build/source/libs/icu/icu-src/source/i18n/number_compact.cpp
index 8ceee1378b2..cc0d8fd2a20 100644
--- a/Build/source/libs/icu/icu-src/source/i18n/number_compact.cpp
+++ b/Build/source/libs/icu/icu-src/source/i18n/number_compact.cpp
@@ -262,7 +262,6 @@ void CompactHandler::precomputeAllModifiers(MutablePatternModifier &buildReferen
buildReference.setPatternInfo(&patternInfo);
info.mod = buildReference.createImmutable(status);
if (U_FAILURE(status)) { return; }
- info.numDigits = patternInfo.positive.integerTotal;
info.patternString = patternString;
}
}
@@ -286,7 +285,6 @@ void CompactHandler::processQuantity(DecimalQuantity &quantity, MicroProps &micr
StandardPlural::Form plural = quantity.getStandardPlural(rules);
const UChar *patternString = data.getPattern(magnitude, plural);
- int numDigits = -1;
if (patternString == nullptr) {
// Use the default (non-compact) modifier.
// No need to take any action.
@@ -299,7 +297,6 @@ void CompactHandler::processQuantity(DecimalQuantity &quantity, MicroProps &micr
const CompactModInfo &info = precomputedMods[i];
if (u_strcmp(patternString, info.patternString) == 0) {
info.mod->applyToMicros(micros, quantity);
- numDigits = info.numDigits;
break;
}
}
@@ -313,12 +310,8 @@ void CompactHandler::processQuantity(DecimalQuantity &quantity, MicroProps &micr
PatternParser::parseToPatternInfo(UnicodeString(patternString), patternInfo, status);
static_cast<MutablePatternModifier*>(const_cast<Modifier*>(micros.modMiddle))
->setPatternInfo(&patternInfo);
- numDigits = patternInfo.positive.integerTotal;
}
- // FIXME: Deal with numDigits == 0 (Awaiting a test case)
- (void)numDigits;
-
// We already performed rounding. Do not perform it again.
micros.rounding = Rounder::constructPassThrough();
}
diff --git a/Build/source/libs/icu/icu-src/source/i18n/number_compact.h b/Build/source/libs/icu/icu-src/source/i18n/number_compact.h
index 2344abf535a..f7adf36416e 100644
--- a/Build/source/libs/icu/icu-src/source/i18n/number_compact.h
+++ b/Build/source/libs/icu/icu-src/source/i18n/number_compact.h
@@ -52,7 +52,6 @@ class CompactData : public MultiplierProducer {
struct CompactModInfo {
const ImmutablePatternModifier *mod;
const UChar* patternString;
- int32_t numDigits;
};
class CompactHandler : public MicroPropsGenerator, public UMemory {
diff --git a/Build/source/libs/icu/icu-src/source/i18n/number_decimalquantity.cpp b/Build/source/libs/icu/icu-src/source/i18n/number_decimalquantity.cpp
index 72463576666..b68df26ba26 100644
--- a/Build/source/libs/icu/icu-src/source/i18n/number_decimalquantity.cpp
+++ b/Build/source/libs/icu/icu-src/source/i18n/number_decimalquantity.cpp
@@ -14,12 +14,15 @@
#include "decContext.h"
#include "decNumber.h"
#include "number_roundingutils.h"
+#include "double-conversion.h"
#include "unicode/plurrule.h"
using namespace icu;
using namespace icu::number;
using namespace icu::number::impl;
+using icu::double_conversion::DoubleToStringConverter;
+
namespace {
int8_t NEGATIVE_FLAG = 1;
@@ -265,6 +268,10 @@ bool DecimalQuantity::isNegative() const {
return (flags & NEGATIVE_FLAG) != 0;
}
+int8_t DecimalQuantity::signum() const {
+ return isNegative() ? -1 : isZero() ? 0 : 1;
+}
+
bool DecimalQuantity::isInfinite() const {
return (flags & INFINITY_FLAG) != 0;
}
@@ -392,31 +399,27 @@ void DecimalQuantity::_setToDoubleFast(double n) {
}
void DecimalQuantity::convertToAccurateDouble() {
- double n = origDouble;
- U_ASSERT(n != 0);
+ U_ASSERT(origDouble != 0);
int32_t delta = origDelta;
- setBcdToZero();
- // Call the slow oracle function (Double.toString in Java, sprintf in C++).
- // The <float.h> constant DBL_DIG defines a platform-specific number of digits in a double.
- // However, this tends to be too low (see #11318). Instead, we always use 14 decimal places.
- static constexpr size_t CAP = 1 + 14 + 8; // Extra space for '+', '.', e+NNN, and '\0'
- char dstr[CAP];
- snprintf(dstr, CAP, "%+1.14e", n);
-
- // 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(dstr, ',');
- if (decimalSeparator != nullptr) {
- *decimalSeparator = '.';
- }
-
- StringPiece sp(dstr);
- DecNumberWithStorage dn;
- stringToDecNumber(dstr, dn);
- _setToDecNumber(dn.getAlias());
+ // Call the slow oracle function (Double.toString in Java, DoubleToAscii in C++).
+ char buffer[DoubleToStringConverter::kBase10MaximalLength + 1];
+ bool sign; // unused; always positive
+ int32_t length;
+ int32_t point;
+ DoubleToStringConverter::DoubleToAscii(
+ origDouble,
+ DoubleToStringConverter::DtoaMode::SHORTEST,
+ 0,
+ buffer,
+ sizeof(buffer),
+ &sign,
+ &length,
+ &point
+ );
+ setBcdToZero();
+ readDoubleConversionToBcd(buffer, length, point);
scale += delta;
explicitExactDouble = true;
}
@@ -833,6 +836,26 @@ void DecimalQuantity::readDecNumberToBcd(decNumber *dn) {
precision = dn->digits;
}
+void DecimalQuantity::readDoubleConversionToBcd(
+ const char* buffer, int32_t length, int32_t point) {
+ // NOTE: Despite the fact that double-conversion's API is called
+ // "DoubleToAscii", they actually use '0' (as opposed to u8'0').
+ if (length > 16) {
+ ensureCapacity(length);
+ for (int32_t i = 0; i < length; i++) {
+ fBCD.bcdBytes.ptr[i] = buffer[length-i-1] - '0';
+ }
+ } else {
+ uint64_t result = 0L;
+ for (int32_t i = 0; i < length; i++) {
+ result |= static_cast<uint64_t>(buffer[length-i-1] - '0') << (4 * i);
+ }
+ fBCD.bcdLong = result;
+ }
+ scale = point - length;
+ precision = length;
+}
+
void DecimalQuantity::compact() {
if (usingBytes) {
int32_t delta = 0;
diff --git a/Build/source/libs/icu/icu-src/source/i18n/number_decimalquantity.h b/Build/source/libs/icu/icu-src/source/i18n/number_decimalquantity.h
index ccb832623cb..4309c3c6380 100644
--- a/Build/source/libs/icu/icu-src/source/i18n/number_decimalquantity.h
+++ b/Build/source/libs/icu/icu-src/source/i18n/number_decimalquantity.h
@@ -115,6 +115,9 @@ class U_I18N_API DecimalQuantity : public IFixedDecimal, public UMemory {
/** @return Whether the value represented by this {@link DecimalQuantity} is less than zero. */
bool isNegative() const;
+ /** @return -1 if the value is negative; 1 if positive; or 0 if zero. */
+ int8_t signum() const;
+
/** @return Whether the value represented by this {@link DecimalQuantity} is infinite. */
bool isInfinite() const U_OVERRIDE;
@@ -395,6 +398,8 @@ class U_I18N_API DecimalQuantity : public IFixedDecimal, public UMemory {
void readDecNumberToBcd(decNumber *dn);
+ void readDoubleConversionToBcd(const char* buffer, int32_t length, int32_t point);
+
void copyBcdFrom(const DecimalQuantity &other);
/**
diff --git a/Build/source/libs/icu/icu-src/source/i18n/number_decimfmtprops.h b/Build/source/libs/icu/icu-src/source/i18n/number_decimfmtprops.h
index 3e25966b6f5..96356cad453 100644
--- a/Build/source/libs/icu/icu-src/source/i18n/number_decimfmtprops.h
+++ b/Build/source/libs/icu/icu-src/source/i18n/number_decimfmtprops.h
@@ -19,8 +19,8 @@ U_NAMESPACE_BEGIN
// Export an explicit template instantiation of the LocalPointer that is used as a
// data member of CurrencyPluralInfoWrapper.
-// (MSVC requires this, even though it should not be necessary.)
-#if defined (_MSC_VER)
+// (When building DLLs for Windows this is required.)
+#if U_PF_WINDOWS <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN
// Ignore warning 4661 as LocalPointerBase does not use operator== or operator!=
#pragma warning(suppress: 4661)
template class U_I18N_API LocalPointerBase<CurrencyPluralInfo>;
diff --git a/Build/source/libs/icu/icu-src/source/i18n/number_fluent.cpp b/Build/source/libs/icu/icu-src/source/i18n/number_fluent.cpp
index 76c3a7ce5c5..27113106c50 100644
--- a/Build/source/libs/icu/icu-src/source/i18n/number_fluent.cpp
+++ b/Build/source/libs/icu/icu-src/source/i18n/number_fluent.cpp
@@ -33,12 +33,13 @@ Derived NumberFormatterSettings<Derived>::unit(const icu::MeasureUnit &unit) con
}
template<typename Derived>
-Derived NumberFormatterSettings<Derived>::adoptUnit(const icu::MeasureUnit *unit) const {
+Derived NumberFormatterSettings<Derived>::adoptUnit(icu::MeasureUnit *unit) const {
Derived copy(*this);
// Just copy 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;
delete unit;
}
@@ -46,6 +47,26 @@ Derived NumberFormatterSettings<Derived>::adoptUnit(const icu::MeasureUnit *unit
}
template<typename Derived>
+Derived NumberFormatterSettings<Derived>::perUnit(const icu::MeasureUnit &perUnit) const {
+ Derived copy(*this);
+ // See comments above about slicing.
+ copy.fMacros.perUnit = perUnit;
+ return copy;
+}
+
+template<typename Derived>
+Derived NumberFormatterSettings<Derived>::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;
+ delete perUnit;
+ }
+ return copy;
+}
+
+template<typename Derived>
Derived NumberFormatterSettings<Derived>::rounding(const Rounder &rounder) const {
Derived copy(*this);
// NOTE: Slicing is OK.
@@ -54,9 +75,11 @@ Derived NumberFormatterSettings<Derived>::rounding(const Rounder &rounder) const
}
template<typename Derived>
-Derived NumberFormatterSettings<Derived>::grouping(const Grouper &grouper) const {
+Derived NumberFormatterSettings<Derived>::grouping(const UGroupingStrategy &strategy) const {
Derived copy(*this);
- copy.fMacros.grouper = grouper;
+ // NOTE: This is slightly different than how the setting is stored in Java
+ // because we want to put it on the stack.
+ copy.fMacros.grouper = Grouper::forStrategy(strategy);
return copy;
}
@@ -75,7 +98,7 @@ Derived NumberFormatterSettings<Derived>::symbols(const DecimalFormatSymbols &sy
}
template<typename Derived>
-Derived NumberFormatterSettings<Derived>::adoptSymbols(const NumberingSystem *ns) const {
+Derived NumberFormatterSettings<Derived>::adoptSymbols(NumberingSystem *ns) const {
Derived copy(*this);
copy.fMacros.symbols.setTo(ns);
return copy;
diff --git a/Build/source/libs/icu/icu-src/source/i18n/number_formatimpl.cpp b/Build/source/libs/icu/icu-src/source/i18n/number_formatimpl.cpp
index 9986ce6d8c6..bc96cb15dab 100644
--- a/Build/source/libs/icu/icu-src/source/i18n/number_formatimpl.cpp
+++ b/Build/source/libs/icu/icu-src/source/i18n/number_formatimpl.cpp
@@ -17,6 +17,8 @@
#include "unicode/dcfmtsym.h"
#include "number_scientific.h"
#include "number_compact.h"
+#include "uresimp.h"
+#include "ureslocs.h"
using namespace icu;
using namespace icu::number;
@@ -88,6 +90,37 @@ const char16_t *getPatternForStyle(const Locale &locale, const char *nsName, Cld
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) {
+ // TODO: Load this data in a centralized location like ICU4J?
+ // 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;
+ 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
+ ures_getByIndex(bundle.getAlias(), 2, bundle.getAlias(), &localStatus);
+ int32_t dummy;
+ result.exists = true;
+ result.pattern = ures_getStringByIndex(bundle.getAlias(), 0, &dummy, &localStatus);
+ result.decimalSeparator = ures_getStringByIndex(bundle.getAlias(), 1, &dummy, &localStatus);
+ result.groupingSeparator = ures_getStringByIndex(bundle.getAlias(), 2, &dummy, &localStatus);
+ status = localStatus;
+ } else if (localStatus != U_MISSING_RESOURCE_ERROR) {
+ status = localStatus;
+ }
+ return result;
+}
+
inline bool unitIsCurrency(const MeasureUnit &unit) {
return uprv_strcmp("currency", unit.getType()) == 0;
}
@@ -161,8 +194,9 @@ NumberFormatterImpl::macrosToMicroGenerator(const MacroProps &macros, bool safe,
bool isPercent = isNoUnit && unitIsPercent(macros.unit);
bool isPermille = isNoUnit && unitIsPermille(macros.unit);
bool isCldrUnit = !isCurrency && !isNoUnit;
- bool isAccounting =
- macros.sign == UNUM_SIGN_ACCOUNTING || macros.sign == UNUM_SIGN_ACCOUNTING_ALWAYS;
+ bool isAccounting = macros.sign == UNUM_SIGN_ACCOUNTING
+ || macros.sign == UNUM_SIGN_ACCOUNTING_ALWAYS
+ || macros.sign == UNUM_SIGN_ACCOUNTING_EXCEPT_ZERO;
CurrencyUnit currency(kDefaultCurrency, status);
if (isCurrency) {
currency = CurrencyUnit(macros.unit, status); // Restore CurrencyUnit from MeasureUnit
@@ -185,20 +219,51 @@ NumberFormatterImpl::macrosToMicroGenerator(const MacroProps &macros, bool safe,
}
const char *nsName = U_SUCCESS(status) ? ns->getName() : "latn";
- // Load and parse the pattern string. It is used for grouping sizes and affixes only.
- CldrPatternStyle patternStyle;
- if (isPercent || isPermille) {
- patternStyle = CLDR_PATTERN_STYLE_PERCENT;
- } else if (!isCurrency || unitWidth == UNUM_UNIT_WIDTH_FULL_NAME) {
- patternStyle = CLDR_PATTERN_STYLE_DECIMAL;
- } else if (isAccounting) {
- // NOTE: Although ACCOUNTING and ACCOUNTING_ALWAYS are only supported in currencies right now,
- // the API contract allows us to add support to other units in the future.
- patternStyle = CLDR_PATTERN_STYLE_ACCOUNTING;
+ // Resolve the symbols. Do this here because currency may need to customize them.
+ if (macros.symbols.isDecimalFormatSymbols()) {
+ fMicros.symbols = macros.symbols.getDecimalFormatSymbols();
} else {
- patternStyle = CLDR_PATTERN_STYLE_CURRENCY;
+ fMicros.symbols = new DecimalFormatSymbols(macros.locale, *ns, status);
+ // Give ownership to the NumberFormatterImpl.
+ fSymbols.adoptInstead(fMicros.symbols);
+ }
+
+ // Load and parse the pattern string. It is used for grouping sizes and affixes only.
+ // 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);
+ 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);
+ fMicros.symbols = symbols;
+ fSymbols.adoptInstead(symbols);
+ symbols->setSymbol(
+ DecimalFormatSymbols::ENumberFormatSymbol::kMonetarySeparatorSymbol,
+ UnicodeString(info.decimalSeparator),
+ FALSE);
+ symbols->setSymbol(
+ DecimalFormatSymbols::ENumberFormatSymbol::kMonetaryGroupingSeparatorSymbol,
+ UnicodeString(info.groupingSeparator),
+ FALSE);
+ }
+ }
+ if (pattern == nullptr) {
+ CldrPatternStyle patternStyle;
+ if (isPercent || isPermille) {
+ patternStyle = CLDR_PATTERN_STYLE_PERCENT;
+ } else if (!isCurrency || unitWidth == UNUM_UNIT_WIDTH_FULL_NAME) {
+ patternStyle = CLDR_PATTERN_STYLE_DECIMAL;
+ } else if (isAccounting) {
+ // NOTE: Although ACCOUNTING and ACCOUNTING_ALWAYS are only supported in currencies right now,
+ // the API contract allows us to add support to other units in the future.
+ patternStyle = CLDR_PATTERN_STYLE_ACCOUNTING;
+ } else {
+ patternStyle = CLDR_PATTERN_STYLE_CURRENCY;
+ }
+ pattern = getPatternForStyle(macros.locale, nsName, patternStyle, status);
}
- const char16_t *pattern = getPatternForStyle(macros.locale, nsName, patternStyle, status);
auto patternInfo = new ParsedPatternInfo();
fPatternInfo.adoptInstead(patternInfo);
PatternParser::parseToPatternInfo(UnicodeString(pattern), *patternInfo, status);
@@ -207,15 +272,6 @@ NumberFormatterImpl::macrosToMicroGenerator(const MacroProps &macros, bool safe,
/// START POPULATING THE DEFAULT MICROPROPS AND BUILDING THE MICROPROPS GENERATOR ///
/////////////////////////////////////////////////////////////////////////////////////
- // Symbols
- if (macros.symbols.isDecimalFormatSymbols()) {
- fMicros.symbols = macros.symbols.getDecimalFormatSymbols();
- } else {
- fMicros.symbols = new DecimalFormatSymbols(macros.locale, *ns, status);
- // Give ownership to the NumberFormatterImpl.
- fSymbols.adoptInstead(fMicros.symbols);
- }
-
// Rounding strategy
if (!macros.rounder.isBogus()) {
fMicros.rounding = macros.rounder;
@@ -233,11 +289,11 @@ NumberFormatterImpl::macrosToMicroGenerator(const MacroProps &macros, bool safe,
fMicros.grouping = macros.grouper;
} else if (macros.notation.fType == Notation::NTN_COMPACT) {
// Compact notation uses minGrouping by default since ICU 59
- fMicros.grouping = Grouper::minTwoDigits();
+ fMicros.grouping = Grouper::forStrategy(UNUM_GROUPING_MIN2);
} else {
- fMicros.grouping = Grouper::defaults();
+ fMicros.grouping = Grouper::forStrategy(UNUM_GROUPING_AUTO);
}
- fMicros.grouping.setLocaleData(*fPatternInfo);
+ fMicros.grouping.setLocaleData(*fPatternInfo, macros.locale);
// Padding strategy
if (!macros.padder.isBogus()) {
@@ -308,6 +364,7 @@ NumberFormatterImpl::macrosToMicroGenerator(const MacroProps &macros, bool safe,
LongNameHandler::forMeasureUnit(
macros.locale,
macros.unit,
+ macros.perUnit,
unitWidth,
resolvePluralRules(macros.rules, macros.locale, status),
chain,
diff --git a/Build/source/libs/icu/icu-src/source/i18n/number_grouping.cpp b/Build/source/libs/icu/icu-src/source/i18n/number_grouping.cpp
index 15362825cc6..a2b1bbd6b33 100644
--- a/Build/source/libs/icu/icu-src/source/i18n/number_grouping.cpp
+++ b/Build/source/libs/icu/icu-src/source/i18n/number_grouping.cpp
@@ -7,36 +7,70 @@
#include "unicode/numberformatter.h"
#include "number_patternstring.h"
+#include "uresimp.h"
using namespace icu;
using namespace icu::number;
using namespace icu::number::impl;
-Grouper Grouper::defaults() {
- return {-2, -2, false};
+namespace {
+
+int16_t getMinGroupingForLocale(const Locale& locale) {
+ // TODO: Cache this?
+ UErrorCode localStatus = U_ZERO_ERROR;
+ LocalUResourceBundlePointer bundle(ures_open(NULL, locale.getName(), &localStatus));
+ int32_t resultLen = 0;
+ const char16_t* result = ures_getStringByKeyWithFallback(
+ bundle.getAlias(),
+ "NumberElements/minimumGroupingDigits",
+ &resultLen,
+ &localStatus);
+ // TODO: Is it safe to assume resultLen == 1? Would locales set minGrouping >= 10?
+ if (U_FAILURE(localStatus) || resultLen != 1) {
+ return 1;
+ }
+ return result[0] - u'0';
}
-Grouper Grouper::minTwoDigits() {
- return {-2, -2, true};
}
-Grouper Grouper::none() {
- return {-1, -1, false};
+Grouper Grouper::forStrategy(UGroupingStrategy grouping) {
+ switch (grouping) {
+ case UNUM_GROUPING_OFF:
+ return {-1, -1, -2};
+ case UNUM_GROUPING_AUTO:
+ return {-2, -2, -2};
+ case UNUM_GROUPING_MIN2:
+ return {-2, -2, -3};
+ case UNUM_GROUPING_ON_ALIGNED:
+ return {-4, -4, 1};
+ case UNUM_GROUPING_THOUSANDS:
+ return {3, 3, 1};
+ default:
+ U_ASSERT(FALSE);
+ }
}
-void Grouper::setLocaleData(const impl::ParsedPatternInfo &patternInfo) {
- if (fGrouping1 != -2) {
+void Grouper::setLocaleData(const impl::ParsedPatternInfo &patternInfo, const Locale& locale) {
+ if (fGrouping1 != -2 && fGrouping2 != -4) {
return;
}
- auto grouping1 = static_cast<int8_t> (patternInfo.positive.groupingSizes & 0xffff);
- auto grouping2 = static_cast<int8_t> ((patternInfo.positive.groupingSizes >> 16) & 0xffff);
- auto grouping3 = static_cast<int8_t> ((patternInfo.positive.groupingSizes >> 32) & 0xffff);
+ auto grouping1 = static_cast<int16_t> (patternInfo.positive.groupingSizes & 0xffff);
+ auto grouping2 = static_cast<int16_t> ((patternInfo.positive.groupingSizes >> 16) & 0xffff);
+ auto grouping3 = static_cast<int16_t> ((patternInfo.positive.groupingSizes >> 32) & 0xffff);
if (grouping2 == -1) {
- grouping1 = -1;
+ grouping1 = fGrouping1 == -4 ? (short) 3 : (short) -1;
}
if (grouping3 == -1) {
grouping2 = grouping1;
}
+ if (fMinGrouping == -2) {
+ fMinGrouping = getMinGroupingForLocale(locale);
+ } else if (fMinGrouping == -3) {
+ fMinGrouping = uprv_max(2, getMinGroupingForLocale(locale));
+ } else {
+ // leave fMinGrouping alone
+ }
fGrouping1 = grouping1;
fGrouping2 = grouping2;
}
@@ -49,7 +83,7 @@ bool Grouper::groupAtPosition(int32_t position, const impl::DecimalQuantity &val
}
position -= fGrouping1;
return position >= 0 && (position % fGrouping2) == 0
- && value.getUpperDisplayMagnitude() - fGrouping1 + 1 >= (fMin2 ? 2 : 1);
+ && value.getUpperDisplayMagnitude() - fGrouping1 + 1 >= fMinGrouping;
}
#endif /* #if !UCONFIG_NO_FORMATTING */
diff --git a/Build/source/libs/icu/icu-src/source/i18n/number_integerwidth.cpp b/Build/source/libs/icu/icu-src/source/i18n/number_integerwidth.cpp
index 10dacfc4acb..4a612273f5e 100644
--- a/Build/source/libs/icu/icu-src/source/i18n/number_integerwidth.cpp
+++ b/Build/source/libs/icu/icu-src/source/i18n/number_integerwidth.cpp
@@ -13,25 +13,28 @@ using namespace icu;
using namespace icu::number;
using namespace icu::number::impl;
-IntegerWidth::IntegerWidth(int8_t minInt, int8_t maxInt) {
+IntegerWidth::IntegerWidth(digits_t minInt, digits_t maxInt) {
fUnion.minMaxInt.fMinInt = minInt;
fUnion.minMaxInt.fMaxInt = maxInt;
}
IntegerWidth IntegerWidth::zeroFillTo(int32_t minInt) {
if (minInt >= 0 && minInt <= kMaxIntFracSig) {
- return {static_cast<int8_t>(minInt), -1};
+ return {static_cast<digits_t>(minInt), -1};
} else {
- return {U_NUMBER_DIGIT_WIDTH_OUTOFBOUNDS_ERROR};
+ return {U_NUMBER_ARG_OUTOFBOUNDS_ERROR};
}
}
IntegerWidth IntegerWidth::truncateAt(int32_t maxInt) {
if (fHasError) { return *this; } // No-op on error
- if (maxInt >= 0 && maxInt <= kMaxIntFracSig) {
- return {fUnion.minMaxInt.fMinInt, static_cast<int8_t>(maxInt)};
+ digits_t minInt = fUnion.minMaxInt.fMinInt;
+ if (maxInt >= 0 && maxInt <= kMaxIntFracSig && minInt <= maxInt) {
+ return {minInt, static_cast<digits_t>(maxInt)};
+ } else if (maxInt == -1) {
+ return {minInt, -1};
} else {
- return {U_NUMBER_DIGIT_WIDTH_OUTOFBOUNDS_ERROR};
+ return {U_NUMBER_ARG_OUTOFBOUNDS_ERROR};
}
}
diff --git a/Build/source/libs/icu/icu-src/source/i18n/number_longnames.cpp b/Build/source/libs/icu/icu-src/source/i18n/number_longnames.cpp
index 88b3413585a..5c363442e7c 100644
--- a/Build/source/libs/icu/icu-src/source/i18n/number_longnames.cpp
+++ b/Build/source/libs/icu/icu-src/source/i18n/number_longnames.cpp
@@ -5,6 +5,7 @@
#if !UCONFIG_NO_FORMATTING && !UPRV_INCOMPLETE_CPP11_SUPPORT
+#include "unicode/simpleformatter.h"
#include "unicode/ures.h"
#include "ureslocs.h"
#include "charstr.h"
@@ -19,6 +20,37 @@ using namespace icu::number::impl;
namespace {
+constexpr int32_t DNAM_INDEX = StandardPlural::Form::COUNT;
+constexpr int32_t PER_INDEX = StandardPlural::Form::COUNT + 1;
+constexpr int32_t ARRAY_LENGTH = StandardPlural::Form::COUNT + 2;
+
+static int32_t getIndex(const char* pluralKeyword, UErrorCode& status) {
+ // pluralKeyword can also be "dnam" or "per"
+ if (uprv_strcmp(pluralKeyword, "dnam") == 0) {
+ return DNAM_INDEX;
+ } else if (uprv_strcmp(pluralKeyword, "per") == 0) {
+ return PER_INDEX;
+ } else {
+ StandardPlural::Form plural = StandardPlural::fromString(pluralKeyword, status);
+ return plural;
+ }
+}
+
+static UnicodeString getWithPlural(
+ const UnicodeString* strings,
+ int32_t plural,
+ UErrorCode& status) {
+ UnicodeString result = strings[plural];
+ if (result.isBogus()) {
+ result = strings[StandardPlural::Form::OTHER];
+ }
+ if (result.isBogus()) {
+ // There should always be data in the "other" plural variant.
+ status = U_INTERNAL_PROGRAM_ERROR;
+ }
+ return result;
+}
+
//////////////////////////
/// BEGIN DATA LOADING ///
@@ -28,7 +60,7 @@ class PluralTableSink : public ResourceSink {
public:
explicit PluralTableSink(UnicodeString *outArray) : outArray(outArray) {
// Initialize the array to bogus strings.
- for (int32_t i = 0; i < StandardPlural::Form::COUNT; i++) {
+ for (int32_t i = 0; i < ARRAY_LENGTH; i++) {
outArray[i].setToBogus();
}
}
@@ -36,17 +68,13 @@ class PluralTableSink : public ResourceSink {
void put(const char *key, ResourceValue &value, UBool /*noFallback*/, UErrorCode &status) U_OVERRIDE {
ResourceTable pluralsTable = value.getTable(status);
if (U_FAILURE(status)) { return; }
- for (int i = 0; pluralsTable.getKeyAndValue(i, key, value); ++i) {
- // In MeasureUnit data, ignore dnam and per units for now.
- if (uprv_strcmp(key, "dnam") == 0 || uprv_strcmp(key, "per") == 0) {
- continue;
- }
- StandardPlural::Form plural = StandardPlural::fromString(key, status);
+ for (int32_t i = 0; pluralsTable.getKeyAndValue(i, key, value); ++i) {
+ int32_t index = getIndex(key, status);
if (U_FAILURE(status)) { return; }
- if (!outArray[plural].isBogus()) {
+ if (!outArray[index].isBogus()) {
continue;
}
- outArray[plural] = value.getUnicodeString(status);
+ outArray[index] = value.getUnicodeString(status);
if (U_FAILURE(status)) { return; }
}
}
@@ -105,6 +133,22 @@ void getCurrencyLongNameData(const Locale &locale, const CurrencyUnit &currency,
}
}
+UnicodeString getPerUnitFormat(const Locale& locale, const UNumberUnitWidth &width, UErrorCode& status) {
+ LocalUResourceBundlePointer unitsBundle(ures_open(U_ICUDATA_UNIT, locale.getName(), &status));
+ if (U_FAILURE(status)) { return {}; }
+ CharString key;
+ key.append("units", status);
+ if (width == UNUM_UNIT_WIDTH_NARROW) {
+ key.append("Narrow", status);
+ } else if (width == UNUM_UNIT_WIDTH_SHORT) {
+ key.append("Short", status);
+ }
+ key.append("/compound/per", status);
+ int32_t len = 0;
+ const UChar* ptr = ures_getStringByKeyWithFallback(unitsBundle.getAlias(), key.data(), &len, &status);
+ return UnicodeString(ptr, len);
+}
+
////////////////////////
/// END DATA LOADING ///
////////////////////////
@@ -112,11 +156,24 @@ void getCurrencyLongNameData(const Locale &locale, const CurrencyUnit &currency,
} // namespace
LongNameHandler
-LongNameHandler::forMeasureUnit(const Locale &loc, const MeasureUnit &unit, const UNumberUnitWidth &width,
- const PluralRules *rules, const MicroPropsGenerator *parent,
- UErrorCode &status) {
+LongNameHandler::forMeasureUnit(const Locale &loc, const MeasureUnit &unitRef, const MeasureUnit &perUnit,
+ const UNumberUnitWidth &width, const PluralRules *rules,
+ const MicroPropsGenerator *parent, UErrorCode &status) {
+ MeasureUnit unit = unitRef;
+ if (uprv_strcmp(perUnit.getType(), "none") != 0) {
+ // Compound unit: first try to simplify (e.g., meters per second is its own unit).
+ bool isResolved = false;
+ MeasureUnit resolved = MeasureUnit::resolveUnitPerUnit(unit, perUnit, &isResolved);
+ if (isResolved) {
+ unit = resolved;
+ } else {
+ // No simplified form is available.
+ return forCompoundUnit(loc, unit, perUnit, width, rules, parent, status);
+ }
+ }
+
LongNameHandler result(rules, parent);
- UnicodeString simpleFormats[StandardPlural::Form::COUNT];
+ UnicodeString simpleFormats[ARRAY_LENGTH];
getMeasureData(loc, unit, width, simpleFormats, status);
if (U_FAILURE(status)) { return result; }
// TODO: What field to use for units?
@@ -124,12 +181,47 @@ LongNameHandler::forMeasureUnit(const Locale &loc, const MeasureUnit &unit, cons
return result;
}
+LongNameHandler
+LongNameHandler::forCompoundUnit(const Locale &loc, const MeasureUnit &unit, const MeasureUnit &perUnit,
+ const UNumberUnitWidth &width, const PluralRules *rules,
+ const MicroPropsGenerator *parent, UErrorCode &status) {
+ LongNameHandler result(rules, parent);
+ UnicodeString primaryData[ARRAY_LENGTH];
+ getMeasureData(loc, unit, width, primaryData, status);
+ if (U_FAILURE(status)) { return result; }
+ UnicodeString secondaryData[ARRAY_LENGTH];
+ getMeasureData(loc, perUnit, width, secondaryData, status);
+ if (U_FAILURE(status)) { return result; }
+
+ UnicodeString perUnitFormat;
+ if (!secondaryData[PER_INDEX].isBogus()) {
+ perUnitFormat = secondaryData[PER_INDEX];
+ } else {
+ UnicodeString rawPerUnitFormat = getPerUnitFormat(loc, width, status);
+ if (U_FAILURE(status)) { return result; }
+ // rawPerUnitFormat is something like "{0}/{1}"; we need to substitute in the secondary unit.
+ SimpleFormatter compiled(rawPerUnitFormat, 2, 2, status);
+ if (U_FAILURE(status)) { return result; }
+ UnicodeString secondaryFormat = getWithPlural(secondaryData, StandardPlural::Form::ONE, status);
+ if (U_FAILURE(status)) { return result; }
+ SimpleFormatter secondaryCompiled(secondaryFormat, 1, 1, status);
+ if (U_FAILURE(status)) { return result; }
+ UnicodeString secondaryString = secondaryCompiled.getTextWithNoArguments().trim();
+ // TODO: Why does UnicodeString need to be explicit in the following line?
+ compiled.format(UnicodeString(u"{0}"), secondaryString, perUnitFormat, status);
+ if (U_FAILURE(status)) { return result; }
+ }
+ // TODO: What field to use for units?
+ multiSimpleFormatsToModifiers(primaryData, perUnitFormat, UNUM_FIELD_COUNT, result.fModifiers, status);
+ return result;
+}
+
LongNameHandler LongNameHandler::forCurrencyLongNames(const Locale &loc, const CurrencyUnit &currency,
const PluralRules *rules,
const MicroPropsGenerator *parent,
UErrorCode &status) {
LongNameHandler result(rules, parent);
- UnicodeString simpleFormats[StandardPlural::Form::COUNT];
+ UnicodeString simpleFormats[ARRAY_LENGTH];
getCurrencyLongNameData(loc, currency, simpleFormats, status);
if (U_FAILURE(status)) { return result; }
simpleFormatsToModifiers(simpleFormats, UNUM_CURRENCY_FIELD, result.fModifiers, status);
@@ -139,20 +231,30 @@ LongNameHandler LongNameHandler::forCurrencyLongNames(const Locale &loc, const C
void LongNameHandler::simpleFormatsToModifiers(const UnicodeString *simpleFormats, Field field,
SimpleModifier *output, UErrorCode &status) {
for (int32_t i = 0; i < StandardPlural::Form::COUNT; i++) {
- UnicodeString simpleFormat = simpleFormats[i];
- if (simpleFormat.isBogus()) {
- simpleFormat = simpleFormats[StandardPlural::Form::OTHER];
- }
- if (simpleFormat.isBogus()) {
- // There should always be data in the "other" plural variant.
- status = U_INTERNAL_PROGRAM_ERROR;
- return;
- }
- SimpleFormatter compiledFormatter(simpleFormat, 1, 1, status);
+ UnicodeString simpleFormat = getWithPlural(simpleFormats, i, status);
+ if (U_FAILURE(status)) { return; }
+ SimpleFormatter compiledFormatter(simpleFormat, 0, 1, status);
+ if (U_FAILURE(status)) { return; }
output[i] = SimpleModifier(compiledFormatter, field, false);
}
}
+void LongNameHandler::multiSimpleFormatsToModifiers(const UnicodeString *leadFormats, UnicodeString trailFormat,
+ Field field, SimpleModifier *output, UErrorCode &status) {
+ SimpleFormatter trailCompiled(trailFormat, 1, 1, status);
+ if (U_FAILURE(status)) { return; }
+ for (int32_t i = 0; i < StandardPlural::Form::COUNT; i++) {
+ UnicodeString leadFormat = getWithPlural(leadFormats, i, status);
+ if (U_FAILURE(status)) { return; }
+ UnicodeString compoundFormat;
+ trailCompiled.format(leadFormat, compoundFormat, status);
+ if (U_FAILURE(status)) { return; }
+ SimpleFormatter compoundCompiled(compoundFormat, 0, 1, status);
+ if (U_FAILURE(status)) { return; }
+ output[i] = SimpleModifier(compoundCompiled, field, false);
+ }
+}
+
void LongNameHandler::processQuantity(DecimalQuantity &quantity, MicroProps &micros,
UErrorCode &status) const {
parent->processQuantity(quantity, micros, status);
diff --git a/Build/source/libs/icu/icu-src/source/i18n/number_longnames.h b/Build/source/libs/icu/icu-src/source/i18n/number_longnames.h
index 22ecbac30e1..8738bb99e7d 100644
--- a/Build/source/libs/icu/icu-src/source/i18n/number_longnames.h
+++ b/Build/source/libs/icu/icu-src/source/i18n/number_longnames.h
@@ -21,8 +21,9 @@ class LongNameHandler : public MicroPropsGenerator, public UMemory {
const MicroPropsGenerator *parent, UErrorCode &status);
static LongNameHandler
- forMeasureUnit(const Locale &loc, const MeasureUnit &unit, const UNumberUnitWidth &width,
- const PluralRules *rules, const MicroPropsGenerator *parent, UErrorCode &status);
+ forMeasureUnit(const Locale &loc, const MeasureUnit &unit, const MeasureUnit &perUnit,
+ const UNumberUnitWidth &width, const PluralRules *rules,
+ const MicroPropsGenerator *parent, UErrorCode &status);
void
processQuantity(DecimalQuantity &quantity, MicroProps &micros, UErrorCode &status) const U_OVERRIDE;
@@ -35,8 +36,15 @@ class LongNameHandler : public MicroPropsGenerator, public UMemory {
LongNameHandler(const PluralRules *rules, const MicroPropsGenerator *parent)
: rules(rules), parent(parent) {}
+ static LongNameHandler
+ forCompoundUnit(const Locale &loc, const MeasureUnit &unit, const MeasureUnit &perUnit,
+ const UNumberUnitWidth &width, const PluralRules *rules,
+ const MicroPropsGenerator *parent, UErrorCode &status);
+
static void simpleFormatsToModifiers(const UnicodeString *simpleFormats, Field field,
SimpleModifier *output, UErrorCode &status);
+ static void multiSimpleFormatsToModifiers(const UnicodeString *leadFormats, UnicodeString trailFormat,
+ Field field, SimpleModifier *output, UErrorCode &status);
};
} // namespace impl
diff --git a/Build/source/libs/icu/icu-src/source/i18n/number_modifiers.cpp b/Build/source/libs/icu/icu-src/source/i18n/number_modifiers.cpp
index a19b12d11ed..872b97010d7 100644
--- a/Build/source/libs/icu/icu-src/source/i18n/number_modifiers.cpp
+++ b/Build/source/libs/icu/icu-src/source/i18n/number_modifiers.cpp
@@ -74,19 +74,29 @@ bool ConstantAffixModifier::isStrong() const {
SimpleModifier::SimpleModifier(const SimpleFormatter &simpleFormatter, Field field, bool strong)
: fCompiledPattern(simpleFormatter.compiledPattern), fField(field), fStrong(strong) {
- U_ASSERT(1 ==
- SimpleFormatter::getArgumentLimit(fCompiledPattern.getBuffer(), fCompiledPattern.length()));
- if (fCompiledPattern.charAt(1) != 0) {
+ int32_t argLimit = SimpleFormatter::getArgumentLimit(
+ fCompiledPattern.getBuffer(), fCompiledPattern.length());
+ if (argLimit == 0) {
+ // No arguments in compiled pattern
fPrefixLength = fCompiledPattern.charAt(1) - ARG_NUM_LIMIT;
- fSuffixOffset = 3 + fPrefixLength;
- } else {
- fPrefixLength = 0;
- fSuffixOffset = 2;
- }
- if (3 + fPrefixLength < fCompiledPattern.length()) {
- fSuffixLength = fCompiledPattern.charAt(fSuffixOffset) - ARG_NUM_LIMIT;
- } else {
+ U_ASSERT(2 + fPrefixLength == fCompiledPattern.length());
+ // Set suffixOffset = -1 to indicate no arguments in compiled pattern.
+ fSuffixOffset = -1;
fSuffixLength = 0;
+ } else {
+ U_ASSERT(argLimit == 1);
+ if (fCompiledPattern.charAt(1) != 0) {
+ fPrefixLength = fCompiledPattern.charAt(1) - ARG_NUM_LIMIT;
+ fSuffixOffset = 3 + fPrefixLength;
+ } else {
+ fPrefixLength = 0;
+ fSuffixOffset = 2;
+ }
+ if (3 + fPrefixLength < fCompiledPattern.length()) {
+ fSuffixLength = fCompiledPattern.charAt(fSuffixOffset) - ARG_NUM_LIMIT;
+ } else {
+ fSuffixLength = 0;
+ }
}
}
@@ -123,26 +133,37 @@ bool SimpleModifier::isStrong() const {
int32_t
SimpleModifier::formatAsPrefixSuffix(NumberStringBuilder &result, int32_t startIndex, int32_t endIndex,
Field field, UErrorCode &status) const {
- if (fPrefixLength > 0) {
- result.insert(startIndex, fCompiledPattern, 2, 2 + fPrefixLength, field, status);
- }
- if (fSuffixLength > 0) {
- result.insert(
- endIndex + fPrefixLength,
- fCompiledPattern,
- 1 + fSuffixOffset,
- 1 + fSuffixOffset + fSuffixLength,
- field,
- status);
+ if (fSuffixOffset == -1) {
+ // There is no argument for the inner number; overwrite the entire segment with our string.
+ return result.splice(startIndex, endIndex, fCompiledPattern, 2, 2 + fPrefixLength, field, status);
+ } else {
+ if (fPrefixLength > 0) {
+ result.insert(startIndex, fCompiledPattern, 2, 2 + fPrefixLength, field, status);
+ }
+ if (fSuffixLength > 0) {
+ result.insert(
+ endIndex + fPrefixLength,
+ fCompiledPattern,
+ 1 + fSuffixOffset,
+ 1 + fSuffixOffset + fSuffixLength,
+ field,
+ status);
+ }
+ return fPrefixLength + fSuffixLength;
}
- return fPrefixLength + fSuffixLength;
}
int32_t ConstantMultiFieldModifier::apply(NumberStringBuilder &output, int leftIndex, int rightIndex,
UErrorCode &status) const {
- // Insert the suffix first since inserting the prefix will change the rightIndex
- int32_t length = output.insert(rightIndex, fSuffix, status);
- length += output.insert(leftIndex, fPrefix, status);
+ int32_t length = output.insert(leftIndex, fPrefix, status);
+ if (fOverwrite) {
+ length += output.splice(
+ leftIndex + length,
+ rightIndex + length,
+ UnicodeString(), 0, 0,
+ UNUM_FIELD_COUNT, status);
+ }
+ length += output.insert(rightIndex + length, fSuffix, status);
return length;
}
@@ -162,10 +183,11 @@ bool ConstantMultiFieldModifier::isStrong() const {
CurrencySpacingEnabledModifier::CurrencySpacingEnabledModifier(const NumberStringBuilder &prefix,
const NumberStringBuilder &suffix,
+ bool overwrite,
bool strong,
const DecimalFormatSymbols &symbols,
UErrorCode &status)
- : ConstantMultiFieldModifier(prefix, suffix, strong) {
+ : ConstantMultiFieldModifier(prefix, suffix, overwrite, strong) {
// Check for currency spacing. Do not build the UnicodeSets unless there is
// a currency code point at a boundary.
if (prefix.length() > 0 && prefix.fieldAt(prefix.length() - 1) == UNUM_CURRENCY_FIELD) {
diff --git a/Build/source/libs/icu/icu-src/source/i18n/number_modifiers.h b/Build/source/libs/icu/icu-src/source/i18n/number_modifiers.h
index 6a88828a44d..4762a6f6d37 100644
--- a/Build/source/libs/icu/icu-src/source/i18n/number_modifiers.h
+++ b/Build/source/libs/icu/icu-src/source/i18n/number_modifiers.h
@@ -103,8 +103,15 @@ class U_I18N_API SimpleModifier : public Modifier, public UMemory {
*/
class U_I18N_API ConstantMultiFieldModifier : public Modifier, public UMemory {
public:
- ConstantMultiFieldModifier(const NumberStringBuilder &prefix, const NumberStringBuilder &suffix,
- bool strong) : fPrefix(prefix), fSuffix(suffix), fStrong(strong) {}
+ ConstantMultiFieldModifier(
+ const NumberStringBuilder &prefix,
+ const NumberStringBuilder &suffix,
+ bool overwrite,
+ bool strong)
+ : fPrefix(prefix),
+ fSuffix(suffix),
+ fOverwrite(overwrite),
+ fStrong(strong) {}
int32_t apply(NumberStringBuilder &output, int32_t leftIndex, int32_t rightIndex,
UErrorCode &status) const U_OVERRIDE;
@@ -120,6 +127,7 @@ class U_I18N_API ConstantMultiFieldModifier : public Modifier, public UMemory {
// value and is treated internally as immutable.
NumberStringBuilder fPrefix;
NumberStringBuilder fSuffix;
+ bool fOverwrite;
bool fStrong;
};
@@ -127,8 +135,13 @@ class U_I18N_API ConstantMultiFieldModifier : public Modifier, public UMemory {
class U_I18N_API CurrencySpacingEnabledModifier : public ConstantMultiFieldModifier {
public:
/** Safe code path */
- CurrencySpacingEnabledModifier(const NumberStringBuilder &prefix, const NumberStringBuilder &suffix,
- bool strong, const DecimalFormatSymbols &symbols, UErrorCode &status);
+ CurrencySpacingEnabledModifier(
+ const NumberStringBuilder &prefix,
+ const NumberStringBuilder &suffix,
+ bool overwrite,
+ bool strong,
+ const DecimalFormatSymbols &symbols,
+ UErrorCode &status);
int32_t apply(NumberStringBuilder &output, int32_t leftIndex, int32_t rightIndex,
UErrorCode &status) const U_OVERRIDE;
@@ -216,31 +229,33 @@ class U_I18N_API ParameterizedModifier : public UMemory {
}
}
- void adoptPositiveNegativeModifiers(const Modifier *positive, const Modifier *negative) {
- mods[0] = positive;
- mods[1] = negative;
+ void adoptPositiveNegativeModifiers(
+ const Modifier *positive, const Modifier *zero, const Modifier *negative) {
+ mods[2] = positive;
+ mods[1] = zero;
+ mods[0] = negative;
}
/** The modifier is ADOPTED. */
- void adoptSignPluralModifier(bool isNegative, StandardPlural::Form plural, const Modifier *mod) {
- mods[getModIndex(isNegative, plural)] = mod;
+ void adoptSignPluralModifier(int8_t signum, StandardPlural::Form plural, const Modifier *mod) {
+ mods[getModIndex(signum, plural)] = mod;
}
/** Returns a reference to the modifier; no ownership change. */
- const Modifier *getModifier(bool isNegative) const {
- return mods[isNegative ? 1 : 0];
+ const Modifier *getModifier(int8_t signum) const {
+ return mods[signum + 1];
}
/** Returns a reference to the modifier; no ownership change. */
- const Modifier *getModifier(bool isNegative, StandardPlural::Form plural) const {
- return mods[getModIndex(isNegative, plural)];
+ const Modifier *getModifier(int8_t signum, StandardPlural::Form plural) const {
+ return mods[getModIndex(signum, plural)];
}
private:
- const Modifier *mods[2 * StandardPlural::COUNT];
+ const Modifier *mods[3 * StandardPlural::COUNT];
- inline static int32_t getModIndex(bool isNegative, StandardPlural::Form plural) {
- return static_cast<int32_t>(plural) * 2 + (isNegative ? 1 : 0);
+ inline static int32_t getModIndex(int8_t signum, StandardPlural::Form plural) {
+ return static_cast<int32_t>(plural) * 3 + (signum + 1);
}
};
diff --git a/Build/source/libs/icu/icu-src/source/i18n/number_notation.cpp b/Build/source/libs/icu/icu-src/source/i18n/number_notation.cpp
index ff0cd9505de..f4ad333354d 100644
--- a/Build/source/libs/icu/icu-src/source/i18n/number_notation.cpp
+++ b/Build/source/libs/icu/icu-src/source/i18n/number_notation.cpp
@@ -54,13 +54,13 @@ Notation Notation::simple() {
ScientificNotation
ScientificNotation::withMinExponentDigits(int32_t minExponentDigits) const {
- if (minExponentDigits >= 0 && minExponentDigits < kMaxIntFracSig) {
+ if (minExponentDigits >= 1 && minExponentDigits <= kMaxIntFracSig) {
ScientificSettings settings = fUnion.scientific;
- settings.fMinExponentDigits = (int8_t) minExponentDigits;
+ settings.fMinExponentDigits = static_cast<digits_t>(minExponentDigits);
NotationUnion union_ = {settings};
return {NTN_SCIENTIFIC, union_};
} else {
- return {U_NUMBER_DIGIT_WIDTH_OUTOFBOUNDS_ERROR};
+ return {U_NUMBER_ARG_OUTOFBOUNDS_ERROR};
}
}
diff --git a/Build/source/libs/icu/icu-src/source/i18n/number_padding.cpp b/Build/source/libs/icu/icu-src/source/i18n/number_padding.cpp
index a478af60541..b1db3490cd4 100644
--- a/Build/source/libs/icu/icu-src/source/i18n/number_padding.cpp
+++ b/Build/source/libs/icu/icu-src/source/i18n/number_padding.cpp
@@ -43,7 +43,7 @@ Padder Padder::codePoints(UChar32 cp, int32_t targetWidth, UNumberFormatPadPosit
if (targetWidth >= 0) {
return {cp, targetWidth, position};
} else {
- return {U_NUMBER_PADDING_WIDTH_OUTOFBOUNDS_ERROR};
+ return {U_NUMBER_ARG_OUTOFBOUNDS_ERROR};
}
}
diff --git a/Build/source/libs/icu/icu-src/source/i18n/number_patternmodifier.cpp b/Build/source/libs/icu/icu-src/source/i18n/number_patternmodifier.cpp
index 0599f92a4f3..e182104c911 100644
--- a/Build/source/libs/icu/icu-src/source/i18n/number_patternmodifier.cpp
+++ b/Build/source/libs/icu/icu-src/source/i18n/number_patternmodifier.cpp
@@ -38,8 +38,8 @@ MutablePatternModifier::setSymbols(const DecimalFormatSymbols *symbols, const Cu
this->rules = rules;
}
-void MutablePatternModifier::setNumberProperties(bool isNegative, StandardPlural::Form plural) {
- this->isNegative = isNegative;
+void MutablePatternModifier::setNumberProperties(int8_t signum, StandardPlural::Form plural) {
+ this->signum = signum;
this->plural = plural;
}
@@ -74,10 +74,12 @@ MutablePatternModifier::createImmutableAndChain(const MicroPropsGenerator *paren
if (needsPlurals()) {
// Slower path when we require the plural keyword.
for (StandardPlural::Form plural : STANDARD_PLURAL_VALUES) {
- setNumberProperties(false, plural);
- pm->adoptSignPluralModifier(false, plural, createConstantModifier(status));
- setNumberProperties(true, plural);
- pm->adoptSignPluralModifier(true, plural, createConstantModifier(status));
+ setNumberProperties(1, plural);
+ pm->adoptSignPluralModifier(1, plural, createConstantModifier(status));
+ setNumberProperties(0, plural);
+ pm->adoptSignPluralModifier(0, plural, createConstantModifier(status));
+ setNumberProperties(-1, plural);
+ pm->adoptSignPluralModifier(-1, plural, createConstantModifier(status));
}
if (U_FAILURE(status)) {
delete pm;
@@ -86,11 +88,13 @@ MutablePatternModifier::createImmutableAndChain(const MicroPropsGenerator *paren
return new ImmutablePatternModifier(pm, rules, parent); // adopts pm
} else {
// Faster path when plural keyword is not needed.
- setNumberProperties(false, StandardPlural::Form::COUNT);
+ setNumberProperties(1, StandardPlural::Form::COUNT);
Modifier *positive = createConstantModifier(status);
- setNumberProperties(true, StandardPlural::Form::COUNT);
+ setNumberProperties(0, StandardPlural::Form::COUNT);
+ Modifier *zero = createConstantModifier(status);
+ setNumberProperties(-1, StandardPlural::Form::COUNT);
Modifier *negative = createConstantModifier(status);
- pm->adoptPositiveNegativeModifiers(positive, negative);
+ pm->adoptPositiveNegativeModifiers(positive, zero, negative);
if (U_FAILURE(status)) {
delete pm;
return nullptr;
@@ -105,9 +109,9 @@ ConstantMultiFieldModifier *MutablePatternModifier::createConstantModifier(UErro
insertPrefix(a, 0, status);
insertSuffix(b, 0, status);
if (patternInfo->hasCurrencySign()) {
- return new CurrencySpacingEnabledModifier(a, b, fStrong, *symbols, status);
+ return new CurrencySpacingEnabledModifier(a, b, !patternInfo->hasBody(), fStrong, *symbols, status);
} else {
- return new ConstantMultiFieldModifier(a, b, fStrong);
+ return new ConstantMultiFieldModifier(a, b, !patternInfo->hasBody(), fStrong);
}
}
@@ -123,13 +127,13 @@ void ImmutablePatternModifier::processQuantity(DecimalQuantity &quantity, MicroP
void ImmutablePatternModifier::applyToMicros(MicroProps &micros, DecimalQuantity &quantity) const {
if (rules == nullptr) {
- micros.modMiddle = pm->getModifier(quantity.isNegative());
+ micros.modMiddle = pm->getModifier(quantity.signum());
} else {
// TODO: Fix this. Avoid the copy.
DecimalQuantity copy(quantity);
copy.roundToInfinity();
StandardPlural::Form plural = copy.getStandardPlural(rules);
- micros.modMiddle = pm->getModifier(quantity.isNegative(), plural);
+ micros.modMiddle = pm->getModifier(quantity.signum(), plural);
}
}
@@ -149,9 +153,9 @@ void MutablePatternModifier::processQuantity(DecimalQuantity &fq, MicroProps &mi
// TODO: Fix this. Avoid the copy.
DecimalQuantity copy(fq);
micros.rounding.apply(copy, status);
- nonConstThis->setNumberProperties(fq.isNegative(), copy.getStandardPlural(rules));
+ nonConstThis->setNumberProperties(fq.signum(), copy.getStandardPlural(rules));
} else {
- nonConstThis->setNumberProperties(fq.isNegative(), StandardPlural::Form::COUNT);
+ nonConstThis->setNumberProperties(fq.signum(), StandardPlural::Form::COUNT);
}
micros.modMiddle = this;
}
@@ -163,9 +167,23 @@ int32_t MutablePatternModifier::apply(NumberStringBuilder &output, int32_t leftI
auto nonConstThis = const_cast<MutablePatternModifier *>(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);
+ }
CurrencySpacingEnabledModifier::applyCurrencySpacing(
- output, leftIndex, prefixLen, rightIndex + prefixLen, suffixLen, *symbols, status);
- return prefixLen + suffixLen;
+ output,
+ leftIndex,
+ prefixLen,
+ rightIndex + overwriteLen + prefixLen,
+ suffixLen,
+ *symbols,
+ status);
+ return prefixLen + overwriteLen + suffixLen;
}
int32_t MutablePatternModifier::getPrefixLength(UErrorCode &status) const {
@@ -230,13 +248,16 @@ UnicodeString MutablePatternModifier::getSymbol(AffixPatternType type) const {
} else if (unitWidth == UNumberUnitWidth::UNUM_UNIT_WIDTH_HIDDEN) {
return UnicodeString();
} 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(),
- UCurrNameStyle::UCURR_SYMBOL_NAME,
+ selector,
&isChoiceFormat,
&symbolLen,
&status);
@@ -278,14 +299,17 @@ void MutablePatternModifier::enterCharSequenceMode(bool isPrefix) {
inCharSequenceMode = true;
// Should the output render '+' where '-' would normally appear in the pattern?
- plusReplacesMinusSign = !isNegative && (
- signDisplay == UNUM_SIGN_ALWAYS ||
- signDisplay == UNUM_SIGN_ACCOUNTING_ALWAYS) &&
- patternInfo->positiveHasPlusSign() == false;
+ 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() && (
- isNegative || (patternInfo->negativeHasMinusSign() && plusReplacesMinusSign));
+ signum == -1 || (patternInfo->negativeHasMinusSign() && plusReplacesMinusSign));
// Resolve the flags for the affix pattern.
fFlags = 0;
@@ -303,7 +327,7 @@ void MutablePatternModifier::enterCharSequenceMode(bool isPrefix) {
// Should we prepend a sign to the pattern?
if (!isPrefix || useNegativeAffixPattern) {
prependSign = false;
- } else if (isNegative) {
+ } else if (signum == -1) {
prependSign = signDisplay != UNUM_SIGN_NEVER;
} else {
prependSign = plusReplacesMinusSign;
diff --git a/Build/source/libs/icu/icu-src/source/i18n/number_patternmodifier.h b/Build/source/libs/icu/icu-src/source/i18n/number_patternmodifier.h
index 705037f0ba7..9c8b95f7764 100644
--- a/Build/source/libs/icu/icu-src/source/i18n/number_patternmodifier.h
+++ b/Build/source/libs/icu/icu-src/source/i18n/number_patternmodifier.h
@@ -18,8 +18,8 @@ U_NAMESPACE_BEGIN
// Export an explicit template instantiation of the LocalPointer that is used as a
// data member of ParameterizedModifier.
-// (MSVC requires this, even though it should not be necessary.)
-#if defined (_MSC_VER)
+// (When building DLLs for Windows this is required.)
+#if U_PF_WINDOWS <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN
// Ignore warning 4661 as LocalPointerBase does not use operator== or operator!=
#pragma warning(suppress: 4661)
template class U_I18N_API LocalPointerBase<number::impl::ParameterizedModifier>;
@@ -125,13 +125,13 @@ class U_I18N_API MutablePatternModifier
/**
* Sets attributes of the current number being processed.
*
- * @param isNegative
- * Whether the number is negative.
+ * @param signum
+ * -1 if negative; +1 if positive; or 0 if zero.
* @param plural
- * The plural form of the number, required only if the pattern contains the triple currency sign, "¤¤¤"
- * (and as indicated by {@link #needsPlurals()}).
+ * The plural form of the number, required only if the pattern contains the triple
+ * currency sign, "¤¤¤" (and as indicated by {@link #needsPlurals()}).
*/
- void setNumberProperties(bool isNegative, StandardPlural::Form plural);
+ void setNumberProperties(int8_t signum, StandardPlural::Form plural);
/**
* Returns true if the pattern represented by this MurkyModifier requires a plural keyword in order to localize.
@@ -211,7 +211,7 @@ class U_I18N_API MutablePatternModifier
const PluralRules *rules;
// Number details (initialized in setNumberProperties)
- bool isNegative;
+ int8_t signum;
StandardPlural::Form plural;
// QuantityChain details (initialized in addToChain)
diff --git a/Build/source/libs/icu/icu-src/source/i18n/number_patternstring.cpp b/Build/source/libs/icu/icu-src/source/i18n/number_patternstring.cpp
index c67e3541816..20178824b0e 100644
--- a/Build/source/libs/icu/icu-src/source/i18n/number_patternstring.cpp
+++ b/Build/source/libs/icu/icu-src/source/i18n/number_patternstring.cpp
@@ -95,6 +95,10 @@ bool ParsedPatternInfo::containsSymbolType(AffixPatternType type, UErrorCode &st
return AffixUtils::containsType(UnicodeStringCharSequence(pattern), type, status);
}
+bool ParsedPatternInfo::hasBody() const {
+ return positive.integerTotal > 0;
+}
+
/////////////////////////////////////////////////////
/// BEGIN RECURSIVE DESCENT PARSER IMPLEMENTATION ///
/////////////////////////////////////////////////////
diff --git a/Build/source/libs/icu/icu-src/source/i18n/number_patternstring.h b/Build/source/libs/icu/icu-src/source/i18n/number_patternstring.h
index 6e1bb7f44dd..ec44290d663 100644
--- a/Build/source/libs/icu/icu-src/source/i18n/number_patternstring.h
+++ b/Build/source/libs/icu/icu-src/source/i18n/number_patternstring.h
@@ -84,6 +84,8 @@ struct U_I18N_API ParsedPatternInfo : public AffixPatternProvider, public UMemor
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
diff --git a/Build/source/libs/icu/icu-src/source/i18n/number_rounding.cpp b/Build/source/libs/icu/icu-src/source/i18n/number_rounding.cpp
index 5c494f09544..fd4dafdf983 100644
--- a/Build/source/libs/icu/icu-src/source/i18n/number_rounding.cpp
+++ b/Build/source/libs/icu/icu-src/source/i18n/number_rounding.cpp
@@ -58,7 +58,7 @@ FractionRounder Rounder::fixedFraction(int32_t minMaxFractionPlaces) {
if (minMaxFractionPlaces >= 0 && minMaxFractionPlaces <= kMaxIntFracSig) {
return constructFraction(minMaxFractionPlaces, minMaxFractionPlaces);
} else {
- return {U_NUMBER_DIGIT_WIDTH_OUTOFBOUNDS_ERROR};
+ return {U_NUMBER_ARG_OUTOFBOUNDS_ERROR};
}
}
@@ -66,7 +66,7 @@ FractionRounder Rounder::minFraction(int32_t minFractionPlaces) {
if (minFractionPlaces >= 0 && minFractionPlaces <= kMaxIntFracSig) {
return constructFraction(minFractionPlaces, -1);
} else {
- return {U_NUMBER_DIGIT_WIDTH_OUTOFBOUNDS_ERROR};
+ return {U_NUMBER_ARG_OUTOFBOUNDS_ERROR};
}
}
@@ -74,7 +74,7 @@ FractionRounder Rounder::maxFraction(int32_t maxFractionPlaces) {
if (maxFractionPlaces >= 0 && maxFractionPlaces <= kMaxIntFracSig) {
return constructFraction(0, maxFractionPlaces);
} else {
- return {U_NUMBER_DIGIT_WIDTH_OUTOFBOUNDS_ERROR};
+ return {U_NUMBER_ARG_OUTOFBOUNDS_ERROR};
}
}
@@ -83,40 +83,40 @@ FractionRounder Rounder::minMaxFraction(int32_t minFractionPlaces, int32_t maxFr
minFractionPlaces <= maxFractionPlaces) {
return constructFraction(minFractionPlaces, maxFractionPlaces);
} else {
- return {U_NUMBER_DIGIT_WIDTH_OUTOFBOUNDS_ERROR};
+ return {U_NUMBER_ARG_OUTOFBOUNDS_ERROR};
}
}
Rounder Rounder::fixedDigits(int32_t minMaxSignificantDigits) {
- if (minMaxSignificantDigits >= 0 && minMaxSignificantDigits <= kMaxIntFracSig) {
+ if (minMaxSignificantDigits >= 1 && minMaxSignificantDigits <= kMaxIntFracSig) {
return constructSignificant(minMaxSignificantDigits, minMaxSignificantDigits);
} else {
- return {U_NUMBER_DIGIT_WIDTH_OUTOFBOUNDS_ERROR};
+ return {U_NUMBER_ARG_OUTOFBOUNDS_ERROR};
}
}
Rounder Rounder::minDigits(int32_t minSignificantDigits) {
- if (minSignificantDigits >= 0 && minSignificantDigits <= kMaxIntFracSig) {
+ if (minSignificantDigits >= 1 && minSignificantDigits <= kMaxIntFracSig) {
return constructSignificant(minSignificantDigits, -1);
} else {
- return {U_NUMBER_DIGIT_WIDTH_OUTOFBOUNDS_ERROR};
+ return {U_NUMBER_ARG_OUTOFBOUNDS_ERROR};
}
}
Rounder Rounder::maxDigits(int32_t maxSignificantDigits) {
- if (maxSignificantDigits >= 0 && maxSignificantDigits <= kMaxIntFracSig) {
- return constructSignificant(0, maxSignificantDigits);
+ if (maxSignificantDigits >= 1 && maxSignificantDigits <= kMaxIntFracSig) {
+ return constructSignificant(1, maxSignificantDigits);
} else {
- return {U_NUMBER_DIGIT_WIDTH_OUTOFBOUNDS_ERROR};
+ return {U_NUMBER_ARG_OUTOFBOUNDS_ERROR};
}
}
Rounder Rounder::minMaxDigits(int32_t minSignificantDigits, int32_t maxSignificantDigits) {
- if (minSignificantDigits >= 0 && maxSignificantDigits <= kMaxIntFracSig &&
+ if (minSignificantDigits >= 1 && maxSignificantDigits <= kMaxIntFracSig &&
minSignificantDigits <= maxSignificantDigits) {
return constructSignificant(minSignificantDigits, maxSignificantDigits);
} else {
- return {U_NUMBER_DIGIT_WIDTH_OUTOFBOUNDS_ERROR};
+ return {U_NUMBER_ARG_OUTOFBOUNDS_ERROR};
}
}
@@ -124,7 +124,7 @@ IncrementRounder Rounder::increment(double roundingIncrement) {
if (roundingIncrement > 0.0) {
return constructIncrement(roundingIncrement, 0);
} else {
- return {U_NUMBER_DIGIT_WIDTH_OUTOFBOUNDS_ERROR};
+ return {U_NUMBER_ARG_OUTOFBOUNDS_ERROR};
}
}
@@ -139,19 +139,19 @@ Rounder Rounder::withMode(RoundingMode roundingMode) const {
Rounder FractionRounder::withMinDigits(int32_t minSignificantDigits) const {
if (fType == RND_ERROR) { return *this; } // no-op in error state
- if (minSignificantDigits >= 0 && minSignificantDigits <= kMaxIntFracSig) {
+ if (minSignificantDigits >= 1 && minSignificantDigits <= kMaxIntFracSig) {
return constructFractionSignificant(*this, minSignificantDigits, -1);
} else {
- return {U_NUMBER_DIGIT_WIDTH_OUTOFBOUNDS_ERROR};
+ return {U_NUMBER_ARG_OUTOFBOUNDS_ERROR};
}
}
Rounder FractionRounder::withMaxDigits(int32_t maxSignificantDigits) const {
if (fType == RND_ERROR) { return *this; } // no-op in error state
- if (maxSignificantDigits >= 0 && maxSignificantDigits <= kMaxIntFracSig) {
+ if (maxSignificantDigits >= 1 && maxSignificantDigits <= kMaxIntFracSig) {
return constructFractionSignificant(*this, -1, maxSignificantDigits);
} else {
- return {U_NUMBER_DIGIT_WIDTH_OUTOFBOUNDS_ERROR};
+ return {U_NUMBER_ARG_OUTOFBOUNDS_ERROR};
}
}
@@ -185,14 +185,14 @@ Rounder IncrementRounder::withMinFraction(int32_t minFrac) const {
if (minFrac >= 0 && minFrac <= kMaxIntFracSig) {
return constructIncrement(fUnion.increment.fIncrement, minFrac);
} else {
- return {U_NUMBER_DIGIT_WIDTH_OUTOFBOUNDS_ERROR};
+ return {U_NUMBER_ARG_OUTOFBOUNDS_ERROR};
}
}
FractionRounder Rounder::constructFraction(int32_t minFrac, int32_t maxFrac) {
FractionSignificantSettings settings;
- settings.fMinFrac = static_cast<int8_t> (minFrac);
- settings.fMaxFrac = static_cast<int8_t> (maxFrac);
+ settings.fMinFrac = static_cast<digits_t>(minFrac);
+ settings.fMaxFrac = static_cast<digits_t>(maxFrac);
settings.fMinSig = -1;
settings.fMaxSig = -1;
RounderUnion union_;
@@ -204,8 +204,8 @@ Rounder Rounder::constructSignificant(int32_t minSig, int32_t maxSig) {
FractionSignificantSettings settings;
settings.fMinFrac = -1;
settings.fMaxFrac = -1;
- settings.fMinSig = static_cast<int8_t>(minSig);
- settings.fMaxSig = static_cast<int8_t>(maxSig);
+ settings.fMinSig = static_cast<digits_t>(minSig);
+ settings.fMaxSig = static_cast<digits_t>(maxSig);
RounderUnion union_;
union_.fracSig = settings;
return {RND_SIGNIFICANT, union_, kDefaultMode};
@@ -214,8 +214,8 @@ Rounder Rounder::constructSignificant(int32_t minSig, int32_t maxSig) {
Rounder
Rounder::constructFractionSignificant(const FractionRounder &base, int32_t minSig, int32_t maxSig) {
FractionSignificantSettings settings = base.fUnion.fracSig;
- settings.fMinSig = static_cast<int8_t>(minSig);
- settings.fMaxSig = static_cast<int8_t>(maxSig);
+ settings.fMinSig = static_cast<digits_t>(minSig);
+ settings.fMaxSig = static_cast<digits_t>(maxSig);
RounderUnion union_;
union_.fracSig = settings;
return {RND_FRACTION_SIGNIFICANT, union_, kDefaultMode};
@@ -224,7 +224,7 @@ Rounder::constructFractionSignificant(const FractionRounder &base, int32_t minSi
IncrementRounder Rounder::constructIncrement(double increment, int32_t minFrac) {
IncrementSettings settings;
settings.fIncrement = increment;
- settings.fMinFrac = minFrac;
+ settings.fMinFrac = static_cast<digits_t>(minFrac);
RounderUnion union_;
union_.increment = settings;
return {RND_INCREMENT, union_, kDefaultMode};
@@ -251,28 +251,39 @@ void Rounder::setLocaleData(const CurrencyUnit &currency, UErrorCode &status) {
int32_t
Rounder::chooseMultiplierAndApply(impl::DecimalQuantity &input, const impl::MultiplierProducer &producer,
UErrorCode &status) {
- // TODO: Make a better and more efficient implementation.
- // TODO: Avoid the object creation here.
- DecimalQuantity copy(input);
-
+ // Do not call this method with zero.
U_ASSERT(!input.isZero());
- int32_t magnitude = input.getMagnitude();
- int32_t multiplier = producer.getMultiplier(magnitude);
+
+ // Perform the first attempt at rounding.
+ int magnitude = input.getMagnitude();
+ int multiplier = producer.getMultiplier(magnitude);
input.adjustMagnitude(multiplier);
apply(input, status);
- // If the number turned to zero when rounding, do not re-attempt the rounding.
- if (!input.isZero() && input.getMagnitude() == magnitude + multiplier + 1) {
- magnitude += 1;
- input = copy;
- multiplier = producer.getMultiplier(magnitude);
- input.adjustMagnitude(multiplier);
- U_ASSERT(input.getMagnitude() == magnitude + multiplier - 1);
- apply(input, status);
- U_ASSERT(input.getMagnitude() == magnitude + multiplier);
+ // If the number rounded to zero, exit.
+ if (input.isZero() || U_FAILURE(status)) {
+ return multiplier;
+ }
+
+ // If the new magnitude after rounding is the same as it was before rounding, then we are done.
+ // This case applies to most numbers.
+ if (input.getMagnitude() == magnitude + multiplier) {
+ return multiplier;
}
- return multiplier;
+ // If the above case DIDN'T apply, then we have a case like 99.9 -> 100 or 999.9 -> 1000:
+ // The number rounded up to the next magnitude. Check if the multiplier changes; if it doesn't,
+ // we do not need to make any more adjustments.
+ int _multiplier = producer.getMultiplier(magnitude + 1);
+ if (multiplier == _multiplier) {
+ return multiplier;
+ }
+
+ // We have a case like 999.9 -> 1000, where the correct output is "1K", not "1000".
+ // Fix the magnitude and re-apply the rounding strategy.
+ input.adjustMagnitude(_multiplier - multiplier);
+ apply(input, status);
+ return _multiplier;
}
/** This is the method that contains the actual rounding logic. */
@@ -331,6 +342,7 @@ void Rounder::apply(impl::DecimalQuantity &value, UErrorCode& status) const {
case RND_CURRENCY:
// Call .withCurrency() before .apply()!
U_ASSERT(false);
+ break;
case RND_PASS_THROUGH:
break;
diff --git a/Build/source/libs/icu/icu-src/source/i18n/number_stringbuilder.cpp b/Build/source/libs/icu/icu-src/source/i18n/number_stringbuilder.cpp
index e6e86bd4291..37159d7e53a 100644
--- a/Build/source/libs/icu/icu-src/source/i18n/number_stringbuilder.cpp
+++ b/Build/source/libs/icu/icu-src/source/i18n/number_stringbuilder.cpp
@@ -191,6 +191,30 @@ NumberStringBuilder::insert(int32_t index, const UnicodeString &unistr, int32_t
return count;
}
+int32_t
+NumberStringBuilder::splice(int32_t startThis, int32_t endThis, const UnicodeString &unistr,
+ int32_t startOther, int32_t endOther, Field field, UErrorCode& status) {
+ int32_t thisLength = endThis - startThis;
+ int32_t otherLength = endOther - startOther;
+ int32_t count = otherLength - thisLength;
+ int32_t position;
+ if (count > 0) {
+ // Overall, chars need to be added.
+ position = prepareForInsert(startThis, count, status);
+ } else {
+ // Overall, chars need to be removed or kept the same.
+ position = remove(startThis, -count);
+ }
+ if (U_FAILURE(status)) {
+ return count;
+ }
+ for (int32_t i = 0; i < otherLength; i++) {
+ getCharPtr()[position + i] = unistr.charAt(startOther + i);
+ getFieldPtr()[position + i] = field;
+ }
+ return count;
+}
+
int32_t NumberStringBuilder::append(const NumberStringBuilder &other, UErrorCode &status) {
return insert(fLength, other, status);
}
@@ -296,6 +320,19 @@ int32_t NumberStringBuilder::prepareForInsertHelper(int32_t index, int32_t count
return fZero + index;
}
+int32_t NumberStringBuilder::remove(int32_t index, int32_t count) {
+ // TODO: Reset the heap here? (If the string after removal can fit on stack?)
+ int32_t position = index + fZero;
+ uprv_memmove2(getCharPtr() + position,
+ getCharPtr() + position + count,
+ sizeof(char16_t) * (fLength - index - count));
+ uprv_memmove2(getFieldPtr() + position,
+ getFieldPtr() + position + count,
+ sizeof(Field) * (fLength - index - count));
+ fLength -= count;
+ return position;
+}
+
UnicodeString NumberStringBuilder::toUnicodeString() const {
return UnicodeString(getCharPtr() + fZero, fLength);
}
diff --git a/Build/source/libs/icu/icu-src/source/i18n/number_stringbuilder.h b/Build/source/libs/icu/icu-src/source/i18n/number_stringbuilder.h
index f08dcb1d1be..a97cc9ca026 100644
--- a/Build/source/libs/icu/icu-src/source/i18n/number_stringbuilder.h
+++ b/Build/source/libs/icu/icu-src/source/i18n/number_stringbuilder.h
@@ -77,6 +77,9 @@ class U_I18N_API NumberStringBuilder : public UMemory {
int32_t insert(int32_t index, const UnicodeString &unistr, int32_t start, int32_t end, Field field,
UErrorCode &status);
+ int32_t splice(int32_t startThis, int32_t endThis, const UnicodeString &unistr,
+ int32_t startOther, int32_t endOther, Field field, UErrorCode& status);
+
int32_t append(const NumberStringBuilder &other, UErrorCode &status);
int32_t insert(int32_t index, const NumberStringBuilder &other, UErrorCode &status);
@@ -123,6 +126,8 @@ class U_I18N_API NumberStringBuilder : public UMemory {
int32_t prepareForInsert(int32_t index, int32_t count, UErrorCode &status);
int32_t prepareForInsertHelper(int32_t index, int32_t count, UErrorCode &status);
+
+ int32_t remove(int32_t index, int32_t count);
};
} // namespace impl
diff --git a/Build/source/libs/icu/icu-src/source/i18n/number_types.h b/Build/source/libs/icu/icu-src/source/i18n/number_types.h
index 2bc21bd40dc..c01765e2cea 100644
--- a/Build/source/libs/icu/icu-src/source/i18n/number_types.h
+++ b/Build/source/libs/icu/icu-src/source/i18n/number_types.h
@@ -31,7 +31,7 @@ typedef UNumberFormatPadPosition PadPosition;
typedef UNumberCompactStyle CompactStyle;
// ICU4J Equivalent: RoundingUtils.MAX_INT_FRAC_SIG
-static constexpr int32_t kMaxIntFracSig = 100;
+static constexpr int32_t kMaxIntFracSig = 999;
// ICU4J Equivalent: RoundingUtils.DEFAULT_ROUNDING_MODE
static constexpr RoundingMode kDefaultMode = RoundingMode::UNUM_FOUND_HALFEVEN;
@@ -42,10 +42,6 @@ static constexpr char16_t kFallbackPaddingString[] = u" ";
// ICU4J Equivalent: NumberFormatterImpl.DEFAULT_CURRENCY
static constexpr char16_t kDefaultCurrency[] = u"XXX";
-// FIXME: New error codes:
-static constexpr UErrorCode U_NUMBER_DIGIT_WIDTH_OUTOFBOUNDS_ERROR = U_ILLEGAL_ARGUMENT_ERROR;
-static constexpr UErrorCode U_NUMBER_PADDING_WIDTH_OUTOFBOUNDS_ERROR = U_ILLEGAL_ARGUMENT_ERROR;
-
// Forward declarations:
class Modifier;
@@ -142,6 +138,13 @@ class U_I18N_API AffixPatternProvider {
virtual bool negativeHasMinusSign() 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
+ * have one. This is used in cases like compact notation, where the pattern replaces the entire
+ * number instead of rendering the number.
+ */
+ virtual bool hasBody() const = 0;
};
/**
@@ -230,10 +233,21 @@ class U_I18N_API MicroPropsGenerator {
virtual void processQuantity(DecimalQuantity& quantity, MicroProps& micros, UErrorCode& status) const = 0;
};
+/**
+ * An interface used by compact notation and scientific notation to choose a multiplier while rounding.
+ */
class MultiplierProducer {
public:
virtual ~MultiplierProducer() = default;
+ /**
+ * Maps a magnitude to a multiplier in powers of ten. For example, in compact notation in English, a magnitude of 5
+ * (e.g., 100,000) should return a multiplier of -3, since the number is displayed in thousands.
+ *
+ * @param magnitude
+ * The power of ten of the input number.
+ * @return The shift in powers of ten.
+ */
virtual int32_t getMultiplier(int32_t magnitude) const = 0;
};
diff --git a/Build/source/libs/icu/icu-src/source/i18n/rbnf.cpp b/Build/source/libs/icu/icu-src/source/i18n/rbnf.cpp
index 66f532e79aa..1b75e5ee1b7 100644
--- a/Build/source/libs/icu/icu-src/source/i18n/rbnf.cpp
+++ b/Build/source/libs/icu/icu-src/source/i18n/rbnf.cpp
@@ -1371,7 +1371,7 @@ RuleBasedNumberFormat::parse(const UnicodeString& text,
ParsePosition working_pp(0);
Formattable working_result;
- rp->parse(workingText, working_pp, kMaxDouble, working_result);
+ rp->parse(workingText, working_pp, kMaxDouble, 0, working_result);
if (working_pp.getIndex() > high_pp.getIndex()) {
high_pp = working_pp;
high_result = working_result;
diff --git a/Build/source/libs/icu/icu-src/source/i18n/regexcmp.cpp b/Build/source/libs/icu/icu-src/source/i18n/regexcmp.cpp
index 4e9ad6ae4d7..ca1008c0d06 100644
--- a/Build/source/libs/icu/icu-src/source/i18n/regexcmp.cpp
+++ b/Build/source/libs/icu/icu-src/source/i18n/regexcmp.cpp
@@ -4450,11 +4450,9 @@ UnicodeSet *RegexCompile::createSetForProperty(const UnicodeString &propName, UB
// See if the property looks like a Java "InBlockName", which
// we will recast as "Block=BlockName"
//
- static const UChar IN[] = {0x49, 0x6E, 0}; // "In"
- static const UChar BLOCK[] = {0x42, 0x6C, 0x6f, 0x63, 0x6b, 0x3d, 00}; // "Block="
- if (mPropName.startsWith(IN, 2) && propName.length()>=3) {
+ if (mPropName.startsWith(u"In", 2) && propName.length()>=3) {
setExpr.truncate(4); // Leaves "[\p{", or "[\P{"
- setExpr.append(BLOCK, -1);
+ setExpr.append(u"Block=", -1);
setExpr.append(UnicodeString(mPropName, 2)); // Property with the leading "In" removed.
setExpr.append(chRBrace);
setExpr.append(chRBracket);
diff --git a/Build/source/libs/icu/icu-src/source/i18n/rematch.cpp b/Build/source/libs/icu/icu-src/source/i18n/rematch.cpp
index d01117f057b..efa3909e5e9 100644
--- a/Build/source/libs/icu/icu-src/source/i18n/rematch.cpp
+++ b/Build/source/libs/icu/icu-src/source/i18n/rematch.cpp
@@ -438,7 +438,7 @@ RegexMatcher &RegexMatcher::appendReplacement(UText *dest,
status = U_REGEX_INVALID_CAPTURE_GROUP_NAME;
}
}
-
+
} else if (u_isdigit(nextChar)) {
// $n Scan for a capture group number
int32_t numCaptureGroups = fPattern->fGroupMap->size();
@@ -459,7 +459,7 @@ RegexMatcher &RegexMatcher::appendReplacement(UText *dest,
break;
}
(void)UTEXT_NEXT32(replacement);
- groupNum=groupNum*10 + nextDigitVal;
+ groupNum=groupNum*10 + nextDigitVal;
++numDigits;
}
} else {
@@ -2187,7 +2187,7 @@ int32_t RegexMatcher::split(UText *input,
break;
}
i++;
- dest[i] = utext_extract_replace(fInputText, dest[i],
+ dest[i] = utext_extract_replace(fInputText, dest[i],
start64(groupNum, status), end64(groupNum, status), &status);
}
@@ -5469,7 +5469,7 @@ GC_Done:
if (lbStartIdx < 0) {
// First time through loop.
lbStartIdx = fp->fInputIdx - minML;
- if (lbStartIdx > 0) {
+ if (lbStartIdx > 0 && lbStartIdx < fInputLength) {
U16_SET_CP_START(inputBuf, 0, lbStartIdx);
}
} else {
@@ -5546,7 +5546,7 @@ GC_Done:
if (lbStartIdx < 0) {
// First time through loop.
lbStartIdx = fp->fInputIdx - minML;
- if (lbStartIdx > 0) {
+ if (lbStartIdx > 0 && lbStartIdx < fInputLength) {
U16_SET_CP_START(inputBuf, 0, lbStartIdx);
}
} else {
@@ -5818,3 +5818,4 @@ UOBJECT_DEFINE_RTTI_IMPLEMENTATION(RegexMatcher)
U_NAMESPACE_END
#endif // !UCONFIG_NO_REGULAR_EXPRESSIONS
+
diff --git a/Build/source/libs/icu/icu-src/source/i18n/simpletz.cpp b/Build/source/libs/icu/icu-src/source/i18n/simpletz.cpp
index e17d14cc7b4..57a7ba8ed75 100644
--- a/Build/source/libs/icu/icu-src/source/i18n/simpletz.cpp
+++ b/Build/source/libs/icu/icu-src/source/i18n/simpletz.cpp
@@ -177,7 +177,7 @@ void SimpleTimeZone::construct(int32_t rawOffsetGMT,
decodeRules(status);
- if (savingsDST <= 0) {
+ if (savingsDST == 0) {
status = U_ILLEGAL_ARGUMENT_ERROR;
}
}
@@ -686,7 +686,7 @@ SimpleTimeZone::setRawOffset(int32_t offsetMillis)
void
SimpleTimeZone::setDSTSavings(int32_t millisSavedDuringDST, UErrorCode& status)
{
- if (millisSavedDuringDST <= 0) {
+ if (millisSavedDuringDST == 0) {
status = U_ILLEGAL_ARGUMENT_ERROR;
}
else {
diff --git a/Build/source/libs/icu/icu-src/source/i18n/ucol.cpp b/Build/source/libs/icu/icu-src/source/i18n/ucol.cpp
index e53dc92d797..f59333ede3c 100644
--- a/Build/source/libs/icu/icu-src/source/i18n/ucol.cpp
+++ b/Build/source/libs/icu/icu-src/source/i18n/ucol.cpp
@@ -95,6 +95,7 @@ ucol_safeClone(const UCollator *coll, void * /*stackBuffer*/, int32_t * pBufferS
Collator *newColl = Collator::fromUCollator(coll)->clone();
if (newColl == NULL) {
*status = U_MEMORY_ALLOCATION_ERROR;
+ return nullptr;
} else {
*status = U_SAFECLONE_ALLOCATED_WARNING;
}
diff --git a/Build/source/libs/icu/icu-src/source/i18n/ucol_res.cpp b/Build/source/libs/icu/icu-src/source/i18n/ucol_res.cpp
index 0f1d6d23b13..76975ecc01d 100644
--- a/Build/source/libs/icu/icu-src/source/i18n/ucol_res.cpp
+++ b/Build/source/libs/icu/icu-src/source/i18n/ucol_res.cpp
@@ -451,6 +451,7 @@ CollationLoader::loadFromData(UErrorCode &errorCode) {
const CollationCacheEntry *entry = new CollationCacheEntry(validLocale, t.getAlias());
if(entry == NULL) {
errorCode = U_MEMORY_ALLOCATION_ERROR;
+ return nullptr;
} else {
t.orphan();
}
diff --git a/Build/source/libs/icu/icu-src/source/i18n/udatpg.cpp b/Build/source/libs/icu/icu-src/source/i18n/udatpg.cpp
index 9ba82b529c5..febf73b3ce4 100644
--- a/Build/source/libs/icu/icu-src/source/i18n/udatpg.cpp
+++ b/Build/source/libs/icu/icu-src/source/i18n/udatpg.cpp
@@ -181,6 +181,25 @@ udatpg_getAppendItemName(const UDateTimePatternGenerator *dtpg,
return result.getBuffer();
}
+U_CAPI int32_t U_EXPORT2
+udatpg_getFieldDisplayName(const UDateTimePatternGenerator *dtpg,
+ UDateTimePatternField field,
+ UDateTimePGDisplayWidth width,
+ UChar *fieldName, int32_t capacity,
+ UErrorCode *pErrorCode) {
+ if (U_FAILURE(*pErrorCode))
+ return -1;
+ if (fieldName == NULL ? capacity != 0 : capacity < 0) {
+ *pErrorCode = U_ILLEGAL_ARGUMENT_ERROR;
+ return -1;
+ }
+ UnicodeString result = ((const DateTimePatternGenerator *)dtpg)->getFieldDisplayName(field,width);
+ if (fieldName == NULL) {
+ return result.length();
+ }
+ return result.extract(fieldName, capacity, *pErrorCode);
+}
+
U_CAPI void U_EXPORT2
udatpg_setDateTimeFormat(const UDateTimePatternGenerator *dtpg,
const UChar *dtFormat, int32_t length) {
diff --git a/Build/source/libs/icu/icu-src/source/i18n/unicode/compactdecimalformat.h b/Build/source/libs/icu/icu-src/source/i18n/unicode/compactdecimalformat.h
index 3fbe5da9cee..d682d2d0e74 100644
--- a/Build/source/libs/icu/icu-src/source/i18n/unicode/compactdecimalformat.h
+++ b/Build/source/libs/icu/icu-src/source/i18n/unicode/compactdecimalformat.h
@@ -16,7 +16,7 @@
#include "unicode/utypes.h"
/**
* \file
- * \brief C++ API: Formats decimal numbers in compact form.
+ * \brief C++ API: Compatibility APIs for compact decimal number formatting.
*/
#if !UCONFIG_NO_FORMATTING
@@ -30,6 +30,11 @@ U_NAMESPACE_BEGIN
class PluralRules;
/**
+ * <p><strong>IMPORTANT:</strong> New users are strongly encouraged to see if
+ * numberformatter.h fits their use case. Although not deprecated, this header
+ * is provided for backwards compatibility only.
+ * <hr/>
+ *
* The CompactDecimalFormat produces abbreviated numbers, suitable for display in
* environments will limited real estate. For example, 'Hits: 1.2B' instead of
* 'Hits: 1,200,000,000'. The format will be appropriate for the given language,
@@ -56,6 +61,9 @@ public:
/**
* Returns a compact decimal instance for specified locale.
+ * <p>
+ * <strong>NOTE:</strong> New users are strongly encouraged to use
+ * {@link NumberFormatter} instead of NumberFormat.
* @param inLocale the given locale.
* @param style whether to use short or long style.
* @param status error code returned here.
diff --git a/Build/source/libs/icu/icu-src/source/i18n/unicode/datefmt.h b/Build/source/libs/icu/icu-src/source/i18n/unicode/datefmt.h
index 3da0797a09b..f8bcf54bfb3 100644
--- a/Build/source/libs/icu/icu-src/source/i18n/unicode/datefmt.h
+++ b/Build/source/libs/icu/icu-src/source/i18n/unicode/datefmt.h
@@ -44,7 +44,8 @@ class TimeZone;
class DateTimePatternGenerator;
// explicit template instantiation. see digitlst.h
-#if defined (_MSC_VER)
+// (When building DLLs for Windows this is required.)
+#if U_PF_WINDOWS <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN
template class U_I18N_API EnumSet<UDateFormatBooleanAttribute,
0,
UDAT_BOOLEAN_ATTRIBUTE_COUNT>;
diff --git a/Build/source/libs/icu/icu-src/source/i18n/unicode/dcfmtsym.h b/Build/source/libs/icu/icu-src/source/i18n/unicode/dcfmtsym.h
index 4dc6f950f29..e58befa31bd 100644
--- a/Build/source/libs/icu/icu-src/source/i18n/unicode/dcfmtsym.h
+++ b/Build/source/libs/icu/icu-src/source/i18n/unicode/dcfmtsym.h
@@ -80,10 +80,6 @@ U_NAMESPACE_BEGIN
* If you supply a pattern with multiple grouping characters, the interval
* between the last one and the end of the integer is the one that is
* used. So "#,##,###,####" == "######,####" == "##,####,####".
- * <P>
- * This class only handles localized digits where the 10 digits are
- * contiguous in Unicode, from 0 to 9. Other digits sets (such as
- * superscripts) would need a different subclass.
*/
class U_I18N_API DecimalFormatSymbols : public UObject {
public:
@@ -396,6 +392,13 @@ public:
inline UBool isCustomIntlCurrencySymbol() const {
return fIsCustomIntlCurrencySymbol;
}
+
+ /**
+ * @internal For ICU use only
+ */
+ inline UChar32 getCodePointZero() const {
+ return fCodePointZero;
+ }
#endif /* U_HIDE_INTERNAL_API */
/**
@@ -410,10 +413,23 @@ public:
* @return the format symbol by the param 'symbol'
* @internal
*/
- inline const UnicodeString &getConstSymbol(ENumberFormatSymbol symbol) const;
+ inline const UnicodeString& getConstSymbol(ENumberFormatSymbol symbol) const;
#ifndef U_HIDE_INTERNAL_API
/**
+ * Returns the const UnicodeString reference, like getConstSymbol,
+ * corresponding to the digit with the given value. This is equivalent
+ * to accessing the symbol from getConstSymbol with the corresponding
+ * key, such as kZeroDigitSymbol or kOneDigitSymbol.
+ *
+ * @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.
+ * @internal This API is currently for ICU use only.
+ */
+ inline const UnicodeString& getConstDigitSymbol(int32_t digit) const;
+
+ /**
* Returns that pattern stored in currecy info. Internal API for use by NumberFormat API.
* @internal
*/
@@ -444,6 +460,22 @@ private:
*/
UnicodeString fNoSymbol;
+ /**
+ * Dealing with code points is faster than dealing with strings when formatting. Because of
+ * this, we maintain a value containing the zero code point that is used whenever digitStrings
+ * represents a sequence of ten code points in order.
+ *
+ * <p>If the value stored here is positive, it means that the code point stored in this value
+ * corresponds to the digitStrings array, and codePointZero can be used instead of the
+ * digitStrings array for the purposes of efficient formatting; if -1, then digitStrings does
+ * *not* contain a sequence of code points, and it must be used directly.
+ *
+ * <p>It is assumed that codePointZero always shadows the value in digitStrings. codePointZero
+ * should never be set directly; rather, it should be updated only when digitStrings mutates.
+ * That is, the flow of information is digitStrings -> codePointZero, not the other way.
+ */
+ UChar32 fCodePointZero;
+
Locale locale;
char actualLocale[ULOC_FULLNAME_CAPACITY];
@@ -469,7 +501,7 @@ DecimalFormatSymbols::getSymbol(ENumberFormatSymbol symbol) const {
return *strPtr;
}
-// See comments above for this function. Not hidden with #ifndef U_HIDE_INTERNAL_API
+// See comments above for this function. Not hidden with #ifdef U_HIDE_INTERNAL_API
inline const UnicodeString &
DecimalFormatSymbols::getConstSymbol(ENumberFormatSymbol symbol) const {
const UnicodeString *strPtr;
@@ -481,6 +513,19 @@ DecimalFormatSymbols::getConstSymbol(ENumberFormatSymbol symbol) const {
return *strPtr;
}
+#ifndef U_HIDE_INTERNAL_API
+inline const UnicodeString& DecimalFormatSymbols::getConstDigitSymbol(int32_t digit) const {
+ if (digit < 0 || digit > 9) {
+ digit = 0;
+ }
+ if (digit == 0) {
+ return fSymbols[kZeroDigitSymbol];
+ }
+ ENumberFormatSymbol key = static_cast<ENumberFormatSymbol>(kOneDigitSymbol + digit - 1);
+ return fSymbols[key];
+}
+#endif
+
// -------------------------------------
inline void
@@ -497,14 +542,20 @@ DecimalFormatSymbols::setSymbol(ENumberFormatSymbol symbol, const UnicodeString
// If the zero digit is being set to a known zero digit according to Unicode,
// then we automatically set the corresponding 1-9 digits
- if ( propogateDigits && symbol == kZeroDigitSymbol && value.countChar32() == 1 ) {
+ // Also record updates to fCodePointZero. Be conservative if in doubt.
+ if (symbol == kZeroDigitSymbol) {
UChar32 sym = value.char32At(0);
- if ( u_charDigitValue(sym) == 0 ) {
+ if ( propogateDigits && u_charDigitValue(sym) == 0 && value.countChar32() == 1 ) {
+ fCodePointZero = sym;
for ( int8_t i = 1 ; i<= 9 ; i++ ) {
sym++;
fSymbols[(int)kOneDigitSymbol+i-1] = UnicodeString(sym);
}
+ } else {
+ fCodePointZero = -1;
}
+ } else if (symbol >= kOneDigitSymbol && symbol <= kNineDigitSymbol) {
+ fCodePointZero = -1;
}
}
diff --git a/Build/source/libs/icu/icu-src/source/i18n/unicode/decimfmt.h b/Build/source/libs/icu/icu-src/source/i18n/unicode/decimfmt.h
index 790053636d5..b062208d9b1 100644
--- a/Build/source/libs/icu/icu-src/source/i18n/unicode/decimfmt.h
+++ b/Build/source/libs/icu/icu-src/source/i18n/unicode/decimfmt.h
@@ -30,7 +30,7 @@
#include "unicode/utypes.h"
/**
* \file
- * \brief C++ API: Formats decimal numbers.
+ * \brief C++ API: Compatibility APIs for decimal formatting.
*/
#if !UCONFIG_NO_FORMATTING
@@ -67,13 +67,19 @@ class PluralRules;
class VisibleDigitsWithExponent;
// explicit template instantiation. see digitlst.h
-#if defined (_MSC_VER)
+// (When building DLLs for Windows this is required.)
+#if U_PF_WINDOWS <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN
template class U_I18N_API EnumSet<UNumberFormatAttribute,
UNUM_MAX_NONBOOLEAN_ATTRIBUTE+1,
UNUM_LIMIT_BOOLEAN_ATTRIBUTE>;
#endif
/**
+ * <p><strong>IMPORTANT:</strong> New users are strongly encouraged to see if
+ * numberformatter.h fits their use case. Although not deprecated, this header
+ * is provided for backwards compatibility only.
+ * <hr/>
+ *
* DecimalFormat is a concrete subclass of NumberFormat that formats decimal
* numbers. It has a variety of features designed to make it possible to parse
* and format numbers in any locale, including support for Western, Arabic, or
@@ -688,6 +694,9 @@ public:
* on NumberFormat such as createInstance. These factories will
* return the most appropriate sub-class of NumberFormat for a given
* locale.
+ * <p>
+ * <strong>NOTE:</strong> New users are strongly encouraged to use
+ * {@link NumberFormatter} instead of DecimalFormat.
* @param status Output param set to success/failure code. If the
* pattern is invalid this will be set to a failure code.
* @stable ICU 2.0
@@ -703,6 +712,9 @@ public:
* on NumberFormat such as createInstance. These factories will
* return the most appropriate sub-class of NumberFormat for a given
* locale.
+ * <p>
+ * <strong>NOTE:</strong> New users are strongly encouraged to use
+ * {@link NumberFormatter} instead of DecimalFormat.
* @param pattern A non-localized pattern string.
* @param status Output param set to success/failure code. If the
* pattern is invalid this will be set to a failure code.
@@ -721,6 +733,9 @@ public:
* createInstance or createCurrencyInstance. If you need only minor adjustments
* to a standard format, you can modify the format returned by
* a NumberFormat factory method.
+ * <p>
+ * <strong>NOTE:</strong> New users are strongly encouraged to use
+ * {@link NumberFormatter} instead of DecimalFormat.
*
* @param pattern a non-localized pattern string
* @param symbolsToAdopt the set of symbols to be used. The caller should not
@@ -826,6 +841,9 @@ public:
* createInstance or createCurrencyInstance. If you need only minor adjustments
* to a standard format, you can modify the format returned by
* a NumberFormat factory method.
+ * <p>
+ * <strong>NOTE:</strong> New users are strongly encouraged to use
+ * {@link NumberFormatter} instead of DecimalFormat.
*
* @param pattern a non-localized pattern string
* @param symbolsToAdopt the set of symbols to be used. The caller should not
@@ -849,6 +867,9 @@ public:
* createInstance or createCurrencyInstance. If you need only minor adjustments
* to a standard format, you can modify the format returned by
* a NumberFormat factory method.
+ * <p>
+ * <strong>NOTE:</strong> New users are strongly encouraged to use
+ * {@link NumberFormatter} instead of DecimalFormat.
*
* @param pattern a non-localized pattern string
* @param symbols the set of symbols to be used
@@ -1964,12 +1985,14 @@ 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
/**
diff --git a/Build/source/libs/icu/icu-src/source/i18n/unicode/dtptngen.h b/Build/source/libs/icu/icu-src/source/i18n/unicode/dtptngen.h
index 5712edbb9ff..feb465e7997 100644
--- a/Build/source/libs/icu/icu-src/source/i18n/unicode/dtptngen.h
+++ b/Build/source/libs/icu/icu-src/source/i18n/unicode/dtptngen.h
@@ -263,14 +263,29 @@ public:
/**
* Getter corresponding to setAppendItemNames. Values below 0 or at or above
- * UDATPG_FIELD_COUNT are illegal arguments.
+ * UDATPG_FIELD_COUNT are illegal arguments. Note: The more general method
+ * for getting date/time field display names is getFieldDisplayName.
*
* @param field such as UDATPG_ERA_FIELD.
* @return name for field
+ * @see getFieldDisplayName
* @stable ICU 3.8
*/
const UnicodeString& getAppendItemName(UDateTimePatternField field) const;
+#ifndef U_HIDE_DRAFT_API
+ /**
+ * The general interface to get a display name for a particular date/time field,
+ * in one of several possible display widths.
+ *
+ * @param field The desired UDateTimePatternField, such as UDATPG_ERA_FIELD.
+ * @param width The desired UDateTimePGDisplayWidth, such as UDATPG_ABBREVIATED.
+ * @return. The display name for field
+ * @draft ICU 61
+ */
+ UnicodeString getFieldDisplayName(UDateTimePatternField field, UDateTimePGDisplayWidth width) const;
+#endif // U_HIDE_DRAFT_API
+
/**
* The DateTimeFormat is a message format pattern used to compose date and
* time patterns. The default pattern in the root locale is "{1} {0}", where
@@ -507,13 +522,17 @@ private:
*/
DateTimePatternGenerator& operator=(const DateTimePatternGenerator& other);
+ // TODO(ticket:13619): re-enable when UDATPG_NARROW no longer in draft mode.
+ // static const int32_t UDATPG_WIDTH_COUNT = UDATPG_NARROW + 1;
+
Locale pLocale; // pattern locale
FormatParser *fp;
DateTimeMatcher* dtMatcher;
DistanceInfo *distanceInfo;
PatternMap *patternMap;
UnicodeString appendItemFormats[UDATPG_FIELD_COUNT];
- UnicodeString appendItemNames[UDATPG_FIELD_COUNT];
+ // TODO(ticket:13619): [3] -> UDATPG_WIDTH_COUNT
+ UnicodeString fieldDisplayNames[UDATPG_FIELD_COUNT][3];
UnicodeString dateTimeFormat;
UnicodeString decimal;
DateTimeMatcher *skipMatcher;
@@ -543,8 +562,11 @@ private:
void setDateTimeFromCalendar(const Locale& locale, UErrorCode& status);
void setDecimalSymbols(const Locale& locale, UErrorCode& status);
UDateTimePatternField getAppendFormatNumber(const char* field) const;
- UDateTimePatternField getAppendNameNumber(const char* field) const;
- UnicodeString& getMutableAppendItemName(UDateTimePatternField field);
+#ifndef U_HIDE_DRAFT_API
+ UDateTimePatternField getFieldAndWidthIndices(const char* key, UDateTimePGDisplayWidth* widthP) const;
+ void setFieldDisplayName(UDateTimePatternField field, UDateTimePGDisplayWidth width, const UnicodeString& value);
+ UnicodeString& getMutableFieldDisplayName(UDateTimePatternField field, UDateTimePGDisplayWidth width);
+#endif // U_HIDE_DRAFT_API
void getAppendName(UDateTimePatternField field, UnicodeString& value);
UnicodeString mapSkeletonMetacharacters(const UnicodeString& patternForm, int32_t* flags, UErrorCode& status);
int32_t getCanonicalIndex(const UnicodeString& field);
diff --git a/Build/source/libs/icu/icu-src/source/i18n/unicode/measfmt.h b/Build/source/libs/icu/icu-src/source/i18n/unicode/measfmt.h
index 156bb81b544..00f2d47a004 100644
--- a/Build/source/libs/icu/icu-src/source/i18n/unicode/measfmt.h
+++ b/Build/source/libs/icu/icu-src/source/i18n/unicode/measfmt.h
@@ -22,7 +22,7 @@
/**
* \file
- * \brief C++ API: Formatter for measure objects.
+ * \brief C++ API: Compatibility APIs for measure formatting.
*/
/**
@@ -87,8 +87,9 @@ class ListFormatter;
class DateFormat;
/**
- *
- * A formatter for measure objects.
+ * <p><strong>IMPORTANT:</strong> New users are strongly encouraged to see if
+ * numberformatter.h fits their use case. Although not deprecated, this header
+ * is provided for backwards compatibility only.
*
* @see Format
* @author Alan Liu
@@ -101,6 +102,9 @@ class U_I18N_API MeasureFormat : public Format {
/**
* Constructor.
+ * <p>
+ * <strong>NOTE:</strong> New users are strongly encouraged to use
+ * {@link NumberFormatter} instead of NumberFormat.
* @stable ICU 53
*/
MeasureFormat(
@@ -108,6 +112,9 @@ class U_I18N_API MeasureFormat : public Format {
/**
* Constructor.
+ * <p>
+ * <strong>NOTE:</strong> New users are strongly encouraged to use
+ * {@link NumberFormatter} instead of NumberFormat.
* @stable ICU 53
*/
MeasureFormat(
@@ -227,6 +234,9 @@ class U_I18N_API MeasureFormat : public Format {
/**
* Return a formatter for CurrencyAmount objects in the given
* locale.
+ * <p>
+ * <strong>NOTE:</strong> New users are strongly encouraged to use
+ * {@link NumberFormatter} instead of NumberFormat.
* @param locale desired locale
* @param ec input-output error code
* @return a formatter object, or NULL upon error
@@ -238,6 +248,9 @@ class U_I18N_API MeasureFormat : public Format {
/**
* Return a formatter for CurrencyAmount objects in the default
* locale.
+ * <p>
+ * <strong>NOTE:</strong> New users are strongly encouraged to use
+ * {@link NumberFormatter} instead of NumberFormat.
* @param ec input-output error code
* @return a formatter object, or NULL upon error
* @stable ICU 3.0
diff --git a/Build/source/libs/icu/icu-src/source/i18n/unicode/measunit.h b/Build/source/libs/icu/icu-src/source/i18n/unicode/measunit.h
index 4140ae3679f..955972440f9 100644
--- a/Build/source/libs/icu/icu-src/source/i18n/unicode/measunit.h
+++ b/Build/source/libs/icu/icu-src/source/i18n/unicode/measunit.h
@@ -196,8 +196,8 @@ class U_I18N_API MeasureUnit: public UObject {
* ICU use only.
* @internal
*/
- static MeasureUnit *resolveUnitPerUnit(
- const MeasureUnit &unit, const MeasureUnit &perUnit);
+ static MeasureUnit resolveUnitPerUnit(
+ const MeasureUnit &unit, const MeasureUnit &perUnit, bool* isResolved);
#endif /* U_HIDE_INTERNAL_API */
// All code between the "Start generated createXXX methods" comment and
@@ -832,15 +832,13 @@ class U_I18N_API MeasureUnit: public UObject {
*/
static MeasureUnit *createPicometer(UErrorCode &status);
-#ifndef U_HIDE_DRAFT_API
/**
* Returns unit of length: point.
* Caller owns returned value and must free it.
* @param status ICU error code.
- * @draft ICU 59
+ * @stable ICU 59
*/
static MeasureUnit *createPoint(UErrorCode &status);
-#endif /* U_HIDE_DRAFT_API */
/**
* Returns unit of length: yard.
diff --git a/Build/source/libs/icu/icu-src/source/i18n/unicode/nounit.h b/Build/source/libs/icu/icu-src/source/i18n/unicode/nounit.h
index 04fc84b33aa..290e77e8806 100644
--- a/Build/source/libs/icu/icu-src/source/i18n/unicode/nounit.h
+++ b/Build/source/libs/icu/icu-src/source/i18n/unicode/nounit.h
@@ -10,17 +10,17 @@
#ifndef __NOUNIT_H__
#define __NOUNIT_H__
+#include "unicode/utypes.h"
+
+#if !UCONFIG_NO_FORMATTING
+
+#include "unicode/measunit.h"
/**
* \file
* \brief C++ API: units for percent and permille
*/
-
-#include "unicode/measunit.h"
-
-#if !UCONFIG_NO_FORMATTING
-
U_NAMESPACE_BEGIN
#ifndef U_HIDE_DRAFT_API
diff --git a/Build/source/libs/icu/icu-src/source/i18n/unicode/numberformatter.h b/Build/source/libs/icu/icu-src/source/i18n/unicode/numberformatter.h
index 4a11c2f9157..3fbb33cceea 100644
--- a/Build/source/libs/icu/icu-src/source/i18n/unicode/numberformatter.h
+++ b/Build/source/libs/icu/icu-src/source/i18n/unicode/numberformatter.h
@@ -88,10 +88,6 @@
* </ul>
*
* <p>
- * * The narrow format for currencies is not currently supported; this is a known issue that will be fixed in a
- * future version. See #11666 for more information.
- *
- * <p>
* This enum is similar to {@link com.ibm.icu.text.MeasureFormat.FormatWidth}.
*
* @draft ICU 60
@@ -155,27 +151,122 @@ typedef enum UNumberUnitWidth {
*
* @draft ICU 60
*/
- UNUM_UNIT_WIDTH_HIDDEN,
+ 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 how to denote positive and negative numbers. Example outputs when formatting 123 and -123 in
- * <em>en-US</em>:
+ * 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 <em>en-IN</em>:
+ *
+ * <ul>
+ * <li>OFF: 1234 and 12345
+ * <li>MIN2: 1234 and 12,34,567
+ * <li>AUTO: 1,234 and 12,34,567
+ * <li>ON_ALIGNED: 1,234 and 12,34,567
+ * <li>THOUSANDS: 1,234 and 1,234,567
+ * </ul>
*
* <p>
+ * 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.
+ *
+ * <p>
+ * 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 <em>minimum of two digits</em> before the first separator).
+ *
+ * <p>
+ * 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).
+ *
+ * <p>
+ * 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.
+ *
+ * <p>
+ * 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).
+ *
+ * <p>
+ * 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.
+ *
+ * <p>
+ * 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.
+ *
+ * <p>
+ * 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 <em>en-US</em>:
+ *
* <ul>
- * <li>AUTO: "123", "-123"
- * <li>ALWAYS: "+123", "-123"
- * <li>NEVER: "123", "123"
- * <li>ACCOUNTING: "$123", "($123)"
- * <li>ACCOUNTING_ALWAYS: "+$123", "($123)"
+ * <li>AUTO: "123", "0", and "-123"
+ * <li>ALWAYS: "+123", "+0", and "-123"
+ * <li>NEVER: "123", "0", and "123"
+ * <li>ACCOUNTING: "$123", "$0", and "($123)"
+ * <li>ACCOUNTING_ALWAYS: "+$123", "+$0", and "($123)"
+ * <li>EXCEPT_ZERO: "+123", "0", and "-123"
+ * <li>ACCOUNTING_EXCEPT_ZERO: "+$123", "$0", and "($123)"
* </ul>
*
* <p>
@@ -190,21 +281,22 @@ typedef enum UNumberSignDisplay {
*
* @draft ICU 60
*/
- UNUM_SIGN_AUTO,
+ UNUM_SIGN_AUTO,
/**
- * Show the minus sign on negative numbers and the plus sign on positive numbers.
+ * 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,
+ UNUM_SIGN_ALWAYS,
/**
* Do not show the sign on positive or negative numbers.
*
* @draft ICU 60
*/
- UNUM_SIGN_NEVER,
+ UNUM_SIGN_NEVER,
/**
* Use the locale-dependent accounting format on negative numbers, and do not show the sign on positive numbers.
@@ -220,22 +312,44 @@ typedef enum UNumberSignDisplay {
*
* @draft ICU 60
*/
- UNUM_SIGN_ACCOUNTING,
+ UNUM_SIGN_ACCOUNTING,
/**
- * Use the locale-dependent accounting format on negative numbers, and show the plus sign on positive numbers.
- * For more information on the accounting format, see the ACCOUNTING sign display strategy.
+ * 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,
+ 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
+ UNUM_SIGN_COUNT
+#endif // U_HIDE_INTERNAL_API
} UNumberSignDisplay;
/**
@@ -261,14 +375,17 @@ typedef enum UNumberDecimalSeparatorDisplay {
*
* @draft ICU 60
*/
- UNUM_DECIMAL_SEPARATOR_ALWAYS,
+ 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
@@ -283,11 +400,27 @@ class Rounder;
class FractionRounder;
class CurrencyRounder;
class IncrementRounder;
-class Grouper;
class IntegerWidth;
namespace impl {
+#ifndef U_HIDE_INTERNAL_API
+/**
+ * Datatype for minimum/maximum fraction digits. Must be able to hold kMaxIntFracSig.
+ *
+ * @internal
+ */
+typedef int16_t digits_t;
+
+/**
+ * Use a default threshold of 3. This means that the third time .format() is called, the data structures get built
+ * using the "safe" code path. The first two calls to .format() will trigger the unsafe code path.
+ *
+ * @internal
+ */
+static constexpr int32_t DEFAULT_THRESHOLD = 3;
+#endif // U_HIDE_INTERNAL_API
+
// Forward declarations:
class Padder;
struct MacroProps;
@@ -471,7 +604,7 @@ class U_I18N_API Notation : public UMemory {
struct ScientificSettings {
int8_t fEngineeringInterval;
bool fRequireMinInt;
- int8_t fMinExponentDigits;
+ impl::digits_t fMinExponentDigits;
UNumberSignDisplay fExponentSignDisplay;
} scientific;
@@ -786,14 +919,14 @@ class U_I18N_API Rounder : public UMemory {
union RounderUnion {
struct FractionSignificantSettings {
// For RND_FRACTION, RND_SIGNIFICANT, and RND_FRACTION_SIGNIFICANT
- int8_t fMinFrac;
- int8_t fMaxFrac;
- int8_t fMinSig;
- int8_t fMaxSig;
+ impl::digits_t fMinFrac;
+ impl::digits_t fMaxFrac;
+ impl::digits_t fMinSig;
+ impl::digits_t fMaxSig;
} fracSig;
struct IncrementSettings {
double fIncrement;
- int32_t fMinFrac;
+ impl::digits_t fMinFrac;
} increment; // For RND_INCREMENT
UCurrencyUsage currencyUsage; // For RND_CURRENCY
UErrorCode errorCode; // For RND_ERROR
@@ -836,6 +969,20 @@ class U_I18N_API Rounder : public UMemory {
/** Version of {@link #apply} that obeys minInt constraints. Used for scientific notation compatibility mode. */
void apply(impl::DecimalQuantity &value, int32_t minInt, UErrorCode status);
+ /**
+ * Rounding endpoint used by Engineering and Compact notation. Chooses the most appropriate multiplier (magnitude
+ * adjustment), applies the adjustment, rounds, and returns the chosen multiplier.
+ *
+ * <p>
+ * 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);
@@ -1003,53 +1150,6 @@ class U_I18N_API IncrementRounder : public Rounder {
};
/**
- * @internal This API is a technical preview. It is likely to change in an upcoming release.
- */
-class U_I18N_API Grouper : public UMemory {
- public:
- /**
- * @internal This API is a technical preview. It is likely to change in an upcoming release.
- */
- static Grouper defaults();
-
- /**
- * @internal This API is a technical preview. It is likely to change in an upcoming release.
- */
- static Grouper minTwoDigits();
-
- /**
- * @internal This API is a technical preview. It is likely to change in an upcoming release.
- */
- static Grouper none();
-
- private:
- int8_t fGrouping1; // -3 means "bogus"; -2 means "needs locale data"; -1 means "no grouping"
- int8_t fGrouping2;
- bool fMin2;
-
- Grouper(int8_t grouping1, int8_t grouping2, bool min2)
- : fGrouping1(grouping1), fGrouping2(grouping2), fMin2(min2) {}
-
- Grouper() : fGrouping1(-3) {};
-
- bool isBogus() const {
- return fGrouping1 == -3;
- }
-
- /** NON-CONST: mutates the current instance. */
- void setLocaleData(const impl::ParsedPatternInfo &patternInfo);
-
- bool groupAtPosition(int32_t position, const impl::DecimalQuantity &value) 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;
-};
-
-/**
* A class that defines the strategy for padding and truncating integers before the decimal separator.
*
* <p>
@@ -1080,7 +1180,8 @@ class U_I18N_API IntegerWidth : public UMemory {
* For example, with maxInt=3, the number 1234 will get printed as "234".
*
* @param maxInt
- * The maximum number of places before the decimal separator.
+ * The maximum number of places before the decimal separator. maxInt == -1 means no
+ * truncation.
* @return An IntegerWidth for passing to the NumberFormatter integerWidth() setter.
* @draft ICU 60
* @see NumberFormatter
@@ -1090,14 +1191,14 @@ class U_I18N_API IntegerWidth : public UMemory {
private:
union {
struct {
- int8_t fMinInt;
- int8_t fMaxInt;
+ impl::digits_t fMinInt;
+ impl::digits_t fMaxInt;
} minMaxInt;
UErrorCode errorCode;
} fUnion;
bool fHasError = false;
- IntegerWidth(int8_t minInt, int8_t maxInt);
+ IntegerWidth(impl::digits_t minInt, impl::digits_t maxInt);
IntegerWidth(UErrorCode errorCode) { // NOLINT
fUnion.errorCode = errorCode;
@@ -1132,14 +1233,7 @@ class U_I18N_API IntegerWidth : public UMemory {
namespace impl {
-/**
- * Use a default threshold of 3. This means that the third time .format() is called, the data structures get built
- * using the "safe" code path. The first two calls to .format() will trigger the unsafe code path.
- *
- * @internal
- */
-static constexpr int32_t DEFAULT_THRESHOLD = 3;
-
+// Do not enclose entire SymbolsWrapper with #ifndef U_HIDE_INTERNAL_API, needed for a protected field
/** @internal */
class U_I18N_API SymbolsWrapper : public UMemory {
public:
@@ -1155,6 +1249,7 @@ class U_I18N_API SymbolsWrapper : public UMemory {
/** @internal */
SymbolsWrapper &operator=(const SymbolsWrapper &other);
+#ifndef U_HIDE_INTERNAL_API
/**
* The provided object is copied, but we do not adopt it.
* @internal
@@ -1202,6 +1297,7 @@ class U_I18N_API SymbolsWrapper : public UMemory {
}
return FALSE;
}
+#endif // U_HIDE_INTERNAL_API
private:
enum SymbolsPointerType {
@@ -1218,14 +1314,72 @@ class U_I18N_API SymbolsWrapper : public UMemory {
void doCleanup();
};
+// Do not enclose entire Grouper with #ifndef U_HIDE_INTERNAL_API, needed for a protected field
+/** @internal */
+class U_I18N_API Grouper : public UMemory {
+ public:
+#ifndef U_HIDE_INTERNAL_API
+ /** @internal */
+ static Grouper forStrategy(UGroupingStrategy grouping);
+
+ // Future: static Grouper forProperties(DecimalFormatProperties& properties);
+
+ /** @internal */
+ Grouper(int16_t grouping1, int16_t grouping2, int16_t minGrouping)
+ : fGrouping1(grouping1), fGrouping2(grouping2), fMinGrouping(minGrouping) {}
+#endif // U_HIDE_INTERNAL_API
+
+ private:
+ /**
+ * The grouping sizes, with the following special values:
+ * <ul>
+ * <li>-1 = no grouping
+ * <li>-2 = needs locale data
+ * <li>-4 = fall back to Western grouping if not in locale
+ * </ul>
+ */
+ int16_t fGrouping1;
+ int16_t fGrouping2;
+
+ /**
+ * The minimum gropuing size, with the following special values:
+ * <ul>
+ * <li>-2 = needs locale data
+ * <li>-3 = no less than 2
+ * </ul>
+ */
+ int16_t fMinGrouping;
+
+ Grouper() : fGrouping1(-3) {};
+
+ bool isBogus() const {
+ return fGrouping1 == -3;
+ }
+
+ /** NON-CONST: mutates the current instance. */
+ void setLocaleData(const impl::ParsedPatternInfo &patternInfo, const Locale& locale);
+
+ bool groupAtPosition(int32_t position, const impl::DecimalQuantity &value) const;
+
+ // To allow MacroProps/MicroProps to initialize empty instances:
+ friend struct MacroProps;
+ friend struct MicroProps;
+
+ // To allow NumberFormatterImpl to access isBogus() and perform other operations:
+ friend class NumberFormatterImpl;
+};
+
+// Do not enclose entire Padder with #ifndef U_HIDE_INTERNAL_API, needed for a protected field
/** @internal */
class U_I18N_API Padder : public UMemory {
public:
+#ifndef U_HIDE_INTERNAL_API
/** @internal */
static Padder none();
/** @internal */
static Padder codePoints(UChar32 cp, int32_t targetWidth, UNumberFormatPadPosition position);
+#endif // U_HIDE_INTERNAL_API
private:
UChar32 fWidth; // -3 = error; -2 = bogus; -1 = no padding
@@ -1275,6 +1429,7 @@ class U_I18N_API Padder : public UMemory {
friend class impl::NumberFormatterImpl;
};
+// Do not enclose entire MacroProps with #ifndef U_HIDE_INTERNAL_API, needed for a protected field
/** @internal */
struct U_I18N_API MacroProps : public UMemory {
/** @internal */
@@ -1284,6 +1439,9 @@ struct U_I18N_API MacroProps : public UMemory {
MeasureUnit unit; // = NoUnit::base();
/** @internal */
+ MeasureUnit perUnit; // = NoUnit::base();
+
+ /** @internal */
Rounder rounder; // = Rounder(); (bogus)
/** @internal */
@@ -1375,29 +1533,30 @@ class U_I18N_API NumberFormatterSettings {
* <li>Percent: "12.3%"
* </ul>
*
- * <p>
* All units will be properly localized with locale data, and all units are compatible with notation styles,
* rounding strategies, and other number formatter settings.
*
- * <p>
- * Pass this method any instance of {@link MeasureUnit}. For units of measure:
+ * Pass this method any instance of {@link MeasureUnit}. For units of measure (which often involve the
+ * factory methods that return a pointer):
*
* <pre>
- * NumberFormatter.with().adoptUnit(MeasureUnit::createMeter(status))
+ * NumberFormatter::with().adoptUnit(MeasureUnit::createMeter(status))
* </pre>
*
* Currency:
*
* <pre>
- * NumberFormatter.with()::unit(CurrencyUnit(u"USD", status))
+ * NumberFormatter::with().unit(CurrencyUnit(u"USD", status))
* </pre>
*
* Percent:
*
* <pre>
- * NumberFormatter.with()::unit(NoUnit.percent())
+ * NumberFormatter::with().unit(NoUnit.percent())
* </pre>
*
+ * See {@link #perUnit} for information on how to format strings like "5 meters per second".
+ *
* The default is to render without units (equivalent to NoUnit.base()).
*
* @param unit
@@ -1406,22 +1565,65 @@ class U_I18N_API NumberFormatterSettings {
* @see MeasureUnit
* @see Currency
* @see NoUnit
+ * @see #perUnit
* @draft ICU 60
*/
Derived unit(const icu::MeasureUnit &unit) const;
/**
* Like unit(), but takes ownership of a pointer. Convenient for use with the MeasureFormat factory
- * methods, which return pointers that need ownership.
+ * methods, which return pointers that need ownership. Example:
+ *
+ * <pre>
+ * NumberFormatter::with().adoptUnit(MeasureUnit::createMeter(status))
+ * </pre>
*
* @param unit
- * The unit to render.
+ * The unit to render.
* @return The fluent chain.
* @see #unit
* @see MeasureUnit
* @draft ICU 60
*/
- Derived adoptUnit(const icu::MeasureUnit *unit) const;
+ Derived adoptUnit(icu::MeasureUnit *unit) const;
+
+ /**
+ * Sets a unit to be used in the denominator. For example, to format "3 m/s", pass METER to the unit and SECOND to
+ * the perUnit.
+ *
+ * Pass this method any instance of {@link MeasureUnit}. Since MeasureUnit factory methods return pointers, the
+ * {@link #adoptPerUnit} version of this method is often more useful.
+ *
+ * The default is not to display any unit in the denominator.
+ *
+ * If a per-unit is specified without a primary unit via {@link #unit}, the behavior is undefined.
+ *
+ * @param perUnit
+ * The unit to render in the denominator.
+ * @return The fluent chain
+ * @see #unit
+ * @draft ICU 61
+ */
+ Derived perUnit(const icu::MeasureUnit &perUnit) const;
+
+ /**
+ * Like perUnit(), but takes ownership of a pointer. Convenient for use with the MeasureFormat factory
+ * methods, which return pointers that need ownership. Example:
+ *
+ * <pre>
+ * NumberFormatter::with()
+ * .adoptUnit(MeasureUnit::createMeter(status))
+ * .adoptPerUnit(MeasureUnit::createSecond(status))
+ * </pre>
+ *
+ * @param perUnit
+ * The unit to render in the denominator.
+ * @return The fluent chain.
+ * @see #perUnit
+ * @see MeasureUnit
+ * @draft ICU 61
+ */
+ Derived adoptPerUnit(icu::MeasureUnit *perUnit) const;
/**
* Specifies the rounding strategy to use when formatting numbers.
@@ -1456,8 +1658,6 @@ class U_I18N_API NumberFormatterSettings {
*/
Derived rounding(const Rounder &rounder) const;
-#ifndef U_HIDE_INTERNAL_API
-
/**
* Specifies the grouping strategy to use when formatting numbers.
*
@@ -1471,25 +1671,21 @@ class U_I18N_API NumberFormatterSettings {
* The exact grouping widths will be chosen based on the locale.
*
* <p>
- * Pass this method the return value of one of the factory methods on {@link Grouper}. For example:
+ * Pass this method an element from the {@link UGroupingStrategy} enum. For example:
*
* <pre>
- * NumberFormatter::with().grouping(Grouper::min2())
+ * NumberFormatter::with().grouping(UNUM_GROUPING_MIN2)
* </pre>
*
- * The default is to perform grouping without concern for the minimum grouping digits.
+ * The default is to perform grouping according to locale data; most locales, but not all locales,
+ * enable it by default.
*
- * @param grouper
+ * @param strategy
* The grouping strategy to use.
* @return The fluent chain.
- * @see Grouper
- * @see Notation
- * @internal
- * @internal ICU 60: This API is technical preview.
+ * @draft ICU 61
*/
- Derived grouping(const Grouper &grouper) const;
-
-#endif /* U_HIDE_INTERNAL_API */
+ Derived grouping(const UGroupingStrategy &strategy) const;
/**
* Specifies the minimum and maximum number of digits to render before the decimal mark.
@@ -1592,7 +1788,7 @@ class U_I18N_API NumberFormatterSettings {
* @see NumberingSystem
* @draft ICU 60
*/
- Derived adoptSymbols(const NumberingSystem *symbols) const;
+ Derived adoptSymbols(NumberingSystem *symbols) const;
/**
* Sets the width of the unit (measure unit or currency). Most common values:
diff --git a/Build/source/libs/icu/icu-src/source/i18n/unicode/numfmt.h b/Build/source/libs/icu/icu-src/source/i18n/unicode/numfmt.h
index 68be021055b..39379851b0f 100644
--- a/Build/source/libs/icu/icu-src/source/i18n/unicode/numfmt.h
+++ b/Build/source/libs/icu/icu-src/source/i18n/unicode/numfmt.h
@@ -28,7 +28,7 @@
/**
* \file
- * \brief C++ API: Abstract base class for all number formats.
+ * \brief C++ API: Compatibility APIs for number formatting.
*/
#if !UCONFIG_NO_FORMATTING
@@ -53,16 +53,16 @@ class StringEnumeration;
#endif
/**
+ * <p><strong>IMPORTANT:</strong> New users are strongly encouraged to see if
+ * numberformatter.h fits their use case. Although not deprecated, this header
+ * is provided for backwards compatibility only.
+ * <hr/>
*
* Abstract base class for all number formats. Provides interface for
* formatting and parsing a number. Also provides methods for
* determining which locales have number formats, and what their names
* are.
*
- * <p><strong>NOTE:</strong> Starting in ICU 60, there is a new set of APIs for localized number
- * formatting that are designed to be an improvement over DecimalFormat. New users are discouraged
- * from using DecimalFormat. For more information, see numberformatter.h.
- *
* \headerfile unicode/numfmt.h "unicode/numfmt.h"
* <P>
* NumberFormat helps you to format and parse numbers for any locale.
@@ -708,6 +708,9 @@ public:
/**
* Create a default style NumberFormat for the current default locale.
* The default formatting style is locale dependent.
+ * <p>
+ * <strong>NOTE:</strong> New users are strongly encouraged to use
+ * {@link NumberFormatter} instead of NumberFormat.
* @stable ICU 2.0
*/
static NumberFormat* U_EXPORT2 createInstance(UErrorCode&);
@@ -716,6 +719,9 @@ public:
* Create a default style NumberFormat for the specified locale.
* The default formatting style is locale dependent.
* @param inLocale the given locale.
+ * <p>
+ * <strong>NOTE:</strong> New users are strongly encouraged to use
+ * {@link NumberFormatter} instead of NumberFormat.
* @stable ICU 2.0
*/
static NumberFormat* U_EXPORT2 createInstance(const Locale& inLocale,
@@ -723,6 +729,9 @@ public:
/**
* Create a specific style NumberFormat for the specified locale.
+ * <p>
+ * <strong>NOTE:</strong> New users are strongly encouraged to use
+ * {@link NumberFormatter} instead of NumberFormat.
* @param desiredLocale the given locale.
* @param style the given style.
* @param errorCode Output param filled with success/failure status.
@@ -759,12 +768,18 @@ public:
/**
* Returns a currency format for the current default locale.
+ * <p>
+ * <strong>NOTE:</strong> New users are strongly encouraged to use
+ * {@link NumberFormatter} instead of NumberFormat.
* @stable ICU 2.0
*/
static NumberFormat* U_EXPORT2 createCurrencyInstance(UErrorCode&);
/**
* Returns a currency format for the specified locale.
+ * <p>
+ * <strong>NOTE:</strong> New users are strongly encouraged to use
+ * {@link NumberFormatter} instead of NumberFormat.
* @param inLocale the given locale.
* @stable ICU 2.0
*/
@@ -773,12 +788,18 @@ public:
/**
* Returns a percentage format for the current default locale.
+ * <p>
+ * <strong>NOTE:</strong> New users are strongly encouraged to use
+ * {@link NumberFormatter} instead of NumberFormat.
* @stable ICU 2.0
*/
static NumberFormat* U_EXPORT2 createPercentInstance(UErrorCode&);
/**
* Returns a percentage format for the specified locale.
+ * <p>
+ * <strong>NOTE:</strong> New users are strongly encouraged to use
+ * {@link NumberFormatter} instead of NumberFormat.
* @param inLocale the given locale.
* @stable ICU 2.0
*/
@@ -787,12 +808,18 @@ public:
/**
* Returns a scientific format for the current default locale.
+ * <p>
+ * <strong>NOTE:</strong> New users are strongly encouraged to use
+ * {@link NumberFormatter} instead of NumberFormat.
* @stable ICU 2.0
*/
static NumberFormat* U_EXPORT2 createScientificInstance(UErrorCode&);
/**
* Returns a scientific format for the specified locale.
+ * <p>
+ * <strong>NOTE:</strong> New users are strongly encouraged to use
+ * {@link NumberFormatter} instead of NumberFormat.
* @param inLocale the given locale.
* @stable ICU 2.0
*/
diff --git a/Build/source/libs/icu/icu-src/source/i18n/unicode/simpletz.h b/Build/source/libs/icu/icu-src/source/i18n/unicode/simpletz.h
index 5b802632b0d..3ae08077e3b 100644
--- a/Build/source/libs/icu/icu-src/source/i18n/unicode/simpletz.h
+++ b/Build/source/libs/icu/icu-src/source/i18n/unicode/simpletz.h
@@ -647,7 +647,8 @@ public:
* Sets the amount of time in ms that the clock is advanced during DST.
* @param millisSavedDuringDST the number of milliseconds the time is
* advanced with respect to standard time when the daylight savings rules
- * are in effect. A positive number, typically one hour (3600000).
+ * are in effect. Typically one hour (+3600000). The amount could be negative,
+ * but not 0.
* @param status An UErrorCode to receive the status.
* @stable ICU 2.0
*/
@@ -657,7 +658,8 @@ public:
* Returns the amount of time in ms that the clock is advanced during DST.
* @return the number of milliseconds the time is
* advanced with respect to standard time when the daylight savings rules
- * are in effect. A positive number, typically one hour (3600000).
+ * are in effect. Typically one hour (+3600000). The amount could be negative,
+ * but not 0.
* @stable ICU 2.0
*/
virtual int32_t getDSTSavings(void) const;
diff --git a/Build/source/libs/icu/icu-src/source/i18n/unicode/udatpg.h b/Build/source/libs/icu/icu-src/source/i18n/unicode/udatpg.h
index 76baa3da589..beae756d87d 100644
--- a/Build/source/libs/icu/icu-src/source/i18n/unicode/udatpg.h
+++ b/Build/source/libs/icu/icu-src/source/i18n/unicode/udatpg.h
@@ -95,6 +95,21 @@ typedef enum UDateTimePatternField {
UDATPG_FIELD_COUNT
} UDateTimePatternField;
+#ifndef U_HIDE_DRAFT_API
+/**
+ * Field display name width constants for udatpg_getFieldDisplayName().
+ * @draft ICU 61
+ */
+typedef enum UDateTimePGDisplayWidth {
+ /** @draft ICU 61 */
+ UDATPG_WIDE,
+ /** @draft ICU 61 */
+ UDATPG_ABBREVIATED,
+ /** @draft ICU 61 */
+ UDATPG_NARROW
+} UDateTimePGDisplayWidth;
+#endif // U_HIDE_DRAFT_API
+
/**
* Masks to control forcing the length of specified fields in the returned
* pattern to match those in the skeleton (when this would not happen
@@ -410,12 +425,14 @@ udatpg_setAppendItemName(UDateTimePatternGenerator *dtpg,
/**
* Getter corresponding to setAppendItemNames. Values below 0 or at or above
- * UDATPG_FIELD_COUNT are illegal arguments.
+ * UDATPG_FIELD_COUNT are illegal arguments. Note: The more general function
+ * for getting date/time field display names is udatpg_getFieldDisplayName.
*
* @param dtpg a pointer to UDateTimePatternGenerator.
* @param field UDateTimePatternField, such as UDATPG_ERA_FIELD
* @param pLength A pointer that will receive the length of the name for field.
* @return name for field
+ * @see udatpg_getFieldDisplayName
* @stable ICU 3.8
*/
U_STABLE const UChar * U_EXPORT2
@@ -423,6 +440,40 @@ udatpg_getAppendItemName(const UDateTimePatternGenerator *dtpg,
UDateTimePatternField field,
int32_t *pLength);
+#ifndef U_HIDE_DRAFT_API
+/**
+ * The general interface to get a display name for a particular date/time field,
+ * in one of several possible display widths.
+ *
+ * @param dtpg
+ * A pointer to the UDateTimePatternGenerator object with the localized
+ * display names.
+ * @param field
+ * The desired UDateTimePatternField, such as UDATPG_ERA_FIELD.
+ * @param width
+ * The desired UDateTimePGDisplayWidth, such as UDATPG_ABBREVIATED.
+ * @param fieldName
+ * A pointer to a buffer to receive the NULL-terminated display name. If the name
+ * fits into fieldName but cannot be NULL-terminated (length == capacity) then
+ * the error code is set to U_STRING_NOT_TERMINATED_WARNING. If the name doesn't
+ * fit into fieldName then the error code is set to U_BUFFER_OVERFLOW_ERROR.
+ * @param capacity
+ * The size of fieldName (in UChars).
+ * @param pErrorCode
+ * A pointer to a UErrorCode to receive any errors
+ * @return
+ * The full length of the name; if greater than capacity, fieldName contains a
+ * truncated result.
+ * @draft ICU 61
+ */
+U_DRAFT int32_t U_EXPORT2
+udatpg_getFieldDisplayName(const UDateTimePatternGenerator *dtpg,
+ UDateTimePatternField field,
+ UDateTimePGDisplayWidth width,
+ UChar *fieldName, int32_t capacity,
+ UErrorCode *pErrorCode);
+#endif // U_HIDE_DRAFT_API
+
/**
* The DateTimeFormat is a message format pattern used to compose date and
* time patterns. The default pattern in the root locale is "{1} {0}", where
diff --git a/Build/source/libs/icu/icu-src/source/i18n/unicode/unum.h b/Build/source/libs/icu/icu-src/source/i18n/unicode/unum.h
index 2ab09b5d0d4..ff251ff2699 100644
--- a/Build/source/libs/icu/icu-src/source/i18n/unicode/unum.h
+++ b/Build/source/libs/icu/icu-src/source/i18n/unicode/unum.h
@@ -32,6 +32,9 @@
* \brief C API: NumberFormat
*
* <h2> Number Format C API </h2>
+ *
+ * <p><strong>IMPORTANT:</strong> New users with C++ capabilities are
+ * strongly encouraged to see if numberformatter.h fits their use case.
*
* Number Format C API Provides functions for
* formatting and parsing a number. Also provides methods for
@@ -559,7 +562,6 @@ unum_formatDouble( const UNumberFormat* fmt,
UFieldPosition *pos, /* 0 if ignore */
UErrorCode* status);
-#ifndef U_HIDE_DRAFT_API
/**
* Format a double using a UNumberFormat according to the UNumberFormat's locale,
* and initialize a UFieldPositionIterator that enumerates the subcomponents of
@@ -600,9 +602,9 @@ unum_formatDouble( const UNumberFormat* fmt,
* @see unum_parseDouble
* @see UFieldPositionIterator
* @see UNumberFormatFields
-* @draft ICU 59
+* @stable ICU 59
*/
-U_DRAFT int32_t U_EXPORT2
+U_STABLE int32_t U_EXPORT2
unum_formatDoubleForFields(const UNumberFormat* format,
double number,
UChar* result,
@@ -610,7 +612,6 @@ unum_formatDoubleForFields(const UNumberFormat* format,
UFieldPositionIterator* fpositer,
UErrorCode* status);
-#endif /* U_HIDE_DRAFT_API */
/**
* Format a decimal number using a UNumberFormat.
diff --git a/Build/source/libs/icu/icu-src/source/i18n/unicode/upluralrules.h b/Build/source/libs/icu/icu-src/source/i18n/unicode/upluralrules.h
index 99d93a4e051..690846bc89c 100644
--- a/Build/source/libs/icu/icu-src/source/i18n/unicode/upluralrules.h
+++ b/Build/source/libs/icu/icu-src/source/i18n/unicode/upluralrules.h
@@ -175,7 +175,6 @@ uplrules_selectWithFormat(const UPluralRules *uplrules,
#endif /* U_HIDE_INTERNAL_API */
-#ifndef U_HIDE_DRAFT_API
/**
* Creates a string enumeration of all plural rule keywords used in this
* UPluralRules object. The rule "other" is always present by default.
@@ -184,12 +183,11 @@ uplrules_selectWithFormat(const UPluralRules *uplrules,
* @param status A pointer to a UErrorCode to receive any errors.
* @return a string enumeration over plural rule keywords, or NULL
* upon error. The caller is responsible for closing the result.
- * @draft ICU 59
+ * @stable ICU 59
*/
-U_DRAFT UEnumeration* U_EXPORT2
+U_STABLE UEnumeration* U_EXPORT2
uplrules_getKeywords(const UPluralRules *uplrules,
UErrorCode *status);
-#endif /* U_HIDE_DRAFT_API */
#endif /* #if !UCONFIG_NO_FORMATTING */
diff --git a/Build/source/libs/icu/icu-src/source/i18n/unicode/utrans.h b/Build/source/libs/icu/icu-src/source/i18n/unicode/utrans.h
index d0f05cf2b60..697681aef85 100644
--- a/Build/source/libs/icu/icu-src/source/i18n/unicode/utrans.h
+++ b/Build/source/libs/icu/icu-src/source/i18n/unicode/utrans.h
@@ -382,7 +382,7 @@ utrans_openIDs(UErrorCode *pErrorCode);
U_STABLE void U_EXPORT2
utrans_trans(const UTransliterator* trans,
UReplaceable* rep,
- UReplaceableCallbacks* repFunc,
+ const UReplaceableCallbacks* repFunc,
int32_t start,
int32_t* limit,
UErrorCode* status);
@@ -433,7 +433,7 @@ utrans_trans(const UTransliterator* trans,
U_STABLE void U_EXPORT2
utrans_transIncremental(const UTransliterator* trans,
UReplaceable* rep,
- UReplaceableCallbacks* repFunc,
+ const UReplaceableCallbacks* repFunc,
UTransPosition* pos,
UErrorCode* status);
diff --git a/Build/source/libs/icu/icu-src/source/i18n/uregex.cpp b/Build/source/libs/icu/icu-src/source/i18n/uregex.cpp
index 0c26bdf656d..12f36894d71 100644
--- a/Build/source/libs/icu/icu-src/source/i18n/uregex.cpp
+++ b/Build/source/libs/icu/icu-src/source/i18n/uregex.cpp
@@ -1465,8 +1465,10 @@ int32_t RegexCImpl::appendReplacement(RegularExpression *regexp,
int32_t groupNum = 0;
U_ASSERT(c == DOLLARSIGN);
- UChar32 c32;
- U16_GET(replacementText, 0, replIdx, replacementLength, c32);
+ UChar32 c32 = -1;
+ if (replIdx < replacementLength) {
+ U16_GET(replacementText, 0, replIdx, replacementLength, c32);
+ }
if (u_isdigit(c32)) {
int32_t numDigits = 0;
int32_t numCaptureGroups = m->fPattern->fGroupMap->size();
diff --git a/Build/source/libs/icu/icu-src/source/i18n/utrans.cpp b/Build/source/libs/icu/icu-src/source/i18n/utrans.cpp
index 5124833ac33..29013ead125 100644
--- a/Build/source/libs/icu/icu-src/source/i18n/utrans.cpp
+++ b/Build/source/libs/icu/icu-src/source/i18n/utrans.cpp
@@ -41,12 +41,12 @@ U_NAMESPACE_BEGIN
class ReplaceableGlue : public Replaceable {
UReplaceable *rep;
- UReplaceableCallbacks *func;
+ const UReplaceableCallbacks *func;
public:
ReplaceableGlue(UReplaceable *replaceable,
- UReplaceableCallbacks *funcCallback);
+ const UReplaceableCallbacks *funcCallback);
virtual ~ReplaceableGlue();
@@ -88,7 +88,7 @@ protected:
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(ReplaceableGlue)
ReplaceableGlue::ReplaceableGlue(UReplaceable *replaceable,
- UReplaceableCallbacks *funcCallback)
+ const UReplaceableCallbacks *funcCallback)
: Replaceable()
{
this->rep = replaceable;
@@ -398,7 +398,7 @@ utrans_openIDs(UErrorCode *pErrorCode) {
U_CAPI void U_EXPORT2
utrans_trans(const UTransliterator* trans,
UReplaceable* rep,
- UReplaceableCallbacks* repFunc,
+ const UReplaceableCallbacks* repFunc,
int32_t start,
int32_t* limit,
UErrorCode* status) {
@@ -418,7 +418,7 @@ utrans_trans(const UTransliterator* trans,
U_CAPI void U_EXPORT2
utrans_transIncremental(const UTransliterator* trans,
UReplaceable* rep,
- UReplaceableCallbacks* repFunc,
+ const UReplaceableCallbacks* repFunc,
UTransPosition* pos,
UErrorCode* status) {