rules.
+ int32_t distance = trieNext(iter, desired, false);
+ if (distance >= 0) {
+ distance = trieNext(iter, supported, true);
+ }
+ if (distance < 0) {
+ UStringTrieResult result = iter.resetToState64(startState).next(u'*'); // <*, *>
+ U_ASSERT(USTRINGTRIE_HAS_VALUE(result));
+ if (uprv_strcmp(desired, supported) == 0) {
+ distance = 0; // same script
+ } else {
+ distance = iter.getValue();
+ U_ASSERT(distance >= 0);
+ }
+ if (result == USTRINGTRIE_FINAL_VALUE) {
+ distance |= DISTANCE_IS_FINAL;
+ }
+ }
+ return distance;
+}
+
+int32_t LocaleDistance::getRegionPartitionsDistance(
+ BytesTrie &iter, uint64_t startState,
+ const char *desiredPartitions, const char *supportedPartitions, int32_t threshold) {
+ char desired = *desiredPartitions++;
+ char supported = *supportedPartitions++;
+ U_ASSERT(desired != 0 && supported != 0);
+ // See if we have single desired/supported partitions, from NUL-terminated
+ // partition strings without explicit length.
+ bool suppLengthGt1 = *supportedPartitions != 0; // gt1: more than 1 character
+ // equivalent to: if (desLength == 1 && suppLength == 1)
+ if (*desiredPartitions == 0 && !suppLengthGt1) {
+ // Fastpath for single desired/supported partitions.
+ UStringTrieResult result = iter.next(uprv_invCharToAscii(desired) | END_OF_SUBTAG);
+ if (USTRINGTRIE_HAS_NEXT(result)) {
+ result = iter.next(uprv_invCharToAscii(supported) | END_OF_SUBTAG);
+ if (USTRINGTRIE_HAS_VALUE(result)) {
+ return iter.getValue();
+ }
+ }
+ return getFallbackRegionDistance(iter, startState);
+ }
+
+ const char *supportedStart = supportedPartitions - 1; // for restart of inner loop
+ int32_t regionDistance = 0;
+ // Fall back to * only once, not for each pair of partition strings.
+ bool star = false;
+ for (;;) {
+ // Look up each desired-partition string only once,
+ // not for each (desired, supported) pair.
+ UStringTrieResult result = iter.next(uprv_invCharToAscii(desired) | END_OF_SUBTAG);
+ if (USTRINGTRIE_HAS_NEXT(result)) {
+ uint64_t desState = suppLengthGt1 ? iter.getState64() : 0;
+ for (;;) {
+ result = iter.next(uprv_invCharToAscii(supported) | END_OF_SUBTAG);
+ int32_t d;
+ if (USTRINGTRIE_HAS_VALUE(result)) {
+ d = iter.getValue();
+ } else if (star) {
+ d = 0;
+ } else {
+ d = getFallbackRegionDistance(iter, startState);
+ star = true;
+ }
+ if (d >= threshold) {
+ return d;
+ } else if (regionDistance < d) {
+ regionDistance = d;
+ }
+ if ((supported = *supportedPartitions++) != 0) {
+ iter.resetToState64(desState);
+ } else {
+ break;
+ }
+ }
+ } else if (!star) {
+ int32_t d = getFallbackRegionDistance(iter, startState);
+ if (d >= threshold) {
+ return d;
+ } else if (regionDistance < d) {
+ regionDistance = d;
+ }
+ star = true;
+ }
+ if ((desired = *desiredPartitions++) != 0) {
+ iter.resetToState64(startState);
+ supportedPartitions = supportedStart;
+ supported = *supportedPartitions++;
+ } else {
+ break;
+ }
+ }
+ return regionDistance;
+}
+
+int32_t LocaleDistance::getFallbackRegionDistance(BytesTrie &iter, uint64_t startState) {
+#if U_DEBUG
+ UStringTrieResult result =
+#endif
+ iter.resetToState64(startState).next(u'*'); // <*, *>
+ U_ASSERT(USTRINGTRIE_HAS_VALUE(result));
+ int32_t distance = iter.getValue();
+ U_ASSERT(distance >= 0);
+ return distance;
+}
+
+int32_t LocaleDistance::trieNext(BytesTrie &iter, const char *s, bool wantValue) {
+ uint8_t c;
+ if ((c = *s) == 0) {
+ return -1; // no empty subtags in the distance data
+ }
+ for (;;) {
+ c = uprv_invCharToAscii(c);
+ // EBCDIC: If *s is not an invariant character,
+ // then c is now 0 and will simply not match anything, which is harmless.
+ uint8_t next = *++s;
+ if (next != 0) {
+ if (!USTRINGTRIE_HAS_NEXT(iter.next(c))) {
+ return -1;
+ }
+ } else {
+ // last character of this subtag
+ UStringTrieResult result = iter.next(c | END_OF_SUBTAG);
+ if (wantValue) {
+ if (USTRINGTRIE_HAS_VALUE(result)) {
+ int32_t value = iter.getValue();
+ if (result == USTRINGTRIE_FINAL_VALUE) {
+ value |= DISTANCE_IS_FINAL;
+ }
+ return value;
+ }
+ } else {
+ if (USTRINGTRIE_HAS_NEXT(result)) {
+ return 0;
+ }
+ }
+ return -1;
+ }
+ c = next;
+ }
+}
+
+UBool LocaleDistance::isParadigmLSR(const LSR &lsr) const {
+ // Linear search for a very short list (length 6 as of 2019).
+ // If there are many paradigm LSRs we should use a hash set.
+ U_ASSERT(paradigmLSRsLength <= 15);
+ for (int32_t i = 0; i < paradigmLSRsLength; ++i) {
+ if (lsr == paradigmLSRs[i]) { return true; }
+ }
+ return false;
+}
+
+U_NAMESPACE_END
diff -Nru icu-64.2/source/common/locdistance.h icu-65.1/source/common/locdistance.h
--- icu-64.2/source/common/locdistance.h 1970-01-01 00:00:00.000000000 +0000
+++ icu-65.1/source/common/locdistance.h 2019-10-03 11:16:41.000000000 +0000
@@ -0,0 +1,109 @@
+// © 2019 and later: Unicode, Inc. and others.
+// License & terms of use: http://www.unicode.org/copyright.html#License
+
+// locdistance.h
+// created: 2019may08 Markus W. Scherer
+
+#ifndef __LOCDISTANCE_H__
+#define __LOCDISTANCE_H__
+
+#include "unicode/utypes.h"
+#include "unicode/bytestrie.h"
+#include "unicode/localematcher.h"
+#include "unicode/locid.h"
+#include "unicode/uobject.h"
+#include "lsr.h"
+
+U_NAMESPACE_BEGIN
+
+struct LocaleDistanceData;
+
+/**
+ * Offline-built data for LocaleMatcher.
+ * Mostly but not only the data for mapping locales to their maximized forms.
+ */
+class LocaleDistance final : public UMemory {
+public:
+ static const LocaleDistance *getSingleton(UErrorCode &errorCode);
+
+ /**
+ * Finds the supported LSR with the smallest distance from the desired one.
+ * Equivalent LSR subtags must be normalized into a canonical form.
+ *
+ * Returns the index of the lowest-distance supported LSR in bits 31..8
+ * (negative if none has a distance below the threshold),
+ * and its distance (0..ABOVE_THRESHOLD) in bits 7..0.
+ */
+ int32_t getBestIndexAndDistance(const LSR &desired,
+ const LSR **supportedLSRs, int32_t supportedLSRsLength,
+ int32_t threshold, ULocMatchFavorSubtag favorSubtag) const;
+
+ int32_t getParadigmLSRsLength() const { return paradigmLSRsLength; }
+
+ UBool isParadigmLSR(const LSR &lsr) const;
+
+ int32_t getDefaultScriptDistance() const {
+ return defaultScriptDistance;
+ }
+
+ int32_t getDefaultDemotionPerDesiredLocale() const {
+ return defaultDemotionPerDesiredLocale;
+ }
+
+private:
+ LocaleDistance(const LocaleDistanceData &data);
+ LocaleDistance(const LocaleDistance &other) = delete;
+ LocaleDistance &operator=(const LocaleDistance &other) = delete;
+
+ static void initLocaleDistance(UErrorCode &errorCode);
+
+ static int32_t getDesSuppScriptDistance(BytesTrie &iter, uint64_t startState,
+ const char *desired, const char *supported);
+
+ static int32_t getRegionPartitionsDistance(
+ BytesTrie &iter, uint64_t startState,
+ const char *desiredPartitions, const char *supportedPartitions,
+ int32_t threshold);
+
+ static int32_t getFallbackRegionDistance(BytesTrie &iter, uint64_t startState);
+
+ static int32_t trieNext(BytesTrie &iter, const char *s, bool wantValue);
+
+ const char *partitionsForRegion(const LSR &lsr) const {
+ // ill-formed region -> one non-matching string
+ int32_t pIndex = regionToPartitionsIndex[lsr.regionIndex];
+ return partitionArrays[pIndex];
+ }
+
+ int32_t getDefaultRegionDistance() const {
+ return defaultRegionDistance;
+ }
+
+ // The trie maps each dlang+slang+dscript+sscript+dregion+sregion
+ // (encoded in ASCII with bit 7 set on the last character of each subtag) to a distance.
+ // There is also a trie value for each subsequence of whole subtags.
+ // One '*' is used for a (desired, supported) pair of "und", "Zzzz"/"", or "ZZ"/"".
+ BytesTrie trie;
+
+ /**
+ * Maps each region to zero or more single-character partitions.
+ */
+ const uint8_t *regionToPartitionsIndex;
+ const char **partitionArrays;
+
+ /**
+ * Used to get the paradigm region for a cluster, if there is one.
+ */
+ const LSR *paradigmLSRs;
+ int32_t paradigmLSRsLength;
+
+ int32_t defaultLanguageDistance;
+ int32_t defaultScriptDistance;
+ int32_t defaultRegionDistance;
+ int32_t minRegionDistance;
+ int32_t defaultDemotionPerDesiredLocale;
+};
+
+U_NAMESPACE_END
+
+#endif // __LOCDISTANCE_H__
diff -Nru icu-64.2/source/common/locdspnm.cpp icu-65.1/source/common/locdspnm.cpp
--- icu-64.2/source/common/locdspnm.cpp 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/locdspnm.cpp 2019-10-03 11:16:41.000000000 +0000
@@ -291,6 +291,7 @@
UnicodeString formatCloseParen;
UnicodeString formatReplaceCloseParen;
UDisplayContext nameLength;
+ UDisplayContext substitute;
// Constants for capitalization context usage types.
enum CapContextUsage {
@@ -337,7 +338,7 @@
UnicodeString& result) const;
private:
UnicodeString& localeIdName(const char* localeId,
- UnicodeString& result) const;
+ UnicodeString& result, bool substitute) const;
UnicodeString& appendWithSep(UnicodeString& buffer, const UnicodeString& src) const;
UnicodeString& adjustForUsageAndContext(CapContextUsage usage, UnicodeString& result) const;
UnicodeString& scriptDisplayName(const char* script, UnicodeString& result, UBool skipAdjust) const;
@@ -359,6 +360,7 @@
, capitalizationContext(UDISPCTX_CAPITALIZATION_NONE)
, capitalizationBrkIter(NULL)
, nameLength(UDISPCTX_LENGTH_FULL)
+ , substitute(UDISPCTX_SUBSTITUTE)
{
initialize();
}
@@ -371,6 +373,7 @@
, capitalizationContext(UDISPCTX_CAPITALIZATION_NONE)
, capitalizationBrkIter(NULL)
, nameLength(UDISPCTX_LENGTH_FULL)
+ , substitute(UDISPCTX_SUBSTITUTE)
{
while (length-- > 0) {
UDisplayContext value = *contexts++;
@@ -385,6 +388,9 @@
case UDISPCTX_TYPE_DISPLAY_LENGTH:
nameLength = value;
break;
+ case UDISPCTX_TYPE_SUBSTITUTE_HANDLING:
+ substitute = value;
+ break;
default:
break;
}
@@ -535,6 +541,8 @@
return capitalizationContext;
case UDISPCTX_TYPE_DISPLAY_LENGTH:
return nameLength;
+ case UDISPCTX_TYPE_SUBSTITUTE_HANDLING:
+ return substitute;
default:
break;
}
@@ -549,7 +557,7 @@
if ( result.length() > 0 && u_islower(result.char32At(0)) && capitalizationBrkIter!= NULL &&
( capitalizationContext==UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE || fCapitalization[usage] ) ) {
// note fCapitalization[usage] won't be set unless capitalizationContext is UI_LIST_OR_MENU or STANDALONE
- static UMutex capitalizationBrkIterLock = U_MUTEX_INITIALIZER;
+ static UMutex capitalizationBrkIterLock;
Mutex lock(&capitalizationBrkIterLock);
result.toTitle(capitalizationBrkIter, locale, U_TITLECASE_NO_LOWERCASE | U_TITLECASE_NO_BREAK_ADJUSTMENT);
}
@@ -583,7 +591,7 @@
do { // loop construct is so we can break early out of search
if (hasScript && hasCountry) {
ncat(buffer, ULOC_FULLNAME_CAPACITY, lang, "_", script, "_", country, (char *)0);
- localeIdName(buffer, resultName);
+ localeIdName(buffer, resultName, false);
if (!resultName.isBogus()) {
hasScript = FALSE;
hasCountry = FALSE;
@@ -592,7 +600,7 @@
}
if (hasScript) {
ncat(buffer, ULOC_FULLNAME_CAPACITY, lang, "_", script, (char *)0);
- localeIdName(buffer, resultName);
+ localeIdName(buffer, resultName, false);
if (!resultName.isBogus()) {
hasScript = FALSE;
break;
@@ -600,7 +608,7 @@
}
if (hasCountry) {
ncat(buffer, ULOC_FULLNAME_CAPACITY, lang, "_", country, (char*)0);
- localeIdName(buffer, resultName);
+ localeIdName(buffer, resultName, false);
if (!resultName.isBogus()) {
hasCountry = FALSE;
break;
@@ -609,7 +617,11 @@
} while (FALSE);
}
if (resultName.isBogus() || resultName.isEmpty()) {
- localeIdName(lang, resultName);
+ localeIdName(lang, resultName, substitute == UDISPCTX_SUBSTITUTE);
+ if (resultName.isBogus()) {
+ result.setToBogus();
+ return result;
+ }
}
UnicodeString resultRemainder;
@@ -617,13 +629,28 @@
UErrorCode status = U_ZERO_ERROR;
if (hasScript) {
- resultRemainder.append(scriptDisplayName(script, temp, TRUE));
+ UnicodeString script_str = scriptDisplayName(script, temp, TRUE);
+ if (script_str.isBogus()) {
+ result.setToBogus();
+ return result;
+ }
+ resultRemainder.append(script_str);
}
if (hasCountry) {
- appendWithSep(resultRemainder, regionDisplayName(country, temp, TRUE));
+ UnicodeString region_str = regionDisplayName(country, temp, TRUE);
+ if (region_str.isBogus()) {
+ result.setToBogus();
+ return result;
+ }
+ appendWithSep(resultRemainder, region_str);
}
if (hasVariant) {
- appendWithSep(resultRemainder, variantDisplayName(variant, temp, TRUE));
+ UnicodeString variant_str = variantDisplayName(variant, temp, TRUE);
+ if (variant_str.isBogus()) {
+ result.setToBogus();
+ return result;
+ }
+ appendWithSep(resultRemainder, variant_str);
}
resultRemainder.findAndReplace(formatOpenParen, formatReplaceOpenParen);
resultRemainder.findAndReplace(formatCloseParen, formatReplaceCloseParen);
@@ -689,14 +716,18 @@
// private
UnicodeString&
LocaleDisplayNamesImpl::localeIdName(const char* localeId,
- UnicodeString& result) const {
+ UnicodeString& result, bool substitute) const {
if (nameLength == UDISPCTX_LENGTH_SHORT) {
langData.getNoFallback("Languages%short", localeId, result);
if (!result.isBogus()) {
return result;
}
}
- return langData.getNoFallback("Languages", localeId, result);
+ if (substitute) {
+ return langData.get("Languages", localeId, result);
+ } else {
+ return langData.getNoFallback("Languages", localeId, result);
+ }
}
UnicodeString&
@@ -706,12 +737,16 @@
return result = UnicodeString(lang, -1, US_INV);
}
if (nameLength == UDISPCTX_LENGTH_SHORT) {
- langData.get("Languages%short", lang, result);
+ langData.getNoFallback("Languages%short", lang, result);
if (!result.isBogus()) {
return adjustForUsageAndContext(kCapContextUsageLanguage, result);
}
}
- langData.get("Languages", lang, result);
+ if (substitute == UDISPCTX_SUBSTITUTE) {
+ langData.get("Languages", lang, result);
+ } else {
+ langData.getNoFallback("Languages", lang, result);
+ }
return adjustForUsageAndContext(kCapContextUsageLanguage, result);
}
@@ -720,12 +755,16 @@
UnicodeString& result,
UBool skipAdjust) const {
if (nameLength == UDISPCTX_LENGTH_SHORT) {
- langData.get("Scripts%short", script, result);
+ langData.getNoFallback("Scripts%short", script, result);
if (!result.isBogus()) {
return skipAdjust? result: adjustForUsageAndContext(kCapContextUsageScript, result);
}
}
- langData.get("Scripts", script, result);
+ if (substitute == UDISPCTX_SUBSTITUTE) {
+ langData.get("Scripts", script, result);
+ } else {
+ langData.getNoFallback("Scripts", script, result);
+ }
return skipAdjust? result: adjustForUsageAndContext(kCapContextUsageScript, result);
}
@@ -746,12 +785,16 @@
UnicodeString& result,
UBool skipAdjust) const {
if (nameLength == UDISPCTX_LENGTH_SHORT) {
- regionData.get("Countries%short", region, result);
+ regionData.getNoFallback("Countries%short", region, result);
if (!result.isBogus()) {
return skipAdjust? result: adjustForUsageAndContext(kCapContextUsageTerritory, result);
}
}
- regionData.get("Countries", region, result);
+ if (substitute == UDISPCTX_SUBSTITUTE) {
+ regionData.get("Countries", region, result);
+ } else {
+ regionData.getNoFallback("Countries", region, result);
+ }
return skipAdjust? result: adjustForUsageAndContext(kCapContextUsageTerritory, result);
}
@@ -767,7 +810,11 @@
UnicodeString& result,
UBool skipAdjust) const {
// don't have a resource for short variant names
- langData.get("Variants", variant, result);
+ if (substitute == UDISPCTX_SUBSTITUTE) {
+ langData.get("Variants", variant, result);
+ } else {
+ langData.getNoFallback("Variants", variant, result);
+ }
return skipAdjust? result: adjustForUsageAndContext(kCapContextUsageVariant, result);
}
@@ -782,7 +829,11 @@
UnicodeString& result,
UBool skipAdjust) const {
// don't have a resource for short key names
- langData.get("Keys", key, result);
+ if (substitute == UDISPCTX_SUBSTITUTE) {
+ langData.get("Keys", key, result);
+ } else {
+ langData.getNoFallback("Keys", key, result);
+ }
return skipAdjust? result: adjustForUsageAndContext(kCapContextUsageKey, result);
}
@@ -802,9 +853,8 @@
UErrorCode sts = U_ZERO_ERROR;
UnicodeString ustrValue(value, -1, US_INV);
int32_t len;
- UBool isChoice = FALSE;
const UChar *currencyName = ucurr_getName(ustrValue.getTerminatedBuffer(),
- locale.getBaseName(), UCURR_LONG_NAME, &isChoice, &len, &sts);
+ locale.getBaseName(), UCURR_LONG_NAME, nullptr /* isChoiceFormat */, &len, &sts);
if (U_FAILURE(sts)) {
// Return the value as is on failure
result = ustrValue;
@@ -815,12 +865,16 @@
}
if (nameLength == UDISPCTX_LENGTH_SHORT) {
- langData.get("Types%short", key, value, result);
+ langData.getNoFallback("Types%short", key, value, result);
if (!result.isBogus()) {
return skipAdjust? result: adjustForUsageAndContext(kCapContextUsageKeyValue, result);
}
}
- langData.get("Types", key, value, result);
+ if (substitute == UDISPCTX_SUBSTITUTE) {
+ langData.get("Types", key, value, result);
+ } else {
+ langData.getNoFallback("Types", key, value, result);
+ }
return skipAdjust? result: adjustForUsageAndContext(kCapContextUsageKeyValue, result);
}
diff -Nru icu-64.2/source/common/locid.cpp icu-65.1/source/common/locid.cpp
--- icu-64.2/source/common/locid.cpp 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/locid.cpp 2019-10-03 11:16:41.000000000 +0000
@@ -38,19 +38,19 @@
#include "unicode/strenum.h"
#include "unicode/stringpiece.h"
#include "unicode/uloc.h"
-#include "putilimp.h"
-#include "mutex.h"
-#include "umutex.h"
-#include "uassert.h"
+
+#include "bytesinkutil.h"
+#include "charstr.h"
#include "cmemory.h"
#include "cstring.h"
+#include "mutex.h"
+#include "putilimp.h"
#include "uassert.h"
+#include "ucln_cmn.h"
#include "uhash.h"
#include "ulocimp.h"
-#include "ucln_cmn.h"
+#include "umutex.h"
#include "ustr_imp.h"
-#include "charstr.h"
-#include "bytesinkutil.h"
U_CDECL_BEGIN
static UBool U_CALLCONV locale_cleanup(void);
@@ -62,10 +62,7 @@
static UInitOnce gLocaleCacheInitOnce = U_INITONCE_INITIALIZER;
// gDefaultLocaleMutex protects all access to gDefaultLocalesHashT and gDefaultLocale.
-static UMutex *gDefaultLocaleMutex() {
- static UMutex m = U_MUTEX_INITIALIZER;
- return &m;
-}
+static UMutex gDefaultLocaleMutex;
static UHashtable *gDefaultLocalesHashT = NULL;
static Locale *gDefaultLocale = NULL;
@@ -174,7 +171,7 @@
Locale *locale_set_default_internal(const char *id, UErrorCode& status) {
// Synchronize this entire function.
- Mutex lock(gDefaultLocaleMutex());
+ Mutex lock(&gDefaultLocaleMutex);
UBool canonicalize = FALSE;
@@ -711,7 +708,7 @@
Locale::getDefault()
{
{
- Mutex lock(gDefaultLocaleMutex());
+ Mutex lock(&gDefaultLocaleMutex);
if (gDefaultLocale != NULL) {
return *gDefaultLocale;
}
@@ -1399,5 +1396,7 @@
return baseName;
}
+Locale::Iterator::~Iterator() = default;
+
//eof
U_NAMESPACE_END
diff -Nru icu-64.2/source/common/loclikely.cpp icu-65.1/source/common/loclikely.cpp
--- icu-64.2/source/common/loclikely.cpp 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/loclikely.cpp 2019-10-03 11:16:41.000000000 +0000
@@ -807,24 +807,24 @@
return FALSE;
}
-#define CHECK_TRAILING_VARIANT_SIZE(trailing, trailingLength) \
- { int32_t count = 0; \
- int32_t i; \
- for (i = 0; i < trailingLength; i++) { \
- if (trailing[i] == '-' || trailing[i] == '_') { \
- count = 0; \
- if (count > 8) { \
- goto error; \
- } \
- } else if (trailing[i] == '@') { \
- break; \
- } else if (count > 8) { \
+#define CHECK_TRAILING_VARIANT_SIZE(trailing, trailingLength) UPRV_BLOCK_MACRO_BEGIN { \
+ int32_t count = 0; \
+ int32_t i; \
+ for (i = 0; i < trailingLength; i++) { \
+ if (trailing[i] == '-' || trailing[i] == '_') { \
+ count = 0; \
+ if (count > 8) { \
goto error; \
- } else { \
- count++; \
} \
+ } else if (trailing[i] == '@') { \
+ break; \
+ } else if (count > 8) { \
+ goto error; \
+ } else { \
+ count++; \
} \
- }
+ } \
+} UPRV_BLOCK_MACRO_END
static void
_uloc_addLikelySubtags(const char* localeID,
diff -Nru icu-64.2/source/common/loclikelysubtags.cpp icu-65.1/source/common/loclikelysubtags.cpp
--- icu-64.2/source/common/loclikelysubtags.cpp 1970-01-01 00:00:00.000000000 +0000
+++ icu-65.1/source/common/loclikelysubtags.cpp 2019-10-03 11:16:41.000000000 +0000
@@ -0,0 +1,638 @@
+// © 2019 and later: Unicode, Inc. and others.
+// License & terms of use: http://www.unicode.org/copyright.html#License
+
+// loclikelysubtags.cpp
+// created: 2019may08 Markus W. Scherer
+
+#include
+#include "unicode/utypes.h"
+#include "unicode/bytestrie.h"
+#include "unicode/localpointer.h"
+#include "unicode/locid.h"
+#include "unicode/uobject.h"
+#include "unicode/ures.h"
+#include "charstr.h"
+#include "cstring.h"
+#include "loclikelysubtags.h"
+#include "lsr.h"
+#include "uassert.h"
+#include "ucln_cmn.h"
+#include "uhash.h"
+#include "uinvchar.h"
+#include "umutex.h"
+#include "uresdata.h"
+#include "uresimp.h"
+
+U_NAMESPACE_BEGIN
+
+namespace {
+
+constexpr char PSEUDO_ACCENTS_PREFIX = '\''; // -XA, -PSACCENT
+constexpr char PSEUDO_BIDI_PREFIX = '+'; // -XB, -PSBIDI
+constexpr char PSEUDO_CRACKED_PREFIX = ','; // -XC, -PSCRACK
+
+/**
+ * Stores NUL-terminated strings with duplicate elimination.
+ * Checks for unique UTF-16 string pointers and converts to invariant characters.
+ */
+class UniqueCharStrings {
+public:
+ UniqueCharStrings(UErrorCode &errorCode) : strings(nullptr) {
+ uhash_init(&map, uhash_hashUChars, uhash_compareUChars, uhash_compareLong, &errorCode);
+ if (U_FAILURE(errorCode)) { return; }
+ strings = new CharString();
+ if (strings == nullptr) {
+ errorCode = U_MEMORY_ALLOCATION_ERROR;
+ }
+ }
+ ~UniqueCharStrings() {
+ uhash_close(&map);
+ delete strings;
+ }
+
+ /** Returns/orphans the CharString that contains all strings. */
+ CharString *orphanCharStrings() {
+ CharString *result = strings;
+ strings = nullptr;
+ return result;
+ }
+
+ /** Adds a string and returns a unique number for it. */
+ int32_t add(const UnicodeString &s, UErrorCode &errorCode) {
+ if (U_FAILURE(errorCode)) { return 0; }
+ if (isFrozen) {
+ errorCode = U_NO_WRITE_PERMISSION;
+ return 0;
+ }
+ // The string points into the resource bundle.
+ const char16_t *p = s.getBuffer();
+ int32_t oldIndex = uhash_geti(&map, p);
+ if (oldIndex != 0) { // found duplicate
+ return oldIndex;
+ }
+ // Explicit NUL terminator for the previous string.
+ // The strings object is also terminated with one implicit NUL.
+ strings->append(0, errorCode);
+ int32_t newIndex = strings->length();
+ strings->appendInvariantChars(s, errorCode);
+ uhash_puti(&map, const_cast(p), newIndex, &errorCode);
+ return newIndex;
+ }
+
+ void freeze() { isFrozen = true; }
+
+ /**
+ * Returns a string pointer for its unique number, if this object is frozen.
+ * Otherwise nullptr.
+ */
+ const char *get(int32_t i) const {
+ U_ASSERT(isFrozen);
+ return isFrozen && i > 0 ? strings->data() + i : nullptr;
+ }
+
+private:
+ UHashtable map;
+ CharString *strings;
+ bool isFrozen = false;
+};
+
+} // namespace
+
+LocaleDistanceData::LocaleDistanceData(LocaleDistanceData &&data) :
+ distanceTrieBytes(data.distanceTrieBytes),
+ regionToPartitions(data.regionToPartitions),
+ partitions(data.partitions),
+ paradigms(data.paradigms), paradigmsLength(data.paradigmsLength),
+ distances(data.distances) {
+ data.partitions = nullptr;
+ data.paradigms = nullptr;
+}
+
+LocaleDistanceData::~LocaleDistanceData() {
+ uprv_free(partitions);
+ delete[] paradigms;
+}
+
+// TODO(ICU-20777): Rename to just LikelySubtagsData.
+struct XLikelySubtagsData {
+ UResourceBundle *langInfoBundle = nullptr;
+ UniqueCharStrings strings;
+ CharStringMap languageAliases;
+ CharStringMap regionAliases;
+ const uint8_t *trieBytes = nullptr;
+ LSR *lsrs = nullptr;
+ int32_t lsrsLength = 0;
+
+ LocaleDistanceData distanceData;
+
+ XLikelySubtagsData(UErrorCode &errorCode) : strings(errorCode) {}
+
+ ~XLikelySubtagsData() {
+ ures_close(langInfoBundle);
+ delete[] lsrs;
+ }
+
+ void load(UErrorCode &errorCode) {
+ langInfoBundle = ures_openDirect(nullptr, "langInfo", &errorCode);
+ if (U_FAILURE(errorCode)) { return; }
+ StackUResourceBundle stackTempBundle;
+ ResourceDataValue value;
+ ures_getValueWithFallback(langInfoBundle, "likely", stackTempBundle.getAlias(),
+ value, errorCode);
+ ResourceTable likelyTable = value.getTable(errorCode);
+ if (U_FAILURE(errorCode)) { return; }
+
+ // Read all strings in the resource bundle and convert them to invariant char *.
+ LocalMemory languageIndexes, regionIndexes, lsrSubtagIndexes;
+ int32_t languagesLength = 0, regionsLength = 0, lsrSubtagsLength = 0;
+ if (!readStrings(likelyTable, "languageAliases", value,
+ languageIndexes, languagesLength, errorCode) ||
+ !readStrings(likelyTable, "regionAliases", value,
+ regionIndexes, regionsLength, errorCode) ||
+ !readStrings(likelyTable, "lsrs", value,
+ lsrSubtagIndexes,lsrSubtagsLength, errorCode)) {
+ return;
+ }
+ if ((languagesLength & 1) != 0 ||
+ (regionsLength & 1) != 0 ||
+ (lsrSubtagsLength % 3) != 0) {
+ errorCode = U_INVALID_FORMAT_ERROR;
+ return;
+ }
+ if (lsrSubtagsLength == 0) {
+ errorCode = U_MISSING_RESOURCE_ERROR;
+ return;
+ }
+
+ if (!likelyTable.findValue("trie", value)) {
+ errorCode = U_MISSING_RESOURCE_ERROR;
+ return;
+ }
+ int32_t length;
+ trieBytes = value.getBinary(length, errorCode);
+ if (U_FAILURE(errorCode)) { return; }
+
+ // Also read distance/matcher data if available,
+ // to open & keep only one resource bundle pointer
+ // and to use one single UniqueCharStrings.
+ UErrorCode matchErrorCode = U_ZERO_ERROR;
+ ures_getValueWithFallback(langInfoBundle, "match", stackTempBundle.getAlias(),
+ value, matchErrorCode);
+ LocalMemory partitionIndexes, paradigmSubtagIndexes;
+ int32_t partitionsLength = 0, paradigmSubtagsLength = 0;
+ if (U_SUCCESS(matchErrorCode)) {
+ ResourceTable matchTable = value.getTable(errorCode);
+ if (U_FAILURE(errorCode)) { return; }
+
+ if (matchTable.findValue("trie", value)) {
+ distanceData.distanceTrieBytes = value.getBinary(length, errorCode);
+ if (U_FAILURE(errorCode)) { return; }
+ }
+
+ if (matchTable.findValue("regionToPartitions", value)) {
+ distanceData.regionToPartitions = value.getBinary(length, errorCode);
+ if (U_FAILURE(errorCode)) { return; }
+ if (length < LSR::REGION_INDEX_LIMIT) {
+ errorCode = U_INVALID_FORMAT_ERROR;
+ return;
+ }
+ }
+
+ if (!readStrings(matchTable, "partitions", value,
+ partitionIndexes, partitionsLength, errorCode) ||
+ !readStrings(matchTable, "paradigms", value,
+ paradigmSubtagIndexes, paradigmSubtagsLength, errorCode)) {
+ return;
+ }
+ if ((paradigmSubtagsLength % 3) != 0) {
+ errorCode = U_INVALID_FORMAT_ERROR;
+ return;
+ }
+
+ if (matchTable.findValue("distances", value)) {
+ distanceData.distances = value.getIntVector(length, errorCode);
+ if (U_FAILURE(errorCode)) { return; }
+ if (length < 4) { // LocaleDistance IX_LIMIT
+ errorCode = U_INVALID_FORMAT_ERROR;
+ return;
+ }
+ }
+ } else if (matchErrorCode == U_MISSING_RESOURCE_ERROR) {
+ // ok for likely subtags
+ } else { // error other than missing resource
+ errorCode = matchErrorCode;
+ return;
+ }
+
+ // Fetch & store invariant-character versions of strings
+ // only after we have collected and de-duplicated all of them.
+ strings.freeze();
+
+ languageAliases = CharStringMap(languagesLength / 2, errorCode);
+ for (int32_t i = 0; i < languagesLength; i += 2) {
+ languageAliases.put(strings.get(languageIndexes[i]),
+ strings.get(languageIndexes[i + 1]), errorCode);
+ }
+
+ regionAliases = CharStringMap(regionsLength / 2, errorCode);
+ for (int32_t i = 0; i < regionsLength; i += 2) {
+ regionAliases.put(strings.get(regionIndexes[i]),
+ strings.get(regionIndexes[i + 1]), errorCode);
+ }
+ if (U_FAILURE(errorCode)) { return; }
+
+ lsrsLength = lsrSubtagsLength / 3;
+ lsrs = new LSR[lsrsLength];
+ if (lsrs == nullptr) {
+ errorCode = U_MEMORY_ALLOCATION_ERROR;
+ return;
+ }
+ for (int32_t i = 0, j = 0; i < lsrSubtagsLength; i += 3, ++j) {
+ lsrs[j] = LSR(strings.get(lsrSubtagIndexes[i]),
+ strings.get(lsrSubtagIndexes[i + 1]),
+ strings.get(lsrSubtagIndexes[i + 2]));
+ }
+
+ if (partitionsLength > 0) {
+ distanceData.partitions = static_cast(
+ uprv_malloc(partitionsLength * sizeof(const char *)));
+ if (distanceData.partitions == nullptr) {
+ errorCode = U_MEMORY_ALLOCATION_ERROR;
+ return;
+ }
+ for (int32_t i = 0; i < partitionsLength; ++i) {
+ distanceData.partitions[i] = strings.get(partitionIndexes[i]);
+ }
+ }
+
+ if (paradigmSubtagsLength > 0) {
+ distanceData.paradigmsLength = paradigmSubtagsLength / 3;
+ LSR *paradigms = new LSR[distanceData.paradigmsLength];
+ if (paradigms == nullptr) {
+ errorCode = U_MEMORY_ALLOCATION_ERROR;
+ return;
+ }
+ for (int32_t i = 0, j = 0; i < paradigmSubtagsLength; i += 3, ++j) {
+ paradigms[j] = LSR(strings.get(paradigmSubtagIndexes[i]),
+ strings.get(paradigmSubtagIndexes[i + 1]),
+ strings.get(paradigmSubtagIndexes[i + 2]));
+ }
+ distanceData.paradigms = paradigms;
+ }
+ }
+
+private:
+ bool readStrings(const ResourceTable &table, const char *key, ResourceValue &value,
+ LocalMemory &indexes, int32_t &length, UErrorCode &errorCode) {
+ if (table.findValue(key, value)) {
+ ResourceArray stringArray = value.getArray(errorCode);
+ if (U_FAILURE(errorCode)) { return false; }
+ length = stringArray.getSize();
+ if (length == 0) { return true; }
+ int32_t *rawIndexes = indexes.allocateInsteadAndCopy(length);
+ if (rawIndexes == nullptr) {
+ errorCode = U_MEMORY_ALLOCATION_ERROR;
+ return false;
+ }
+ for (int i = 0; i < length; ++i) {
+ stringArray.getValue(i, value); // returns TRUE because i < length
+ rawIndexes[i] = strings.add(value.getUnicodeString(errorCode), errorCode);
+ if (U_FAILURE(errorCode)) { return false; }
+ }
+ }
+ return true;
+ }
+};
+
+namespace {
+
+XLikelySubtags *gLikelySubtags = nullptr;
+UInitOnce gInitOnce = U_INITONCE_INITIALIZER;
+
+UBool U_CALLCONV cleanup() {
+ delete gLikelySubtags;
+ gLikelySubtags = nullptr;
+ gInitOnce.reset();
+ return TRUE;
+}
+
+} // namespace
+
+void U_CALLCONV XLikelySubtags::initLikelySubtags(UErrorCode &errorCode) {
+ // This function is invoked only via umtx_initOnce().
+ U_ASSERT(gLikelySubtags == nullptr);
+ XLikelySubtagsData data(errorCode);
+ data.load(errorCode);
+ if (U_FAILURE(errorCode)) { return; }
+ gLikelySubtags = new XLikelySubtags(data);
+ if (gLikelySubtags == nullptr) {
+ errorCode = U_MEMORY_ALLOCATION_ERROR;
+ return;
+ }
+ ucln_common_registerCleanup(UCLN_COMMON_LIKELY_SUBTAGS, cleanup);
+}
+
+const XLikelySubtags *XLikelySubtags::getSingleton(UErrorCode &errorCode) {
+ if (U_FAILURE(errorCode)) { return nullptr; }
+ umtx_initOnce(gInitOnce, &XLikelySubtags::initLikelySubtags, errorCode);
+ return gLikelySubtags;
+}
+
+XLikelySubtags::XLikelySubtags(XLikelySubtagsData &data) :
+ langInfoBundle(data.langInfoBundle),
+ strings(data.strings.orphanCharStrings()),
+ languageAliases(std::move(data.languageAliases)),
+ regionAliases(std::move(data.regionAliases)),
+ trie(data.trieBytes),
+ lsrs(data.lsrs),
+#if U_DEBUG
+ lsrsLength(data.lsrsLength),
+#endif
+ distanceData(std::move(data.distanceData)) {
+ data.langInfoBundle = nullptr;
+ data.lsrs = nullptr;
+
+ // Cache the result of looking up language="und" encoded as "*", and "und-Zzzz" ("**").
+ UStringTrieResult result = trie.next(u'*');
+ U_ASSERT(USTRINGTRIE_HAS_NEXT(result));
+ trieUndState = trie.getState64();
+ result = trie.next(u'*');
+ U_ASSERT(USTRINGTRIE_HAS_NEXT(result));
+ trieUndZzzzState = trie.getState64();
+ result = trie.next(u'*');
+ U_ASSERT(USTRINGTRIE_HAS_VALUE(result));
+ defaultLsrIndex = trie.getValue();
+ trie.reset();
+
+ for (char16_t c = u'a'; c <= u'z'; ++c) {
+ result = trie.next(c);
+ if (result == USTRINGTRIE_NO_VALUE) {
+ trieFirstLetterStates[c - u'a'] = trie.getState64();
+ }
+ trie.reset();
+ }
+}
+
+XLikelySubtags::~XLikelySubtags() {
+ ures_close(langInfoBundle);
+ delete strings;
+ delete[] lsrs;
+}
+
+LSR XLikelySubtags::makeMaximizedLsrFrom(const Locale &locale, UErrorCode &errorCode) const {
+ const char *name = locale.getName();
+ if (uprv_isAtSign(name[0]) && name[1] == 'x' && name[2] == '=') { // name.startsWith("@x=")
+ // Private use language tag x-subtag-subtag...
+ return LSR(name, "", "");
+ }
+ return makeMaximizedLsr(locale.getLanguage(), locale.getScript(), locale.getCountry(),
+ locale.getVariant(), errorCode);
+}
+
+namespace {
+
+const char *getCanonical(const CharStringMap &aliases, const char *alias) {
+ const char *canonical = aliases.get(alias);
+ return canonical == nullptr ? alias : canonical;
+}
+
+} // namespace
+
+LSR XLikelySubtags::makeMaximizedLsr(const char *language, const char *script, const char *region,
+ const char *variant, UErrorCode &errorCode) const {
+ // Handle pseudolocales like en-XA, ar-XB, fr-PSCRACK.
+ // They should match only themselves,
+ // not other locales with what looks like the same language and script subtags.
+ char c1;
+ if (region[0] == 'X' && (c1 = region[1]) != 0 && region[2] == 0) {
+ switch (c1) {
+ case 'A':
+ return LSR(PSEUDO_ACCENTS_PREFIX, language, script, region, errorCode);
+ case 'B':
+ return LSR(PSEUDO_BIDI_PREFIX, language, script, region, errorCode);
+ case 'C':
+ return LSR(PSEUDO_CRACKED_PREFIX, language, script, region, errorCode);
+ default: // normal locale
+ break;
+ }
+ }
+
+ if (variant[0] == 'P' && variant[1] == 'S') {
+ if (uprv_strcmp(variant, "PSACCENT") == 0) {
+ return LSR(PSEUDO_ACCENTS_PREFIX, language, script,
+ *region == 0 ? "XA" : region, errorCode);
+ } else if (uprv_strcmp(variant, "PSBIDI") == 0) {
+ return LSR(PSEUDO_BIDI_PREFIX, language, script,
+ *region == 0 ? "XB" : region, errorCode);
+ } else if (uprv_strcmp(variant, "PSCRACK") == 0) {
+ return LSR(PSEUDO_CRACKED_PREFIX, language, script,
+ *region == 0 ? "XC" : region, errorCode);
+ }
+ // else normal locale
+ }
+
+ language = getCanonical(languageAliases, language);
+ // (We have no script mappings.)
+ region = getCanonical(regionAliases, region);
+ return maximize(language, script, region);
+}
+
+LSR XLikelySubtags::maximize(const char *language, const char *script, const char *region) const {
+ if (uprv_strcmp(language, "und") == 0) {
+ language = "";
+ }
+ if (uprv_strcmp(script, "Zzzz") == 0) {
+ script = "";
+ }
+ if (uprv_strcmp(region, "ZZ") == 0) {
+ region = "";
+ }
+ if (*script != 0 && *region != 0 && *language != 0) {
+ return LSR(language, script, region); // already maximized
+ }
+
+ uint32_t retainOldMask = 0;
+ BytesTrie iter(trie);
+ uint64_t state;
+ int32_t value;
+ // Small optimization: Array lookup for first language letter.
+ int32_t c0;
+ if (0 <= (c0 = uprv_lowerOrdinal(language[0])) && c0 <= 25 &&
+ language[1] != 0 && // language.length() >= 2
+ (state = trieFirstLetterStates[c0]) != 0) {
+ value = trieNext(iter.resetToState64(state), language, 1);
+ } else {
+ value = trieNext(iter, language, 0);
+ }
+ if (value >= 0) {
+ if (*language != 0) {
+ retainOldMask |= 4;
+ }
+ state = iter.getState64();
+ } else {
+ retainOldMask |= 4;
+ iter.resetToState64(trieUndState); // "und" ("*")
+ state = 0;
+ }
+
+ if (value > 0) {
+ // Intermediate or final value from just language.
+ if (value == SKIP_SCRIPT) {
+ value = 0;
+ }
+ if (*script != 0) {
+ retainOldMask |= 2;
+ }
+ } else {
+ value = trieNext(iter, script, 0);
+ if (value >= 0) {
+ if (*script != 0) {
+ retainOldMask |= 2;
+ }
+ state = iter.getState64();
+ } else {
+ retainOldMask |= 2;
+ if (state == 0) {
+ iter.resetToState64(trieUndZzzzState); // "und-Zzzz" ("**")
+ } else {
+ iter.resetToState64(state);
+ value = trieNext(iter, "", 0);
+ U_ASSERT(value >= 0);
+ state = iter.getState64();
+ }
+ }
+ }
+
+ if (value > 0) {
+ // Final value from just language or language+script.
+ if (*region != 0) {
+ retainOldMask |= 1;
+ }
+ } else {
+ value = trieNext(iter, region, 0);
+ if (value >= 0) {
+ if (*region != 0) {
+ retainOldMask |= 1;
+ }
+ } else {
+ retainOldMask |= 1;
+ if (state == 0) {
+ value = defaultLsrIndex;
+ } else {
+ iter.resetToState64(state);
+ value = trieNext(iter, "", 0);
+ U_ASSERT(value > 0);
+ }
+ }
+ }
+ U_ASSERT(value < lsrsLength);
+ const LSR &result = lsrs[value];
+
+ if (*language == 0) {
+ language = "und";
+ }
+
+ if (retainOldMask == 0) {
+ // Quickly return a copy of the lookup-result LSR
+ // without new allocation of the subtags.
+ return LSR(result.language, result.script, result.region);
+ }
+ if ((retainOldMask & 4) == 0) {
+ language = result.language;
+ }
+ if ((retainOldMask & 2) == 0) {
+ script = result.script;
+ }
+ if ((retainOldMask & 1) == 0) {
+ region = result.region;
+ }
+ return LSR(language, script, region);
+}
+
+int32_t XLikelySubtags::trieNext(BytesTrie &iter, const char *s, int32_t i) {
+ UStringTrieResult result;
+ uint8_t c;
+ if ((c = s[i]) == 0) {
+ result = iter.next(u'*');
+ } else {
+ for (;;) {
+ c = uprv_invCharToAscii(c);
+ // EBCDIC: If s[i] is not an invariant character,
+ // then c is now 0 and will simply not match anything, which is harmless.
+ uint8_t next = s[++i];
+ if (next != 0) {
+ if (!USTRINGTRIE_HAS_NEXT(iter.next(c))) {
+ return -1;
+ }
+ } else {
+ // last character of this subtag
+ result = iter.next(c | 0x80);
+ break;
+ }
+ c = next;
+ }
+ }
+ switch (result) {
+ case USTRINGTRIE_NO_MATCH: return -1;
+ case USTRINGTRIE_NO_VALUE: return 0;
+ case USTRINGTRIE_INTERMEDIATE_VALUE:
+ U_ASSERT(iter.getValue() == SKIP_SCRIPT);
+ return SKIP_SCRIPT;
+ case USTRINGTRIE_FINAL_VALUE: return iter.getValue();
+ default: return -1;
+ }
+}
+
+// TODO(ICU-20777): Switch Locale/uloc_ likely-subtags API from the old code
+// in loclikely.cpp to this new code, including activating this
+// minimizeSubtags() function. The LocaleMatcher does not minimize.
+#if 0
+LSR XLikelySubtags::minimizeSubtags(const char *languageIn, const char *scriptIn,
+ const char *regionIn, ULocale.Minimize fieldToFavor,
+ UErrorCode &errorCode) const {
+ LSR result = maximize(languageIn, scriptIn, regionIn);
+
+ // We could try just a series of checks, like:
+ // LSR result2 = addLikelySubtags(languageIn, "", "");
+ // if result.equals(result2) return result2;
+ // However, we can optimize 2 of the cases:
+ // (languageIn, "", "")
+ // (languageIn, "", regionIn)
+
+ // value00 = lookup(result.language, "", "")
+ BytesTrie iter = new BytesTrie(trie);
+ int value = trieNext(iter, result.language, 0);
+ U_ASSERT(value >= 0);
+ if (value == 0) {
+ value = trieNext(iter, "", 0);
+ U_ASSERT(value >= 0);
+ if (value == 0) {
+ value = trieNext(iter, "", 0);
+ }
+ }
+ U_ASSERT(value > 0);
+ LSR value00 = lsrs[value];
+ boolean favorRegionOk = false;
+ if (result.script.equals(value00.script)) { //script is default
+ if (result.region.equals(value00.region)) {
+ return new LSR(result.language, "", "");
+ } else if (fieldToFavor == ULocale.Minimize.FAVOR_REGION) {
+ return new LSR(result.language, "", result.region);
+ } else {
+ favorRegionOk = true;
+ }
+ }
+
+ // The last case is not as easy to optimize.
+ // Maybe do later, but for now use the straightforward code.
+ LSR result2 = maximize(languageIn, scriptIn, "");
+ if (result2.equals(result)) {
+ return new LSR(result.language, result.script, "");
+ } else if (favorRegionOk) {
+ return new LSR(result.language, "", result.region);
+ }
+ return result;
+}
+#endif
+
+U_NAMESPACE_END
diff -Nru icu-64.2/source/common/loclikelysubtags.h icu-65.1/source/common/loclikelysubtags.h
--- icu-64.2/source/common/loclikelysubtags.h 1970-01-01 00:00:00.000000000 +0000
+++ icu-65.1/source/common/loclikelysubtags.h 2019-10-03 11:16:41.000000000 +0000
@@ -0,0 +1,143 @@
+// © 2019 and later: Unicode, Inc. and others.
+// License & terms of use: http://www.unicode.org/copyright.html#License
+
+// loclikelysubtags.h
+// created: 2019may08 Markus W. Scherer
+
+#ifndef __LOCLIKELYSUBTAGS_H__
+#define __LOCLIKELYSUBTAGS_H__
+
+#include
+#include "unicode/utypes.h"
+#include "unicode/bytestrie.h"
+#include "unicode/locid.h"
+#include "unicode/uobject.h"
+#include "unicode/ures.h"
+#include "lsr.h"
+#include "uhash.h"
+
+U_NAMESPACE_BEGIN
+
+struct XLikelySubtagsData;
+
+/**
+ * Map of const char * keys & values.
+ * Stores pointers as is: Does not own/copy/adopt/release strings.
+ */
+class CharStringMap final : public UMemory {
+public:
+ /** Constructs an unusable non-map. */
+ CharStringMap() : map(nullptr) {}
+ CharStringMap(int32_t size, UErrorCode &errorCode) {
+ map = uhash_openSize(uhash_hashChars, uhash_compareChars, uhash_compareChars,
+ size, &errorCode);
+ }
+ CharStringMap(CharStringMap &&other) U_NOEXCEPT : map(other.map) {
+ other.map = nullptr;
+ }
+ CharStringMap(const CharStringMap &other) = delete;
+ ~CharStringMap() {
+ uhash_close(map);
+ }
+
+ CharStringMap &operator=(CharStringMap &&other) U_NOEXCEPT {
+ map = other.map;
+ other.map = nullptr;
+ return *this;
+ }
+ CharStringMap &operator=(const CharStringMap &other) = delete;
+
+ const char *get(const char *key) const { return static_cast(uhash_get(map, key)); }
+ void put(const char *key, const char *value, UErrorCode &errorCode) {
+ uhash_put(map, const_cast(key), const_cast(value), &errorCode);
+ }
+
+private:
+ UHashtable *map;
+};
+
+struct LocaleDistanceData {
+ LocaleDistanceData() = default;
+ LocaleDistanceData(LocaleDistanceData &&data);
+ ~LocaleDistanceData();
+
+ const uint8_t *distanceTrieBytes = nullptr;
+ const uint8_t *regionToPartitions = nullptr;
+ const char **partitions = nullptr;
+ const LSR *paradigms = nullptr;
+ int32_t paradigmsLength = 0;
+ const int32_t *distances = nullptr;
+
+private:
+ LocaleDistanceData &operator=(const LocaleDistanceData &) = delete;
+};
+
+// TODO(ICU-20777): Rename to just LikelySubtags.
+class XLikelySubtags final : public UMemory {
+public:
+ ~XLikelySubtags();
+
+ static constexpr int32_t SKIP_SCRIPT = 1;
+
+ // VisibleForTesting
+ static const XLikelySubtags *getSingleton(UErrorCode &errorCode);
+
+ // VisibleForTesting
+ LSR makeMaximizedLsrFrom(const Locale &locale, UErrorCode &errorCode) const;
+
+ // TODO(ICU-20777): Switch Locale/uloc_ likely-subtags API from the old code
+ // in loclikely.cpp to this new code, including activating this
+ // minimizeSubtags() function. The LocaleMatcher does not minimize.
+#if 0
+ LSR minimizeSubtags(const char *languageIn, const char *scriptIn, const char *regionIn,
+ ULocale.Minimize fieldToFavor, UErrorCode &errorCode) const;
+#endif
+
+ // visible for LocaleDistance
+ const LocaleDistanceData &getDistanceData() const { return distanceData; }
+
+private:
+ XLikelySubtags(XLikelySubtagsData &data);
+ XLikelySubtags(const XLikelySubtags &other) = delete;
+ XLikelySubtags &operator=(const XLikelySubtags &other) = delete;
+
+ static void initLikelySubtags(UErrorCode &errorCode);
+
+ LSR makeMaximizedLsr(const char *language, const char *script, const char *region,
+ const char *variant, UErrorCode &errorCode) const;
+
+ /**
+ * Raw access to addLikelySubtags. Input must be in canonical format, eg "en", not "eng" or "EN".
+ */
+ LSR maximize(const char *language, const char *script, const char *region) const;
+
+ static int32_t trieNext(BytesTrie &iter, const char *s, int32_t i);
+
+ UResourceBundle *langInfoBundle;
+ // We could store the strings by value, except that if there were few enough strings,
+ // moving the contents could copy it to a different array,
+ // invalidating the pointers stored in the maps.
+ CharString *strings;
+ CharStringMap languageAliases;
+ CharStringMap regionAliases;
+
+ // The trie maps each lang+script+region (encoded in ASCII) to an index into lsrs.
+ // There is also a trie value for each intermediate lang and lang+script.
+ // '*' is used instead of "und", "Zzzz"/"" and "ZZ"/"".
+ BytesTrie trie;
+ uint64_t trieUndState;
+ uint64_t trieUndZzzzState;
+ int32_t defaultLsrIndex;
+ uint64_t trieFirstLetterStates[26];
+ const LSR *lsrs;
+#if U_DEBUG
+ int32_t lsrsLength;
+#endif
+
+ // distance/matcher data: see comment in XLikelySubtagsData::load()
+ LocaleDistanceData distanceData;
+};
+
+U_NAMESPACE_END
+
+#endif // __LOCLIKELYSUBTAGS_H__
diff -Nru icu-64.2/source/common/lsr.cpp icu-65.1/source/common/lsr.cpp
--- icu-64.2/source/common/lsr.cpp 1970-01-01 00:00:00.000000000 +0000
+++ icu-65.1/source/common/lsr.cpp 2019-10-03 11:16:41.000000000 +0000
@@ -0,0 +1,101 @@
+// © 2019 and later: Unicode, Inc. and others.
+// License & terms of use: http://www.unicode.org/copyright.html#License
+
+// lsr.cpp
+// created: 2019may08 Markus W. Scherer
+
+#include "unicode/utypes.h"
+#include "charstr.h"
+#include "cmemory.h"
+#include "cstring.h"
+#include "lsr.h"
+#include "uinvchar.h"
+#include "ustr_imp.h"
+
+U_NAMESPACE_BEGIN
+
+LSR::LSR(char prefix, const char *lang, const char *scr, const char *r, UErrorCode &errorCode) :
+ language(nullptr), script(nullptr), region(r),
+ regionIndex(indexForRegion(region)) {
+ if (U_SUCCESS(errorCode)) {
+ CharString langScript;
+ langScript.append(prefix, errorCode).append(lang, errorCode).append('\0', errorCode);
+ int32_t scriptOffset = langScript.length();
+ langScript.append(prefix, errorCode).append(scr, errorCode);
+ owned = langScript.cloneData(errorCode);
+ if (U_SUCCESS(errorCode)) {
+ language = owned;
+ script = owned + scriptOffset;
+ }
+ }
+}
+
+LSR::LSR(LSR &&other) U_NOEXCEPT :
+ language(other.language), script(other.script), region(other.region), owned(other.owned),
+ regionIndex(other.regionIndex), hashCode(other.hashCode) {
+ if (owned != nullptr) {
+ other.language = other.script = "";
+ other.owned = nullptr;
+ other.hashCode = 0;
+ }
+}
+
+void LSR::deleteOwned() {
+ uprv_free(owned);
+}
+
+LSR &LSR::operator=(LSR &&other) U_NOEXCEPT {
+ this->~LSR();
+ language = other.language;
+ script = other.script;
+ region = other.region;
+ regionIndex = other.regionIndex;
+ owned = other.owned;
+ hashCode = other.hashCode;
+ if (owned != nullptr) {
+ other.language = other.script = "";
+ other.owned = nullptr;
+ other.hashCode = 0;
+ }
+ return *this;
+}
+
+UBool LSR::operator==(const LSR &other) const {
+ return
+ uprv_strcmp(language, other.language) == 0 &&
+ uprv_strcmp(script, other.script) == 0 &&
+ regionIndex == other.regionIndex &&
+ // Compare regions if both are ill-formed (and their indexes are 0).
+ (regionIndex > 0 || uprv_strcmp(region, other.region) == 0);
+}
+
+int32_t LSR::indexForRegion(const char *region) {
+ int32_t c = region[0];
+ int32_t a = c - '0';
+ if (0 <= a && a <= 9) { // digits: "419"
+ int32_t b = region[1] - '0';
+ if (b < 0 || 9 < b) { return 0; }
+ c = region[2] - '0';
+ if (c < 0 || 9 < c || region[3] != 0) { return 0; }
+ return (10 * a + b) * 10 + c + 1;
+ } else { // letters: "DE"
+ a = uprv_upperOrdinal(c);
+ if (a < 0 || 25 < a) { return 0; }
+ int32_t b = uprv_upperOrdinal(region[1]);
+ if (b < 0 || 25 < b || region[2] != 0) { return 0; }
+ return 26 * a + b + 1001;
+ }
+ return 0;
+}
+
+LSR &LSR::setHashCode() {
+ if (hashCode == 0) {
+ hashCode =
+ (ustr_hashCharsN(language, static_cast(uprv_strlen(language))) * 37 +
+ ustr_hashCharsN(script, static_cast(uprv_strlen(script)))) * 37 +
+ regionIndex;
+ }
+ return *this;
+}
+
+U_NAMESPACE_END
diff -Nru icu-64.2/source/common/lsr.h icu-65.1/source/common/lsr.h
--- icu-64.2/source/common/lsr.h 1970-01-01 00:00:00.000000000 +0000
+++ icu-65.1/source/common/lsr.h 2019-10-03 11:16:41.000000000 +0000
@@ -0,0 +1,72 @@
+// © 2019 and later: Unicode, Inc. and others.
+// License & terms of use: http://www.unicode.org/copyright.html#License
+
+// lsr.h
+// created: 2019may08 Markus W. Scherer
+
+#ifndef __LSR_H__
+#define __LSR_H__
+
+#include "unicode/utypes.h"
+#include "unicode/uobject.h"
+#include "cstring.h"
+
+U_NAMESPACE_BEGIN
+
+struct LSR final : public UMemory {
+ static constexpr int32_t REGION_INDEX_LIMIT = 1001 + 26 * 26;
+
+ const char *language;
+ const char *script;
+ const char *region;
+ char *owned = nullptr;
+ /** Index for region, 0 if ill-formed. @see indexForRegion */
+ int32_t regionIndex = 0;
+ /** Only set for LSRs that will be used in a hash table. */
+ int32_t hashCode = 0;
+
+ LSR() : language("und"), script(""), region("") {}
+
+ /** Constructor which aliases all subtag pointers. */
+ LSR(const char *lang, const char *scr, const char *r) :
+ language(lang), script(scr), region(r),
+ regionIndex(indexForRegion(region)) {}
+ /**
+ * Constructor which prepends the prefix to the language and script,
+ * copies those into owned memory, and aliases the region.
+ */
+ LSR(char prefix, const char *lang, const char *scr, const char *r, UErrorCode &errorCode);
+ LSR(LSR &&other) U_NOEXCEPT;
+ LSR(const LSR &other) = delete;
+ inline ~LSR() {
+ // Pure inline code for almost all instances.
+ if (owned != nullptr) {
+ deleteOwned();
+ }
+ }
+
+ LSR &operator=(LSR &&other) U_NOEXCEPT;
+ LSR &operator=(const LSR &other) = delete;
+
+ /**
+ * Returns a positive index (>0) for a well-formed region code.
+ * Do not rely on a particular region->index mapping; it may change.
+ * Returns 0 for ill-formed strings.
+ */
+ static int32_t indexForRegion(const char *region);
+
+ UBool operator==(const LSR &other) const;
+
+ inline UBool operator!=(const LSR &other) const {
+ return !operator==(other);
+ }
+
+ LSR &setHashCode();
+
+private:
+ void deleteOwned();
+};
+
+U_NAMESPACE_END
+
+#endif // __LSR_H__
diff -Nru icu-64.2/source/common/Makefile.in icu-65.1/source/common/Makefile.in
--- icu-64.2/source/common/Makefile.in 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/Makefile.in 2019-10-03 11:16:41.000000000 +0000
@@ -88,8 +88,9 @@
ucnv_ext.o ucnvmbcs.o ucnv2022.o ucnvhz.o ucnv_lmb.o ucnvisci.o ucnvdisp.o ucnv_set.o ucnv_ct.o \
resource.o uresbund.o ures_cnv.o uresdata.o resbund.o resbund_cnv.o \
ucurr.o \
-localebuilder.o \
+localebuilder.o localeprioritylist.o \
messagepattern.o ucat.o locmap.o uloc.o locid.o locutil.o locavailable.o locdispnames.o locdspnm.o loclikely.o locresdata.o \
+lsr.o loclikelysubtags.o locdistance.o localematcher.o \
bytestream.o stringpiece.o bytesinkutil.o \
stringtriebuilder.o bytestriebuilder.o \
bytestrie.o bytestrieiterator.o \
@@ -115,7 +116,8 @@
sharedobject.o simpleformatter.o unifiedcache.o uloc_keytype.o \
ubiditransform.o \
pluralmap.o \
-static_unicode_sets.o
+static_unicode_sets.o \
+restrace.o
## Header files to install
HEADERS = $(srcdir)/unicode/*.h
diff -Nru icu-64.2/source/common/mutex.h icu-65.1/source/common/mutex.h
--- icu-64.2/source/common/mutex.h 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/mutex.h 2019-10-03 11:16:41.000000000 +0000
@@ -28,50 +28,48 @@
U_NAMESPACE_BEGIN
-//----------------------------------------------------------------------------
-// Code within that accesses shared static or global data should
-// should instantiate a Mutex object while doing so. You should make your own
-// private mutex where possible.
-
-// For example:
-//
-// UMutex myMutex = U_MUTEX_INITIALIZER;
-//
-// void Function(int arg1, int arg2)
-// {
-// static Object* foo; // Shared read-write object
-// Mutex mutex(&myMutex); // or no args for the global lock
-// foo->Method();
-// // When 'mutex' goes out of scope and gets destroyed here, the lock is released
-// }
-//
-// Note: Do NOT use the form 'Mutex mutex();' as that merely forward-declares a function
-// returning a Mutex. This is a common mistake which silently slips through the
-// compiler!!
-//
+/**
+ * Mutex is a helper class for convenient locking and unlocking of a UMutex.
+ *
+ * Creating a local scope Mutex will lock a UMutex, holding the lock until the Mutex
+ * goes out of scope.
+ *
+ * If no UMutex is specified, the ICU global mutex is implied.
+ *
+ * For example:
+ *
+ * static UMutex myMutex;
+ *
+ * void Function(int arg1, int arg2)
+ * {
+ * static Object* foo; // Shared read-write object
+ * Mutex mutex(&myMutex); // or no args for the global lock
+ * foo->Method();
+ * // When 'mutex' goes out of scope and gets destroyed here, the lock is released
+ * }
+ *
+ * Note: Do NOT use the form 'Mutex mutex();' as that merely forward-declares a function
+ * returning a Mutex. This is a common mistake which silently slips through the
+ * compiler!!
+ */
class U_COMMON_API Mutex : public UMemory {
public:
- inline Mutex(UMutex *mutex = NULL);
- inline ~Mutex();
+ Mutex(UMutex *mutex = nullptr) : fMutex(mutex) {
+ umtx_lock(fMutex);
+ }
+ ~Mutex() {
+ umtx_unlock(fMutex);
+ }
+
+ Mutex(const Mutex &other) = delete; // forbid assigning of this class
+ Mutex &operator=(const Mutex &other) = delete; // forbid copying of this class
+ void *operator new(size_t s) = delete; // forbid heap allocation. Locals only.
private:
- UMutex *fMutex;
-
- Mutex(const Mutex &other); // forbid copying of this class
- Mutex &operator=(const Mutex &other); // forbid copying of this class
+ UMutex *fMutex;
};
-inline Mutex::Mutex(UMutex *mutex)
- : fMutex(mutex)
-{
- umtx_lock(fMutex);
-}
-
-inline Mutex::~Mutex()
-{
- umtx_unlock(fMutex);
-}
U_NAMESPACE_END
diff -Nru icu-64.2/source/common/normalizer2impl.h icu-65.1/source/common/normalizer2impl.h
--- icu-64.2/source/common/normalizer2impl.h 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/normalizer2impl.h 2019-10-03 11:16:41.000000000 +0000
@@ -245,9 +245,7 @@
*/
class U_COMMON_API Normalizer2Impl : public UObject {
public:
- Normalizer2Impl() : normTrie(NULL), fCanonIterData(NULL) {
- fCanonIterDataInitOnce.reset();
- }
+ Normalizer2Impl() : normTrie(NULL), fCanonIterData(NULL) { }
virtual ~Normalizer2Impl();
void init(const int32_t *inIndexes, const UCPTrie *inTrie,
@@ -723,7 +721,7 @@
const uint16_t *extraData; // mappings and/or compositions for yesYes, yesNo & noNo characters
const uint8_t *smallFCD; // [0x100] one bit per 32 BMP code points, set if any FCD!=0
- UInitOnce fCanonIterDataInitOnce;
+ UInitOnce fCanonIterDataInitOnce = U_INITONCE_INITIALIZER;
CanonIterData *fCanonIterData;
};
diff -Nru icu-64.2/source/common/putil.cpp icu-65.1/source/common/putil.cpp
--- icu-64.2/source/common/putil.cpp 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/putil.cpp 2019-10-03 11:16:41.000000000 +0000
@@ -249,7 +249,7 @@
}
static UDate getUTCtime_fake() {
- static UMutex fakeClockMutex = U_MUTEX_INTIALIZER;
+ static UMutex fakeClockMutex;
umtx_lock(&fakeClockMutex);
if(!fakeClock_set) {
UDate real = getUTCtime_real();
@@ -1315,11 +1315,10 @@
# endif
#endif
-#if U_PLATFORM_HAS_WINUWP_API != 0
+#if defined(ICU_DATA_DIR_WINDOWS)
// Helper function to get the ICU Data Directory under the Windows directory location.
static BOOL U_CALLCONV getIcuDataDirectoryUnderWindowsDirectory(char* directoryBuffer, UINT bufferLength)
{
-#if defined(ICU_DATA_DIR_WINDOWS)
wchar_t windowsPath[MAX_PATH];
char windowsPathUtf8[MAX_PATH];
@@ -1346,7 +1345,6 @@
}
}
}
-#endif
return FALSE;
}
@@ -1380,9 +1378,9 @@
*/
# if !defined(ICU_NO_USER_DATA_OVERRIDE) && !UCONFIG_NO_FILE_IO
/* First try to get the environment variable */
-# if U_PLATFORM_HAS_WINUWP_API == 0 // Windows UWP does not support getenv
+# if U_PLATFORM_HAS_WINUWP_API == 0 // Windows UWP does not support getenv
path=getenv("ICU_DATA");
-# endif
+# endif
# endif
/* ICU_DATA_DIR may be set as a compile option.
@@ -1411,7 +1409,7 @@
}
#endif
-#if U_PLATFORM_HAS_WINUWP_API != 0 && defined(ICU_DATA_DIR_WINDOWS)
+#if defined(ICU_DATA_DIR_WINDOWS)
char datadir_path_buffer[MAX_PATH];
if (getIcuDataDirectoryUnderWindowsDirectory(datadir_path_buffer, UPRV_LENGTHOF(datadir_path_buffer))) {
path = datadir_path_buffer;
@@ -1461,12 +1459,17 @@
const char *dir = "";
-#if U_PLATFORM_HAS_WINUWP_API != 0
- // The UWP version does not support the environment variable setting, but can possibly pick them up from the Windows directory.
+#if U_PLATFORM_HAS_WINUWP_API == 1
+// The UWP version does not support the environment variable setting.
+
+# if defined(ICU_DATA_DIR_WINDOWS)
+ // When using the Windows system data, we can possibly pick up time zone data from the Windows directory.
char datadir_path_buffer[MAX_PATH];
if (getIcuDataDirectoryUnderWindowsDirectory(datadir_path_buffer, UPRV_LENGTHOF(datadir_path_buffer))) {
dir = datadir_path_buffer;
}
+# endif
+
#else
dir = getenv("ICU_TIMEZONE_FILES_DIR");
#endif // U_PLATFORM_HAS_WINUWP_API
@@ -1560,6 +1563,10 @@
{
/* Nothing worked. Give it a nice POSIX default value. */
posixID = "en_US_POSIX";
+ // Note: this test will not catch 'C.UTF-8',
+ // that will be handled in uprv_getDefaultLocaleID().
+ // Leave this mapping here for the uprv_getPOSIXIDForDefaultCodepage()
+ // caller which expects to see "en_US_POSIX" in many branches.
}
return posixID;
}
@@ -1631,8 +1638,8 @@
}
// Copy the ID into owned memory.
- // Over-allocate in case we replace "@" with "__".
- char *correctedPOSIXLocale = static_cast(uprv_malloc(uprv_strlen(posixID) + 1 + 1));
+ // Over-allocate in case we replace "C" with "en_US_POSIX" (+10), + null termination
+ char *correctedPOSIXLocale = static_cast(uprv_malloc(uprv_strlen(posixID) + 10 + 1));
if (correctedPOSIXLocale == nullptr) {
return nullptr;
}
@@ -1641,11 +1648,18 @@
char *limit;
if ((limit = uprv_strchr(correctedPOSIXLocale, '.')) != nullptr) {
*limit = 0;
- if ((limit = uprv_strchr(correctedPOSIXLocale, '@')) != nullptr) {
- *limit = 0;
- }
+ }
+ if ((limit = uprv_strchr(correctedPOSIXLocale, '@')) != nullptr) {
+ *limit = 0;
}
+ if ((uprv_strcmp("C", correctedPOSIXLocale) == 0) // no @ variant
+ || (uprv_strcmp("POSIX", correctedPOSIXLocale) == 0)) {
+ // Raw input was C.* or POSIX.*, Give it a nice POSIX default value.
+ // (The "C"/"POSIX" case is handled in uprv_getPOSIXIDForCategory())
+ uprv_strcpy(correctedPOSIXLocale, "en_US_POSIX");
+ }
+
/* Note that we scan the *uncorrected* ID. */
const char *p;
if ((p = uprv_strrchr(posixID, '@')) != nullptr) {
@@ -1668,7 +1682,7 @@
if ((q = uprv_strchr(p, '.')) != nullptr) {
/* How big will the resulting string be? */
int32_t len = (int32_t)(uprv_strlen(correctedPOSIXLocale) + (q-p));
- uprv_strncat(correctedPOSIXLocale, p, q-p);
+ uprv_strncat(correctedPOSIXLocale, p, q-p); // do not include charset
correctedPOSIXLocale[len] = 0;
}
else {
@@ -2053,7 +2067,7 @@
static char codepage[64];
DWORD codepageNumber = 0;
-#if U_PLATFORM_HAS_WINUWP_API > 0
+#if U_PLATFORM_HAS_WINUWP_API == 1
// UWP doesn't have a direct API to get the default ACP as Microsoft would rather
// have folks use Unicode than a "system" code page, however this is the same
// codepage as the system default locale codepage. (FWIW, the system locale is
diff -Nru icu-64.2/source/common/putilimp.h icu-65.1/source/common/putilimp.h
--- icu-64.2/source/common/putilimp.h 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/putilimp.h 2019-10-03 11:16:41.000000000 +0000
@@ -179,76 +179,6 @@
/** @} */
/*===========================================================================*/
-/** @{ GCC built in functions for atomic memory operations */
-/*===========================================================================*/
-
-/**
- * \def U_HAVE_GCC_ATOMICS
- * @internal
- */
-#ifdef U_HAVE_GCC_ATOMICS
- /* Use the predefined value. */
-#elif U_PLATFORM == U_PF_MINGW
- #define U_HAVE_GCC_ATOMICS 0
-#elif U_GCC_MAJOR_MINOR >= 404 || defined(__clang__)
- /* TODO: Intel icc and IBM xlc on AIX also support gcc atomics. (Intel originated them.)
- * Add them for these compilers.
- * Note: Clang sets __GNUC__ defines for version 4.2, so misses the 4.4 test here.
- */
-# define U_HAVE_GCC_ATOMICS 1
-#else
-# define U_HAVE_GCC_ATOMICS 0
-#endif
-
-/** @} */
-
-/**
- * \def U_HAVE_STD_ATOMICS
- * Defines whether to use the C++11 std::atomic functions.
- * If false, ICU will fall back to compiler or platform specific alternatives.
- * Note: support for these fall back options for atomics will be removed in a future version
- * of ICU, and the use of C++ 11 atomics will be required.
- * @internal
- */
-#ifdef U_HAVE_STD_ATOMICS
- /* Use the predefined value. */
-#else
-# define U_HAVE_STD_ATOMICS 1
-#endif
-
-/**
- * \def U_HAVE_CLANG_ATOMICS
- * Defines whether Clang c11 style built-in atomics are available.
- * These are used in preference to gcc atomics when both are available.
- */
-#ifdef U_HAVE_CLANG_ATOMICS
- /* Use the predefined value. */
-#elif __has_builtin(__c11_atomic_load) && \
- __has_builtin(__c11_atomic_store) && \
- __has_builtin(__c11_atomic_fetch_add) && \
- __has_builtin(__c11_atomic_fetch_sub)
-# define U_HAVE_CLANG_ATOMICS 1
-#else
-# define U_HAVE_CLANG_ATOMICS 0
-#endif
-
-
-/**
- * \def U_HAVE_STD_MUTEX
- * Defines whether to use the C++11 std::mutex functions.
- * If false, ICU will fall back to compiler or platform specific alternatives.
- * std::mutex is preferred, and used by default unless this setting is overridden.
- * Note: support for other options for mutexes will be removed in a future version
- * of ICU, and the use of std::mutex will be required.
- * @internal
- */
-#ifdef U_HAVE_STD_MUTEX
- /* Use the predefined value. */
-#else
-# define U_HAVE_STD_MUTEX 1
-#endif
-
-/*===========================================================================*/
/** @{ Programs used by ICU code */
/*===========================================================================*/
diff -Nru icu-64.2/source/common/rbbi_cache.cpp icu-65.1/source/common/rbbi_cache.cpp
--- icu-64.2/source/common/rbbi_cache.cpp 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/rbbi_cache.cpp 2019-10-03 11:16:41.000000000 +0000
@@ -519,7 +519,7 @@
// The initial handleNext() only advanced by a single code point. Go again.
position = fBI->handleNext(); // Safe rules identify safe pairs.
}
- };
+ }
positionStatusIdx = fBI->fRuleStatusIndex;
}
} while (position >= fromPosition);
diff -Nru icu-64.2/source/common/rbbi.cpp icu-65.1/source/common/rbbi.cpp
--- icu-64.2/source/common/rbbi.cpp 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/rbbi.cpp 2019-10-03 11:16:41.000000000 +0000
@@ -323,8 +323,8 @@
// Virtual function: does the right thing with subclasses.
//
//-----------------------------------------------------------------------------
-BreakIterator*
-RuleBasedBreakIterator::clone(void) const {
+RuleBasedBreakIterator*
+RuleBasedBreakIterator::clone() const {
return new RuleBasedBreakIterator(*this);
}
@@ -352,7 +352,7 @@
// or have a different iteration position.
// Note that fText's position is always the same as the break iterator's position.
return FALSE;
- };
+ }
if (!(fPosition == that2.fPosition &&
fRuleStatusIndex == that2.fRuleStatusIndex &&
@@ -1079,10 +1079,8 @@
}
-BreakIterator * RuleBasedBreakIterator::createBufferClone(void * /*stackBuffer*/,
- int32_t &bufferSize,
- UErrorCode &status)
-{
+RuleBasedBreakIterator *RuleBasedBreakIterator::createBufferClone(
+ void * /*stackBuffer*/, int32_t &bufferSize, UErrorCode &status) {
if (U_FAILURE(status)){
return NULL;
}
diff -Nru icu-64.2/source/common/resbund.cpp icu-65.1/source/common/resbund.cpp
--- icu-64.2/source/common/resbund.cpp 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/resbund.cpp 2019-10-03 11:16:41.000000000 +0000
@@ -51,6 +51,7 @@
#include "unicode/utypes.h"
#include "unicode/resbund.h"
+#include "cmemory.h"
#include "mutex.h"
#include "uassert.h"
#include "umutex.h"
@@ -377,7 +378,7 @@
}
const Locale &ResourceBundle::getLocale(void) const {
- static UMutex gLocaleLock = U_MUTEX_INITIALIZER;
+ static UMutex gLocaleLock;
Mutex lock(&gLocaleLock);
if (fLocale != NULL) {
return *fLocale;
diff -Nru icu-64.2/source/common/resource.h icu-65.1/source/common/resource.h
--- icu-64.2/source/common/resource.h 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/resource.h 2019-10-03 11:16:41.000000000 +0000
@@ -28,6 +28,7 @@
#include "unicode/utypes.h"
#include "unicode/unistr.h"
#include "unicode/ures.h"
+#include "restrace.h"
struct ResourceData;
@@ -47,8 +48,10 @@
ResourceArray() : items16(NULL), items32(NULL), length(0) {}
/** Only for implementation use. @internal */
- ResourceArray(const uint16_t *i16, const uint32_t *i32, int32_t len) :
- items16(i16), items32(i32), length(len) {}
+ ResourceArray(const uint16_t *i16, const uint32_t *i32, int32_t len,
+ const ResourceTracer& traceInfo) :
+ items16(i16), items32(i32), length(len),
+ fTraceInfo(traceInfo) {}
/**
* @return The number of items in the array resource.
@@ -68,6 +71,7 @@
const uint16_t *items16;
const uint32_t *items32;
int32_t length;
+ ResourceTracer fTraceInfo;
};
/**
@@ -80,27 +84,37 @@
/** Only for implementation use. @internal */
ResourceTable(const uint16_t *k16, const int32_t *k32,
- const uint16_t *i16, const uint32_t *i32, int32_t len) :
- keys16(k16), keys32(k32), items16(i16), items32(i32), length(len) {}
+ const uint16_t *i16, const uint32_t *i32, int32_t len,
+ const ResourceTracer& traceInfo) :
+ keys16(k16), keys32(k32), items16(i16), items32(i32), length(len),
+ fTraceInfo(traceInfo) {}
/**
* @return The number of items in the array resource.
*/
int32_t getSize() const { return length; }
/**
- * @param i Array item index.
+ * @param i Table item index.
* @param key Output-only, receives the key of the i'th item.
* @param value Output-only, receives the value of the i'th item.
* @return TRUE if i is non-negative and less than getSize().
*/
UBool getKeyAndValue(int32_t i, const char *&key, ResourceValue &value) const;
+ /**
+ * @param key Key string to find in the table.
+ * @param value Output-only, receives the value of the item with that key.
+ * @return TRUE if the table contains the key.
+ */
+ UBool findValue(const char *key, ResourceValue &value) const;
+
private:
const uint16_t *keys16;
const int32_t *keys32;
const uint16_t *items16;
const uint32_t *items32;
int32_t length;
+ ResourceTracer fTraceInfo;
};
/**
diff -Nru icu-64.2/source/common/restrace.cpp icu-65.1/source/common/restrace.cpp
--- icu-64.2/source/common/restrace.cpp 1970-01-01 00:00:00.000000000 +0000
+++ icu-65.1/source/common/restrace.cpp 2019-10-03 11:16:41.000000000 +0000
@@ -0,0 +1,130 @@
+// © 2019 and later: Unicode, Inc. and others.
+// License & terms of use: http://www.unicode.org/copyright.html
+
+#include "unicode/utypes.h"
+
+#if U_ENABLE_TRACING
+
+#include "restrace.h"
+#include "charstr.h"
+#include "cstring.h"
+#include "utracimp.h"
+#include "uresimp.h"
+#include "uassert.h"
+#include "util.h"
+
+U_NAMESPACE_BEGIN
+
+ResourceTracer::~ResourceTracer() = default;
+
+void ResourceTracer::trace(const char* resType) const {
+ U_ASSERT(fResB || fParent);
+ UTRACE_ENTRY(UTRACE_UDATA_RESOURCE);
+ UErrorCode status = U_ZERO_ERROR;
+
+ CharString filePath;
+ getFilePath(filePath, status);
+
+ CharString resPath;
+ getResPath(resPath, status);
+
+ // The longest type ("intvector") is 9 chars
+ const char kSpaces[] = " ";
+ CharString format;
+ format.append(kSpaces, sizeof(kSpaces) - 1 - uprv_strlen(resType), status);
+ format.append("(%s) %s @ %s", status);
+
+ UTRACE_DATA3(UTRACE_VERBOSE,
+ format.data(),
+ resType,
+ filePath.data(),
+ resPath.data());
+ UTRACE_EXIT_STATUS(status);
+}
+
+void ResourceTracer::traceOpen() const {
+ U_ASSERT(fResB);
+ UTRACE_ENTRY(UTRACE_UDATA_BUNDLE);
+ UErrorCode status = U_ZERO_ERROR;
+
+ CharString filePath;
+ UTRACE_DATA1(UTRACE_VERBOSE, "%s", getFilePath(filePath, status).data());
+ UTRACE_EXIT_STATUS(status);
+}
+
+CharString& ResourceTracer::getFilePath(CharString& output, UErrorCode& status) const {
+ if (fResB) {
+ output.append(fResB->fData->fPath, status);
+ output.append('/', status);
+ output.append(fResB->fData->fName, status);
+ output.append(".res", status);
+ } else {
+ fParent->getFilePath(output, status);
+ }
+ return output;
+}
+
+CharString& ResourceTracer::getResPath(CharString& output, UErrorCode& status) const {
+ if (fResB) {
+ output.append('/', status);
+ output.append(fResB->fResPath, status);
+ // removing the trailing /
+ U_ASSERT(output[output.length()-1] == '/');
+ output.truncate(output.length()-1);
+ } else {
+ fParent->getResPath(output, status);
+ }
+ if (fKey) {
+ output.append('/', status);
+ output.append(fKey, status);
+ }
+ if (fIndex != -1) {
+ output.append('[', status);
+ UnicodeString indexString;
+ ICU_Utility::appendNumber(indexString, fIndex);
+ output.appendInvariantChars(indexString, status);
+ output.append(']', status);
+ }
+ return output;
+}
+
+void FileTracer::traceOpen(const char* path, const char* type, const char* name) {
+ if (uprv_strcmp(type, "res") == 0) {
+ traceOpenResFile(path, name);
+ } else {
+ traceOpenDataFile(path, type, name);
+ }
+}
+
+void FileTracer::traceOpenDataFile(const char* path, const char* type, const char* name) {
+ UTRACE_ENTRY(UTRACE_UDATA_DATA_FILE);
+ UErrorCode status = U_ZERO_ERROR;
+
+ CharString filePath;
+ filePath.append(path, status);
+ filePath.append('/', status);
+ filePath.append(name, status);
+ filePath.append('.', status);
+ filePath.append(type, status);
+
+ UTRACE_DATA1(UTRACE_VERBOSE, "%s", filePath.data());
+ UTRACE_EXIT_STATUS(status);
+}
+
+void FileTracer::traceOpenResFile(const char* path, const char* name) {
+ UTRACE_ENTRY(UTRACE_UDATA_RES_FILE);
+ UErrorCode status = U_ZERO_ERROR;
+
+ CharString filePath;
+ filePath.append(path, status);
+ filePath.append('/', status);
+ filePath.append(name, status);
+ filePath.append(".res", status);
+
+ UTRACE_DATA1(UTRACE_VERBOSE, "%s", filePath.data());
+ UTRACE_EXIT_STATUS(status);
+}
+
+U_NAMESPACE_END
+
+#endif // U_ENABLE_TRACING
diff -Nru icu-64.2/source/common/restrace.h icu-65.1/source/common/restrace.h
--- icu-64.2/source/common/restrace.h 1970-01-01 00:00:00.000000000 +0000
+++ icu-65.1/source/common/restrace.h 2019-10-03 11:16:41.000000000 +0000
@@ -0,0 +1,147 @@
+// © 2019 and later: Unicode, Inc. and others.
+// License & terms of use: http://www.unicode.org/copyright.html
+
+#ifndef __RESTRACE_H__
+#define __RESTRACE_H__
+
+#include "unicode/utypes.h"
+
+#if U_ENABLE_TRACING
+
+struct UResourceBundle;
+
+U_NAMESPACE_BEGIN
+
+class CharString;
+
+/**
+ * Instances of this class store information used to trace reads from resource
+ * bundles when ICU is built with --enable-tracing.
+ *
+ * All arguments of type const UResourceBundle*, const char*, and
+ * const ResourceTracer& are stored as pointers. The caller must retain
+ * ownership for the lifetime of this ResourceTracer.
+ *
+ * Exported as U_COMMON_API for Windows because it is a value field
+ * in other exported types.
+ */
+class U_COMMON_API ResourceTracer {
+public:
+ ResourceTracer() :
+ fResB(nullptr),
+ fParent(nullptr),
+ fKey(nullptr),
+ fIndex(-1) {}
+
+ ResourceTracer(const UResourceBundle* resB) :
+ fResB(resB),
+ fParent(nullptr),
+ fKey(nullptr),
+ fIndex(-1) {}
+
+ ResourceTracer(const UResourceBundle* resB, const char* key) :
+ fResB(resB),
+ fParent(nullptr),
+ fKey(key),
+ fIndex(-1) {}
+
+ ResourceTracer(const UResourceBundle* resB, int32_t index) :
+ fResB(resB),
+ fParent(nullptr),
+ fKey(nullptr),
+ fIndex(index) {}
+
+ ResourceTracer(const ResourceTracer& parent, const char* key) :
+ fResB(nullptr),
+ fParent(&parent),
+ fKey(key),
+ fIndex(-1) {}
+
+ ResourceTracer(const ResourceTracer& parent, int32_t index) :
+ fResB(nullptr),
+ fParent(&parent),
+ fKey(nullptr),
+ fIndex(index) {}
+
+ ~ResourceTracer();
+
+ void trace(const char* type) const;
+ void traceOpen() const;
+
+ /**
+ * Calls trace() if the resB or parent provided to the constructor was
+ * non-null; otherwise, does nothing.
+ */
+ void maybeTrace(const char* type) const {
+ if (fResB || fParent) {
+ trace(type);
+ }
+ }
+
+private:
+ const UResourceBundle* fResB;
+ const ResourceTracer* fParent;
+ const char* fKey;
+ int32_t fIndex;
+
+ CharString& getFilePath(CharString& output, UErrorCode& status) const;
+
+ CharString& getResPath(CharString& output, UErrorCode& status) const;
+};
+
+/**
+ * This class provides methods to trace data file reads when ICU is built
+ * with --enable-tracing.
+ */
+class FileTracer {
+public:
+ static void traceOpen(const char* path, const char* type, const char* name);
+
+private:
+ static void traceOpenDataFile(const char* path, const char* type, const char* name);
+ static void traceOpenResFile(const char* path, const char* name);
+};
+
+U_NAMESPACE_END
+
+#else // U_ENABLE_TRACING
+
+U_NAMESPACE_BEGIN
+
+/**
+ * Default trivial implementation when --enable-tracing is not used.
+ */
+class U_COMMON_API ResourceTracer {
+public:
+ ResourceTracer() {}
+
+ ResourceTracer(const void*) {}
+
+ ResourceTracer(const void*, const char*) {}
+
+ ResourceTracer(const void*, int32_t) {}
+
+ ResourceTracer(const ResourceTracer&, const char*) {}
+
+ ResourceTracer(const ResourceTracer&, int32_t) {}
+
+ void trace(const char*) const {}
+
+ void traceOpen() const {}
+
+ void maybeTrace(const char*) const {}
+};
+
+/**
+ * Default trivial implementation when --enable-tracing is not used.
+ */
+class FileTracer {
+public:
+ static void traceOpen(const char*, const char*, const char*) {}
+};
+
+U_NAMESPACE_END
+
+#endif // U_ENABLE_TRACING
+
+#endif //__RESTRACE_H__
diff -Nru icu-64.2/source/common/schriter.cpp icu-65.1/source/common/schriter.cpp
--- icu-64.2/source/common/schriter.cpp 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/schriter.cpp 2019-10-03 11:16:41.000000000 +0000
@@ -101,7 +101,7 @@
&& end == realThat.end;
}
-CharacterIterator*
+StringCharacterIterator*
StringCharacterIterator::clone() const {
return new StringCharacterIterator(*this);
}
diff -Nru icu-64.2/source/common/serv.cpp icu-65.1/source/common/serv.cpp
--- icu-64.2/source/common/serv.cpp 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/serv.cpp 2019-10-03 11:16:41.000000000 +0000
@@ -333,10 +333,7 @@
******************************************************************
*/
-static UMutex *lock() {
- static UMutex m = U_MUTEX_INITIALIZER;
- return &m;
-}
+static UMutex lock;
ICUService::ICUService()
: name()
@@ -361,7 +358,7 @@
ICUService::~ICUService()
{
{
- Mutex mutex(lock());
+ Mutex mutex(&lock);
clearCaches();
delete factories;
factories = NULL;
@@ -452,7 +449,7 @@
// if factory is not null, we're calling from within the mutex,
// and since some unix machines don't have reentrant mutexes we
// need to make sure not to try to lock it again.
- XMutex mutex(lock(), factory != NULL);
+ XMutex mutex(&lock, factory != NULL);
if (serviceCache == NULL) {
ncthis->serviceCache = new Hashtable(status);
@@ -618,7 +615,7 @@
}
{
- Mutex mutex(lock());
+ Mutex mutex(&lock);
const Hashtable* map = getVisibleIDMap(status);
if (map != NULL) {
ICUServiceKey* fallbackKey = createKey(matchID, status);
@@ -695,7 +692,7 @@
{
{
UErrorCode status = U_ZERO_ERROR;
- Mutex mutex(lock());
+ Mutex mutex(&lock);
const Hashtable* map = getVisibleIDMap(status);
if (map != NULL) {
ICUServiceFactory* f = (ICUServiceFactory*)map->get(id);
@@ -747,7 +744,7 @@
result.setDeleter(userv_deleteStringPair);
if (U_SUCCESS(status)) {
ICUService* ncthis = (ICUService*)this; // cast away semantic const
- Mutex mutex(lock());
+ Mutex mutex(&lock);
if (dnCache != NULL && dnCache->locale != locale) {
delete dnCache;
@@ -852,7 +849,7 @@
ICUService::registerFactory(ICUServiceFactory* factoryToAdopt, UErrorCode& status)
{
if (U_SUCCESS(status) && factoryToAdopt != NULL) {
- Mutex mutex(lock());
+ Mutex mutex(&lock);
if (factories == NULL) {
factories = new UVector(deleteUObject, NULL, status);
@@ -883,7 +880,7 @@
ICUServiceFactory *factory = (ICUServiceFactory*)rkey;
UBool result = FALSE;
if (factory != NULL && factories != NULL) {
- Mutex mutex(lock());
+ Mutex mutex(&lock);
if (factories->removeElement(factory)) {
clearCaches();
@@ -903,7 +900,7 @@
ICUService::reset()
{
{
- Mutex mutex(lock());
+ Mutex mutex(&lock);
reInitializeFactories();
clearCaches();
}
diff -Nru icu-64.2/source/common/servls.cpp icu-65.1/source/common/servls.cpp
--- icu-64.2/source/common/servls.cpp 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/servls.cpp 2019-10-03 11:16:41.000000000 +0000
@@ -263,7 +263,7 @@
{
const Locale& loc = Locale::getDefault();
ICULocaleService* ncThis = (ICULocaleService*)this;
- static UMutex llock = U_MUTEX_INITIALIZER;
+ static UMutex llock;
{
Mutex mutex(&llock);
if (loc != fallbackLocale) {
diff -Nru icu-64.2/source/common/servnotf.cpp icu-65.1/source/common/servnotf.cpp
--- icu-64.2/source/common/servnotf.cpp 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/servnotf.cpp 2019-10-03 11:16:41.000000000 +0000
@@ -21,10 +21,7 @@
EventListener::~EventListener() {}
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(EventListener)
-static UMutex *notifyLock() {
- static UMutex m = U_MUTEX_INITIALIZER;
- return &m;
-}
+static UMutex notifyLock;
ICUNotifier::ICUNotifier(void)
: listeners(NULL)
@@ -33,7 +30,7 @@
ICUNotifier::~ICUNotifier(void) {
{
- Mutex lmx(notifyLock());
+ Mutex lmx(¬ifyLock);
delete listeners;
listeners = NULL;
}
@@ -50,7 +47,7 @@
}
if (acceptsListener(*l)) {
- Mutex lmx(notifyLock());
+ Mutex lmx(¬ifyLock);
if (listeners == NULL) {
listeners = new UVector(5, status);
} else {
@@ -83,7 +80,7 @@
}
{
- Mutex lmx(notifyLock());
+ Mutex lmx(¬ifyLock);
if (listeners != NULL) {
// identity equality check
for (int i = 0, e = listeners->size(); i < e; ++i) {
@@ -106,7 +103,7 @@
ICUNotifier::notifyChanged(void)
{
if (listeners != NULL) {
- Mutex lmx(notifyLock());
+ Mutex lmx(¬ifyLock);
if (listeners != NULL) {
for (int i = 0, e = listeners->size(); i < e; ++i) {
EventListener* el = (EventListener*)listeners->elementAt(i);
diff -Nru icu-64.2/source/common/uarrsort.cpp icu-65.1/source/common/uarrsort.cpp
--- icu-64.2/source/common/uarrsort.cpp 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/uarrsort.cpp 2019-10-03 11:16:41.000000000 +0000
@@ -34,6 +34,10 @@
STACK_ITEM_SIZE=200
};
+static constexpr int32_t sizeInMaxAlignTs(int32_t sizeInBytes) {
+ return (sizeInBytes + sizeof(max_align_t) - 1) / sizeof(max_align_t);
+}
+
/* UComparator convenience implementations ---------------------------------- */
U_CAPI int32_t U_EXPORT2
@@ -134,25 +138,15 @@
static void
insertionSort(char *array, int32_t length, int32_t itemSize,
UComparator *cmp, const void *context, UErrorCode *pErrorCode) {
- UAlignedMemory v[STACK_ITEM_SIZE/sizeof(UAlignedMemory)+1];
- void *pv;
- /* allocate an intermediate item variable (v) */
- if(itemSize<=STACK_ITEM_SIZE) {
- pv=v;
- } else {
- pv=uprv_malloc(itemSize);
- if(pv==NULL) {
- *pErrorCode=U_MEMORY_ALLOCATION_ERROR;
- return;
- }
+ icu::MaybeStackArray v;
+ if (sizeInMaxAlignTs(itemSize) > v.getCapacity() &&
+ v.resize(sizeInMaxAlignTs(itemSize)) == nullptr) {
+ *pErrorCode = U_MEMORY_ALLOCATION_ERROR;
+ return;
}
- doInsertionSort(array, length, itemSize, cmp, context, pv);
-
- if(pv!=v) {
- uprv_free(pv);
- }
+ doInsertionSort(array, length, itemSize, cmp, context, v.getAlias());
}
/* QuickSort ---------------------------------------------------------------- */
@@ -238,26 +232,16 @@
static void
quickSort(char *array, int32_t length, int32_t itemSize,
UComparator *cmp, const void *context, UErrorCode *pErrorCode) {
- UAlignedMemory xw[(2*STACK_ITEM_SIZE)/sizeof(UAlignedMemory)+1];
- void *p;
-
/* allocate two intermediate item variables (x and w) */
- if(itemSize<=STACK_ITEM_SIZE) {
- p=xw;
- } else {
- p=uprv_malloc(2*itemSize);
- if(p==NULL) {
- *pErrorCode=U_MEMORY_ALLOCATION_ERROR;
- return;
- }
+ icu::MaybeStackArray xw;
+ if(sizeInMaxAlignTs(itemSize)*2 > xw.getCapacity() &&
+ xw.resize(sizeInMaxAlignTs(itemSize) * 2) == nullptr) {
+ *pErrorCode=U_MEMORY_ALLOCATION_ERROR;
+ return;
}
- subQuickSort(array, 0, length, itemSize,
- cmp, context, p, (char *)p+itemSize);
-
- if(p!=xw) {
- uprv_free(p);
- }
+ subQuickSort(array, 0, length, itemSize, cmp, context,
+ xw.getAlias(), xw.getAlias() + sizeInMaxAlignTs(itemSize));
}
/* uprv_sortArray() API ----------------------------------------------------- */
diff -Nru icu-64.2/source/common/ubidiimp.h icu-65.1/source/common/ubidiimp.h
--- icu-64.2/source/common/ubidiimp.h 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/ubidiimp.h 2019-10-03 11:16:41.000000000 +0000
@@ -198,8 +198,8 @@
/* in a Run, logicalStart will get this bit set if the run level is odd */
#define INDEX_ODD_BIT (1UL<<31)
-#define MAKE_INDEX_ODD_PAIR(index, level) ((index)|((int32_t)(level)<<31))
-#define ADD_ODD_BIT_FROM_LEVEL(x, level) ((x)|=((int32_t)(level)<<31))
+#define MAKE_INDEX_ODD_PAIR(index, level) ((index)|((int32_t)((level)&1)<<31))
+#define ADD_ODD_BIT_FROM_LEVEL(x, level) ((x)|=((int32_t)((level)&1)<<31))
#define REMOVE_ODD_BIT(x) ((x)&=~INDEX_ODD_BIT)
#define GET_INDEX(x) ((x)&~INDEX_ODD_BIT)
@@ -387,41 +387,49 @@
} BidiMemoryForAllocation;
/* Macros for initial checks at function entry */
-#define RETURN_IF_NULL_OR_FAILING_ERRCODE(pErrcode, retvalue) \
- if((pErrcode)==NULL || U_FAILURE(*pErrcode)) return retvalue
-#define RETURN_IF_NOT_VALID_PARA(bidi, errcode, retvalue) \
- if(!IS_VALID_PARA(bidi)) { \
- errcode=U_INVALID_STATE_ERROR; \
- return retvalue; \
- }
-#define RETURN_IF_NOT_VALID_PARA_OR_LINE(bidi, errcode, retvalue) \
- if(!IS_VALID_PARA_OR_LINE(bidi)) { \
- errcode=U_INVALID_STATE_ERROR; \
- return retvalue; \
- }
-#define RETURN_IF_BAD_RANGE(arg, start, limit, errcode, retvalue) \
- if((arg)<(start) || (arg)>=(limit)) { \
- (errcode)=U_ILLEGAL_ARGUMENT_ERROR; \
- return retvalue; \
- }
-
-#define RETURN_VOID_IF_NULL_OR_FAILING_ERRCODE(pErrcode) \
- if((pErrcode)==NULL || U_FAILURE(*pErrcode)) return
-#define RETURN_VOID_IF_NOT_VALID_PARA(bidi, errcode) \
- if(!IS_VALID_PARA(bidi)) { \
- errcode=U_INVALID_STATE_ERROR; \
- return; \
- }
-#define RETURN_VOID_IF_NOT_VALID_PARA_OR_LINE(bidi, errcode) \
- if(!IS_VALID_PARA_OR_LINE(bidi)) { \
- errcode=U_INVALID_STATE_ERROR; \
- return; \
- }
-#define RETURN_VOID_IF_BAD_RANGE(arg, start, limit, errcode) \
- if((arg)<(start) || (arg)>=(limit)) { \
- (errcode)=U_ILLEGAL_ARGUMENT_ERROR; \
- return; \
- }
+#define RETURN_IF_NULL_OR_FAILING_ERRCODE(pErrcode, retvalue) UPRV_BLOCK_MACRO_BEGIN { \
+ if((pErrcode)==NULL || U_FAILURE(*pErrcode)) return retvalue; \
+} UPRV_BLOCK_MACRO_END
+#define RETURN_IF_NOT_VALID_PARA(bidi, errcode, retvalue) UPRV_BLOCK_MACRO_BEGIN { \
+ if(!IS_VALID_PARA(bidi)) { \
+ errcode=U_INVALID_STATE_ERROR; \
+ return retvalue; \
+ } \
+} UPRV_BLOCK_MACRO_END
+#define RETURN_IF_NOT_VALID_PARA_OR_LINE(bidi, errcode, retvalue) UPRV_BLOCK_MACRO_BEGIN { \
+ if(!IS_VALID_PARA_OR_LINE(bidi)) { \
+ errcode=U_INVALID_STATE_ERROR; \
+ return retvalue; \
+ } \
+} UPRV_BLOCK_MACRO_END
+#define RETURN_IF_BAD_RANGE(arg, start, limit, errcode, retvalue) UPRV_BLOCK_MACRO_BEGIN { \
+ if((arg)<(start) || (arg)>=(limit)) { \
+ (errcode)=U_ILLEGAL_ARGUMENT_ERROR; \
+ return retvalue; \
+ } \
+} UPRV_BLOCK_MACRO_END
+
+#define RETURN_VOID_IF_NULL_OR_FAILING_ERRCODE(pErrcode) UPRV_BLOCK_MACRO_BEGIN { \
+ if((pErrcode)==NULL || U_FAILURE(*pErrcode)) return; \
+} UPRV_BLOCK_MACRO_END
+#define RETURN_VOID_IF_NOT_VALID_PARA(bidi, errcode) UPRV_BLOCK_MACRO_BEGIN { \
+ if(!IS_VALID_PARA(bidi)) { \
+ errcode=U_INVALID_STATE_ERROR; \
+ return; \
+ } \
+} UPRV_BLOCK_MACRO_END
+#define RETURN_VOID_IF_NOT_VALID_PARA_OR_LINE(bidi, errcode) UPRV_BLOCK_MACRO_BEGIN { \
+ if(!IS_VALID_PARA_OR_LINE(bidi)) { \
+ errcode=U_INVALID_STATE_ERROR; \
+ return; \
+ } \
+} UPRV_BLOCK_MACRO_END
+#define RETURN_VOID_IF_BAD_RANGE(arg, start, limit, errcode) UPRV_BLOCK_MACRO_BEGIN { \
+ if((arg)<(start) || (arg)>=(limit)) { \
+ (errcode)=U_ILLEGAL_ARGUMENT_ERROR; \
+ return; \
+ } \
+} UPRV_BLOCK_MACRO_END
/* helper function to (re)allocate memory if allowed */
U_CFUNC UBool
diff -Nru icu-64.2/source/common/ubiditransform.cpp icu-65.1/source/common/ubiditransform.cpp
--- icu-64.2/source/common/ubiditransform.cpp 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/ubiditransform.cpp 2019-10-03 11:16:41.000000000 +0000
@@ -31,11 +31,11 @@
#define SHAPE_LOGICAL U_SHAPE_TEXT_DIRECTION_LOGICAL
#define SHAPE_VISUAL U_SHAPE_TEXT_DIRECTION_VISUAL_LTR
-#define CHECK_LEN(STR, LEN, ERROR) { \
- if (LEN == 0) return 0; \
- if (LEN < -1) { *(ERROR) = U_ILLEGAL_ARGUMENT_ERROR; return 0; } \
- if (LEN == -1) LEN = u_strlen(STR); \
- }
+#define CHECK_LEN(STR, LEN, ERROR) UPRV_BLOCK_MACRO_BEGIN { \
+ if (LEN == 0) return 0; \
+ if (LEN < -1) { *(ERROR) = U_ILLEGAL_ARGUMENT_ERROR; return 0; } \
+ if (LEN == -1) LEN = u_strlen(STR); \
+} UPRV_BLOCK_MACRO_END
#define MAX_ACTIONS 7
diff -Nru icu-64.2/source/common/ucase.cpp icu-65.1/source/common/ucase.cpp
--- icu-64.2/source/common/ucase.cpp 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/ucase.cpp 2019-10-03 11:16:41.000000000 +0000
@@ -116,7 +116,7 @@
* moved to the last uint16_t of the value, use +1 for beginning of next slot
* @param value (out) int32_t or uint32_t output if hasSlot, otherwise not modified
*/
-#define GET_SLOT_VALUE(excWord, idx, pExc16, value) \
+#define GET_SLOT_VALUE(excWord, idx, pExc16, value) UPRV_BLOCK_MACRO_BEGIN { \
if(((excWord)&UCASE_EXC_DOUBLE_SLOTS)==0) { \
(pExc16)+=SLOT_OFFSET(excWord, idx); \
(value)=*pExc16; \
@@ -124,7 +124,8 @@
(pExc16)+=2*SLOT_OFFSET(excWord, idx); \
(value)=*pExc16++; \
(value)=((value)<<16)|*pExc16; \
- }
+ } \
+} UPRV_BLOCK_MACRO_END
/* simple case mappings ----------------------------------------------------- */
diff -Nru icu-64.2/source/common/uchar.cpp icu-65.1/source/common/uchar.cpp
--- icu-64.2/source/common/uchar.cpp 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/uchar.cpp 2019-10-03 11:16:41.000000000 +0000
@@ -40,7 +40,7 @@
/* constants and macros for access to the data ------------------------------ */
/* getting a uint32_t properties word from the data */
-#define GET_PROPS(c, result) ((result)=UTRIE2_GET16(&propsTrie, c));
+#define GET_PROPS(c, result) ((result)=UTRIE2_GET16(&propsTrie, c))
/* API functions ------------------------------------------------------------ */
diff -Nru icu-64.2/source/common/uchriter.cpp icu-65.1/source/common/uchriter.cpp
--- icu-64.2/source/common/uchriter.cpp 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/uchriter.cpp 2019-10-03 11:16:41.000000000 +0000
@@ -89,7 +89,7 @@
return ustr_hashUCharsN(text, textLength) ^ pos ^ begin ^ end;
}
-CharacterIterator*
+UCharCharacterIterator*
UCharCharacterIterator::clone() const {
return new UCharCharacterIterator(*this);
}
diff -Nru icu-64.2/source/common/ucln_cmn.cpp icu-65.1/source/common/ucln_cmn.cpp
--- icu-64.2/source/common/ucln_cmn.cpp 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/ucln_cmn.cpp 2019-10-03 11:16:41.000000000 +0000
@@ -65,9 +65,20 @@
ucln_common_registerCleanup(ECleanupCommonType type,
cleanupFunc *func)
{
+ // Thread safety messiness: From ticket 10295, calls to registerCleanup() may occur
+ // concurrently. Although such cases should be storing the same value, they raise errors
+ // from the thread sanity checker. Doing the store within a mutex avoids those.
+ // BUT that can trigger a recursive entry into std::call_once() in umutex.cpp when this code,
+ // running from the call_once function, tries to grab the ICU global mutex, which
+ // re-enters the mutex init path. So, work-around by special casing UCLN_COMMON_MUTEX, not
+ // using the ICU global mutex for it.
+ //
+ // No other point in ICU uses std::call_once().
+
U_ASSERT(UCLN_COMMON_START < type && type < UCLN_COMMON_COUNT);
- if (UCLN_COMMON_START < type && type < UCLN_COMMON_COUNT)
- {
+ if (type == UCLN_COMMON_MUTEX) {
+ gCommonCleanupFunctions[type] = func;
+ } else if (UCLN_COMMON_START < type && type < UCLN_COMMON_COUNT) {
icu::Mutex m; // See ticket 10295 for discussion.
gCommonCleanupFunctions[type] = func;
}
diff -Nru icu-64.2/source/common/ucln_cmn.h icu-65.1/source/common/ucln_cmn.h
--- icu-64.2/source/common/ucln_cmn.h 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/ucln_cmn.h 2019-10-03 11:16:41.000000000 +0000
@@ -22,8 +22,6 @@
/* These are the cleanup functions for various APIs. */
/* @return true if cleanup complete successfully.*/
-U_CFUNC UBool umtx_cleanup(void);
-
U_CFUNC UBool utrace_cleanup(void);
U_CFUNC UBool ucln_lib_cleanup(void);
@@ -41,6 +39,8 @@
UCLN_COMMON_LOCALE_KEY_TYPE,
UCLN_COMMON_LOCALE,
UCLN_COMMON_LOCALE_AVAILABLE,
+ UCLN_COMMON_LIKELY_SUBTAGS,
+ UCLN_COMMON_LOCALE_DISTANCE,
UCLN_COMMON_ULOC,
UCLN_COMMON_CURRENCY,
UCLN_COMMON_LOADED_NORMALIZER2,
@@ -62,6 +62,7 @@
*/
UCLN_COMMON_UNIFIED_CACHE,
UCLN_COMMON_URES,
+ UCLN_COMMON_MUTEX, // Mutexes should be the last to be cleaned up.
UCLN_COMMON_COUNT /* This must be last */
} ECleanupCommonType;
diff -Nru icu-64.2/source/common/ucnv2022.cpp icu-65.1/source/common/ucnv2022.cpp
--- icu-64.2/source/common/ucnv2022.cpp 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/ucnv2022.cpp 2019-10-03 11:16:41.000000000 +0000
@@ -3571,20 +3571,11 @@
/*
* Structure for cloning an ISO 2022 converter into a single memory block.
- * ucnv_safeClone() of the converter will align the entire cloneStruct,
- * and then ucnv_safeClone() of the sub-converter may additionally align
- * currentConverter inside the cloneStruct, for which we need the deadSpace
- * after currentConverter.
- * This is because UAlignedMemory may be larger than the actually
- * necessary alignment size for the platform.
- * The other cloneStruct fields will not be moved around,
- * and are aligned properly with cloneStruct's alignment.
*/
struct cloneStruct
{
UConverter cnv;
UConverter currentConverter;
- UAlignedMemory deadSpace;
UConverterDataISO2022 mydata;
};
@@ -3602,6 +3593,10 @@
UConverterDataISO2022 *cnvData;
int32_t i, size;
+ if (U_FAILURE(*status)){
+ return nullptr;
+ }
+
if (*pBufferSize == 0) { /* 'preflighting' request - set needed size into *pBufferSize */
*pBufferSize = (int32_t)sizeof(struct cloneStruct);
return NULL;
@@ -3619,7 +3614,7 @@
/* share the subconverters */
if(cnvData->currentConverter != NULL) {
- size = (int32_t)(sizeof(UConverter) + sizeof(UAlignedMemory)); /* include size of padding */
+ size = (int32_t)sizeof(UConverter);
localClone->mydata.currentConverter =
ucnv_safeClone(cnvData->currentConverter,
&localClone->currentConverter,
diff -Nru icu-64.2/source/common/ucnv_bld.cpp icu-65.1/source/common/ucnv_bld.cpp
--- icu-64.2/source/common/ucnv_bld.cpp 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/ucnv_bld.cpp 2019-10-03 11:16:41.000000000 +0000
@@ -194,10 +194,7 @@
/*initializes some global variables */
static UHashtable *SHARED_DATA_HASHTABLE = NULL;
-static icu::UMutex *cnvCacheMutex() { /* Mutex for synchronizing cnv cache access. */
- static icu::UMutex m = U_MUTEX_INITIALIZER;
- return &m;
-}
+static icu::UMutex cnvCacheMutex;
/* Note: the global mutex is used for */
/* reference count updates. */
@@ -602,9 +599,9 @@
ucnv_unloadSharedDataIfReady(UConverterSharedData *sharedData)
{
if(sharedData != NULL && sharedData->isReferenceCounted) {
- umtx_lock(cnvCacheMutex());
+ umtx_lock(&cnvCacheMutex);
ucnv_unload(sharedData);
- umtx_unlock(cnvCacheMutex());
+ umtx_unlock(&cnvCacheMutex);
}
}
@@ -612,9 +609,9 @@
ucnv_incrementRefCount(UConverterSharedData *sharedData)
{
if(sharedData != NULL && sharedData->isReferenceCounted) {
- umtx_lock(cnvCacheMutex());
+ umtx_lock(&cnvCacheMutex);
sharedData->referenceCounter++;
- umtx_unlock(cnvCacheMutex());
+ umtx_unlock(&cnvCacheMutex);
}
}
@@ -815,9 +812,9 @@
pArgs->nestedLoads=1;
pArgs->pkg=NULL;
- umtx_lock(cnvCacheMutex());
+ umtx_lock(&cnvCacheMutex);
mySharedConverterData = ucnv_load(pArgs, err);
- umtx_unlock(cnvCacheMutex());
+ umtx_unlock(&cnvCacheMutex);
if (U_FAILURE (*err) || (mySharedConverterData == NULL))
{
return NULL;
@@ -1064,7 +1061,7 @@
* because the sequence of looking up in the cache + incrementing
* is protected by cnvCacheMutex.
*/
- umtx_lock(cnvCacheMutex());
+ umtx_lock(&cnvCacheMutex);
/*
* double loop: A delta/extension-only converter has a pointer to its base table's
* shared data; the first iteration of the outer loop may see the delta converter
@@ -1093,7 +1090,7 @@
}
}
} while(++i == 1 && remaining > 0);
- umtx_unlock(cnvCacheMutex());
+ umtx_unlock(&cnvCacheMutex);
UTRACE_DATA1(UTRACE_INFO, "ucnv_flushCache() exits with %d converters remaining", remaining);
@@ -1199,7 +1196,7 @@
}
algorithmicSharedData = getAlgorithmicTypeFromName(stackArgs.name);
- umtx_lock(cnvCacheMutex());
+ umtx_lock(&cnvCacheMutex);
gDefaultAlgorithmicSharedData = algorithmicSharedData;
gDefaultConverterContainsOption = containsOption;
@@ -1215,7 +1212,7 @@
ucnv_enableCleanup();
- umtx_unlock(cnvCacheMutex());
+ umtx_unlock(&cnvCacheMutex);
}
#endif
@@ -1240,7 +1237,7 @@
but ucnv_setDefaultName is not thread safe.
*/
{
- icu::Mutex lock(cnvCacheMutex());
+ icu::Mutex lock(&cnvCacheMutex);
name = gDefaultConverterName;
}
if(name==NULL) {
diff -Nru icu-64.2/source/common/ucnvbocu.cpp icu-65.1/source/common/ucnvbocu.cpp
--- icu-64.2/source/common/ucnvbocu.cpp 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/ucnvbocu.cpp 2019-10-03 11:16:41.000000000 +0000
@@ -202,14 +202,14 @@
* @param d Divisor.
* @param m Output variable for the rest (modulo result).
*/
-#define NEGDIVMOD(n, d, m) { \
+#define NEGDIVMOD(n, d, m) UPRV_BLOCK_MACRO_BEGIN { \
(m)=(n)%(d); \
(n)/=(d); \
if((m)<0) { \
--(n); \
(m)+=(d); \
} \
-}
+} UPRV_BLOCK_MACRO_END
/* Faster versions of packDiff() for single-byte-encoded diff values. */
diff -Nru icu-64.2/source/common/ucnv.cpp icu-65.1/source/common/ucnv.cpp
--- icu-64.2/source/common/ucnv.cpp 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/ucnv.cpp 2019-10-03 11:16:41.000000000 +0000
@@ -25,6 +25,8 @@
#if !UCONFIG_NO_CONVERSION
+#include
+
#include "unicode/ustring.h"
#include "unicode/ucnv.h"
#include "unicode/ucnv_err.h"
@@ -158,7 +160,6 @@
UConverter *localConverter, *allocatedConverter;
int32_t stackBufferSize;
int32_t bufferSizeNeeded;
- char *stackBufferChars = (char *)stackBuffer;
UErrorCode cbErr;
UConverterToUnicodeArgs toUArgs = {
sizeof(UConverterToUnicodeArgs),
@@ -224,23 +225,22 @@
}
}
-
- /* Pointers on 64-bit platforms need to be aligned
- * on a 64-bit boundary in memory.
+ /* Adjust (if necessary) the stackBuffer pointer to be aligned correctly for a UConverter.
+ * TODO(Jira ICU-20736) Redo this using std::align() once g++4.9 compatibility is no longer needed.
*/
- if (U_ALIGNMENT_OFFSET(stackBuffer) != 0) {
- int32_t offsetUp = (int32_t)U_ALIGNMENT_OFFSET_UP(stackBufferChars);
- if(stackBufferSize > offsetUp) {
- stackBufferSize -= offsetUp;
- stackBufferChars += offsetUp;
+ if (stackBuffer) {
+ uintptr_t p = reinterpret_cast(stackBuffer);
+ uintptr_t aligned_p = (p + alignof(UConverter) - 1) & ~(alignof(UConverter) - 1);
+ ptrdiff_t pointerAdjustment = aligned_p - p;
+ if (bufferSizeNeeded + pointerAdjustment <= stackBufferSize) {
+ stackBuffer = reinterpret_cast(aligned_p);
+ stackBufferSize -= pointerAdjustment;
} else {
/* prevent using the stack buffer but keep the size > 0 so that we do not just preflight */
stackBufferSize = 1;
}
}
- stackBuffer = (void *)stackBufferChars;
-
/* Now, see if we must allocate any memory */
if (stackBufferSize < bufferSizeNeeded || stackBuffer == NULL)
{
@@ -475,7 +475,7 @@
const UChar *s,
int32_t length,
UErrorCode *err) {
- UAlignedMemory cloneBuffer[U_CNV_SAFECLONE_BUFFERSIZE / sizeof(UAlignedMemory) + 1];
+ alignas(UConverter) char cloneBuffer[U_CNV_SAFECLONE_BUFFERSIZE];
char chars[UCNV_ERROR_BUFFER_LENGTH];
UConverter *clone;
diff -Nru icu-64.2/source/common/ucnvhz.cpp icu-65.1/source/common/ucnvhz.cpp
--- icu-64.2/source/common/ucnvhz.cpp 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/ucnvhz.cpp 2019-10-03 11:16:41.000000000 +0000
@@ -38,7 +38,7 @@
#define ESC_LEN 2
-#define CONCAT_ESCAPE_MACRO( args, targetIndex,targetLength,strToAppend, err, len,sourceIndex){ \
+#define CONCAT_ESCAPE_MACRO(args, targetIndex,targetLength,strToAppend, err, len,sourceIndex) UPRV_BLOCK_MACRO_BEGIN { \
while(len-->0){ \
if(targetIndex < targetLength){ \
args->target[targetIndex] = (unsigned char) *strToAppend; \
@@ -53,7 +53,7 @@
} \
strToAppend++; \
} \
-}
+} UPRV_BLOCK_MACRO_END
typedef struct{
@@ -518,19 +518,11 @@
/*
* Structure for cloning an HZ converter into a single memory block.
- * ucnv_safeClone() of the HZ converter will align the entire cloneHZStruct,
- * and then ucnv_safeClone() of the sub-converter may additionally align
- * subCnv inside the cloneHZStruct, for which we need the deadSpace after
- * subCnv. This is because UAlignedMemory may be larger than the actually
- * necessary alignment size for the platform.
- * The other cloneHZStruct fields will not be moved around,
- * and are aligned properly with cloneHZStruct's alignment.
*/
struct cloneHZStruct
{
UConverter cnv;
UConverter subCnv;
- UAlignedMemory deadSpace;
UConverterDataHZ mydata;
};
@@ -545,12 +537,12 @@
int32_t size, bufferSizeNeeded = sizeof(struct cloneHZStruct);
if (U_FAILURE(*status)){
- return 0;
+ return nullptr;
}
if (*pBufferSize == 0){ /* 'preflighting' request - set needed size into *pBufferSize */
*pBufferSize = bufferSizeNeeded;
- return 0;
+ return nullptr;
}
localClone = (struct cloneHZStruct *)stackBuffer;
@@ -561,7 +553,7 @@
localClone->cnv.isExtraLocal = TRUE;
/* deep-clone the sub-converter */
- size = (int32_t)(sizeof(UConverter) + sizeof(UAlignedMemory)); /* include size of padding */
+ size = (int32_t)sizeof(UConverter);
((UConverterDataHZ*)localClone->cnv.extraInfo)->gbConverter =
ucnv_safeClone(((UConverterDataHZ*)cnv->extraInfo)->gbConverter, &localClone->subCnv, &size, status);
diff -Nru icu-64.2/source/common/ucnvisci.cpp icu-65.1/source/common/ucnvisci.cpp
--- icu-64.2/source/common/ucnvisci.cpp 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/ucnvisci.cpp 2019-10-03 11:16:41.000000000 +0000
@@ -831,7 +831,7 @@
};
-#define WRITE_TO_TARGET_FROM_U(args,offsets,source,target,targetLimit,targetByteUnit,err){ \
+#define WRITE_TO_TARGET_FROM_U(args,offsets,source,target,targetLimit,targetByteUnit,err) UPRV_BLOCK_MACRO_BEGIN { \
int32_t offset = (int32_t)(source - args->source-1); \
/* write the targetUniChar to target */ \
if(target < targetLimit){ \
@@ -884,7 +884,7 @@
(uint8_t) (targetByteUnit); \
*err = U_BUFFER_OVERFLOW_ERROR; \
} \
-}
+} UPRV_BLOCK_MACRO_END
/* Rules:
* Explicit Halant :
@@ -1119,7 +1119,7 @@
{ GURMUKHI, PNJ_MASK }
};
-#define WRITE_TO_TARGET_TO_U(args,source,target,offsets,offset,targetUniChar,delta, err){\
+#define WRITE_TO_TARGET_TO_U(args,source,target,offsets,offset,targetUniChar,delta, err) UPRV_BLOCK_MACRO_BEGIN { \
/* add offset to current Indic Block */ \
if(targetUniChar>ASCII_END && \
targetUniChar != ZWJ && \
@@ -1140,9 +1140,9 @@
(UChar)targetUniChar; \
*err = U_BUFFER_OVERFLOW_ERROR; \
} \
-}
+} UPRV_BLOCK_MACRO_END
-#define GET_MAPPING(sourceChar,targetUniChar,data){ \
+#define GET_MAPPING(sourceChar,targetUniChar,data) UPRV_BLOCK_MACRO_BEGIN { \
targetUniChar = toUnicodeTable[(sourceChar)] ; \
/* is the code point valid in current script? */ \
if(sourceChar> ASCII_END && \
@@ -1153,7 +1153,7 @@
targetUniChar=missingCharMarker; \
} \
} \
-}
+} UPRV_BLOCK_MACRO_END
/***********
* Rules for ISCII to Unicode converter
diff -Nru icu-64.2/source/common/ucnv_lmb.cpp icu-65.1/source/common/ucnv_lmb.cpp
--- icu-64.2/source/common/ucnv_lmb.cpp 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/ucnv_lmb.cpp 2019-10-03 11:16:41.000000000 +0000
@@ -1107,11 +1107,13 @@
all input as required by ICU converter semantics.
*/
-#define CHECK_SOURCE_LIMIT(index) \
- if (args->source+index > args->sourceLimit){\
- *err = U_TRUNCATED_CHAR_FOUND;\
- args->source = args->sourceLimit;\
- return 0xffff;}
+#define CHECK_SOURCE_LIMIT(index) UPRV_BLOCK_MACRO_BEGIN { \
+ if (args->source+index > args->sourceLimit) { \
+ *err = U_TRUNCATED_CHAR_FOUND; \
+ args->source = args->sourceLimit; \
+ return 0xffff; \
+ } \
+} UPRV_BLOCK_MACRO_END
/* Return the Unicode representation for the current LMBCS character */
diff -Nru icu-64.2/source/common/ucnvsel.cpp icu-65.1/source/common/ucnvsel.cpp
--- icu-64.2/source/common/ucnvsel.cpp 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/ucnvsel.cpp 2019-10-03 11:16:41.000000000 +0000
@@ -691,36 +691,36 @@
/* internal function! */
static UEnumeration *selectForMask(const UConverterSelector* sel,
- uint32_t *mask, UErrorCode *status) {
+ uint32_t *theMask, UErrorCode *status) {
+ LocalMemory mask(theMask);
// this is the context we will use. Store a table of indices to which
// encodings are legit.
- struct Enumerator* result = (Enumerator*)uprv_malloc(sizeof(Enumerator));
- if (result == NULL) {
- uprv_free(mask);
+ LocalMemory result(static_cast(uprv_malloc(sizeof(Enumerator))));
+ if (result.isNull()) {
*status = U_MEMORY_ALLOCATION_ERROR;
- return NULL;
+ return nullptr;
}
- result->index = NULL; // this will be allocated later!
+ result->index = nullptr; // this will be allocated later!
result->length = result->cur = 0;
result->sel = sel;
- UEnumeration *en = (UEnumeration *)uprv_malloc(sizeof(UEnumeration));
- if (en == NULL) {
+ LocalMemory en(static_cast(uprv_malloc(sizeof(UEnumeration))));
+ if (en.isNull()) {
// TODO(markus): Combine Enumerator and UEnumeration into one struct.
- uprv_free(mask);
- uprv_free(result);
*status = U_MEMORY_ALLOCATION_ERROR;
- return NULL;
+ return nullptr;
}
- memcpy(en, &defaultEncodings, sizeof(UEnumeration));
- en->context = result;
-
+ memcpy(en.getAlias(), &defaultEncodings, sizeof(UEnumeration));
+
int32_t columns = (sel->encodingsCount+31)/32;
- int16_t numOnes = countOnes(mask, columns);
+ int16_t numOnes = countOnes(mask.getAlias(), columns);
// now, we know the exact space we need for index
if (numOnes > 0) {
- result->index = (int16_t*) uprv_malloc(numOnes * sizeof(int16_t));
-
+ result->index = static_cast(uprv_malloc(numOnes * sizeof(int16_t)));
+ if (result->index == nullptr) {
+ *status = U_MEMORY_ALLOCATION_ERROR;
+ return nullptr;
+ }
int32_t i, j;
int16_t k = 0;
for (j = 0 ; j < columns; j++) {
@@ -734,8 +734,8 @@
}
} //otherwise, index will remain NULL (and will never be touched by
//the enumerator code anyway)
- uprv_free(mask);
- return en;
+ en->context = result.orphan();
+ return en.orphan();
}
/* check a string against the selector - UTF16 version */
diff -Nru icu-64.2/source/common/ucptrie.cpp icu-65.1/source/common/ucptrie.cpp
--- icu-64.2/source/common/ucptrie.cpp 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/ucptrie.cpp 2019-10-03 11:16:41.000000000 +0000
@@ -280,7 +280,7 @@
int32_t prevI3Block = -1;
int32_t prevBlock = -1;
UChar32 c = start;
- uint32_t trieValue, value;
+ uint32_t trieValue, value = nullValue;
bool haveValue = false;
do {
int32_t i3Block;
diff -Nru icu-64.2/source/common/ucurr.cpp icu-65.1/source/common/ucurr.cpp
--- icu-64.2/source/common/ucurr.cpp 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/ucurr.cpp 2019-10-03 11:16:41.000000000 +0000
@@ -365,10 +365,7 @@
#if !UCONFIG_NO_SERVICE
struct CReg;
-static UMutex *gCRegLock() {
- static UMutex m = U_MUTEX_INITIALIZER;
- return &m;
-}
+static UMutex gCRegLock;
static CReg* gCRegHead = 0;
struct CReg : public icu::UMemory {
@@ -394,14 +391,14 @@
if (status && U_SUCCESS(*status) && _iso && _id) {
CReg* n = new CReg(_iso, _id);
if (n) {
- umtx_lock(gCRegLock());
+ umtx_lock(&gCRegLock);
if (!gCRegHead) {
/* register for the first time */
ucln_common_registerCleanup(UCLN_COMMON_CURRENCY, currency_cleanup);
}
n->next = gCRegHead;
gCRegHead = n;
- umtx_unlock(gCRegLock());
+ umtx_unlock(&gCRegLock);
return n;
}
*status = U_MEMORY_ALLOCATION_ERROR;
@@ -411,7 +408,7 @@
static UBool unreg(UCurrRegistryKey key) {
UBool found = FALSE;
- umtx_lock(gCRegLock());
+ umtx_lock(&gCRegLock);
CReg** p = &gCRegHead;
while (*p) {
@@ -424,13 +421,13 @@
p = &((*p)->next);
}
- umtx_unlock(gCRegLock());
+ umtx_unlock(&gCRegLock);
return found;
}
static const UChar* get(const char* id) {
const UChar* result = NULL;
- umtx_lock(gCRegLock());
+ umtx_lock(&gCRegLock);
CReg* p = gCRegHead;
/* register cleanup of the mutex */
@@ -442,7 +439,7 @@
}
p = p->next;
}
- umtx_unlock(gCRegLock());
+ umtx_unlock(&gCRegLock);
return result;
}
@@ -716,7 +713,9 @@
// We no longer support choice format data in names. Data should not contain
// choice patterns.
- *isChoiceFormat = FALSE;
+ if (isChoiceFormat != NULL) {
+ *isChoiceFormat = FALSE;
+ }
if (U_SUCCESS(ec2)) {
U_ASSERT(s != NULL);
return s;
@@ -1356,10 +1355,7 @@
// It is a simple round-robin replacement strategy.
static int8_t currentCacheEntryIndex = 0;
-static UMutex *gCurrencyCacheMutex() {
- static UMutex m = U_MUTEX_INITIALIZER;
- return &m;
-}
+static UMutex gCurrencyCacheMutex;
// Cache deletion
static void
@@ -1408,7 +1404,7 @@
CurrencyNameStruct* currencySymbols = NULL;
CurrencyNameCacheEntry* cacheEntry = NULL;
- umtx_lock(gCurrencyCacheMutex());
+ umtx_lock(&gCurrencyCacheMutex);
// in order to handle racing correctly,
// not putting 'search' in a separate function.
int8_t found = -1;
@@ -1423,13 +1419,13 @@
cacheEntry = currCache[found];
++(cacheEntry->refCount);
}
- umtx_unlock(gCurrencyCacheMutex());
+ umtx_unlock(&gCurrencyCacheMutex);
if (found == -1) {
collectCurrencyNames(locale, ¤cyNames, &total_currency_name_count, ¤cySymbols, &total_currency_symbol_count, ec);
if (U_FAILURE(ec)) {
return NULL;
}
- umtx_lock(gCurrencyCacheMutex());
+ umtx_lock(&gCurrencyCacheMutex);
// check again.
for (int8_t i = 0; i < CURRENCY_NAME_CACHE_NUM; ++i) {
if (currCache[i]!= NULL &&
@@ -1468,19 +1464,19 @@
cacheEntry = currCache[found];
++(cacheEntry->refCount);
}
- umtx_unlock(gCurrencyCacheMutex());
+ umtx_unlock(&gCurrencyCacheMutex);
}
return cacheEntry;
}
static void releaseCacheEntry(CurrencyNameCacheEntry* cacheEntry) {
- umtx_lock(gCurrencyCacheMutex());
+ umtx_lock(&gCurrencyCacheMutex);
--(cacheEntry->refCount);
if (cacheEntry->refCount == 0) { // remove
deleteCacheEntry(cacheEntry);
}
- umtx_unlock(gCurrencyCacheMutex());
+ umtx_unlock(&gCurrencyCacheMutex);
}
U_CAPI void
@@ -1601,10 +1597,9 @@
{
U_NAMESPACE_USE
- UBool isChoiceFormat;
int32_t len;
const UChar* currname = ucurr_getName(iso, loc, UCURR_SYMBOL_NAME,
- &isChoiceFormat, &len, &ec);
+ nullptr /* isChoiceFormat */, &len, &ec);
if (U_SUCCESS(ec)) {
result.setTo(currname, len);
}
diff -Nru icu-64.2/source/common/udata.cpp icu-65.1/source/common/udata.cpp
--- icu-64.2/source/common/udata.cpp 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/udata.cpp 2019-10-03 11:16:41.000000000 +0000
@@ -33,6 +33,7 @@
#include "cstring.h"
#include "mutex.h"
#include "putilimp.h"
+#include "restrace.h"
#include "uassert.h"
#include "ucln_cmn.h"
#include "ucmndata.h"
@@ -110,11 +111,12 @@
static UHashtable *gCommonDataCache = NULL; /* Global hash table of opened ICU data files. */
static icu::UInitOnce gCommonDataCacheInitOnce = U_INITONCE_INITIALIZER;
-#if U_PLATFORM_HAS_WINUWP_API == 0
+#if !defined(ICU_DATA_DIR_WINDOWS)
static UDataFileAccess gDataFileAccess = UDATA_DEFAULT_ACCESS; // Access not synchronized.
// Modifying is documented as thread-unsafe.
#else
-static UDataFileAccess gDataFileAccess = UDATA_NO_FILES; // Windows UWP looks in one spot explicitly
+// If we are using the Windows data directory, then look in one spot only.
+static UDataFileAccess gDataFileAccess = UDATA_NO_FILES;
#endif
static UBool U_CALLCONV
@@ -206,7 +208,7 @@
return didUpdate;
}
-#if U_PLATFORM_HAS_WINUWP_API == 0
+#if !defined(ICU_DATA_DIR_WINDOWS)
static UBool
setCommonICUDataPointer(const void *pData, UBool /*warn*/, UErrorCode *pErrorCode) {
@@ -320,7 +322,7 @@
retVal = el->item;
}
#ifdef UDATA_DEBUG
- fprintf(stderr, "Cache: [%s] -> %p\n", baseName, retVal);
+ fprintf(stderr, "Cache: [%s] -> %p\n", baseName, (void*) retVal);
#endif
return retVal;
}
@@ -383,7 +385,7 @@
#ifdef UDATA_DEBUG
fprintf(stderr, "Cache: [%s] <<< %p : %s. vFunc=%p\n", newElement->name,
- newElement->item, u_errorName(subErr), newElement->item->vFuncs);
+ (void*) newElement->item, u_errorName(subErr), (void*) newElement->item->vFuncs);
#endif
if (subErr == U_USING_DEFAULT_WARNING || U_FAILURE(subErr)) {
@@ -477,7 +479,7 @@
nextPath = itemPath.data();
}
#ifdef UDATA_DEBUG
- fprintf(stderr, "SUFFIX=%s [%p]\n", inSuffix, inSuffix);
+ fprintf(stderr, "SUFFIX=%s [%p]\n", inSuffix, (void*) inSuffix);
#endif
/** Suffix **/
@@ -492,12 +494,11 @@
/* pathBuffer will hold the output path strings returned by this iterator */
#ifdef UDATA_DEBUG
- fprintf(stderr, "%p: init %s -> [path=%s], [base=%s], [suff=%s], [itempath=%s], [nextpath=%s], [checklast4=%s]\n",
- iter,
+ fprintf(stderr, "0: init %s -> [path=%s], [base=%s], [suff=%s], [itempath=%s], [nextpath=%s], [checklast4=%s]\n",
item,
path,
basename,
- suffix,
+ suffix.data(),
itemPath.data(),
nextPath,
checkLastFour?"TRUE":"false");
@@ -553,7 +554,7 @@
fprintf(stderr, "rest of path (IDD) = %s\n", currentPath);
fprintf(stderr, " ");
{
- uint32_t qqq;
+ int32_t qqq;
for(qqq=0;qqqpHeader == &U_ICUDATA_ENTRY_POINT) {
@@ -714,7 +717,8 @@
setCommonICUDataPointer(uprv_getICUData_conversion(), FALSE, pErrorCode);
}
*/
-#if U_PLATFORM_HAS_WINUWP_API == 0 // Windows UWP Platform does not support dll icu data at this time
+#if !defined(ICU_DATA_DIR_WINDOWS)
+// When using the Windows system data, we expect only a single data file.
setCommonICUDataPointer(&U_ICUDATA_ENTRY_POINT, FALSE, pErrorCode);
{
Mutex lock;
@@ -831,7 +835,7 @@
* Use a specific mutex to avoid nested locks of the global mutex.
*/
#if MAP_IMPLEMENTATION==MAP_STDIO
- static UMutex extendICUDataMutex = U_MUTEX_INITIALIZER;
+ static UMutex extendICUDataMutex;
umtx_lock(&extendICUDataMutex);
#endif
if(!umtx_loadAcquire(gHaveTriedToLoadCommonData)) {
@@ -1070,13 +1074,13 @@
/* look up the data piece in the common data */
pHeader=pCommonData->vFuncs->Lookup(pCommonData, tocEntryName, &length, subErrorCode);
#ifdef UDATA_DEBUG
- fprintf(stderr, "%s: pHeader=%p - %s\n", tocEntryName, pHeader, u_errorName(*subErrorCode));
+ fprintf(stderr, "%s: pHeader=%p - %s\n", tocEntryName, (void*) pHeader, u_errorName(*subErrorCode));
#endif
if(pHeader!=NULL) {
pEntryData = checkDataItem(pHeader, isAcceptable, context, type, name, subErrorCode, pErrorCode);
#ifdef UDATA_DEBUG
- fprintf(stderr, "pEntryData=%p\n", pEntryData);
+ fprintf(stderr, "pEntryData=%p\n", (void*) pEntryData);
#endif
if (U_FAILURE(*pErrorCode)) {
return NULL;
@@ -1168,6 +1172,9 @@
UBool isICUData = FALSE;
+ FileTracer::traceOpen(path, type, name);
+
+
/* Is this path ICU data? */
if(path == NULL ||
!strcmp(path, U_ICUDATA_ALIAS) || /* "ICUDATA" */
@@ -1276,12 +1283,12 @@
fprintf(stderr, " tocEntryPath = %s\n", tocEntryName.data());
#endif
-#if U_PLATFORM_HAS_WINUWP_API == 0 // Windows UWP Platform does not support dll icu data at this time
+#if !defined(ICU_DATA_DIR_WINDOWS)
if(path == NULL) {
path = COMMON_DATA_NAME; /* "icudt26e" */
}
#else
- // Windows UWP expects only a single data file.
+ // When using the Windows system data, we expects only a single data file.
path = COMMON_DATA_NAME; /* "icudt26e" */
#endif
diff -Nru icu-64.2/source/common/uhash.cpp icu-65.1/source/common/uhash.cpp
--- icu-64.2/source/common/uhash.cpp 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/uhash.cpp 2019-10-03 11:16:41.000000000 +0000
@@ -119,13 +119,14 @@
/* This macro expects a UHashTok.pointer as its keypointer and
valuepointer parameters */
-#define HASH_DELETE_KEY_VALUE(hash, keypointer, valuepointer) \
- if (hash->keyDeleter != NULL && keypointer != NULL) { \
- (*hash->keyDeleter)(keypointer); \
- } \
- if (hash->valueDeleter != NULL && valuepointer != NULL) { \
- (*hash->valueDeleter)(valuepointer); \
- }
+#define HASH_DELETE_KEY_VALUE(hash, keypointer, valuepointer) UPRV_BLOCK_MACRO_BEGIN { \
+ if (hash->keyDeleter != NULL && keypointer != NULL) { \
+ (*hash->keyDeleter)(keypointer); \
+ } \
+ if (hash->valueDeleter != NULL && valuepointer != NULL) { \
+ (*hash->valueDeleter)(valuepointer); \
+ } \
+} UPRV_BLOCK_MACRO_END
/*
* Constants for hinting whether a key or value is an integer
diff -Nru icu-64.2/source/common/uidna.cpp icu-65.1/source/common/uidna.cpp
--- icu-64.2/source/common/uidna.cpp 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/uidna.cpp 2019-10-03 11:16:41.000000000 +0000
@@ -57,18 +57,16 @@
inline static UBool
startsWithPrefix(const UChar* src , int32_t srcLength){
- UBool startsWithPrefix = TRUE;
-
if(srcLength < ACE_PREFIX_LENGTH){
return FALSE;
}
for(int8_t i=0; i< ACE_PREFIX_LENGTH; i++){
if(toASCIILower(src[i]) != ACE_PREFIX[i]){
- startsWithPrefix = FALSE;
+ return FALSE;
}
}
- return startsWithPrefix;
+ return TRUE;
}
@@ -441,6 +439,7 @@
for(int32_t j=0; j 0x7f){
srcIsASCII = FALSE;
+ break;
}/*else if(isLDHChar(src[j])==FALSE){
// here we do not assemble surrogates
// since we know that LDH code points
diff -Nru icu-64.2/source/common/uinvchar.cpp icu-65.1/source/common/uinvchar.cpp
--- icu-64.2/source/common/uinvchar.cpp 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/uinvchar.cpp 2019-10-03 11:16:41.000000000 +0000
@@ -207,7 +207,8 @@
while(length>0) {
u=*us++;
if(!UCHAR_IS_INVARIANT(u)) {
- UPRV_UNREACHABLE; /* Variant characters were used. These are not portable in ICU. */
+ U_ASSERT(FALSE); /* Variant characters were used. These are not portable in ICU. */
+ u=0;
}
*cs++=(char)UCHAR_TO_CHAR(u);
--length;
@@ -445,6 +446,13 @@
return length;
}
+U_CFUNC UBool
+uprv_isEbcdicAtSign(char c) {
+ static const uint8_t ebcdicAtSigns[] = {
+ 0x7C, 0x44, 0x66, 0x80, 0xAC, 0xAE, 0xAF, 0xB5, 0xEC, 0xEF, 0x00 };
+ return c != 0 && uprv_strchr((const char *)ebcdicAtSigns, c) != nullptr;
+}
+
/* compare invariant strings; variant characters compare less than others and unlike each other */
U_CFUNC int32_t
uprv_compareInvAscii(const UDataSwapper *ds,
@@ -562,6 +570,11 @@
}
U_CAPI char U_EXPORT2
+uprv_ebcdicToAscii(char c) {
+ return (char)asciiFromEbcdic[(uint8_t)c];
+}
+
+U_CAPI char U_EXPORT2
uprv_ebcdicToLowercaseAscii(char c) {
return (char)lowercaseAsciiFromEbcdic[(uint8_t)c];
}
diff -Nru icu-64.2/source/common/uinvchar.h icu-65.1/source/common/uinvchar.h
--- icu-64.2/source/common/uinvchar.h 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/uinvchar.h 2019-10-03 11:16:41.000000000 +0000
@@ -68,6 +68,75 @@
# error Unknown charset family!
#endif
+#ifdef __cplusplus
+
+U_NAMESPACE_BEGIN
+
+/**
+ * Like U_UPPER_ORDINAL(x) but with validation.
+ * Returns 0..25 for A..Z else a value outside 0..25.
+ */
+inline int32_t uprv_upperOrdinal(int32_t c) {
+#if U_CHARSET_FAMILY==U_ASCII_FAMILY
+ return c - 'A';
+#elif U_CHARSET_FAMILY==U_EBCDIC_FAMILY
+ // EBCDIC: A-Z (26 letters) is split into three ranges A-I (9 letters), J-R (9), S-Z (8).
+ // https://en.wikipedia.org/wiki/EBCDIC_037#Codepage_layout
+ if (c <= 'I') { return c - 'A'; } // A-I --> 0-8
+ if (c < 'J') { return -1; }
+ if (c <= 'R') { return c - 'J' + 9; } // J-R --> 9..17
+ if (c < 'S') { return -1; }
+ return c - 'S' + 18; // S-Z --> 18..25
+#else
+# error Unknown charset family!
+#endif
+}
+
+// Like U_UPPER_ORDINAL(x) but for lowercase and with validation.
+// Returns 0..25 for a..z else a value outside 0..25.
+inline int32_t uprv_lowerOrdinal(int32_t c) {
+#if U_CHARSET_FAMILY==U_ASCII_FAMILY
+ return c - 'a';
+#elif U_CHARSET_FAMILY==U_EBCDIC_FAMILY
+ // EBCDIC: a-z (26 letters) is split into three ranges a-i (9 letters), j-r (9), s-z (8).
+ // https://en.wikipedia.org/wiki/EBCDIC_037#Codepage_layout
+ if (c <= 'i') { return c - 'a'; } // a-i --> 0-8
+ if (c < 'j') { return -1; }
+ if (c <= 'r') { return c - 'j' + 9; } // j-r --> 9..17
+ if (c < 's') { return -1; }
+ return c - 's' + 18; // s-z --> 18..25
+#else
+# error Unknown charset family!
+#endif
+}
+
+U_NAMESPACE_END
+
+#endif
+
+/**
+ * Returns true if c == '@' is possible.
+ * The @ sign is variant, and the @ sign used on one
+ * EBCDIC machine won't be compiled the same way on other EBCDIC based machines.
+ * @internal
+ */
+U_CFUNC UBool
+uprv_isEbcdicAtSign(char c);
+
+/**
+ * \def uprv_isAtSign
+ * Returns true if c == '@' is possible.
+ * For ASCII, checks for exactly '@'. For EBCDIC, calls uprv_isEbcdicAtSign().
+ * @internal
+ */
+#if U_CHARSET_FAMILY==U_ASCII_FAMILY
+# define uprv_isAtSign(c) ((c)=='@')
+#elif U_CHARSET_FAMILY==U_EBCDIC_FAMILY
+# define uprv_isAtSign(c) uprv_isEbcdicAtSign(c)
+#else
+# error Unknown charset family!
+#endif
+
/**
* Compare two EBCDIC invariant-character strings in ASCII order.
* @internal
@@ -87,6 +156,26 @@
#else
# error Unknown charset family!
#endif
+
+/**
+ * Converts an EBCDIC invariant character to ASCII.
+ * @internal
+ */
+U_INTERNAL char U_EXPORT2
+uprv_ebcdicToAscii(char c);
+
+/**
+ * \def uprv_invCharToAscii
+ * Converts an invariant character to ASCII.
+ * @internal
+ */
+#if U_CHARSET_FAMILY==U_ASCII_FAMILY
+# define uprv_invCharToAscii(c) (c)
+#elif U_CHARSET_FAMILY==U_EBCDIC_FAMILY
+# define uprv_invCharToAscii(c) uprv_ebcdicToAscii(c)
+#else
+# error Unknown charset family!
+#endif
/**
* Converts an EBCDIC invariant character to lowercase ASCII.
diff -Nru icu-64.2/source/common/uloc.cpp icu-65.1/source/common/uloc.cpp
--- icu-64.2/source/common/uloc.cpp 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/uloc.cpp 2019-10-03 11:16:41.000000000 +0000
@@ -148,7 +148,8 @@
"mad", "maf", "mag", "mai", "mak", "man", "mas", "mde",
"mdf", "mdh", "mdr", "men", "mer", "mfe", "mg", "mga",
"mgh", "mgo", "mh", "mi", "mic", "min", "mis", "mk",
- "ml", "mn", "mnc", "mni", "moh", "mos", "mr", "mrj",
+ "ml", "mn", "mnc", "mni", "mo",
+ "moh", "mos", "mr", "mrj",
"ms", "mt", "mua", "mul", "mus", "mwl", "mwr", "mwv",
"my", "mye", "myv", "mzn",
"na", "nan", "nap", "naq", "nb", "nd", "nds", "ne",
@@ -264,7 +265,8 @@
"mad", "maf", "mag", "mai", "mak", "man", "mas", "mde",
"mdf", "mdh", "mdr", "men", "mer", "mfe", "mlg", "mga",
"mgh", "mgo", "mah", "mri", "mic", "min", "mis", "mkd",
- "mal", "mon", "mnc", "mni", "moh", "mos", "mar", "mrj",
+ "mal", "mon", "mnc", "mni", "mol",
+ "moh", "mos", "mar", "mrj",
"msa", "mlt", "mua", "mul", "mus", "mwl", "mwr", "mwv",
"mya", "mye", "myv", "mzn",
"nau", "nan", "nap", "naq", "nob", "nde", "nds", "nep",
@@ -480,14 +482,15 @@
/* Test if the locale id has BCP47 u extension and does not have '@' */
#define _hasBCP47Extension(id) (id && uprv_strstr(id, "@") == NULL && getShortestSubtagLength(localeID) == 1)
/* Converts the BCP47 id to Unicode id. Does nothing to id if conversion fails */
-#define _ConvertBCP47(finalID, id, buffer, length,err) \
- if (uloc_forLanguageTag(id, buffer, length, NULL, err) <= 0 || \
- U_FAILURE(*err) || *err == U_STRING_NOT_TERMINATED_WARNING) { \
- finalID=id; \
- if (*err == U_STRING_NOT_TERMINATED_WARNING) { *err = U_BUFFER_OVERFLOW_ERROR; } \
- } else { \
- finalID=buffer; \
- }
+#define _ConvertBCP47(finalID, id, buffer, length,err) UPRV_BLOCK_MACRO_BEGIN { \
+ if (uloc_forLanguageTag(id, buffer, length, NULL, err) <= 0 || \
+ U_FAILURE(*err) || *err == U_STRING_NOT_TERMINATED_WARNING) { \
+ finalID=id; \
+ if (*err == U_STRING_NOT_TERMINATED_WARNING) { *err = U_BUFFER_OVERFLOW_ERROR; } \
+ } else { \
+ finalID=buffer; \
+ } \
+} UPRV_BLOCK_MACRO_END
/* Gets the size of the shortest subtag in the given localeID. */
static int32_t getShortestSubtagLength(const char *localeID) {
int32_t localeIDLength = static_cast(uprv_strlen(localeID));
@@ -1454,31 +1457,29 @@
U_CAPI UEnumeration* U_EXPORT2
uloc_openKeywordList(const char *keywordList, int32_t keywordListSize, UErrorCode* status)
{
- UKeywordsContext *myContext = NULL;
- UEnumeration *result = NULL;
+ LocalMemory myContext;
+ LocalMemory result;
- if(U_FAILURE(*status)) {
- return NULL;
+ if (U_FAILURE(*status)) {
+ return nullptr;
}
- result = (UEnumeration *)uprv_malloc(sizeof(UEnumeration));
- /* Null pointer test */
- if (result == NULL) {
+ myContext.adoptInstead(static_cast(uprv_malloc(sizeof(UKeywordsContext))));
+ result.adoptInstead(static_cast(uprv_malloc(sizeof(UEnumeration))));
+ if (myContext.isNull() || result.isNull()) {
*status = U_MEMORY_ALLOCATION_ERROR;
- return NULL;
+ return nullptr;
}
- uprv_memcpy(result, &gKeywordsEnum, sizeof(UEnumeration));
- myContext = static_cast(uprv_malloc(sizeof(UKeywordsContext)));
- if (myContext == NULL) {
+ uprv_memcpy(result.getAlias(), &gKeywordsEnum, sizeof(UEnumeration));
+ myContext->keywords = static_cast(uprv_malloc(keywordListSize+1));
+ if (myContext->keywords == nullptr) {
*status = U_MEMORY_ALLOCATION_ERROR;
- uprv_free(result);
- return NULL;
+ return nullptr;
}
- myContext->keywords = (char *)uprv_malloc(keywordListSize+1);
uprv_memcpy(myContext->keywords, keywordList, keywordListSize);
myContext->keywords[keywordListSize] = 0;
myContext->current = myContext->keywords;
- result->context = myContext;
- return result;
+ result->context = myContext.orphan();
+ return result.orphan();
}
U_CAPI UEnumeration* U_EXPORT2
diff -Nru icu-64.2/source/common/uloc_tag.cpp icu-65.1/source/common/uloc_tag.cpp
--- icu-64.2/source/common/uloc_tag.cpp 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/uloc_tag.cpp 2019-10-03 11:16:41.000000000 +0000
@@ -1558,10 +1558,8 @@
return;
}
- if (!_addAttributeToList(&attrFirst, attr)) {
- *status = U_ILLEGAL_ARGUMENT_ERROR;
- return;
- }
+ // duplicate attribute is ignored, causes no error.
+ _addAttributeToList(&attrFirst, attr);
/* next tag */
pTag += len;
diff -Nru icu-64.2/source/common/umutex.cpp icu-65.1/source/common/umutex.cpp
--- icu-64.2/source/common/umutex.cpp 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/umutex.cpp 2019-10-03 11:16:41.000000000 +0000
@@ -24,6 +24,7 @@
#include "unicode/utypes.h"
#include "uassert.h"
+#include "ucln_cmn.h"
#include "cmemory.h"
U_NAMESPACE_BEGIN
@@ -35,60 +36,94 @@
#error U_USER_MUTEX_CPP not supported
#endif
+
/*************************************************************************************************
*
* ICU Mutex wrappers.
*
*************************************************************************************************/
-// The ICU global mutex. Used when ICU implementation code passes NULL for the mutex pointer.
-static UMutex *globalMutex() {
- static UMutex m = U_MUTEX_INITIALIZER;
- return &m;
+namespace {
+std::mutex *initMutex;
+std::condition_variable *initCondition;
+
+// The ICU global mutex.
+// Used when ICU implementation code passes nullptr for the mutex pointer.
+UMutex globalMutex;
+
+std::once_flag initFlag;
+std::once_flag *pInitFlag = &initFlag;
+
+} // Anonymous namespace
+
+U_CDECL_BEGIN
+static UBool U_CALLCONV umtx_cleanup() {
+ initMutex->~mutex();
+ initCondition->~condition_variable();
+ UMutex::cleanup();
+
+ // Reset the once_flag, by destructing it and creating a fresh one in its place.
+ // Do not use this trick anywhere else in ICU; use umtx_initOnce, not std::call_once().
+ pInitFlag->~once_flag();
+ pInitFlag = new(&initFlag) std::once_flag();
+ return true;
+}
+
+static void U_CALLCONV umtx_init() {
+ initMutex = STATIC_NEW(std::mutex);
+ initCondition = STATIC_NEW(std::condition_variable);
+ ucln_common_registerCleanup(UCLN_COMMON_MUTEX, umtx_cleanup);
+}
+U_CDECL_END
+
+
+std::mutex *UMutex::getMutex() {
+ std::mutex *retPtr = fMutex.load(std::memory_order_acquire);
+ if (retPtr == nullptr) {
+ std::call_once(*pInitFlag, umtx_init);
+ std::lock_guard guard(*initMutex);
+ retPtr = fMutex.load(std::memory_order_acquire);
+ if (retPtr == nullptr) {
+ fMutex = new(fStorage) std::mutex();
+ retPtr = fMutex;
+ fListLink = gListHead;
+ gListHead = this;
+ }
+ }
+ U_ASSERT(retPtr != nullptr);
+ return retPtr;
}
-U_CAPI void U_EXPORT2
-umtx_lock(UMutex *mutex) {
- if (mutex == nullptr) {
- mutex = globalMutex();
+UMutex *UMutex::gListHead = nullptr;
+
+void UMutex::cleanup() {
+ UMutex *next = nullptr;
+ for (UMutex *m = gListHead; m != nullptr; m = next) {
+ (*m->fMutex).~mutex();
+ m->fMutex = nullptr;
+ next = m->fListLink;
+ m->fListLink = nullptr;
}
- mutex->fMutex.lock();
+ gListHead = nullptr;
}
U_CAPI void U_EXPORT2
-umtx_unlock(UMutex* mutex)
-{
+umtx_lock(UMutex *mutex) {
if (mutex == nullptr) {
- mutex = globalMutex();
+ mutex = &globalMutex;
}
- mutex->fMutex.unlock();
+ mutex->lock();
}
-UConditionVar::UConditionVar() : fCV() {
-}
-UConditionVar::~UConditionVar() {
-}
-
-U_CAPI void U_EXPORT2
-umtx_condWait(UConditionVar *cond, UMutex *mutex) {
+U_CAPI void U_EXPORT2
+umtx_unlock(UMutex* mutex)
+{
if (mutex == nullptr) {
- mutex = globalMutex();
+ mutex = &globalMutex;
}
- cond->fCV.wait(mutex->fMutex);
-}
-
-
-U_CAPI void U_EXPORT2
-umtx_condBroadcast(UConditionVar *cond) {
- cond->fCV.notify_all();
-}
-
-
-U_CAPI void U_EXPORT2
-umtx_condSignal(UConditionVar *cond) {
- cond->fCV.notify_one();
+ mutex->unlock();
}
@@ -98,17 +133,6 @@
*
*************************************************************************************************/
-static std::mutex &initMutex() {
- static std::mutex m;
- return m;
-}
-
-static std::condition_variable &initCondition() {
- static std::condition_variable cv;
- return cv;
-}
-
-
// This function is called when a test of a UInitOnce::fState reveals that
// initialization has not completed, that we either need to call the init
// function on this thread, or wait for some other thread to complete.
@@ -119,8 +143,8 @@
//
U_COMMON_API UBool U_EXPORT2
umtx_initImplPreInit(UInitOnce &uio) {
- std::unique_lock lock(initMutex());
-
+ std::call_once(*pInitFlag, umtx_init);
+ std::unique_lock lock(*initMutex);
if (umtx_loadAcquire(uio.fState) == 0) {
umtx_storeRelease(uio.fState, 1);
return true; // Caller will next call the init function.
@@ -128,7 +152,7 @@
while (umtx_loadAcquire(uio.fState) == 1) {
// Another thread is currently running the initialization.
// Wait until it completes.
- initCondition().wait(lock);
+ initCondition->wait(lock);
}
U_ASSERT(uio.fState == 2);
return false;
@@ -145,10 +169,10 @@
U_COMMON_API void U_EXPORT2
umtx_initImplPostInit(UInitOnce &uio) {
{
- std::unique_lock lock(initMutex());
+ std::unique_lock lock(*initMutex);
umtx_storeRelease(uio.fState, 2);
}
- initCondition().notify_all();
+ initCondition->notify_all();
}
U_NAMESPACE_END
diff -Nru icu-64.2/source/common/umutex.h icu-65.1/source/common/umutex.h
--- icu-64.2/source/common/umutex.h 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/umutex.h 2019-10-03 11:16:41.000000000 +0000
@@ -23,6 +23,7 @@
#include
#include
#include
+#include
#include "unicode/utypes.h"
#include "unicode/uclean.h"
@@ -36,10 +37,11 @@
#error U_USER_ATOMICS and U_USER_MUTEX_H are not supported
#endif
-
// Export an explicit template instantiation of std::atomic.
// When building DLLs for Windows this is required as it is used as a data member of the exported SharedObject class.
// See digitlst.h, pluralaffix.h, datefmt.h, and others for similar examples.
+//
+// Similar story for std::atomic, and the exported UMutex class.
#if U_PF_WINDOWS <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN && !defined(U_IN_DOXYGEN)
#if defined(__clang__) || defined(_MSC_VER)
#if defined(__clang__)
@@ -48,12 +50,14 @@
#pragma clang diagnostic ignored "-Winstantiation-after-specialization"
#endif
template struct U_COMMON_API std::atomic;
+template struct U_COMMON_API std::atomic;
#if defined(__clang__)
#pragma clang diagnostic pop
#endif
#elif defined(__GNUC__)
// For GCC this class is already exported/visible, so no need for U_COMMON_API.
template struct std::atomic;
+template struct std::atomic;
#endif
#endif
@@ -180,49 +184,78 @@
}
}
+// UMutex should be constexpr-constructible, so that no initialization code
+// is run during startup.
+// This works on all C++ libraries except MS VS before VS2019.
+#if (defined(_CPPLIB_VER) && !defined(_MSVC_STL_VERSION)) || \
+ (defined(_MSVC_STL_VERSION) && _MSVC_STL_VERSION < 142)
+ // (VS std lib older than VS2017) || (VS std lib version < VS2019)
+# define UMUTEX_CONSTEXPR
+#else
+# define UMUTEX_CONSTEXPR constexpr
+#endif
-/*************************************************************************************************
+/**
+ * UMutex - ICU Mutex class.
*
- * ICU Mutex wrappers. Originally wrapped operating system mutexes, giving the rest of ICU a
- * platform independent set of mutex operations. Now vestigial, wrapping std::mutex only.
- * For internal ICU use only.
- *
- *************************************************************************************************/
+ * This is the preferred Mutex class for use within ICU implementation code.
+ * It is a thin wrapper over C++ std::mutex, with these additions:
+ * - Static instances are safe, not triggering static construction or destruction,
+ * and the associated order of construction or destruction issues.
+ * - Plumbed into u_cleanup() for destructing the underlying std::mutex,
+ * which frees any OS level resources they may be holding.
+ *
+ * Limitations:
+ * - Static or global instances only. Cannot be heap allocated. Cannot appear as a
+ * member of another class.
+ * - No condition variables or other advanced features. If needed, you will need to use
+ * std::mutex and std::condition_variable directly. For an example, see unifiedcache.cpp
+ *
+ * Typical Usage:
+ * static UMutex myMutex;
+ *
+ * {
+ * Mutex lock(myMutex);
+ * ... // Do stuff that is protected by myMutex;
+ * } // myMutex is released when lock goes out of scope.
+ */
-struct UMutex : public icu::UMemory {
- UMutex() = default;
+class U_COMMON_API UMutex {
+public:
+ UMUTEX_CONSTEXPR UMutex() {}
~UMutex() = default;
+
UMutex(const UMutex &other) = delete;
UMutex &operator =(const UMutex &other) = delete;
+ void *operator new(size_t) = delete;
- std::mutex fMutex = {}; // Note: struct - pubic members - because most access is from
- // // plain C style functions (umtx_lock(), etc.)
-};
-
-
-struct UConditionVar : public icu::UMemory {
- U_COMMON_API UConditionVar();
- U_COMMON_API ~UConditionVar();
- UConditionVar(const UConditionVar &other) = delete;
- UConditionVar &operator =(const UConditionVar &other) = delete;
-
- std::condition_variable_any fCV;
+ // requirements for C++ BasicLockable, allows UMutex to work with std::lock_guard
+ void lock() {
+ std::mutex *m = fMutex.load(std::memory_order_acquire);
+ if (m == nullptr) { m = getMutex(); }
+ m->lock();
+ }
+ void unlock() { fMutex.load(std::memory_order_relaxed)->unlock(); }
+
+ static void cleanup();
+
+private:
+ alignas(std::mutex) char fStorage[sizeof(std::mutex)] {};
+ std::atomic fMutex { nullptr };
+
+ /** All initialized UMutexes are kept in a linked list, so that they can be found,
+ * and the underlying std::mutex destructed, by u_cleanup().
+ */
+ UMutex *fListLink { nullptr };
+ static UMutex *gListHead;
+
+ /** Out-of-line function to lazily initialize a UMutex on first use.
+ * Initial fast check is inline, in lock(). The returned value may never
+ * be nullptr.
+ */
+ std::mutex *getMutex();
};
-#define U_MUTEX_INITIALIZER {}
-#define U_CONDITION_INITIALIZER {}
-
-// Implementation notes for UConditionVar:
-//
-// Use an out-of-line constructor to reduce problems with the ICU dependency checker.
-// On Linux, the default constructor of std::condition_variable_any
-// produces an in-line reference to global operator new(), which the
-// dependency checker flags for any file that declares a UConditionVar. With
-// an out-of-line constructor, the dependency is constrained to umutex.o
-//
-// Do not export (U_COMMON_API) the entire class, but only the constructor
-// and destructor, to avoid Windows build problems with attempting to export the
-// std::condition_variable_any.
/* Lock a mutex.
* @param mutex The given mutex to be locked. Pass NULL to specify
@@ -237,30 +270,6 @@
*/
U_INTERNAL void U_EXPORT2 umtx_unlock (UMutex* mutex);
-/*
- * Wait on a condition variable.
- * The calling thread will unlock the mutex and wait on the condition variable.
- * The mutex must be locked by the calling thread when invoking this function.
- *
- * @param cond the condition variable to wait on.
- * @param mutex the associated mutex.
- */
-
-U_INTERNAL void U_EXPORT2 umtx_condWait(UConditionVar *cond, UMutex *mutex);
-
-
-/*
- * Broadcast wakeup of all threads waiting on a Condition.
- *
- * @param cond the condition variable.
- */
-U_INTERNAL void U_EXPORT2 umtx_condBroadcast(UConditionVar *cond);
-
-/*
- * Signal a condition variable, waking up one waiting thread.
- */
-U_INTERNAL void U_EXPORT2 umtx_condSignal(UConditionVar *cond);
-
U_NAMESPACE_END
diff -Nru icu-64.2/source/common/unames.cpp icu-65.1/source/common/unames.cpp
--- icu-64.2/source/common/unames.cpp 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/unames.cpp 2019-10-03 11:16:41.000000000 +0000
@@ -212,13 +212,13 @@
return U_SUCCESS(*pErrorCode);
}
-#define WRITE_CHAR(buffer, bufferLength, bufferPos, c) { \
+#define WRITE_CHAR(buffer, bufferLength, bufferPos, c) UPRV_BLOCK_MACRO_BEGIN { \
if((bufferLength)>0) { \
*(buffer)++=c; \
--(bufferLength); \
} \
++(bufferPos); \
-}
+} UPRV_BLOCK_MACRO_END
#define U_ISO_COMMENT U_CHAR_NAME_CHOICE_COUNT
diff -Nru icu-64.2/source/common/unicode/appendable.h icu-65.1/source/common/unicode/appendable.h
--- icu-64.2/source/common/unicode/appendable.h 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/unicode/appendable.h 2019-10-03 11:16:41.000000000 +0000
@@ -23,6 +23,9 @@
*/
#include "unicode/utypes.h"
+
+#if U_SHOW_CPLUSPLUS_API
+
#include "unicode/uobject.h"
U_NAMESPACE_BEGIN
@@ -231,4 +234,6 @@
U_NAMESPACE_END
+#endif /* U_SHOW_CPLUSPLUS_API */
+
#endif // __APPENDABLE_H__
diff -Nru icu-64.2/source/common/unicode/brkiter.h icu-65.1/source/common/unicode/brkiter.h
--- icu-64.2/source/common/unicode/brkiter.h 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/unicode/brkiter.h 2019-10-03 11:16:41.000000000 +0000
@@ -29,6 +29,10 @@
* \brief C++ API: Break Iterator.
*/
+#include "unicode/utypes.h"
+
+#if U_SHOW_CPLUSPLUS_API
+
#if UCONFIG_NO_BREAK_ITERATION
U_NAMESPACE_BEGIN
@@ -135,7 +139,7 @@
* method which subclasses implement.
* @stable ICU 2.0
*/
- virtual BreakIterator* clone(void) const = 0;
+ virtual BreakIterator* clone() const = 0;
/**
* Return a polymorphic class ID for this object. Different subclasses
@@ -493,6 +497,7 @@
static UnicodeString& U_EXPORT2 getDisplayName(const Locale& objectLocale,
UnicodeString& name);
+#ifndef U_FORCE_HIDE_DEPRECATED_API
/**
* Deprecated functionality. Use clone() instead.
*
@@ -515,6 +520,7 @@
virtual BreakIterator * createBufferClone(void *stackBuffer,
int32_t &BufferSize,
UErrorCode &status) = 0;
+#endif // U_FORCE_HIDE_DEPRECATED_API
#ifndef U_HIDE_DEPRECATED_API
@@ -658,5 +664,7 @@
#endif /* #if !UCONFIG_NO_BREAK_ITERATION */
+#endif /* U_SHOW_CPLUSPLUS_API */
+
#endif // BRKITER_H
//eof
diff -Nru icu-64.2/source/common/unicode/bytestream.h icu-65.1/source/common/unicode/bytestream.h
--- icu-64.2/source/common/unicode/bytestream.h 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/unicode/bytestream.h 2019-10-03 11:16:41.000000000 +0000
@@ -38,6 +38,9 @@
*/
#include "unicode/utypes.h"
+
+#if U_SHOW_CPLUSPLUS_API
+
#include "unicode/uobject.h"
#include "unicode/std_string.h"
@@ -267,4 +270,6 @@
U_NAMESPACE_END
+#endif /* U_SHOW_CPLUSPLUS_API */
+
#endif // __BYTESTREAM_H__
diff -Nru icu-64.2/source/common/unicode/bytestriebuilder.h icu-65.1/source/common/unicode/bytestriebuilder.h
--- icu-64.2/source/common/unicode/bytestriebuilder.h 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/unicode/bytestriebuilder.h 2019-10-03 11:16:41.000000000 +0000
@@ -23,6 +23,9 @@
#define __BYTESTRIEBUILDER_H__
#include "unicode/utypes.h"
+
+#if U_SHOW_CPLUSPLUS_API
+
#include "unicode/bytestrie.h"
#include "unicode/stringpiece.h"
#include "unicode/stringtriebuilder.h"
@@ -179,4 +182,6 @@
U_NAMESPACE_END
+#endif /* U_SHOW_CPLUSPLUS_API */
+
#endif // __BYTESTRIEBUILDER_H__
diff -Nru icu-64.2/source/common/unicode/bytestrie.h icu-65.1/source/common/unicode/bytestrie.h
--- icu-64.2/source/common/unicode/bytestrie.h 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/unicode/bytestrie.h 2019-10-03 11:16:41.000000000 +0000
@@ -23,6 +23,9 @@
*/
#include "unicode/utypes.h"
+
+#if U_SHOW_CPLUSPLUS_API
+
#include "unicode/stringpiece.h"
#include "unicode/uobject.h"
#include "unicode/ustringtrie.h"
@@ -94,6 +97,41 @@
return *this;
}
+#ifndef U_HIDE_DRAFT_API
+ /**
+ * Returns the state of this trie as a 64-bit integer.
+ * The state value is never 0.
+ *
+ * @return opaque state value
+ * @see resetToState64
+ * @draft ICU 65
+ */
+ uint64_t getState64() const {
+ return (static_cast(remainingMatchLength_ + 2) << kState64RemainingShift) |
+ (uint64_t)(pos_ - bytes_);
+ }
+
+ /**
+ * Resets this trie to the saved state.
+ * Unlike resetToState(State), the 64-bit state value
+ * must be from getState64() from the same trie object or
+ * from one initialized the exact same way.
+ * Because of no validation, this method is faster.
+ *
+ * @param state The opaque trie state value from getState64().
+ * @return *this
+ * @see getState64
+ * @see resetToState
+ * @see reset
+ * @draft ICU 65
+ */
+ BytesTrie &resetToState64(uint64_t state) {
+ remainingMatchLength_ = static_cast(state >> kState64RemainingShift) - 2;
+ pos_ = bytes_ + (state & kState64PosMask);
+ return *this;
+ }
+#endif /* U_HIDE_DRAFT_API */
+
/**
* BytesTrie state object, for saving a trie's current state
* and resetting the trie back to this state later.
@@ -502,6 +540,13 @@
static const int32_t kMaxTwoByteDelta=((kMinThreeByteDeltaLead-kMinTwoByteDeltaLead)<<8)-1; // 0x2fff
static const int32_t kMaxThreeByteDelta=((kFourByteDeltaLead-kMinThreeByteDeltaLead)<<16)-1; // 0xdffff
+ // For getState64():
+ // The remainingMatchLength_ is -1..14=(kMaxLinearMatchLength=0x10)-2
+ // so we need at least 5 bits for that.
+ // We add 2 to store it as a positive value 1..16=kMaxLinearMatchLength.
+ static constexpr int32_t kState64RemainingShift = 59;
+ static constexpr uint64_t kState64PosMask = (UINT64_C(1) << kState64RemainingShift) - 1;
+
uint8_t *ownedArray_;
// Fixed value referencing the BytesTrie bytes.
@@ -517,4 +562,6 @@
U_NAMESPACE_END
+#endif /* U_SHOW_CPLUSPLUS_API */
+
#endif // __BYTESTRIE_H__
diff -Nru icu-64.2/source/common/unicode/caniter.h icu-65.1/source/common/unicode/caniter.h
--- icu-64.2/source/common/unicode/caniter.h 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/unicode/caniter.h 2019-10-03 11:16:41.000000000 +0000
@@ -12,6 +12,8 @@
#include "unicode/utypes.h"
+#if U_SHOW_CPLUSPLUS_API
+
#if !UCONFIG_NO_NORMALIZATION
#include "unicode/uobject.h"
@@ -207,4 +209,6 @@
#endif /* #if !UCONFIG_NO_NORMALIZATION */
+#endif /* U_SHOW_CPLUSPLUS_API */
+
#endif
diff -Nru icu-64.2/source/common/unicode/casemap.h icu-65.1/source/common/unicode/casemap.h
--- icu-64.2/source/common/unicode/casemap.h 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/unicode/casemap.h 2019-10-03 11:16:41.000000000 +0000
@@ -8,6 +8,9 @@
#define __CASEMAP_H__
#include "unicode/utypes.h"
+
+#if U_SHOW_CPLUSPLUS_API
+
#include "unicode/stringpiece.h"
#include "unicode/uobject.h"
@@ -489,4 +492,6 @@
U_NAMESPACE_END
+#endif /* U_SHOW_CPLUSPLUS_API */
+
#endif // __CASEMAP_H__
diff -Nru icu-64.2/source/common/unicode/char16ptr.h icu-65.1/source/common/unicode/char16ptr.h
--- icu-64.2/source/common/unicode/char16ptr.h 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/unicode/char16ptr.h 2019-10-03 11:16:41.000000000 +0000
@@ -7,9 +7,12 @@
#ifndef __CHAR16PTR_H__
#define __CHAR16PTR_H__
-#include
#include "unicode/utypes.h"
+#if U_SHOW_CPLUSPLUS_API
+
+#include
+
/**
* \file
* \brief C++ API: char16_t pointer wrappers with
@@ -305,4 +308,6 @@
U_NAMESPACE_END
+#endif /* U_SHOW_CPLUSPLUS_API */
+
#endif // __CHAR16PTR_H__
diff -Nru icu-64.2/source/common/unicode/chariter.h icu-65.1/source/common/unicode/chariter.h
--- icu-64.2/source/common/unicode/chariter.h 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/unicode/chariter.h 2019-10-03 11:16:41.000000000 +0000
@@ -13,6 +13,9 @@
#define CHARITER_H
#include "unicode/utypes.h"
+
+#if U_SHOW_CPLUSPLUS_API
+
#include "unicode/uobject.h"
#include "unicode/unistr.h"
/**
@@ -377,7 +380,7 @@
* @return a pointer to a new CharacterIterator
* @stable ICU 2.0
*/
- virtual CharacterIterator* clone(void) const = 0;
+ virtual CharacterIterator* clone() const = 0;
/**
* Sets the iterator to refer to the first code unit in its
@@ -725,4 +728,7 @@
}
U_NAMESPACE_END
+
+#endif /* U_SHOW_CPLUSPLUS_API */
+
#endif
diff -Nru icu-64.2/source/common/unicode/dbbi.h icu-65.1/source/common/unicode/dbbi.h
--- icu-64.2/source/common/unicode/dbbi.h 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/unicode/dbbi.h 2019-10-03 11:16:41.000000000 +0000
@@ -13,6 +13,10 @@
#ifndef DBBI_H
#define DBBI_H
+#include "unicode/utypes.h"
+
+#if U_SHOW_CPLUSPLUS_API
+
#include "unicode/rbbi.h"
#if !UCONFIG_NO_BREAK_ITERATION
@@ -39,4 +43,6 @@
#endif /* #if !UCONFIG_NO_BREAK_ITERATION */
+#endif /* U_SHOW_CPLUSPLUS_API */
+
#endif
diff -Nru icu-64.2/source/common/unicode/docmain.h icu-65.1/source/common/unicode/docmain.h
--- icu-64.2/source/common/unicode/docmain.h 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/unicode/docmain.h 2019-10-03 11:16:41.000000000 +0000
@@ -99,7 +99,7 @@
*
*
* Codepage Conversion
- * ucnv.h, ucnvsel.hb
+ * ucnv.h, ucnvsel.h
* C API
*
*
@@ -115,7 +115,7 @@
*
* Locales
* uloc.h
- * icu::Locale, icu::LocaleBuilder
+ * icu::Locale, icu::LocaleBuilder, icu::LocaleMatcher
*
*
* Resource Bundles
diff -Nru icu-64.2/source/common/unicode/dtintrv.h icu-65.1/source/common/unicode/dtintrv.h
--- icu-64.2/source/common/unicode/dtintrv.h 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/unicode/dtintrv.h 2019-10-03 11:16:41.000000000 +0000
@@ -15,6 +15,9 @@
#define __DTINTRV_H__
#include "unicode/utypes.h"
+
+#if U_SHOW_CPLUSPLUS_API
+
#include "unicode/uobject.h"
/**
@@ -22,7 +25,6 @@
* \brief C++ API: Date Interval data type
*/
-
U_NAMESPACE_BEGIN
@@ -157,4 +159,6 @@
U_NAMESPACE_END
+#endif /* U_SHOW_CPLUSPLUS_API */
+
#endif
diff -Nru icu-64.2/source/common/unicode/edits.h icu-65.1/source/common/unicode/edits.h
--- icu-64.2/source/common/unicode/edits.h 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/unicode/edits.h 2019-10-03 11:16:41.000000000 +0000
@@ -8,6 +8,9 @@
#define __EDITS_H__
#include "unicode/utypes.h"
+
+#if U_SHOW_CPLUSPLUS_API
+
#include "unicode/uobject.h"
/**
@@ -159,7 +162,7 @@
* @return TRUE if U_FAILURE(outErrorCode)
* @stable ICU 59
*/
- UBool copyErrorTo(UErrorCode &outErrorCode);
+ UBool copyErrorTo(UErrorCode &outErrorCode) const;
/**
* How much longer is the new text compared with the old text?
@@ -523,4 +526,6 @@
U_NAMESPACE_END
+#endif /* U_SHOW_CPLUSPLUS_API */
+
#endif // __EDITS_H__
diff -Nru icu-64.2/source/common/unicode/errorcode.h icu-65.1/source/common/unicode/errorcode.h
--- icu-64.2/source/common/unicode/errorcode.h 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/unicode/errorcode.h 2019-10-03 11:16:41.000000000 +0000
@@ -26,6 +26,9 @@
*/
#include "unicode/utypes.h"
+
+#if U_SHOW_CPLUSPLUS_API
+
#include "unicode/uobject.h"
U_NAMESPACE_BEGIN
@@ -136,4 +139,6 @@
U_NAMESPACE_END
+#endif /* U_SHOW_CPLUSPLUS_API */
+
#endif // __ERRORCODE_H__
diff -Nru icu-64.2/source/common/unicode/filteredbrk.h icu-65.1/source/common/unicode/filteredbrk.h
--- icu-64.2/source/common/unicode/filteredbrk.h 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/unicode/filteredbrk.h 2019-10-03 11:16:41.000000000 +0000
@@ -11,6 +11,9 @@
#define FILTEREDBRK_H
#include "unicode/utypes.h"
+
+#if U_SHOW_CPLUSPLUS_API
+
#include "unicode/brkiter.h"
#if !UCONFIG_NO_BREAK_ITERATION && !UCONFIG_NO_FILTERED_BREAK_ITERATION
@@ -101,6 +104,7 @@
*/
virtual UBool unsuppressBreakAfter(const UnicodeString& string, UErrorCode& status) = 0;
+#ifndef U_FORCE_HIDE_DEPRECATED_API
/**
* This function has been deprecated in favor of wrapIteratorWithFilter()
* The behavior is identical.
@@ -111,6 +115,7 @@
* @see wrapBreakIteratorWithFilter()
*/
virtual BreakIterator *build(BreakIterator* adoptBreakIterator, UErrorCode& status) = 0;
+#endif // U_FORCE_HIDE_DEPRECATED_API
/**
* Wrap (adopt) an existing break iterator in a new filtered instance.
@@ -142,4 +147,6 @@
#endif // #if !UCONFIG_NO_BREAK_ITERATION && !UCONFIG_NO_FILTERED_BREAK_ITERATION
+#endif /* U_SHOW_CPLUSPLUS_API */
+
#endif // #ifndef FILTEREDBRK_H
diff -Nru icu-64.2/source/common/unicode/idna.h icu-65.1/source/common/unicode/idna.h
--- icu-64.2/source/common/unicode/idna.h 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/unicode/idna.h 2019-10-03 11:16:41.000000000 +0000
@@ -24,6 +24,8 @@
#include "unicode/utypes.h"
+#if U_SHOW_CPLUSPLUS_API
+
#if !UCONFIG_NO_IDNA
#include "unicode/bytestream.h"
@@ -322,4 +324,7 @@
U_NAMESPACE_END
#endif // UCONFIG_NO_IDNA
+
+#endif /* U_SHOW_CPLUSPLUS_API */
+
#endif // __IDNA_H__
diff -Nru icu-64.2/source/common/unicode/localebuilder.h icu-65.1/source/common/unicode/localebuilder.h
--- icu-64.2/source/common/unicode/localebuilder.h 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/unicode/localebuilder.h 2019-10-03 11:16:41.000000000 +0000
@@ -3,11 +3,14 @@
#ifndef __LOCALEBUILDER_H__
#define __LOCALEBUILDER_H__
+#include "unicode/utypes.h"
+
+#if U_SHOW_CPLUSPLUS_API
+
#include "unicode/locid.h"
+#include "unicode/localematcher.h"
#include "unicode/stringpiece.h"
#include "unicode/uobject.h"
-#include "unicode/utypes.h"
-
#ifndef U_HIDE_DRAFT_API
/**
@@ -276,7 +279,24 @@
*/
Locale build(UErrorCode& status);
+#ifndef U_HIDE_DRAFT_API
+ /**
+ * Sets the UErrorCode if an error occurred while recording sets.
+ * Preserves older error codes in the outErrorCode.
+ * @param outErrorCode Set to an error code that occurred while setting subtags.
+ * Unchanged if there is no such error or if outErrorCode
+ * already contained an error.
+ * @return TRUE if U_FAILURE(outErrorCode)
+ * @draft ICU 65
+ */
+ UBool copyErrorTo(UErrorCode &outErrorCode) const;
+#endif /* U_HIDE_DRAFT_API */
+
private:
+ friend class LocaleMatcher::Result;
+
+ void copyExtensionsFrom(const Locale& src, UErrorCode& errorCode);
+
UErrorCode status_;
char language_[9];
char script_[5];
@@ -289,4 +309,7 @@
U_NAMESPACE_END
#endif // U_HIDE_DRAFT_API
+
+#endif /* U_SHOW_CPLUSPLUS_API */
+
#endif // __LOCALEBUILDER_H__
diff -Nru icu-64.2/source/common/unicode/localematcher.h icu-65.1/source/common/unicode/localematcher.h
--- icu-64.2/source/common/unicode/localematcher.h 1970-01-01 00:00:00.000000000 +0000
+++ icu-65.1/source/common/unicode/localematcher.h 2019-10-03 11:16:41.000000000 +0000
@@ -0,0 +1,605 @@
+// © 2019 and later: Unicode, Inc. and others.
+// License & terms of use: http://www.unicode.org/copyright.html#License
+
+// localematcher.h
+// created: 2019may08 Markus W. Scherer
+
+#ifndef __LOCALEMATCHER_H__
+#define __LOCALEMATCHER_H__
+
+#include "unicode/utypes.h"
+
+#if U_SHOW_CPLUSPLUS_API
+
+#include "unicode/locid.h"
+#include "unicode/stringpiece.h"
+#include "unicode/uobject.h"
+
+/**
+ * \file
+ * \brief C++ API: Locale matcher: User's desired locales vs. application's supported locales.
+ */
+
+#ifndef U_HIDE_DRAFT_API
+
+/**
+ * Builder option for whether the language subtag or the script subtag is most important.
+ *
+ * @see Builder#setFavorSubtag(FavorSubtag)
+ * @draft ICU 65
+ */
+enum ULocMatchFavorSubtag {
+ /**
+ * Language differences are most important, then script differences, then region differences.
+ * (This is the default behavior.)
+ *
+ * @draft ICU 65
+ */
+ ULOCMATCH_FAVOR_LANGUAGE,
+ /**
+ * Makes script differences matter relatively more than language differences.
+ *
+ * @draft ICU 65
+ */
+ ULOCMATCH_FAVOR_SCRIPT
+};
+#ifndef U_IN_DOXYGEN
+typedef enum ULocMatchFavorSubtag ULocMatchFavorSubtag;
+#endif
+
+/**
+ * Builder option for whether all desired locales are treated equally or
+ * earlier ones are preferred.
+ *
+ * @see Builder#setDemotionPerDesiredLocale(Demotion)
+ * @draft ICU 65
+ */
+enum ULocMatchDemotion {
+ /**
+ * All desired locales are treated equally.
+ *
+ * @draft ICU 65
+ */
+ ULOCMATCH_DEMOTION_NONE,
+ /**
+ * Earlier desired locales are preferred.
+ *
+ * From each desired locale to the next,
+ * the distance to any supported locale is increased by an additional amount
+ * which is at least as large as most region mismatches.
+ * A later desired locale has to have a better match with some supported locale
+ * due to more than merely having the same region subtag.
+ *
+ *
For example: Supported={en, sv} desired=[en-GB, sv]
+ * yields Result(en-GB, en)
because
+ * with the demotion of sv its perfect match is no better than
+ * the region distance between the earlier desired locale en-GB and en=en-US.
+ *
+ *
Notes:
+ *
+ * In some cases, language and/or script differences can be as small as
+ * the typical region difference. (Example: sr-Latn vs. sr-Cyrl)
+ * It is possible for certain region differences to be larger than usual,
+ * and larger than the demotion.
+ * (As of CLDR 35 there is no such case, but
+ * this is possible in future versions of the data.)
+ *
+ *
+ * @draft ICU 65
+ */
+ ULOCMATCH_DEMOTION_REGION
+};
+#ifndef U_IN_DOXYGEN
+typedef enum ULocMatchDemotion ULocMatchDemotion;
+#endif
+
+struct UHashtable;
+
+U_NAMESPACE_BEGIN
+
+struct LSR;
+
+class LocaleDistance;
+class LocaleLsrIterator;
+class UVector;
+class XLikelySubtags;
+
+/**
+ * Immutable class that picks the best match between a user's desired locales and
+ * an application's supported locales.
+ * Movable but not copyable.
+ *
+ * Example:
+ *
+ * UErrorCode errorCode = U_ZERO_ERROR;
+ * LocaleMatcher matcher = LocaleMatcher::Builder().setSupportedLocales("fr, en-GB, en").build(errorCode);
+ * Locale *bestSupported = matcher.getBestLocale(Locale.US, errorCode); // "en"
+ *
+ *
+ * A matcher takes into account when languages are close to one another,
+ * such as Danish and Norwegian,
+ * and when regional variants are close, like en-GB and en-AU as opposed to en-US.
+ *
+ *
If there are multiple supported locales with the same (language, script, region)
+ * likely subtags, then the current implementation returns the first of those locales.
+ * It ignores variant subtags (except for pseudolocale variants) and extensions.
+ * This may change in future versions.
+ *
+ *
For example, the current implementation does not distinguish between
+ * de, de-DE, de-Latn, de-1901, de-u-co-phonebk.
+ *
+ *
If you prefer one equivalent locale over another, then provide only the preferred one,
+ * or place it earlier in the list of supported locales.
+ *
+ *
Otherwise, the order of supported locales may have no effect on the best-match results.
+ * The current implementation compares each desired locale with supported locales
+ * in the following order:
+ * 1. Default locale, if supported;
+ * 2. CLDR "paradigm locales" like en-GB and es-419;
+ * 3. other supported locales.
+ * This may change in future versions.
+ *
+ *
Often a product will just need one matcher instance, built with the languages
+ * that it supports. However, it may want multiple instances with different
+ * default languages based on additional information, such as the domain.
+ *
+ *
This class is not intended for public subclassing.
+ *
+ * @draft ICU 65
+ */
+class U_COMMON_API LocaleMatcher : public UMemory {
+public:
+ /**
+ * Data for the best-matching pair of a desired and a supported locale.
+ * Movable but not copyable.
+ *
+ * @draft ICU 65
+ */
+ class U_COMMON_API Result : public UMemory {
+ public:
+ /**
+ * Move constructor; might modify the source.
+ * This object will have the same contents that the source object had.
+ *
+ * @param src Result to move contents from.
+ * @draft ICU 65
+ */
+ Result(Result &&src) U_NOEXCEPT;
+
+ /**
+ * Destructor.
+ *
+ * @draft ICU 65
+ */
+ ~Result();
+
+ /**
+ * Move assignment; might modify the source.
+ * This object will have the same contents that the source object had.
+ *
+ * @param src Result to move contents from.
+ * @draft ICU 65
+ */
+ Result &operator=(Result &&src) U_NOEXCEPT;
+
+ /**
+ * Returns the best-matching desired locale.
+ * nullptr if the list of desired locales is empty or if none matched well enough.
+ *
+ * @return the best-matching desired locale, or nullptr.
+ * @draft ICU 65
+ */
+ inline const Locale *getDesiredLocale() const { return desiredLocale; }
+
+ /**
+ * Returns the best-matching supported locale.
+ * If none matched well enough, this is the default locale.
+ * The default locale is nullptr if the list of supported locales is empty and
+ * no explicit default locale is set.
+ *
+ * @return the best-matching supported locale, or nullptr.
+ * @draft ICU 65
+ */
+ inline const Locale *getSupportedLocale() const { return supportedLocale; }
+
+ /**
+ * Returns the index of the best-matching desired locale in the input Iterable order.
+ * -1 if the list of desired locales is empty or if none matched well enough.
+ *
+ * @return the index of the best-matching desired locale, or -1.
+ * @draft ICU 65
+ */
+ inline int32_t getDesiredIndex() const { return desiredIndex; }
+
+ /**
+ * Returns the index of the best-matching supported locale in the
+ * constructor’s or builder’s input order (“set” Collection plus “added” locales).
+ * If the matcher was built from a locale list string, then the iteration order is that
+ * of a LocalePriorityList built from the same string.
+ * -1 if the list of supported locales is empty or if none matched well enough.
+ *
+ * @return the index of the best-matching supported locale, or -1.
+ * @draft ICU 65
+ */
+ inline int32_t getSupportedIndex() const { return supportedIndex; }
+
+ /**
+ * Takes the best-matching supported locale and adds relevant fields of the
+ * best-matching desired locale, such as the -t- and -u- extensions.
+ * May replace some fields of the supported locale.
+ * The result is the locale that should be used for date and number formatting, collation, etc.
+ * Returns the root locale if getSupportedLocale() returns nullptr.
+ *
+ *
Example: desired=ar-SA-u-nu-latn, supported=ar-EG, resolved locale=ar-SA-u-nu-latn
+ *
+ * @return a locale combining the best-matching desired and supported locales.
+ * @draft ICU 65
+ */
+ Locale makeResolvedLocale(UErrorCode &errorCode) const;
+
+ private:
+ Result(const Locale *desired, const Locale *supported,
+ int32_t desIndex, int32_t suppIndex, UBool owned) :
+ desiredLocale(desired), supportedLocale(supported),
+ desiredIndex(desIndex), supportedIndex(suppIndex),
+ desiredIsOwned(owned) {}
+
+ Result(const Result &other) = delete;
+ Result &operator=(const Result &other) = delete;
+
+ const Locale *desiredLocale;
+ const Locale *supportedLocale;
+ int32_t desiredIndex;
+ int32_t supportedIndex;
+ UBool desiredIsOwned;
+
+ friend class LocaleMatcher;
+ };
+
+ /**
+ * LocaleMatcher builder.
+ * Movable but not copyable.
+ *
+ * @see LocaleMatcher#builder()
+ * @draft ICU 65
+ */
+ class U_COMMON_API Builder : public UMemory {
+ public:
+ /**
+ * Constructs a builder used in chaining parameters for building a LocaleMatcher.
+ *
+ * @return a new Builder object
+ * @draft ICU 65
+ */
+ Builder() {}
+
+ /**
+ * Move constructor; might modify the source.
+ * This builder will have the same contents that the source builder had.
+ *
+ * @param src Builder to move contents from.
+ * @draft ICU 65
+ */
+ Builder(Builder &&src) U_NOEXCEPT;
+
+ /**
+ * Destructor.
+ *
+ * @draft ICU 65
+ */
+ ~Builder();
+
+ /**
+ * Move assignment; might modify the source.
+ * This builder will have the same contents that the source builder had.
+ *
+ * @param src Builder to move contents from.
+ * @draft ICU 65
+ */
+ Builder &operator=(Builder &&src) U_NOEXCEPT;
+
+ /**
+ * Parses an Accept-Language string
+ * (RFC 2616 Section 14.4 ),
+ * such as "af, en, fr;q=0.9", and sets the supported locales accordingly.
+ * Allows whitespace in more places but does not allow "*".
+ * Clears any previously set/added supported locales first.
+ *
+ * @param locales the Accept-Language string of locales to set
+ * @return this Builder object
+ * @draft ICU 65
+ */
+ Builder &setSupportedLocalesFromListString(StringPiece locales);
+
+ /**
+ * Copies the supported locales, preserving iteration order.
+ * Clears any previously set/added supported locales first.
+ * Duplicates are allowed, and are not removed.
+ *
+ * @param locales the list of locale
+ * @return this Builder object
+ * @draft ICU 65
+ */
+ Builder &setSupportedLocales(Locale::Iterator &locales);
+
+ /**
+ * Copies the supported locales from the begin/end range, preserving iteration order.
+ * Clears any previously set/added supported locales first.
+ * Duplicates are allowed, and are not removed.
+ *
+ * Each of the iterator parameter values must be an
+ * input iterator whose value is convertible to const Locale &.
+ *
+ * @param begin Start of range.
+ * @param end Exclusive end of range.
+ * @return this Builder object
+ * @draft ICU 65
+ */
+ template
+ Builder &setSupportedLocales(Iter begin, Iter end) {
+ if (U_FAILURE(errorCode_)) { return *this; }
+ clearSupportedLocales();
+ while (begin != end) {
+ addSupportedLocale(*begin++);
+ }
+ return *this;
+ }
+
+ /**
+ * Copies the supported locales from the begin/end range, preserving iteration order.
+ * Calls the converter to convert each *begin to a Locale or const Locale &.
+ * Clears any previously set/added supported locales first.
+ * Duplicates are allowed, and are not removed.
+ *
+ * Each of the iterator parameter values must be an
+ * input iterator whose value is convertible to const Locale &.
+ *
+ * @param begin Start of range.
+ * @param end Exclusive end of range.
+ * @param converter Converter from *begin to const Locale & or compatible.
+ * @return this Builder object
+ * @draft ICU 65
+ */
+ template
+ Builder &setSupportedLocalesViaConverter(Iter begin, Iter end, Conv converter) {
+ if (U_FAILURE(errorCode_)) { return *this; }
+ clearSupportedLocales();
+ while (begin != end) {
+ addSupportedLocale(converter(*begin++));
+ }
+ return *this;
+ }
+
+ /**
+ * Adds another supported locale.
+ * Duplicates are allowed, and are not removed.
+ *
+ * @param locale another locale
+ * @return this Builder object
+ * @draft ICU 65
+ */
+ Builder &addSupportedLocale(const Locale &locale);
+
+ /**
+ * Sets the default locale; if nullptr, or if it is not set explicitly,
+ * then the first supported locale is used as the default locale.
+ *
+ * @param defaultLocale the default locale (will be copied)
+ * @return this Builder object
+ * @draft ICU 65
+ */
+ Builder &setDefaultLocale(const Locale *defaultLocale);
+
+ /**
+ * If ULOCMATCH_FAVOR_SCRIPT, then the language differences are smaller than script
+ * differences.
+ * This is used in situations (such as maps) where
+ * it is better to fall back to the same script than a similar language.
+ *
+ * @param subtag the subtag to favor
+ * @return this Builder object
+ * @draft ICU 65
+ */
+ Builder &setFavorSubtag(ULocMatchFavorSubtag subtag);
+
+ /**
+ * Option for whether all desired locales are treated equally or
+ * earlier ones are preferred (this is the default).
+ *
+ * @param demotion the demotion per desired locale to set.
+ * @return this Builder object
+ * @draft ICU 65
+ */
+ Builder &setDemotionPerDesiredLocale(ULocMatchDemotion demotion);
+
+ /**
+ * Sets the UErrorCode if an error occurred while setting parameters.
+ * Preserves older error codes in the outErrorCode.
+ *
+ * @param outErrorCode Set to an error code if it does not contain one already
+ * and an error occurred while setting parameters.
+ * Otherwise unchanged.
+ * @return TRUE if U_FAILURE(outErrorCode)
+ * @draft ICU 65
+ */
+ UBool copyErrorTo(UErrorCode &outErrorCode) const;
+
+ /**
+ * Builds and returns a new locale matcher.
+ * This builder can continue to be used.
+ *
+ * @param errorCode ICU error code. Its input value must pass the U_SUCCESS() test,
+ * or else the function returns immediately. Check for U_FAILURE()
+ * on output or use with function chaining. (See User Guide for details.)
+ * @return new LocaleMatcher.
+ * @draft ICU 65
+ */
+ LocaleMatcher build(UErrorCode &errorCode) const;
+
+ private:
+ friend class LocaleMatcher;
+
+ Builder(const Builder &other) = delete;
+ Builder &operator=(const Builder &other) = delete;
+
+ void clearSupportedLocales();
+ bool ensureSupportedLocaleVector();
+
+ UErrorCode errorCode_ = U_ZERO_ERROR;
+ UVector *supportedLocales_ = nullptr;
+ int32_t thresholdDistance_ = -1;
+ ULocMatchDemotion demotion_ = ULOCMATCH_DEMOTION_REGION;
+ Locale *defaultLocale_ = nullptr;
+ ULocMatchFavorSubtag favor_ = ULOCMATCH_FAVOR_LANGUAGE;
+ };
+
+ // FYI No public LocaleMatcher constructors in C++; use the Builder.
+
+ /**
+ * Move copy constructor; might modify the source.
+ * This matcher will have the same settings that the source matcher had.
+ * @param src source matcher
+ * @draft ICU 65
+ */
+ LocaleMatcher(LocaleMatcher &&src) U_NOEXCEPT;
+
+ /**
+ * Destructor.
+ * @draft ICU 65
+ */
+ ~LocaleMatcher();
+
+ /**
+ * Move assignment operator; might modify the source.
+ * This matcher will have the same settings that the source matcher had.
+ * The behavior is undefined if *this and src are the same object.
+ * @param src source matcher
+ * @return *this
+ * @draft ICU 65
+ */
+ LocaleMatcher &operator=(LocaleMatcher &&src) U_NOEXCEPT;
+
+ /**
+ * Returns the supported locale which best matches the desired locale.
+ *
+ * @param desiredLocale Typically a user's language.
+ * @param errorCode ICU error code. Its input value must pass the U_SUCCESS() test,
+ * or else the function returns immediately. Check for U_FAILURE()
+ * on output or use with function chaining. (See User Guide for details.)
+ * @return the best-matching supported locale.
+ * @draft ICU 65
+ */
+ const Locale *getBestMatch(const Locale &desiredLocale, UErrorCode &errorCode) const;
+
+ /**
+ * Returns the supported locale which best matches one of the desired locales.
+ *
+ * @param desiredLocales Typically a user's languages, in order of preference (descending).
+ * @param errorCode ICU error code. Its input value must pass the U_SUCCESS() test,
+ * or else the function returns immediately. Check for U_FAILURE()
+ * on output or use with function chaining. (See User Guide for details.)
+ * @return the best-matching supported locale.
+ * @draft ICU 65
+ */
+ const Locale *getBestMatch(Locale::Iterator &desiredLocales, UErrorCode &errorCode) const;
+
+ /**
+ * Parses an Accept-Language string
+ * (RFC 2616 Section 14.4 ),
+ * such as "af, en, fr;q=0.9",
+ * and returns the supported locale which best matches one of the desired locales.
+ * Allows whitespace in more places but does not allow "*".
+ *
+ * @param desiredLocaleList Typically a user's languages, as an Accept-Language string.
+ * @param errorCode ICU error code. Its input value must pass the U_SUCCESS() test,
+ * or else the function returns immediately. Check for U_FAILURE()
+ * on output or use with function chaining. (See User Guide for details.)
+ * @return the best-matching supported locale.
+ * @draft ICU 65
+ */
+ const Locale *getBestMatchForListString(StringPiece desiredLocaleList, UErrorCode &errorCode) const;
+
+ /**
+ * Returns the best match between the desired locale and the supported locales.
+ * If the result's desired locale is not nullptr, then it is the address of the input locale.
+ * It has not been cloned.
+ *
+ * @param desiredLocale Typically a user's language.
+ * @param errorCode ICU error code. Its input value must pass the U_SUCCESS() test,
+ * or else the function returns immediately. Check for U_FAILURE()
+ * on output or use with function chaining. (See User Guide for details.)
+ * @return the best-matching pair of the desired and a supported locale.
+ * @draft ICU 65
+ */
+ Result getBestMatchResult(const Locale &desiredLocale, UErrorCode &errorCode) const;
+
+ /**
+ * Returns the best match between the desired and supported locales.
+ * If the result's desired locale is not nullptr, then it is a clone of
+ * the best-matching desired locale. The Result object owns the clone.
+ *
+ * @param desiredLocales Typically a user's languages, in order of preference (descending).
+ * @param errorCode ICU error code. Its input value must pass the U_SUCCESS() test,
+ * or else the function returns immediately. Check for U_FAILURE()
+ * on output or use with function chaining. (See User Guide for details.)
+ * @return the best-matching pair of a desired and a supported locale.
+ * @draft ICU 65
+ */
+ Result getBestMatchResult(Locale::Iterator &desiredLocales, UErrorCode &errorCode) const;
+
+#ifndef U_HIDE_INTERNAL_API
+ /**
+ * Returns a fraction between 0 and 1, where 1 means that the languages are a
+ * perfect match, and 0 means that they are completely different.
+ *
+ * This is mostly an implementation detail, and the precise values may change over time.
+ * The implementation may use either the maximized forms or the others ones, or both.
+ * The implementation may or may not rely on the forms to be consistent with each other.
+ *
+ *
Callers should construct and use a matcher rather than match pairs of locales directly.
+ *
+ * @param desired Desired locale.
+ * @param supported Supported locale.
+ * @param errorCode ICU error code. Its input value must pass the U_SUCCESS() test,
+ * or else the function returns immediately. Check for U_FAILURE()
+ * on output or use with function chaining. (See User Guide for details.)
+ * @return value between 0 and 1, inclusive.
+ * @internal (has a known user)
+ */
+ double internalMatch(const Locale &desired, const Locale &supported, UErrorCode &errorCode) const;
+#endif // U_HIDE_INTERNAL_API
+
+private:
+ LocaleMatcher(const Builder &builder, UErrorCode &errorCode);
+ LocaleMatcher(const LocaleMatcher &other) = delete;
+ LocaleMatcher &operator=(const LocaleMatcher &other) = delete;
+
+ int32_t getBestSuppIndex(LSR desiredLSR, LocaleLsrIterator *remainingIter, UErrorCode &errorCode) const;
+
+ const XLikelySubtags &likelySubtags;
+ const LocaleDistance &localeDistance;
+ int32_t thresholdDistance;
+ int32_t demotionPerDesiredLocale;
+ ULocMatchFavorSubtag favorSubtag;
+
+ // These are in input order.
+ const Locale ** supportedLocales;
+ LSR *lsrs;
+ int32_t supportedLocalesLength;
+ // These are in preference order: 1. Default locale 2. paradigm locales 3. others.
+ UHashtable *supportedLsrToIndex; // Map stores index+1 because 0 is "not found"
+ // Array versions of the supportedLsrToIndex keys and values.
+ // The distance lookup loops over the supportedLSRs and returns the index of the best match.
+ const LSR **supportedLSRs;
+ int32_t *supportedIndexes;
+ int32_t supportedLSRsLength;
+ Locale *ownedDefaultLocale;
+ const Locale *defaultLocale;
+ int32_t defaultLocaleIndex;
+};
+
+U_NAMESPACE_END
+
+#endif // U_HIDE_DRAFT_API
+#endif // U_SHOW_CPLUSPLUS_API
+#endif // __LOCALEMATCHER_H__
diff -Nru icu-64.2/source/common/unicode/locdspnm.h icu-65.1/source/common/unicode/locdspnm.h
--- icu-64.2/source/common/unicode/locdspnm.h 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/unicode/locdspnm.h 2019-10-03 11:16:41.000000000 +0000
@@ -12,6 +12,8 @@
#include "unicode/utypes.h"
+#if U_SHOW_CPLUSPLUS_API
+
/**
* \file
* \brief C++ API: Provides display names of Locale and its components.
@@ -204,4 +206,6 @@
#endif
+#endif /* U_SHOW_CPLUSPLUS_API */
+
#endif
diff -Nru icu-64.2/source/common/unicode/locid.h icu-65.1/source/common/unicode/locid.h
--- icu-64.2/source/common/unicode/locid.h 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/unicode/locid.h 2019-10-03 11:16:41.000000000 +0000
@@ -31,11 +31,14 @@
#ifndef LOCID_H
#define LOCID_H
+#include "unicode/utypes.h"
+
+#if U_SHOW_CPLUSPLUS_API
+
#include "unicode/bytestream.h"
#include "unicode/localpointer.h"
#include "unicode/strenum.h"
#include "unicode/stringpiece.h"
-#include "unicode/utypes.h"
#include "unicode/uobject.h"
#include "unicode/putil.h"
#include "unicode/uloc.h"
@@ -284,16 +287,14 @@
*/
Locale(const Locale& other);
-#ifndef U_HIDE_DRAFT_API
/**
* Move constructor; might leave source in bogus state.
* This locale will have the same contents that the source locale had.
*
* @param other The Locale object being moved in.
- * @draft ICU 63
+ * @stable ICU 63
*/
Locale(Locale&& other) U_NOEXCEPT;
-#endif // U_HIDE_DRAFT_API
/**
* Destructor
@@ -310,7 +311,6 @@
*/
Locale& operator=(const Locale& other);
-#ifndef U_HIDE_DRAFT_API
/**
* Move assignment operator; might leave source in bogus state.
* This locale will have the same contents that the source locale had.
@@ -318,10 +318,9 @@
*
* @param other The Locale object being moved in.
* @return *this
- * @draft ICU 63
+ * @stable ICU 63
*/
Locale& operator=(Locale&& other) U_NOEXCEPT;
-#endif // U_HIDE_DRAFT_API
/**
* Checks if two locale keys are the same.
@@ -389,7 +388,6 @@
UErrorCode& success);
#endif /* U_HIDE_SYSTEM_API */
-#ifndef U_HIDE_DRAFT_API
/**
* Returns a Locale for the specified BCP47 language tag string.
* If the specified language tag contains any ill-formed subtags,
@@ -405,7 +403,7 @@
* @param tag the input BCP47 language tag.
* @param status error information if creating the Locale failed.
* @return the Locale for the specified BCP47 language tag.
- * @draft ICU 63
+ * @stable ICU 63
*/
static Locale U_EXPORT2 forLanguageTag(StringPiece tag, UErrorCode& status);
@@ -420,7 +418,7 @@
* @param sink the output sink receiving the BCP47 language
* tag for this Locale.
* @param status error information if creating the language tag failed.
- * @draft ICU 63
+ * @stable ICU 63
*/
void toLanguageTag(ByteSink& sink, UErrorCode& status) const;
@@ -432,11 +430,10 @@
*
* @param status error information if creating the language tag failed.
* @return the BCP47 language tag for this Locale.
- * @draft ICU 63
+ * @stable ICU 63
*/
template
inline StringClass toLanguageTag(UErrorCode& status) const;
-#endif // U_HIDE_DRAFT_API
/**
* Creates a locale which has had minimal canonicalization
@@ -508,7 +505,6 @@
*/
const char * getBaseName() const;
-#ifndef U_HIDE_DRAFT_API
/**
* Add the likely subtags for this Locale, per the algorithm described
* in the following CLDR technical report:
@@ -536,7 +532,7 @@
* @param status error information if maximizing this Locale failed.
* If this Locale is not well-formed, the error code is
* U_ILLEGAL_ARGUMENT_ERROR.
- * @draft ICU 63
+ * @stable ICU 63
*/
void addLikelySubtags(UErrorCode& status);
@@ -567,10 +563,9 @@
* @param status error information if maximizing this Locale failed.
* If this Locale is not well-formed, the error code is
* U_ILLEGAL_ARGUMENT_ERROR.
- * @draft ICU 63
+ * @stable ICU 63
*/
void minimizeSubtags(UErrorCode& status);
-#endif // U_HIDE_DRAFT_API
/**
* Gets the list of keywords for the specified locale.
@@ -583,8 +578,6 @@
*/
StringEnumeration * createKeywords(UErrorCode &status) const;
-#ifndef U_HIDE_DRAFT_API
-
/**
* Gets the list of Unicode keywords for the specified locale.
*
@@ -592,7 +585,7 @@
* @return pointer to StringEnumeration class, or NULL if there are no keywords.
* Client must dispose of it by calling delete.
* @see getUnicodeKeywords
- * @draft ICU 63
+ * @stable ICU 63
*/
StringEnumeration * createUnicodeKeywords(UErrorCode &status) const;
@@ -605,7 +598,7 @@
*
* @param iterator an STL style output iterator to write the keywords to.
* @param status error information if creating set of keywords failed.
- * @draft ICU 63
+ * @stable ICU 63
*/
template
inline void getKeywords(OutputIterator iterator, UErrorCode& status) const;
@@ -619,13 +612,11 @@
*
* @param iterator an STL style output iterator to write the keywords to.
* @param status error information if creating set of keywords failed.
- * @draft ICU 63
+ * @stable ICU 63
*/
template
inline void getUnicodeKeywords(OutputIterator iterator, UErrorCode& status) const;
-#endif // U_HIDE_DRAFT_API
-
/**
* Gets the value for a keyword.
*
@@ -644,7 +635,6 @@
*/
int32_t getKeywordValue(const char* keywordName, char *buffer, int32_t bufferCapacity, UErrorCode &status) const;
-#ifndef U_HIDE_DRAFT_API
/**
* Gets the value for a keyword.
*
@@ -656,7 +646,7 @@
* @param keywordName name of the keyword for which we want the value.
* @param sink the sink to receive the keyword value.
* @param status error information if getting the value failed.
- * @draft ICU 63
+ * @stable ICU 63
*/
void getKeywordValue(StringPiece keywordName, ByteSink& sink, UErrorCode& status) const;
@@ -671,7 +661,7 @@
* @param keywordName name of the keyword for which we want the value.
* @param status error information if getting the value failed.
* @return the keyword value.
- * @draft ICU 63
+ * @stable ICU 63
*/
template
inline StringClass getKeywordValue(StringPiece keywordName, UErrorCode& status) const;
@@ -687,7 +677,7 @@
* @param keywordName name of the keyword for which we want the value.
* @param sink the sink to receive the keyword value.
* @param status error information if getting the value failed.
- * @draft ICU 63
+ * @stable ICU 63
*/
void getUnicodeKeywordValue(StringPiece keywordName, ByteSink& sink, UErrorCode& status) const;
@@ -702,11 +692,10 @@
* @param keywordName name of the keyword for which we want the value.
* @param status error information if getting the value failed.
* @return the keyword value.
- * @draft ICU 63
+ * @stable ICU 63
*/
template
inline StringClass getUnicodeKeywordValue(StringPiece keywordName, UErrorCode& status) const;
-#endif // U_HIDE_DRAFT_API
/**
* Sets or removes the value for a keyword.
@@ -729,7 +718,6 @@
*/
void setKeywordValue(const char* keywordName, const char* keywordValue, UErrorCode &status);
-#ifndef U_HIDE_DRAFT_API
/**
* Sets or removes the value for a keyword.
*
@@ -746,7 +734,7 @@
* NULL, will result in the keyword being removed. No error is given if
* that keyword does not exist.
* @param status Returns any error information while performing this operation.
- * @draft ICU 63
+ * @stable ICU 63
*/
void setKeywordValue(StringPiece keywordName, StringPiece keywordValue, UErrorCode& status);
@@ -766,10 +754,9 @@
* NULL, will result in the keyword being removed. No error is given if
* that keyword does not exist.
* @param status Returns any error information while performing this operation.
- * @draft ICU 63
+ * @stable ICU 63
*/
void setUnicodeKeywordValue(StringPiece keywordName, StringPiece keywordValue, UErrorCode& status);
-#endif // U_HIDE_DRAFT_API
/**
* returns the locale's three-letter language code, as specified
@@ -1008,6 +995,104 @@
*/
virtual UClassID getDynamicClassID() const;
+#ifndef U_HIDE_DRAFT_API
+ /**
+ * A Locale iterator interface similar to a Java Iterator.
+ * @draft ICU 65
+ */
+ class U_COMMON_API Iterator /* not : public UObject because this is an interface/mixin class */ {
+ public:
+ /** @draft ICU 65 */
+ virtual ~Iterator();
+
+ /**
+ * @return TRUE if next() can be called again.
+ * @draft ICU 65
+ */
+ virtual UBool hasNext() const = 0;
+
+ /**
+ * @return the next locale.
+ * @draft ICU 65
+ */
+ virtual const Locale &next() = 0;
+ };
+
+ /**
+ * A generic Locale iterator implementation over Locale input iterators.
+ * @draft ICU 65
+ */
+ template
+ class RangeIterator : public Iterator, public UMemory {
+ public:
+ /**
+ * Constructs an iterator from a begin/end range.
+ * Each of the iterator parameter values must be an
+ * input iterator whose value is convertible to const Locale &.
+ *
+ * @param begin Start of range.
+ * @param end Exclusive end of range.
+ * @draft ICU 65
+ */
+ RangeIterator(Iter begin, Iter end) : it_(begin), end_(end) {}
+
+ /**
+ * @return TRUE if next() can be called again.
+ * @draft ICU 65
+ */
+ UBool hasNext() const override { return it_ != end_; }
+
+ /**
+ * @return the next locale.
+ * @draft ICU 65
+ */
+ const Locale &next() override { return *it_++; }
+
+ private:
+ Iter it_;
+ const Iter end_;
+ };
+
+ /**
+ * A generic Locale iterator implementation over Locale input iterators.
+ * Calls the converter to convert each *begin to a const Locale &.
+ * @draft ICU 65
+ */
+ template
+ class ConvertingIterator : public Iterator, public UMemory {
+ public:
+ /**
+ * Constructs an iterator from a begin/end range.
+ * Each of the iterator parameter values must be an
+ * input iterator whose value the converter converts to const Locale &.
+ *
+ * @param begin Start of range.
+ * @param end Exclusive end of range.
+ * @param converter Converter from *begin to const Locale & or compatible.
+ * @draft ICU 65
+ */
+ ConvertingIterator(Iter begin, Iter end, Conv converter) :
+ it_(begin), end_(end), converter_(converter) {}
+
+ /**
+ * @return TRUE if next() can be called again.
+ * @draft ICU 65
+ */
+ UBool hasNext() const override { return it_ != end_; }
+
+ /**
+ * @return the next locale.
+ * @draft ICU 65
+ */
+ const Locale &next() override { return converter_(*it_++); }
+
+ private:
+ Iter it_;
+ const Iter end_;
+ Conv converter_;
+ };
+#endif // U_HIDE_DRAFT_API
+
protected: /* only protected for testing purposes. DO NOT USE. */
#ifndef U_HIDE_INTERNAL_API
/**
@@ -1074,7 +1159,6 @@
return !operator==(other);
}
-#ifndef U_HIDE_DRAFT_API
template inline StringClass
Locale::toLanguageTag(UErrorCode& status) const
{
@@ -1083,7 +1167,6 @@
toLanguageTag(sink, status);
return result;
}
-#endif // U_HIDE_DRAFT_API
inline const char *
Locale::getCountry() const
@@ -1115,13 +1198,11 @@
return fullName;
}
-#ifndef U_HIDE_DRAFT_API
-
template inline void
Locale::getKeywords(OutputIterator iterator, UErrorCode& status) const
{
LocalPointer keys(createKeywords(status));
- if (U_FAILURE(status)) {
+ if (U_FAILURE(status) || keys.isNull()) {
return;
}
for (;;) {
@@ -1138,7 +1219,7 @@
Locale::getUnicodeKeywords(OutputIterator iterator, UErrorCode& status) const
{
LocalPointer keys(createUnicodeKeywords(status));
- if (U_FAILURE(status)) {
+ if (U_FAILURE(status) || keys.isNull()) {
return;
}
for (;;) {
@@ -1169,8 +1250,6 @@
return result;
}
-#endif // U_HIDE_DRAFT_API
-
inline UBool
Locale::isBogus(void) const {
return fIsBogus;
@@ -1178,4 +1257,6 @@
U_NAMESPACE_END
+#endif /* U_SHOW_CPLUSPLUS_API */
+
#endif
diff -Nru icu-64.2/source/common/unicode/messagepattern.h icu-65.1/source/common/unicode/messagepattern.h
--- icu-64.2/source/common/unicode/messagepattern.h 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/unicode/messagepattern.h 2019-10-03 11:16:41.000000000 +0000
@@ -24,6 +24,8 @@
#include "unicode/utypes.h"
+#if U_SHOW_CPLUSPLUS_API
+
#if !UCONFIG_NO_FORMATTING
#include "unicode/parseerr.h"
@@ -942,4 +944,6 @@
#endif // !UCONFIG_NO_FORMATTING
+#endif /* U_SHOW_CPLUSPLUS_API */
+
#endif // __MESSAGEPATTERN_H__
diff -Nru icu-64.2/source/common/unicode/normalizer2.h icu-65.1/source/common/unicode/normalizer2.h
--- icu-64.2/source/common/unicode/normalizer2.h 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/unicode/normalizer2.h 2019-10-03 11:16:41.000000000 +0000
@@ -26,6 +26,8 @@
#include "unicode/utypes.h"
+#if U_SHOW_CPLUSPLUS_API
+
#if !UCONFIG_NO_NORMALIZATION
#include "unicode/stringpiece.h"
@@ -771,4 +773,7 @@
U_NAMESPACE_END
#endif // !UCONFIG_NO_NORMALIZATION
+
+#endif /* U_SHOW_CPLUSPLUS_API */
+
#endif // __NORMALIZER2_H__
diff -Nru icu-64.2/source/common/unicode/normlzr.h icu-65.1/source/common/unicode/normlzr.h
--- icu-64.2/source/common/unicode/normlzr.h 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/unicode/normlzr.h 2019-10-03 11:16:41.000000000 +0000
@@ -13,6 +13,8 @@
#include "unicode/utypes.h"
+#if U_SHOW_CPLUSPLUS_API
+
/**
* \file
* \brief C++ API: Unicode Normalization
@@ -183,6 +185,7 @@
Normalizer(const CharacterIterator& iter, UNormalizationMode mode);
#endif /* U_HIDE_DEPRECATED_API */
+#ifndef U_FORCE_HIDE_DEPRECATED_API
/**
* Copy constructor.
* @param copy The object to be copied.
@@ -195,7 +198,7 @@
* @deprecated ICU 56 Use Normalizer2 instead.
*/
virtual ~Normalizer();
-
+#endif // U_FORCE_HIDE_DEPRECATED_API
//-------------------------------------------------------------------------
// Static utility methods
@@ -599,7 +602,7 @@
* @return a pointer to a new Normalizer
* @deprecated ICU 56 Use Normalizer2 instead.
*/
- Normalizer* clone(void) const;
+ Normalizer* clone() const;
/**
* Generates a hash code for this iterator.
@@ -723,12 +726,14 @@
static UClassID U_EXPORT2 getStaticClassID();
#endif /* U_HIDE_DEPRECATED_API */
+#ifndef U_FORCE_HIDE_DEPRECATED_API
/**
* ICU "poor man's RTTI", returns a UClassID for the actual class.
* @return a UClassID for the actual class.
* @deprecated ICU 56 Use Normalizer2 instead.
*/
virtual UClassID getDynamicClassID() const;
+#endif // U_FORCE_HIDE_DEPRECATED_API
private:
//-------------------------------------------------------------------------
@@ -807,3 +812,5 @@
#endif /* #if !UCONFIG_NO_NORMALIZATION */
#endif // NORMLZR_H
+
+#endif /* U_SHOW_CPLUSPLUS_API */
diff -Nru icu-64.2/source/common/unicode/parsepos.h icu-65.1/source/common/unicode/parsepos.h
--- icu-64.2/source/common/unicode/parsepos.h 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/unicode/parsepos.h 2019-10-03 11:16:41.000000000 +0000
@@ -19,6 +19,9 @@
#define PARSEPOS_H
#include "unicode/utypes.h"
+
+#if U_SHOW_CPLUSPLUS_API
+
#include "unicode/uobject.h"
@@ -229,4 +232,6 @@
}
U_NAMESPACE_END
+#endif /* U_SHOW_CPLUSPLUS_API */
+
#endif
diff -Nru icu-64.2/source/common/unicode/platform.h icu-65.1/source/common/unicode/platform.h
--- icu-64.2/source/common/unicode/platform.h 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/unicode/platform.h 2019-10-03 11:16:41.000000000 +0000
@@ -135,6 +135,14 @@
/** Fuchsia is a POSIX-ish platform. @internal */
#define U_PF_FUCHSIA 4100
/* Maximum value for Linux-based platform is 4499 */
+/**
+ * Emscripten is a C++ transpiler for the Web that can target asm.js or
+ * WebAssembly. It provides some POSIX-compatible wrappers and stubs and
+ * some Linux-like functionality, but is not fully compatible with
+ * either.
+ * @internal
+ */
+#define U_PF_EMSCRIPTEN 5010
/** z/OS is the successor to OS/390 which was the successor to MVS. @internal */
#define U_PF_OS390 9000
/** "IBM i" is the current name of what used to be i5/OS and earlier OS/400. @internal */
@@ -192,6 +200,8 @@
# define U_PLATFORM U_PF_OS390
#elif defined(__OS400__) || defined(__TOS_OS400__)
# define U_PLATFORM U_PF_OS400
+#elif defined(__EMSCRIPTEN__)
+# define U_PLATFORM U_PF_EMSCRIPTEN
#else
# define U_PLATFORM U_PF_UNKNOWN
#endif
@@ -414,26 +424,40 @@
#endif
/* Compatibility with compilers other than clang: http://clang.llvm.org/docs/LanguageExtensions.html */
-#ifndef __has_attribute
-# define __has_attribute(x) 0
+#ifdef __has_attribute
+# define UPRV_HAS_ATTRIBUTE(x) __has_attribute(x)
+#else
+# define UPRV_HAS_ATTRIBUTE(x) 0
#endif
-#ifndef __has_cpp_attribute
-# define __has_cpp_attribute(x) 0
+#ifdef __has_cpp_attribute
+# define UPRV_HAS_CPP_ATTRIBUTE(x) __has_cpp_attribute(x)
+#else
+# define UPRV_HAS_CPP_ATTRIBUTE(x) 0
#endif
-#ifndef __has_declspec_attribute
-# define __has_declspec_attribute(x) 0
+#ifdef __has_declspec_attribute
+# define UPRV_HAS_DECLSPEC_ATTRIBUTE(x) __has_declspec_attribute(x)
+#else
+# define UPRV_HAS_DECLSPEC_ATTRIBUTE(x) 0
#endif
-#ifndef __has_builtin
-# define __has_builtin(x) 0
+#ifdef __has_builtin
+# define UPRV_HAS_BUILTIN(x) __has_builtin(x)
+#else
+# define UPRV_HAS_BUILTIN(x) 0
#endif
-#ifndef __has_feature
-# define __has_feature(x) 0
+#ifdef __has_feature
+# define UPRV_HAS_FEATURE(x) __has_feature(x)
+#else
+# define UPRV_HAS_FEATURE(x) 0
#endif
-#ifndef __has_extension
-# define __has_extension(x) 0
+#ifdef __has_extension
+# define UPRV_HAS_EXTENSION(x) __has_extension(x)
+#else
+# define UPRV_HAS_EXTENSION(x) 0
#endif
-#ifndef __has_warning
-# define __has_warning(x) 0
+#ifdef __has_warning
+# define UPRV_HAS_WARNING(x) __has_warning(x)
+#else
+# define UPRV_HAS_WARNING(x) 0
#endif
/**
@@ -452,7 +476,9 @@
* Attribute to specify the size of the allocated buffer for malloc-like functions
* @internal
*/
-#if (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))) || __has_attribute(alloc_size)
+#if (defined(__GNUC__) && \
+ (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))) || \
+ UPRV_HAS_ATTRIBUTE(alloc_size)
# define U_ALLOC_SIZE_ATTR(X) __attribute__ ((alloc_size(X)))
# define U_ALLOC_SIZE_ATTR2(X,Y) __attribute__ ((alloc_size(X,Y)))
#else
@@ -516,8 +542,9 @@
#elif defined(__clang__)
// Test for compiler vs. feature separately.
// Other compilers might choke on the feature test.
-# if __has_cpp_attribute(clang::fallthrough) || \
- (__has_feature(cxx_attributes) && __has_warning("-Wimplicit-fallthrough"))
+# if UPRV_HAS_CPP_ATTRIBUTE(clang::fallthrough) || \
+ (UPRV_HAS_FEATURE(cxx_attributes) && \
+ UPRV_HAS_WARNING("-Wimplicit-fallthrough"))
# define U_FALLTHROUGH [[clang::fallthrough]]
# endif
#elif defined(__GNUC__) && (__GNUC__ >= 7)
@@ -620,7 +647,8 @@
*/
#ifdef U_CHARSET_IS_UTF8
/* Use the predefined value. */
-#elif U_PLATFORM_IS_LINUX_BASED || U_PLATFORM_IS_DARWIN_BASED
+#elif U_PLATFORM_IS_LINUX_BASED || U_PLATFORM_IS_DARWIN_BASED || \
+ U_PLATFORM == U_PF_EMSCRIPTEN
# define U_CHARSET_IS_UTF8 1
#else
# define U_CHARSET_IS_UTF8 0
@@ -707,7 +735,7 @@
* narrow-character strings are in EBCDIC.
*/
# define U_SIZEOF_WCHAR_T 2
-#else
+# else
/*
* LOCALETYPE(*CLD) or LOCALETYPE(*LOCALE) is specified.
* Wide-character strings are in 16-bit EBCDIC,
@@ -786,7 +814,8 @@
/* Use the predefined value. */
#elif defined(U_STATIC_IMPLEMENTATION)
# define U_EXPORT
-#elif defined(_MSC_VER) || (__has_declspec_attribute(dllexport) && __has_declspec_attribute(dllimport))
+#elif defined(_MSC_VER) || (UPRV_HAS_DECLSPEC_ATTRIBUTE(dllexport) && \
+ UPRV_HAS_DECLSPEC_ATTRIBUTE(dllimport))
# define U_EXPORT __declspec(dllexport)
#elif defined(__GNUC__)
# define U_EXPORT __attribute__((visibility("default")))
@@ -810,7 +839,8 @@
#ifdef U_IMPORT
/* Use the predefined value. */
-#elif defined(_MSC_VER) || (__has_declspec_attribute(dllexport) && __has_declspec_attribute(dllimport))
+#elif defined(_MSC_VER) || (UPRV_HAS_DECLSPEC_ATTRIBUTE(dllexport) && \
+ UPRV_HAS_DECLSPEC_ATTRIBUTE(dllimport))
/* Windows needs to export/import data. */
# define U_IMPORT __declspec(dllimport)
#else
@@ -852,4 +882,4 @@
#endif
/* @} */
-#endif
+#endif // _PLATFORM_H
diff -Nru icu-64.2/source/common/unicode/rbbi.h icu-65.1/source/common/unicode/rbbi.h
--- icu-64.2/source/common/unicode/rbbi.h 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/unicode/rbbi.h 2019-10-03 11:16:41.000000000 +0000
@@ -18,6 +18,8 @@
#include "unicode/utypes.h"
+#if U_SHOW_CPLUSPLUS_API
+
/**
* \file
* \brief C++ API: Rule Based Break Iterator
@@ -272,7 +274,7 @@
* @return a newly-constructed RuleBasedBreakIterator
* @stable ICU 2.0
*/
- virtual BreakIterator* clone() const;
+ virtual RuleBasedBreakIterator* clone() const;
/**
* Compute a hash code for this BreakIterator
@@ -536,6 +538,7 @@
*/
static UClassID U_EXPORT2 getStaticClassID(void);
+#ifndef U_FORCE_HIDE_DEPRECATED_API
/**
* Deprecated functionality. Use clone() instead.
*
@@ -562,10 +565,10 @@
* or if the stackBuffer was too small to hold the clone.
* @deprecated ICU 52. Use clone() instead.
*/
- virtual BreakIterator * createBufferClone(void *stackBuffer,
- int32_t &BufferSize,
- UErrorCode &status);
-
+ virtual RuleBasedBreakIterator *createBufferClone(void *stackBuffer,
+ int32_t &BufferSize,
+ UErrorCode &status);
+#endif // U_FORCE_HIDE_DEPRECATED_API
/**
* Return the binary form of compiled break rules,
@@ -696,4 +699,6 @@
#endif /* #if !UCONFIG_NO_BREAK_ITERATION */
+#endif /* U_SHOW_CPLUSPLUS_API */
+
#endif
diff -Nru icu-64.2/source/common/unicode/rep.h icu-65.1/source/common/unicode/rep.h
--- icu-64.2/source/common/unicode/rep.h 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/unicode/rep.h 2019-10-03 11:16:41.000000000 +0000
@@ -16,6 +16,10 @@
#ifndef REP_H
#define REP_H
+#include "unicode/utypes.h"
+
+#if U_SHOW_CPLUSPLUS_API
+
#include "unicode/uobject.h"
/**
@@ -189,9 +193,6 @@
* Clones can be used concurrently in multiple threads.
* If a subclass does not implement clone(), or if an error occurs,
* then NULL is returned.
- * The clone functions in all subclasses return a pointer to a Replaceable
- * because some compilers do not support covariant (same-as-this)
- * return types; cast to the appropriate subclass if necessary.
* The caller must delete the clone.
*
* @return a clone of this object
@@ -260,4 +261,6 @@
U_NAMESPACE_END
+#endif /* U_SHOW_CPLUSPLUS_API */
+
#endif
diff -Nru icu-64.2/source/common/unicode/resbund.h icu-65.1/source/common/unicode/resbund.h
--- icu-64.2/source/common/unicode/resbund.h 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/unicode/resbund.h 2019-10-03 11:16:41.000000000 +0000
@@ -49,6 +49,9 @@
#define RESBUND_H
#include "unicode/utypes.h"
+
+#if U_SHOW_CPLUSPLUS_API
+
#include "unicode/uobject.h"
#include "unicode/ures.h"
#include "unicode/unistr.h"
@@ -489,4 +492,7 @@
};
U_NAMESPACE_END
+
+#endif /* U_SHOW_CPLUSPLUS_API */
+
#endif
diff -Nru icu-64.2/source/common/unicode/schriter.h icu-65.1/source/common/unicode/schriter.h
--- icu-64.2/source/common/unicode/schriter.h 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/unicode/schriter.h 2019-10-03 11:16:41.000000000 +0000
@@ -21,6 +21,9 @@
#define SCHRITER_H
#include "unicode/utypes.h"
+
+#if U_SHOW_CPLUSPLUS_API
+
#include "unicode/chariter.h"
#include "unicode/uchriter.h"
@@ -130,7 +133,7 @@
* @return the newly cloned object.
* @stable ICU 2.0
*/
- virtual CharacterIterator* clone(void) const;
+ virtual StringCharacterIterator* clone() const;
/**
* Sets the iterator to iterate over the provided string.
@@ -186,4 +189,7 @@
};
U_NAMESPACE_END
+
+#endif /* U_SHOW_CPLUSPLUS_API */
+
#endif
diff -Nru icu-64.2/source/common/unicode/simpleformatter.h icu-65.1/source/common/unicode/simpleformatter.h
--- icu-64.2/source/common/unicode/simpleformatter.h 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/unicode/simpleformatter.h 2019-10-03 11:16:41.000000000 +0000
@@ -17,6 +17,9 @@
*/
#include "unicode/utypes.h"
+
+#if U_SHOW_CPLUSPLUS_API
+
#include "unicode/unistr.h"
U_NAMESPACE_BEGIN
@@ -333,4 +336,6 @@
U_NAMESPACE_END
+#endif /* U_SHOW_CPLUSPLUS_API */
+
#endif // __SIMPLEFORMATTER_H__
diff -Nru icu-64.2/source/common/unicode/std_string.h icu-65.1/source/common/unicode/std_string.h
--- icu-64.2/source/common/unicode/std_string.h 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/unicode/std_string.h 2019-10-03 11:16:41.000000000 +0000
@@ -27,6 +27,8 @@
#include "unicode/utypes.h"
+#if U_SHOW_CPLUSPLUS_API
+
// Workaround for a libstdc++ bug before libstdc++4.6 (2011).
// https://bugs.llvm.org/show_bug.cgi?id=13364
#if defined(__GLIBCXX__)
@@ -34,4 +36,6 @@
#endif
#include
+#endif /* U_SHOW_CPLUSPLUS_API */
+
#endif // __STD_STRING_H__
diff -Nru icu-64.2/source/common/unicode/strenum.h icu-65.1/source/common/unicode/strenum.h
--- icu-64.2/source/common/unicode/strenum.h 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/unicode/strenum.h 2019-10-03 11:16:41.000000000 +0000
@@ -12,6 +12,10 @@
#ifndef STRENUM_H
#define STRENUM_H
+#include "unicode/utypes.h"
+
+#if U_SHOW_CPLUSPLUS_API
+
#include "unicode/uobject.h"
#include "unicode/unistr.h"
@@ -67,9 +71,6 @@
* Clones can be used concurrently in multiple threads.
* If a subclass does not implement clone(), or if an error occurs,
* then NULL is returned.
- * The clone functions in all subclasses return a base class pointer
- * because some compilers do not support covariant (same-as-this)
- * return types; cast to the appropriate subclass if necessary.
* The caller must delete the clone.
*
* @return a clone of this object
@@ -274,5 +275,7 @@
U_NAMESPACE_END
+#endif /* U_SHOW_CPLUSPLUS_API */
+
/* STRENUM_H */
#endif
diff -Nru icu-64.2/source/common/unicode/stringpiece.h icu-65.1/source/common/unicode/stringpiece.h
--- icu-64.2/source/common/unicode/stringpiece.h 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/unicode/stringpiece.h 2019-10-03 11:16:41.000000000 +0000
@@ -28,6 +28,12 @@
*/
#include "unicode/utypes.h"
+
+#if U_SHOW_CPLUSPLUS_API
+
+#include
+#include
+
#include "unicode/uobject.h"
#include "unicode/std_string.h"
@@ -74,6 +80,33 @@
*/
StringPiece(const std::string& str)
: ptr_(str.data()), length_(static_cast(str.size())) { }
+#ifndef U_HIDE_DRAFT_API
+ /**
+ * Constructs from some other implementation of a string piece class, from any
+ * C++ record type that has these two methods:
+ *
+ * \code{.cpp}
+ *
+ * struct OtherStringPieceClass {
+ * const char* data();
+ * size_t size();
+ * };
+ *
+ * \endcode
+ *
+ * The other string piece class will typically be std::string_view from C++17
+ * or absl::string_view from Abseil.
+ *
+ * @param str the other string piece
+ * @draft ICU 65
+ */
+ template ::value &&
+ std::is_same::value>::type>
+ StringPiece(T str)
+ : ptr_(str.data()), length_(static_cast(str.size())) {}
+#endif // U_HIDE_DRAFT_API
/**
* Constructs from a const char * pointer and a specified length.
* @param offset a const char * pointer (need not be terminated)
@@ -221,4 +254,6 @@
U_NAMESPACE_END
+#endif /* U_SHOW_CPLUSPLUS_API */
+
#endif // __STRINGPIECE_H__
diff -Nru icu-64.2/source/common/unicode/stringtriebuilder.h icu-65.1/source/common/unicode/stringtriebuilder.h
--- icu-64.2/source/common/unicode/stringtriebuilder.h 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/unicode/stringtriebuilder.h 2019-10-03 11:16:41.000000000 +0000
@@ -18,6 +18,9 @@
#define __STRINGTRIEBUILDER_H__
#include "unicode/utypes.h"
+
+#if U_SHOW_CPLUSPLUS_API
+
#include "unicode/uobject.h"
/**
@@ -418,4 +421,6 @@
U_NAMESPACE_END
+#endif /* U_SHOW_CPLUSPLUS_API */
+
#endif // __STRINGTRIEBUILDER_H__
diff -Nru icu-64.2/source/common/unicode/symtable.h icu-65.1/source/common/unicode/symtable.h
--- icu-64.2/source/common/unicode/symtable.h 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/unicode/symtable.h 2019-10-03 11:16:41.000000000 +0000
@@ -13,6 +13,9 @@
#define SYMTABLE_H
#include "unicode/utypes.h"
+
+#if U_SHOW_CPLUSPLUS_API
+
#include "unicode/uobject.h"
/**
@@ -111,4 +114,6 @@
};
U_NAMESPACE_END
+#endif /* U_SHOW_CPLUSPLUS_API */
+
#endif
diff -Nru icu-64.2/source/common/unicode/uchar.h icu-65.1/source/common/unicode/uchar.h
--- icu-64.2/source/common/unicode/uchar.h 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/unicode/uchar.h 2019-10-03 11:16:41.000000000 +0000
@@ -2578,8 +2578,6 @@
U_STABLE UBool U_EXPORT2
u_hasBinaryProperty(UChar32 c, UProperty which);
-#ifndef U_HIDE_DRAFT_API
-
/**
* Returns a frozen USet for a binary property.
* The library retains ownership over the returned object.
@@ -2593,13 +2591,11 @@
* @see UProperty
* @see u_hasBinaryProperty
* @see Unicode::fromUSet
- * @draft ICU 63
+ * @stable ICU 63
*/
U_CAPI const USet * U_EXPORT2
u_getBinaryPropertySet(UProperty property, UErrorCode *pErrorCode);
-#endif // U_HIDE_DRAFT_API
-
/**
* Check if a code point has the Alphabetic Unicode property.
* Same as u_hasBinaryProperty(c, UCHAR_ALPHABETIC).
@@ -2757,8 +2753,6 @@
U_STABLE int32_t U_EXPORT2
u_getIntPropertyMaxValue(UProperty which);
-#ifndef U_HIDE_DRAFT_API
-
/**
* Returns an immutable UCPMap for an enumerated/catalog/int-valued property.
* The library retains ownership over the returned object.
@@ -2772,13 +2766,11 @@
* @return the property as a map
* @see UProperty
* @see u_getIntPropertyValue
- * @draft ICU 63
+ * @stable ICU 63
*/
U_CAPI const UCPMap * U_EXPORT2
u_getIntPropertyMap(UProperty property, UErrorCode *pErrorCode);
-#endif // U_HIDE_DRAFT_API
-
/**
* Get the numeric value for a Unicode code point as defined in the
* Unicode Character Database.
@@ -3197,15 +3189,14 @@
u_isprint(UChar32 c);
/**
- * Determines whether the specified code point is a base character.
+ * Non-standard: Determines whether the specified code point is a base character.
* True for general categories "L" (letters), "N" (numbers),
* "Mc" (spacing combining marks), and "Me" (enclosing marks).
*
- * Note that this is different from the Unicode definition in
- * chapter 3.5, conformance clause D13,
- * which defines base characters to be all characters (not Cn)
- * that do not graphically combine with preceding characters (M)
- * and that are neither control (Cc) or format (Cf) characters.
+ * Note that this is different from the Unicode Standard definition in
+ * chapter 3.6, conformance clause D51 “Base character”,
+ * which defines base characters as the code points with general categories
+ * Letter (L), Number (N), Punctuation (P), Symbol (S), or Space Separator (Zs).
*
* @param c the code point to be tested
* @return TRUE if the code point is a base character according to this function
diff -Nru icu-64.2/source/common/unicode/ucharstriebuilder.h icu-65.1/source/common/unicode/ucharstriebuilder.h
--- icu-64.2/source/common/unicode/ucharstriebuilder.h 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/unicode/ucharstriebuilder.h 2019-10-03 11:16:41.000000000 +0000
@@ -18,6 +18,9 @@
#define __UCHARSTRIEBUILDER_H__
#include "unicode/utypes.h"
+
+#if U_SHOW_CPLUSPLUS_API
+
#include "unicode/stringtriebuilder.h"
#include "unicode/ucharstrie.h"
#include "unicode/unistr.h"
@@ -184,4 +187,6 @@
U_NAMESPACE_END
+#endif /* U_SHOW_CPLUSPLUS_API */
+
#endif // __UCHARSTRIEBUILDER_H__
diff -Nru icu-64.2/source/common/unicode/ucharstrie.h icu-65.1/source/common/unicode/ucharstrie.h
--- icu-64.2/source/common/unicode/ucharstrie.h 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/unicode/ucharstrie.h 2019-10-03 11:16:41.000000000 +0000
@@ -24,6 +24,9 @@
*/
#include "unicode/utypes.h"
+
+#if U_SHOW_CPLUSPLUS_API
+
#include "unicode/unistr.h"
#include "unicode/uobject.h"
#include "unicode/ustringtrie.h"
@@ -94,6 +97,41 @@
return *this;
}
+#ifndef U_HIDE_DRAFT_API
+ /**
+ * Returns the state of this trie as a 64-bit integer.
+ * The state value is never 0.
+ *
+ * @return opaque state value
+ * @see resetToState64
+ * @draft ICU 65
+ */
+ uint64_t getState64() const {
+ return (static_cast(remainingMatchLength_ + 2) << kState64RemainingShift) |
+ (uint64_t)(pos_ - uchars_);
+ }
+
+ /**
+ * Resets this trie to the saved state.
+ * Unlike resetToState(State), the 64-bit state value
+ * must be from getState64() from the same trie object or
+ * from one initialized the exact same way.
+ * Because of no validation, this method is faster.
+ *
+ * @param state The opaque trie state value from getState64().
+ * @return *this
+ * @see getState64
+ * @see resetToState
+ * @see reset
+ * @draft ICU 65
+ */
+ UCharsTrie &resetToState64(uint64_t state) {
+ remainingMatchLength_ = static_cast(state >> kState64RemainingShift) - 2;
+ pos_ = uchars_ + (state & kState64PosMask);
+ return *this;
+ }
+#endif /* U_HIDE_DRAFT_API */
+
/**
* UCharsTrie state object, for saving a trie's current state
* and resetting the trie back to this state later.
@@ -560,6 +598,13 @@
static const int32_t kMaxTwoUnitDelta=((kThreeUnitDeltaLead-kMinTwoUnitDeltaLead)<<16)-1; // 0x03feffff
+ // For getState64():
+ // The remainingMatchLength_ is -1..14=(kMaxLinearMatchLength=0x10)-2
+ // so we need at least 5 bits for that.
+ // We add 2 to store it as a positive value 1..16=kMaxLinearMatchLength.
+ static constexpr int32_t kState64RemainingShift = 59;
+ static constexpr uint64_t kState64PosMask = (UINT64_C(1) << kState64RemainingShift) - 1;
+
char16_t *ownedArray_;
// Fixed value referencing the UCharsTrie words.
@@ -575,4 +620,6 @@
U_NAMESPACE_END
+#endif /* U_SHOW_CPLUSPLUS_API */
+
#endif // __UCHARSTRIE_H__
diff -Nru icu-64.2/source/common/unicode/uchriter.h icu-65.1/source/common/unicode/uchriter.h
--- icu-64.2/source/common/unicode/uchriter.h 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/unicode/uchriter.h 2019-10-03 11:16:41.000000000 +0000
@@ -11,6 +11,9 @@
#define UCHRITER_H
#include "unicode/utypes.h"
+
+#if U_SHOW_CPLUSPLUS_API
+
#include "unicode/chariter.h"
/**
@@ -132,7 +135,7 @@
* @return the CharacterIterator newly created
* @stable ICU 2.0
*/
- virtual CharacterIterator* clone(void) const;
+ virtual UCharCharacterIterator* clone() const;
/**
* Sets the iterator to refer to the first code unit in its
@@ -384,4 +387,7 @@
};
U_NAMESPACE_END
+
+#endif /* U_SHOW_CPLUSPLUS_API */
+
#endif
diff -Nru icu-64.2/source/common/unicode/uconfig.h icu-65.1/source/common/unicode/uconfig.h
--- icu-64.2/source/common/unicode/uconfig.h 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/unicode/uconfig.h 2019-10-03 11:16:41.000000000 +0000
@@ -453,4 +453,4 @@
# define UCONFIG_NO_FILTERED_BREAK_ITERATION 0
#endif
-#endif
+#endif // __UCONFIG_H__
diff -Nru icu-64.2/source/common/unicode/ucpmap.h icu-65.1/source/common/unicode/ucpmap.h
--- icu-64.2/source/common/unicode/ucpmap.h 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/unicode/ucpmap.h 2019-10-03 11:16:41.000000000 +0000
@@ -9,8 +9,6 @@
#include "unicode/utypes.h"
-#ifndef U_HIDE_DRAFT_API
-
U_CDECL_BEGIN
/**
@@ -28,7 +26,7 @@
*
* @see UCPTrie
* @see UMutableCPTrie
- * @draft ICU 63
+ * @stable ICU 63
*/
typedef struct UCPMap UCPMap;
@@ -39,13 +37,13 @@
* @see ucpmap_getRange
* @see ucptrie_getRange
* @see umutablecptrie_getRange
- * @draft ICU 63
+ * @stable ICU 63
*/
enum UCPMapRangeOption {
/**
* ucpmap_getRange() enumerates all same-value ranges as stored in the map.
* Most users should use this option.
- * @draft ICU 63
+ * @stable ICU 63
*/
UCPMAP_RANGE_NORMAL,
/**
@@ -61,7 +59,7 @@
* special values optimized for UTF-16 string processing
* or for special error behavior for unpaired surrogates,
* but those values are not to be associated with the lead surrogate code *points*.
- * @draft ICU 63
+ * @stable ICU 63
*/
UCPMAP_RANGE_FIXED_LEAD_SURROGATES,
/**
@@ -77,7 +75,7 @@
* special values optimized for UTF-16 string processing
* or for special error behavior for unpaired surrogates,
* but those values are not to be associated with the lead surrogate code *points*.
- * @draft ICU 63
+ * @stable ICU 63
*/
UCPMAP_RANGE_FIXED_ALL_SURROGATES
};
@@ -93,7 +91,7 @@
* @param c the code point
* @return the map value,
* or an implementation-defined error value if the code point is not in the range 0..U+10FFFF
- * @draft ICU 63
+ * @stable ICU 63
*/
U_CAPI uint32_t U_EXPORT2
ucpmap_get(const UCPMap *map, UChar32 c);
@@ -110,7 +108,7 @@
* @param context an opaque pointer, as passed into the getRange function
* @param value a value from the map
* @return the modified value
- * @draft ICU 63
+ * @stable ICU 63
*/
typedef uint32_t U_CALLCONV
UCPMapValueFilter(const void *context, uint32_t value);
@@ -149,7 +147,7 @@
* may have been modified by filter(context, map value)
* if that function pointer is not NULL
* @return the range end code point, or -1 if start is not a valid code point
- * @draft ICU 63
+ * @stable ICU 63
*/
U_CAPI UChar32 U_EXPORT2
ucpmap_getRange(const UCPMap *map, UChar32 start,
@@ -158,5 +156,4 @@
U_CDECL_END
-#endif // U_HIDE_DRAFT_API
#endif
diff -Nru icu-64.2/source/common/unicode/ucptrie.h icu-65.1/source/common/unicode/ucptrie.h
--- icu-64.2/source/common/unicode/ucptrie.h 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/unicode/ucptrie.h 2019-10-03 11:16:41.000000000 +0000
@@ -9,8 +9,6 @@
#include "unicode/utypes.h"
-#ifndef U_HIDE_DRAFT_API
-
#include "unicode/localpointer.h"
#include "unicode/ucpmap.h"
#include "unicode/utf8.h"
@@ -55,7 +53,7 @@
* The macros will return bogus values, or may crash, if used on the wrong type or value width.
*
* @see UMutableCPTrie
- * @draft ICU 63
+ * @stable ICU 63
*/
struct UCPTrie {
#ifndef U_IN_DOXYGEN
@@ -115,23 +113,23 @@
* @see umutablecptrie_buildImmutable
* @see ucptrie_openFromBinary
* @see ucptrie_getType
- * @draft ICU 63
+ * @stable ICU 63
*/
enum UCPTrieType {
/**
* For ucptrie_openFromBinary() to accept any type.
* ucptrie_getType() will return the actual type.
- * @draft ICU 63
+ * @stable ICU 63
*/
UCPTRIE_TYPE_ANY = -1,
/**
* Fast/simple/larger BMP data structure. Use functions and "fast" macros.
- * @draft ICU 63
+ * @stable ICU 63
*/
UCPTRIE_TYPE_FAST,
/**
* Small/slower BMP data structure. Use functions and "small" macros.
- * @draft ICU 63
+ * @stable ICU 63
*/
UCPTRIE_TYPE_SMALL
};
@@ -145,30 +143,30 @@
* @see umutablecptrie_buildImmutable
* @see ucptrie_openFromBinary
* @see ucptrie_getValueWidth
- * @draft ICU 63
+ * @stable ICU 63
*/
enum UCPTrieValueWidth {
/**
* For ucptrie_openFromBinary() to accept any data value width.
* ucptrie_getValueWidth() will return the actual data value width.
- * @draft ICU 63
+ * @stable ICU 63
*/
UCPTRIE_VALUE_BITS_ANY = -1,
/**
* The trie stores 16 bits per data value.
* It returns them as unsigned values 0..0xffff=65535.
- * @draft ICU 63
+ * @stable ICU 63
*/
UCPTRIE_VALUE_BITS_16,
/**
* The trie stores 32 bits per data value.
- * @draft ICU 63
+ * @stable ICU 63
*/
UCPTRIE_VALUE_BITS_32,
/**
* The trie stores 8 bits per data value.
* It returns them as unsigned values 0..0xff=255.
- * @draft ICU 63
+ * @stable ICU 63
*/
UCPTRIE_VALUE_BITS_8
};
@@ -200,7 +198,7 @@
* @see umutablecptrie_open
* @see umutablecptrie_buildImmutable
* @see ucptrie_toBinary
- * @draft ICU 63
+ * @stable ICU 63
*/
U_CAPI UCPTrie * U_EXPORT2
ucptrie_openFromBinary(UCPTrieType type, UCPTrieValueWidth valueWidth,
@@ -211,30 +209,11 @@
* Closes a trie and releases associated memory.
*
* @param trie the trie
- * @draft ICU 63
+ * @stable ICU 63
*/
U_CAPI void U_EXPORT2
ucptrie_close(UCPTrie *trie);
-#if U_SHOW_CPLUSPLUS_API
-
-U_NAMESPACE_BEGIN
-
-/**
- * \class LocalUCPTriePointer
- * "Smart pointer" class, closes a UCPTrie via ucptrie_close().
- * For most methods see the LocalPointerBase base class.
- *
- * @see LocalPointerBase
- * @see LocalPointer
- * @draft ICU 63
- */
-U_DEFINE_LOCAL_OPEN_POINTER(LocalUCPTriePointer, UCPTrie, ucptrie_close);
-
-U_NAMESPACE_END
-
-#endif
-
/**
* Returns the trie type.
*
@@ -242,7 +221,7 @@
* @return the trie type
* @see ucptrie_openFromBinary
* @see UCPTRIE_TYPE_ANY
- * @draft ICU 63
+ * @stable ICU 63
*/
U_CAPI UCPTrieType U_EXPORT2
ucptrie_getType(const UCPTrie *trie);
@@ -254,7 +233,7 @@
* @return the number of bits in a trie data value
* @see ucptrie_openFromBinary
* @see UCPTRIE_VALUE_BITS_ANY
- * @draft ICU 63
+ * @stable ICU 63
*/
U_CAPI UCPTrieValueWidth U_EXPORT2
ucptrie_getValueWidth(const UCPTrie *trie);
@@ -271,7 +250,7 @@
* @param c the code point
* @return the trie value,
* or the trie error value if the code point is not in the range 0..U+10FFFF
- * @draft ICU 63
+ * @stable ICU 63
*/
U_CAPI uint32_t U_EXPORT2
ucptrie_get(const UCPTrie *trie, UChar32 c);
@@ -310,7 +289,7 @@
* may have been modified by filter(context, trie value)
* if that function pointer is not NULL
* @return the range end code point, or -1 if start is not a valid code point
- * @draft ICU 63
+ * @stable ICU 63
*/
U_CAPI UChar32 U_EXPORT2
ucptrie_getRange(const UCPTrie *trie, UChar32 start,
@@ -330,7 +309,7 @@
* @return the number of bytes written or (if buffer overflow) needed for the trie
*
* @see ucptrie_openFromBinary()
- * @draft ICU 63
+ * @stable ICU 63
*/
U_CAPI int32_t U_EXPORT2
ucptrie_toBinary(const UCPTrie *trie, void *data, int32_t capacity, UErrorCode *pErrorCode);
@@ -341,7 +320,7 @@
* Do not use this macro in any other way.
*
* @see UCPTRIE_VALUE_BITS_16
- * @draft ICU 63
+ * @stable ICU 63
*/
#define UCPTRIE_16(trie, i) ((trie)->data.ptr16[i])
@@ -351,7 +330,7 @@
* Do not use this macro in any other way.
*
* @see UCPTRIE_VALUE_BITS_32
- * @draft ICU 63
+ * @stable ICU 63
*/
#define UCPTRIE_32(trie, i) ((trie)->data.ptr32[i])
@@ -361,7 +340,7 @@
* Do not use this macro in any other way.
*
* @see UCPTRIE_VALUE_BITS_8
- * @draft ICU 63
+ * @stable ICU 63
*/
#define UCPTRIE_8(trie, i) ((trie)->data.ptr8[i])
@@ -373,7 +352,7 @@
* @param dataAccess UCPTRIE_16, UCPTRIE_32, or UCPTRIE_8 according to the trie’s value width
* @param c (UChar32, in) the input code point
* @return The code point's trie value.
- * @draft ICU 63
+ * @stable ICU 63
*/
#define UCPTRIE_FAST_GET(trie, dataAccess, c) dataAccess(trie, _UCPTRIE_CP_INDEX(trie, 0xffff, c))
@@ -385,7 +364,7 @@
* @param dataAccess UCPTRIE_16, UCPTRIE_32, or UCPTRIE_8 according to the trie’s value width
* @param c (UChar32, in) the input code point
* @return The code point's trie value.
- * @draft ICU 63
+ * @stable ICU 63
*/
#define UCPTRIE_SMALL_GET(trie, dataAccess, c) \
dataAccess(trie, _UCPTRIE_CP_INDEX(trie, UCPTRIE_SMALL_MAX, c))
@@ -401,9 +380,9 @@
* @param limit (const UChar *, in) the limit pointer for the text, or NULL if NUL-terminated
* @param c (UChar32, out) variable for the code point
* @param result (out) variable for the trie lookup result
- * @draft ICU 63
+ * @stable ICU 63
*/
-#define UCPTRIE_FAST_U16_NEXT(trie, dataAccess, src, limit, c, result) { \
+#define UCPTRIE_FAST_U16_NEXT(trie, dataAccess, src, limit, c, result) UPRV_BLOCK_MACRO_BEGIN { \
(c) = *(src)++; \
int32_t __index; \
if (!U16_IS_SURROGATE(c)) { \
@@ -419,7 +398,7 @@
} \
} \
(result) = dataAccess(trie, __index); \
-}
+} UPRV_BLOCK_MACRO_END
/**
* UTF-16: Reads the previous code point (UChar32 c, out), pre-decrements src,
@@ -432,9 +411,9 @@
* @param src (const UChar *, in/out) the source text pointer
* @param c (UChar32, out) variable for the code point
* @param result (out) variable for the trie lookup result
- * @draft ICU 63
+ * @stable ICU 63
*/
-#define UCPTRIE_FAST_U16_PREV(trie, dataAccess, start, src, c, result) { \
+#define UCPTRIE_FAST_U16_PREV(trie, dataAccess, start, src, c, result) UPRV_BLOCK_MACRO_BEGIN { \
(c) = *--(src); \
int32_t __index; \
if (!U16_IS_SURROGATE(c)) { \
@@ -450,7 +429,7 @@
} \
} \
(result) = dataAccess(trie, __index); \
-}
+} UPRV_BLOCK_MACRO_END
/**
* UTF-8: Post-increments src and gets a value from the trie.
@@ -466,9 +445,9 @@
* @param src (const char *, in/out) the source text pointer
* @param limit (const char *, in) the limit pointer for the text (must not be NULL)
* @param result (out) variable for the trie lookup result
- * @draft ICU 63
+ * @stable ICU 63
*/
-#define UCPTRIE_FAST_U8_NEXT(trie, dataAccess, src, limit, result) { \
+#define UCPTRIE_FAST_U8_NEXT(trie, dataAccess, src, limit, result) UPRV_BLOCK_MACRO_BEGIN { \
int32_t __lead = (uint8_t)*(src)++; \
if (!U8_IS_SINGLE(__lead)) { \
uint8_t __t1, __t2, __t3; \
@@ -496,7 +475,7 @@
} \
} \
(result) = dataAccess(trie, __lead); \
-}
+} UPRV_BLOCK_MACRO_END
/**
* UTF-8: Pre-decrements src and gets a value from the trie.
@@ -512,9 +491,9 @@
* @param start (const char *, in) the start pointer for the text
* @param src (const char *, in/out) the source text pointer
* @param result (out) variable for the trie lookup result
- * @draft ICU 63
+ * @stable ICU 63
*/
-#define UCPTRIE_FAST_U8_PREV(trie, dataAccess, start, src, result) { \
+#define UCPTRIE_FAST_U8_PREV(trie, dataAccess, start, src, result) UPRV_BLOCK_MACRO_BEGIN { \
int32_t __index = (uint8_t)*--(src); \
if (!U8_IS_SINGLE(__index)) { \
__index = ucptrie_internalU8PrevIndex((trie), __index, (const uint8_t *)(start), \
@@ -523,7 +502,7 @@
__index >>= 3; \
} \
(result) = dataAccess(trie, __index); \
-}
+} UPRV_BLOCK_MACRO_END
/**
* Returns a trie value for an ASCII code point, without range checking.
@@ -532,7 +511,7 @@
* @param dataAccess UCPTRIE_16, UCPTRIE_32, or UCPTRIE_8 according to the trie’s value width
* @param c (UChar32, in) the input code point; must be U+0000..U+007F
* @return The ASCII code point's trie value.
- * @draft ICU 63
+ * @stable ICU 63
*/
#define UCPTRIE_ASCII_GET(trie, dataAccess, c) dataAccess(trie, c)
@@ -545,7 +524,7 @@
* @param dataAccess UCPTRIE_16, UCPTRIE_32, or UCPTRIE_8 according to the trie’s value width
* @param c (UChar32, in) the input code point, must be U+0000..U+FFFF
* @return The BMP code point's trie value.
- * @draft ICU 63
+ * @stable ICU 63
*/
#define UCPTRIE_FAST_BMP_GET(trie, dataAccess, c) dataAccess(trie, _UCPTRIE_FAST_INDEX(trie, c))
@@ -557,7 +536,7 @@
* @param dataAccess UCPTRIE_16, UCPTRIE_32, or UCPTRIE_8 according to the trie’s value width
* @param c (UChar32, in) the input code point, must be U+10000..U+10FFFF
* @return The supplementary code point's trie value.
- * @draft ICU 63
+ * @stable ICU 63
*/
#define UCPTRIE_FAST_SUPP_GET(trie, dataAccess, c) dataAccess(trie, _UCPTRIE_SMALL_INDEX(trie, c))
@@ -642,5 +621,24 @@
U_CDECL_END
#endif // U_IN_DOXYGEN
-#endif // U_HIDE_DRAFT_API
+
+#if U_SHOW_CPLUSPLUS_API
+
+U_NAMESPACE_BEGIN
+
+/**
+ * \class LocalUCPTriePointer
+ * "Smart pointer" class, closes a UCPTrie via ucptrie_close().
+ * For most methods see the LocalPointerBase base class.
+ *
+ * @see LocalPointerBase
+ * @see LocalPointer
+ * @stable ICU 63
+ */
+U_DEFINE_LOCAL_OPEN_POINTER(LocalUCPTriePointer, UCPTrie, ucptrie_close);
+
+U_NAMESPACE_END
+
+#endif // U_SHOW_CPLUSPLUS_API
+
#endif
diff -Nru icu-64.2/source/common/unicode/ucurr.h icu-65.1/source/common/unicode/ucurr.h
--- icu-64.2/source/common/unicode/ucurr.h 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/unicode/ucurr.h 2019-10-03 11:16:41.000000000 +0000
@@ -159,14 +159,14 @@
* @param currency null-terminated 3-letter ISO 4217 code
* @param locale locale in which to display currency
* @param nameStyle selector for which kind of name to return
- * @param isChoiceFormat fill-in set to TRUE if the returned value
- * is a ChoiceFormat pattern; otherwise it is a static string
+ * @param isChoiceFormat always set to FALSE, or can be NULL;
+ * display names are static strings;
+ * since ICU 4.4, ChoiceFormat patterns are no longer supported
* @param len fill-in parameter to receive length of result
* @param ec error code
* @return pointer to display string of 'len' UChars. If the resource
* data contains no entry for 'currency', then 'currency' itself is
- * returned. If *isChoiceFormat is TRUE, then the result is a
- * ChoiceFormat pattern. Otherwise it is a static string.
+ * returned.
* @stable ICU 2.6
*/
U_STABLE const UChar* U_EXPORT2
@@ -183,14 +183,15 @@
* currency object in the en_US locale is "US dollar" or "US dollars".
* @param currency null-terminated 3-letter ISO 4217 code
* @param locale locale in which to display currency
- * @param isChoiceFormat fill-in set to TRUE if the returned value
- * is a ChoiceFormat pattern; otherwise it is a static string
+ * @param isChoiceFormat always set to FALSE, or can be NULL;
+ * display names are static strings;
+ * since ICU 4.4, ChoiceFormat patterns are no longer supported
* @param pluralCount plural count
* @param len fill-in parameter to receive length of result
* @param ec error code
* @return pointer to display string of 'len' UChars. If the resource
* data contains no entry for 'currency', then 'currency' itself is
- * returned.
+ * returned.
* @stable ICU 4.2
*/
U_STABLE const UChar* U_EXPORT2
@@ -320,7 +321,7 @@
* Provides a UEnumeration object for listing ISO-4217 codes.
* @param currType You can use one of several UCurrCurrencyType values for this
* variable. You can also | (or) them together to get a specific list of
- * currencies. Most people will want to use the (UCURR_CURRENCY|UCURR_NON_DEPRECATED) value to
+ * currencies. Most people will want to use the (UCURR_COMMON|UCURR_NON_DEPRECATED) value to
* get a list of current currencies.
* @param pErrorCode Error code
* @stable ICU 3.2
diff -Nru icu-64.2/source/common/unicode/udata.h icu-65.1/source/common/unicode/udata.h
--- icu-64.2/source/common/unicode/udata.h 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/unicode/udata.h 2019-10-03 11:16:41.000000000 +0000
@@ -264,25 +264,6 @@
U_STABLE void U_EXPORT2
udata_close(UDataMemory *pData);
-#if U_SHOW_CPLUSPLUS_API
-
-U_NAMESPACE_BEGIN
-
-/**
- * \class LocalUDataMemoryPointer
- * "Smart pointer" class, closes a UDataMemory via udata_close().
- * For most methods see the LocalPointerBase base class.
- *
- * @see LocalPointerBase
- * @see LocalPointer
- * @stable ICU 4.4
- */
-U_DEFINE_LOCAL_OPEN_POINTER(LocalUDataMemoryPointer, UDataMemory, udata_close);
-
-U_NAMESPACE_END
-
-#endif
-
/**
* Get the pointer to the actual data inside the data memory.
* The data is read-only.
@@ -434,4 +415,23 @@
U_CDECL_END
+#if U_SHOW_CPLUSPLUS_API
+
+U_NAMESPACE_BEGIN
+
+/**
+ * \class LocalUDataMemoryPointer
+ * "Smart pointer" class, closes a UDataMemory via udata_close().
+ * For most methods see the LocalPointerBase base class.
+ *
+ * @see LocalPointerBase
+ * @see LocalPointer
+ * @stable ICU 4.4
+ */
+U_DEFINE_LOCAL_OPEN_POINTER(LocalUDataMemoryPointer, UDataMemory, udata_close);
+
+U_NAMESPACE_END
+
+#endif // U_SHOW_CPLUSPLUS_API
+
#endif
diff -Nru icu-64.2/source/common/unicode/uloc.h icu-65.1/source/common/unicode/uloc.h
--- icu-64.2/source/common/unicode/uloc.h 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/unicode/uloc.h 2019-10-03 11:16:41.000000000 +0000
@@ -742,12 +742,18 @@
/**
- * Gets the specified locale from a list of all available locales.
- * The return value is a pointer to an item of
- * a locale name array. Both this array and the pointers
- * it contains are owned by ICU and should not be deleted or written through
- * by the caller. The locale name is terminated by a null pointer.
- * @param n the specific locale name index of the available locale list
+ * Gets the specified locale from a list of available locales.
+ *
+ * This method corresponds to uloc_openAvailableByType called with the
+ * ULOC_AVAILABLE_DEFAULT type argument.
+ *
+ * The return value is a pointer to an item of a locale name array. Both this
+ * array and the pointers it contains are owned by ICU and should not be
+ * deleted or written through by the caller. The locale name is terminated by
+ * a null pointer.
+ *
+ * @param n the specific locale name index of the available locale list;
+ * should not exceed the number returned by uloc_countAvailable.
* @return a specified locale name of all available locales
* @stable ICU 2.0
*/
@@ -762,6 +768,72 @@
*/
U_STABLE int32_t U_EXPORT2 uloc_countAvailable(void);
+#ifndef U_HIDE_DRAFT_API
+
+/**
+ * Types for uloc_getAvailableByType and uloc_countAvailableByType.
+ *
+ * @draft ICU 65
+ */
+typedef enum ULocAvailableType {
+ /**
+ * Locales that return data when passed to ICU APIs,
+ * but not including legacy or alias locales.
+ *
+ * @draft ICU 65
+ */
+ ULOC_AVAILABLE_DEFAULT,
+
+ /**
+ * Legacy or alias locales that return data when passed to ICU APIs.
+ * Examples of supported legacy or alias locales:
+ *
+ * - iw (alias to he)
+ * - mo (alias to ro)
+ * - zh_CN (alias to zh_Hans_CN)
+ * - sr_BA (alias to sr_Cyrl_BA)
+ * - ars (alias to ar_SA)
+ *
+ * The locales in this set are disjoint from the ones in
+ * ULOC_AVAILABLE_DEFAULT. To get both sets at the same time, use
+ * ULOC_AVAILABLE_WITH_LEGACY_ALIASES.
+ *
+ * @draft ICU 65
+ */
+ ULOC_AVAILABLE_ONLY_LEGACY_ALIASES,
+
+ /**
+ * The union of the locales in ULOC_AVAILABLE_DEFAULT and
+ * ULOC_AVAILABLE_ONLY_LEGACY_ALIAS.
+ *
+ * @draft ICU 65
+ */
+ ULOC_AVAILABLE_WITH_LEGACY_ALIASES,
+
+#ifndef U_HIDE_INTERNAL_API
+ /**
+ * @internal
+ */
+ ULOC_AVAILABLE_COUNT
+#endif
+} ULocAvailableType;
+
+/**
+ * Gets a list of available locales according to the type argument, allowing
+ * the user to access different sets of supported locales in ICU.
+ *
+ * The returned UEnumeration must be closed by the caller.
+ *
+ * @param type Type choice from ULocAvailableType.
+ * @param status Set if an error occurred.
+ * @return a UEnumeration owned by the caller, or nullptr on failure.
+ * @draft ICU 65
+ */
+U_DRAFT UEnumeration* U_EXPORT2
+uloc_openAvailableByType(ULocAvailableType type, UErrorCode* status);
+
+#endif // U_HIDE_DRAFT_API
+
/**
*
* Gets a list of all available 2-letter language codes defined in ISO 639,
diff -Nru icu-64.2/source/common/unicode/umachine.h icu-65.1/source/common/unicode/umachine.h
--- icu-64.2/source/common/unicode/umachine.h 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/unicode/umachine.h 2019-10-03 11:16:41.000000000 +0000
@@ -140,6 +140,42 @@
#define U_FINAL final
#endif
+// Before ICU 65, function-like, multi-statement ICU macros were just defined as
+// series of statements wrapped in { } blocks and the caller could choose to
+// either treat them as if they were actual functions and end the invocation
+// with a trailing ; creating an empty statement after the block or else omit
+// this trailing ; using the knowledge that the macro would expand to { }.
+//
+// But doing so doesn't work well with macros that look like functions and
+// compiler warnings about empty statements (ICU-20601) and ICU 65 therefore
+// switches to the standard solution of wrapping such macros in do { } while.
+//
+// This will however break existing code that depends on being able to invoke
+// these macros without a trailing ; so to be able to remain compatible with
+// such code the wrapper is itself defined as macros so that it's possible to
+// build ICU 65 and later with the old macro behaviour, like this:
+//
+// export CPPFLAGS='-DUPRV_BLOCK_MACRO_BEGIN="" -DUPRV_BLOCK_MACRO_END=""'
+// runConfigureICU ...
+//
+
+/**
+ * \def UPRV_BLOCK_MACRO_BEGIN
+ * Defined as the "do" keyword by default.
+ * @internal
+ */
+#ifndef UPRV_BLOCK_MACRO_BEGIN
+#define UPRV_BLOCK_MACRO_BEGIN do
+#endif
+
+/**
+ * \def UPRV_BLOCK_MACRO_END
+ * Defined as "while (FALSE)" by default.
+ * @internal
+ */
+#ifndef UPRV_BLOCK_MACRO_END
+#define UPRV_BLOCK_MACRO_END while (FALSE)
+#endif
/*==========================================================================*/
/* limits for int32_t etc., like in POSIX inttypes.h */
diff -Nru icu-64.2/source/common/unicode/umutablecptrie.h icu-65.1/source/common/unicode/umutablecptrie.h
--- icu-64.2/source/common/unicode/umutablecptrie.h 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/unicode/umutablecptrie.h 2019-10-03 11:16:41.000000000 +0000
@@ -9,8 +9,6 @@
#include "unicode/utypes.h"
-#ifndef U_HIDE_DRAFT_API
-
#include "unicode/localpointer.h"
#include "unicode/ucpmap.h"
#include "unicode/ucptrie.h"
@@ -44,7 +42,7 @@
*
* @see UCPTrie
* @see umutablecptrie_buildImmutable
- * @draft ICU 63
+ * @stable ICU 63
*/
typedef struct UMutableCPTrie UMutableCPTrie;
@@ -59,7 +57,7 @@
* @param errorValue the value for out-of-range code points and ill-formed UTF-8/16
* @param pErrorCode an in/out ICU UErrorCode
* @return the trie
- * @draft ICU 63
+ * @stable ICU 63
*/
U_CAPI UMutableCPTrie * U_EXPORT2
umutablecptrie_open(uint32_t initialValue, uint32_t errorValue, UErrorCode *pErrorCode);
@@ -71,7 +69,7 @@
* @param other the trie to clone
* @param pErrorCode an in/out ICU UErrorCode
* @return the trie clone
- * @draft ICU 63
+ * @stable ICU 63
*/
U_CAPI UMutableCPTrie * U_EXPORT2
umutablecptrie_clone(const UMutableCPTrie *other, UErrorCode *pErrorCode);
@@ -80,7 +78,7 @@
* Closes a mutable trie and releases associated memory.
*
* @param trie the trie
- * @draft ICU 63
+ * @stable ICU 63
*/
U_CAPI void U_EXPORT2
umutablecptrie_close(UMutableCPTrie *trie);
@@ -96,7 +94,7 @@
*
* @see LocalPointerBase
* @see LocalPointer
- * @draft ICU 63
+ * @stable ICU 63
*/
U_DEFINE_LOCAL_OPEN_POINTER(LocalUMutableCPTriePointer, UMutableCPTrie, umutablecptrie_close);
@@ -111,7 +109,7 @@
* @param map the source map
* @param pErrorCode an in/out ICU UErrorCode
* @return the mutable trie
- * @draft ICU 63
+ * @stable ICU 63
*/
U_CAPI UMutableCPTrie * U_EXPORT2
umutablecptrie_fromUCPMap(const UCPMap *map, UErrorCode *pErrorCode);
@@ -123,7 +121,7 @@
* @param trie the immutable trie
* @param pErrorCode an in/out ICU UErrorCode
* @return the mutable trie
- * @draft ICU 63
+ * @stable ICU 63
*/
U_CAPI UMutableCPTrie * U_EXPORT2
umutablecptrie_fromUCPTrie(const UCPTrie *trie, UErrorCode *pErrorCode);
@@ -134,7 +132,7 @@
* @param trie the trie
* @param c the code point
* @return the value
- * @draft ICU 63
+ * @stable ICU 63
*/
U_CAPI uint32_t U_EXPORT2
umutablecptrie_get(const UMutableCPTrie *trie, UChar32 c);
@@ -166,7 +164,7 @@
* may have been modified by filter(context, trie value)
* if that function pointer is not NULL
* @return the range end code point, or -1 if start is not a valid code point
- * @draft ICU 63
+ * @stable ICU 63
*/
U_CAPI UChar32 U_EXPORT2
umutablecptrie_getRange(const UMutableCPTrie *trie, UChar32 start,
@@ -180,7 +178,7 @@
* @param c the code point
* @param value the value
* @param pErrorCode an in/out ICU UErrorCode
- * @draft ICU 63
+ * @stable ICU 63
*/
U_CAPI void U_EXPORT2
umutablecptrie_set(UMutableCPTrie *trie, UChar32 c, uint32_t value, UErrorCode *pErrorCode);
@@ -194,7 +192,7 @@
* @param end the last code point to get the value (inclusive)
* @param value the value
* @param pErrorCode an in/out ICU UErrorCode
- * @draft ICU 63
+ * @stable ICU 63
*/
U_CAPI void U_EXPORT2
umutablecptrie_setRange(UMutableCPTrie *trie,
@@ -229,7 +227,7 @@
* @param pErrorCode an in/out ICU UErrorCode
*
* @see umutablecptrie_fromUCPTrie
- * @draft ICU 63
+ * @stable ICU 63
*/
U_CAPI UCPTrie * U_EXPORT2
umutablecptrie_buildImmutable(UMutableCPTrie *trie, UCPTrieType type, UCPTrieValueWidth valueWidth,
@@ -237,5 +235,4 @@
U_CDECL_END
-#endif // U_HIDE_DRAFT_API
#endif
diff -Nru icu-64.2/source/common/unicode/unifilt.h icu-65.1/source/common/unicode/unifilt.h
--- icu-64.2/source/common/unicode/unifilt.h 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/unicode/unifilt.h 2019-10-03 11:16:41.000000000 +0000
@@ -12,6 +12,10 @@
#ifndef UNIFILT_H
#define UNIFILT_H
+#include "unicode/utypes.h"
+
+#if U_SHOW_CPLUSPLUS_API
+
#include "unicode/unifunct.h"
#include "unicode/unimatch.h"
@@ -68,6 +72,14 @@
virtual ~UnicodeFilter();
/**
+ * Clones this object polymorphically.
+ * The caller owns the result and should delete it when done.
+ * @return clone, or nullptr if an error occurred
+ * @stable ICU 2.4
+ */
+ virtual UnicodeFilter* clone() const = 0;
+
+ /**
* Returns true for characters that are in the selected
* subset. In other words, if a character is to be
* filtered , then contains() returns
@@ -119,4 +131,6 @@
U_NAMESPACE_END
+#endif /* U_SHOW_CPLUSPLUS_API */
+
#endif
diff -Nru icu-64.2/source/common/unicode/unifunct.h icu-65.1/source/common/unicode/unifunct.h
--- icu-64.2/source/common/unicode/unifunct.h 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/unicode/unifunct.h 2019-10-03 11:16:41.000000000 +0000
@@ -13,6 +13,9 @@
#define UNIFUNCT_H
#include "unicode/utypes.h"
+
+#if U_SHOW_CPLUSPLUS_API
+
#include "unicode/uobject.h"
/**
@@ -124,4 +127,6 @@
U_NAMESPACE_END
+#endif /* U_SHOW_CPLUSPLUS_API */
+
#endif
diff -Nru icu-64.2/source/common/unicode/unimatch.h icu-65.1/source/common/unicode/unimatch.h
--- icu-64.2/source/common/unicode/unimatch.h 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/unicode/unimatch.h 2019-10-03 11:16:41.000000000 +0000
@@ -17,6 +17,7 @@
* \brief C++ API: Unicode Matcher
*/
+#if U_SHOW_CPLUSPLUS_API
U_NAMESPACE_BEGIN
@@ -162,4 +163,6 @@
U_NAMESPACE_END
+#endif /* U_SHOW_CPLUSPLUS_API */
+
#endif
diff -Nru icu-64.2/source/common/unicode/uniset.h icu-65.1/source/common/unicode/uniset.h
--- icu-64.2/source/common/unicode/uniset.h 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/unicode/uniset.h 2019-10-03 11:16:41.000000000 +0000
@@ -13,6 +13,10 @@
#ifndef UNICODESET_H
#define UNICODESET_H
+#include "unicode/utypes.h"
+
+#if U_SHOW_CPLUSPLUS_API
+
#include "unicode/ucpmap.h"
#include "unicode/unifilt.h"
#include "unicode/unistr.h"
@@ -501,7 +505,7 @@
* @see cloneAsThawed
* @stable ICU 2.0
*/
- virtual UnicodeFunctor* clone() const;
+ virtual UnicodeSet* clone() const;
/**
* Returns the hash code value for this set.
@@ -579,7 +583,7 @@
* @see cloneAsThawed
* @stable ICU 3.8
*/
- UnicodeFunctor *freeze();
+ UnicodeSet *freeze();
/**
* Clone the set and make the clone mutable.
@@ -589,7 +593,7 @@
* @see isFrozen
* @stable ICU 3.8
*/
- UnicodeFunctor *cloneAsThawed() const;
+ UnicodeSet *cloneAsThawed() const;
//----------------------------------------------------------------
// Public API
@@ -1651,11 +1655,10 @@
const UnicodeSet* inclusions,
UErrorCode &status);
-#ifndef U_HIDE_DRAFT_API // Skipped: ucpmap.h is draft only.
+ // UCPMap is now stable ICU 63
void applyIntPropertyValue(const UCPMap *map,
UCPMapValueFilter *filter, const void *context,
UErrorCode &errorCode);
-#endif /* U_HIDE_DRAFT_API */
/**
* Set the new pattern to cache.
@@ -1736,4 +1739,6 @@
U_NAMESPACE_END
+#endif /* U_SHOW_CPLUSPLUS_API */
+
#endif
diff -Nru icu-64.2/source/common/unicode/unistr.h icu-65.1/source/common/unicode/unistr.h
--- icu-64.2/source/common/unicode/unistr.h 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/unicode/unistr.h 2019-10-03 11:16:41.000000000 +0000
@@ -28,8 +28,11 @@
* \brief C++ API: Unicode String
*/
-#include
#include "unicode/utypes.h"
+
+#if U_SHOW_CPLUSPLUS_API
+
+#include
#include "unicode/char16ptr.h"
#include "unicode/rep.h"
#include "unicode/std_string.h"
@@ -209,7 +212,9 @@
* similar functionality as the Java String and StringBuffer/StringBuilder classes.
* It is a concrete implementation of the abstract class Replaceable (for transliteration).
*
- * A UnicodeString may also "alias" an external array of characters
+ * The UnicodeString equivalent of std::string’s clear() is remove().
+ *
+ * A UnicodeString may "alias" an external array of characters
* (that is, point to it, rather than own the array)
* whose lifetime must then at least match the lifetime of the aliasing object.
* This aliasing may be preserved when returning a UnicodeString by value,
@@ -2092,8 +2097,7 @@
* s.truncate(0); // set to an empty string (complete truncation), or
* s=UnicodeString(); // assign an empty string, or
* s.setTo((UChar32)-1); // set to a pseudo code point that is out of range, or
- * static const char16_t nul=0;
- * s.setTo(&nul, 0); // set to an empty C Unicode string
+ * s.setTo(u"", 0); // set to an empty C Unicode string
* }
* \endcode
*
@@ -2534,11 +2538,14 @@
/* Remove operations */
/**
- * Remove all characters from the UnicodeString object.
+ * Removes all characters from the UnicodeString object and clears the bogus flag.
+ * This is the UnicodeString equivalent of std::string’s clear().
+ *
* @return a reference to this
+ * @see setToBogus
* @stable ICU 2.0
*/
- inline UnicodeString& remove(void);
+ inline UnicodeString& remove();
/**
* Remove the characters in the range
@@ -3034,11 +3041,11 @@
* uint16_t * constructor.
* Delegates to UnicodeString(const char16_t *, int32_t).
* @param text UTF-16 string
- * @param length string length
+ * @param textLength string length
* @stable ICU 59
*/
- UnicodeString(const uint16_t *text, int32_t length) :
- UnicodeString(ConstChar16Ptr(text), length) {}
+ UnicodeString(const uint16_t *text, int32_t textLength) :
+ UnicodeString(ConstChar16Ptr(text), textLength) {}
#endif
#if U_SIZEOF_WCHAR_T==2 || defined(U_IN_DOXYGEN)
@@ -3047,21 +3054,21 @@
* (Only defined if U_SIZEOF_WCHAR_T==2.)
* Delegates to UnicodeString(const char16_t *, int32_t).
* @param text NUL-terminated UTF-16 string
- * @param length string length
+ * @param textLength string length
* @stable ICU 59
*/
- UnicodeString(const wchar_t *text, int32_t length) :
- UnicodeString(ConstChar16Ptr(text), length) {}
+ UnicodeString(const wchar_t *text, int32_t textLength) :
+ UnicodeString(ConstChar16Ptr(text), textLength) {}
#endif
/**
* nullptr_t constructor.
* Effectively the same as the default constructor, makes an empty string object.
* @param text nullptr
- * @param length ignored
+ * @param textLength ignored
* @stable ICU 59
*/
- inline UnicodeString(const std::nullptr_t text, int32_t length);
+ inline UnicodeString(const std::nullptr_t text, int32_t textLength);
/**
* Readonly-aliasing char16_t* constructor.
@@ -3266,13 +3273,13 @@
* }
* \endcode
* @param src String using only invariant characters.
- * @param length Length of src, or -1 if NUL-terminated.
+ * @param textLength Length of src, or -1 if NUL-terminated.
* @param inv Signature-distinguishing paramater, use US_INV.
*
* @see US_INV
* @stable ICU 3.2
*/
- UnicodeString(const char *src, int32_t length, enum EInvariant inv);
+ UnicodeString(const char *src, int32_t textLength, enum EInvariant inv);
/**
@@ -3323,9 +3330,6 @@
* Clones can be used concurrently in multiple threads.
* If a subclass does not implement clone(), or if an error occurs,
* then NULL is returned.
- * The clone functions in all subclasses return a pointer to a Replaceable
- * because some compilers do not support covariant (same-as-this)
- * return types; cast to the appropriate subclass if necessary.
* The caller must delete the clone.
*
* @return a clone of this object
@@ -3334,7 +3338,7 @@
* @see getDynamicClassID
* @stable ICU 2.6
*/
- virtual Replaceable *clone() const;
+ virtual UnicodeString *clone() const;
/** Destructor.
* @stable ICU 2.0
@@ -4748,4 +4752,6 @@
U_NAMESPACE_END
+#endif /* U_SHOW_CPLUSPLUS_API */
+
#endif
diff -Nru icu-64.2/source/common/unicode/unorm.h icu-65.1/source/common/unicode/unorm.h
--- icu-64.2/source/common/unicode/unorm.h 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/unicode/unorm.h 2019-10-03 11:16:41.000000000 +0000
@@ -131,6 +131,8 @@
// Do not conditionalize the following enum with #ifndef U_HIDE_DEPRECATED_API,
// it is needed for layout of Normalizer object.
+#ifndef U_FORCE_HIDE_DEPRECATED_API
+
/**
* Constants for normalization modes.
* @deprecated ICU 56 Use unorm2.h instead.
@@ -155,6 +157,8 @@
UNORM_MODE_COUNT
} UNormalizationMode;
+#endif // U_FORCE_HIDE_DEPRECATED_API
+
#ifndef U_HIDE_DEPRECATED_API
/**
diff -Nru icu-64.2/source/common/unicode/uobject.h icu-65.1/source/common/unicode/uobject.h
--- icu-64.2/source/common/unicode/uobject.h 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/unicode/uobject.h 2019-10-03 11:16:41.000000000 +0000
@@ -20,6 +20,9 @@
#define __UOBJECT_H__
#include "unicode/utypes.h"
+
+#if U_SHOW_CPLUSPLUS_API
+
#include "unicode/platform.h"
/**
@@ -43,7 +46,7 @@
* @stable ICU 4.2. Since ICU 64, Use U_NOEXCEPT instead. See ICU-20422.
*/
#ifndef U_NO_THROW
-#define U_NO_THROW throw()
+#define U_NO_THROW U_NOEXCEPT
#endif
/*===========================================================================*/
@@ -212,11 +215,8 @@
* The clone() function is not available in UObject because it is not
* implemented by all ICU classes.
* Many ICU services provide a clone() function for their class trees,
- * defined on the service's C++ base class, and all subclasses within that
- * service class tree return a pointer to the service base class
+ * defined on the service's C++ base class
* (which itself is a subclass of UObject).
- * This is because some compilers do not support covariant (same-as-this)
- * return types; cast to the appropriate subclass if necessary.
*
* @stable ICU 2.2
*/
@@ -319,4 +319,6 @@
U_NAMESPACE_END
+#endif /* U_SHOW_CPLUSPLUS_API */
+
#endif
diff -Nru icu-64.2/source/common/unicode/urename.h icu-65.1/source/common/unicode/urename.h
--- icu-64.2/source/common/unicode/urename.h 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/unicode/urename.h 2019-10-03 11:16:41.000000000 +0000
@@ -193,10 +193,13 @@
#define res_getAlias U_ICU_ENTRY_POINT_RENAME(res_getAlias)
#define res_getArrayItem U_ICU_ENTRY_POINT_RENAME(res_getArrayItem)
#define res_getBinary U_ICU_ENTRY_POINT_RENAME(res_getBinary)
+#define res_getBinaryNoTrace U_ICU_ENTRY_POINT_RENAME(res_getBinaryNoTrace)
#define res_getIntVector U_ICU_ENTRY_POINT_RENAME(res_getIntVector)
+#define res_getIntVectorNoTrace U_ICU_ENTRY_POINT_RENAME(res_getIntVectorNoTrace)
#define res_getPublicType U_ICU_ENTRY_POINT_RENAME(res_getPublicType)
#define res_getResource U_ICU_ENTRY_POINT_RENAME(res_getResource)
#define res_getString U_ICU_ENTRY_POINT_RENAME(res_getString)
+#define res_getStringNoTrace U_ICU_ENTRY_POINT_RENAME(res_getStringNoTrace)
#define res_getTableItemByIndex U_ICU_ENTRY_POINT_RENAME(res_getTableItemByIndex)
#define res_getTableItemByKey U_ICU_ENTRY_POINT_RENAME(res_getTableItemByKey)
#define res_load U_ICU_ENTRY_POINT_RENAME(res_load)
@@ -523,6 +526,7 @@
#define ucal_getDefaultTimeZone U_ICU_ENTRY_POINT_RENAME(ucal_getDefaultTimeZone)
#define ucal_getFieldDifference U_ICU_ENTRY_POINT_RENAME(ucal_getFieldDifference)
#define ucal_getGregorianChange U_ICU_ENTRY_POINT_RENAME(ucal_getGregorianChange)
+#define ucal_getHostTimeZone U_ICU_ENTRY_POINT_RENAME(ucal_getHostTimeZone)
#define ucal_getKeywordValuesForLocale U_ICU_ENTRY_POINT_RENAME(ucal_getKeywordValuesForLocale)
#define ucal_getLimit U_ICU_ENTRY_POINT_RENAME(ucal_getLimit)
#define ucal_getLocaleByType U_ICU_ENTRY_POINT_RENAME(ucal_getLocaleByType)
@@ -575,7 +579,6 @@
#define ucasemap_getLocale U_ICU_ENTRY_POINT_RENAME(ucasemap_getLocale)
#define ucasemap_getOptions U_ICU_ENTRY_POINT_RENAME(ucasemap_getOptions)
#define ucasemap_internalUTF8ToTitle U_ICU_ENTRY_POINT_RENAME(ucasemap_internalUTF8ToTitle)
-#define ucasemap_mapUTF8 U_ICU_ENTRY_POINT_RENAME(ucasemap_mapUTF8)
#define ucasemap_open U_ICU_ENTRY_POINT_RENAME(ucasemap_open)
#define ucasemap_setBreakIterator U_ICU_ENTRY_POINT_RENAME(ucasemap_setBreakIterator)
#define ucasemap_setLocale U_ICU_ENTRY_POINT_RENAME(ucasemap_setLocale)
@@ -930,16 +933,9 @@
#define ufieldpositer_close U_ICU_ENTRY_POINT_RENAME(ufieldpositer_close)
#define ufieldpositer_next U_ICU_ENTRY_POINT_RENAME(ufieldpositer_next)
#define ufieldpositer_open U_ICU_ENTRY_POINT_RENAME(ufieldpositer_open)
-#define ufile_close_translit U_ICU_ENTRY_POINT_RENAME(ufile_close_translit)
-#define ufile_fill_uchar_buffer U_ICU_ENTRY_POINT_RENAME(ufile_fill_uchar_buffer)
-#define ufile_flush_io U_ICU_ENTRY_POINT_RENAME(ufile_flush_io)
-#define ufile_flush_translit U_ICU_ENTRY_POINT_RENAME(ufile_flush_translit)
#define ufile_getch U_ICU_ENTRY_POINT_RENAME(ufile_getch)
#define ufile_getch32 U_ICU_ENTRY_POINT_RENAME(ufile_getch32)
-#define ufmt_64tou U_ICU_ENTRY_POINT_RENAME(ufmt_64tou)
#define ufmt_close U_ICU_ENTRY_POINT_RENAME(ufmt_close)
-#define ufmt_defaultCPToUnicode U_ICU_ENTRY_POINT_RENAME(ufmt_defaultCPToUnicode)
-#define ufmt_digitvalue U_ICU_ENTRY_POINT_RENAME(ufmt_digitvalue)
#define ufmt_getArrayItemByIndex U_ICU_ENTRY_POINT_RENAME(ufmt_getArrayItemByIndex)
#define ufmt_getArrayLength U_ICU_ENTRY_POINT_RENAME(ufmt_getArrayLength)
#define ufmt_getDate U_ICU_ENTRY_POINT_RENAME(ufmt_getDate)
@@ -951,11 +947,7 @@
#define ufmt_getType U_ICU_ENTRY_POINT_RENAME(ufmt_getType)
#define ufmt_getUChars U_ICU_ENTRY_POINT_RENAME(ufmt_getUChars)
#define ufmt_isNumeric U_ICU_ENTRY_POINT_RENAME(ufmt_isNumeric)
-#define ufmt_isdigit U_ICU_ENTRY_POINT_RENAME(ufmt_isdigit)
#define ufmt_open U_ICU_ENTRY_POINT_RENAME(ufmt_open)
-#define ufmt_ptou U_ICU_ENTRY_POINT_RENAME(ufmt_ptou)
-#define ufmt_uto64 U_ICU_ENTRY_POINT_RENAME(ufmt_uto64)
-#define ufmt_utop U_ICU_ENTRY_POINT_RENAME(ufmt_utop)
#define ufmtval_getString U_ICU_ENTRY_POINT_RENAME(ufmtval_getString)
#define ufmtval_nextPosition U_ICU_ENTRY_POINT_RENAME(ufmtval_nextPosition)
#define ugender_getInstance U_ICU_ENTRY_POINT_RENAME(ugender_getInstance)
@@ -1103,6 +1095,7 @@
#define uloc_getVariant U_ICU_ENTRY_POINT_RENAME(uloc_getVariant)
#define uloc_isRightToLeft U_ICU_ENTRY_POINT_RENAME(uloc_isRightToLeft)
#define uloc_minimizeSubtags U_ICU_ENTRY_POINT_RENAME(uloc_minimizeSubtags)
+#define uloc_openAvailableByType U_ICU_ENTRY_POINT_RENAME(uloc_openAvailableByType)
#define uloc_openKeywordList U_ICU_ENTRY_POINT_RENAME(uloc_openKeywordList)
#define uloc_openKeywords U_ICU_ENTRY_POINT_RENAME(uloc_openKeywords)
#define uloc_setDefault U_ICU_ENTRY_POINT_RENAME(uloc_setDefault)
@@ -1159,9 +1152,6 @@
#define umsg_toPattern U_ICU_ENTRY_POINT_RENAME(umsg_toPattern)
#define umsg_vformat U_ICU_ENTRY_POINT_RENAME(umsg_vformat)
#define umsg_vparse U_ICU_ENTRY_POINT_RENAME(umsg_vparse)
-#define umtx_condBroadcast U_ICU_ENTRY_POINT_RENAME(umtx_condBroadcast)
-#define umtx_condSignal U_ICU_ENTRY_POINT_RENAME(umtx_condSignal)
-#define umtx_condWait U_ICU_ENTRY_POINT_RENAME(umtx_condWait)
#define umtx_lock U_ICU_ENTRY_POINT_RENAME(umtx_lock)
#define umtx_unlock U_ICU_ENTRY_POINT_RENAME(umtx_unlock)
#define umutablecptrie_buildImmutable U_ICU_ENTRY_POINT_RENAME(umutablecptrie_buildImmutable)
@@ -1327,7 +1317,6 @@
#define uprv_decNumberAbs U_ICU_ENTRY_POINT_RENAME(uprv_decNumberAbs)
#define uprv_decNumberAdd U_ICU_ENTRY_POINT_RENAME(uprv_decNumberAdd)
#define uprv_decNumberAnd U_ICU_ENTRY_POINT_RENAME(uprv_decNumberAnd)
-#define uprv_decNumberClass U_ICU_ENTRY_POINT_RENAME(uprv_decNumberClass)
#define uprv_decNumberClassToString U_ICU_ENTRY_POINT_RENAME(uprv_decNumberClassToString)
#define uprv_decNumberCompare U_ICU_ENTRY_POINT_RENAME(uprv_decNumberCompare)
#define uprv_decNumberCompareSignal U_ICU_ENTRY_POINT_RENAME(uprv_decNumberCompareSignal)
@@ -1393,6 +1382,7 @@
#define uprv_dlsym_func U_ICU_ENTRY_POINT_RENAME(uprv_dlsym_func)
#define uprv_eastrncpy U_ICU_ENTRY_POINT_RENAME(uprv_eastrncpy)
#define uprv_ebcdicFromAscii U_ICU_ENTRY_POINT_RENAME(uprv_ebcdicFromAscii)
+#define uprv_ebcdicToAscii U_ICU_ENTRY_POINT_RENAME(uprv_ebcdicToAscii)
#define uprv_ebcdicToLowercaseAscii U_ICU_ENTRY_POINT_RENAME(uprv_ebcdicToLowercaseAscii)
#define uprv_ebcdictolower U_ICU_ENTRY_POINT_RENAME(uprv_ebcdictolower)
#define uprv_fabs U_ICU_ENTRY_POINT_RENAME(uprv_fabs)
@@ -1412,6 +1402,7 @@
#define uprv_getUTCtime U_ICU_ENTRY_POINT_RENAME(uprv_getUTCtime)
#define uprv_int32Comparator U_ICU_ENTRY_POINT_RENAME(uprv_int32Comparator)
#define uprv_isASCIILetter U_ICU_ENTRY_POINT_RENAME(uprv_isASCIILetter)
+#define uprv_isEbcdicAtSign U_ICU_ENTRY_POINT_RENAME(uprv_isEbcdicAtSign)
#define uprv_isInfinite U_ICU_ENTRY_POINT_RENAME(uprv_isInfinite)
#define uprv_isInvariantString U_ICU_ENTRY_POINT_RENAME(uprv_isInvariantString)
#define uprv_isInvariantUString U_ICU_ENTRY_POINT_RENAME(uprv_isInvariantUString)
@@ -1579,6 +1570,7 @@
#define ures_getUTF8String U_ICU_ENTRY_POINT_RENAME(ures_getUTF8String)
#define ures_getUTF8StringByIndex U_ICU_ENTRY_POINT_RENAME(ures_getUTF8StringByIndex)
#define ures_getUTF8StringByKey U_ICU_ENTRY_POINT_RENAME(ures_getUTF8StringByKey)
+#define ures_getValueWithFallback U_ICU_ENTRY_POINT_RENAME(ures_getValueWithFallback)
#define ures_getVersion U_ICU_ENTRY_POINT_RENAME(ures_getVersion)
#define ures_getVersionByKey U_ICU_ENTRY_POINT_RENAME(ures_getVersionByKey)
#define ures_getVersionNumber U_ICU_ENTRY_POINT_RENAME(ures_getVersionNumber)
diff -Nru icu-64.2/source/common/unicode/usetiter.h icu-65.1/source/common/unicode/usetiter.h
--- icu-64.2/source/common/unicode/usetiter.h 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/unicode/usetiter.h 2019-10-03 11:16:41.000000000 +0000
@@ -10,6 +10,9 @@
#define USETITER_H
#include "unicode/utypes.h"
+
+#if U_SHOW_CPLUSPLUS_API
+
#include "unicode/uobject.h"
#include "unicode/unistr.h"
@@ -317,4 +320,6 @@
U_NAMESPACE_END
+#endif /* U_SHOW_CPLUSPLUS_API */
+
#endif
diff -Nru icu-64.2/source/common/unicode/utext.h icu-65.1/source/common/unicode/utext.h
--- icu-64.2/source/common/unicode/utext.h 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/unicode/utext.h 2019-10-03 11:16:41.000000000 +0000
@@ -766,12 +766,14 @@
*
* @stable ICU 3.8
*/
-#define UTEXT_SETNATIVEINDEX(ut, ix) \
- { int64_t __offset = (ix) - (ut)->chunkNativeStart; \
- if (__offset>=0 && __offset<(int64_t)(ut)->nativeIndexingLimit && (ut)->chunkContents[__offset]<0xdc00) { \
- (ut)->chunkOffset=(int32_t)__offset; \
- } else { \
- utext_setNativeIndex((ut), (ix)); } }
+#define UTEXT_SETNATIVEINDEX(ut, ix) UPRV_BLOCK_MACRO_BEGIN { \
+ int64_t __offset = (ix) - (ut)->chunkNativeStart; \
+ if (__offset>=0 && __offset<(int64_t)(ut)->nativeIndexingLimit && (ut)->chunkContents[__offset]<0xdc00) { \
+ (ut)->chunkOffset=(int32_t)__offset; \
+ } else { \
+ utext_setNativeIndex((ut), (ix)); \
+ } \
+} UPRV_BLOCK_MACRO_END
diff -Nru icu-64.2/source/common/unicode/utf16.h icu-65.1/source/common/unicode/utf16.h
--- icu-64.2/source/common/unicode/utf16.h 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/unicode/utf16.h 2019-10-03 11:16:41.000000000 +0000
@@ -163,7 +163,7 @@
* @see U16_GET
* @stable ICU 2.4
*/
-#define U16_GET_UNSAFE(s, i, c) { \
+#define U16_GET_UNSAFE(s, i, c) UPRV_BLOCK_MACRO_BEGIN { \
(c)=(s)[i]; \
if(U16_IS_SURROGATE(c)) { \
if(U16_IS_SURROGATE_LEAD(c)) { \
@@ -172,7 +172,7 @@
(c)=U16_GET_SUPPLEMENTARY((s)[(i)-1], (c)); \
} \
} \
-}
+} UPRV_BLOCK_MACRO_END
/**
* Get a code point from a string at a random-access offset,
@@ -197,7 +197,7 @@
* @see U16_GET_UNSAFE
* @stable ICU 2.4
*/
-#define U16_GET(s, start, i, length, c) { \
+#define U16_GET(s, start, i, length, c) UPRV_BLOCK_MACRO_BEGIN { \
(c)=(s)[i]; \
if(U16_IS_SURROGATE(c)) { \
uint16_t __c2; \
@@ -211,7 +211,7 @@
} \
} \
} \
-}
+} UPRV_BLOCK_MACRO_END
/**
* Get a code point from a string at a random-access offset,
@@ -236,7 +236,7 @@
* @see U16_GET_UNSAFE
* @stable ICU 60
*/
-#define U16_GET_OR_FFFD(s, start, i, length, c) { \
+#define U16_GET_OR_FFFD(s, start, i, length, c) UPRV_BLOCK_MACRO_BEGIN { \
(c)=(s)[i]; \
if(U16_IS_SURROGATE(c)) { \
uint16_t __c2; \
@@ -254,7 +254,7 @@
} \
} \
} \
-}
+} UPRV_BLOCK_MACRO_END
/* definitions with forward iteration --------------------------------------- */
@@ -277,12 +277,12 @@
* @see U16_NEXT
* @stable ICU 2.4
*/
-#define U16_NEXT_UNSAFE(s, i, c) { \
+#define U16_NEXT_UNSAFE(s, i, c) UPRV_BLOCK_MACRO_BEGIN { \
(c)=(s)[(i)++]; \
if(U16_IS_LEAD(c)) { \
(c)=U16_GET_SUPPLEMENTARY((c), (s)[(i)++]); \
} \
-}
+} UPRV_BLOCK_MACRO_END
/**
* Get a code point from a string at a code point boundary offset,
@@ -305,7 +305,7 @@
* @see U16_NEXT_UNSAFE
* @stable ICU 2.4
*/
-#define U16_NEXT(s, i, length, c) { \
+#define U16_NEXT(s, i, length, c) UPRV_BLOCK_MACRO_BEGIN { \
(c)=(s)[(i)++]; \
if(U16_IS_LEAD(c)) { \
uint16_t __c2; \
@@ -314,7 +314,7 @@
(c)=U16_GET_SUPPLEMENTARY((c), __c2); \
} \
} \
-}
+} UPRV_BLOCK_MACRO_END
/**
* Get a code point from a string at a code point boundary offset,
@@ -337,7 +337,7 @@
* @see U16_NEXT_UNSAFE
* @stable ICU 60
*/
-#define U16_NEXT_OR_FFFD(s, i, length, c) { \
+#define U16_NEXT_OR_FFFD(s, i, length, c) UPRV_BLOCK_MACRO_BEGIN { \
(c)=(s)[(i)++]; \
if(U16_IS_SURROGATE(c)) { \
uint16_t __c2; \
@@ -348,7 +348,7 @@
(c)=0xfffd; \
} \
} \
-}
+} UPRV_BLOCK_MACRO_END
/**
* Append a code point to a string, overwriting 1 or 2 code units.
@@ -363,14 +363,14 @@
* @see U16_APPEND
* @stable ICU 2.4
*/
-#define U16_APPEND_UNSAFE(s, i, c) { \
+#define U16_APPEND_UNSAFE(s, i, c) UPRV_BLOCK_MACRO_BEGIN { \
if((uint32_t)(c)<=0xffff) { \
(s)[(i)++]=(uint16_t)(c); \
} else { \
(s)[(i)++]=(uint16_t)(((c)>>10)+0xd7c0); \
(s)[(i)++]=(uint16_t)(((c)&0x3ff)|0xdc00); \
} \
-}
+} UPRV_BLOCK_MACRO_END
/**
* Append a code point to a string, overwriting 1 or 2 code units.
@@ -389,7 +389,7 @@
* @see U16_APPEND_UNSAFE
* @stable ICU 2.4
*/
-#define U16_APPEND(s, i, capacity, c, isError) { \
+#define U16_APPEND(s, i, capacity, c, isError) UPRV_BLOCK_MACRO_BEGIN { \
if((uint32_t)(c)<=0xffff) { \
(s)[(i)++]=(uint16_t)(c); \
} else if((uint32_t)(c)<=0x10ffff && (i)+1<(capacity)) { \
@@ -398,7 +398,7 @@
} else /* c>0x10ffff or not enough space */ { \
(isError)=TRUE; \
} \
-}
+} UPRV_BLOCK_MACRO_END
/**
* Advance the string offset from one code point boundary to the next.
@@ -410,11 +410,11 @@
* @see U16_FWD_1
* @stable ICU 2.4
*/
-#define U16_FWD_1_UNSAFE(s, i) { \
+#define U16_FWD_1_UNSAFE(s, i) UPRV_BLOCK_MACRO_BEGIN { \
if(U16_IS_LEAD((s)[(i)++])) { \
++(i); \
} \
-}
+} UPRV_BLOCK_MACRO_END
/**
* Advance the string offset from one code point boundary to the next.
@@ -429,11 +429,11 @@
* @see U16_FWD_1_UNSAFE
* @stable ICU 2.4
*/
-#define U16_FWD_1(s, i, length) { \
+#define U16_FWD_1(s, i, length) UPRV_BLOCK_MACRO_BEGIN { \
if(U16_IS_LEAD((s)[(i)++]) && (i)!=(length) && U16_IS_TRAIL((s)[i])) { \
++(i); \
} \
-}
+} UPRV_BLOCK_MACRO_END
/**
* Advance the string offset from one code point boundary to the n-th next one,
@@ -447,13 +447,13 @@
* @see U16_FWD_N
* @stable ICU 2.4
*/
-#define U16_FWD_N_UNSAFE(s, i, n) { \
+#define U16_FWD_N_UNSAFE(s, i, n) UPRV_BLOCK_MACRO_BEGIN { \
int32_t __N=(n); \
while(__N>0) { \
U16_FWD_1_UNSAFE(s, i); \
--__N; \
} \
-}
+} UPRV_BLOCK_MACRO_END
/**
* Advance the string offset from one code point boundary to the n-th next one,
@@ -470,13 +470,13 @@
* @see U16_FWD_N_UNSAFE
* @stable ICU 2.4
*/
-#define U16_FWD_N(s, i, length, n) { \
+#define U16_FWD_N(s, i, length, n) UPRV_BLOCK_MACRO_BEGIN { \
int32_t __N=(n); \
while(__N>0 && ((i)<(length) || ((length)<0 && (s)[i]!=0))) { \
U16_FWD_1(s, i, length); \
--__N; \
} \
-}
+} UPRV_BLOCK_MACRO_END
/**
* Adjust a random-access offset to a code point boundary
@@ -491,11 +491,11 @@
* @see U16_SET_CP_START
* @stable ICU 2.4
*/
-#define U16_SET_CP_START_UNSAFE(s, i) { \
+#define U16_SET_CP_START_UNSAFE(s, i) UPRV_BLOCK_MACRO_BEGIN { \
if(U16_IS_TRAIL((s)[i])) { \
--(i); \
} \
-}
+} UPRV_BLOCK_MACRO_END
/**
* Adjust a random-access offset to a code point boundary
@@ -511,11 +511,11 @@
* @see U16_SET_CP_START_UNSAFE
* @stable ICU 2.4
*/
-#define U16_SET_CP_START(s, start, i) { \
+#define U16_SET_CP_START(s, start, i) UPRV_BLOCK_MACRO_BEGIN { \
if(U16_IS_TRAIL((s)[i]) && (i)>(start) && U16_IS_LEAD((s)[(i)-1])) { \
--(i); \
} \
-}
+} UPRV_BLOCK_MACRO_END
/* definitions with backward iteration -------------------------------------- */
@@ -539,12 +539,12 @@
* @see U16_PREV
* @stable ICU 2.4
*/
-#define U16_PREV_UNSAFE(s, i, c) { \
+#define U16_PREV_UNSAFE(s, i, c) UPRV_BLOCK_MACRO_BEGIN { \
(c)=(s)[--(i)]; \
if(U16_IS_TRAIL(c)) { \
(c)=U16_GET_SUPPLEMENTARY((s)[--(i)], (c)); \
} \
-}
+} UPRV_BLOCK_MACRO_END
/**
* Move the string offset from one code point boundary to the previous one
@@ -566,7 +566,7 @@
* @see U16_PREV_UNSAFE
* @stable ICU 2.4
*/
-#define U16_PREV(s, start, i, c) { \
+#define U16_PREV(s, start, i, c) UPRV_BLOCK_MACRO_BEGIN { \
(c)=(s)[--(i)]; \
if(U16_IS_TRAIL(c)) { \
uint16_t __c2; \
@@ -575,7 +575,7 @@
(c)=U16_GET_SUPPLEMENTARY(__c2, (c)); \
} \
} \
-}
+} UPRV_BLOCK_MACRO_END
/**
* Move the string offset from one code point boundary to the previous one
@@ -597,7 +597,7 @@
* @see U16_PREV_UNSAFE
* @stable ICU 60
*/
-#define U16_PREV_OR_FFFD(s, start, i, c) { \
+#define U16_PREV_OR_FFFD(s, start, i, c) UPRV_BLOCK_MACRO_BEGIN { \
(c)=(s)[--(i)]; \
if(U16_IS_SURROGATE(c)) { \
uint16_t __c2; \
@@ -608,7 +608,7 @@
(c)=0xfffd; \
} \
} \
-}
+} UPRV_BLOCK_MACRO_END
/**
* Move the string offset from one code point boundary to the previous one.
@@ -621,11 +621,11 @@
* @see U16_BACK_1
* @stable ICU 2.4
*/
-#define U16_BACK_1_UNSAFE(s, i) { \
+#define U16_BACK_1_UNSAFE(s, i) UPRV_BLOCK_MACRO_BEGIN { \
if(U16_IS_TRAIL((s)[--(i)])) { \
--(i); \
} \
-}
+} UPRV_BLOCK_MACRO_END
/**
* Move the string offset from one code point boundary to the previous one.
@@ -639,11 +639,11 @@
* @see U16_BACK_1_UNSAFE
* @stable ICU 2.4
*/
-#define U16_BACK_1(s, start, i) { \
+#define U16_BACK_1(s, start, i) UPRV_BLOCK_MACRO_BEGIN { \
if(U16_IS_TRAIL((s)[--(i)]) && (i)>(start) && U16_IS_LEAD((s)[(i)-1])) { \
--(i); \
} \
-}
+} UPRV_BLOCK_MACRO_END
/**
* Move the string offset from one code point boundary to the n-th one before it,
@@ -658,13 +658,13 @@
* @see U16_BACK_N
* @stable ICU 2.4
*/
-#define U16_BACK_N_UNSAFE(s, i, n) { \
+#define U16_BACK_N_UNSAFE(s, i, n) UPRV_BLOCK_MACRO_BEGIN { \
int32_t __N=(n); \
while(__N>0) { \
U16_BACK_1_UNSAFE(s, i); \
--__N; \
} \
-}
+} UPRV_BLOCK_MACRO_END
/**
* Move the string offset from one code point boundary to the n-th one before it,
@@ -680,13 +680,13 @@
* @see U16_BACK_N_UNSAFE
* @stable ICU 2.4
*/
-#define U16_BACK_N(s, start, i, n) { \
+#define U16_BACK_N(s, start, i, n) UPRV_BLOCK_MACRO_BEGIN { \
int32_t __N=(n); \
while(__N>0 && (i)>(start)) { \
U16_BACK_1(s, start, i); \
--__N; \
} \
-}
+} UPRV_BLOCK_MACRO_END
/**
* Adjust a random-access offset to a code point boundary after a code point.
@@ -701,11 +701,11 @@
* @see U16_SET_CP_LIMIT
* @stable ICU 2.4
*/
-#define U16_SET_CP_LIMIT_UNSAFE(s, i) { \
+#define U16_SET_CP_LIMIT_UNSAFE(s, i) UPRV_BLOCK_MACRO_BEGIN { \
if(U16_IS_LEAD((s)[(i)-1])) { \
++(i); \
} \
-}
+} UPRV_BLOCK_MACRO_END
/**
* Adjust a random-access offset to a code point boundary after a code point.
@@ -724,10 +724,10 @@
* @see U16_SET_CP_LIMIT_UNSAFE
* @stable ICU 2.4
*/
-#define U16_SET_CP_LIMIT(s, start, i, length) { \
+#define U16_SET_CP_LIMIT(s, start, i, length) UPRV_BLOCK_MACRO_BEGIN { \
if((start)<(i) && ((i)<(length) || (length)<0) && U16_IS_LEAD((s)[(i)-1]) && U16_IS_TRAIL((s)[i])) { \
++(i); \
} \
-}
+} UPRV_BLOCK_MACRO_END
#endif
diff -Nru icu-64.2/source/common/unicode/utf8.h icu-65.1/source/common/unicode/utf8.h
--- icu-64.2/source/common/unicode/utf8.h 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/unicode/utf8.h 2019-10-03 11:16:41.000000000 +0000
@@ -229,11 +229,11 @@
* @see U8_GET
* @stable ICU 2.4
*/
-#define U8_GET_UNSAFE(s, i, c) { \
+#define U8_GET_UNSAFE(s, i, c) UPRV_BLOCK_MACRO_BEGIN { \
int32_t _u8_get_unsafe_index=(int32_t)(i); \
U8_SET_CP_START_UNSAFE(s, _u8_get_unsafe_index); \
U8_NEXT_UNSAFE(s, _u8_get_unsafe_index, c); \
-}
+} UPRV_BLOCK_MACRO_END
/**
* Get a code point from a string at a random-access offset,
@@ -256,11 +256,11 @@
* @see U8_GET_UNSAFE
* @stable ICU 2.4
*/
-#define U8_GET(s, start, i, length, c) { \
+#define U8_GET(s, start, i, length, c) UPRV_BLOCK_MACRO_BEGIN { \
int32_t _u8_get_index=(i); \
U8_SET_CP_START(s, start, _u8_get_index); \
U8_NEXT(s, _u8_get_index, length, c); \
-}
+} UPRV_BLOCK_MACRO_END
/**
* Get a code point from a string at a random-access offset,
@@ -287,11 +287,11 @@
* @see U8_GET
* @stable ICU 51
*/
-#define U8_GET_OR_FFFD(s, start, i, length, c) { \
+#define U8_GET_OR_FFFD(s, start, i, length, c) UPRV_BLOCK_MACRO_BEGIN { \
int32_t _u8_get_index=(i); \
U8_SET_CP_START(s, start, _u8_get_index); \
U8_NEXT_OR_FFFD(s, _u8_get_index, length, c); \
-}
+} UPRV_BLOCK_MACRO_END
/* definitions with forward iteration --------------------------------------- */
@@ -312,7 +312,7 @@
* @see U8_NEXT
* @stable ICU 2.4
*/
-#define U8_NEXT_UNSAFE(s, i, c) { \
+#define U8_NEXT_UNSAFE(s, i, c) UPRV_BLOCK_MACRO_BEGIN { \
(c)=(uint8_t)(s)[(i)++]; \
if(!U8_IS_SINGLE(c)) { \
if((c)<0xe0) { \
@@ -326,7 +326,7 @@
(i)+=3; \
} \
} \
-}
+} UPRV_BLOCK_MACRO_END
/**
* Get a code point from a string at a code point boundary offset,
@@ -377,7 +377,7 @@
#define U8_NEXT_OR_FFFD(s, i, length, c) U8_INTERNAL_NEXT_OR_SUB(s, i, length, c, 0xfffd)
/** @internal */
-#define U8_INTERNAL_NEXT_OR_SUB(s, i, length, c, sub) { \
+#define U8_INTERNAL_NEXT_OR_SUB(s, i, length, c, sub) UPRV_BLOCK_MACRO_BEGIN { \
(c)=(uint8_t)(s)[(i)++]; \
if(!U8_IS_SINGLE(c)) { \
uint8_t __t = 0; \
@@ -403,7 +403,7 @@
(c)=(sub); /* ill-formed*/ \
} \
} \
-}
+} UPRV_BLOCK_MACRO_END
/**
* Append a code point to a string, overwriting 1 to 4 bytes.
@@ -418,7 +418,7 @@
* @see U8_APPEND
* @stable ICU 2.4
*/
-#define U8_APPEND_UNSAFE(s, i, c) { \
+#define U8_APPEND_UNSAFE(s, i, c) UPRV_BLOCK_MACRO_BEGIN { \
uint32_t __uc=(c); \
if(__uc<=0x7f) { \
(s)[(i)++]=(uint8_t)__uc; \
@@ -436,7 +436,7 @@
} \
(s)[(i)++]=(uint8_t)((__uc&0x3f)|0x80); \
} \
-}
+} UPRV_BLOCK_MACRO_END
/**
* Append a code point to a string, overwriting 1 to 4 bytes.
@@ -455,7 +455,7 @@
* @see U8_APPEND_UNSAFE
* @stable ICU 2.4
*/
-#define U8_APPEND(s, i, capacity, c, isError) { \
+#define U8_APPEND(s, i, capacity, c, isError) UPRV_BLOCK_MACRO_BEGIN { \
uint32_t __uc=(c); \
if(__uc<=0x7f) { \
(s)[(i)++]=(uint8_t)__uc; \
@@ -474,7 +474,7 @@
} else { \
(isError)=TRUE; \
} \
-}
+} UPRV_BLOCK_MACRO_END
/**
* Advance the string offset from one code point boundary to the next.
@@ -486,9 +486,9 @@
* @see U8_FWD_1
* @stable ICU 2.4
*/
-#define U8_FWD_1_UNSAFE(s, i) { \
+#define U8_FWD_1_UNSAFE(s, i) UPRV_BLOCK_MACRO_BEGIN { \
(i)+=1+U8_COUNT_TRAIL_BYTES_UNSAFE((s)[i]); \
-}
+} UPRV_BLOCK_MACRO_END
/**
* Advance the string offset from one code point boundary to the next.
@@ -503,7 +503,7 @@
* @see U8_FWD_1_UNSAFE
* @stable ICU 2.4
*/
-#define U8_FWD_1(s, i, length) { \
+#define U8_FWD_1(s, i, length) UPRV_BLOCK_MACRO_BEGIN { \
uint8_t __b=(s)[(i)++]; \
if(U8_IS_LEAD(__b) && (i)!=(length)) { \
uint8_t __t1=(s)[i]; \
@@ -524,7 +524,7 @@
} \
} \
} \
-}
+} UPRV_BLOCK_MACRO_END
/**
* Advance the string offset from one code point boundary to the n-th next one,
@@ -538,13 +538,13 @@
* @see U8_FWD_N
* @stable ICU 2.4
*/
-#define U8_FWD_N_UNSAFE(s, i, n) { \
+#define U8_FWD_N_UNSAFE(s, i, n) UPRV_BLOCK_MACRO_BEGIN { \
int32_t __N=(n); \
while(__N>0) { \
U8_FWD_1_UNSAFE(s, i); \
--__N; \
} \
-}
+} UPRV_BLOCK_MACRO_END
/**
* Advance the string offset from one code point boundary to the n-th next one,
@@ -561,13 +561,13 @@
* @see U8_FWD_N_UNSAFE
* @stable ICU 2.4
*/
-#define U8_FWD_N(s, i, length, n) { \
+#define U8_FWD_N(s, i, length, n) UPRV_BLOCK_MACRO_BEGIN { \
int32_t __N=(n); \
while(__N>0 && ((i)<(length) || ((length)<0 && (s)[i]!=0))) { \
U8_FWD_1(s, i, length); \
--__N; \
} \
-}
+} UPRV_BLOCK_MACRO_END
/**
* Adjust a random-access offset to a code point boundary
@@ -582,9 +582,9 @@
* @see U8_SET_CP_START
* @stable ICU 2.4
*/
-#define U8_SET_CP_START_UNSAFE(s, i) { \
+#define U8_SET_CP_START_UNSAFE(s, i) UPRV_BLOCK_MACRO_BEGIN { \
while(U8_IS_TRAIL((s)[i])) { --(i); } \
-}
+} UPRV_BLOCK_MACRO_END
/**
* Adjust a random-access offset to a code point boundary
@@ -603,11 +603,11 @@
* @see U8_TRUNCATE_IF_INCOMPLETE
* @stable ICU 2.4
*/
-#define U8_SET_CP_START(s, start, i) { \
+#define U8_SET_CP_START(s, start, i) UPRV_BLOCK_MACRO_BEGIN { \
if(U8_IS_TRAIL((s)[(i)])) { \
(i)=utf8_back1SafeBody(s, start, (i)); \
} \
-}
+} UPRV_BLOCK_MACRO_END
/**
* If the string ends with a UTF-8 byte sequence that is valid so far
@@ -635,7 +635,7 @@
* @see U8_SET_CP_START
* @stable ICU 61
*/
-#define U8_TRUNCATE_IF_INCOMPLETE(s, start, length) \
+#define U8_TRUNCATE_IF_INCOMPLETE(s, start, length) UPRV_BLOCK_MACRO_BEGIN { \
if((length)>(start)) { \
uint8_t __b1=s[(length)-1]; \
if(U8_IS_SINGLE(__b1)) { \
@@ -656,7 +656,8 @@
} \
} \
} \
- }
+ } \
+} UPRV_BLOCK_MACRO_END
/* definitions with backward iteration -------------------------------------- */
@@ -679,7 +680,7 @@
* @see U8_PREV
* @stable ICU 2.4
*/
-#define U8_PREV_UNSAFE(s, i, c) { \
+#define U8_PREV_UNSAFE(s, i, c) UPRV_BLOCK_MACRO_BEGIN { \
(c)=(uint8_t)(s)[--(i)]; \
if(U8_IS_TRAIL(c)) { \
uint8_t __b, __count=1, __shift=6; \
@@ -699,7 +700,7 @@
} \
} \
} \
-}
+} UPRV_BLOCK_MACRO_END
/**
* Move the string offset from one code point boundary to the previous one
@@ -721,12 +722,12 @@
* @see U8_PREV_UNSAFE
* @stable ICU 2.4
*/
-#define U8_PREV(s, start, i, c) { \
+#define U8_PREV(s, start, i, c) UPRV_BLOCK_MACRO_BEGIN { \
(c)=(uint8_t)(s)[--(i)]; \
if(!U8_IS_SINGLE(c)) { \
(c)=utf8_prevCharSafeBody((const uint8_t *)s, start, &(i), c, -1); \
} \
-}
+} UPRV_BLOCK_MACRO_END
/**
* Move the string offset from one code point boundary to the previous one
@@ -752,12 +753,12 @@
* @see U8_PREV
* @stable ICU 51
*/
-#define U8_PREV_OR_FFFD(s, start, i, c) { \
+#define U8_PREV_OR_FFFD(s, start, i, c) UPRV_BLOCK_MACRO_BEGIN { \
(c)=(uint8_t)(s)[--(i)]; \
if(!U8_IS_SINGLE(c)) { \
(c)=utf8_prevCharSafeBody((const uint8_t *)s, start, &(i), c, -3); \
} \
-}
+} UPRV_BLOCK_MACRO_END
/**
* Move the string offset from one code point boundary to the previous one.
@@ -770,9 +771,9 @@
* @see U8_BACK_1
* @stable ICU 2.4
*/
-#define U8_BACK_1_UNSAFE(s, i) { \
+#define U8_BACK_1_UNSAFE(s, i) UPRV_BLOCK_MACRO_BEGIN { \
while(U8_IS_TRAIL((s)[--(i)])) {} \
-}
+} UPRV_BLOCK_MACRO_END
/**
* Move the string offset from one code point boundary to the previous one.
@@ -786,11 +787,11 @@
* @see U8_BACK_1_UNSAFE
* @stable ICU 2.4
*/
-#define U8_BACK_1(s, start, i) { \
+#define U8_BACK_1(s, start, i) UPRV_BLOCK_MACRO_BEGIN { \
if(U8_IS_TRAIL((s)[--(i)])) { \
(i)=utf8_back1SafeBody(s, start, (i)); \
} \
-}
+} UPRV_BLOCK_MACRO_END
/**
* Move the string offset from one code point boundary to the n-th one before it,
@@ -805,13 +806,13 @@
* @see U8_BACK_N
* @stable ICU 2.4
*/
-#define U8_BACK_N_UNSAFE(s, i, n) { \
+#define U8_BACK_N_UNSAFE(s, i, n) UPRV_BLOCK_MACRO_BEGIN { \
int32_t __N=(n); \
while(__N>0) { \
U8_BACK_1_UNSAFE(s, i); \
--__N; \
} \
-}
+} UPRV_BLOCK_MACRO_END
/**
* Move the string offset from one code point boundary to the n-th one before it,
@@ -827,13 +828,13 @@
* @see U8_BACK_N_UNSAFE
* @stable ICU 2.4
*/
-#define U8_BACK_N(s, start, i, n) { \
+#define U8_BACK_N(s, start, i, n) UPRV_BLOCK_MACRO_BEGIN { \
int32_t __N=(n); \
while(__N>0 && (i)>(start)) { \
U8_BACK_1(s, start, i); \
--__N; \
} \
-}
+} UPRV_BLOCK_MACRO_END
/**
* Adjust a random-access offset to a code point boundary after a code point.
@@ -848,10 +849,10 @@
* @see U8_SET_CP_LIMIT
* @stable ICU 2.4
*/
-#define U8_SET_CP_LIMIT_UNSAFE(s, i) { \
+#define U8_SET_CP_LIMIT_UNSAFE(s, i) UPRV_BLOCK_MACRO_BEGIN { \
U8_BACK_1_UNSAFE(s, i); \
U8_FWD_1_UNSAFE(s, i); \
-}
+} UPRV_BLOCK_MACRO_END
/**
* Adjust a random-access offset to a code point boundary after a code point.
@@ -870,11 +871,11 @@
* @see U8_SET_CP_LIMIT_UNSAFE
* @stable ICU 2.4
*/
-#define U8_SET_CP_LIMIT(s, start, i, length) { \
+#define U8_SET_CP_LIMIT(s, start, i, length) UPRV_BLOCK_MACRO_BEGIN { \
if((start)<(i) && ((i)<(length) || (length)<0)) { \
U8_BACK_1(s, start, i); \
U8_FWD_1(s, i, length); \
} \
-}
+} UPRV_BLOCK_MACRO_END
#endif
diff -Nru icu-64.2/source/common/unicode/utf_old.h icu-65.1/source/common/unicode/utf_old.h
--- icu-64.2/source/common/unicode/utf_old.h 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/unicode/utf_old.h 2019-10-03 11:16:41.000000000 +0000
@@ -19,9 +19,6 @@
/**
* \file
* \brief C API: Deprecated macros for Unicode string handling
- */
-
-/**
*
* The macros in utf_old.h are all deprecated and their use discouraged.
* Some of the design principles behind the set of UTF macros
@@ -139,12 +136,16 @@
*
*
*
- * @deprecated ICU 2.4. Use the macros in utf.h, utf16.h, utf8.h instead.
+ * Deprecated ICU 2.4. Use the macros in utf.h, utf16.h, utf8.h instead.
*/
#ifndef __UTF_OLD_H__
#define __UTF_OLD_H__
+#include "unicode/utf.h"
+#include "unicode/utf8.h"
+#include "unicode/utf16.h"
+
/**
* \def U_HIDE_OBSOLETE_UTF_OLD_H
*
@@ -162,10 +163,6 @@
#if !defined(U_HIDE_DEPRECATED_API) && !U_HIDE_OBSOLETE_UTF_OLD_H
-#include "unicode/utf.h"
-#include "unicode/utf8.h"
-#include "unicode/utf16.h"
-
/* Formerly utf.h, part 1 --------------------------------------------------- */
#ifdef U_USE_UTF_DEPRECATES
@@ -365,21 +362,21 @@
#define UTF8_ARRAY_SIZE(size) ((5*(size))/2)
/** @deprecated ICU 2.4. Renamed to U8_GET_UNSAFE, see utf_old.h. */
-#define UTF8_GET_CHAR_UNSAFE(s, i, c) { \
+#define UTF8_GET_CHAR_UNSAFE(s, i, c) UPRV_BLOCK_MACRO_BEGIN { \
int32_t _utf8_get_char_unsafe_index=(int32_t)(i); \
UTF8_SET_CHAR_START_UNSAFE(s, _utf8_get_char_unsafe_index); \
UTF8_NEXT_CHAR_UNSAFE(s, _utf8_get_char_unsafe_index, c); \
-}
+} UPRV_BLOCK_MACRO_END
/** @deprecated ICU 2.4. Use U8_GET instead, see utf_old.h. */
-#define UTF8_GET_CHAR_SAFE(s, start, i, length, c, strict) { \
+#define UTF8_GET_CHAR_SAFE(s, start, i, length, c, strict) UPRV_BLOCK_MACRO_BEGIN { \
int32_t _utf8_get_char_safe_index=(int32_t)(i); \
UTF8_SET_CHAR_START_SAFE(s, start, _utf8_get_char_safe_index); \
UTF8_NEXT_CHAR_SAFE(s, _utf8_get_char_safe_index, length, c, strict); \
-}
+} UPRV_BLOCK_MACRO_END
/** @deprecated ICU 2.4. Renamed to U8_NEXT_UNSAFE, see utf_old.h. */
-#define UTF8_NEXT_CHAR_UNSAFE(s, i, c) { \
+#define UTF8_NEXT_CHAR_UNSAFE(s, i, c) UPRV_BLOCK_MACRO_BEGIN { \
(c)=(s)[(i)++]; \
if((uint8_t)((c)-0xc0)<0x35) { \
uint8_t __count=UTF8_COUNT_TRAIL_BYTES(c); \
@@ -396,10 +393,10 @@
break; \
} \
} \
-}
+} UPRV_BLOCK_MACRO_END
/** @deprecated ICU 2.4. Renamed to U8_APPEND_UNSAFE, see utf_old.h. */
-#define UTF8_APPEND_CHAR_UNSAFE(s, i, c) { \
+#define UTF8_APPEND_CHAR_UNSAFE(s, i, c) UPRV_BLOCK_MACRO_BEGIN { \
if((uint32_t)(c)<=0x7f) { \
(s)[(i)++]=(uint8_t)(c); \
} else { \
@@ -416,29 +413,29 @@
} \
(s)[(i)++]=(uint8_t)(((c)&0x3f)|0x80); \
} \
-}
+} UPRV_BLOCK_MACRO_END
/** @deprecated ICU 2.4. Renamed to U8_FWD_1_UNSAFE, see utf_old.h. */
-#define UTF8_FWD_1_UNSAFE(s, i) { \
+#define UTF8_FWD_1_UNSAFE(s, i) UPRV_BLOCK_MACRO_BEGIN { \
(i)+=1+UTF8_COUNT_TRAIL_BYTES((s)[i]); \
-}
+} UPRV_BLOCK_MACRO_END
/** @deprecated ICU 2.4. Renamed to U8_FWD_N_UNSAFE, see utf_old.h. */
-#define UTF8_FWD_N_UNSAFE(s, i, n) { \
+#define UTF8_FWD_N_UNSAFE(s, i, n) UPRV_BLOCK_MACRO_BEGIN { \
int32_t __N=(n); \
while(__N>0) { \
UTF8_FWD_1_UNSAFE(s, i); \
--__N; \
} \
-}
+} UPRV_BLOCK_MACRO_END
/** @deprecated ICU 2.4. Renamed to U8_SET_CP_START_UNSAFE, see utf_old.h. */
-#define UTF8_SET_CHAR_START_UNSAFE(s, i) { \
+#define UTF8_SET_CHAR_START_UNSAFE(s, i) UPRV_BLOCK_MACRO_BEGIN { \
while(UTF8_IS_TRAIL((s)[i])) { --(i); } \
-}
+} UPRV_BLOCK_MACRO_END
/** @deprecated ICU 2.4. Use U8_NEXT instead, see utf_old.h. */
-#define UTF8_NEXT_CHAR_SAFE(s, i, length, c, strict) { \
+#define UTF8_NEXT_CHAR_SAFE(s, i, length, c, strict) UPRV_BLOCK_MACRO_BEGIN { \
(c)=(s)[(i)++]; \
if((c)>=0x80) { \
if(UTF8_IS_LEAD(c)) { \
@@ -447,16 +444,16 @@
(c)=UTF8_ERROR_VALUE_1; \
} \
} \
-}
+} UPRV_BLOCK_MACRO_END
/** @deprecated ICU 2.4. Use U8_APPEND instead, see utf_old.h. */
-#define UTF8_APPEND_CHAR_SAFE(s, i, length, c) { \
+#define UTF8_APPEND_CHAR_SAFE(s, i, length, c) UPRV_BLOCK_MACRO_BEGIN { \
if((uint32_t)(c)<=0x7f) { \
(s)[(i)++]=(uint8_t)(c); \
} else { \
(i)=utf8_appendCharSafeBody(s, (int32_t)(i), (int32_t)(length), c, NULL); \
} \
-}
+} UPRV_BLOCK_MACRO_END
/** @deprecated ICU 2.4. Renamed to U8_FWD_1, see utf_old.h. */
#define UTF8_FWD_1_SAFE(s, i, length) U8_FWD_1(s, i, length)
@@ -468,7 +465,7 @@
#define UTF8_SET_CHAR_START_SAFE(s, start, i) U8_SET_CP_START(s, start, i)
/** @deprecated ICU 2.4. Renamed to U8_PREV_UNSAFE, see utf_old.h. */
-#define UTF8_PREV_CHAR_UNSAFE(s, i, c) { \
+#define UTF8_PREV_CHAR_UNSAFE(s, i, c) UPRV_BLOCK_MACRO_BEGIN { \
(c)=(s)[--(i)]; \
if(UTF8_IS_TRAIL(c)) { \
uint8_t __b, __count=1, __shift=6; \
@@ -488,30 +485,30 @@
} \
} \
} \
-}
+} UPRV_BLOCK_MACRO_END
/** @deprecated ICU 2.4. Renamed to U8_BACK_1_UNSAFE, see utf_old.h. */
-#define UTF8_BACK_1_UNSAFE(s, i) { \
+#define UTF8_BACK_1_UNSAFE(s, i) UPRV_BLOCK_MACRO_BEGIN { \
while(UTF8_IS_TRAIL((s)[--(i)])) {} \
-}
+} UPRV_BLOCK_MACRO_END
/** @deprecated ICU 2.4. Renamed to U8_BACK_N_UNSAFE, see utf_old.h. */
-#define UTF8_BACK_N_UNSAFE(s, i, n) { \
+#define UTF8_BACK_N_UNSAFE(s, i, n) UPRV_BLOCK_MACRO_BEGIN { \
int32_t __N=(n); \
while(__N>0) { \
UTF8_BACK_1_UNSAFE(s, i); \
--__N; \
} \
-}
+} UPRV_BLOCK_MACRO_END
/** @deprecated ICU 2.4. Renamed to U8_SET_CP_LIMIT_UNSAFE, see utf_old.h. */
-#define UTF8_SET_CHAR_LIMIT_UNSAFE(s, i) { \
+#define UTF8_SET_CHAR_LIMIT_UNSAFE(s, i) UPRV_BLOCK_MACRO_BEGIN { \
UTF8_BACK_1_UNSAFE(s, i); \
UTF8_FWD_1_UNSAFE(s, i); \
-}
+} UPRV_BLOCK_MACRO_END
/** @deprecated ICU 2.4. Use U8_PREV instead, see utf_old.h. */
-#define UTF8_PREV_CHAR_SAFE(s, start, i, c, strict) { \
+#define UTF8_PREV_CHAR_SAFE(s, start, i, c, strict) UPRV_BLOCK_MACRO_BEGIN { \
(c)=(s)[--(i)]; \
if((c)>=0x80) { \
if((c)<=0xbf) { \
@@ -520,7 +517,7 @@
(c)=UTF8_ERROR_VALUE_1; \
} \
} \
-}
+} UPRV_BLOCK_MACRO_END
/** @deprecated ICU 2.4. Renamed to U8_BACK_1, see utf_old.h. */
#define UTF8_BACK_1_SAFE(s, start, i) U8_BACK_1(s, start, i)
@@ -593,7 +590,7 @@
* UTF16_PREV_CHAR[_UNSAFE]() is more efficient for that.
* @deprecated ICU 2.4. Renamed to U16_GET_UNSAFE, see utf_old.h.
*/
-#define UTF16_GET_CHAR_UNSAFE(s, i, c) { \
+#define UTF16_GET_CHAR_UNSAFE(s, i, c) UPRV_BLOCK_MACRO_BEGIN { \
(c)=(s)[i]; \
if(UTF_IS_SURROGATE(c)) { \
if(UTF_IS_SURROGATE_FIRST(c)) { \
@@ -602,10 +599,10 @@
(c)=UTF16_GET_PAIR_VALUE((s)[(i)-1], (c)); \
} \
} \
-}
+} UPRV_BLOCK_MACRO_END
/** @deprecated ICU 2.4. Use U16_GET instead, see utf_old.h. */
-#define UTF16_GET_CHAR_SAFE(s, start, i, length, c, strict) { \
+#define UTF16_GET_CHAR_SAFE(s, start, i, length, c, strict) UPRV_BLOCK_MACRO_BEGIN { \
(c)=(s)[i]; \
if(UTF_IS_SURROGATE(c)) { \
uint16_t __c2; \
@@ -629,51 +626,51 @@
} else if((strict) && !UTF_IS_UNICODE_CHAR(c)) { \
(c)=UTF_ERROR_VALUE; \
} \
-}
+} UPRV_BLOCK_MACRO_END
/** @deprecated ICU 2.4. Renamed to U16_NEXT_UNSAFE, see utf_old.h. */
-#define UTF16_NEXT_CHAR_UNSAFE(s, i, c) { \
+#define UTF16_NEXT_CHAR_UNSAFE(s, i, c) UPRV_BLOCK_MACRO_BEGIN { \
(c)=(s)[(i)++]; \
if(UTF_IS_FIRST_SURROGATE(c)) { \
(c)=UTF16_GET_PAIR_VALUE((c), (s)[(i)++]); \
} \
-}
+} UPRV_BLOCK_MACRO_END
/** @deprecated ICU 2.4. Renamed to U16_APPEND_UNSAFE, see utf_old.h. */
-#define UTF16_APPEND_CHAR_UNSAFE(s, i, c) { \
+#define UTF16_APPEND_CHAR_UNSAFE(s, i, c) UPRV_BLOCK_MACRO_BEGIN { \
if((uint32_t)(c)<=0xffff) { \
(s)[(i)++]=(uint16_t)(c); \
} else { \
(s)[(i)++]=(uint16_t)(((c)>>10)+0xd7c0); \
(s)[(i)++]=(uint16_t)(((c)&0x3ff)|0xdc00); \
} \
-}
+} UPRV_BLOCK_MACRO_END
/** @deprecated ICU 2.4. Renamed to U16_FWD_1_UNSAFE, see utf_old.h. */
-#define UTF16_FWD_1_UNSAFE(s, i) { \
+#define UTF16_FWD_1_UNSAFE(s, i) UPRV_BLOCK_MACRO_BEGIN { \
if(UTF_IS_FIRST_SURROGATE((s)[(i)++])) { \
++(i); \
} \
-}
+} UPRV_BLOCK_MACRO_END
/** @deprecated ICU 2.4. Renamed to U16_FWD_N_UNSAFE, see utf_old.h. */
-#define UTF16_FWD_N_UNSAFE(s, i, n) { \
+#define UTF16_FWD_N_UNSAFE(s, i, n) UPRV_BLOCK_MACRO_BEGIN { \
int32_t __N=(n); \
while(__N>0) { \
UTF16_FWD_1_UNSAFE(s, i); \
--__N; \
} \
-}
+} UPRV_BLOCK_MACRO_END
/** @deprecated ICU 2.4. Renamed to U16_SET_CP_START_UNSAFE, see utf_old.h. */
-#define UTF16_SET_CHAR_START_UNSAFE(s, i) { \
+#define UTF16_SET_CHAR_START_UNSAFE(s, i) UPRV_BLOCK_MACRO_BEGIN { \
if(UTF_IS_SECOND_SURROGATE((s)[i])) { \
--(i); \
} \
-}
+} UPRV_BLOCK_MACRO_END
/** @deprecated ICU 2.4. Use U16_NEXT instead, see utf_old.h. */
-#define UTF16_NEXT_CHAR_SAFE(s, i, length, c, strict) { \
+#define UTF16_NEXT_CHAR_SAFE(s, i, length, c, strict) UPRV_BLOCK_MACRO_BEGIN { \
(c)=(s)[(i)++]; \
if(UTF_IS_FIRST_SURROGATE(c)) { \
uint16_t __c2; \
@@ -689,10 +686,10 @@
/* unmatched second surrogate or other non-character */ \
(c)=UTF_ERROR_VALUE; \
} \
-}
+} UPRV_BLOCK_MACRO_END
/** @deprecated ICU 2.4. Use U16_APPEND instead, see utf_old.h. */
-#define UTF16_APPEND_CHAR_SAFE(s, i, length, c) { \
+#define UTF16_APPEND_CHAR_SAFE(s, i, length, c) UPRV_BLOCK_MACRO_BEGIN { \
if((uint32_t)(c)<=0xffff) { \
(s)[(i)++]=(uint16_t)(c); \
} else if((uint32_t)(c)<=0x10ffff) { \
@@ -705,7 +702,7 @@
} else /* c>0x10ffff, write error value */ { \
(s)[(i)++]=UTF_ERROR_VALUE; \
} \
-}
+} UPRV_BLOCK_MACRO_END
/** @deprecated ICU 2.4. Renamed to U16_FWD_1, see utf_old.h. */
#define UTF16_FWD_1_SAFE(s, i, length) U16_FWD_1(s, i, length)
@@ -717,38 +714,38 @@
#define UTF16_SET_CHAR_START_SAFE(s, start, i) U16_SET_CP_START(s, start, i)
/** @deprecated ICU 2.4. Renamed to U16_PREV_UNSAFE, see utf_old.h. */
-#define UTF16_PREV_CHAR_UNSAFE(s, i, c) { \
+#define UTF16_PREV_CHAR_UNSAFE(s, i, c) UPRV_BLOCK_MACRO_BEGIN { \
(c)=(s)[--(i)]; \
if(UTF_IS_SECOND_SURROGATE(c)) { \
(c)=UTF16_GET_PAIR_VALUE((s)[--(i)], (c)); \
} \
-}
+} UPRV_BLOCK_MACRO_END
/** @deprecated ICU 2.4. Renamed to U16_BACK_1_UNSAFE, see utf_old.h. */
-#define UTF16_BACK_1_UNSAFE(s, i) { \
+#define UTF16_BACK_1_UNSAFE(s, i) UPRV_BLOCK_MACRO_BEGIN { \
if(UTF_IS_SECOND_SURROGATE((s)[--(i)])) { \
--(i); \
} \
-}
+} UPRV_BLOCK_MACRO_END
/** @deprecated ICU 2.4. Renamed to U16_BACK_N_UNSAFE, see utf_old.h. */
-#define UTF16_BACK_N_UNSAFE(s, i, n) { \
+#define UTF16_BACK_N_UNSAFE(s, i, n) UPRV_BLOCK_MACRO_BEGIN { \
int32_t __N=(n); \
while(__N>0) { \
UTF16_BACK_1_UNSAFE(s, i); \
--__N; \
} \
-}
+} UPRV_BLOCK_MACRO_END
/** @deprecated ICU 2.4. Renamed to U16_SET_CP_LIMIT_UNSAFE, see utf_old.h. */
-#define UTF16_SET_CHAR_LIMIT_UNSAFE(s, i) { \
+#define UTF16_SET_CHAR_LIMIT_UNSAFE(s, i) UPRV_BLOCK_MACRO_BEGIN { \
if(UTF_IS_FIRST_SURROGATE((s)[(i)-1])) { \
++(i); \
} \
-}
+} UPRV_BLOCK_MACRO_END
/** @deprecated ICU 2.4. Use U16_PREV instead, see utf_old.h. */
-#define UTF16_PREV_CHAR_SAFE(s, start, i, c, strict) { \
+#define UTF16_PREV_CHAR_SAFE(s, start, i, c, strict) UPRV_BLOCK_MACRO_BEGIN { \
(c)=(s)[--(i)]; \
if(UTF_IS_SECOND_SURROGATE(c)) { \
uint16_t __c2; \
@@ -764,7 +761,7 @@
/* unmatched first surrogate or other non-character */ \
(c)=UTF_ERROR_VALUE; \
} \
-}
+} UPRV_BLOCK_MACRO_END
/** @deprecated ICU 2.4. Renamed to U16_BACK_1, see utf_old.h. */
#define UTF16_BACK_1_SAFE(s, start, i) U16_BACK_1(s, start, i)
@@ -830,122 +827,122 @@
#define UTF32_ARRAY_SIZE(size) (size)
/** @deprecated ICU 2.4. Obsolete, see utf_old.h. */
-#define UTF32_GET_CHAR_UNSAFE(s, i, c) { \
+#define UTF32_GET_CHAR_UNSAFE(s, i, c) UPRV_BLOCK_MACRO_BEGIN { \
(c)=(s)[i]; \
-}
+} UPRV_BLOCK_MACRO_END
/** @deprecated ICU 2.4. Obsolete, see utf_old.h. */
-#define UTF32_GET_CHAR_SAFE(s, start, i, length, c, strict) { \
+#define UTF32_GET_CHAR_SAFE(s, start, i, length, c, strict) UPRV_BLOCK_MACRO_BEGIN { \
(c)=(s)[i]; \
if(!UTF32_IS_SAFE(c, strict)) { \
(c)=UTF_ERROR_VALUE; \
} \
-}
+} UPRV_BLOCK_MACRO_END
/* definitions with forward iteration --------------------------------------- */
/** @deprecated ICU 2.4. Obsolete, see utf_old.h. */
-#define UTF32_NEXT_CHAR_UNSAFE(s, i, c) { \
+#define UTF32_NEXT_CHAR_UNSAFE(s, i, c) UPRV_BLOCK_MACRO_BEGIN { \
(c)=(s)[(i)++]; \
-}
+} UPRV_BLOCK_MACRO_END
/** @deprecated ICU 2.4. Obsolete, see utf_old.h. */
-#define UTF32_APPEND_CHAR_UNSAFE(s, i, c) { \
+#define UTF32_APPEND_CHAR_UNSAFE(s, i, c) UPRV_BLOCK_MACRO_BEGIN { \
(s)[(i)++]=(c); \
-}
+} UPRV_BLOCK_MACRO_END
/** @deprecated ICU 2.4. Obsolete, see utf_old.h. */
-#define UTF32_FWD_1_UNSAFE(s, i) { \
+#define UTF32_FWD_1_UNSAFE(s, i) UPRV_BLOCK_MACRO_BEGIN { \
++(i); \
-}
+} UPRV_BLOCK_MACRO_END
/** @deprecated ICU 2.4. Obsolete, see utf_old.h. */
-#define UTF32_FWD_N_UNSAFE(s, i, n) { \
+#define UTF32_FWD_N_UNSAFE(s, i, n) UPRV_BLOCK_MACRO_BEGIN { \
(i)+=(n); \
-}
+} UPRV_BLOCK_MACRO_END
/** @deprecated ICU 2.4. Obsolete, see utf_old.h. */
-#define UTF32_SET_CHAR_START_UNSAFE(s, i) { \
-}
+#define UTF32_SET_CHAR_START_UNSAFE(s, i) UPRV_BLOCK_MACRO_BEGIN { \
+} UPRV_BLOCK_MACRO_END
/** @deprecated ICU 2.4. Obsolete, see utf_old.h. */
-#define UTF32_NEXT_CHAR_SAFE(s, i, length, c, strict) { \
+#define UTF32_NEXT_CHAR_SAFE(s, i, length, c, strict) UPRV_BLOCK_MACRO_BEGIN { \
(c)=(s)[(i)++]; \
if(!UTF32_IS_SAFE(c, strict)) { \
(c)=UTF_ERROR_VALUE; \
} \
-}
+} UPRV_BLOCK_MACRO_END
/** @deprecated ICU 2.4. Obsolete, see utf_old.h. */
-#define UTF32_APPEND_CHAR_SAFE(s, i, length, c) { \
+#define UTF32_APPEND_CHAR_SAFE(s, i, length, c) UPRV_BLOCK_MACRO_BEGIN { \
if((uint32_t)(c)<=0x10ffff) { \
(s)[(i)++]=(c); \
} else /* c>0x10ffff, write 0xfffd */ { \
(s)[(i)++]=0xfffd; \
} \
-}
+} UPRV_BLOCK_MACRO_END
/** @deprecated ICU 2.4. Obsolete, see utf_old.h. */
-#define UTF32_FWD_1_SAFE(s, i, length) { \
+#define UTF32_FWD_1_SAFE(s, i, length) UPRV_BLOCK_MACRO_BEGIN { \
++(i); \
-}
+} UPRV_BLOCK_MACRO_END
/** @deprecated ICU 2.4. Obsolete, see utf_old.h. */
-#define UTF32_FWD_N_SAFE(s, i, length, n) { \
+#define UTF32_FWD_N_SAFE(s, i, length, n) UPRV_BLOCK_MACRO_BEGIN { \
if(((i)+=(n))>(length)) { \
(i)=(length); \
} \
-}
+} UPRV_BLOCK_MACRO_END
/** @deprecated ICU 2.4. Obsolete, see utf_old.h. */
-#define UTF32_SET_CHAR_START_SAFE(s, start, i) { \
-}
+#define UTF32_SET_CHAR_START_SAFE(s, start, i) UPRV_BLOCK_MACRO_BEGIN { \
+} UPRV_BLOCK_MACRO_END
/* definitions with backward iteration -------------------------------------- */
/** @deprecated ICU 2.4. Obsolete, see utf_old.h. */
-#define UTF32_PREV_CHAR_UNSAFE(s, i, c) { \
+#define UTF32_PREV_CHAR_UNSAFE(s, i, c) UPRV_BLOCK_MACRO_BEGIN { \
(c)=(s)[--(i)]; \
-}
+} UPRV_BLOCK_MACRO_END
/** @deprecated ICU 2.4. Obsolete, see utf_old.h. */
-#define UTF32_BACK_1_UNSAFE(s, i) { \
+#define UTF32_BACK_1_UNSAFE(s, i) UPRV_BLOCK_MACRO_BEGIN { \
--(i); \
-}
+} UPRV_BLOCK_MACRO_END
/** @deprecated ICU 2.4. Obsolete, see utf_old.h. */
-#define UTF32_BACK_N_UNSAFE(s, i, n) { \
+#define UTF32_BACK_N_UNSAFE(s, i, n) UPRV_BLOCK_MACRO_BEGIN { \
(i)-=(n); \
-}
+} UPRV_BLOCK_MACRO_END
/** @deprecated ICU 2.4. Obsolete, see utf_old.h. */
-#define UTF32_SET_CHAR_LIMIT_UNSAFE(s, i) { \
-}
+#define UTF32_SET_CHAR_LIMIT_UNSAFE(s, i) UPRV_BLOCK_MACRO_BEGIN { \
+} UPRV_BLOCK_MACRO_END
/** @deprecated ICU 2.4. Obsolete, see utf_old.h. */
-#define UTF32_PREV_CHAR_SAFE(s, start, i, c, strict) { \
+#define UTF32_PREV_CHAR_SAFE(s, start, i, c, strict) UPRV_BLOCK_MACRO_BEGIN { \
(c)=(s)[--(i)]; \
if(!UTF32_IS_SAFE(c, strict)) { \
(c)=UTF_ERROR_VALUE; \
} \
-}
+} UPRV_BLOCK_MACRO_END
/** @deprecated ICU 2.4. Obsolete, see utf_old.h. */
-#define UTF32_BACK_1_SAFE(s, start, i) { \
+#define UTF32_BACK_1_SAFE(s, start, i) UPRV_BLOCK_MACRO_BEGIN { \
--(i); \
-}
+} UPRV_BLOCK_MACRO_END
/** @deprecated ICU 2.4. Obsolete, see utf_old.h. */
-#define UTF32_BACK_N_SAFE(s, start, i, n) { \
+#define UTF32_BACK_N_SAFE(s, start, i, n) UPRV_BLOCK_MACRO_BEGIN { \
(i)-=(n); \
if((i)<(start)) { \
(i)=(start); \
} \
-}
+} UPRV_BLOCK_MACRO_END
/** @deprecated ICU 2.4. Obsolete, see utf_old.h. */
-#define UTF32_SET_CHAR_LIMIT_SAFE(s, i, length) { \
-}
+#define UTF32_SET_CHAR_LIMIT_SAFE(s, i, length) UPRV_BLOCK_MACRO_BEGIN { \
+} UPRV_BLOCK_MACRO_END
/* Formerly utf.h, part 2 --------------------------------------------------- */
diff -Nru icu-64.2/source/common/unicode/utrace.h icu-65.1/source/common/unicode/utrace.h
--- icu-64.2/source/common/unicode/utrace.h 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/unicode/utrace.h 2019-10-03 11:16:41.000000000 +0000
@@ -66,6 +66,7 @@
UTRACE_FUNCTION_START=0,
UTRACE_U_INIT=UTRACE_FUNCTION_START,
UTRACE_U_CLEANUP,
+
#ifndef U_HIDE_DEPRECATED_API
/**
* One more than the highest normal collation trace location.
@@ -83,6 +84,7 @@
UTRACE_UCNV_FLUSH_CACHE,
UTRACE_UCNV_LOAD,
UTRACE_UCNV_UNLOAD,
+
#ifndef U_HIDE_DEPRECATED_API
/**
* One more than the highest normal collation trace location.
@@ -101,13 +103,80 @@
UTRACE_UCOL_STRCOLLITER,
UTRACE_UCOL_OPEN_FROM_SHORT_STRING,
UTRACE_UCOL_STRCOLLUTF8, /**< @stable ICU 50 */
+
#ifndef U_HIDE_DEPRECATED_API
/**
* One more than the highest normal collation trace location.
* @deprecated ICU 58 The numeric value may change over time, see ICU ticket #12420.
*/
- UTRACE_COLLATION_LIMIT
+ UTRACE_COLLATION_LIMIT,
#endif // U_HIDE_DEPRECATED_API
+
+#ifndef U_HIDE_DRAFT_API
+
+ /**
+ * The lowest resource/data location.
+ * @draft ICU 65
+ */
+ UTRACE_UDATA_START=0x3000,
+
+ /**
+ * Indicates that a value was read from a resource bundle. Provides three
+ * C-style strings to UTraceData: type, file name, and resource path. The
+ * possible types are:
+ *
+ * - "string" (a string value was accessed)
+ * - "binary" (a binary value was accessed)
+ * - "intvector" (a integer vector value was accessed)
+ * - "int" (a signed integer value was accessed)
+ * - "uint" (a unsigned integer value was accessed)
+ * - "get" (a path was loaded, but the value was not accessed)
+ * - "getalias" (a path was loaded, and an alias was resolved)
+ *
+ * @draft ICU 65
+ */
+ UTRACE_UDATA_RESOURCE=UTRACE_UDATA_START,
+
+ /**
+ * Indicates that a resource bundle was opened.
+ *
+ * Provides one C-style string to UTraceData: file name.
+ * @draft ICU 65
+ */
+ UTRACE_UDATA_BUNDLE,
+
+ /**
+ * Indicates that a data file was opened, but not *.res files.
+ *
+ * Provides one C-style string to UTraceData: file name.
+ *
+ * @draft ICU 65
+ */
+ UTRACE_UDATA_DATA_FILE,
+
+ /**
+ * Indicates that a *.res file was opened.
+ *
+ * This differs from UTRACE_UDATA_BUNDLE because a res file is typically
+ * opened only once per application runtime, but the bundle corresponding
+ * to that res file may be opened many times.
+ *
+ * Provides one C-style string to UTraceData: file name.
+ *
+ * @draft ICU 65
+ */
+ UTRACE_UDATA_RES_FILE,
+
+#endif // U_HIDE_DRAFT_API
+
+#ifndef U_HIDE_INTERNAL_API
+ /**
+ * One more than the highest normal resource/data trace location.
+ * @internal The numeric value may change over time, see ICU ticket #12420.
+ */
+ UTRACE_RES_DATA_LIMIT,
+#endif // U_HIDE_INTERNAL_API
+
} UTraceFunctionNumber;
/**
diff -Nru icu-64.2/source/common/unicode/utypes.h icu-65.1/source/common/unicode/utypes.h
--- icu-64.2/source/common/unicode/utypes.h 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/unicode/utypes.h 2019-10-03 11:16:41.000000000 +0000
@@ -385,17 +385,31 @@
/*===========================================================================*/
/**
- * Error code to replace exception handling, so that the code is compatible with all C++ compilers,
- * and to use the same mechanism for C and C++.
+ * Standard ICU4C error code type, a substitute for exceptions.
+ *
+ * Initialize the UErrorCode with U_ZERO_ERROR, and check for success or
+ * failure using U_SUCCESS() or U_FAILURE():
+ *
+ * UErrorCode errorCode = U_ZERO_ERROR;
+ * // call ICU API that needs an error code parameter.
+ * if (U_FAILURE(errorCode)) {
+ * // An error occurred. Handle it here.
+ * }
+ *
+ * C++ code should use icu::ErrorCode, available in unicode/errorcode.h, or a
+ * suitable subclass.
+ *
+ * For more information, see:
+ * http://icu-project.org/userguide/conventions
+ *
+ * Note: By convention, ICU functions that take a reference (C++) or a pointer
+ * (C) to a UErrorCode first test:
+ *
+ * if (U_FAILURE(errorCode)) { return immediately; }
*
- * \par
- * ICU functions that take a reference (C++) or a pointer (C) to a UErrorCode
- * first test if(U_FAILURE(errorCode)) { return immediately; }
* so that in a chain of such functions the first one that sets an error code
* causes the following ones to not perform any operations.
*
- * \par
- * Error codes should be tested using U_FAILURE() and U_SUCCESS().
* @stable ICU 2.0
*/
typedef enum UErrorCode {
diff -Nru icu-64.2/source/common/unicode/uvernum.h icu-65.1/source/common/unicode/uvernum.h
--- icu-64.2/source/common/unicode/uvernum.h 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/unicode/uvernum.h 2019-10-03 11:16:41.000000000 +0000
@@ -60,13 +60,13 @@
* This value will change in the subsequent releases of ICU
* @stable ICU 2.4
*/
-#define U_ICU_VERSION_MAJOR_NUM 64
+#define U_ICU_VERSION_MAJOR_NUM 65
/** The current ICU minor version as an integer.
* This value will change in the subsequent releases of ICU
* @stable ICU 2.6
*/
-#define U_ICU_VERSION_MINOR_NUM 2
+#define U_ICU_VERSION_MINOR_NUM 1
/** The current ICU patchlevel version as an integer.
* This value will change in the subsequent releases of ICU
@@ -86,7 +86,7 @@
* This value will change in the subsequent releases of ICU
* @stable ICU 2.6
*/
-#define U_ICU_VERSION_SUFFIX _64
+#define U_ICU_VERSION_SUFFIX _65
/**
* \def U_DEF2_ICU_ENTRY_POINT_RENAME
@@ -139,7 +139,7 @@
* This value will change in the subsequent releases of ICU
* @stable ICU 2.4
*/
-#define U_ICU_VERSION "64.2"
+#define U_ICU_VERSION "65.1"
/**
* The current ICU library major version number as a string, for library name suffixes.
@@ -152,13 +152,13 @@
*
* @stable ICU 2.6
*/
-#define U_ICU_VERSION_SHORT "64"
+#define U_ICU_VERSION_SHORT "65"
#ifndef U_HIDE_INTERNAL_API
/** Data version in ICU4C.
* @internal ICU 4.4 Internal Use Only
**/
-#define U_ICU_DATA_VERSION "64.2"
+#define U_ICU_DATA_VERSION "65.1"
#endif /* U_HIDE_INTERNAL_API */
/*===========================================================================
diff -Nru icu-64.2/source/common/unicode/uversion.h icu-65.1/source/common/unicode/uversion.h
--- icu-64.2/source/common/unicode/uversion.h 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/unicode/uversion.h 2019-10-03 11:16:41.000000000 +0000
@@ -62,26 +62,22 @@
/* C++ namespace if supported. Versioned unless versioning is disabled. */
/*===========================================================================*/
+/* Define C++ namespace symbols. */
+#ifdef __cplusplus
+
/**
* \def U_NAMESPACE_BEGIN
- * This is used to begin a declaration of a public ICU C++ API.
- * When not compiling for C++, it does nothing.
- * When compiling for C++, it begins an extern "C++" linkage block (to protect
- * against cases in which an external client includes ICU header files inside
- * an extern "C" linkage block).
+ * This is used to begin a declaration of a public ICU C++ API within
+ * versioned-ICU-namespace block.
*
- * It also begins a versioned-ICU-namespace block.
* @stable ICU 2.4
*/
/**
* \def U_NAMESPACE_END
* This is used to end a declaration of a public ICU C++ API.
- * When not compiling for C++, it does nothing.
- * When compiling for C++, it ends the extern "C++" block begun by
- * U_NAMESPACE_BEGIN.
+ * It ends the versioned-ICU-namespace block begun by U_NAMESPACE_BEGIN.
*
- * It also ends the versioned-ICU-namespace block begun by U_NAMESPACE_BEGIN.
* @stable ICU 2.4
*/
@@ -89,9 +85,6 @@
* \def U_NAMESPACE_USE
* This is used to specify that the rest of the code uses the
* public ICU C++ API namespace.
- * This is invoked by default; we recommend that you turn it off:
- * See the "Recommended Build Options" section of the ICU4C readme
- * (http://source.icu-project.org/repos/icu/icu/trunk/readme.html#RecBuild)
* @stable ICU 2.4
*/
@@ -105,8 +98,6 @@
* @stable ICU 2.4
*/
-/* Define C++ namespace symbols. */
-#ifdef __cplusplus
# if U_DISABLE_RENAMING
# define U_ICU_NAMESPACE icu
namespace U_ICU_NAMESPACE { }
@@ -116,8 +107,8 @@
namespace icu = U_ICU_NAMESPACE;
# endif
-# define U_NAMESPACE_BEGIN extern "C++" { namespace U_ICU_NAMESPACE {
-# define U_NAMESPACE_END } }
+# define U_NAMESPACE_BEGIN namespace U_ICU_NAMESPACE {
+# define U_NAMESPACE_END }
# define U_NAMESPACE_USE using namespace U_ICU_NAMESPACE;
# define U_NAMESPACE_QUALIFIER U_ICU_NAMESPACE::
@@ -133,12 +124,7 @@
# if U_USING_ICU_NAMESPACE
U_NAMESPACE_USE
# endif
-#else
-# define U_NAMESPACE_BEGIN
-# define U_NAMESPACE_END
-# define U_NAMESPACE_USE
-# define U_NAMESPACE_QUALIFIER
-#endif
+#endif /* __cplusplus */
/*===========================================================================*/
/* General version helper functions. Definitions in putil.c */
diff -Nru icu-64.2/source/common/unifiedcache.cpp icu-65.1/source/common/unifiedcache.cpp
--- icu-64.2/source/common/unifiedcache.cpp 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/unifiedcache.cpp 2019-10-03 11:16:41.000000000 +0000
@@ -13,22 +13,15 @@
#include "unifiedcache.h"
#include // For std::max()
+#include
-#include "mutex.h"
#include "uassert.h"
#include "uhash.h"
#include "ucln_cmn.h"
-#include "umutex.h"
static icu::UnifiedCache *gCache = NULL;
-static icu::UMutex *gCacheMutex() {
- static icu::UMutex m = U_MUTEX_INITIALIZER;
- return &m;
-}
-static icu::UConditionVar *gInProgressValueAddedCond() {
- static icu::UConditionVar cv = U_CONDITION_INITIALIZER;
- return &cv;
-}
+static std::mutex *gCacheMutex = nullptr;
+static std::condition_variable *gInProgressValueAddedCond;
static icu::UInitOnce gCacheInitOnce = U_INITONCE_INITIALIZER;
static const int32_t MAX_EVICT_ITERATIONS = 10;
@@ -39,10 +32,12 @@
U_CDECL_BEGIN
static UBool U_CALLCONV unifiedcache_cleanup() {
gCacheInitOnce.reset();
- if (gCache) {
- delete gCache;
- gCache = NULL;
- }
+ delete gCache;
+ gCache = nullptr;
+ gCacheMutex->~mutex();
+ gCacheMutex = nullptr;
+ gInProgressValueAddedCond->~condition_variable();
+ gInProgressValueAddedCond = nullptr;
return TRUE;
}
U_CDECL_END
@@ -77,6 +72,8 @@
ucln_common_registerCleanup(
UCLN_COMMON_UNIFIED_CACHE, unifiedcache_cleanup);
+ gCacheMutex = STATIC_NEW(std::mutex);
+ gInProgressValueAddedCond = STATIC_NEW(std::condition_variable);
gCache = new UnifiedCache(status);
if (gCache == NULL) {
status = U_MEMORY_ALLOCATION_ERROR;
@@ -138,28 +135,28 @@
status = U_ILLEGAL_ARGUMENT_ERROR;
return;
}
- Mutex lock(gCacheMutex());
+ std::lock_guard lock(*gCacheMutex);
fMaxUnused = count;
fMaxPercentageOfInUse = percentageOfInUseItems;
}
int32_t UnifiedCache::unusedCount() const {
- Mutex lock(gCacheMutex());
+ std::lock_guard lock(*gCacheMutex);
return uhash_count(fHashtable) - fNumValuesInUse;
}
int64_t UnifiedCache::autoEvictedCount() const {
- Mutex lock(gCacheMutex());
+ std::lock_guard lock(*gCacheMutex);
return fAutoEvictedCount;
}
int32_t UnifiedCache::keyCount() const {
- Mutex lock(gCacheMutex());
+ std::lock_guard lock(*gCacheMutex);
return uhash_count(fHashtable);
}
void UnifiedCache::flush() const {
- Mutex lock(gCacheMutex());
+ std::lock_guard lock(*gCacheMutex);
// Use a loop in case cache items that are flushed held hard references to
// other cache items making those additional cache items eligible for
@@ -168,7 +165,7 @@
}
void UnifiedCache::handleUnreferencedObject() const {
- Mutex lock(gCacheMutex());
+ std::lock_guard lock(*gCacheMutex);
--fNumValuesInUse;
_runEvictionSlice();
}
@@ -187,7 +184,7 @@
}
void UnifiedCache::dumpContents() const {
- Mutex lock(gCacheMutex());
+ std::lock_guard lock(*gCacheMutex);
_dumpContents();
}
@@ -227,7 +224,7 @@
// Now all that should be left in the cache are entries that refer to
// each other and entries with hard references from outside the cache.
// Nothing we can do about these so proceed to wipe out the cache.
- Mutex lock(gCacheMutex());
+ std::lock_guard lock(*gCacheMutex);
_flush(TRUE);
}
uhash_close(fHashtable);
@@ -328,7 +325,7 @@
const CacheKeyBase &key,
const SharedObject *&value,
UErrorCode &status) const {
- Mutex lock(gCacheMutex());
+ std::lock_guard lock(*gCacheMutex);
const UHashElement *element = uhash_find(fHashtable, &key);
if (element != NULL && !_inProgress(element)) {
_fetch(element, value, status);
@@ -353,15 +350,15 @@
UErrorCode &status) const {
U_ASSERT(value == NULL);
U_ASSERT(status == U_ZERO_ERROR);
- Mutex lock(gCacheMutex());
+ std::unique_lock lock(*gCacheMutex);
const UHashElement *element = uhash_find(fHashtable, &key);
// If the hash table contains an inProgress placeholder entry for this key,
// this means that another thread is currently constructing the value object.
// Loop, waiting for that construction to complete.
while (element != NULL && _inProgress(element)) {
- umtx_condWait(gInProgressValueAddedCond(), gCacheMutex());
- element = uhash_find(fHashtable, &key);
+ gInProgressValueAddedCond->wait(lock);
+ element = uhash_find(fHashtable, &key);
}
// If the hash table contains an entry for the key,
@@ -433,7 +430,7 @@
// Tell waiting threads that we replace in-progress status with
// an error.
- umtx_condBroadcast(gInProgressValueAddedCond());
+ gInProgressValueAddedCond->notify_all();
}
void UnifiedCache::_fetch(
diff -Nru icu-64.2/source/common/uniset.cpp icu-65.1/source/common/uniset.cpp
--- icu-64.2/source/common/uniset.cpp 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/uniset.cpp 2019-10-03 11:16:41.000000000 +0000
@@ -278,11 +278,11 @@
* to support cloning in order to allow classes using
* UnicodeMatchers, such as Transliterator, to implement cloning.
*/
-UnicodeFunctor* UnicodeSet::clone() const {
+UnicodeSet* UnicodeSet::clone() const {
return new UnicodeSet(*this);
}
-UnicodeFunctor *UnicodeSet::cloneAsThawed() const {
+UnicodeSet *UnicodeSet::cloneAsThawed() const {
return new UnicodeSet(*this, TRUE);
}
@@ -2172,7 +2172,7 @@
// We can regenerate an equivalent pattern later when requested.
}
-UnicodeFunctor *UnicodeSet::freeze() {
+UnicodeSet *UnicodeSet::freeze() {
if(!isFrozen() && !isBogus()) {
compact();
diff -Nru icu-64.2/source/common/uniset_props.cpp icu-65.1/source/common/uniset_props.cpp
--- icu-64.2/source/common/uniset_props.cpp 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/uniset_props.cpp 2019-10-03 11:16:41.000000000 +0000
@@ -802,7 +802,10 @@
// Property set API
//----------------------------------------------------------------
-#define FAIL(ec) {ec=U_ILLEGAL_ARGUMENT_ERROR; return *this;}
+#define FAIL(ec) UPRV_BLOCK_MACRO_BEGIN { \
+ ec=U_ILLEGAL_ARGUMENT_ERROR; \
+ return *this; \
+} UPRV_BLOCK_MACRO_END
UnicodeSet&
UnicodeSet::applyIntPropertyValue(UProperty prop, int32_t value, UErrorCode& ec) {
diff -Nru icu-64.2/source/common/unisetspan.cpp icu-65.1/source/common/unisetspan.cpp
--- icu-64.2/source/common/unisetspan.cpp 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/unisetspan.cpp 2019-10-03 11:16:41.000000000 +0000
@@ -400,7 +400,7 @@
if(otherStringSpan.pSpanNotSet==&otherStringSpan.spanSet) {
pSpanNotSet=&spanSet;
} else {
- pSpanNotSet=(UnicodeSet *)otherStringSpan.pSpanNotSet->clone();
+ pSpanNotSet=otherStringSpan.pSpanNotSet->clone();
}
// Allocate a block of meta data.
@@ -436,7 +436,7 @@
if(spanSet.contains(c)) {
return; // Nothing to do.
}
- UnicodeSet *newSet=(UnicodeSet *)spanSet.cloneAsThawed();
+ UnicodeSet *newSet=spanSet.cloneAsThawed();
if(newSet==NULL) {
return; // Out of memory.
} else {
diff -Nru icu-64.2/source/common/unistr.cpp icu-65.1/source/common/unistr.cpp
--- icu-64.2/source/common/unistr.cpp 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/unistr.cpp 2019-10-03 11:16:41.000000000 +0000
@@ -332,7 +332,7 @@
}
// UnicodeString overrides clone() with a real implementation
-Replaceable *
+UnicodeString *
UnicodeString::clone() const {
return new UnicodeString(*this);
}
diff -Nru icu-64.2/source/common/uresbund.cpp icu-65.1/source/common/uresbund.cpp
--- icu-64.2/source/common/uresbund.cpp 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/uresbund.cpp 2019-10-03 11:16:41.000000000 +0000
@@ -31,6 +31,7 @@
#include "ucln_cmn.h"
#include "cmemory.h"
#include "cstring.h"
+#include "mutex.h"
#include "uhash.h"
#include "unicode/uenum.h"
#include "uenumimp.h"
@@ -38,6 +39,7 @@
#include "umutex.h"
#include "putilimp.h"
#include "uassert.h"
+#include "uresdata.h"
using namespace icu;
@@ -47,12 +49,9 @@
completely removed.
*/
static UHashtable *cache = NULL;
-static icu::UInitOnce gCacheInitOnce;
+static icu::UInitOnce gCacheInitOnce = U_INITONCE_INITIALIZER;
-static UMutex *resbMutex() {
- static UMutex m = U_MUTEX_INITIALIZER;
- return &m;
-}
+static UMutex resbMutex;
/* INTERNAL: hashes an entry */
static int32_t U_CALLCONV hashEntry(const UHashTok parm) {
@@ -96,13 +95,12 @@
* Internal function
*/
static void entryIncrease(UResourceDataEntry *entry) {
- umtx_lock(resbMutex());
+ Mutex lock(&resbMutex);
entry->fCountExisting++;
while(entry->fParent != NULL) {
entry = entry->fParent;
entry->fCountExisting++;
}
- umtx_unlock(resbMutex());
}
/**
@@ -184,9 +182,8 @@
/*if shared data hasn't even been lazy evaluated yet
* return 0
*/
- umtx_lock(resbMutex());
+ Mutex lock(&resbMutex);
if (cache == NULL) {
- umtx_unlock(resbMutex());
return 0;
}
@@ -218,7 +215,6 @@
* got decremented by free_entry().
*/
} while(deletedMore);
- umtx_unlock(resbMutex());
return rbDeletedNum;
}
@@ -232,9 +228,8 @@
const UHashElement *e;
UResourceDataEntry *resB;
- umtx_lock(resbMutex());
+ Mutex lock(&resbMutex);
if (cache == NULL) {
- umtx_unlock(resbMutex());
fprintf(stderr,"%s:%d: RB Cache is NULL.\n", __FILE__, __LINE__);
return FALSE;
}
@@ -253,9 +248,6 @@
}
fprintf(stderr,"%s:%d: RB Cache still contains %d items.\n", __FILE__, __LINE__, uhash_count(cache));
-
- umtx_unlock(resbMutex());
-
return cacheNotEmpty;
}
@@ -401,7 +393,8 @@
/* We'll try to get alias string from the bundle */
aliasres = res_getResource(&(r->fData), "%%ALIAS");
if (aliasres != RES_BOGUS) {
- const UChar *alias = res_getString(&(r->fData), aliasres, &aliasLen);
+ // No tracing: called during initial data loading
+ const UChar *alias = res_getStringNoTrace(&(r->fData), aliasres, &aliasLen);
if(alias != NULL && aliasLen > 0) { /* if there is actual alias - unload and load new data */
u_UCharsToChars(alias, aliasName, aliasLen+1);
r->fAlias = init_entry(aliasName, path, status);
@@ -542,7 +535,8 @@
Resource parentRes = res_getResource(&t1->fData, "%%Parent");
if (parentRes != RES_BOGUS) { // An explicit parent was found.
int32_t parentLocaleLen = 0;
- const UChar *parentLocaleName = res_getString(&(t1->fData), parentRes, &parentLocaleLen);
+ // No tracing: called during initial data loading
+ const UChar *parentLocaleName = res_getStringNoTrace(&(t1->fData), parentRes, &parentLocaleLen);
if(parentLocaleName != NULL && 0 < parentLocaleLen && parentLocaleLen < nameCapacity) {
u_UCharsToChars(parentLocaleName, name, parentLocaleLen + 1);
if (uprv_strcmp(name, kRootLocaleName) == 0) {
@@ -666,107 +660,105 @@
}
}
- umtx_lock(resbMutex());
- { /* umtx_lock */
- /* We're going to skip all the locales that do not have any data */
- r = findFirstExisting(path, name, &isRoot, &hasChopped, &isDefault, &intStatus);
+ Mutex lock(&resbMutex); // Lock resbMutex until the end of this function.
+
+ /* We're going to skip all the locales that do not have any data */
+ r = findFirstExisting(path, name, &isRoot, &hasChopped, &isDefault, &intStatus);
+ // If we failed due to out-of-memory, report the failure and exit early.
+ if (intStatus == U_MEMORY_ALLOCATION_ERROR) {
+ *status = intStatus;
+ goto finish;
+ }
+
+ if(r != NULL) { /* if there is one real locale, we can look for parents. */
+ t1 = r;
+ hasRealData = TRUE;
+ if ( usingUSRData ) { /* This code inserts user override data into the inheritance chain */
+ UErrorCode usrStatus = U_ZERO_ERROR;
+ UResourceDataEntry *u1 = init_entry(t1->fName, usrDataPath, &usrStatus);
+ // If we failed due to out-of-memory, report the failure and exit early.
+ if (intStatus == U_MEMORY_ALLOCATION_ERROR) {
+ *status = intStatus;
+ goto finish;
+ }
+ if ( u1 != NULL ) {
+ if(u1->fBogus == U_ZERO_ERROR) {
+ u1->fParent = t1;
+ r = u1;
+ } else {
+ /* the USR override data wasn't found, set it to be deleted */
+ u1->fCountExisting = 0;
+ }
+ }
+ }
+ if (hasChopped && !isRoot) {
+ if (!loadParentsExceptRoot(t1, name, UPRV_LENGTHOF(name), usingUSRData, usrDataPath, status)) {
+ goto finish;
+ }
+ }
+ }
+
+ /* we could have reached this point without having any real data */
+ /* if that is the case, we need to chain in the default locale */
+ if(r==NULL && openType == URES_OPEN_LOCALE_DEFAULT_ROOT && !isDefault && !isRoot) {
+ /* insert default locale */
+ uprv_strcpy(name, uloc_getDefault());
+ r = findFirstExisting(path, name, &isRoot, &hasChopped, &isDefault, &intStatus);
// If we failed due to out-of-memory, report the failure and exit early.
if (intStatus == U_MEMORY_ALLOCATION_ERROR) {
*status = intStatus;
- goto finishUnlock;
+ goto finish;
}
-
- if(r != NULL) { /* if there is one real locale, we can look for parents. */
+ intStatus = U_USING_DEFAULT_WARNING;
+ if(r != NULL) { /* the default locale exists */
t1 = r;
hasRealData = TRUE;
- if ( usingUSRData ) { /* This code inserts user override data into the inheritance chain */
- UErrorCode usrStatus = U_ZERO_ERROR;
- UResourceDataEntry *u1 = init_entry(t1->fName, usrDataPath, &usrStatus);
- // If we failed due to out-of-memory, report the failure and exit early.
- if (intStatus == U_MEMORY_ALLOCATION_ERROR) {
- *status = intStatus;
- goto finishUnlock;
- }
- if ( u1 != NULL ) {
- if(u1->fBogus == U_ZERO_ERROR) {
- u1->fParent = t1;
- r = u1;
- } else {
- /* the USR override data wasn't found, set it to be deleted */
- u1->fCountExisting = 0;
- }
- }
- }
+ isDefault = TRUE;
+ // TODO: Why not if (usingUSRData) { ... } like in the non-default-locale code path?
if (hasChopped && !isRoot) {
if (!loadParentsExceptRoot(t1, name, UPRV_LENGTHOF(name), usingUSRData, usrDataPath, status)) {
- goto finishUnlock;
+ goto finish;
}
}
}
+ }
- /* we could have reached this point without having any real data */
- /* if that is the case, we need to chain in the default locale */
- if(r==NULL && openType == URES_OPEN_LOCALE_DEFAULT_ROOT && !isDefault && !isRoot) {
- /* insert default locale */
- uprv_strcpy(name, uloc_getDefault());
- r = findFirstExisting(path, name, &isRoot, &hasChopped, &isDefault, &intStatus);
- // If we failed due to out-of-memory, report the failure and exit early.
- if (intStatus == U_MEMORY_ALLOCATION_ERROR) {
- *status = intStatus;
- goto finishUnlock;
- }
+ /* we could still have r == NULL at this point - maybe even default locale is not */
+ /* present */
+ if(r == NULL) {
+ uprv_strcpy(name, kRootLocaleName);
+ r = findFirstExisting(path, name, &isRoot, &hasChopped, &isDefault, &intStatus);
+ // If we failed due to out-of-memory, report the failure and exit early.
+ if (intStatus == U_MEMORY_ALLOCATION_ERROR) {
+ *status = intStatus;
+ goto finish;
+ }
+ if(r != NULL) {
+ t1 = r;
intStatus = U_USING_DEFAULT_WARNING;
- if(r != NULL) { /* the default locale exists */
- t1 = r;
- hasRealData = TRUE;
- isDefault = TRUE;
- // TODO: Why not if (usingUSRData) { ... } like in the non-default-locale code path?
- if (hasChopped && !isRoot) {
- if (!loadParentsExceptRoot(t1, name, UPRV_LENGTHOF(name), usingUSRData, usrDataPath, status)) {
- goto finishUnlock;
- }
- }
- }
+ hasRealData = TRUE;
+ } else { /* we don't even have the root locale */
+ *status = U_MISSING_RESOURCE_ERROR;
+ goto finish;
}
-
- /* we could still have r == NULL at this point - maybe even default locale is not */
- /* present */
- if(r == NULL) {
- uprv_strcpy(name, kRootLocaleName);
- r = findFirstExisting(path, name, &isRoot, &hasChopped, &isDefault, &intStatus);
- // If we failed due to out-of-memory, report the failure and exit early.
- if (intStatus == U_MEMORY_ALLOCATION_ERROR) {
- *status = intStatus;
- goto finishUnlock;
- }
- if(r != NULL) {
- t1 = r;
- intStatus = U_USING_DEFAULT_WARNING;
- hasRealData = TRUE;
- } else { /* we don't even have the root locale */
- *status = U_MISSING_RESOURCE_ERROR;
- goto finishUnlock;
- }
- } else if(!isRoot && uprv_strcmp(t1->fName, kRootLocaleName) != 0 &&
- t1->fParent == NULL && !r->fData.noFallback) {
- if (!insertRootBundle(t1, status)) {
- goto finishUnlock;
- }
- if(!hasRealData) {
- r->fBogus = U_USING_DEFAULT_WARNING;
- }
+ } else if(!isRoot && uprv_strcmp(t1->fName, kRootLocaleName) != 0 &&
+ t1->fParent == NULL && !r->fData.noFallback) {
+ if (!insertRootBundle(t1, status)) {
+ goto finish;
}
-
- // TODO: Does this ever loop?
- while(r != NULL && !isRoot && t1->fParent != NULL) {
- t1->fParent->fCountExisting++;
- t1 = t1->fParent;
+ if(!hasRealData) {
+ r->fBogus = U_USING_DEFAULT_WARNING;
}
- } /* umtx_lock */
-finishUnlock:
- umtx_unlock(resbMutex());
+ }
+
+ // TODO: Does this ever loop?
+ while(r != NULL && !isRoot && t1->fParent != NULL) {
+ t1->fParent->fCountExisting++;
+ t1 = t1->fParent;
+ }
+finish:
if(U_SUCCESS(*status)) {
if(intStatus != U_ZERO_ERROR) {
*status = intStatus;
@@ -790,7 +782,7 @@
return NULL;
}
- umtx_lock(resbMutex());
+ Mutex lock(&resbMutex);
// findFirstExisting() without fallbacks.
UResourceDataEntry *r = init_entry(localeID, path, status);
if(U_SUCCESS(*status)) {
@@ -828,7 +820,6 @@
t1 = t1->fParent;
}
}
- umtx_unlock(resbMutex());
return r;
}
@@ -871,9 +862,8 @@
*/
static void entryClose(UResourceDataEntry *resB) {
- umtx_lock(resbMutex());
+ Mutex lock(&resbMutex);
entryCloseInt(resB);
- umtx_unlock(resbMutex());
}
/*
@@ -1177,6 +1167,7 @@
if(mainRes != result) {
ures_close(mainRes);
}
+ ResourceTracer(resB).maybeTrace("getalias");
return result;
}
} else {
@@ -1256,6 +1247,7 @@
/*resB->fParent = parent->fRes;*/
uprv_memmove(&resB->fResData, rdata, sizeof(ResourceData));
resB->fSize = res_countArrayItems(&(resB->fResData), resB->fRes);
+ ResourceTracer(resB).trace("get");
return resB;
}
@@ -1304,7 +1296,7 @@
*status = U_ILLEGAL_ARGUMENT_ERROR;
return NULL;
}
- s = res_getString(&(resB->fResData), resB->fRes, len);
+ s = res_getString({resB}, &(resB->fResData), resB->fRes, len);
if (s == NULL) {
*status = U_RESOURCE_TYPE_MISMATCH;
}
@@ -1393,7 +1385,7 @@
*status = U_ILLEGAL_ARGUMENT_ERROR;
return NULL;
}
- p = res_getBinary(&(resB->fResData), resB->fRes, len);
+ p = res_getBinary({resB}, &(resB->fResData), resB->fRes, len);
if (p == NULL) {
*status = U_RESOURCE_TYPE_MISMATCH;
}
@@ -1410,7 +1402,7 @@
*status = U_ILLEGAL_ARGUMENT_ERROR;
return NULL;
}
- p = res_getIntVector(&(resB->fResData), resB->fRes, len);
+ p = res_getIntVector({resB}, &(resB->fResData), resB->fRes, len);
if (p == NULL) {
*status = U_RESOURCE_TYPE_MISMATCH;
}
@@ -1431,7 +1423,7 @@
*status = U_RESOURCE_TYPE_MISMATCH;
return 0xffffffff;
}
- return RES_GET_INT(resB->fRes);
+ return res_getInt({resB}, resB->fRes);
}
U_CAPI uint32_t U_EXPORT2 ures_getUInt(const UResourceBundle* resB, UErrorCode *status) {
@@ -1446,7 +1438,7 @@
*status = U_RESOURCE_TYPE_MISMATCH;
return 0xffffffff;
}
- return RES_GET_UINT(resB->fRes);
+ return res_getUInt({resB}, resB->fRes);
}
U_CAPI UResType U_EXPORT2 ures_getType(const UResourceBundle *resB) {
@@ -1457,10 +1449,18 @@
}
U_CAPI const char * U_EXPORT2 ures_getKey(const UResourceBundle *resB) {
+ //
+ // TODO: Trace ures_getKey? I guess not usually.
+ //
+ // We usually get the key string to decide whether we want the value, or to
+ // make a key-value pair. Tracing the value should suffice.
+ //
+ // However, I believe we have some data (e.g., in res_index) where the key
+ // strings are the data. Tracing the enclosing table should suffice.
+ //
if(resB == NULL) {
return NULL;
}
-
return(resB->fKey);
}
@@ -1480,7 +1480,7 @@
ures_close(tempRes);
return result;
} else {
- return res_getString(&(resB->fResData), r, len);
+ return res_getString({resB, sIndex}, &(resB->fResData), r, len);
}
}
@@ -1516,7 +1516,7 @@
switch(RES_GET_TYPE(resB->fRes)) {
case URES_STRING:
case URES_STRING_V2:
- return res_getString(&(resB->fResData), resB->fRes, len);
+ return res_getString({resB}, &(resB->fResData), resB->fRes, len);
case URES_TABLE:
case URES_TABLE16:
case URES_TABLE32:
@@ -1661,7 +1661,7 @@
switch(RES_GET_TYPE(resB->fRes)) {
case URES_STRING:
case URES_STRING_V2:
- return res_getString(&(resB->fResData), resB->fRes, len);
+ return res_getString({resB}, &(resB->fResData), resB->fRes, len);
case URES_TABLE:
case URES_TABLE16:
case URES_TABLE32:
@@ -1953,10 +1953,10 @@
// When the sink sees the no-fallback/no-inheritance marker,
// then it would remove the parent's item.
// We would deserialize parent values even though they are overridden in a child bundle.
- value.pResData = &bundle->fResData;
+ value.setData(&bundle->fResData);
UResourceDataEntry *parentEntry = bundle->fData->fParent;
UBool hasParent = parentEntry != NULL && U_SUCCESS(parentEntry->fBogus);
- value.setResource(bundle->fRes);
+ value.setResource(bundle->fRes, ResourceTracer(bundle));
sink.put(bundle->fKey, value, !hasParent, errorCode);
if (hasParent) {
// We might try to query the sink whether
@@ -2001,31 +2001,60 @@
} // namespace
+// Requires a ResourceDataValue fill-in, so that we need not cast from a ResourceValue.
+// Unfortunately, the caller must know which subclass to make and pass in.
+// Alternatively, we could make it as polymorphic as in Java by
+// returning a ResourceValue pointer (possibly wrapped into a LocalPointer)
+// that the caller then owns.
+//
+// Also requires a UResourceBundle fill-in, so that the value's ResourceTracer
+// can point to a non-local bundle.
+// Without tracing, the child bundle could be a function-local object.
+U_CAPI void U_EXPORT2
+ures_getValueWithFallback(const UResourceBundle *bundle, const char *path,
+ UResourceBundle *tempFillIn,
+ ResourceDataValue &value, UErrorCode &errorCode) {
+ if (U_FAILURE(errorCode)) { return; }
+ if (path == nullptr) {
+ errorCode = U_ILLEGAL_ARGUMENT_ERROR;
+ return;
+ }
+ const UResourceBundle *rb;
+ if (*path == 0) {
+ // empty path
+ rb = bundle;
+ } else {
+ rb = ures_getByKeyWithFallback(bundle, path, tempFillIn, &errorCode);
+ if (U_FAILURE(errorCode)) {
+ return;
+ }
+ }
+ value.setData(&rb->fResData);
+ value.setResource(rb->fRes, ResourceTracer(rb));
+}
+
U_CAPI void U_EXPORT2
ures_getAllItemsWithFallback(const UResourceBundle *bundle, const char *path,
icu::ResourceSink &sink, UErrorCode &errorCode) {
if (U_FAILURE(errorCode)) { return; }
- if (path == NULL) {
+ if (path == nullptr) {
errorCode = U_ILLEGAL_ARGUMENT_ERROR;
return;
}
- UResourceBundle stackBundle;
- ures_initStackObject(&stackBundle);
+ StackUResourceBundle stackBundle;
const UResourceBundle *rb;
if (*path == 0) {
// empty path
rb = bundle;
} else {
- rb = ures_getByKeyWithFallback(bundle, path, &stackBundle, &errorCode);
+ rb = ures_getByKeyWithFallback(bundle, path, stackBundle.getAlias(), &errorCode);
if (U_FAILURE(errorCode)) {
- ures_close(&stackBundle);
return;
}
}
// Get all table items with fallback.
ResourceDataValue value;
getAllItemsWithFallback(rb, value, sink, errorCode);
- ures_close(&stackBundle);
}
U_CAPI UResourceBundle* U_EXPORT2 ures_getByKey(const UResourceBundle *resB, const char* inKey, UResourceBundle *fillIn, UErrorCode *status) {
@@ -2108,7 +2137,7 @@
switch (RES_GET_TYPE(res)) {
case URES_STRING:
case URES_STRING_V2:
- return res_getString(rd, res, len);
+ return res_getString({resB, key}, rd, res, len);
case URES_ALIAS:
{
const UChar* result = 0;
@@ -2130,7 +2159,7 @@
switch (RES_GET_TYPE(res)) {
case URES_STRING:
case URES_STRING_V2:
- return res_getString(&(resB->fResData), res, len);
+ return res_getString({resB, key}, &(resB->fResData), res, len);
case URES_ALIAS:
{
const UChar* result = 0;
@@ -2151,6 +2180,7 @@
/* here should go a first attempt to locate the key using index table */
const ResourceData *rd = getFallbackData(resB, &key, &realData, &res, status);
if(U_SUCCESS(*status)) {
+ // TODO: Tracing
return res_getString(rd, res, len);
} else {
*status = U_MISSING_RESOURCE_ERROR;
@@ -2296,6 +2326,8 @@
r->fSize = res_countArrayItems(&(r->fResData), r->fRes);
r->fIndex = -1;
+ ResourceTracer(r).traceOpen();
+
return r;
}
diff -Nru icu-64.2/source/common/uresdata.cpp icu-65.1/source/common/uresdata.cpp
--- icu-64.2/source/common/uresdata.cpp 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/uresdata.cpp 2019-10-03 11:16:41.000000000 +0000
@@ -33,6 +33,7 @@
#include "uinvchar.h"
#include "uresdata.h"
#include "uresimp.h"
+#include "utracimp.h"
/*
* Resource access helpers
@@ -307,7 +308,7 @@
}
U_CAPI const UChar * U_EXPORT2
-res_getString(const ResourceData *pResData, Resource res, int32_t *pLength) {
+res_getStringNoTrace(const ResourceData *pResData, Resource res, int32_t *pLength) {
const UChar *p;
uint32_t offset=RES_GET_OFFSET(res);
int32_t length;
@@ -402,7 +403,8 @@
}
for(int32_t i = 0; i < length; ++i) {
int32_t sLength;
- const UChar *s = res_getString(pResData, array.internalGetResource(pResData, i), &sLength);
+ // No tracing: handled by the caller
+ const UChar *s = res_getStringNoTrace(pResData, array.internalGetResource(pResData, i), &sLength);
if(s == NULL) {
errorCode = U_RESOURCE_TYPE_MISMATCH;
return 0;
@@ -434,7 +436,7 @@
}
U_CAPI const uint8_t * U_EXPORT2
-res_getBinary(const ResourceData *pResData, Resource res, int32_t *pLength) {
+res_getBinaryNoTrace(const ResourceData *pResData, Resource res, int32_t *pLength) {
const uint8_t *p;
uint32_t offset=RES_GET_OFFSET(res);
int32_t length;
@@ -454,7 +456,7 @@
U_CAPI const int32_t * U_EXPORT2
-res_getIntVector(const ResourceData *pResData, Resource res, int32_t *pLength) {
+res_getIntVectorNoTrace(const ResourceData *pResData, Resource res, int32_t *pLength) {
const int32_t *p;
uint32_t offset=RES_GET_OFFSET(res);
int32_t length;
@@ -507,7 +509,7 @@
if(U_FAILURE(errorCode)) {
return NULL;
}
- const UChar *s = res_getString(pResData, res, &length);
+ const UChar *s = res_getString(fTraceInfo, &getData(), res, &length);
if(s == NULL) {
errorCode = U_RESOURCE_TYPE_MISMATCH;
}
@@ -518,7 +520,7 @@
if(U_FAILURE(errorCode)) {
return NULL;
}
- const UChar *s = res_getAlias(pResData, res, &length);
+ const UChar *s = res_getAlias(&getData(), res, &length);
if(s == NULL) {
errorCode = U_RESOURCE_TYPE_MISMATCH;
}
@@ -532,7 +534,7 @@
if(RES_GET_TYPE(res) != URES_INT) {
errorCode = U_RESOURCE_TYPE_MISMATCH;
}
- return RES_GET_INT(res);
+ return res_getInt(fTraceInfo, res);
}
uint32_t ResourceDataValue::getUInt(UErrorCode &errorCode) const {
@@ -542,14 +544,14 @@
if(RES_GET_TYPE(res) != URES_INT) {
errorCode = U_RESOURCE_TYPE_MISMATCH;
}
- return RES_GET_UINT(res);
+ return res_getUInt(fTraceInfo, res);
}
const int32_t *ResourceDataValue::getIntVector(int32_t &length, UErrorCode &errorCode) const {
if(U_FAILURE(errorCode)) {
return NULL;
}
- const int32_t *iv = res_getIntVector(pResData, res, &length);
+ const int32_t *iv = res_getIntVector(fTraceInfo, &getData(), res, &length);
if(iv == NULL) {
errorCode = U_RESOURCE_TYPE_MISMATCH;
}
@@ -560,7 +562,7 @@
if(U_FAILURE(errorCode)) {
return NULL;
}
- const uint8_t *b = res_getBinary(pResData, res, &length);
+ const uint8_t *b = res_getBinary(fTraceInfo, &getData(), res, &length);
if(b == NULL) {
errorCode = U_RESOURCE_TYPE_MISMATCH;
}
@@ -578,19 +580,19 @@
switch(RES_GET_TYPE(res)) {
case URES_ARRAY:
if (offset!=0) { // empty if offset==0
- items32 = (const Resource *)pResData->pRoot+offset;
+ items32 = (const Resource *)getData().pRoot+offset;
length = *items32++;
}
break;
case URES_ARRAY16:
- items16 = pResData->p16BitUnits+offset;
+ items16 = getData().p16BitUnits+offset;
length = *items16++;
break;
default:
errorCode = U_RESOURCE_TYPE_MISMATCH;
return ResourceArray();
}
- return ResourceArray(items16, items32, length);
+ return ResourceArray(items16, items32, length, fTraceInfo);
}
ResourceTable ResourceDataValue::getTable(UErrorCode &errorCode) const {
@@ -606,19 +608,19 @@
switch(RES_GET_TYPE(res)) {
case URES_TABLE:
if (offset != 0) { // empty if offset==0
- keys16 = (const uint16_t *)(pResData->pRoot+offset);
+ keys16 = (const uint16_t *)(getData().pRoot+offset);
length = *keys16++;
items32 = (const Resource *)(keys16+length+(~length&1));
}
break;
case URES_TABLE16:
- keys16 = pResData->p16BitUnits+offset;
+ keys16 = getData().p16BitUnits+offset;
length = *keys16++;
items16 = keys16 + length;
break;
case URES_TABLE32:
if (offset != 0) { // empty if offset==0
- keys32 = pResData->pRoot+offset;
+ keys32 = getData().pRoot+offset;
length = *keys32++;
items32 = (const Resource *)keys32 + length;
}
@@ -627,22 +629,22 @@
errorCode = U_RESOURCE_TYPE_MISMATCH;
return ResourceTable();
}
- return ResourceTable(keys16, keys32, items16, items32, length);
+ return ResourceTable(keys16, keys32, items16, items32, length, fTraceInfo);
}
UBool ResourceDataValue::isNoInheritanceMarker() const {
- return ::isNoInheritanceMarker(pResData, res);
+ return ::isNoInheritanceMarker(&getData(), res);
}
int32_t ResourceDataValue::getStringArray(UnicodeString *dest, int32_t capacity,
UErrorCode &errorCode) const {
- return ::getStringArray(pResData, getArray(errorCode), dest, capacity, errorCode);
+ return ::getStringArray(&getData(), getArray(errorCode), dest, capacity, errorCode);
}
int32_t ResourceDataValue::getStringArrayOrStringAsArray(UnicodeString *dest, int32_t capacity,
UErrorCode &errorCode) const {
if(URES_IS_ARRAY(res)) {
- return ::getStringArray(pResData, getArray(errorCode), dest, capacity, errorCode);
+ return ::getStringArray(&getData(), getArray(errorCode), dest, capacity, errorCode);
}
if(U_FAILURE(errorCode)) {
return 0;
@@ -656,7 +658,7 @@
return 1;
}
int32_t sLength;
- const UChar *s = res_getString(pResData, res, &sLength);
+ const UChar *s = res_getString(fTraceInfo, &getData(), res, &sLength);
if(s != NULL) {
dest[0].setTo(TRUE, s, sLength);
return 1;
@@ -671,7 +673,7 @@
return us;
}
int32_t sLength;
- const UChar *s = res_getString(pResData, res, &sLength);
+ const UChar *s = res_getString(fTraceInfo, &getData(), res, &sLength);
if(s != NULL) {
us.setTo(TRUE, s, sLength);
return us;
@@ -681,7 +683,8 @@
return us;
}
if(array.getSize() > 0) {
- s = res_getString(pResData, array.internalGetResource(pResData, 0), &sLength);
+ // Tracing is already performed above (unimportant for trace that this is an array)
+ s = res_getStringNoTrace(&getData(), array.internalGetResource(&getData(), 0), &sLength);
if(s != NULL) {
us.setTo(TRUE, s, sLength);
return us;
@@ -818,18 +821,45 @@
const char *&key, icu::ResourceValue &value) const {
if(0 <= i && i < length) {
icu::ResourceDataValue &rdValue = static_cast(value);
- if (keys16 != NULL) {
- key = RES_GET_KEY16(rdValue.pResData, keys16[i]);
+ if (keys16 != nullptr) {
+ key = RES_GET_KEY16(&rdValue.getData(), keys16[i]);
} else {
- key = RES_GET_KEY32(rdValue.pResData, keys32[i]);
+ key = RES_GET_KEY32(&rdValue.getData(), keys32[i]);
}
Resource res;
- if (items16 != NULL) {
- res = makeResourceFrom16(rdValue.pResData, items16[i]);
+ if (items16 != nullptr) {
+ res = makeResourceFrom16(&rdValue.getData(), items16[i]);
} else {
res = items32[i];
}
- rdValue.setResource(res);
+ // Note: the ResourceTracer keeps a reference to the field of this
+ // ResourceTable. This is OK because the ResourceTable should remain
+ // alive for the duration that fields are being read from it
+ // (including nested fields).
+ rdValue.setResource(res, ResourceTracer(fTraceInfo, key));
+ return TRUE;
+ }
+ return FALSE;
+}
+
+UBool icu::ResourceTable::findValue(const char *key, ResourceValue &value) const {
+ icu::ResourceDataValue &rdValue = static_cast(value);
+ const char *realKey = nullptr;
+ int32_t i;
+ if (keys16 != nullptr) {
+ i = _res_findTableItem(&rdValue.getData(), keys16, length, key, &realKey);
+ } else {
+ i = _res_findTable32Item(&rdValue.getData(), keys32, length, key, &realKey);
+ }
+ if (i >= 0) {
+ Resource res;
+ if (items16 != nullptr) {
+ res = makeResourceFrom16(&rdValue.getData(), items16[i]);
+ } else {
+ res = items32[i];
+ }
+ // Same note about lifetime as in getKeyAndValue().
+ rdValue.setResource(res, ResourceTracer(fTraceInfo, key));
return TRUE;
}
return FALSE;
@@ -875,7 +905,13 @@
UBool icu::ResourceArray::getValue(int32_t i, icu::ResourceValue &value) const {
if(0 <= i && i < length) {
icu::ResourceDataValue &rdValue = static_cast(value);
- rdValue.setResource(internalGetResource(rdValue.pResData, i));
+ // Note: the ResourceTracer keeps a reference to the field of this
+ // ResourceArray. This is OK because the ResourceArray should remain
+ // alive for the duration that fields are being read from it
+ // (including nested fields).
+ rdValue.setResource(
+ internalGetResource(&rdValue.getData(), i),
+ ResourceTracer(fTraceInfo, i));
return TRUE;
}
return FALSE;
diff -Nru icu-64.2/source/common/uresdata.h icu-65.1/source/common/uresdata.h
--- icu-64.2/source/common/uresdata.h 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/uresdata.h 2019-10-03 11:16:41.000000000 +0000
@@ -69,14 +69,16 @@
#define RES_GET_OFFSET(res) ((res)&0x0fffffff)
#define RES_GET_POINTER(pRoot, res) ((pRoot)+RES_GET_OFFSET(res))
-/* get signed and unsigned integer values directly from the Resource handle */
+/* get signed and unsigned integer values directly from the Resource handle
+ * NOTE: For proper logging, please use the res_getInt() constexpr
+ */
#if U_SIGNED_RIGHT_SHIFT_IS_ARITHMETIC
-# define RES_GET_INT(res) (((int32_t)((res)<<4L))>>4L)
+# define RES_GET_INT_NO_TRACE(res) (((int32_t)((res)<<4L))>>4L)
#else
-# define RES_GET_INT(res) (int32_t)(((res)&0x08000000) ? (res)|0xf0000000 : (res)&0x07ffffff)
+# define RES_GET_INT_NO_TRACE(res) (int32_t)(((res)&0x08000000) ? (res)|0xf0000000 : (res)&0x07ffffff)
#endif
-#define RES_GET_UINT(res) ((res)&0x0fffffff)
+#define RES_GET_UINT_NO_TRACE(res) ((res)&0x0fffffff)
#define URES_IS_ARRAY(type) ((int32_t)(type)==URES_ARRAY || (int32_t)(type)==URES_ARRAY16)
#define URES_IS_TABLE(type) ((int32_t)(type)==URES_TABLE || (int32_t)(type)==URES_TABLE16 || (int32_t)(type)==URES_TABLE32)
@@ -423,22 +425,26 @@
U_INTERNAL UResType U_EXPORT2
res_getPublicType(Resource res);
+///////////////////////////////////////////////////////////////////////////
+// To enable tracing, use the inline versions of the res_get* functions. //
+///////////////////////////////////////////////////////////////////////////
+
/*
* Return a pointer to a zero-terminated, const UChar* string
* and set its length in *pLength.
* Returns NULL if not found.
*/
U_INTERNAL const UChar * U_EXPORT2
-res_getString(const ResourceData *pResData, Resource res, int32_t *pLength);
-
-U_INTERNAL const UChar * U_EXPORT2
-res_getAlias(const ResourceData *pResData, Resource res, int32_t *pLength);
+res_getStringNoTrace(const ResourceData *pResData, Resource res, int32_t *pLength);
U_INTERNAL const uint8_t * U_EXPORT2
-res_getBinary(const ResourceData *pResData, Resource res, int32_t *pLength);
+res_getBinaryNoTrace(const ResourceData *pResData, Resource res, int32_t *pLength);
U_INTERNAL const int32_t * U_EXPORT2
-res_getIntVector(const ResourceData *pResData, Resource res, int32_t *pLength);
+res_getIntVectorNoTrace(const ResourceData *pResData, Resource res, int32_t *pLength);
+
+U_INTERNAL const UChar * U_EXPORT2
+res_getAlias(const ResourceData *pResData, Resource res, int32_t *pLength);
U_INTERNAL Resource U_EXPORT2
res_getResource(const ResourceData *pResData, const char *key);
@@ -470,17 +476,55 @@
#ifdef __cplusplus
#include "resource.h"
+#include "restrace.h"
U_NAMESPACE_BEGIN
+inline const UChar* res_getString(const ResourceTracer& traceInfo,
+ const ResourceData *pResData, Resource res, int32_t *pLength) {
+ traceInfo.trace("string");
+ return res_getStringNoTrace(pResData, res, pLength);
+}
+
+inline const uint8_t* res_getBinary(const ResourceTracer& traceInfo,
+ const ResourceData *pResData, Resource res, int32_t *pLength) {
+ traceInfo.trace("binary");
+ return res_getBinaryNoTrace(pResData, res, pLength);
+}
+
+inline const int32_t* res_getIntVector(const ResourceTracer& traceInfo,
+ const ResourceData *pResData, Resource res, int32_t *pLength) {
+ traceInfo.trace("intvector");
+ return res_getIntVectorNoTrace(pResData, res, pLength);
+}
+
+inline int32_t res_getInt(const ResourceTracer& traceInfo, Resource res) {
+ traceInfo.trace("int");
+ return RES_GET_INT_NO_TRACE(res);
+}
+
+inline uint32_t res_getUInt(const ResourceTracer& traceInfo, Resource res) {
+ traceInfo.trace("uint");
+ return RES_GET_UINT_NO_TRACE(res);
+}
+
class ResourceDataValue : public ResourceValue {
public:
- ResourceDataValue() : pResData(NULL), res(static_cast(URES_NONE)) {}
+ ResourceDataValue() :
+ res(static_cast(URES_NONE)),
+ fTraceInfo() {}
virtual ~ResourceDataValue();
- void setData(const ResourceData *data) { pResData = data; }
- void setResource(Resource r) { res = r; }
+ void setData(const ResourceData *data) {
+ resData = *data;
+ }
+
+ void setResource(Resource r, ResourceTracer&& traceInfo) {
+ res = r;
+ fTraceInfo = traceInfo;
+ }
+ const ResourceData &getData() const { return resData; }
virtual UResType getType() const;
virtual const UChar *getString(int32_t &length, UErrorCode &errorCode) const;
virtual const UChar *getAliasString(int32_t &length, UErrorCode &errorCode) const;
@@ -497,10 +541,12 @@
UErrorCode &errorCode) const;
virtual UnicodeString getStringOrFirstOfArray(UErrorCode &errorCode) const;
- const ResourceData *pResData;
-
private:
+ // TODO(ICU-20769): If UResourceBundle.fResData becomes a pointer,
+ // then remove this value field again and just store a pResData pointer.
+ ResourceData resData;
Resource res;
+ ResourceTracer fTraceInfo;
};
U_NAMESPACE_END
diff -Nru icu-64.2/source/common/uresimp.h icu-65.1/source/common/uresimp.h
--- icu-64.2/source/common/uresimp.h 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/uresimp.h 2019-10-03 11:16:41.000000000 +0000
@@ -67,6 +67,9 @@
char *fVersion;
UResourceDataEntry *fTopLevelData; /* for getting the valid locale */
char *fResPath; /* full path to the resource: "zh_TW/CollationElements/Sequence" */
+ // TODO(ICU-20769): Try to change the by-value fResData into a pointer,
+ // with the struct in only one place for each bundle.
+ // Also replace class ResourceDataValue.resData with a pResData pointer again.
ResourceData fResData;
char fResBuf[RES_BUFSIZE];
int32_t fResPathLen;
@@ -282,6 +285,11 @@
#ifdef __cplusplus
U_CAPI void U_EXPORT2
+ures_getValueWithFallback(const UResourceBundle *bundle, const char *path,
+ UResourceBundle *tempFillIn,
+ icu::ResourceDataValue &value, UErrorCode &errorCode);
+
+U_CAPI void U_EXPORT2
ures_getAllItemsWithFallback(const UResourceBundle *bundle, const char *path,
icu::ResourceSink &sink, UErrorCode &errorCode);
diff -Nru icu-64.2/source/common/usprep.cpp icu-65.1/source/common/usprep.cpp
--- icu-64.2/source/common/usprep.cpp 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/usprep.cpp 2019-10-03 11:16:41.000000000 +0000
@@ -45,13 +45,9 @@
Static cache for already opened StringPrep profiles
*/
static UHashtable *SHARED_DATA_HASHTABLE = NULL;
-static icu::UInitOnce gSharedDataInitOnce;
-
-static UMutex *usprepMutex() {
- static UMutex m = U_MUTEX_INITIALIZER;
- return &m;
-}
+static icu::UInitOnce gSharedDataInitOnce = U_INITONCE_INITIALIZER;
+static UMutex usprepMutex;
/* format version of spp file */
//static uint8_t formatVersion[4]={ 0, 0, 0, 0 };
@@ -151,9 +147,9 @@
* if shared data hasn't even been lazy evaluated yet
* return 0
*/
- umtx_lock(usprepMutex());
+ umtx_lock(&usprepMutex);
if (SHARED_DATA_HASHTABLE == NULL) {
- umtx_unlock(usprepMutex());
+ umtx_unlock(&usprepMutex);
return 0;
}
@@ -184,7 +180,7 @@
}
}
- umtx_unlock(usprepMutex());
+ umtx_unlock(&usprepMutex);
return deletedNum;
}
@@ -262,7 +258,7 @@
}
/* in the mutex block, set the data for this process */
- umtx_lock(usprepMutex());
+ umtx_lock(&usprepMutex);
if(profile->sprepData==NULL) {
profile->sprepData=dataMemory;
dataMemory=NULL;
@@ -271,7 +267,7 @@
} else {
p=(const int32_t *)udata_getMemory(profile->sprepData);
}
- umtx_unlock(usprepMutex());
+ umtx_unlock(&usprepMutex);
/* initialize some variables */
profile->mappingData=(uint16_t *)((uint8_t *)(p+_SPREP_INDEX_TOP)+profile->indexes[_SPREP_INDEX_TRIE_SIZE]);
@@ -328,12 +324,12 @@
stackKey.path = (char*) path;
/* fetch the data from the cache */
- umtx_lock(usprepMutex());
+ umtx_lock(&usprepMutex);
profile = (UStringPrepProfile*) (uhash_get(SHARED_DATA_HASHTABLE,&stackKey));
if(profile != NULL) {
profile->refCount++;
}
- umtx_unlock(usprepMutex());
+ umtx_unlock(&usprepMutex);
if(profile == NULL) {
/* else load the data and put the data in the cache */
@@ -365,7 +361,7 @@
return NULL;
}
- umtx_lock(usprepMutex());
+ umtx_lock(&usprepMutex);
// If another thread already inserted the same key/value, refcount and cleanup our thread data
profile = (UStringPrepProfile*) (uhash_get(SHARED_DATA_HASHTABLE,&stackKey));
if(profile != NULL) {
@@ -386,7 +382,7 @@
profile->refCount = 1;
uhash_put(SHARED_DATA_HASHTABLE, key.orphan(), profile, status);
}
- umtx_unlock(usprepMutex());
+ umtx_unlock(&usprepMutex);
}
return profile;
@@ -425,12 +421,12 @@
return;
}
- umtx_lock(usprepMutex());
+ umtx_lock(&usprepMutex);
/* decrement the ref count*/
if(profile->refCount > 0){
profile->refCount--;
}
- umtx_unlock(usprepMutex());
+ umtx_unlock(&usprepMutex);
}
diff -Nru icu-64.2/source/common/ustring.cpp icu-65.1/source/common/ustring.cpp
--- icu-64.2/source/common/ustring.cpp 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/ustring.cpp 2019-10-03 11:16:41.000000000 +0000
@@ -1428,7 +1428,7 @@
* NUL-terminate a string no matter what its type.
* Set warning and error codes accordingly.
*/
-#define __TERMINATE_STRING(dest, destCapacity, length, pErrorCode) \
+#define __TERMINATE_STRING(dest, destCapacity, length, pErrorCode) UPRV_BLOCK_MACRO_BEGIN { \
if(pErrorCode!=NULL && U_SUCCESS(*pErrorCode)) { \
/* not a public function, so no complete argument checking */ \
\
@@ -1448,7 +1448,8 @@
/* even the string itself did not fit - set an error code */ \
*pErrorCode=U_BUFFER_OVERFLOW_ERROR; \
} \
- }
+ } \
+} UPRV_BLOCK_MACRO_END
U_CAPI int32_t U_EXPORT2
u_terminateUChars(UChar *dest, int32_t destCapacity, int32_t length, UErrorCode *pErrorCode) {
@@ -1488,7 +1489,7 @@
the output range. [LIU]
*/
-#define STRING_HASH(TYPE, STR, STRLEN, DEREF) \
+#define STRING_HASH(TYPE, STR, STRLEN, DEREF) UPRV_BLOCK_MACRO_BEGIN { \
uint32_t hash = 0; \
const TYPE *p = (const TYPE*) STR; \
if (p != NULL) { \
@@ -1500,7 +1501,8 @@
p += inc; \
} \
} \
- return static_cast(hash)
+ return static_cast(hash); \
+} UPRV_BLOCK_MACRO_END
/* Used by UnicodeString to compute its hashcode - Not public API. */
U_CAPI int32_t U_EXPORT2
diff -Nru icu-64.2/source/common/ustr_titlecase_brkiter.cpp icu-65.1/source/common/ustr_titlecase_brkiter.cpp
--- icu-64.2/source/common/ustr_titlecase_brkiter.cpp 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/ustr_titlecase_brkiter.cpp 2019-10-03 11:16:41.000000000 +0000
@@ -45,7 +45,7 @@
WholeStringBreakIterator() : BreakIterator(), length(0) {}
~WholeStringBreakIterator() U_OVERRIDE;
UBool operator==(const BreakIterator&) const U_OVERRIDE;
- BreakIterator *clone() const U_OVERRIDE;
+ WholeStringBreakIterator *clone() const U_OVERRIDE;
static UClassID U_EXPORT2 getStaticClassID();
UClassID getDynamicClassID() const U_OVERRIDE;
CharacterIterator &getText() const U_OVERRIDE;
@@ -62,9 +62,9 @@
int32_t preceding(int32_t offset) U_OVERRIDE;
UBool isBoundary(int32_t offset) U_OVERRIDE;
int32_t next(int32_t n) U_OVERRIDE;
- BreakIterator *createBufferClone(void *stackBuffer, int32_t &BufferSize,
- UErrorCode &errorCode) U_OVERRIDE;
- BreakIterator &refreshInputText(UText *input, UErrorCode &errorCode) U_OVERRIDE;
+ WholeStringBreakIterator *createBufferClone(void *stackBuffer, int32_t &BufferSize,
+ UErrorCode &errorCode) U_OVERRIDE;
+ WholeStringBreakIterator &refreshInputText(UText *input, UErrorCode &errorCode) U_OVERRIDE;
private:
int32_t length;
@@ -74,7 +74,7 @@
WholeStringBreakIterator::~WholeStringBreakIterator() {}
UBool WholeStringBreakIterator::operator==(const BreakIterator&) const { return FALSE; }
-BreakIterator *WholeStringBreakIterator::clone() const { return nullptr; }
+WholeStringBreakIterator *WholeStringBreakIterator::clone() const { return nullptr; }
CharacterIterator &WholeStringBreakIterator::getText() const {
UPRV_UNREACHABLE; // really should not be called
@@ -113,14 +113,14 @@
UBool WholeStringBreakIterator::isBoundary(int32_t /*offset*/) { return FALSE; }
int32_t WholeStringBreakIterator::next(int32_t /*n*/) { return length; }
-BreakIterator *WholeStringBreakIterator::createBufferClone(
+WholeStringBreakIterator *WholeStringBreakIterator::createBufferClone(
void * /*stackBuffer*/, int32_t & /*BufferSize*/, UErrorCode &errorCode) {
if (U_SUCCESS(errorCode)) {
errorCode = U_UNSUPPORTED_ERROR;
}
return nullptr;
}
-BreakIterator &WholeStringBreakIterator::refreshInputText(
+WholeStringBreakIterator &WholeStringBreakIterator::refreshInputText(
UText * /*input*/, UErrorCode &errorCode) {
if (U_SUCCESS(errorCode)) {
errorCode = U_UNSUPPORTED_ERROR;
diff -Nru icu-64.2/source/common/utext.cpp icu-65.1/source/common/utext.cpp
--- icu-64.2/source/common/utext.cpp 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/utext.cpp 2019-10-03 11:16:41.000000000 +0000
@@ -567,7 +567,7 @@
struct ExtendedUText {
UText ut;
- UAlignedMemory extension;
+ max_align_t extension;
};
static const UText emptyText = UTEXT_INITIALIZER;
@@ -582,7 +582,7 @@
// We need to heap-allocate storage for the new UText
int32_t spaceRequired = sizeof(UText);
if (extraSpace > 0) {
- spaceRequired = sizeof(ExtendedUText) + extraSpace - sizeof(UAlignedMemory);
+ spaceRequired = sizeof(ExtendedUText) + extraSpace - sizeof(max_align_t);
}
ut = (UText *)uprv_malloc(spaceRequired);
if (ut == NULL) {
diff -Nru icu-64.2/source/common/util.cpp icu-65.1/source/common/util.cpp
--- icu-64.2/source/common/util.cpp 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/util.cpp 2019-10-03 11:16:41.000000000 +0000
@@ -276,6 +276,16 @@
return -1; // text ended before end of pat
}
+int32_t ICU_Utility::parseAsciiInteger(const UnicodeString& str, int32_t& pos) {
+ int32_t result = 0;
+ UChar c;
+ while (pos < str.length() && (c = str.charAt(pos)) >= u'0' && c <= u'9') {
+ result = result * 10 + (c - u'0');
+ pos++;
+ }
+ return result;
+}
+
/**
* Append a character to a rule that is being built up. To flush
* the quoteBuf to rule, make one final call with isLiteral == TRUE.
diff -Nru icu-64.2/source/common/util.h icu-65.1/source/common/util.h
--- icu-64.2/source/common/util.h 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/util.h 2019-10-03 11:16:41.000000000 +0000
@@ -179,13 +179,22 @@
* Parse an integer at pos, either of the form \d+ or of the form
* 0x[0-9A-Fa-f]+ or 0[0-7]+, that is, in standard decimal, hex,
* or octal format.
- * @param pos INPUT-OUTPUT parameter. On input, the first
- * character to parse. On output, the character after the last
- * parsed character.
+ * @param pos INPUT-OUTPUT parameter. On input, the index of the first
+ * character to parse. On output, the index of the character after the
+ * last parsed character.
*/
static int32_t parseInteger(const UnicodeString& rule, int32_t& pos, int32_t limit);
/**
+ * Parse an integer at pos using only ASCII digits.
+ * Base 10 only.
+ * @param pos INPUT-OUTPUT parameter. On input, the index of the first
+ * character to parse. On output, the index of the character after the
+ * last parsed character.
+ */
+ static int32_t parseAsciiInteger(const UnicodeString& str, int32_t& pos);
+
+ /**
* Parse a Unicode identifier from the given string at the given
* position. Return the identifier, or an empty string if there
* is no identifier.
diff -Nru icu-64.2/source/common/utrace.cpp icu-65.1/source/common/utrace.cpp
--- icu-64.2/source/common/utrace.cpp 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/utrace.cpp 2019-10-03 11:16:41.000000000 +0000
@@ -476,6 +476,16 @@
NULL
};
+
+static const char* const
+trResDataNames[] = {
+ "resc",
+ "bundle-open",
+ "file-open",
+ "res-open",
+ NULL
+};
+
U_CAPI const char * U_EXPORT2
utrace_functionName(int32_t fnNumber) {
@@ -485,6 +495,8 @@
return trConvNames[fnNumber - UTRACE_CONVERSION_START];
} else if(UTRACE_COLLATION_START <= fnNumber && fnNumber < UTRACE_COLLATION_LIMIT){
return trCollNames[fnNumber - UTRACE_COLLATION_START];
+ } else if(UTRACE_UDATA_START <= fnNumber && fnNumber < UTRACE_RES_DATA_LIMIT){
+ return trResDataNames[fnNumber - UTRACE_UDATA_START];
} else {
return "[BOGUS Trace Function Number]";
}
diff -Nru icu-64.2/source/common/utracimp.h icu-65.1/source/common/utracimp.h
--- icu-64.2/source/common/utracimp.h 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/utracimp.h 2019-10-03 11:16:41.000000000 +0000
@@ -144,10 +144,12 @@
*/
#define UTRACE_ENTRY(fnNumber) \
int32_t utraceFnNumber=(fnNumber); \
+UPRV_BLOCK_MACRO_BEGIN { \
if(utrace_getLevel()>=UTRACE_INFO) { \
utrace_entry(fnNumber); \
utraceFnNumber |= UTRACE_TRACED_ENTRY; \
- }
+ } \
+} UPRV_BLOCK_MACRO_END
/**
@@ -162,10 +164,12 @@
*/
#define UTRACE_ENTRY_OC(fnNumber) \
int32_t utraceFnNumber=(fnNumber); \
+UPRV_BLOCK_MACRO_BEGIN { \
if(utrace_getLevel()>=UTRACE_OPEN_CLOSE) { \
utrace_entry(fnNumber); \
utraceFnNumber |= UTRACE_TRACED_ENTRY; \
- }
+ } \
+} UPRV_BLOCK_MACRO_END
/**
* Trace statement for each exit point of a function that has a UTRACE_ENTRY()
@@ -179,10 +183,11 @@
*
* @internal
*/
-#define UTRACE_EXIT() \
- {if(utraceFnNumber & UTRACE_TRACED_ENTRY) { \
+#define UTRACE_EXIT() UPRV_BLOCK_MACRO_BEGIN { \
+ if(utraceFnNumber & UTRACE_TRACED_ENTRY) { \
utrace_exit(utraceFnNumber & ~UTRACE_TRACED_ENTRY, UTRACE_EXITV_NONE); \
- }}
+ } \
+} UPRV_BLOCK_MACRO_END
/**
* Trace statement for each exit point of a function that has a UTRACE_ENTRY()
@@ -192,25 +197,29 @@
*
* @internal
*/
-#define UTRACE_EXIT_VALUE(val) \
- {if(utraceFnNumber & UTRACE_TRACED_ENTRY) { \
+#define UTRACE_EXIT_VALUE(val) UPRV_BLOCK_MACRO_BEGIN { \
+ if(utraceFnNumber & UTRACE_TRACED_ENTRY) { \
utrace_exit(utraceFnNumber & ~UTRACE_TRACED_ENTRY, UTRACE_EXITV_I32, val); \
- }}
+ } \
+} UPRV_BLOCK_MACRO_END
-#define UTRACE_EXIT_STATUS(status) \
- {if(utraceFnNumber & UTRACE_TRACED_ENTRY) { \
+#define UTRACE_EXIT_STATUS(status) UPRV_BLOCK_MACRO_BEGIN { \
+ if(utraceFnNumber & UTRACE_TRACED_ENTRY) { \
utrace_exit(utraceFnNumber & ~UTRACE_TRACED_ENTRY, UTRACE_EXITV_STATUS, status); \
- }}
+ } \
+} UPRV_BLOCK_MACRO_END
-#define UTRACE_EXIT_VALUE_STATUS(val, status) \
- {if(utraceFnNumber & UTRACE_TRACED_ENTRY) { \
+#define UTRACE_EXIT_VALUE_STATUS(val, status) UPRV_BLOCK_MACRO_BEGIN { \
+ if(utraceFnNumber & UTRACE_TRACED_ENTRY) { \
utrace_exit(utraceFnNumber & ~UTRACE_TRACED_ENTRY, (UTRACE_EXITV_I32 | UTRACE_EXITV_STATUS), val, status); \
- }}
+ } \
+} UPRV_BLOCK_MACRO_END
-#define UTRACE_EXIT_PTR_STATUS(ptr, status) \
- {if(utraceFnNumber & UTRACE_TRACED_ENTRY) { \
+#define UTRACE_EXIT_PTR_STATUS(ptr, status) UPRV_BLOCK_MACRO_BEGIN { \
+ if(utraceFnNumber & UTRACE_TRACED_ENTRY) { \
utrace_exit(utraceFnNumber & ~UTRACE_TRACED_ENTRY, (UTRACE_EXITV_PTR | UTRACE_EXITV_STATUS), ptr, status); \
- }}
+ } \
+} UPRV_BLOCK_MACRO_END
/**
* Trace statement used inside functions that have a UTRACE_ENTRY() statement.
@@ -220,10 +229,11 @@
* Calls utrace_data() if the level is high enough.
* @internal
*/
-#define UTRACE_DATA0(level, fmt) \
+#define UTRACE_DATA0(level, fmt) UPRV_BLOCK_MACRO_BEGIN { \
if(UTRACE_LEVEL(level)) { \
utrace_data(utraceFnNumber & ~UTRACE_TRACED_ENTRY, (level), (fmt)); \
- }
+ } \
+} UPRV_BLOCK_MACRO_END
/**
* Trace statement used inside functions that have a UTRACE_ENTRY() statement.
@@ -233,10 +243,11 @@
* Calls utrace_data() if the level is high enough.
* @internal
*/
-#define UTRACE_DATA1(level, fmt, a) \
+#define UTRACE_DATA1(level, fmt, a) UPRV_BLOCK_MACRO_BEGIN { \
if(UTRACE_LEVEL(level)) { \
utrace_data(utraceFnNumber & ~UTRACE_TRACED_ENTRY , (level), (fmt), (a)); \
- }
+ } \
+} UPRV_BLOCK_MACRO_END
/**
* Trace statement used inside functions that have a UTRACE_ENTRY() statement.
@@ -246,10 +257,11 @@
* Calls utrace_data() if the level is high enough.
* @internal
*/
-#define UTRACE_DATA2(level, fmt, a, b) \
+#define UTRACE_DATA2(level, fmt, a, b) UPRV_BLOCK_MACRO_BEGIN { \
if(UTRACE_LEVEL(level)) { \
utrace_data(utraceFnNumber & ~UTRACE_TRACED_ENTRY , (level), (fmt), (a), (b)); \
- }
+ } \
+} UPRV_BLOCK_MACRO_END
/**
* Trace statement used inside functions that have a UTRACE_ENTRY() statement.
@@ -259,10 +271,11 @@
* Calls utrace_data() if the level is high enough.
* @internal
*/
-#define UTRACE_DATA3(level, fmt, a, b, c) \
+#define UTRACE_DATA3(level, fmt, a, b, c) UPRV_BLOCK_MACRO_BEGIN { \
if(UTRACE_LEVEL(level)) { \
utrace_data(utraceFnNumber & ~UTRACE_TRACED_ENTRY, (level), (fmt), (a), (b), (c)); \
- }
+ } \
+} UPRV_BLOCK_MACRO_END
/**
* Trace statement used inside functions that have a UTRACE_ENTRY() statement.
@@ -272,10 +285,11 @@
* Calls utrace_data() if the level is high enough.
* @internal
*/
-#define UTRACE_DATA4(level, fmt, a, b, c, d) \
+#define UTRACE_DATA4(level, fmt, a, b, c, d) UPRV_BLOCK_MACRO_BEGIN { \
if(UTRACE_LEVEL(level)) { \
utrace_data(utraceFnNumber & ~UTRACE_TRACED_ENTRY, (level), (fmt), (a), (b), (c), (d)); \
- }
+ } \
+} UPRV_BLOCK_MACRO_END
/**
* Trace statement used inside functions that have a UTRACE_ENTRY() statement.
@@ -285,10 +299,11 @@
* Calls utrace_data() if the level is high enough.
* @internal
*/
-#define UTRACE_DATA5(level, fmt, a, b, c, d, e) \
+#define UTRACE_DATA5(level, fmt, a, b, c, d, e) UPRV_BLOCK_MACRO_BEGIN { \
if(UTRACE_LEVEL(level)) { \
utrace_data(utraceFnNumber & ~UTRACE_TRACED_ENTRY, (level), (fmt), (a), (b), (c), (d), (e)); \
- }
+ } \
+} UPRV_BLOCK_MACRO_END
/**
* Trace statement used inside functions that have a UTRACE_ENTRY() statement.
@@ -298,10 +313,11 @@
* Calls utrace_data() if the level is high enough.
* @internal
*/
-#define UTRACE_DATA6(level, fmt, a, b, c, d, e, f) \
+#define UTRACE_DATA6(level, fmt, a, b, c, d, e, f) UPRV_BLOCK_MACRO_BEGIN { \
if(UTRACE_LEVEL(level)) { \
utrace_data(utraceFnNumber & ~UTRACE_TRACED_ENTRY, (level), (fmt), (a), (b), (c), (d), (e), (f)); \
- }
+ } \
+} UPRV_BLOCK_MACRO_END
/**
* Trace statement used inside functions that have a UTRACE_ENTRY() statement.
@@ -311,10 +327,11 @@
* Calls utrace_data() if the level is high enough.
* @internal
*/
-#define UTRACE_DATA7(level, fmt, a, b, c, d, e, f, g) \
+#define UTRACE_DATA7(level, fmt, a, b, c, d, e, f, g) UPRV_BLOCK_MACRO_BEGIN { \
if(UTRACE_LEVEL(level)) { \
utrace_data(utraceFnNumber & ~UTRACE_TRACED_ENTRY, (level), (fmt), (a), (b), (c), (d), (e), (f), (g)); \
- }
+ } \
+} UPRV_BLOCK_MACRO_END
/**
* Trace statement used inside functions that have a UTRACE_ENTRY() statement.
@@ -324,10 +341,11 @@
* Calls utrace_data() if the level is high enough.
* @internal
*/
-#define UTRACE_DATA8(level, fmt, a, b, c, d, e, f, g, h) \
+#define UTRACE_DATA8(level, fmt, a, b, c, d, e, f, g, h) UPRV_BLOCK_MACRO_BEGIN { \
if(UTRACE_LEVEL(level)) { \
utrace_data(utraceFnNumber & ~UTRACE_TRACED_ENTRY, (level), (fmt), (a), (b), (c), (d), (e), (f), (g), (h)); \
- }
+ } \
+} UPRV_BLOCK_MACRO_END
/**
* Trace statement used inside functions that have a UTRACE_ENTRY() statement.
@@ -337,10 +355,11 @@
* Calls utrace_data() if the level is high enough.
* @internal
*/
-#define UTRACE_DATA9(level, fmt, a, b, c, d, e, f, g, h, i) \
+#define UTRACE_DATA9(level, fmt, a, b, c, d, e, f, g, h, i) UPRV_BLOCK_MACRO_BEGIN { \
if(UTRACE_LEVEL(level)) { \
utrace_data(utraceFnNumber & ~UTRACE_TRACED_ENTRY, (level), (fmt), (a), (b), (c), (d), (e), (f), (g), (h), (i)); \
- }
+ } \
+} UPRV_BLOCK_MACRO_END
#else
diff -Nru icu-64.2/source/common/utrie2.h icu-65.1/source/common/utrie2.h
--- icu-64.2/source/common/utrie2.h 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/utrie2.h 2019-10-03 11:16:41.000000000 +0000
@@ -871,7 +871,7 @@
(trie)->data[_UTRIE2_INDEX_FROM_CP(trie, asciiOffset, c)]
/** Internal next-post-increment: get the next code point (c) and its data. */
-#define _UTRIE2_U16_NEXT(trie, data, src, limit, c, result) { \
+#define _UTRIE2_U16_NEXT(trie, data, src, limit, c, result) UPRV_BLOCK_MACRO_BEGIN { \
{ \
uint16_t __c2; \
(c)=*(src)++; \
@@ -885,10 +885,10 @@
(result)=_UTRIE2_GET_FROM_SUPP((trie), data, (c)); \
} \
} \
-}
+} UPRV_BLOCK_MACRO_END
/** Internal pre-decrement-previous: get the previous code point (c) and its data */
-#define _UTRIE2_U16_PREV(trie, data, start, src, c, result) { \
+#define _UTRIE2_U16_PREV(trie, data, start, src, c, result) UPRV_BLOCK_MACRO_BEGIN { \
{ \
uint16_t __c2; \
(c)=*--(src); \
@@ -900,10 +900,10 @@
(result)=_UTRIE2_GET_FROM_SUPP((trie), data, (c)); \
} \
} \
-}
+} UPRV_BLOCK_MACRO_END
/** Internal UTF-8 next-post-increment: get the next code point's data. */
-#define _UTRIE2_U8_NEXT(trie, ascii, data, src, limit, result) { \
+#define _UTRIE2_U8_NEXT(trie, ascii, data, src, limit, result) UPRV_BLOCK_MACRO_BEGIN { \
uint8_t __lead=(uint8_t)*(src)++; \
if(U8_IS_SINGLE(__lead)) { \
(result)=(trie)->ascii[__lead]; \
@@ -935,10 +935,10 @@
(result)=(trie)->data[__index>>3]; \
} \
} \
-}
+} UPRV_BLOCK_MACRO_END
/** Internal UTF-8 pre-decrement-previous: get the previous code point's data. */
-#define _UTRIE2_U8_PREV(trie, ascii, data, start, src, result) { \
+#define _UTRIE2_U8_PREV(trie, ascii, data, start, src, result) UPRV_BLOCK_MACRO_BEGIN { \
uint8_t __b=(uint8_t)*--(src); \
if(U8_IS_SINGLE(__b)) { \
(result)=(trie)->ascii[__b]; \
@@ -948,7 +948,7 @@
(src)-=__index&7; \
(result)=(trie)->data[__index>>3]; \
} \
-}
+} UPRV_BLOCK_MACRO_END
U_CDECL_END
diff -Nru icu-64.2/source/common/utrie.h icu-65.1/source/common/utrie.h
--- icu-64.2/source/common/utrie.h 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/common/utrie.h 2019-10-03 11:16:41.000000000 +0000
@@ -182,7 +182,7 @@
]
/** Internal trie getter from a pair of surrogates */
-#define _UTRIE_GET_FROM_PAIR(trie, data, c, c2, result, resultType) { \
+#define _UTRIE_GET_FROM_PAIR(trie, data, c, c2, result, resultType) UPRV_BLOCK_MACRO_BEGIN { \
int32_t __offset; \
\
/* get data for lead surrogate */ \
@@ -195,18 +195,18 @@
} else { \
(result)=(resultType)((trie)->initialValue); \
} \
-}
+} UPRV_BLOCK_MACRO_END
/** Internal trie getter from a BMP code point, treating a lead surrogate as a normal code point */
#define _UTRIE_GET_FROM_BMP(trie, data, c16) \
- _UTRIE_GET_RAW(trie, data, 0xd800<=(c16) && (c16)<=0xdbff ? UTRIE_LEAD_INDEX_DISP : 0, c16);
+ _UTRIE_GET_RAW(trie, data, 0xd800<=(c16) && (c16)<=0xdbff ? UTRIE_LEAD_INDEX_DISP : 0, c16)
/**
* Internal trie getter from a code point.
* Could be faster(?) but longer with
* if((c32)<=0xd7ff) { (result)=_UTRIE_GET_RAW(trie, data, 0, c32); }
*/
-#define _UTRIE_GET(trie, data, c32, result, resultType) \
+#define _UTRIE_GET(trie, data, c32, result, resultType) UPRV_BLOCK_MACRO_BEGIN { \
if((uint32_t)(c32)<=0xffff) { \
/* BMP code points */ \
(result)=_UTRIE_GET_FROM_BMP(trie, data, c32); \
@@ -217,10 +217,11 @@
} else { \
/* out of range */ \
(result)=(resultType)((trie)->initialValue); \
- }
+ } \
+} UPRV_BLOCK_MACRO_END
/** Internal next-post-increment: get the next code point (c, c2) and its data */
-#define _UTRIE_NEXT(trie, data, src, limit, c, c2, result, resultType) { \
+#define _UTRIE_NEXT(trie, data, src, limit, c, c2, result, resultType) UPRV_BLOCK_MACRO_BEGIN { \
(c)=*(src)++; \
if(!U16_IS_LEAD(c)) { \
(c2)=0; \
@@ -233,10 +234,10 @@
(c2)=0; \
(result)=_UTRIE_GET_RAW((trie), data, UTRIE_LEAD_INDEX_DISP, (c)); \
} \
-}
+} UPRV_BLOCK_MACRO_END
/** Internal previous: get the previous code point (c, c2) and its data */
-#define _UTRIE_PREVIOUS(trie, data, start, src, c, c2, result, resultType) { \
+#define _UTRIE_PREVIOUS(trie, data, start, src, c, c2, result, resultType) UPRV_BLOCK_MACRO_BEGIN { \
(c)=*--(src); \
if(!U16_IS_SURROGATE(c)) { \
(c2)=0; \
@@ -257,7 +258,7 @@
(c2)=0; \
(result)=_UTRIE_GET_RAW((trie), data, UTRIE_LEAD_INDEX_DISP, (c)); \
} \
-}
+} UPRV_BLOCK_MACRO_END
/* Public UTrie API ---------------------------------------------------------*/
diff -Nru icu-64.2/source/config/mh-cygwin-msvc icu-65.1/source/config/mh-cygwin-msvc
--- icu-64.2/source/config/mh-cygwin-msvc 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/config/mh-cygwin-msvc 2019-10-03 11:16:41.000000000 +0000
@@ -121,13 +121,13 @@
LIBICUTOOLUTIL= $(LIBDIR)/$(LIBICU)$(TOOLUTIL_STUBNAME)$(ICULIBSUFFIX).lib
## These are the library specific LDFLAGS
-LDFLAGSICUDT+= -base:"0x4ad00000" -NOENTRY# The NOENTRY option is required for creating a resource-only DLL.
-LDFLAGSICUUC= -base:"0x4a800000"# in-uc = 1MB
-LDFLAGSICUI18N= -base:"0x4a900000"# io-in = 2MB
-LDFLAGSICUIO= -base:"0x4ab00000"# le-io = 1MB
-LDFLAGSICULX= -base:"0x4ac80000"
+LDFLAGSICUDT+= -NOENTRY# The NOENTRY option is required for creating a resource-only DLL.
+LDFLAGSICUUC=# Unused for now.
+LDFLAGSICUI18N=# Unused for now.
+LDFLAGSICUIO=# Unused for now.
+LDFLAGSICULX=# Unused for now.
LDFLAGSCTESTFW=# Unused for now.
-LDFLAGSICUTOOLUTIL= -base:"0x4ac00000"# Same as layout. Layout and tools probably won't mix.
+LDFLAGSICUTOOLUTIL=# Unused for now.
# The #M# is used to delete lines for icu-config
# Current full path directory.
diff -Nru icu-64.2/source/config/mh-mingw icu-65.1/source/config/mh-mingw
--- icu-64.2/source/config/mh-mingw 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/config/mh-mingw 2019-10-03 11:16:41.000000000 +0000
@@ -103,13 +103,29 @@
#SH## with usually. Many applications will want to add ${ICULIBS_I18N} as well.
#SH#ICULIBS="${ICULIBS_BASE} ${ICULIBS_I18N} ${ICULIBS_COMMON} ${ICULIBS_DATA} "
-# The #M# is used to delete lines for icu-config
-# Current full path directory.
-#CURR_FULL_DIR=$(shell pwd -W)#M# for MSYS
-CURR_FULL_DIR?=$(subst \,/,$(shell cmd /c cd))#M# for Cygwin shell
-# Current full path directory for use in source code in a -D compiler option.
-#CURR_SRCCODE_FULL_DIR=$(subst /,\\\\,$(shell pwd -W))#M# for MSYS
-CURR_SRCCODE_FULL_DIR=$(subst \,/,$(shell cmd /c cd))#M# for Cygwin shell
+# Note: The #M# is used to delete lines for icu-config
+MSYS_VERSION ?= $(if $(findstring Msys, $(shell uname -o)),$(word 1, $(subst ., ,$(shell uname -r))),0)#M#
+$(info Detected MSYS version: $(MSYS_VERSION))
+
+ifeq ($(MSYS_VERSION),$(filter $(MSYS_VERSION),0 1))
+ # Older versions of MSYS don't have cygpath by default. #M#
+
+ # Current full path directory. #M#
+ #CURR_FULL_DIR=$(shell pwd -W)#M# for MSYS
+ CURR_FULL_DIR?=$(subst \,/,$(shell cmd /c cd))#M# for Cygwin shell
+
+ # Current full path directory for use in source code in a -D compiler option. #M#
+ #CURR_SRCCODE_FULL_DIR=$(subst /,\\\\,$(shell pwd -W))#M# for MSYS
+ CURR_SRCCODE_FULL_DIR=$(subst \,/,$(shell cmd /c cd))#M# for Cygwin shell
+else
+ # MSYS2 and up have cygpath by default #M#
+
+ # Current full path directory. #M#
+ CURR_FULL_DIR?=$(shell cygpath . -a -m)#M#
+
+ # Current full path directory for use in source code in a -D compiler option. #M#
+ CURR_SRCCODE_FULL_DIR=$(shell cygpath . -a -m)#M#
+endif
## Compilation rules
%.$(STATIC_O): $(srcdir)/%.c
diff -Nru icu-64.2/source/config/mh-mingw64 icu-65.1/source/config/mh-mingw64
--- icu-64.2/source/config/mh-mingw64 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/config/mh-mingw64 2019-10-03 11:16:41.000000000 +0000
@@ -103,13 +103,29 @@
#SH## with usually. Many applications will want to add ${ICULIBS_I18N} as well.
#SH#ICULIBS="${ICULIBS_BASE} ${ICULIBS_I18N} ${ICULIBS_COMMON} ${ICULIBS_DATA} "
-# The #M# is used to delete lines for icu-config
-# Current full path directory.
-#CURR_FULL_DIR=$(shell pwd -W)#M# for MSYS
-CURR_FULL_DIR?=$(subst \,/,$(shell cmd /c cd))#M# for Cygwin shell
-# Current full path directory for use in source code in a -D compiler option.
-#CURR_SRCCODE_FULL_DIR=$(subst /,\\\\,$(shell pwd -W))#M# for MSYS
-CURR_SRCCODE_FULL_DIR=$(subst \,/,$(shell cmd /c cd))#M# for Cygwin shell
+# Note: The #M# is used to delete lines for icu-config
+MSYS_VERSION ?= $(if $(findstring Msys, $(shell uname -o)),$(word 1, $(subst ., ,$(shell uname -r))),0)#M#
+$(info Detected MSYS version: $(MSYS_VERSION))
+
+ifeq ($(MSYS_VERSION),$(filter $(MSYS_VERSION),0 1))
+ # Older versions of MSYS don't have cygpath by default. #M#
+
+ # Current full path directory. #M#
+ #CURR_FULL_DIR=$(shell pwd -W)#M# for MSYS
+ CURR_FULL_DIR?=$(subst \,/,$(shell cmd /c cd))#M# for Cygwin shell
+
+ # Current full path directory for use in source code in a -D compiler option. #M#
+ #CURR_SRCCODE_FULL_DIR=$(subst /,\\\\,$(shell pwd -W))#M# for MSYS
+ CURR_SRCCODE_FULL_DIR=$(subst \,/,$(shell cmd /c cd))#M# for Cygwin shell
+else
+ # MSYS2 and up have cygpath by default #M#
+
+ # Current full path directory. #M#
+ CURR_FULL_DIR?=$(shell cygpath . -a -m)#M#
+
+ # Current full path directory for use in source code in a -D compiler option. #M#
+ CURR_SRCCODE_FULL_DIR=$(shell cygpath . -a -m)#M#
+endif
## Compilation rules
%.$(STATIC_O): $(srcdir)/%.c
diff -Nru icu-64.2/source/config/mh-msys-msvc icu-65.1/source/config/mh-msys-msvc
--- icu-64.2/source/config/mh-msys-msvc 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/config/mh-msys-msvc 2019-10-03 11:16:41.000000000 +0000
@@ -122,13 +122,13 @@
LIBICUTOOLUTIL= $(LIBDIR)/$(LIBICU)$(TOOLUTIL_STUBNAME)$(ICULIBSUFFIX).lib
## These are the library specific LDFLAGS
-LDFLAGSICUDT+= -base:"0x4ad00000" -NOENTRY# The NOENTRY option is required for creating a resource-only DLL.
-LDFLAGSICUUC= -base:"0x4a800000"# in-uc = 1MB
-LDFLAGSICUI18N= -base:"0x4a900000"# io-in = 2MB
-LDFLAGSICUIO= -base:"0x4ab00000"# le-io = 1MB
-LDFLAGSICULX= -base:"0x4ac80000"
+LDFLAGSICUDT+= -NOENTRY# The NOENTRY option is required for creating a resource-only DLL.
+LDFLAGSICUUC=# Unused for now.
+LDFLAGSICUI18N=# Unused for now.
+LDFLAGSICUIO=# Unused for now.
+LDFLAGSICULX=# Unused for now.
LDFLAGSCTESTFW=# Unused for now.
-LDFLAGSICUTOOLUTIL= -base:"0x4ac00000"# Same as layout. Layout and tools probably won't mix.
+LDFLAGSICUTOOLUTIL=# Unused for now.
## Compilation rules
%.$(STATIC_O): $(srcdir)/%.c
diff -Nru icu-64.2/source/configure icu-65.1/source/configure
--- icu-64.2/source/configure 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/configure 2019-10-03 11:16:41.000000000 +0000
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for ICU 64.2.
+# Generated by GNU Autoconf 2.69 for ICU 65.1.
#
# Report bugs to .
#
@@ -582,8 +582,8 @@
# Identity of this package.
PACKAGE_NAME='ICU'
PACKAGE_TARNAME='International Components for Unicode'
-PACKAGE_VERSION='64.2'
-PACKAGE_STRING='ICU 64.2'
+PACKAGE_VERSION='65.1'
+PACKAGE_STRING='ICU 65.1'
PACKAGE_BUGREPORT='http://icu-project.org/bugs'
PACKAGE_URL='http://icu-project.org'
@@ -645,6 +645,8 @@
DATA_PACKAGING_MODE
thepkgicudatadir
pkgicudatadir
+U_HAVE_FUZZER
+FUZZER_TRUE
U_HAVE_TOOLS
TOOLS_TRUE
U_HAVE_LAYOUTEX
@@ -797,6 +799,7 @@
enable_layoutex
enable_layout
enable_tools
+enable_fuzzer
with_data_packaging
with_library_suffix
enable_tests
@@ -1359,7 +1362,7 @@
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures ICU 64.2 to adapt to many kinds of systems.
+\`configure' configures ICU 65.1 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1425,7 +1428,7 @@
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of ICU 64.2:";;
+ short | recursive ) echo "Configuration of ICU 65.1:";;
esac
cat <<\_ACEOF
@@ -1454,6 +1457,7 @@
icu-le-hb must be installed via pkg-config. See http://harfbuzz.org
--enable-tools build ICU's tools default=yes
+ --enable-fuzzer build ICU's fuzzer test targets default=no
--enable-tests build ICU tests default=yes
--enable-samples build ICU samples default=yes
@@ -1562,7 +1566,7 @@
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-ICU configure 64.2
+ICU configure 65.1
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2197,6 +2201,60 @@
} # ac_fn_c_check_func
+# ac_fn_cxx_check_type LINENO TYPE VAR INCLUDES
+# ---------------------------------------------
+# Tests whether TYPE exists after having included INCLUDES, setting cache
+# variable VAR accordingly.
+ac_fn_cxx_check_type ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ eval "$3=no"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+int
+main ()
+{
+if (sizeof ($2))
+ return 0;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+int
+main ()
+{
+if (sizeof (($2)))
+ return 0;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+
+else
+ eval "$3=yes"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_cxx_check_type
+
# ac_fn_c_check_type LINENO TYPE VAR INCLUDES
# -------------------------------------------
# Tests whether TYPE exists after having included INCLUDES, setting cache
@@ -2254,7 +2312,7 @@
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by ICU $as_me 64.2, which was
+It was created by ICU $as_me 65.1, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@@ -7149,6 +7207,29 @@
fi
+# Check if C++17 std::string_view is available.
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+ac_fn_cxx_check_type "$LINENO" "std::string_view" "ac_cv_type_std__string_view" "#include
+"
+if test "x$ac_cv_type_std__string_view" = xyes; then :
+
+fi
+
+if test "x$ac_cv_type_std__string_view" = xyes; then :
+ CONFIG_CPPFLAGS="${CONFIG_CPPFLAGS} -DU_HAVE_STRING_VIEW=1"
+fi
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
# Checks for typedefs
ac_fn_c_check_type "$LINENO" "int8_t" "ac_cv_type_int8_t" "$ac_includes_default"
if test "x$ac_cv_type_int8_t" = xyes; then :
@@ -7665,6 +7746,28 @@
U_HAVE_TOOLS=0
fi
+# Enable/disable fuzzer target tests.
+# Check whether --enable-fuzzer was given.
+if test "${enable_fuzzer+set}" = set; then :
+ enableval=$enable_fuzzer; case "${enableval}" in
+ yes) fuzzer=true ;;
+ no) fuzzer=false ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-fuzzer" "$LINENO" 5 ;;
+ esac
+else
+ fuzzer=false
+fi
+
+
+
+if test "$fuzzer" = true; then
+ FUZZER_TRUE=
+ U_HAVE_FUZZER=1
+else
+ FUZZER_TRUE='#'
+ U_HAVE_FUZZER=0
+fi
+
# Check whether --with-data-packaging was given.
if test "${with_data_packaging+set}" = set; then :
@@ -7863,6 +7966,7 @@
if test "${CXX}" = "clang++"; then
CLANGCXXFLAGS="-Qunused-arguments -Wno-parentheses-equality"
+ LIBCXXFLAGS="$LIBCXXFLAGS -Wglobal-constructors"
else
CLANGCXXFLAGS=""
fi
@@ -7883,7 +7987,7 @@
# output the Makefiles
-ac_config_files="$ac_config_files icudefs.mk Makefile data/pkgdataMakefile config/Makefile.inc config/icu.pc config/pkgdataMakefile data/Makefile stubdata/Makefile common/Makefile i18n/Makefile layoutex/Makefile io/Makefile extra/Makefile extra/uconv/Makefile extra/uconv/pkgdataMakefile extra/scrptrun/Makefile tools/Makefile tools/ctestfw/Makefile tools/toolutil/Makefile tools/makeconv/Makefile tools/genrb/Makefile tools/genccode/Makefile tools/gencmn/Makefile tools/gencnval/Makefile tools/gendict/Makefile tools/gentest/Makefile tools/gennorm2/Makefile tools/genbrk/Makefile tools/gensprep/Makefile tools/icuinfo/Makefile tools/icupkg/Makefile tools/icuswap/Makefile tools/pkgdata/Makefile tools/tzcode/Makefile tools/gencfu/Makefile tools/escapesrc/Makefile test/Makefile test/compat/Makefile test/testdata/Makefile test/testdata/pkgdataMakefile test/hdrtst/Makefile test/intltest/Makefile test/cintltst/Makefile test/iotest/Makefile test/letest/Makefile test/perf/Makefile test/perf/collationperf/Makefile test/perf/collperf/Makefile test/perf/collperf2/Makefile test/perf/dicttrieperf/Makefile test/perf/ubrkperf/Makefile test/perf/charperf/Makefile test/perf/convperf/Makefile test/perf/normperf/Makefile test/perf/DateFmtPerf/Makefile test/perf/howExpensiveIs/Makefile test/perf/strsrchperf/Makefile test/perf/unisetperf/Makefile test/perf/usetperf/Makefile test/perf/ustrperf/Makefile test/perf/utfperf/Makefile test/perf/utrie2perf/Makefile test/perf/leperf/Makefile samples/Makefile samples/date/Makefile samples/cal/Makefile samples/layout/Makefile"
+ac_config_files="$ac_config_files icudefs.mk Makefile data/pkgdataMakefile config/Makefile.inc config/icu.pc config/pkgdataMakefile data/Makefile stubdata/Makefile common/Makefile i18n/Makefile layoutex/Makefile io/Makefile extra/Makefile extra/uconv/Makefile extra/uconv/pkgdataMakefile extra/scrptrun/Makefile tools/Makefile tools/ctestfw/Makefile tools/toolutil/Makefile tools/makeconv/Makefile tools/genrb/Makefile tools/genccode/Makefile tools/gencmn/Makefile tools/gencnval/Makefile tools/gendict/Makefile tools/gentest/Makefile tools/gennorm2/Makefile tools/genbrk/Makefile tools/gensprep/Makefile tools/icuinfo/Makefile tools/icupkg/Makefile tools/icuswap/Makefile tools/pkgdata/Makefile tools/tzcode/Makefile tools/gencfu/Makefile tools/escapesrc/Makefile test/Makefile test/compat/Makefile test/testdata/Makefile test/testdata/pkgdataMakefile test/hdrtst/Makefile test/intltest/Makefile test/cintltst/Makefile test/iotest/Makefile test/letest/Makefile test/perf/Makefile test/perf/collationperf/Makefile test/perf/collperf/Makefile test/perf/collperf2/Makefile test/perf/dicttrieperf/Makefile test/perf/ubrkperf/Makefile test/perf/charperf/Makefile test/perf/convperf/Makefile test/perf/normperf/Makefile test/perf/DateFmtPerf/Makefile test/perf/howExpensiveIs/Makefile test/perf/strsrchperf/Makefile test/perf/unisetperf/Makefile test/perf/usetperf/Makefile test/perf/ustrperf/Makefile test/perf/utfperf/Makefile test/perf/utrie2perf/Makefile test/perf/leperf/Makefile test/fuzzer/Makefile samples/Makefile samples/date/Makefile samples/cal/Makefile samples/layout/Makefile"
cat >confcache <<\_ACEOF
# This file is a shell script that caches the results of configure
@@ -8428,7 +8532,7 @@
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
-This file was extended by ICU $as_me 64.2, which was
+This file was extended by ICU $as_me 65.1, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -8482,7 +8586,7 @@
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
-ICU config.status 64.2
+ICU config.status 65.1
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
@@ -8656,6 +8760,7 @@
"test/perf/utfperf/Makefile") CONFIG_FILES="$CONFIG_FILES test/perf/utfperf/Makefile" ;;
"test/perf/utrie2perf/Makefile") CONFIG_FILES="$CONFIG_FILES test/perf/utrie2perf/Makefile" ;;
"test/perf/leperf/Makefile") CONFIG_FILES="$CONFIG_FILES test/perf/leperf/Makefile" ;;
+ "test/fuzzer/Makefile") CONFIG_FILES="$CONFIG_FILES test/fuzzer/Makefile" ;;
"samples/Makefile") CONFIG_FILES="$CONFIG_FILES samples/Makefile" ;;
"samples/date/Makefile") CONFIG_FILES="$CONFIG_FILES samples/date/Makefile" ;;
"samples/cal/Makefile") CONFIG_FILES="$CONFIG_FILES samples/cal/Makefile" ;;
@@ -9123,7 +9228,8 @@
if test -f "$srcdir/data/locales/root.txt";
then
echo "Spawning Python to generate data/rules.mk..."
- PYTHONPATH="$srcdir/data" $PYTHON -m buildtool \
+ PYTHONPATH="$srcdir/python" \
+ $PYTHON -m icutools.databuilder \
--mode gnumake \
--seqmode parallel \
--src_dir "$srcdir/data" \
@@ -9138,7 +9244,8 @@
touch data/rules.mk
fi
echo "Spawning Python to generate test/testdata/rules.mk..."
- PYTHONPATH="$srcdir/test/testdata:$srcdir/data" $PYTHON -m buildtool \
+ PYTHONPATH="$srcdir/python" \
+ $PYTHON -m icutools.databuilder \
--mode gnumake \
--seqmode parallel \
--src_dir "$srcdir/test/testdata" \
diff -Nru icu-64.2/source/configure.ac icu-65.1/source/configure.ac
--- icu-64.2/source/configure.ac 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/configure.ac 2019-10-03 11:16:41.000000000 +0000
@@ -903,6 +903,14 @@
fi
AC_SUBST(U_HAVE_STRTOD_L)
+# Check if C++17 std::string_view is available.
+AC_LANG_PUSH([C++])
+AC_CHECK_TYPE(std::string_view, [], [], [[#include ]])
+if test "x$ac_cv_type_std__string_view" = xyes; then :
+ CONFIG_CPPFLAGS="${CONFIG_CPPFLAGS} -DU_HAVE_STRING_VIEW=1"
+fi
+AC_LANG_POP([C++])
+
# Checks for typedefs
AC_CHECK_TYPE(int8_t,signed char)
AC_CHECK_TYPE(uint8_t,unsigned char)
@@ -1124,6 +1132,17 @@
tools=true)
ICU_CONDITIONAL(TOOLS, test "$tools" = true)
+# Enable/disable fuzzer target tests.
+AC_ARG_ENABLE(fuzzer,
+ [ --enable-fuzzer build ICU's fuzzer test targets [default=no]],
+ [case "${enableval}" in
+ yes) fuzzer=true ;;
+ no) fuzzer=false ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-fuzzer) ;;
+ esac],
+ fuzzer=false)
+ICU_CONDITIONAL(FUZZER, test "$fuzzer" = true)
+
AC_ARG_WITH(data-packaging,
[ --with-data-packaging specify how to package ICU data. Possible values:
files raw files (.res, etc)
@@ -1304,6 +1323,7 @@
if test "${CXX}" = "clang++"; then
CLANGCXXFLAGS="-Qunused-arguments -Wno-parentheses-equality"
+ LIBCXXFLAGS="$LIBCXXFLAGS -Wglobal-constructors"
else
CLANGCXXFLAGS=""
fi
@@ -1387,6 +1407,7 @@
test/perf/utfperf/Makefile \
test/perf/utrie2perf/Makefile \
test/perf/leperf/Makefile \
+ test/fuzzer/Makefile \
samples/Makefile samples/date/Makefile \
samples/cal/Makefile samples/layout/Makefile])
AC_OUTPUT
@@ -1399,7 +1420,8 @@
if test -f "$srcdir/data/locales/root.txt";
then
echo "Spawning Python to generate data/rules.mk..."
- PYTHONPATH="$srcdir/data" $PYTHON -m buildtool \
+ PYTHONPATH="$srcdir/python" \
+ $PYTHON -m icutools.databuilder \
--mode gnumake \
--seqmode parallel \
--src_dir "$srcdir/data" \
@@ -1414,7 +1436,8 @@
touch data/rules.mk
fi
echo "Spawning Python to generate test/testdata/rules.mk..."
- PYTHONPATH="$srcdir/test/testdata:$srcdir/data" $PYTHON -m buildtool \
+ PYTHONPATH="$srcdir/python" \
+ $PYTHON -m icutools.databuilder \
--mode gnumake \
--seqmode parallel \
--src_dir "$srcdir/test/testdata" \
diff -Nru icu-64.2/source/data/BUILDRULES.py icu-65.1/source/data/BUILDRULES.py
--- icu-64.2/source/data/BUILDRULES.py 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/data/BUILDRULES.py 2019-10-03 11:16:41.000000000 +0000
@@ -5,14 +5,13 @@
# TODO(ICU-20301): Remove this.
from __future__ import print_function
-from buildtool import *
-from buildtool import locale_dependencies
-from buildtool import utils
-from buildtool.request_types import *
+from icutools.databuilder import *
+from icutools.databuilder import locale_dependencies
+from icutools.databuilder import utils
+from icutools.databuilder.request_types import *
import os
import sys
-import xml.etree.ElementTree as ET
def generate(config, glob, common_vars):
@@ -23,6 +22,7 @@
exit(1)
requests += generate_cnvalias(config, glob, common_vars)
+ requests += generate_ulayout(config, glob, common_vars)
requests += generate_confusables(config, glob, common_vars)
requests += generate_conversion_mappings(config, glob, common_vars)
requests += generate_brkitr_brk(config, glob, common_vars)
@@ -32,7 +32,6 @@
requests += generate_coll_ucadata(config, glob, common_vars)
requests += generate_full_unicore_data(config, glob, common_vars)
requests += generate_unames(config, glob, common_vars)
- requests += generate_ulayout(config, glob, common_vars)
requests += generate_misc(config, glob, common_vars)
requests += generate_curr_supplemental(config, glob, common_vars)
requests += generate_translit(config, glob, common_vars)
@@ -43,48 +42,49 @@
"locales",
None,
"icu-locale-deprecates.xml",
- True,
+ config.use_pool_bundle,
[])
requests += generate_tree(config, glob, common_vars,
"curr",
"curr",
"icu-locale-deprecates.xml",
- True,
+ config.use_pool_bundle,
[])
requests += generate_tree(config, glob, common_vars,
"lang",
"lang",
"icu-locale-deprecates.xml",
- True,
+ config.use_pool_bundle,
[])
requests += generate_tree(config, glob, common_vars,
"region",
"region",
"icu-locale-deprecates.xml",
- True,
+ config.use_pool_bundle,
[])
requests += generate_tree(config, glob, common_vars,
"zone",
"zone",
"icu-locale-deprecates.xml",
- True,
+ config.use_pool_bundle,
[])
requests += generate_tree(config, glob, common_vars,
"unit",
"unit",
"icu-locale-deprecates.xml",
- True,
+ config.use_pool_bundle,
[])
requests += generate_tree(config, glob, common_vars,
"coll",
"coll",
"icu-coll-deprecates.xml",
+ # Never use pool bundle for coll, brkitr, or rbnf
False,
# Depends on timezoneTypes.res and keyTypeData.res.
# TODO: We should not need this dependency to build collation.
@@ -95,6 +95,7 @@
"brkitr",
"brkitr",
"icu-locale-deprecates.xml",
+ # Never use pool bundle for coll, brkitr, or rbnf
False,
[DepTarget("brkitr_brk"), DepTarget("dictionaries")])
@@ -102,6 +103,7 @@
"rbnf",
"rbnf",
"icu-rbnf-deprecates.xml",
+ # Never use pool bundle for coll, brkitr, or rbnf
False,
[])
@@ -187,7 +189,7 @@
RepeatedExecutionRequest(
name = "brkitr_brk",
category = "brkitr_rules",
- dep_targets = [DepTarget("cnvalias")],
+ dep_targets = [DepTarget("cnvalias"), DepTarget("ulayout")],
input_files = input_files,
output_files = output_files,
tool = IcuTool("genbrk"),
@@ -516,54 +518,48 @@
)
]
- # Generate index txt file
- synthetic_locales = set()
- deprecates_xml_path = os.path.join(os.path.dirname(__file__), xml_filename)
- deprecates_xml = ET.parse(deprecates_xml_path)
- for child in deprecates_xml.getroot():
- if child.tag == "alias":
- synthetic_locales.add(child.attrib["from"])
- elif child.tag == "emptyLocale":
- synthetic_locales.add(child.attrib["locale"])
- else:
- raise ValueError("Unknown tag in deprecates XML: %s" % child.tag)
- index_input_files = []
+ # Generate res_index file
+ # Exclude the deprecated locale variants and root; see ICU-20628. This
+ # could be data-driven, but we do not want to perform I/O in this script
+ # (for example, we do not want to read from an XML file).
+ excluded_locales = set([
+ "ja_JP_TRADITIONAL",
+ "th_TH_TRADITIONAL",
+ "de_",
+ "de__PHONEBOOK",
+ "es_",
+ "es__TRADITIONAL",
+ "root",
+ ])
+ # Put alias locales in a separate structure; see ICU-20627
+ alias_locales = set(locale_dependencies.data["aliases"].keys())
+ alias_files = []
+ installed_files = []
for f in input_files:
- file_stem = f.filename[f.filename.rfind("/")+1:-4]
- if file_stem == "root":
- continue
- if file_stem in synthetic_locales:
+ file_stem = IndexRequest.locale_file_stem(f)
+ if file_stem in excluded_locales:
continue
- index_input_files.append(f)
+ destination = alias_files if file_stem in alias_locales else installed_files
+ destination.append(f)
cldr_version = locale_dependencies.data["cldrVersion"] if sub_dir == "locales" else None
index_file_txt = TmpFile("{IN_SUB_DIR}/{INDEX_NAME}.txt".format(
IN_SUB_DIR = sub_dir,
**common_vars
))
- index_file_target_name = "%s_index_txt" % sub_dir
- requests += [
- IndexTxtRequest(
- name = index_file_target_name,
- category = category,
- input_files = index_input_files,
- output_file = index_file_txt,
- cldr_version = cldr_version
- )
- ]
-
- # Generate index res file
index_res_file = OutFile("{OUT_PREFIX}{INDEX_NAME}.res".format(
OUT_PREFIX = out_prefix,
**common_vars
))
+ index_file_target_name = "%s_index_txt" % sub_dir
requests += [
- SingleExecutionRequest(
- name = "%s_index_res" % sub_dir,
+ IndexRequest(
+ name = index_file_target_name,
category = category,
- dep_targets = [DepTarget(index_file_target_name)],
- input_files = [],
- output_files = [index_res_file],
- tool = IcuTool("genrb"),
+ installed_files = installed_files,
+ alias_files = alias_files,
+ txt_file = index_file_txt,
+ output_file = index_res_file,
+ cldr_version = cldr_version,
args = "-s {TMP_DIR}/{IN_SUB_DIR} -d {OUT_DIR}/{OUT_PREFIX} -i {OUT_DIR} "
"-k "
"{INDEX_NAME}.txt",
diff -Nru icu-64.2/source/data/buildtool/comment_stripper.py icu-65.1/source/data/buildtool/comment_stripper.py
--- icu-64.2/source/data/buildtool/comment_stripper.py 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/data/buildtool/comment_stripper.py 1970-01-01 00:00:00.000000000 +0000
@@ -1,51 +0,0 @@
-# Copyright (C) 2018 and later: Unicode, Inc. and others.
-# License & terms of use: http://www.unicode.org/copyright.html
-
-import io
-
-class CommentStripper(object):
- """Removes lines starting with "//" from a file stream."""
-
- def __init__(self, f):
- self.f = f
- self.state = 0
-
- def read(self, size=-1):
- bytes = self.f.read(size)
- # TODO: Do we need to read more bytes if comments were stripped
- # in order to obey the size request?
- return "".join(self._strip_comments(bytes))
-
- def _strip_comments(self, bytes):
- for byte in bytes:
- if self.state == 0:
- # state 0: start of a line
- if byte == "/":
- self.state = 1
- elif byte == "\n":
- self.state = 0
- yield byte
- else:
- self.state = 2
- yield byte
- elif self.state == 1:
- # state 1: read a single '/'
- if byte == "/":
- self.state = 3
- elif byte == "\n":
- self.state = 0
- yield "/" # the one that was skipped
- yield "\n"
- else:
- self.state = 2
- yield "/" # the one that was skipped
- yield byte
- elif self.state == 2:
- # state 2: middle of a line, no comment
- if byte == "\n":
- self.state = 0
- yield byte
- elif self.state == 3:
- # state 3: inside a comment
- if byte == "\n":
- self.state = 0
diff -Nru icu-64.2/source/data/buildtool/filtration.py icu-65.1/source/data/buildtool/filtration.py
--- icu-64.2/source/data/buildtool/filtration.py 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/data/buildtool/filtration.py 1970-01-01 00:00:00.000000000 +0000
@@ -1,385 +0,0 @@
-# Copyright (C) 2018 and later: Unicode, Inc. and others.
-# License & terms of use: http://www.unicode.org/copyright.html
-
-# Python 2/3 Compatibility (ICU-20299)
-# TODO(ICU-20301): Remove this.
-from __future__ import print_function
-
-from abc import abstractmethod
-from collections import defaultdict
-import re
-import sys
-
-from . import *
-from . import utils
-from .locale_dependencies import data as DEPENDENCY_DATA
-from .request_types import *
-
-
-# Note: for this to be a proper abstract class, it should extend abc.ABC.
-# There is no nice way to do this that works in both Python 2 and 3.
-# TODO(ICU-20301): Make this inherit from abc.ABC.
-class Filter(object):
- @staticmethod
- def create_from_json(json_data):
- if "filterType" in json_data:
- filter_type = json_data["filterType"]
- else:
- filter_type = "file-stem"
-
- if filter_type == "file-stem":
- return FileStemFilter(json_data)
- elif filter_type == "language":
- return LanguageFilter(json_data)
- elif filter_type == "regex":
- return RegexFilter(json_data)
- elif filter_type == "exclude":
- return ExclusionFilter()
- elif filter_type == "union":
- return UnionFilter(json_data)
- elif filter_type == "locale":
- return LocaleFilter(json_data)
- else:
- print("Error: Unknown filterType option: %s" % filter_type, file=sys.stderr)
- return None
-
- def filter(self, request):
- if not request.apply_file_filter(self):
- return []
- for file in request.all_input_files():
- assert self.match(file)
- return [request]
-
- @classmethod
- def _file_to_file_stem(cls, file):
- start = file.filename.rfind("/")
- limit = file.filename.rfind(".")
- return file.filename[start+1:limit]
-
- @abstractmethod
- def match(self, file):
- pass
-
-
-class InclusionFilter(Filter):
- def match(self, file):
- return True
-
-
-class ExclusionFilter(Filter):
- def match(self, file):
- return False
-
-
-class WhitelistBlacklistFilter(Filter):
- def __init__(self, json_data):
- if "whitelist" in json_data:
- self.is_whitelist = True
- self.whitelist = json_data["whitelist"]
- else:
- assert "blacklist" in json_data, "Need either whitelist or blacklist: %s" % str(json_data)
- self.is_whitelist = False
- self.blacklist = json_data["blacklist"]
-
- def match(self, file):
- file_stem = self._file_to_file_stem(file)
- return self._should_include(file_stem)
-
- @abstractmethod
- def _should_include(self, file_stem):
- pass
-
-
-class FileStemFilter(WhitelistBlacklistFilter):
- def _should_include(self, file_stem):
- if self.is_whitelist:
- return file_stem in self.whitelist
- else:
- return file_stem not in self.blacklist
-
-
-class LanguageFilter(WhitelistBlacklistFilter):
- def _should_include(self, file_stem):
- language = file_stem.split("_")[0]
- if language == "root":
- # Always include root.txt
- return True
- if self.is_whitelist:
- return language in self.whitelist
- else:
- return language not in self.blacklist
-
-
-class RegexFilter(WhitelistBlacklistFilter):
- def __init__(self, *args):
- # TODO(ICU-20301): Change this to: super().__init__(*args)
- super(RegexFilter, self).__init__(*args)
- if self.is_whitelist:
- self.whitelist = [re.compile(pat) for pat in self.whitelist]
- else:
- self.blacklist = [re.compile(pat) for pat in self.blacklist]
-
- def _should_include(self, file_stem):
- if self.is_whitelist:
- for pattern in self.whitelist:
- if pattern.match(file_stem):
- return True
- return False
- else:
- for pattern in self.blacklist:
- if pattern.match(file_stem):
- return False
- return True
-
-
-class UnionFilter(Filter):
- def __init__(self, json_data):
- # Collect the sub-filters.
- self.sub_filters = []
- for filter_json in json_data["unionOf"]:
- self.sub_filters.append(Filter.create_from_json(filter_json))
-
- def match(self, file):
- """Match iff any of the sub-filters match."""
- for filter in self.sub_filters:
- if filter.match(file):
- return True
- return False
-
-
-LANGUAGE_SCRIPT_REGEX = re.compile(r"^([a-z]{2,3})_[A-Z][a-z]{3}$")
-LANGUAGE_ONLY_REGEX = re.compile(r"^[a-z]{2,3}$")
-
-class LocaleFilter(Filter):
- def __init__(self, json_data):
- self.locales_requested = set()
- self.locales_required = set()
- self.include_children = json_data.get("includeChildren", True)
- self.include_scripts = json_data.get("includeScripts", False)
-
- # Compute the requested and required locales.
- for locale in json_data["whitelist"]:
- self._add_locale_and_parents(locale)
-
- def _add_locale_and_parents(self, locale):
- # Store the locale as *requested*
- self.locales_requested.add(locale)
- # Store the locale and its dependencies as *required*
- while locale is not None:
- self.locales_required.add(locale)
- locale = self._get_parent_locale(locale)
-
- def match(self, file):
- locale = self._file_to_file_stem(file)
-
- # A locale is *required* if it is *requested* or an ancestor of a
- # *requested* locale.
- if locale in self.locales_required:
- return True
-
- # Resolve include_scripts and include_children.
- return self._match_recursive(locale)
-
- def _match_recursive(self, locale):
- # Base case: return True if we reached a *requested* locale,
- # or False if we ascend out of the locale tree.
- if locale is None:
- return False
- if locale in self.locales_requested:
- return True
-
- # Check for alternative scripts.
- # This causes sr_Latn to check sr instead of going directly to root.
- if self.include_scripts:
- match = LANGUAGE_SCRIPT_REGEX.match(locale)
- if match and self._match_recursive(match.group(1)):
- return True
-
- # Check if we are a descendant of a *requested* locale.
- if self.include_children:
- parent = self._get_parent_locale(locale)
- if self._match_recursive(parent):
- return True
-
- # No matches.
- return False
-
- @classmethod
- def _get_parent_locale(cls, locale):
- if locale in DEPENDENCY_DATA["parents"]:
- return DEPENDENCY_DATA["parents"][locale]
- if locale in DEPENDENCY_DATA["aliases"]:
- return DEPENDENCY_DATA["aliases"][locale]
- if LANGUAGE_ONLY_REGEX.match(locale):
- return "root"
- i = locale.rfind("_")
- if i < 0:
- return None
- return locale[:i]
-
-
-def apply_filters(requests, config):
- """Runs the filters and returns a new list of requests."""
- requests = _apply_file_filters(requests, config)
- requests = _apply_resource_filters(requests, config)
- return requests
-
-
-def _apply_file_filters(old_requests, config):
- """Filters out entire files."""
- filters = _preprocess_file_filters(old_requests, config)
- new_requests = []
- for request in old_requests:
- category = request.category
- if category in filters:
- new_requests += filters[category].filter(request)
- else:
- new_requests.append(request)
- return new_requests
-
-
-def _preprocess_file_filters(requests, config):
- all_categories = set(
- request.category
- for request in requests
- )
- all_categories.remove(None)
- all_categories = list(sorted(all_categories))
- json_data = config.filters_json_data
- filters = {}
- for category in all_categories:
- if "featureFilters" in json_data and category in json_data["featureFilters"]:
- filters[category] = Filter.create_from_json(
- json_data["featureFilters"][category]
- )
- elif "localeFilter" in json_data and category[-5:] == "_tree":
- filters[category] = Filter.create_from_json(
- json_data["localeFilter"]
- )
- if "featureFilters" in json_data:
- for category in json_data["featureFilters"]:
- if category not in all_categories:
- print("Warning: category %s is not known" % category, file=sys.stderr)
- return filters
-
-
-class ResourceFilterInfo(object):
- def __init__(self, category):
- self.category = category
- self.filter_tmp_dir = "filters/%s" % category
- self.input_files = None
- self.filter_files = None
- self.rules_by_file = None
-
- def apply_to_requests(self, all_requests):
- # Call this method only once per list of requests.
- assert self.input_files is None
- for request in all_requests:
- if request.category != self.category:
- continue
- if not isinstance(request, AbstractExecutionRequest):
- continue
- if request.tool != IcuTool("genrb"):
- continue
- if not request.input_files:
- continue
- self._set_files(request.input_files)
- request.dep_targets += [self.filter_files[:]]
- arg_str = "--filterDir {TMP_DIR}/%s" % self.filter_tmp_dir
- request.args = "%s %s" % (arg_str, request.args)
-
- # Make sure we found the target request
- if self.input_files is None:
- print("WARNING: Category not found: %s" % self.category, file=sys.stderr)
- self.input_files = []
- self.filter_files = []
- self.rules_by_file = []
-
- def _set_files(self, files):
- # Note: The input files to genrb for a certain category should always
- # be the same. For example, there are often two genrb calls: one for
- # --writePoolBundle, and the other for --usePoolBundle. They are both
- # expected to have the same list of input files.
- if self.input_files is not None:
- assert self.input_files == files
- return
- self.input_files = list(files)
- self.filter_files = [
- TmpFile("%s/%s" % (self.filter_tmp_dir, basename))
- for basename in (
- file.filename[file.filename.rfind("/")+1:]
- for file in files
- )
- ]
- self.rules_by_file = [[] for _ in range(len(files))]
-
- def add_rules(self, file_filter, rules):
- for file, rule_list in zip(self.input_files, self.rules_by_file):
- if file_filter.match(file):
- rule_list += rules
-
- def make_requests(self):
- # Map from rule list to filter files with that rule list
- unique_rules = defaultdict(list)
- for filter_file, rules in zip(self.filter_files, self.rules_by_file):
- unique_rules[tuple(rules)].append(filter_file)
-
- new_requests = []
- i = 0
- for rules, filter_files in unique_rules.items():
- base_filter_file = filter_files[0]
- new_requests += [
- PrintFileRequest(
- name = "%s_print_%d" % (self.category, i),
- output_file = base_filter_file,
- content = self._generate_resource_filter_txt(rules)
- )
- ]
- i += 1
- for filter_file in filter_files[1:]:
- new_requests += [
- CopyRequest(
- name = "%s_copy_%d" % (self.category, i),
- input_file = base_filter_file,
- output_file = filter_file
- )
- ]
- i += 1
- return new_requests
-
- @classmethod
- def _generate_resource_filter_txt(cls, rules):
- result = "# Caution: This file is automatically generated\n\n"
- result += "\n".join(rules)
- return result
-
-
-def _apply_resource_filters(all_requests, config):
- """Creates filters for looking within resource bundle files."""
- json_data = config.filters_json_data
- if "resourceFilters" not in json_data:
- return all_requests
-
- collected = {}
- for entry in json_data["resourceFilters"]:
- if "files" in entry:
- file_filter = Filter.create_from_json(entry["files"])
- else:
- file_filter = InclusionFilter()
- for category in entry["categories"]:
- # not defaultdict because we need to pass arguments to the constructor
- if category not in collected:
- filter_info = ResourceFilterInfo(category)
- filter_info.apply_to_requests(all_requests)
- collected[category] = filter_info
- else:
- filter_info = collected[category]
- filter_info.add_rules(file_filter, entry["rules"])
-
- # Add the filter generation requests to the beginning so that by default
- # they are made before genrb gets run (order is required by windirect)
- new_requests = []
- for filter_info in collected.values():
- new_requests += filter_info.make_requests()
- new_requests += all_requests
- return new_requests
diff -Nru icu-64.2/source/data/buildtool/filtration_schema.json icu-65.1/source/data/buildtool/filtration_schema.json
--- icu-64.2/source/data/buildtool/filtration_schema.json 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/data/buildtool/filtration_schema.json 1970-01-01 00:00:00.000000000 +0000
@@ -1,146 +0,0 @@
-// Copyright (C) 2018 and later: Unicode, Inc. and others.
-// License & terms of use: http://www.unicode.org/copyright.html
-
-{
- "$id": "http://unicode.org/icu-filter-schema",
- "$schema": "http://json-schema.org/draft-04/schema#",
- "description": "JSON Schema for an ICU data filter file",
- "type": "object",
- "properties": {
- "localeFilter": { "$ref": "#/definitions/filter" },
- "featureFilters": {
- "type": "object",
- "additionalProperties": { "$ref": "#/definitions/filter" }
- },
- "resourceFilters": {
- "type": "array",
- "items": {
- "type": "object",
- "properties": {
- "categories": {
- "type": "array",
- "items": { "type": "string" }
- },
- "files": { "$ref": "#/definitions/filter" },
- "rules": {
- "type": "array",
- "items": {
- "type": "string",
- "pattern": "^[+-]/((\\w+|\\*)(/\\w+|/\\*)*)?$"
- }
- }
- },
- "required": ["categories", "rules"],
- "additionalProperties": false
- }
- },
- "fileReplacements": {
- "type": "object",
- "properties": {
- "directory": { "type": "string" },
- "replacements": {
- "type": "array",
- "items": {
- "type": "object",
- "properties": {
- "src": { "type": "string" },
- "dest": { "type": "string" }
- },
- "additionalProperties": false,
- "required": ["src", "dest"]
- }
- }
- },
- "additionalProperties": false,
- "required": ["directory", "replacements"]
- },
- "collationUCAData": {
- "type": "string",
- "enum": ["unihan", "implicithan"]
- }
- },
- "additionalProperties": false,
- "definitions": {
- "filter": {
- "type": "object",
- "oneOf": [
- {
- "properties": {
- "filterType": {
- "$ref": "#/definitions/blacklistWhitelistFilterTypes"
- },
- "whitelist": { "$ref": "#/definitions/stringList" }
- },
- "required": ["whitelist"],
- "additionalProperties": false
- },
- {
- "properties": {
- "filterType": {
- "$ref": "#/definitions/blacklistWhitelistFilterTypes"
- },
- "blacklist": { "$ref": "#/definitions/stringList" }
- },
- "required": ["blacklist"],
- "additionalProperties": false
- },
- {
- "properties": {
- "filterType": {
- "type": "string",
- "enum": ["exclude"]
- }
- },
- "required": ["filterType"],
- "additionalProperties": false
- },
- {
- "properties": {
- "filterType": {
- "type": "string",
- "enum": ["locale"]
- },
- "includeChildren": {
- "type": "boolean"
- },
- "includeScripts": {
- "type": "boolean"
- },
- "whitelist": { "$ref": "#/definitions/stringList" }
- },
- "required": ["filterType", "whitelist"],
- "additionalProperties": false
- },
- {
- "properties": {
- "filterType": {
- "type": "string",
- "enum": ["union"]
- },
- "unionOf": {
- "type": "array",
- "items": { "$ref": "#/definitions/filter" }
- }
- },
- "required": ["filterType", "unionOf"],
- "additionalProperties": false
- }
- ]
- },
- "blacklistWhitelistFilterTypes": {
- "type": "string",
- "enum": [
- "language",
- "regex"
- ]
- },
- "stringList": {
- "type": "array",
- "items": {
- "type": "string"
- },
- "minItems": 1,
- "uniqueItems": true
- }
- }
-}
diff -Nru icu-64.2/source/data/buildtool/__init__.py icu-65.1/source/data/buildtool/__init__.py
--- icu-64.2/source/data/buildtool/__init__.py 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/data/buildtool/__init__.py 1970-01-01 00:00:00.000000000 +0000
@@ -1,16 +0,0 @@
-# Copyright (C) 2018 and later: Unicode, Inc. and others.
-# License & terms of use: http://www.unicode.org/copyright.html
-
-from collections import namedtuple
-
-LocalFile = namedtuple("LocalFile", ["dirname", "filename"])
-SrcFile = namedtuple("SrcFile", ["filename"])
-InFile = namedtuple("InFile", ["filename"])
-TmpFile = namedtuple("TmpFile", ["filename"])
-OutFile = namedtuple("OutFile", ["filename"])
-PkgFile = namedtuple("PkgFile", ["filename"])
-
-IcuTool = namedtuple("IcuTool", ["name"])
-SystemTool = namedtuple("SystemTool", ["name"])
-
-DepTarget = namedtuple("DepTarget", ["name"])
diff -Nru icu-64.2/source/data/buildtool/locale_dependencies.py icu-65.1/source/data/buildtool/locale_dependencies.py
--- icu-64.2/source/data/buildtool/locale_dependencies.py 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/data/buildtool/locale_dependencies.py 1970-01-01 00:00:00.000000000 +0000
@@ -1,224 +0,0 @@
-# -*- coding: utf-8 -*-
-# © 2019 and later: Unicode, Inc. and others.
-# License & terms of use: http://www.unicode.org/copyright.html#License
-
-data = {
- "cldrVersion": "35.1",
- "aliases": {
- "ars": "ar_SA",
- "az_AZ": "az_Latn_AZ",
- "bs_BA": "bs_Latn_BA",
- "en_NH": "en_VU",
- "en_RH": "en_ZW",
- "ff_CM": "ff_Latn_CM",
- "ff_GN": "ff_Latn_GN",
- "ff_MR": "ff_Latn_MR",
- "ff_SN": "ff_Latn_SN",
- "in": "id",
- "in_ID": "id_ID",
- "iw": "he",
- "iw_IL": "he_IL",
- "mo": "ro",
- "no_NO": "nb_NO",
- "no_NO_NY": "nn_NO",
- "no": "nb",
- "pa_IN": "pa_Guru_IN",
- "pa_PK": "pa_Arab_PK",
- "sh": "sr_Latn",
- "sh_BA": "sr_Latn_BA",
- "sh_CS": "sr_Latn_RS",
- "sh_YU": "sr_Latn_RS",
- "shi_MA": "shi_Tfng_MA",
- "sr_BA": "sr_Cyrl_BA",
- "sr_CS": "sr_Cyrl_RS",
- "sr_ME": "sr_Latn_ME",
- "sr_RS": "sr_Cyrl_RS",
- "sr_XK": "sr_Cyrl_XK",
- "sr_YU": "sr_Cyrl_RS",
- "sr_Cyrl_YU": "sr_Cyrl_RS",
- "sr_Cyrl_CS": "sr_Cyrl_RS",
- "sr_Latn_YU": "sr_Latn_RS",
- "sr_Latn_CS": "sr_Latn_RS",
- "tl": "fil",
- "tl_PH": "fil_PH",
- "uz_AF": "uz_Arab_AF",
- "uz_UZ": "uz_Latn_UZ",
- "vai_LR": "vai_Vaii_LR",
- "yue_CN": "yue_Hans_CN",
- "yue_HK": "yue_Hant_HK",
- "zh_CN": "zh_Hans_CN",
- "zh_HK": "zh_Hant_HK",
- "zh_MO": "zh_Hant_MO",
- "zh_SG": "zh_Hans_SG",
- "zh_TW": "zh_Hant_TW"
- },
- "parents": {
- "ff_Adlm": "root",
- "en_CM": "en_001",
- "so_Arab": "root",
- "en_KY": "en_001",
- "en_TC": "en_001",
- "yue_Hans": "root",
- "en_CX": "en_001",
- "es_EC": "es_419",
- "es_US": "es_419",
- "byn_Latn": "root",
- "en_CY": "en_001",
- "en_LC": "en_001",
- "en_TK": "en_001",
- "tg_Arab": "root",
- "es_UY": "es_419",
- "ky_Latn": "root",
- "en_TO": "en_001",
- "en_TT": "en_001",
- "en_DE": "en_150",
- "es_MX": "es_419",
- "en_TV": "en_001",
- "en_DG": "en_001",
- "pt_ST": "pt_PT",
- "en_DM": "en_001",
- "en_LR": "en_001",
- "en_TZ": "en_001",
- "en_LS": "en_001",
- "en_DK": "en_150",
- "blt_Latn": "root",
- "es_VE": "es_419",
- "es_NI": "es_419",
- "sd_Khoj": "root",
- "pt_AO": "pt_PT",
- "en_UG": "en_001",
- "yo_Arab": "root",
- "dje_Arab": "root",
- "en_MG": "en_001",
- "en_MO": "en_001",
- "en_MU": "en_001",
- "en_MS": "en_001",
- "en_MT": "en_001",
- "shi_Latn": "root",
- "es_BR": "es_419",
- "en_AU": "en_001",
- "en_ZM": "en_001",
- "en_AT": "en_150",
- "es_BZ": "es_419",
- "uz_Arab": "root",
- "az_Cyrl": "root",
- "es_SV": "es_419",
- "en_ZW": "en_001",
- "en_JE": "en_001",
- "en_BB": "en_001",
- "sd_Deva": "root",
- "pa_Arab": "root",
- "en_RW": "en_001",
- "es_CO": "es_419",
- "en_JM": "en_001",
- "en_BE": "en_150",
- "dyo_Arab": "root",
- "es_CL": "es_419",
- "en_BM": "en_001",
- "en_SC": "en_001",
- "es_CR": "es_419",
- "en_150": "en_001",
- "en_BS": "en_001",
- "en_SD": "en_001",
- "pt_GQ": "pt_PT",
- "en_SB": "en_001",
- "es_CU": "es_419",
- "en_SG": "en_001",
- "uz_Cyrl": "root",
- "en_BW": "en_001",
- "en_SH": "en_001",
- "en_SE": "en_150",
- "pt_GW": "pt_PT",
- "ky_Arab": "root",
- "en_BZ": "en_001",
- "en_SL": "en_001",
- "en_SI": "en_150",
- "ff_Arab": "root",
- "en_KE": "en_001",
- "bm_Nkoo": "root",
- "en_CC": "en_001",
- "en_SS": "en_001",
- "iu_Latn": "root",
- "en_CA": "en_001",
- "en_KI": "en_001",
- "es_DO": "es_419",
- "en_SX": "en_001",
- "en_CH": "en_150",
- "en_KN": "en_001",
- "en_CK": "en_001",
- "ml_Arab": "root",
- "en_SZ": "en_001",
- "pt_FR": "pt_PT",
- "ug_Cyrl": "root",
- "en_GY": "en_001",
- "en_PH": "en_001",
- "en_PG": "en_001",
- "en_PK": "en_001",
- "cu_Glag": "root",
- "en_PN": "en_001",
- "kk_Arab": "root",
- "en_HK": "en_001",
- "zh_Hant": "root",
- "en_PW": "en_001",
- "es_AR": "es_419",
- "pt_MZ": "pt_PT",
- "sd_Sind": "root",
- "en_Shaw": "root",
- "en_IE": "en_001",
- "ms_Arab": "root",
- "en_IM": "en_001",
- "en_IN": "en_001",
- "es_BO": "es_419",
- "en_IL": "en_001",
- "en_AI": "en_001",
- "az_Arab": "root",
- "en_AG": "en_001",
- "en_IO": "en_001",
- "en_ZA": "en_001",
- "en_MY": "en_001",
- "en_ER": "en_001",
- "en_VC": "en_001",
- "mn_Mong": "root",
- "vai_Latn": "root",
- "en_MW": "en_001",
- "pt_LU": "pt_PT",
- "bs_Cyrl": "root",
- "en_VG": "en_001",
- "en_NA": "en_001",
- "en_NF": "en_001",
- "en_NG": "en_001",
- "ha_Arab": "root",
- "en_NL": "en_150",
- "zh_Hant_MO": "zh_Hant_HK",
- "en_VU": "en_001",
- "en_FJ": "en_001",
- "en_NR": "en_001",
- "en_FK": "en_001",
- "es_GT": "es_419",
- "en_FI": "en_150",
- "ku_Arab": "root",
- "pt_MO": "pt_PT",
- "en_FM": "en_001",
- "en_NU": "en_001",
- "en_NZ": "en_001",
- "pt_CH": "pt_PT",
- "en_Dsrt": "root",
- "es_PE": "es_419",
- "es_PA": "es_419",
- "pt_CV": "pt_PT",
- "wo_Arab": "root",
- "en_WS": "en_001",
- "en_GD": "en_001",
- "en_GB": "en_001",
- "es_HN": "es_419",
- "pt_TL": "pt_PT",
- "en_GG": "en_001",
- "en_GH": "en_001",
- "es_PR": "es_419",
- "sw_Arab": "root",
- "en_GI": "en_001",
- "sr_Latn": "root",
- "en_GM": "en_001",
- "es_PY": "es_419"
- }
-}
diff -Nru icu-64.2/source/data/buildtool/__main__.py icu-65.1/source/data/buildtool/__main__.py
--- icu-64.2/source/data/buildtool/__main__.py 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/data/buildtool/__main__.py 1970-01-01 00:00:00.000000000 +0000
@@ -1,292 +0,0 @@
-# Copyright (C) 2018 and later: Unicode, Inc. and others.
-# License & terms of use: http://www.unicode.org/copyright.html
-
-# Python 2/3 Compatibility (ICU-20299)
-# TODO(ICU-20301): Remove this.
-from __future__ import print_function
-
-import argparse
-import glob as pyglob
-import json
-import os
-import sys
-
-from . import *
-from .comment_stripper import CommentStripper
-from .request_types import CopyRequest
-from .renderers import makefile, unix_exec, windows_exec
-from . import filtration, utils
-import BUILDRULES
-
-flag_parser = argparse.ArgumentParser(
- description = """Generates rules for building ICU binary data files from text
-and other input files in source control.
-
-Use the --mode option to declare how to execute those rules, either exporting
-the rules to a Makefile or spawning child processes to run them immediately:
-
- --mode=gnumake prints a Makefile to standard out.
- --mode=unix-exec spawns child processes in a Unix-like environment.
- --mode=windows-exec spawns child processes in a Windows-like environment.
-
-Tips for --mode=unix-exec
-=========================
-
-Create two empty directories for out_dir and tmp_dir. They will get filled
-with a lot of intermediate files.
-
-Set LD_LIBRARY_PATH to include the lib directory. e.g., from icu4c/source:
-
- $ LD_LIBRARY_PATH=lib PYTHONPATH=data python3 -m buildtool ...
-
-Once buildtool finishes, you have compiled the data, but you have not packaged
-it into a .dat or .so file. This is done by the separate pkgdata tool in bin.
-Read the docs of pkgdata:
-
- $ LD_LIBRARY_PATH=lib ./bin/pkgdata --help
-
-Example command line to call pkgdata:
-
- $ LD_LIBRARY_PATH=lib ./bin/pkgdata -m common -p icudt63l -c \\
- -O data/icupkg.inc -s $OUTDIR -d $TMPDIR $TMPDIR/icudata.lst
-
-where $OUTDIR and $TMPDIR are your out and tmp directories, respectively.
-The above command will create icudt63l.dat in the tmpdir.
-
-Command-Line Arguments
-======================
-""",
- formatter_class = argparse.RawDescriptionHelpFormatter
-)
-
-arg_group_required = flag_parser.add_argument_group("required arguments")
-arg_group_required.add_argument(
- "--mode",
- help = "What to do with the generated rules.",
- choices = ["gnumake", "unix-exec", "windows-exec"],
- required = True
-)
-
-flag_parser.add_argument(
- "--src_dir",
- help = "Path to data source folder (icu4c/source/data).",
- default = "."
-)
-flag_parser.add_argument(
- "--filter_file",
- metavar = "PATH",
- help = "Path to an ICU data filter JSON file.",
- default = None
-)
-flag_parser.add_argument(
- "--include_uni_core_data",
- help = "Include the full Unicode core data in the dat file.",
- default = False,
- action = "store_true"
-)
-flag_parser.add_argument(
- "--seqmode",
- help = "Whether to optimize rules to be run sequentially (fewer threads) or in parallel (many threads). Defaults to 'sequential', which is better for unix-exec and windows-exec modes. 'parallel' is often better for massively parallel build systems.",
- choices = ["sequential", "parallel"],
- default = "sequential"
-)
-
-arg_group_exec = flag_parser.add_argument_group("arguments for unix-exec and windows-exec modes")
-arg_group_exec.add_argument(
- "--out_dir",
- help = "Path to where to save output data files.",
- default = "icudata"
-)
-arg_group_exec.add_argument(
- "--tmp_dir",
- help = "Path to where to save temporary files.",
- default = "icutmp"
-)
-arg_group_exec.add_argument(
- "--tool_dir",
- help = "Path to where to find binary tools (genrb, etc).",
- default = "../bin"
-)
-arg_group_exec.add_argument(
- "--tool_cfg",
- help = "The build configuration of the tools. Used in 'windows-exec' mode only.",
- default = "x86/Debug"
-)
-
-
-class Config(object):
-
- def __init__(self, args):
- # Process arguments
- self.max_parallel = (args.seqmode == "parallel")
-
- # Boolean: Whether to include core Unicode data files in the .dat file
- self.include_uni_core_data = args.include_uni_core_data
-
- # Default fields before processing filter file
- self.filters_json_data = {}
-
- # Process filter file
- if args.filter_file:
- try:
- with open(args.filter_file, "r") as f:
- print("Note: Applying filters from %s." % args.filter_file, file=sys.stderr)
- self._parse_filter_file(f)
- except IOError:
- print("Error: Could not read filter file %s." % args.filter_file, file=sys.stderr)
- exit(1)
-
- # Either "unihan" or "implicithan"
- self.coll_han_type = "unihan"
- if "collationUCAData" in self.filters_json_data:
- self.coll_han_type = self.filters_json_data["collationUCAData"]
-
- def _parse_filter_file(self, f):
- # Use the Hjson parser if it is available; otherwise, use vanilla JSON.
- try:
- import hjson
- self.filters_json_data = hjson.load(f)
- except ImportError:
- self.filters_json_data = json.load(CommentStripper(f))
-
- # Optionally pre-validate the JSON schema before further processing.
- # Some schema errors will be caught later, but this step ensures
- # maximal validity.
- try:
- import jsonschema
- schema_path = os.path.join(os.path.dirname(__file__), "filtration_schema.json")
- with open(schema_path) as schema_f:
- schema = json.load(CommentStripper(schema_f))
- validator = jsonschema.Draft4Validator(schema)
- for error in validator.iter_errors(self.filters_json_data, schema):
- print("WARNING: ICU data filter JSON file:", error.message,
- "at", "".join(
- "[%d]" % part if isinstance(part, int) else ".%s" % part
- for part in error.absolute_path
- ),
- file=sys.stderr)
- except ImportError:
- print("Tip: to validate your filter file, install the Pip package 'jsonschema'", file=sys.stderr)
- pass
-
-
-def add_copy_input_requests(requests, config, common_vars):
- files_to_copy = set()
- for request in requests:
- for f in request.all_input_files():
- if isinstance(f, InFile):
- files_to_copy.add(f)
-
- result = []
- id = 0
-
- json_data = config.filters_json_data["fileReplacements"]
- dirname = json_data["directory"]
- for directive in json_data["replacements"]:
- input_file = LocalFile(dirname, directive["src"])
- output_file = InFile(directive["dest"])
- result += [
- CopyRequest(
- name = "input_copy_%d" % id,
- input_file = input_file,
- output_file = output_file
- )
- ]
- files_to_copy.remove(output_file)
- id += 1
-
- for f in files_to_copy:
- result += [
- CopyRequest(
- name = "input_copy_%d" % id,
- input_file = SrcFile(f.filename),
- output_file = f
- )
- ]
- id += 1
-
- result += requests
- return result
-
-
-def main():
- args = flag_parser.parse_args()
- config = Config(args)
-
- if args.mode == "gnumake":
- makefile_vars = {
- "SRC_DIR": "$(srcdir)",
- "IN_DIR": "$(srcdir)",
- "INDEX_NAME": "res_index"
- }
- makefile_env = ["ICUDATA_CHAR", "OUT_DIR", "TMP_DIR"]
- common = {
- key: "$(%s)" % key
- for key in list(makefile_vars.keys()) + makefile_env
- }
- common["GLOB_DIR"] = args.src_dir
- else:
- common = {
- # GLOB_DIR is used now, whereas IN_DIR is used during execution phase.
- # There is no useful distinction in unix-exec or windows-exec mode.
- "GLOB_DIR": args.src_dir,
- "SRC_DIR": args.src_dir,
- "IN_DIR": args.src_dir,
- "OUT_DIR": args.out_dir,
- "TMP_DIR": args.tmp_dir,
- "INDEX_NAME": "res_index",
- # TODO: Pull this from configure script:
- "ICUDATA_CHAR": "l"
- }
-
- def glob(pattern):
- result_paths = pyglob.glob("{GLOB_DIR}/{PATTERN}".format(
- GLOB_DIR = args.src_dir,
- PATTERN = pattern
- ))
- # For the purposes of buildtool, force Unix-style directory separators.
- return [v.replace("\\", "/")[len(args.src_dir)+1:] for v in sorted(result_paths)]
-
- requests = BUILDRULES.generate(config, glob, common)
- requests = filtration.apply_filters(requests, config)
- requests = utils.flatten_requests(requests, config, common)
-
- if "fileReplacements" in config.filters_json_data:
- tmp_in_dir = "{TMP_DIR}/in".format(**common)
- if makefile_vars:
- makefile_vars["IN_DIR"] = tmp_in_dir
- else:
- common["IN_DIR"] = tmp_in_dir
- requests = add_copy_input_requests(requests, config, common)
-
- build_dirs = utils.compute_directories(requests)
-
- if args.mode == "gnumake":
- print(makefile.get_gnumake_rules(
- build_dirs,
- requests,
- makefile_vars,
- common_vars = common
- ))
- elif args.mode == "windows-exec":
- return windows_exec.run(
- build_dirs = build_dirs,
- requests = requests,
- common_vars = common,
- tool_dir = args.tool_dir,
- tool_cfg = args.tool_cfg
- )
- elif args.mode == "unix-exec":
- return unix_exec.run(
- build_dirs = build_dirs,
- requests = requests,
- common_vars = common,
- tool_dir = args.tool_dir
- )
- else:
- print("Mode not supported: %s" % args.mode)
- return 1
- return 0
-
-if __name__ == "__main__":
- exit(main())
diff -Nru icu-64.2/source/data/buildtool/renderers/common_exec.py icu-65.1/source/data/buildtool/renderers/common_exec.py
--- icu-64.2/source/data/buildtool/renderers/common_exec.py 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/data/buildtool/renderers/common_exec.py 1970-01-01 00:00:00.000000000 +0000
@@ -1,93 +0,0 @@
-# Copyright (C) 2018 and later: Unicode, Inc. and others.
-# License & terms of use: http://www.unicode.org/copyright.html
-
-from . import *
-from .. import *
-from .. import utils
-from ..request_types import *
-
-import os
-import shutil
-import subprocess
-
-def run(build_dirs, requests, common_vars, **kwargs):
- for bd in build_dirs:
- os.makedirs(bd.format(**common_vars), exist_ok=True)
- for request in requests:
- status = run_helper(request, common_vars, **kwargs)
- if status != 0:
- print("!!! ERROR executing above command line: exit code %d" % status)
- return 1
- print("All data build commands executed")
- return 0
-
-def run_helper(request, common_vars, is_windows, tool_dir, tool_cfg=None, **kwargs):
- if isinstance(request, PrintFileRequest):
- output_path = "{DIRNAME}/{FILENAME}".format(
- DIRNAME = utils.dir_for(request.output_file).format(**common_vars),
- FILENAME = request.output_file.filename,
- )
- print("Printing to file: %s" % output_path)
- with open(output_path, "w") as f:
- f.write(request.content)
- return 0
- if isinstance(request, CopyRequest):
- input_path = "{DIRNAME}/{FILENAME}".format(
- DIRNAME = utils.dir_for(request.input_file).format(**common_vars),
- FILENAME = request.input_file.filename,
- )
- output_path = "{DIRNAME}/{FILENAME}".format(
- DIRNAME = utils.dir_for(request.output_file).format(**common_vars),
- FILENAME = request.output_file.filename,
- )
- print("Copying file to: %s" % output_path)
- shutil.copyfile(input_path, output_path)
- return 0
- if isinstance(request, VariableRequest):
- # No-op
- return 0
-
- assert isinstance(request.tool, IcuTool)
- if is_windows:
- cmd_template = "{TOOL_DIR}/{TOOL}/{TOOL_CFG}/{TOOL}.exe {{ARGS}}".format(
- TOOL_DIR = tool_dir,
- TOOL_CFG = tool_cfg,
- TOOL = request.tool.name,
- **common_vars
- )
- else:
- cmd_template = "{TOOL_DIR}/{TOOL} {{ARGS}}".format(
- TOOL_DIR = tool_dir,
- TOOL = request.tool.name,
- **common_vars
- )
-
- if isinstance(request, RepeatedExecutionRequest):
- for loop_vars in utils.repeated_execution_request_looper(request):
- command_line = utils.format_repeated_request_command(
- request,
- cmd_template,
- loop_vars,
- common_vars
- )
- if is_windows:
- # Note: this / to \ substitution may be too aggressive?
- command_line = command_line.replace("/", "\\")
- print("Running: %s" % command_line)
- res = subprocess.run(command_line, shell=True)
- if res.returncode != 0:
- return res.returncode
- return 0
- if isinstance(request, SingleExecutionRequest):
- command_line = utils.format_single_request_command(
- request,
- cmd_template,
- common_vars
- )
- if is_windows:
- # Note: this / to \ substitution may be too aggressive?
- command_line = command_line.replace("/", "\\")
- print("Running: %s" % command_line)
- res = subprocess.run(command_line, shell=True)
- return res.returncode
- assert False
diff -Nru icu-64.2/source/data/buildtool/renderers/__init__.py icu-65.1/source/data/buildtool/renderers/__init__.py
--- icu-64.2/source/data/buildtool/renderers/__init__.py 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/data/buildtool/renderers/__init__.py 1970-01-01 00:00:00.000000000 +0000
@@ -1,10 +0,0 @@
-# Copyright (C) 2018 and later: Unicode, Inc. and others.
-# License & terms of use: http://www.unicode.org/copyright.html
-
-from collections import namedtuple
-
-MakeRule = namedtuple("MakeRule", ["name", "dep_literals", "dep_files", "output_file", "cmds"])
-
-MakeFilesVar = namedtuple("MakeFilesVar", ["name", "files"])
-
-MakeStringVar = namedtuple("MakeStringVar", ["name", "content"])
diff -Nru icu-64.2/source/data/buildtool/renderers/makefile.py icu-65.1/source/data/buildtool/renderers/makefile.py
--- icu-64.2/source/data/buildtool/renderers/makefile.py 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/data/buildtool/renderers/makefile.py 1970-01-01 00:00:00.000000000 +0000
@@ -1,245 +0,0 @@
-# Copyright (C) 2018 and later: Unicode, Inc. and others.
-# License & terms of use: http://www.unicode.org/copyright.html
-
-# Python 2/3 Compatibility (ICU-20299)
-# TODO(ICU-20301): Remove this.
-from __future__ import print_function
-
-from . import *
-from .. import *
-from .. import utils
-from ..request_types import *
-
-def get_gnumake_rules(build_dirs, requests, makefile_vars, **kwargs):
- makefile_string = ""
-
- # Common Variables
- common_vars = kwargs["common_vars"]
- for key, value in sorted(makefile_vars.items()):
- makefile_string += "{KEY} = {VALUE}\n".format(
- KEY = key,
- VALUE = value
- )
- makefile_string += "\n"
-
- # Directories
- dirs_timestamp_file = "{TMP_DIR}/dirs.timestamp".format(**common_vars)
- makefile_string += "DIRS = {TIMESTAMP_FILE}\n\n".format(
- TIMESTAMP_FILE = dirs_timestamp_file
- )
- makefile_string += "{TIMESTAMP_FILE}:\n\t$(MKINSTALLDIRS) {ALL_DIRS}\n\techo timestamp > {TIMESTAMP_FILE}\n\n".format(
- TIMESTAMP_FILE = dirs_timestamp_file,
- ALL_DIRS = " ".join(build_dirs).format(**common_vars)
- )
-
- # Generate Rules
- make_rules = []
- for request in requests:
- make_rules += get_gnumake_rules_helper(request, **kwargs)
-
- # Main Commands
- for rule in make_rules:
- if isinstance(rule, MakeFilesVar):
- makefile_string += "{NAME} = {FILE_LIST}\n\n".format(
- NAME = rule.name,
- FILE_LIST = files_to_makefile(rule.files, wrap = True, **kwargs),
- )
- continue
-
- if isinstance(rule, MakeStringVar):
- makefile_string += "define {NAME}\n{CONTENT}\nendef\nexport {NAME}\n\n".format(
- NAME = rule.name,
- CONTENT = rule.content
- )
- continue
-
- assert isinstance(rule, MakeRule)
- header_line = "{OUT_FILE}: {DEP_FILES} {DEP_LITERALS} | $(DIRS)".format(
- OUT_FILE = files_to_makefile([rule.output_file], **kwargs),
- DEP_FILES = files_to_makefile(rule.dep_files, wrap = True, **kwargs),
- DEP_LITERALS = " ".join(rule.dep_literals)
- )
-
- if len(rule.cmds) == 0:
- makefile_string += "%s\n\n" % header_line
- continue
-
- makefile_string += "{HEADER_LINE}\n{RULE_LINES}\n\n".format(
- HEADER_LINE = header_line,
- RULE_LINES = "\n".join("\t%s" % cmd for cmd in rule.cmds)
- )
-
- return makefile_string
-
-def files_to_makefile(files, common_vars, wrap = False, **kwargs):
- if len(files) == 0:
- return ""
- dirnames = [utils.dir_for(file).format(**common_vars) for file in files]
- join_str = " \\\n\t\t" if wrap and len(files) > 2 else " "
- if len(files) == 1:
- return "%s/%s" % (dirnames[0], files[0].filename)
- elif len(set(dirnames)) == 1:
- return "$(addprefix %s/,%s)" % (dirnames[0], join_str.join(file.filename for file in files))
- else:
- return join_str.join("%s/%s" % (d, f.filename) for d,f in zip(dirnames, files))
-
-def get_gnumake_rules_helper(request, common_vars, **kwargs):
-
- if isinstance(request, PrintFileRequest):
- var_name = "%s_CONTENT" % request.name.upper()
- return [
- MakeStringVar(
- name = var_name,
- content = request.content
- ),
- MakeRule(
- name = request.name,
- dep_literals = [],
- dep_files = [],
- output_file = request.output_file,
- cmds = [
- "echo \"$${VAR_NAME}\" > {MAKEFILENAME}".format(
- VAR_NAME = var_name,
- MAKEFILENAME = files_to_makefile([request.output_file], common_vars),
- **common_vars
- )
- ]
- )
- ]
-
-
- if isinstance(request, CopyRequest):
- return [
- MakeRule(
- name = request.name,
- dep_literals = [],
- dep_files = [request.input_file],
- output_file = request.output_file,
- cmds = ["cp %s %s" % (
- files_to_makefile([request.input_file], common_vars),
- files_to_makefile([request.output_file], common_vars))
- ]
- )
- ]
-
- if isinstance(request, VariableRequest):
- return [
- MakeFilesVar(
- name = request.name.upper(),
- files = request.input_files
- )
- ]
-
- if request.tool.name == "make":
- cmd_template = "$(MAKE) {ARGS}"
- elif request.tool.name == "gentest":
- cmd_template = "$(INVOKE) $(GENTEST) {ARGS}"
- else:
- assert isinstance(request.tool, IcuTool)
- cmd_template = "$(INVOKE) $(TOOLBINDIR)/{TOOL} {{ARGS}}".format(
- TOOL = request.tool.name
- )
-
- if isinstance(request, SingleExecutionRequest):
- cmd = utils.format_single_request_command(request, cmd_template, common_vars)
- dep_files = request.all_input_files()
-
- if len(request.output_files) > 1:
- # Special case for multiple output files: Makefile rules should have only one
- # output file apiece. More information:
- # https://www.gnu.org/software/automake/manual/html_node/Multiple-Outputs.html
- timestamp_var_name = "%s_ALL" % request.name.upper()
- timestamp_file = TmpFile("%s.timestamp" % request.name)
- rules = [
- MakeFilesVar(
- name = timestamp_var_name,
- files = [timestamp_file]
- ),
- MakeRule(
- name = "%s_all" % request.name,
- dep_literals = [],
- dep_files = dep_files,
- output_file = timestamp_file,
- cmds = [
- cmd,
- "echo timestamp > {MAKEFILENAME}".format(
- MAKEFILENAME = files_to_makefile([timestamp_file], common_vars)
- )
- ]
- )
- ]
- for i, file in enumerate(request.output_files):
- rules += [
- MakeRule(
- name = "%s_%d" % (request.name, i),
- dep_literals = ["$(%s)" % timestamp_var_name],
- dep_files = [],
- output_file = file,
- cmds = []
- )
- ]
- return rules
-
- elif len(dep_files) > 5:
- # For nicer printing, for long input lists, use a helper variable.
- dep_var_name = "%s_DEPS" % request.name.upper()
- return [
- MakeFilesVar(
- name = dep_var_name,
- files = dep_files
- ),
- MakeRule(
- name = request.name,
- dep_literals = ["$(%s)" % dep_var_name],
- dep_files = [],
- output_file = request.output_files[0],
- cmds = [cmd]
- )
- ]
-
- else:
- return [
- MakeRule(
- name = request.name,
- dep_literals = [],
- dep_files = dep_files,
- output_file = request.output_files[0],
- cmds = [cmd]
- )
- ]
-
- if isinstance(request, RepeatedExecutionRequest):
- rules = []
- dep_literals = []
- # To keep from repeating the same dep files many times, make a variable.
- if len(request.common_dep_files) > 0:
- dep_var_name = "%s_DEPS" % request.name.upper()
- dep_literals = ["$(%s)" % dep_var_name]
- rules += [
- MakeFilesVar(
- name = dep_var_name,
- files = request.common_dep_files
- )
- ]
- # Add a rule for each individual file.
- for loop_vars in utils.repeated_execution_request_looper(request):
- (_, specific_dep_files, input_file, output_file) = loop_vars
- name_suffix = input_file[input_file.filename.rfind("/")+1:input_file.filename.rfind(".")]
- cmd = utils.format_repeated_request_command(
- request,
- cmd_template,
- loop_vars,
- common_vars
- )
- rules += [
- MakeRule(
- name = "%s_%s" % (request.name, name_suffix),
- dep_literals = dep_literals,
- dep_files = specific_dep_files + [input_file],
- output_file = output_file,
- cmds = [cmd]
- )
- ]
- return rules
-
- assert False
diff -Nru icu-64.2/source/data/buildtool/renderers/unix_exec.py icu-65.1/source/data/buildtool/renderers/unix_exec.py
--- icu-64.2/source/data/buildtool/renderers/unix_exec.py 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/data/buildtool/renderers/unix_exec.py 1970-01-01 00:00:00.000000000 +0000
@@ -1,7 +0,0 @@
-# Copyright (C) 2018 and later: Unicode, Inc. and others.
-# License & terms of use: http://www.unicode.org/copyright.html
-
-from . import common_exec
-
-def run(**kwargs):
- return common_exec.run(is_windows=False, **kwargs)
diff -Nru icu-64.2/source/data/buildtool/renderers/windows_exec.py icu-65.1/source/data/buildtool/renderers/windows_exec.py
--- icu-64.2/source/data/buildtool/renderers/windows_exec.py 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/data/buildtool/renderers/windows_exec.py 1970-01-01 00:00:00.000000000 +0000
@@ -1,7 +0,0 @@
-# Copyright (C) 2018 and later: Unicode, Inc. and others.
-# License & terms of use: http://www.unicode.org/copyright.html
-
-from . import common_exec
-
-def run(**kwargs):
- return common_exec.run(is_windows=True, **kwargs)
diff -Nru icu-64.2/source/data/buildtool/request_types.py icu-65.1/source/data/buildtool/request_types.py
--- icu-64.2/source/data/buildtool/request_types.py 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/data/buildtool/request_types.py 1970-01-01 00:00:00.000000000 +0000
@@ -1,331 +0,0 @@
-# Copyright (C) 2018 and later: Unicode, Inc. and others.
-# License & terms of use: http://www.unicode.org/copyright.html
-
-# Python 2/3 Compatibility (ICU-20299)
-# TODO(ICU-20301): Remove this.
-from __future__ import print_function
-
-from abc import abstractmethod
-import copy
-import sys
-
-from . import *
-from . import utils
-
-
-# TODO(ICU-20301): Remove arguments from all instances of super() in this file
-
-# Note: for this to be a proper abstract class, it should extend abc.ABC.
-# There is no nice way to do this that works in both Python 2 and 3.
-# TODO(ICU-20301): Make this inherit from abc.ABC.
-class AbstractRequest(object):
- def __init__(self, **kwargs):
-
- # Used for identification purposes
- self.name = None
-
- # The filter category that applies to this request
- self.category = None
-
- self._set_fields(kwargs)
-
- def _set_fields(self, kwargs):
- for key, value in list(kwargs.items()):
- if hasattr(self, key):
- if isinstance(value, list):
- value = copy.copy(value)
- elif isinstance(value, dict):
- value = copy.deepcopy(value)
- setattr(self, key, value)
- else:
- raise ValueError("Unknown argument: %s" % key)
-
- def apply_file_filter(self, filter):
- """
- Returns True if this request still has input files after filtering,
- or False if the request is "empty" after filtering.
- """
- return True
-
- def flatten(self, config, all_requests, common_vars):
- return [self]
-
- def all_input_files(self):
- return []
-
- def all_output_files(self):
- return []
-
-
-class AbstractExecutionRequest(AbstractRequest):
- def __init__(self, **kwargs):
-
- # Names of targets (requests) or files that this request depends on.
- # The entries of dep_targets may be any of the following types:
- #
- # 1. DepTarget, for the output of an execution request.
- # 2. InFile, TmpFile, etc., for a specific file.
- # 3. A list of InFile, TmpFile, etc., where the list is the same
- # length as self.input_files and self.output_files.
- #
- # In cases 1 and 2, the dependency is added to all rules that the
- # request generates. In case 3, the dependency is added only to the
- # rule that generates the output file at the same array index.
- self.dep_targets = []
-
- # Computed during self.flatten(); don't edit directly.
- self.common_dep_files = []
-
- # Primary input files
- self.input_files = []
-
- # Output files; for some subclasses, this must be the same length
- # as input_files
- self.output_files = []
-
- # What tool to execute
- self.tool = None
-
- # Argument string to pass to the tool with optional placeholders
- self.args = ""
-
- # Placeholders to substitute into the argument string; if any of these
- # have a list type, the list must be equal in length to input_files
- self.format_with = {}
-
- super(AbstractExecutionRequest, self).__init__(**kwargs)
-
- def apply_file_filter(self, filter):
- i = 0
- while i < len(self.input_files):
- if filter.match(self.input_files[i]):
- i += 1
- continue
- self._del_at(i)
- return i > 0
-
- def _del_at(self, i):
- del self.input_files[i]
- for _, v in self.format_with.items():
- if isinstance(v, list):
- assert len(v) == len(self.input_files) + 1
- del v[i]
- for v in self.dep_targets:
- if isinstance(v, list):
- assert len(v) == len(self.input_files) + 1
- del v[i]
-
- def flatten(self, config, all_requests, common_vars):
- self._dep_targets_to_files(all_requests)
- return super(AbstractExecutionRequest, self).flatten(config, all_requests, common_vars)
-
- def _dep_targets_to_files(self, all_requests):
- if not self.dep_targets:
- return
- for dep_target in self.dep_targets:
- if isinstance(dep_target, list):
- if hasattr(self, "specific_dep_files"):
- assert len(dep_target) == len(self.specific_dep_files)
- for file, out_list in zip(dep_target, self.specific_dep_files):
- assert hasattr(file, "filename")
- out_list.append(file)
- else:
- self.common_dep_files += dep_target
- continue
- if not isinstance(dep_target, DepTarget):
- # Copy file entries directly to dep_files.
- assert hasattr(dep_target, "filename")
- self.common_dep_files.append(dep_target)
- continue
- # For DepTarget entries, search for the target.
- for request in all_requests:
- if request.name == dep_target.name:
- self.common_dep_files += request.all_output_files()
- break
- else:
- print("Warning: Unable to find target %s, a dependency of %s" % (
- dep_target.name,
- self.name
- ), file=sys.stderr)
-
- def all_input_files(self):
- return self.common_dep_files + self.input_files
-
- def all_output_files(self):
- return self.output_files
-
-
-class SingleExecutionRequest(AbstractExecutionRequest):
- def __init__(self, **kwargs):
- super(SingleExecutionRequest, self).__init__(**kwargs)
-
-
-class RepeatedExecutionRequest(AbstractExecutionRequest):
- def __init__(self, **kwargs):
-
- # Placeholders to substitute into the argument string unique to each
- # iteration; all values must be lists equal in length to input_files
- self.repeat_with = {}
-
- # Lists for dep files that are specific to individual resource bundle files
- self.specific_dep_files = [[] for _ in range(len(kwargs["input_files"]))]
-
- super(RepeatedExecutionRequest, self).__init__(**kwargs)
-
- def _del_at(self, i):
- super(RepeatedExecutionRequest, self)._del_at(i)
- del self.output_files[i]
- for _, v in self.repeat_with.items():
- if isinstance(v, list):
- del v[i]
-
- def all_input_files(self):
- files = super(RepeatedExecutionRequest, self).all_input_files()
- for specific_file_list in self.specific_dep_files:
- files += specific_file_list
- return files
-
-
-class RepeatedOrSingleExecutionRequest(AbstractExecutionRequest):
- def __init__(self, **kwargs):
- self.repeat_with = {}
- super(RepeatedOrSingleExecutionRequest, self).__init__(**kwargs)
-
- def flatten(self, config, all_requests, common_vars):
- if config.max_parallel:
- new_request = RepeatedExecutionRequest(
- name = self.name,
- category = self.category,
- dep_targets = self.dep_targets,
- input_files = self.input_files,
- output_files = self.output_files,
- tool = self.tool,
- args = self.args,
- format_with = self.format_with,
- repeat_with = self.repeat_with
- )
- else:
- new_request = SingleExecutionRequest(
- name = self.name,
- category = self.category,
- dep_targets = self.dep_targets,
- input_files = self.input_files,
- output_files = self.output_files,
- tool = self.tool,
- args = self.args,
- format_with = utils.concat_dicts(self.format_with, self.repeat_with)
- )
- return new_request.flatten(config, all_requests, common_vars)
-
- def _del_at(self, i):
- super(RepeatedOrSingleExecutionRequest, self)._del_at(i)
- del self.output_files[i]
- for _, v in self.repeat_with.items():
- if isinstance(v, list):
- del v[i]
-
-
-class PrintFileRequest(AbstractRequest):
- def __init__(self, **kwargs):
- self.output_file = None
- self.content = None
- super(PrintFileRequest, self).__init__(**kwargs)
-
- def all_output_files(self):
- return [self.output_file]
-
-
-class CopyRequest(AbstractRequest):
- def __init__(self, **kwargs):
- self.input_file = None
- self.output_file = None
- super(CopyRequest, self).__init__(**kwargs)
-
- def all_input_files(self):
- return [self.input_file]
-
- def all_output_files(self):
- return [self.output_file]
-
-
-class VariableRequest(AbstractRequest):
- def __init__(self, **kwargs):
- self.input_files = []
- super(VariableRequest, self).__init__(**kwargs)
-
- def all_input_files(self):
- return self.input_files
-
-
-class ListRequest(AbstractRequest):
- def __init__(self, **kwargs):
- self.variable_name = None
- self.output_file = None
- self.include_tmp = None
- super(ListRequest, self).__init__(**kwargs)
-
- def flatten(self, config, all_requests, common_vars):
- list_files = list(sorted(utils.get_all_output_files(all_requests)))
- if self.include_tmp:
- variable_files = list(sorted(utils.get_all_output_files(all_requests, include_tmp=True)))
- else:
- # Always include the list file itself
- variable_files = list_files + [self.output_file]
- return PrintFileRequest(
- name = self.name,
- output_file = self.output_file,
- content = "\n".join(file.filename for file in list_files)
- ).flatten(config, all_requests, common_vars) + VariableRequest(
- name = self.variable_name,
- input_files = variable_files
- ).flatten(config, all_requests, common_vars)
-
- def all_output_files(self):
- return [self.output_file]
-
-
-class IndexTxtRequest(AbstractRequest):
- def __init__(self, **kwargs):
- self.input_files = []
- self.output_file = None
- self.cldr_version = ""
- super(IndexTxtRequest, self).__init__(**kwargs)
-
- def apply_file_filter(self, filter):
- i = 0
- while i < len(self.input_files):
- if filter.match(self.input_files[i]):
- i += 1
- continue
- del self.input_files[i]
- return i > 0
-
- def flatten(self, config, all_requests, common_vars):
- return PrintFileRequest(
- name = self.name,
- output_file = self.output_file,
- content = self._generate_index_file(common_vars)
- ).flatten(config, all_requests, common_vars)
-
- def _generate_index_file(self, common_vars):
- locales = [f.filename[f.filename.rfind("/")+1:-4] for f in self.input_files]
- formatted_version = " CLDRVersion { \"%s\" }\n" % self.cldr_version if self.cldr_version else ""
- formatted_locales = "\n".join([" %s {\"\"}" % v for v in locales])
- # TODO: CLDRVersion is required only in the base file
- return ("// Warning this file is automatically generated\n"
- "{INDEX_NAME}:table(nofallback) {{\n"
- "{FORMATTED_VERSION}"
- " InstalledLocales {{\n"
- "{FORMATTED_LOCALES}\n"
- " }}\n"
- "}}").format(
- FORMATTED_VERSION = formatted_version,
- FORMATTED_LOCALES = formatted_locales,
- **common_vars
- )
-
- def all_input_files(self):
- return self.input_files
-
- def all_output_files(self):
- return [self.output_file]
diff -Nru icu-64.2/source/data/buildtool/test/filtration_test.py icu-65.1/source/data/buildtool/test/filtration_test.py
--- icu-64.2/source/data/buildtool/test/filtration_test.py 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/data/buildtool/test/filtration_test.py 1970-01-01 00:00:00.000000000 +0000
@@ -1,353 +0,0 @@
-# Copyright (C) 2018 and later: Unicode, Inc. and others.
-# License & terms of use: http://www.unicode.org/copyright.html
-
-import unittest
-
-from .. import InFile
-from ..filtration import Filter
-
-EXAMPLE_FILE_STEMS = [
- "af_NA",
- "af_ZA",
- "af",
- "ar",
- "ar_SA",
- "ars",
- "bs_BA",
- "bs_Cyrl_BA",
- "bs_Cyrl",
- "bs_Latn_BA",
- "bs_Latn",
- "bs",
- "en_001",
- "en_150",
- "en_DE",
- "en_GB",
- "en_US",
- "root",
- "sr_BA",
- "sr_CS",
- "sr_Cyrl_BA",
- "sr_Cyrl_CS",
- "sr_Cyrl_ME",
- "sr_Cyrl",
- "sr_Latn_BA",
- "sr_Latn_CS",
- "sr_Latn_ME",
- "sr_Latn",
- "sr_ME",
- "sr",
- "vai_Latn_LR",
- "vai_Latn",
- "vai_LR",
- "vai_Vaii_LR",
- "vai_Vaii",
- "vai",
- "zh_CN",
- "zh_Hans_CN",
- "zh_Hans_HK",
- "zh_Hans_MO",
- "zh_Hans_SG",
- "zh_Hans",
- "zh_Hant_HK",
- "zh_Hant_MO",
- "zh_Hant_TW",
- "zh_Hant",
- "zh_HK",
- "zh_MO",
- "zh_SG",
- "zh_TW",
- "zh"
-]
-
-class FiltrationTest(unittest.TestCase):
-
- def test_exclude(self):
- self._check_filter(Filter.create_from_json({
- "filterType": "exclude"
- }), [
- ])
-
- def test_default_whitelist(self):
- self._check_filter(Filter.create_from_json({
- "whitelist": [
- "ars",
- "zh_Hans"
- ]
- }), [
- "ars",
- "zh_Hans"
- ])
-
- def test_default_blacklist(self):
- expected_matches = set(EXAMPLE_FILE_STEMS)
- expected_matches.remove("ars")
- expected_matches.remove("zh_Hans")
- self._check_filter(Filter.create_from_json({
- "blacklist": [
- "ars",
- "zh_Hans"
- ]
- }), expected_matches)
-
- def test_language_whitelist(self):
- self._check_filter(Filter.create_from_json({
- "filterType": "language",
- "whitelist": [
- "af",
- "bs"
- ]
- }), [
- "root",
- "af_NA",
- "af_ZA",
- "af",
- "bs_BA",
- "bs_Cyrl_BA",
- "bs_Cyrl",
- "bs_Latn_BA",
- "bs_Latn",
- "bs"
- ])
-
- def test_language_blacklist(self):
- expected_matches = set(EXAMPLE_FILE_STEMS)
- expected_matches.remove("af_NA")
- expected_matches.remove("af_ZA")
- expected_matches.remove("af")
- self._check_filter(Filter.create_from_json({
- "filterType": "language",
- "blacklist": [
- "af"
- ]
- }), expected_matches)
-
- def test_regex_whitelist(self):
- self._check_filter(Filter.create_from_json({
- "filterType": "regex",
- "whitelist": [
- r"^ar.*$",
- r"^zh$"
- ]
- }), [
- "ar",
- "ar_SA",
- "ars",
- "zh"
- ])
-
- def test_regex_blacklist(self):
- expected_matches = set(EXAMPLE_FILE_STEMS)
- expected_matches.remove("ar")
- expected_matches.remove("ar_SA")
- expected_matches.remove("ars")
- expected_matches.remove("zh")
- self._check_filter(Filter.create_from_json({
- "filterType": "regex",
- "blacklist": [
- r"^ar.*$",
- r"^zh$"
- ]
- }), expected_matches)
-
- def test_locale_basic(self):
- self._check_filter(Filter.create_from_json({
- "filterType": "locale",
- "whitelist": [
- # Default scripts:
- # sr => Cyrl
- # vai => Vaii
- # zh => Hans
- "bs_BA", # is an alias to bs_Latn_BA
- "en_DE",
- "sr", # Language with no script
- "vai_Latn", # Language with non-default script
- "zh_Hans" # Language with default script
- ]
- }), [
- "root",
- # bs: should include the full dependency tree of bs_BA
- "bs_BA",
- "bs_Latn_BA",
- "bs_Latn",
- "bs",
- # en: should include the full dependency tree of en_DE
- "en",
- "en_DE",
- "en_150",
- "en_001",
- # sr: include Cyrl, the default, but not Latn.
- "sr",
- "sr_BA",
- "sr_CS",
- "sr_Cyrl",
- "sr_Cyrl_BA",
- "sr_Cyrl_CS",
- "sr_Cyrl_ME",
- # vai: include Latn but NOT Vaii.
- "vai_Latn",
- "vai_Latn_LR",
- # zh: include Hans but NOT Hant.
- "zh",
- "zh_CN",
- "zh_SG",
- "zh_Hans",
- "zh_Hans_CN",
- "zh_Hans_HK",
- "zh_Hans_MO",
- "zh_Hans_SG"
- ])
-
- def test_locale_no_children(self):
- self._check_filter(Filter.create_from_json({
- "filterType": "locale",
- "includeChildren": False,
- "whitelist": [
- # See comments in test_locale_basic.
- "bs_BA",
- "en_DE",
- "sr",
- "vai_Latn",
- "zh_Hans"
- ]
- }), [
- "root",
- "bs_BA",
- "bs_Latn_BA",
- "bs_Latn",
- "bs",
- "en",
- "en_DE",
- "en_150",
- "en_001",
- "sr",
- "vai_Latn",
- "zh",
- "zh_Hans",
- ])
-
- def test_locale_include_scripts(self):
- self._check_filter(Filter.create_from_json({
- "filterType": "locale",
- "includeScripts": True,
- "whitelist": [
- # See comments in test_locale_basic.
- "bs_BA",
- "en_DE",
- "sr",
- "vai_Latn",
- "zh_Hans"
- ]
- }), [
- "root",
- # bs: includeScripts only works for language-only (without region)
- "bs_BA",
- "bs_Latn_BA",
- "bs_Latn",
- "bs",
- # en: should include the full dependency tree of en_DE
- "en",
- "en_DE",
- "en_150",
- "en_001",
- # sr: include Latn, since no particular script was requested.
- "sr_BA",
- "sr_CS",
- "sr_Cyrl_BA",
- "sr_Cyrl_CS",
- "sr_Cyrl_ME",
- "sr_Cyrl",
- "sr_Latn_BA",
- "sr_Latn_CS",
- "sr_Latn_ME",
- "sr_Latn",
- "sr_ME",
- "sr",
- # vai: do NOT include Vaii; the script was explicitly requested.
- "vai_Latn_LR",
- "vai_Latn",
- # zh: do NOT include Hant; the script was explicitly requested.
- "zh_CN",
- "zh_SG",
- "zh_Hans_CN",
- "zh_Hans_HK",
- "zh_Hans_MO",
- "zh_Hans_SG",
- "zh_Hans",
- "zh"
- ])
-
- def test_locale_no_children_include_scripts(self):
- self._check_filter(Filter.create_from_json({
- "filterType": "locale",
- "includeChildren": False,
- "includeScripts": True,
- "whitelist": [
- # See comments in test_locale_basic.
- "bs_BA",
- "en_DE",
- "sr",
- "vai_Latn",
- "zh_Hans"
- ]
- }), [
- "root",
- # bs: includeScripts only works for language-only (without region)
- "bs_BA",
- "bs_Latn_BA",
- "bs_Latn",
- "bs",
- # en: should include the full dependency tree of en_DE
- "en",
- "en_DE",
- "en_150",
- "en_001",
- # sr: include Cyrl and Latn but no other children
- "sr",
- "sr_Cyrl",
- "sr_Latn",
- # vai: include only the requested script
- "vai_Latn",
- # zh: include only the requested script
- "zh",
- "zh_Hans",
- ])
-
- def test_union(self):
- self._check_filter(Filter.create_from_json({
- "filterType": "union",
- "unionOf": [
- {
- "whitelist": [
- "ars",
- "zh_Hans"
- ]
- },
- {
- "filterType": "regex",
- "whitelist": [
- r"^bs.*$",
- r"^zh$"
- ]
- }
- ]
- }), [
- "ars",
- "zh_Hans",
- "bs_BA",
- "bs_Cyrl_BA",
- "bs_Cyrl",
- "bs_Latn_BA",
- "bs_Latn",
- "bs",
- "zh"
- ])
-
- def _check_filter(self, filter, expected_matches):
- for file_stem in EXAMPLE_FILE_STEMS:
- is_match = filter.match(InFile("locales/%s.txt" % file_stem))
- expected_match = file_stem in expected_matches
- self.assertEqual(is_match, expected_match, file_stem)
-
-# Export the test for the runner
-suite = unittest.makeSuite(FiltrationTest)
diff -Nru icu-64.2/source/data/buildtool/test/__init__.py icu-65.1/source/data/buildtool/test/__init__.py
--- icu-64.2/source/data/buildtool/test/__init__.py 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/data/buildtool/test/__init__.py 1970-01-01 00:00:00.000000000 +0000
@@ -1,2 +0,0 @@
-# Copyright (C) 2018 and later: Unicode, Inc. and others.
-# License & terms of use: http://www.unicode.org/copyright.html
diff -Nru icu-64.2/source/data/buildtool/test/__main__.py icu-65.1/source/data/buildtool/test/__main__.py
--- icu-64.2/source/data/buildtool/test/__main__.py 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/data/buildtool/test/__main__.py 1970-01-01 00:00:00.000000000 +0000
@@ -1,14 +0,0 @@
-# Copyright (C) 2018 and later: Unicode, Inc. and others.
-# License & terms of use: http://www.unicode.org/copyright.html
-
-import unittest
-
-from . import filtration_test
-
-def load_tests(loader, tests, pattern):
- suite = unittest.TestSuite()
- suite.addTest(filtration_test.suite)
- return suite
-
-if __name__ == '__main__':
- unittest.main()
diff -Nru icu-64.2/source/data/buildtool/utils.py icu-65.1/source/data/buildtool/utils.py
--- icu-64.2/source/data/buildtool/utils.py 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/data/buildtool/utils.py 1970-01-01 00:00:00.000000000 +0000
@@ -1,104 +0,0 @@
-# Copyright (C) 2018 and later: Unicode, Inc. and others.
-# License & terms of use: http://www.unicode.org/copyright.html
-
-# Python 2/3 Compatibility (ICU-20299)
-# TODO(ICU-20301): Remove this.
-from __future__ import print_function
-
-import sys
-
-from . import *
-
-
-def dir_for(file):
- if isinstance(file, LocalFile):
- return file.dirname
- if isinstance(file, SrcFile):
- return "{SRC_DIR}"
- if isinstance(file, InFile):
- return "{IN_DIR}"
- if isinstance(file, TmpFile):
- return "{TMP_DIR}"
- if isinstance(file, OutFile):
- return "{OUT_DIR}"
- if isinstance(file, PkgFile):
- return "{PKG_DIR}"
- assert False
-
-
-def concat_dicts(*dicts):
- # There is not a super great way to do this in Python:
- new_dict = {}
- for dict in dicts:
- new_dict.update(dict)
- return new_dict
-
-
-def repeated_execution_request_looper(request):
- # dictionary of lists to list of dictionaries:
- ld = [
- dict(zip(request.repeat_with, t))
- for t in zip(*request.repeat_with.values())
- ]
- if not ld:
- # No special options given in repeat_with
- ld = [{} for _ in range(len(request.input_files))]
- return zip(ld, request.specific_dep_files, request.input_files, request.output_files)
-
-
-def format_single_request_command(request, cmd_template, common_vars):
- return cmd_template.format(
- ARGS = request.args.format(
- INPUT_FILES = [file.filename for file in request.input_files],
- OUTPUT_FILES = [file.filename for file in request.output_files],
- **concat_dicts(common_vars, request.format_with)
- )
- )
-
-
-def format_repeated_request_command(request, cmd_template, loop_vars, common_vars):
- (iter_vars, _, input_file, output_file) = loop_vars
- return cmd_template.format(
- ARGS = request.args.format(
- INPUT_FILE = input_file.filename,
- OUTPUT_FILE = output_file.filename,
- **concat_dicts(common_vars, request.format_with, iter_vars)
- )
- )
-
-
-def flatten_requests(requests, config, common_vars):
- result = []
- for request in requests:
- result += request.flatten(config, requests, common_vars)
- return result
-
-
-def get_all_output_files(requests, include_tmp=False):
- files = []
- for request in requests:
- files += request.all_output_files()
-
- # Filter out all files but those in OUT_DIR if necessary.
- # It is also easy to filter for uniqueness; do it right now and return.
- if not include_tmp:
- files = (file for file in files if isinstance(file, OutFile))
- return list(set(files))
-
- # Filter for unique values. NOTE: Cannot use set() because we need to accept same filename as
- # OutFile and TmpFile as different, and by default they evaluate as equal.
- return [f for _, f in set((type(f), f) for f in files)]
-
-
-def compute_directories(requests):
- dirs = set()
- for file in get_all_output_files(requests, include_tmp=True):
- path = "%s/%s" % (dir_for(file), file.filename)
- dirs.add(path[:path.rfind("/")])
- return list(sorted(dirs))
-
-
-class SpaceSeparatedList(list):
- """A list that joins itself with spaces when converted to a string."""
- def __str__(self):
- return " ".join(self)
diff -Nru icu-64.2/source/data/build.xml icu-65.1/source/data/build.xml
--- icu-64.2/source/data/build.xml 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/data/build.xml 2019-10-03 11:16:41.000000000 +0000
@@ -43,13 +43,17 @@
-
+
+
+
+
+
@@ -60,11 +64,31 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
@@ -101,22 +125,23 @@
-
+
-
+
-
+
-
+
+
@@ -154,11 +179,11 @@
-
+
-
+
@@ -169,11 +194,11 @@
-
+
-
+
@@ -184,12 +209,12 @@
-
+
-
+
@@ -200,119 +225,119 @@
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
@@ -325,11 +350,11 @@
-
+
-
+
@@ -337,12 +362,12 @@
-
+
-
+
@@ -354,11 +379,11 @@
-
+
@@ -374,7 +399,7 @@
-
+
diff -Nru icu-64.2/source/data/cldr-icu-readme.txt icu-65.1/source/data/cldr-icu-readme.txt
--- icu-64.2/source/data/cldr-icu-readme.txt 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/data/cldr-icu-readme.txt 2019-10-03 11:16:41.000000000 +0000
@@ -35,21 +35,6 @@
#
#----
#
-# CLDR dtd caching
-#
-# Parts of the build process (notably building the new ICU data files in step 4)
-# require http: access to files in the CLDR repository; for example, processing
-# the files in icu4c/source/data/xml/ may require access to
-# http://www.unicode.org/repos/cldr/trunk/common/dtd/ldml.dtd
-#
-# Unless you cache the dtds locally by
-# 1. creating a temp directory e.g. ~/.cldrdtd
-# 2. setting CLDR_DTD_CACHE to it e.g. -DCLDR_DTD_CACHE=~/.cldrdtd
-# your system will make excessive network requests, which will result in the
-# Unicode server blocking access.
-#
-#----
-#
# There are several environment variables that need to be defined.
#
# a) Java- and ant-related variables
@@ -62,9 +47,6 @@
#
# -Xmx4096m, to give Java more memory; otherwise it may run out
# of heap.
-# -DCLDR_DTD_CACHE=~/.cldrdtd (or some other temp directory
-# that already exists), to reduce frequent http: access to dtds
-# and consequent blockage by Unicode server.
#
# b) CLDR-related variables
#
@@ -73,6 +55,16 @@
# CLDR_CLASSES: Path to the CLDR Tools classes directory. If not set, defaults
# to $CLDR_DIR/tools/java/classes
#
+# CLDR_TMP_DIR: Parent of temporary CLDR production data.
+# Defaults to $CLDR_DIR/../cldr-aux (sibling to CLDR_DIR).
+#
+# *** NOTE ***: In CLDR release-36-beta, the GenerateProductionData
+# tool no longer generates data into $CLDR_TMP_DIR/production; instead
+# it generates data into $CLDR_DIR/../cldr-staging/production. However
+# the rest of the build still assumes that the generated data is in
+# $CLDR_TMP_DIR/production. So CLDR_TMP_DIR must be defined to be
+# $CLDR_DIR/../cldr-staging
+#
# c) ICU-related variables
# These variables only need to be set if you're directly reusing the
# commands below.
@@ -140,38 +132,23 @@
# 1a. Java and ant variables, adjust for your system
export JAVA_HOME=`/usr/libexec/java_home`
-export ANT_OPTS="-Xmx4096m -DCLDR_DTD_CACHE=~/.cldrdtd"
+export ANT_OPTS="-Xmx4096m
# 1b. CLDR variables, adjust for your setup; with cygwin it might be e.g.
# CLDR_DIR=`cygpath -wp /build/cldr`
-export CLDR_DIR=$HOME/cldr/trunk
+export CLDR_DIR=$HOME/cldr-myfork
# 1c. ICU variables
-export ICU4C_DIR=$HOME/icu/icu4c
-export ICU4J_ROOT=$HOME/icu/icu4j
-
-# 1d. Pre-populate your CLDR DTD cache. You need to do this only once.
-
-mkdir ~/.cldrdtd
-cd ~/.cldrdtd
-curl http://www.unicode.org/repos/cldr/trunk/common/dtd/ldml.dtd \
- -o http___www.unicode.org_repos_cldr_trunk_common_dtd_ldml.dtd
-# WAIT before hitting the server again; it WILL NOT give you a second chance!
-sleep 5
-curl http://www.unicode.org/repos/cldr/trunk/common/dtd/ldmlICU.dtd \
- -o http___www.unicode.org_repos_cldr_trunk_common_dtd_ldmlICU.dtd
-sleep 5
-curl http://www.unicode.org/repos/cldr/trunk/common/dtd/ldmlSupplemental.dtd \
- -o http___www.unicode.org_repos_cldr_trunk_common_dtd_ldmlSupplemental.dtd
+export ICU4C_DIR=$HOME/icu-myfork/icu4c
+export ICU4J_ROOT=$HOME/icu-myfork/icu4j
-# 2. Build the CLDR Java tools
-# Optionally build the jar, but ant will look inside the classes directory anyway
+# 2. Build the CLDR Java tools and jar
cd $CLDR_DIR/tools/java
ant all
-#ant jar
+ant jar
# 3. Configure ICU4C, build and test without new data first, to verify that
# there are no pre-existing errors. Here is the runConfigureICU
@@ -182,7 +159,7 @@
make all 2>&1 | tee /tmp/icu4c-oldData-makeAll.txt
make check 2>&1 | tee /tmp/icu4c-oldData-makeCheck.txt
-# 4. Build the new ICU4C data files; these include .txt files and .mk files.
+# 4. Build the new ICU4C data files; these include .txt files and .py files.
# These new files will replace whatever was already present in the ICU4C sources.
# This process uses ant with ICU's data/build.xml and data/icu-config.xml to
# operate (via CLDR's ant/CLDRConverterTool.java and ant/CLDRBuild.java) the
@@ -193,22 +170,15 @@
# Running "ant setup" is not required, but it will print useful errors to
# debug issues with your path when it fails.
#
-# If you see timeout errors when building the rbnf data, for example, then you are
-# likely not using a CLDR dtd cache; see "CLDR dtd caching" above. If you are using
-# a dtd cache and are still having timeout problems, the IP address of your system
-# may have been blocked due to previous excessive access. In this case you may need
-# to contact a Unicode sysadmin to restore access.
-#
-# Unfortunately, even if you have your DTD cache variable enabled, you may still
-# get blocked and unable to populate your cache because of multiple successive
-# requests to download the required DTD files. It is recommended that you
-# pre-populate your cache as shown above in step 1d.
cd $ICU4C_DIR/source/data
ant setup
ant clean
ant all 2>&1 | tee /tmp/cldr-newData-buildLog.txt
+# NOTE: if you change the CLDR data, please run "ant cleanprod" to clean out the
+# temporary production data directory (usually $CLDR_DIR/../cldr-aux/production )
+
# 5. Check which data files have modifications, which have been added or removed
# (if there are no changes, you may not need to proceed further). Make sure the
# list seems reasonable.
@@ -291,6 +261,22 @@
# more failures in ICU4C or ICU4J (except failures that were present before you
# began testing the new CLDR data).
+# Note that certain data changes and related test failures may require the
+# rebuilding of other kinds of data. For example:
+# a) Changes to locale matching data may cause failures in e.g. the following:
+# com.ibm.icu.dev.test.util.LocaleDistanceTest (testLoadedDataSameAsBuiltFromScratch)
+# com.ibm.icu.dev.test.util.LocaleMatcherTest (testLikelySubtagsLoadedDataSameAsBuiltFromScratch)
+# To address these requires building and running the tool
+# icu4j/tools/misc/src/com/ibm/icu/dev/tool/locale/LocaleDistanceBuilder.java
+# to regenerate the file icu4c/source/data/misc/langInfo.txt and then regenerating
+# the ICU4J data jars.
+# b) Changes to plurals data may cause failures in e.g. the following
+# com.ibm.icu.dev.test.format.PluralRulesTest (TestLocales)
+# To address these requires updating the LOCALE_SNAPSHOT data in
+# icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/PluralRulesTest.java
+# by modifying the TestLocales() test there to run generateLOCALE_SNAPSHOT() and then
+# copying in the updated data.
+
# 15. Check the file changes; then git add or git rm as necessary, and
# commit the changes.
diff -Nru icu-64.2/source/data/dtd/cldr-35.1/common/dtd/ldml.dtd icu-65.1/source/data/dtd/cldr-35.1/common/dtd/ldml.dtd
--- icu-64.2/source/data/dtd/cldr-35.1/common/dtd/ldml.dtd 1970-01-01 00:00:00.000000000 +0000
+++ icu-65.1/source/data/dtd/cldr-35.1/common/dtd/ldml.dtd 2019-10-03 11:16:41.000000000 +0000
@@ -0,0 +1,3146 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff -Nru icu-64.2/source/data/dtd/cldr-35.1/common/dtd/ldmlICU.dtd icu-65.1/source/data/dtd/cldr-35.1/common/dtd/ldmlICU.dtd
--- icu-64.2/source/data/dtd/cldr-35.1/common/dtd/ldmlICU.dtd 1970-01-01 00:00:00.000000000 +0000
+++ icu-65.1/source/data/dtd/cldr-35.1/common/dtd/ldmlICU.dtd 2019-10-03 11:16:41.000000000 +0000
@@ -0,0 +1,113 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff -Nru icu-64.2/source/data/icu-config.xml icu-65.1/source/data/icu-config.xml
--- icu-64.2/source/data/icu-config.xml 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/data/icu-config.xml 2019-10-03 11:16:41.000000000 +0000
@@ -370,6 +370,7 @@
+
Binary files /tmp/tmp1eTomn/Up6jWaEcgn/icu-64.2/source/data/in/icudt64l.dat and /tmp/tmp1eTomn/1QfOdCdfdZ/icu-65.1/source/data/in/icudt64l.dat differ
Binary files /tmp/tmp1eTomn/Up6jWaEcgn/icu-64.2/source/data/in/icudt65l.dat and /tmp/tmp1eTomn/1QfOdCdfdZ/icu-65.1/source/data/in/icudt65l.dat differ
diff -Nru icu-64.2/source/data/makedata.mak icu-65.1/source/data/makedata.mak
--- icu-64.2/source/data/makedata.mak 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/data/makedata.mak 2019-10-03 11:16:41.000000000 +0000
@@ -12,11 +12,11 @@
##############################################################################
# Keep the following in sync with the version - see common/unicode/uvernum.h
-U_ICUDATA_NAME=icudt64
+U_ICUDATA_NAME=icudt65
##############################################################################
!IF "$(UWP)" == "UWP"
# Optionally change the name of the data file for the UWP version.
-U_ICUDATA_NAME=icudt64
+U_ICUDATA_NAME=icudt65
!ENDIF
U_ICUDATA_ENDIAN_SUFFIX=l
UNICODE_VERSION=12.1
@@ -71,6 +71,7 @@
# Timestamp files to keep track of current build state
TOOLS_TS=$(ICUTMP)\tools.timestamp
COREDATA_TS=$(ICUTMP)\coredata.timestamp
+ARM_CROSSBUILD_TS=
# ICUCOL
# The directory that contains colfiles.mk files along with *.txt collation data files
@@ -106,6 +107,8 @@
#
!IF "$(CFG)" == "ARM\Release" || "$(CFG)" == "ARM\Debug"
DLL_OUTPUT=$(ICUP)\binARM$(UWP)
+!ELSE IF "$(CFG)" == "ARM64\Release" || "$(CFG)" == "ARM64\Debug"
+DLL_OUTPUT=$(ICUP)\binARM64$(UWP)
!ELSE IF "$(CFG)" == "x64\Release" || "$(CFG)" == "x64\Debug"
DLL_OUTPUT=$(ICUP)\bin64$(UWP)
!ELSE IF "$(UWP)" == "UWP"
@@ -113,6 +116,7 @@
!ELSE
DLL_OUTPUT=$(ICUP)\bin$(UWP)
!ENDIF
+!MESSAGE ICU data DLL_OUTPUT path is $(DLL_OUTPUT)
#
# TESTDATA
@@ -126,7 +130,7 @@
#
# TESTDATABLD
-# The build directory for test data intermidiate files
+# The build directory for test data intermediate files
# (Tests are NOT run from this makefile,
# only the data is put in place.)
TESTDATABLD=$(ICUP)\source\test\testdata\out\build
@@ -138,20 +142,39 @@
ICUTOOLS=$(ICUP)\source\tools
!MESSAGE ICU tools path is $(ICUTOOLS)
+# ARM_CROSS_BUILD
+# In order to support cross-compiling for ARM/ARM64 using the x64 tools
+# we need to know if we're building the ARM/ARM64 data DLL, otherwise
+# the existence of the x64 bits will cause us to think we are already done.
+# Note: This is only for the "regular" builds, the UWP builds have a separate project file entirely.
+ARM_CROSS_BUILD=
+!IF "$(UWP)" == ""
+!IF "$(CFG)" == "ARM\Release" || "$(CFG)" == "ARM\Debug"
+ARM_CROSS_BUILD=ARM
+ARM_CROSSBUILD_TS=$(ICUTMP)\$(ARM_CROSS_BUILD).timestamp
+!ELSE IF "$(CFG)" == "ARM64\Release" || "$(CFG)" == "ARM64\Debug"
+ARM_CROSS_BUILD=ARM64
+ARM_CROSSBUILD_TS=$(ICUTMP)\$(ARM_CROSS_BUILD).timestamp
+!ENDIF
+!ENDIF
+
#
# TOOLS CFG PATH
-# ARM needs to use one of the other tools, so make sure to get an usable cfg path
+# Generally the tools want to run on the same architecture as is being built.
+# Thus ARM and ARM64 need to use another build of the other tools, so make sure to get an usable cfg path.
# Since tools, particularly pkggen, have architecture built-in, we made x64 on
# Windows be machine-independent and use those tools.
#
+!IF "$(ARM_CROSS_BUILD)" == ""
CFGTOOLS=$(CFG)
-!IF "$(CFG)" == "ARM\Release" || "$(CFG)" == "ARM\Debug"
+!ELSE
CFGTOOLS=x64\Release
!ENDIF
!MESSAGE ICU tools CFG subpath is $(CFGTOOLS)
+
# The current ICU tools need to be in the path first.
-# x86 uses x86, x64 and arm use x64
+# x86 uses x86; x64, arm, and arm64 use x64
!IF "$(CFG)" == "x86\Release" || "$(CFG)" == "x86\Debug"
PATH = $(ICUP)\bin;$(PATH)
ICUPBIN=$(ICUP)\bin
@@ -190,9 +213,12 @@
COMMON_ICUDATA_ARGUMENTS=-f -e $(U_ICUDATA_NAME) -v $(ICU_PACKAGE_MODE) -c -p $(ICUPKG) -T "$(ICUTMP)" -L $(U_ICUDATA_NAME) -d "$(ICUBLD_PKG)" -s .
!IF "$(UWP)" == "UWP"
COMMON_ICUDATA_ARGUMENTS=$(COMMON_ICUDATA_ARGUMENTS) -u
+!ENDIF
!IF "$(CFG)" == "ARM\Release" || "$(CFG)" == "ARM\Debug"
-COMMON_ICUDATA_ARGUMENTS=$(COMMON_ICUDATA_ARGUMENTS) -a
+COMMON_ICUDATA_ARGUMENTS=$(COMMON_ICUDATA_ARGUMENTS) -a ARM
!ENDIF
+!IF "$(CFG)" == "ARM64\Release" || "$(CFG)" == "ARM64\Debug"
+COMMON_ICUDATA_ARGUMENTS=$(COMMON_ICUDATA_ARGUMENTS) -a ARM64
!ENDIF
#############################################################################
@@ -204,6 +230,7 @@
# Building the common dll in $(ICUBLD_PKG) unconditionally copies it to $(DLL_OUTPUT) too.
#
#############################################################################
+!IF "$(ARM_CROSS_BUILD)" == ""
ALL : GODATA "$(ICU_LIB_TARGET)" "$(TESTDATAOUT)\testdata.dat"
@echo All targets are up to date
@@ -212,6 +239,11 @@
copy "$(ICUOUT)\$(U_ICUDATA_NAME)$(U_ICUDATA_ENDIAN_SUFFIX).dat" "$(ICUMAKE)\..\..\commondata\"
!ENDIF
+!ELSE
+ALL : GODATA "$(ICU_LIB_TARGET)" "$(TESTDATAOUT)\testdata.dat" $(ARM_CROSSBUILD_TS)
+ @echo All targets are up to date
+
+!ENDIF
# Three main targets: tools, core data, and test data.
# Keep track of whether they are built via timestamp files.
@@ -233,15 +265,16 @@
$(COREDATA_TS):
@cd "$(ICUSRCDATA)"
- py -3 -B -m buildtool \
+ set PYTHONPATH=$(ICUP)\source\python;%PYTHONPATH%
+ py -3 -B -m icutools.databuilder \
--mode windows-exec \
--src_dir "$(ICUSRCDATA)" \
--tool_dir "$(ICUTOOLS)" \
--tool_cfg "$(CFG)" \
--out_dir "$(ICUBLD_PKG)" \
- --tmp_dir "$(ICUTMP)"
+ --tmp_dir "$(ICUTMP)" \
--filter_file "$(ICU_DATA_FILTER_FILE)" \
- $(ICU_DATA_BUILDTOOL_OPTS) \
+ $(ICU_DATA_BUILDTOOL_OPTS)
@echo "timestamp" > $(COREDATA_TS)
@@ -378,6 +411,18 @@
-@erase "$(ICUTMP)\$(ICUPKG).dat"
!ENDIF
+"$(ARM_CROSSBUILD_TS)" : $(COMMON_ICUDATA_DEPENDENCIES) "$(ICU_LIB_TARGET)"
+ @echo Building ICU data for "$(ARM_CROSS_BUILD)" from x64
+ cd "$(ICUBLD_PKG)"
+ "$(ICUPBIN)\pkgdata" $(COMMON_ICUDATA_ARGUMENTS) $(ICUTMP)\icudata.lst
+ -@erase "$(ICU_LIB_TARGET)"
+ @if not exist "$(DLL_OUTPUT)" mkdir "$(DLL_OUTPUT)"
+ copy "$(U_ICUDATA_NAME).dll" "$(ICU_LIB_TARGET)"
+ -@erase "$(U_ICUDATA_NAME).dll"
+ copy "$(ICUTMP)\$(ICUPKG).dat" "$(ICUOUT)\$(U_ICUDATA_NAME)$(U_ICUDATA_ENDIAN_SUFFIX).dat"
+ -@erase "$(ICUTMP)\$(ICUPKG).dat"
+ @echo "timestamp" > $(ARM_CROSSBUILD_TS)
+
# utility target to create missing directories
# Most directories are made by Python, but still create ICUTMP
# so it works in the source archive
@@ -386,6 +431,7 @@
@if not exist "$(ICUTMP)\$(NULL)" mkdir "$(ICUTMP)"
@if not exist "$(ICUOUT)\build\$(NULL)" mkdir "$(ICUOUT)\build"
@if not exist "$(ICUBLD_PKG)\$(NULL)" mkdir "$(ICUBLD_PKG)"
+ @if not exist "$(TESTDATAOUT)" mkdir "$(TESTDATAOUT)"
# utility target to send us to the right dir
GODATA : CREATE_DIRS
@@ -394,60 +440,11 @@
# This is to remove all the data files
CLEAN : GODATA
@echo Cleaning up the data files.
- @cd "$(ICUBLD_PKG)"
- -@erase "*.cnv"
- -@erase "*.exp"
- -@erase "*.icu"
- -@erase "*.lib"
- -@erase "*.nrm"
- -@erase "*.res"
- -@erase "*.spp"
- -@erase "*.txt"
- -@erase "*.cfu"
- -@erase "curr\*.res"
- -@erase "curr\*.txt"
- -@erase "lang\*.res"
- -@erase "lang\*.txt"
- -@erase "region\*.res"
- -@erase "region\*.txt"
- -@erase "zone\*.res"
- -@erase "zone\*.txt"
- @cd "$(ICUBLD_PKG)\$(ICUBRK)"
- -@erase "*.brk"
- -@erase "*.res"
- -@erase "*.txt"
- -@erase "*.dict"
- @cd "$(ICUBLD_PKG)\$(ICUCOL)"
- -@erase "*.res"
- -@erase "*.txt"
- @cd "$(ICUBLD_PKG)\$(ICURBNF)"
- -@erase "*.res"
- -@erase "*.txt"
- @cd "$(ICUBLD_PKG)\$(ICUTRNS)"
- -@erase "*.res"
@cd "$(ICUOUT)"
- -@erase "*.dat"
- @cd "$(ICUTMP)"
- -@erase "*.html"
- -@erase "*.lst"
- -@erase "*.mak"
- -@erase "*.obj"
- -@erase "*.res"
- -@erase "*.timestamp"
- @cd "$(TESTDATABLD)"
- -@erase "*.cnv"
- -@erase "*.icu"
- -@erase "*.mak"
- -@erase "*.nrm"
- -@erase "*.res"
- -@erase "*.spp"
- -@erase "*.txt"
- @cd "$(TESTDATAOUT)"
- -@erase "*.dat"
- @cd "$(TESTDATAOUT)\testdata"
- -@erase "*.typ"
- @cd "$(ICUBLD_PKG)"
-
+ -@erase "$(ICUOUT)\*.dat"
+ @rmdir $(ICUBLD) /s /q
+ @rmdir $(ICUTMP) /s /q
+ @rmdir $(TESTDATAOUT) /s /q
# DLL version information
# If you modify this, modify winmode.c in pkgdata.
diff -Nru icu-64.2/source/data/makedata_uwp.vcxproj icu-65.1/source/data/makedata_uwp.vcxproj
--- icu-64.2/source/data/makedata_uwp.vcxproj 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/data/makedata_uwp.vcxproj 2019-10-03 11:16:41.000000000 +0000
@@ -13,6 +13,10 @@
Debug
ARM
+
+ Debug
+ ARM64
+
Release
Win32
@@ -25,6 +29,10 @@
Release
ARM
+
+ Release
+ ARM64
+
{B1D53358-37BD-48BC-B27C-68BAF1E78508}
@@ -46,65 +54,20 @@
<_ProjectFileVersion>10.0.30319.1
- .\data\tmp\x86\
- .\data\tmp\x86\
- .\data\tmp\x64\
- .\data\tmp\x64\
- .\data\tmp\arm\
- .\data\tmp\arm\
- .\data\build\
- .\data\build\
- .\data\build\
- .\data\build\
- .\data\build\
- .\data\build\
- NMAKE /f makedata.mak ICUMAKE="$(ProjectDir)\" CFG=x86\Release UWP=UWP
- NMAKE /f makedata.mak ICUMAKE="$(ProjectDir)\" CFG=x86\Release UWP=UWP clean all
- NMAKE /f makedata.mak ICUMAKE="$(ProjectDir)\" CFG=x86\Release UWP=UWP clean
- NMAKE /f makedata.mak ICUMAKE="$(ProjectDir)\" CFG=x86\Debug UWP=UWP
- NMAKE /f makedata.mak ICUMAKE="$(ProjectDir)\" CFG=x86\Debug UWP=UWP clean all
- NMAKE /f makedata.mak ICUMAKE="$(ProjectDir)\" CFG=x86\Debug UWP=UWP clean
- NMAKE /f makedata.mak ICUMAKE="$(ProjectDir)\" CFG=x64\Release UWP=UWP
- NMAKE /f makedata.mak ICUMAKE="$(ProjectDir)\" CFG=x64\Release UWP=UWP clean all
- NMAKE /f makedata.mak ICUMAKE="$(ProjectDir)\" CFG=x64\Release UWP=UWP clean
- NMAKE /f makedata.mak ICUMAKE="$(ProjectDir)\" CFG=x64\Debug UWP=UWP
- NMAKE /f makedata.mak ICUMAKE="$(ProjectDir)\" CFG=x64\Debug UWP=UWP clean all
- NMAKE /f makedata.mak ICUMAKE="$(ProjectDir)\" CFG=x64\Debug UWP=UWP clean
- NMAKE /f makedata.mak ICUMAKE="$(ProjectDir)\" CFG=ARM\Release UWP=UWP
- NMAKE /f makedata.mak ICUMAKE="$(ProjectDir)\" CFG=ARM\Release UWP=UWP clean all
- NMAKE /f makedata.mak ICUMAKE="$(ProjectDir)\" CFG=ARM\Release UWP=UWP clean
- NMAKE /f makedata.mak ICUMAKE="$(ProjectDir)\" CFG=ARM\Debug UWP=UWP
- NMAKE /f makedata.mak ICUMAKE="$(ProjectDir)\" CFG=ARM\Debug UWP=UWP clean all
- NMAKE /f makedata.mak ICUMAKE="$(ProjectDir)\" CFG=ARM\Debug UWP=UWP clean
+ .\data\tmp\$(Platform)\
+ .\data\build\
+ $(Platform)\$(Configuration)
+
+ .\data\tmp\x86\
+ x86\$(Configuration)
+
+ NMAKE /f makedata.mak ICUMAKE="$(ProjectDir)\" CFG=$(MakeCFG) UWP=UWP
+ NMAKE /f makedata.mak ICUMAKE="$(ProjectDir)\" CFG=$(MakeCFG) UWP=UWP clean all
+ NMAKE /f makedata.mak ICUMAKE="$(ProjectDir)\" CFG=$(MakeCFG) UWP=UWP clean
-
-
- .\out\tmp\x86\ReleaseUWPBuildLog.html
-
-
-
-
- .\out\tmp\x86\DebugUWPBuildLog.html
-
-
-
-
- .\out\tmp\x64\ReleaseUWPBuildLog.html
-
-
-
-
- .\out\tmp\x64\DebugUWPBuildLog.html
-
-
-
-
- .\out\tmp\arm\ReleaseUWPBuildLog.html
-
-
-
+
- .\out\tmp\arm\DebugUWPBuildLog.html
+ $(OutDir)$(Configuration)UWPBuildLog.html
@@ -116,7 +79,6 @@
-
diff -Nru icu-64.2/source/data/makedata.vcxproj icu-65.1/source/data/makedata.vcxproj
--- icu-64.2/source/data/makedata.vcxproj 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/data/makedata.vcxproj 2019-10-03 11:16:41.000000000 +0000
@@ -19,69 +19,26 @@
<_ProjectFileVersion>10.0.30319.1
- .\data\tmp\x86\
- .\data\build\
- NMAKE /f makedata.mak ICUMAKE="$(ProjectDir)\" CFG=x86\Release
- NMAKE /f makedata.mak ICUMAKE="$(ProjectDir)\" CFG=x86\Release clean all
- NMAKE /f makedata.mak ICUMAKE="$(ProjectDir)\" CFG=x86\Release clean
-
- $(NMakePreprocessorDefinitions)
- $(NMakeIncludeSearchPath)
- $(NMakeForcedIncludes)
- $(NMakeAssemblySearchPath)
- $(NMakeForcedUsingAssemblies)
- .\data\tmp\x86\
- .\data\build\
- NMAKE /f makedata.mak ICUMAKE="$(ProjectDir)\" CFG=x86\Debug
- NMAKE /f makedata.mak ICUMAKE="$(ProjectDir)\" CFG=x86\Debug clean all
- NMAKE /f makedata.mak ICUMAKE="$(ProjectDir)\" CFG=x86\Debug clean
-
- $(NMakePreprocessorDefinitions)
- $(NMakeIncludeSearchPath)
- $(NMakeForcedIncludes)
- $(NMakeAssemblySearchPath)
- $(NMakeForcedUsingAssemblies)
- .\data\tmp\x64\
- .\data\build\
- NMAKE /f makedata.mak ICUMAKE="$(ProjectDir)\" CFG=x64\Release
- NMAKE /f makedata.mak ICUMAKE="$(ProjectDir)\" CFG=x64\Release clean all
- NMAKE /f makedata.mak ICUMAKE="$(ProjectDir)\" CFG=x64\Release clean
-
- $(NMakePreprocessorDefinitions)
- $(NMakeIncludeSearchPath)
- $(NMakeForcedIncludes)
- $(NMakeAssemblySearchPath)
- $(NMakeForcedUsingAssemblies)
- .\data\tmp\x64\
- .\data\build\
- NMAKE /f makedata.mak ICUMAKE="$(ProjectDir)\" CFG=x64\Debug
- NMAKE /f makedata.mak ICUMAKE="$(ProjectDir)\" CFG=x64\Debug clean all
- NMAKE /f makedata.mak ICUMAKE="$(ProjectDir)\" CFG=x64\Debug clean
-
- $(NMakePreprocessorDefinitions)
- $(NMakeIncludeSearchPath)
- $(NMakeForcedIncludes)
- $(NMakeAssemblySearchPath)
- $(NMakeForcedUsingAssemblies)
+ .\data\tmp\$(Platform)\
+ .\data\build\
+ $(Platform)\$(Configuration)
+
+ .\data\tmp\x86\
+ x86\$(Configuration)
+
+ NMAKE /f makedata.mak ICUMAKE="$(ProjectDir)\" CFG=$(MakeCFG)
+ NMAKE /f makedata.mak ICUMAKE="$(ProjectDir)\" CFG=$(MakeCFG) clean all
+ NMAKE /f makedata.mak ICUMAKE="$(ProjectDir)\" CFG=$(MakeCFG) clean
+
+ $(NMakePreprocessorDefinitions)
+ $(NMakeIncludeSearchPath)
+ $(NMakeForcedIncludes)
+ $(NMakeAssemblySearchPath)
+ $(NMakeForcedUsingAssemblies)
-
+
- .\out\tmp\x86\ReleaseBuildLog.html
-
-
-
-
- .\out\tmp\x86\DebugBuildLog.html
-
-
-
-
- .\out\tmp\x64\ReleaseBuildLog.html
-
-
-
-
- .\out\tmp\x64\DebugBuildLog.html
+ .\data\log\$(Platform)\$(Configuration)BuildLog.html
@@ -93,7 +50,6 @@
-
@@ -199,4 +155,4 @@
-
\ No newline at end of file
+
diff -Nru icu-64.2/source/data/makedata.vcxproj.filters icu-65.1/source/data/makedata.vcxproj.filters
--- icu-64.2/source/data/makedata.vcxproj.filters 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/data/makedata.vcxproj.filters 2019-10-03 11:16:41.000000000 +0000
@@ -35,9 +35,6 @@
Make Files
-
- Make Files
-
Make Files
diff -Nru icu-64.2/source/data/Makefile.in icu-65.1/source/data/Makefile.in
--- icu-64.2/source/data/Makefile.in 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/data/Makefile.in 2019-10-03 11:16:41.000000000 +0000
@@ -136,7 +136,7 @@
$(RMV) $(LIBDIR)/*$(LIB_ICUDATA_NAME)*.$(SO)* $(LIBDIR)/$(LIB_STATIC_ICUDATA_NAME).$(A)
check-local:
- PYTHONPATH=$(srcdir) @PYTHON@ -m buildtool.test
+ PYTHONPATH=$(top_srcdir)/python @PYTHON@ -m icutools.databuilder.test
# Find out if we have a source archive.
# If we have that, then use that instead of building everything from scratch.
@@ -266,7 +266,7 @@
TZDATA = $(firstword $(wildcard $(top_builddir)/tools/tzcode/tzdata*.tar.gz) $(wildcard $(top_srcdir)/tools/tzcode/tzdata*.tar.gz))
endif
-# TODO(ICU-20466): Make the TZDATA override part of Python buildtool
+# TODO(ICU-20466): Make the TZDATA override part of Python icutools.databuilder
ifneq ($(TZDATA),)
TZCODE_DIR=$(top_builddir)/tools/tzcode
diff -Nru icu-64.2/source/extra/Makefile.in icu-65.1/source/extra/Makefile.in
--- icu-64.2/source/extra/Makefile.in 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/extra/Makefile.in 2019-10-03 11:16:41.000000000 +0000
@@ -23,7 +23,7 @@
## Files to remove for 'make clean'
CLEANFILES = *~
-SUBDIRS = uconv
+SUBDIRS = scrptrun uconv
## List of phony targets
.PHONY : all all-local all-recursive install install-local \
diff -Nru icu-64.2/source/extra/scrptrun/scrptrun.cpp icu-65.1/source/extra/scrptrun/scrptrun.cpp
--- icu-64.2/source/extra/scrptrun/scrptrun.cpp 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/extra/scrptrun/scrptrun.cpp 2019-10-03 11:16:41.000000000 +0000
@@ -19,6 +19,8 @@
#include "cmemory.h"
#include "scrptrun.h"
+U_NAMESPACE_BEGIN
+
const char ScriptRun::fgClassID=0;
UChar32 ScriptRun::pairedChars[] = {
@@ -201,3 +203,4 @@
return true;
}
+U_NAMESPACE_END
diff -Nru icu-64.2/source/extra/scrptrun/scrptrun.h icu-65.1/source/extra/scrptrun/scrptrun.h
--- icu-64.2/source/extra/scrptrun/scrptrun.h 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/extra/scrptrun/scrptrun.h 2019-10-03 11:16:41.000000000 +0000
@@ -20,6 +20,8 @@
#include "unicode/uobject.h"
#include "unicode/uscript.h"
+U_NAMESPACE_BEGIN
+
struct ScriptRecord
{
UChar32 startChar;
@@ -152,5 +154,6 @@
reset(start, length);
}
+U_NAMESPACE_END
#endif
diff -Nru icu-64.2/source/extra/scrptrun/srtest.cpp icu-65.1/source/extra/scrptrun/srtest.cpp
--- icu-64.2/source/extra/scrptrun/srtest.cpp 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/extra/scrptrun/srtest.cpp 2019-10-03 11:16:41.000000000 +0000
@@ -27,9 +27,9 @@
int32_t testLength = UPRV_LENGTHOF(testChars);
-void main()
+int main()
{
- ScriptRun scriptRun(testChars, 0, testLength);
+ icu::ScriptRun scriptRun(testChars, 0, testLength);
while (scriptRun.next()) {
int32_t start = scriptRun.getScriptStart();
@@ -38,4 +38,5 @@
printf("Script '%s' from %d to %d.\n", uscript_getName(code), start, end);
}
+ return 0;
}
diff -Nru icu-64.2/source/extra/uconv/makedata.mak icu-65.1/source/extra/uconv/makedata.mak
--- icu-64.2/source/extra/uconv/makedata.mak 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/extra/uconv/makedata.mak 2019-10-03 11:16:41.000000000 +0000
@@ -17,7 +17,7 @@
!ENDIF
#Here we test if a valid configuration is given
-!IF "$(CFG)" != "Release" && "$(CFG)" != "release" && "$(CFG)" != "Debug" && "$(CFG)" != "debug" && "$(CFG)" != "x86\Release" && "$(CFG)" != "x86\Debug" && "$(CFG)" != "x64\Release" && "$(CFG)" != "x64\Debug"
+!IF "$(CFG)" != "Release" && "$(CFG)" != "release" && "$(CFG)" != "Debug" && "$(CFG)" != "debug" && "$(CFG)" != "x86\Release" && "$(CFG)" != "x86\Debug" && "$(CFG)" != "x64\Release" && "$(CFG)" != "x64\Debug" && "$(CFG)" != "ARM\Release" && "$(CFG)" != "ARM\Debug" && "$(CFG)" != "ARM64\Release" && "$(CFG)" != "ARM64\Debug"
!MESSAGE Invalid configuration "$(CFG)" specified.
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
@@ -51,7 +51,9 @@
ICD=$(ICUDATA)^\
DATA_PATH=$(ICUP)\data^\
-!IF "$(CFG)" == "x64\Release" || "$(CFG)" == "x64\Debug"
+# Use the x64 tools for building ARM and ARM64.
+# Note: This is similar to the TOOLS CFG PATH in source\data\makedata.mak
+!IF "$(CFG)" == "x64\Release" || "$(CFG)" == "x64\Debug" || "$(CFG)" == "ARM\Release" || "$(CFG)" == "ARM\Debug" || "$(CFG)" == "ARM64\Release" || "$(CFG)" == "ARM64\Debug"
ICUTOOLS=$(ICUP)\bin64
PATH = $(ICUP)\bin64;$(PATH)
!ELSE
@@ -59,14 +61,29 @@
PATH = $(ICUP)\bin;$(PATH)
!ENDIF
+# If building ARM/ARM, then we need to pass the arch as an argument.
+EXTRA_PKGDATA_ARGUMENTS=
+!IF "$(CFG)" == "ARM\Release" || "$(CFG)" == "ARM\Debug"
+EXTRA_PKGDATA_ARGUMENTS=-a ARM
+!ENDIF
+!IF "$(CFG)" == "ARM64\Release" || "$(CFG)" == "ARM64\Debug"
+EXTRA_PKGDATA_ARGUMENTS=-a ARM64
+!ENDIF
+
# Make sure the necessary tools exist before continuing. (This is to prevent cryptic errors from NMAKE).
!IF !EXISTS($(ICUTOOLS)\pkgdata.exe)
!MESSAGE Unable to find "$(ICUTOOLS)\pkgdata.exe"
!ERROR The tool 'pkgdata.exe' does not exist! (Have you built all of ICU yet?).
+!IF "$(CFG)" == "ARM\Release" || "$(CFG)" == "ARM\Debug" || "$(CFG)" == "ARM64\Release" || "$(CFG)" == "ARM64\Debug"
+!ERROR Note that the ARM and ARM64 builds require building x64 first.
+!ENDIF
!ENDIF
!IF !EXISTS($(ICUTOOLS)\genrb.exe)
!MESSAGE Unable to find "$(ICUTOOLS)\genrb.exe"
!ERROR The tool 'genrb.exe' does not exist! (Have you built all of ICU yet?).
+!IF "$(CFG)" == "ARM\Release" || "$(CFG)" == "ARM\Debug" || "$(CFG)" == "ARM64\Release" || "$(CFG)" == "ARM64\Debug"
+!ERROR Note that the ARM and ARM64 builds require building x64 first.
+!ENDIF
!ENDIF
# Suffixes for data files
@@ -98,7 +115,7 @@
# invoke pkgdata - static
"$(DLL_OUTPUT)\$(RESNAME).lib" : $(RB_FILES) $(RESFILES)
@echo Building $(RESNAME).lib
- @"$(ICUTOOLS)\pkgdata" -f -v -m static -c -p $(RESNAME) -d "$(DLL_OUTPUT)" -s "$(RESDIR)" <
<_ProjectFileVersion>10.0.30319.1
- .\x86\Release\
- .\x86\Release\
- false
- .\x86\Debug\
- .\x86\Debug\
- true
- .\x64\Release\
- .\x64\Release\
- false
- .\x64\Debug\
- .\x64\Debug\
- true
+ .\$(Platform)\$(Configuration)\
+ .\$(Platform)\$(Configuration)\
+ $(Platform)\$(Configuration)
+
+ .\x86\$(Configuration)\
+ .\x86\$(Configuration)\
+ x86\$(Configuration)
+
+ true
+ false
-
+
-
- ..\..\..\include;..\..\common;%(AdditionalIncludeDirectories)
- UCONVMSG_LINK;%(PreprocessorDefinitions)
- true
- Level3
-
-
-
-
- copy "$(TargetPath)" ..\..\..\bin
-
- $(ProjectDir)..\..\..\bin\$(TargetFileName);%(Outputs)
-
- .\x86\Release/uconv.tlb
+ $(OutDir)\uconv.tlb
- MultiThreadedDLL
- true
- .\x86\Release/uconv.pch
- .\x86\Release/
- .\x86\Release/
- .\x86\Release/
+ Level3
Default
+ true
+ ..\..\..\include;..\..\common;%(AdditionalIncludeDirectories)
+ UCONVMSG_LINK;%(PreprocessorDefinitions)
+ $(OutDir)\uconv.pch
+ $(OutDir)/
+ $(OutDir)/
+ $(OutDir)\uconv.pdb
- uconvmsg.lib;icuuc.lib;icuin.lib;%(AdditionalDependencies)
- .\x86\Release/uconv.exe
- x86\Release;..\..\..\lib;%(AdditionalLibraryDirectories)
- .\x86\Release/uconv.pdb
Console
- false
-
-
+ $(OutDir)\uconv.exe
+ uconvmsg.lib;%(AdditionalDependencies)
+ $(OutDir);..\..\..\$(IcuLibOutputDir);%(AdditionalLibraryDirectories)
-
-
- copy "$(TargetPath)" ..\..\..\bin
-
- $(ProjectDir)..\..\..\bin\$(TargetFileName);%(Outputs)
+ copy "$(TargetPath)" ..\..\..\$(IcuBinOutputDir)
+ ..\..\..\$(IcuBinOutputDir)\$(TargetFileName);%(Outputs)
-
- .\x86\Debug/uconv.tlb
-
+
+
+
+ true
MultiThreadedDebugDLL
- .\x86\Debug/uconv.pch
- .\x86\Debug/
- .\x86\Debug/
- .\x86\Debug/
- EditAndContinue
- Default
- uconvmsg.lib;icuucd.lib;icuind.lib;%(AdditionalDependencies)
- .\x86\Debug/uconv.exe
- x86\Debug;..\..\..\lib;%(AdditionalLibraryDirectories)
- true
- .\x86\Debug/uconv.pdb
- Console
- false
-
-
+ icuucd.lib;icuind.lib;%(AdditionalDependencies)
-
-
- copy "$(TargetPath)" ..\..\..\bin64
-
- $(ProjectDir)..\..\..\bin64\$(TargetFileName);%(Outputs)
-
-
- .\x64\Release/uconv.tlb
-
+
+
MultiThreadedDLL
true
- .\x64\Release/uconv.pch
- .\x64\Release/
- .\x64\Release/
- .\x64\Release/
- Default
- uconvmsg.lib;icuuc.lib;icuin.lib;%(AdditionalDependencies)
- .\x64\Release/uconv.exe
- x64\Release;..\..\..\lib64;%(AdditionalLibraryDirectories)
- .\x64\Release/uconv.pdb
- Console
-
-
-
-
- copy "$(TargetPath)" ..\..\..\bin64
-
- $(ProjectDir)..\..\..\bin64\$(TargetFileName);%(Outputs)
-
-
- .\x64\Debug/uconv.tlb
-
-
- MultiThreadedDebugDLL
- .\x64\Debug/uconv.pch
- .\x64\Debug/
- .\x64\Debug/
- .\x64\Debug/
- ProgramDatabase
- Default
-
-
- uconvmsg.lib;icuucd.lib;icuind.lib;%(AdditionalDependencies)
- .\x64\Debug/uconv.exe
- x64\Debug;..\..\..\lib64;%(AdditionalLibraryDirectories)
- true
- .\x64\Debug/uconv.pdb
- Console
+ icuuc.lib;icuin.lib;%(AdditionalDependencies)
@@ -178,18 +102,8 @@
- nmake /nologo /f %(Filename).mak icup="$(ProjectDir)..\..\.." CFG=x86\Debug
-
- x86\Debug/uconvmsg.lib;%(Outputs)
- nmake /nologo /f %(Filename).mak icup="$(ProjectDir)..\..\.." CFG=x64\Debug
-
- x64\Debug/uconvmsg.lib;%(Outputs)
- nmake /nologo /f %(Filename).mak icup="$(ProjectDir)..\..\.." CFG=x86\Release
-
- x86\Release/uconvmsg.lib;%(Outputs)
- nmake /nologo /f %(Filename).mak icup="$(ProjectDir)..\..\.." CFG=x64\Release
-
- x64\Release/uconvmsg.lib;%(Outputs)
+ nmake /nologo /f %(Filename).mak icup="$(ProjectDir)..\..\.." CFG=$(MakeCFG)
+ $(MakeCFG)\uconvmsg.lib;%(Outputs)
diff -Nru icu-64.2/source/i18n/alphaindex.cpp icu-65.1/source/i18n/alphaindex.cpp
--- icu-64.2/source/i18n/alphaindex.cpp 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/i18n/alphaindex.cpp 2019-10-03 11:16:41.000000000 +0000
@@ -260,8 +260,7 @@
// but that would be worth it only if this method is called multiple times,
// or called after using the old-style bucket iterator API.
LocalPointer immutableBucketList(createBucketList(errorCode));
- LocalPointer coll(
- static_cast(collatorPrimaryOnly_->clone()));
+ LocalPointer coll(collatorPrimaryOnly_->clone());
if (immutableBucketList.isNull() || coll.isNull()) {
errorCode = U_MEMORY_ALLOCATION_ERROR;
return NULL;
@@ -907,7 +906,7 @@
return;
}
}
- collatorPrimaryOnly_ = static_cast(collator_->clone());
+ collatorPrimaryOnly_ = collator_->clone();
if (collatorPrimaryOnly_ == NULL) {
status = U_MEMORY_ALLOCATION_ERROR;
return;
@@ -958,7 +957,7 @@
}
if (leftString == NULL) {
return 1;
- };
+ }
if (rightString == NULL) {
return -1;
}
diff -Nru icu-64.2/source/i18n/anytrans.cpp icu-65.1/source/i18n/anytrans.cpp
--- icu-64.2/source/i18n/anytrans.cpp 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/i18n/anytrans.cpp 2019-10-03 11:16:41.000000000 +0000
@@ -226,7 +226,7 @@
/**
* Transliterator API.
*/
-Transliterator* AnyTransliterator::clone() const {
+AnyTransliterator* AnyTransliterator::clone() const {
return new AnyTransliterator(*this);
}
diff -Nru icu-64.2/source/i18n/anytrans.h icu-65.1/source/i18n/anytrans.h
--- icu-64.2/source/i18n/anytrans.h 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/i18n/anytrans.h 2019-10-03 11:16:41.000000000 +0000
@@ -66,7 +66,7 @@
/**
* Transliterator API.
*/
- virtual Transliterator* clone() const;
+ virtual AnyTransliterator* clone() const;
/**
* Implements {@link Transliterator#handleTransliterate}.
diff -Nru icu-64.2/source/i18n/astro.cpp icu-65.1/source/i18n/astro.cpp
--- icu-64.2/source/i18n/astro.cpp 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/i18n/astro.cpp 2019-10-03 11:16:41.000000000 +0000
@@ -65,10 +65,7 @@
return(uprv_isNaN(d));
}
-static icu::UMutex *ccLock() {
- static icu::UMutex m = U_MUTEX_INITIALIZER;
- return &m;
-}
+static icu::UMutex ccLock;
U_CDECL_BEGIN
static UBool calendar_astro_cleanup(void) {
@@ -1552,12 +1549,12 @@
if(U_FAILURE(status)) {
return 0;
}
- umtx_lock(ccLock());
+ umtx_lock(&ccLock);
if(*cache == NULL) {
createCache(cache, status);
if(U_FAILURE(status)) {
- umtx_unlock(ccLock());
+ umtx_unlock(&ccLock);
return 0;
}
}
@@ -1565,7 +1562,7 @@
res = uhash_igeti((*cache)->fTable, key);
U_DEBUG_ASTRO_MSG(("%p: GET: [%d] == %d\n", (*cache)->fTable, key, res));
- umtx_unlock(ccLock());
+ umtx_unlock(&ccLock);
return res;
}
@@ -1573,12 +1570,12 @@
if(U_FAILURE(status)) {
return;
}
- umtx_lock(ccLock());
+ umtx_lock(&ccLock);
if(*cache == NULL) {
createCache(cache, status);
if(U_FAILURE(status)) {
- umtx_unlock(ccLock());
+ umtx_unlock(&ccLock);
return;
}
}
@@ -1586,7 +1583,7 @@
uhash_iputi((*cache)->fTable, key, value, &status);
U_DEBUG_ASTRO_MSG(("%p: PUT: [%d] := %d\n", (*cache)->fTable, key, value));
- umtx_unlock(ccLock());
+ umtx_unlock(&ccLock);
}
CalendarCache::CalendarCache(int32_t size, UErrorCode &status) {
diff -Nru icu-64.2/source/i18n/bocsu.h icu-65.1/source/i18n/bocsu.h
--- icu-64.2/source/i18n/bocsu.h 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/i18n/bocsu.h 2019-10-03 11:16:41.000000000 +0000
@@ -144,14 +144,14 @@
* yields negative modulo results and quotients that are one more than
* what we need here.
*/
-#define NEGDIVMOD(n, d, m) { \
+#define NEGDIVMOD(n, d, m) UPRV_BLOCK_MACRO_BEGIN { \
(m)=(n)%(d); \
(n)/=(d); \
if((m)<0) { \
--(n); \
(m)+=(d); \
} \
-}
+} UPRV_BLOCK_MACRO_END
U_CFUNC UChar32
u_writeIdenticalLevelRun(UChar32 prev, const UChar *s, int32_t length, icu::ByteSink &sink);
diff -Nru icu-64.2/source/i18n/brktrans.cpp icu-65.1/source/i18n/brktrans.cpp
--- icu-64.2/source/i18n/brktrans.cpp 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/i18n/brktrans.cpp 2019-10-03 11:16:41.000000000 +0000
@@ -64,7 +64,7 @@
/**
* Transliterator API.
*/
-Transliterator* BreakTransliterator::clone(void) const {
+BreakTransliterator* BreakTransliterator::clone() const {
return new BreakTransliterator(*this);
}
diff -Nru icu-64.2/source/i18n/brktrans.h icu-65.1/source/i18n/brktrans.h
--- icu-64.2/source/i18n/brktrans.h 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/i18n/brktrans.h 2019-10-03 11:16:41.000000000 +0000
@@ -54,7 +54,7 @@
* Transliterator API.
* @return A copy of the object.
*/
- virtual Transliterator* clone(void) const;
+ virtual BreakTransliterator* clone() const;
virtual const UnicodeString &getInsertion() const;
diff -Nru icu-64.2/source/i18n/buddhcal.cpp icu-65.1/source/i18n/buddhcal.cpp
--- icu-64.2/source/i18n/buddhcal.cpp 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/i18n/buddhcal.cpp 2019-10-03 11:16:41.000000000 +0000
@@ -53,7 +53,7 @@
return *this;
}
-Calendar* BuddhistCalendar::clone(void) const
+BuddhistCalendar* BuddhistCalendar::clone() const
{
return new BuddhistCalendar(*this);
}
@@ -133,7 +133,7 @@
*/
static UDate gSystemDefaultCenturyStart = DBL_MIN;
static int32_t gSystemDefaultCenturyStartYear = -1;
-static icu::UInitOnce gBCInitOnce;
+static icu::UInitOnce gBCInitOnce = U_INITONCE_INITIALIZER;
UBool BuddhistCalendar::haveDefaultCentury() const
diff -Nru icu-64.2/source/i18n/buddhcal.h icu-65.1/source/i18n/buddhcal.h
--- icu-64.2/source/i18n/buddhcal.h 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/i18n/buddhcal.h 2019-10-03 11:16:41.000000000 +0000
@@ -94,7 +94,7 @@
* @return return a polymorphic copy of this calendar.
* @internal
*/
- virtual Calendar* clone(void) const;
+ virtual BuddhistCalendar* clone() const;
public:
/**
diff -Nru icu-64.2/source/i18n/calendar.cpp icu-65.1/source/i18n/calendar.cpp
--- icu-64.2/source/i18n/calendar.cpp 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/i18n/calendar.cpp 2019-10-03 11:16:41.000000000 +0000
@@ -268,6 +268,8 @@
// canonicalize, so grandfathered variant will be transformed to keywords
// e.g ja_JP_TRADITIONAL -> ja_JP@calendar=japanese
+ // NOTE: Since ICU-20187, ja_JP_TRADITIONAL no longer canonicalizes, and
+ // the Gregorian calendar is returned instead.
int32_t canonicalLen = uloc_canonicalize(locid, canonicalName, sizeof(canonicalName) - 1, &status);
if (U_FAILURE(status)) {
return CALTYPE_GREGORIAN;
@@ -748,6 +750,7 @@
validLocale[0] = 0;
actualLocale[0] = 0;
if (U_FAILURE(success)) {
+ delete zone;
return;
}
if(zone == 0) {
@@ -2592,7 +2595,7 @@
return FALSE;
}
// clone the calendar so we don't mess with the real one.
- Calendar *work = (Calendar*)this->clone();
+ Calendar *work = this->clone();
if (work == NULL) {
status = U_MEMORY_ALLOCATION_ERROR;
return FALSE;
@@ -2752,7 +2755,7 @@
// clone the calendar so we don't mess with the real one, and set it to
// accept anything for the field values
- Calendar *work = (Calendar*)this->clone();
+ Calendar *work = this->clone();
if (work == NULL) {
status = U_MEMORY_ALLOCATION_ERROR;
return 0;
diff -Nru icu-64.2/source/i18n/casetrn.cpp icu-65.1/source/i18n/casetrn.cpp
--- icu-64.2/source/i18n/casetrn.cpp 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/i18n/casetrn.cpp 2019-10-03 11:16:41.000000000 +0000
@@ -125,7 +125,7 @@
/**
* Transliterator API.
*/
-/*Transliterator* CaseMapTransliterator::clone(void) const {
+/*CaseMapTransliterator* CaseMapTransliterator::clone() const {
return new CaseMapTransliterator(*this);
}*/
diff -Nru icu-64.2/source/i18n/casetrn.h icu-65.1/source/i18n/casetrn.h
--- icu-64.2/source/i18n/casetrn.h 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/i18n/casetrn.h 2019-10-03 11:16:41.000000000 +0000
@@ -58,7 +58,7 @@
* Transliterator API.
* @return a copy of the object.
*/
- virtual Transliterator* clone(void) const = 0;
+ virtual CaseMapTransliterator* clone() const = 0;
/**
* ICU "poor man's RTTI", returns a UClassID for the actual class.
diff -Nru icu-64.2/source/i18n/chnsecal.cpp icu-65.1/source/i18n/chnsecal.cpp
--- icu-64.2/source/i18n/chnsecal.cpp 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/i18n/chnsecal.cpp 2019-10-03 11:16:41.000000000 +0000
@@ -51,10 +51,7 @@
// --- The cache --
-static icu::UMutex *astroLock() { // Protects access to gChineseCalendarAstro.
- static icu::UMutex m = U_MUTEX_INITIALIZER;
- return &m;
-}
+static icu::UMutex astroLock;
static icu::CalendarAstronomer *gChineseCalendarAstro = NULL;
// Lazy Creation & Access synchronized by class CalendarCache with a mutex.
@@ -121,7 +118,7 @@
//-------------------------------------------------------------------------
-Calendar* ChineseCalendar::clone() const {
+ChineseCalendar* ChineseCalendar::clone() const {
return new ChineseCalendar(*this);
}
@@ -538,14 +535,14 @@
// PST 1298 with a final result of Dec 14 10:31:59 PST 1299.
double ms = daysToMillis(Grego::fieldsToDay(gyear, UCAL_DECEMBER, 1));
- umtx_lock(astroLock());
+ umtx_lock(&astroLock);
if(gChineseCalendarAstro == NULL) {
gChineseCalendarAstro = new CalendarAstronomer();
ucln_i18n_registerCleanup(UCLN_I18N_CHINESE_CALENDAR, calendar_chinese_cleanup);
}
gChineseCalendarAstro->setTime(ms);
UDate solarLong = gChineseCalendarAstro->getSunTime(CalendarAstronomer::WINTER_SOLSTICE(), TRUE);
- umtx_unlock(astroLock());
+ umtx_unlock(&astroLock);
// Winter solstice is 270 degrees solar longitude aka Dongzhi
cacheValue = (int32_t)millisToDays(solarLong);
@@ -568,14 +565,14 @@
*/
int32_t ChineseCalendar::newMoonNear(double days, UBool after) const {
- umtx_lock(astroLock());
+ umtx_lock(&astroLock);
if(gChineseCalendarAstro == NULL) {
gChineseCalendarAstro = new CalendarAstronomer();
ucln_i18n_registerCleanup(UCLN_I18N_CHINESE_CALENDAR, calendar_chinese_cleanup);
}
gChineseCalendarAstro->setTime(daysToMillis(days));
UDate newMoon = gChineseCalendarAstro->getMoonTime(CalendarAstronomer::NEW_MOON(), after);
- umtx_unlock(astroLock());
+ umtx_unlock(&astroLock);
return (int32_t) millisToDays(newMoon);
}
@@ -600,14 +597,14 @@
*/
int32_t ChineseCalendar::majorSolarTerm(int32_t days) const {
- umtx_lock(astroLock());
+ umtx_lock(&astroLock);
if(gChineseCalendarAstro == NULL) {
gChineseCalendarAstro = new CalendarAstronomer();
ucln_i18n_registerCleanup(UCLN_I18N_CHINESE_CALENDAR, calendar_chinese_cleanup);
}
gChineseCalendarAstro->setTime(daysToMillis(days));
UDate solarLongitude = gChineseCalendarAstro->getSunLongitude();
- umtx_unlock(astroLock());
+ umtx_unlock(&astroLock);
// Compute (floor(solarLongitude / (pi/6)) + 2) % 12
int32_t term = ( ((int32_t)(6 * solarLongitude / CalendarAstronomer::PI)) + 2 ) % 12;
diff -Nru icu-64.2/source/i18n/chnsecal.h icu-65.1/source/i18n/chnsecal.h
--- icu-64.2/source/i18n/chnsecal.h 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/i18n/chnsecal.h 2019-10-03 11:16:41.000000000 +0000
@@ -144,7 +144,7 @@
virtual ~ChineseCalendar();
// clone
- virtual Calendar* clone() const;
+ virtual ChineseCalendar* clone() const;
private:
diff -Nru icu-64.2/source/i18n/choicfmt.cpp icu-65.1/source/i18n/choicfmt.cpp
--- icu-64.2/source/i18n/choicfmt.cpp 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/i18n/choicfmt.cpp 2019-10-03 11:16:41.000000000 +0000
@@ -563,7 +563,7 @@
// -------------------------------------
-Format*
+ChoiceFormat*
ChoiceFormat::clone() const
{
ChoiceFormat *aCopy = new ChoiceFormat(*this);
diff -Nru icu-64.2/source/i18n/collationiterator.cpp icu-65.1/source/i18n/collationiterator.cpp
--- icu-64.2/source/i18n/collationiterator.cpp 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/i18n/collationiterator.cpp 2019-10-03 11:16:41.000000000 +0000
@@ -872,7 +872,7 @@
// consistent with forward iteration.
while(offsets.size() <= ceBuffer.length) {
offsets.addElement(limitOffset, errorCode);
- };
+ }
}
return ceBuffer.get(--ceBuffer.length);
} else {
@@ -932,7 +932,7 @@
offset = getOffset();
while(offsets.size() < ceBuffer.length) {
offsets.addElement(offset, errorCode);
- };
+ }
}
U_ASSERT(offsets.size() == ceBuffer.length);
// End offset corresponding to just after the unsafe-backwards segment.
diff -Nru icu-64.2/source/i18n/coll.cpp icu-65.1/source/i18n/coll.cpp
--- icu-64.2/source/i18n/coll.cpp 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/i18n/coll.cpp 2019-10-03 11:16:41.000000000 +0000
@@ -67,7 +67,7 @@
static icu::ICULocaleService* gService = NULL;
static icu::UInitOnce gServiceInitOnce = U_INITONCE_INITIALIZER;
#endif
-static icu::UInitOnce gAvailableLocaleListInitOnce;
+static icu::UInitOnce gAvailableLocaleListInitOnce = U_INITONCE_INITIALIZER;
/**
* Release all static memory held by collator.
diff -Nru icu-64.2/source/i18n/compactdecimalformat.cpp icu-65.1/source/i18n/compactdecimalformat.cpp
--- icu-64.2/source/i18n/compactdecimalformat.cpp 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/i18n/compactdecimalformat.cpp 2019-10-03 11:16:41.000000000 +0000
@@ -30,9 +30,9 @@
: DecimalFormat(new DecimalFormatSymbols(inLocale, status), status) {
if (U_FAILURE(status)) return;
// Minimal properties: let the non-shim code path do most of the logic for us.
- fields->properties->compactStyle = style;
- fields->properties->groupingSize = -2; // do not forward grouping information
- fields->properties->minimumGroupingDigits = 2;
+ fields->properties.compactStyle = style;
+ fields->properties.groupingSize = -2; // do not forward grouping information
+ fields->properties.minimumGroupingDigits = 2;
touch(status);
}
@@ -45,7 +45,7 @@
return *this;
}
-Format* CompactDecimalFormat::clone() const {
+CompactDecimalFormat* CompactDecimalFormat::clone() const {
return new CompactDecimalFormat(*this);
}
diff -Nru icu-64.2/source/i18n/coptccal.cpp icu-65.1/source/i18n/coptccal.cpp
--- icu-64.2/source/i18n/coptccal.cpp 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/i18n/coptccal.cpp 2019-10-03 11:16:41.000000000 +0000
@@ -40,7 +40,7 @@
{
}
-Calendar*
+CopticCalendar*
CopticCalendar::clone() const
{
return new CopticCalendar(*this);
diff -Nru icu-64.2/source/i18n/coptccal.h icu-65.1/source/i18n/coptccal.h
--- icu-64.2/source/i18n/coptccal.h 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/i18n/coptccal.h 2019-10-03 11:16:41.000000000 +0000
@@ -145,7 +145,7 @@
* @return return a polymorphic copy of this calendar.
* @internal
*/
- virtual Calendar* clone(void) const;
+ virtual CopticCalendar* clone() const;
/**
* return the calendar type, "coptic"
diff -Nru icu-64.2/source/i18n/cpdtrans.cpp icu-65.1/source/i18n/cpdtrans.cpp
--- icu-64.2/source/i18n/cpdtrans.cpp 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/i18n/cpdtrans.cpp 2019-10-03 11:16:41.000000000 +0000
@@ -323,7 +323,7 @@
/**
* Transliterator API.
*/
-Transliterator* CompoundTransliterator::clone(void) const {
+CompoundTransliterator* CompoundTransliterator::clone() const {
return new CompoundTransliterator(*this);
}
diff -Nru icu-64.2/source/i18n/cpdtrans.h icu-65.1/source/i18n/cpdtrans.h
--- icu-64.2/source/i18n/cpdtrans.h 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/i18n/cpdtrans.h 2019-10-03 11:16:41.000000000 +0000
@@ -98,7 +98,7 @@
/**
* Transliterator API.
*/
- virtual Transliterator* clone(void) const;
+ virtual CompoundTransliterator* clone() const;
/**
* Returns the number of transliterators in this chain.
diff -Nru icu-64.2/source/i18n/csdetect.cpp icu-65.1/source/i18n/csdetect.cpp
--- icu-64.2/source/i18n/csdetect.cpp 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/i18n/csdetect.cpp 2019-10-03 11:16:41.000000000 +0000
@@ -47,7 +47,7 @@
U_NAMESPACE_END
static icu::CSRecognizerInfo **fCSRecognizers = NULL;
-static icu::UInitOnce gCSRecognizersInitOnce;
+static icu::UInitOnce gCSRecognizersInitOnce = U_INITONCE_INITIALIZER;
static int32_t fCSRecognizers_size = 0;
U_CDECL_BEGIN
diff -Nru icu-64.2/source/i18n/curramt.cpp icu-65.1/source/i18n/curramt.cpp
--- icu-64.2/source/i18n/curramt.cpp 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/i18n/curramt.cpp 2019-10-03 11:16:41.000000000 +0000
@@ -38,7 +38,7 @@
return *this;
}
-UObject* CurrencyAmount::clone() const {
+CurrencyAmount* CurrencyAmount::clone() const {
return new CurrencyAmount(*this);
}
diff -Nru icu-64.2/source/i18n/currfmt.cpp icu-65.1/source/i18n/currfmt.cpp
--- icu-64.2/source/i18n/currfmt.cpp 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/i18n/currfmt.cpp 2019-10-03 11:16:41.000000000 +0000
@@ -33,7 +33,7 @@
CurrencyFormat::~CurrencyFormat() {
}
-Format* CurrencyFormat::clone() const {
+CurrencyFormat* CurrencyFormat::clone() const {
return new CurrencyFormat(*this);
}
diff -Nru icu-64.2/source/i18n/currfmt.h icu-65.1/source/i18n/currfmt.h
--- icu-64.2/source/i18n/currfmt.h 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/i18n/currfmt.h 2019-10-03 11:16:41.000000000 +0000
@@ -57,7 +57,7 @@
/**
* Override Format API.
*/
- virtual Format* clone() const;
+ virtual CurrencyFormat* clone() const;
using MeasureFormat::format;
diff -Nru icu-64.2/source/i18n/currunit.cpp icu-65.1/source/i18n/currunit.cpp
--- icu-64.2/source/i18n/currunit.cpp 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/i18n/currunit.cpp 2019-10-03 11:16:41.000000000 +0000
@@ -109,7 +109,7 @@
return *this;
}
-UObject* CurrencyUnit::clone() const {
+CurrencyUnit* CurrencyUnit::clone() const {
return new CurrencyUnit(*this);
}
diff -Nru icu-64.2/source/i18n/dangical.cpp icu-65.1/source/i18n/dangical.cpp
--- icu-64.2/source/i18n/dangical.cpp 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/i18n/dangical.cpp 2019-10-03 11:16:41.000000000 +0000
@@ -65,7 +65,7 @@
{
}
-Calendar*
+DangiCalendar*
DangiCalendar::clone() const
{
return new DangiCalendar(*this);
diff -Nru icu-64.2/source/i18n/dangical.h icu-65.1/source/i18n/dangical.h
--- icu-64.2/source/i18n/dangical.h 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/i18n/dangical.h 2019-10-03 11:16:41.000000000 +0000
@@ -66,7 +66,7 @@
* Clone.
* @internal
*/
- virtual Calendar* clone() const;
+ virtual DangiCalendar* clone() const;
//----------------------------------------------------------------------
// Internal methods & astronomical calculations
diff -Nru icu-64.2/source/i18n/datefmt.cpp icu-65.1/source/i18n/datefmt.cpp
--- icu-64.2/source/i18n/datefmt.cpp 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/i18n/datefmt.cpp 2019-10-03 11:16:41.000000000 +0000
@@ -154,7 +154,7 @@
fCalendar = NULL;
}
if(other.fNumberFormat) {
- fNumberFormat = (NumberFormat*)other.fNumberFormat->clone();
+ fNumberFormat = other.fNumberFormat->clone();
} else {
fNumberFormat = NULL;
}
@@ -598,7 +598,7 @@
void
DateFormat::setNumberFormat(const NumberFormat& newNumberFormat)
{
- NumberFormat* newNumFmtClone = (NumberFormat*)newNumberFormat.clone();
+ NumberFormat* newNumFmtClone = newNumberFormat.clone();
if (newNumFmtClone != NULL) {
adoptNumberFormat(newNumFmtClone);
}
diff -Nru icu-64.2/source/i18n/decimfmt.cpp icu-65.1/source/i18n/decimfmt.cpp
--- icu-64.2/source/i18n/decimfmt.cpp 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/i18n/decimfmt.cpp 2019-10-03 11:16:41.000000000 +0000
@@ -95,7 +95,7 @@
new CurrencyPluralInfo(fields->symbols->getLocale(), status),
status);
if (U_FAILURE(status)) { return; }
- fields->properties->currencyPluralInfo.fPtr.adoptInstead(cpi.orphan());
+ fields->properties.currencyPluralInfo.fPtr.adoptInstead(cpi.orphan());
}
touch(status);
}
@@ -111,21 +111,14 @@
status = U_MEMORY_ALLOCATION_ERROR;
return;
}
- fields->formatter.adoptInsteadAndCheckErrorCode(new LocalizedNumberFormatter(), status);
- fields->properties.adoptInsteadAndCheckErrorCode(new DecimalFormatProperties(), status);
- fields->exportedProperties.adoptInsteadAndCheckErrorCode(new DecimalFormatProperties(), status);
if (adoptedSymbols.isNull()) {
fields->symbols.adoptInsteadAndCheckErrorCode(new DecimalFormatSymbols(status), status);
} else {
fields->symbols.adoptInsteadAndCheckErrorCode(adoptedSymbols.orphan(), status);
}
- // In order to simplify error handling logic in the various getters/setters/etc, we do not allow
- // any partially populated DecimalFormatFields object. We must have a fully complete fields object
- // or else we set it to nullptr.
- if (fields->formatter.isNull() || fields->properties.isNull() || fields->exportedProperties.isNull() || fields->symbols.isNull()) {
+ if (U_FAILURE(status)) {
delete fields;
fields = nullptr;
- status = U_MEMORY_ALLOCATION_ERROR;
}
}
@@ -133,8 +126,8 @@
void DecimalFormat::setParseAllInput(UNumberFormatAttributeValue value) {
if (fields == nullptr) { return; }
- if (value == fields->properties->parseAllInput) { return; }
- fields->properties->parseAllInput = value;
+ if (value == fields->properties.parseAllInput) { return; }
+ fields->properties.parseAllInput = value;
}
#endif
@@ -379,9 +372,9 @@
if (fields == nullptr) {
return;
}
- if (UBOOL_TO_BOOL(enabled) == fields->properties->groupingUsed) { return; }
+ if (UBOOL_TO_BOOL(enabled) == fields->properties.groupingUsed) { return; }
NumberFormat::setGroupingUsed(enabled); // to set field for compatibility
- fields->properties->groupingUsed = enabled;
+ fields->properties.groupingUsed = enabled;
touchNoError();
}
@@ -389,9 +382,9 @@
if (fields == nullptr) {
return;
}
- if (UBOOL_TO_BOOL(value) == fields->properties->parseIntegerOnly) { return; }
+ if (UBOOL_TO_BOOL(value) == fields->properties.parseIntegerOnly) { return; }
NumberFormat::setParseIntegerOnly(value); // to set field for compatibility
- fields->properties->parseIntegerOnly = value;
+ fields->properties.parseIntegerOnly = value;
touchNoError();
}
@@ -400,9 +393,9 @@
return;
}
ParseMode mode = enable ? PARSE_MODE_LENIENT : PARSE_MODE_STRICT;
- if (!fields->properties->parseMode.isNull() && mode == fields->properties->parseMode.getNoError()) { return; }
+ if (!fields->properties.parseMode.isNull() && mode == fields->properties.parseMode.getNoError()) { return; }
NumberFormat::setLenient(enable); // to set field for compatibility
- fields->properties->parseMode = mode;
+ fields->properties.parseMode = mode;
touchNoError();
}
@@ -441,19 +434,16 @@
// Note: it is not safe to copy fields->formatter or fWarehouse directly because fields->formatter might have
// dangling pointers to fields inside fWarehouse. The safe thing is to re-construct fields->formatter from
// the property bag, despite being somewhat slower.
- fields = new DecimalFormatFields();
+ fields = new DecimalFormatFields(source.fields->properties);
if (fields == nullptr) {
return; // no way to report an error.
}
UErrorCode status = U_ZERO_ERROR;
- fields->formatter.adoptInsteadAndCheckErrorCode(new LocalizedNumberFormatter(), status);
- fields->properties.adoptInsteadAndCheckErrorCode(new DecimalFormatProperties(*source.fields->properties), status);
fields->symbols.adoptInsteadAndCheckErrorCode(new DecimalFormatSymbols(*source.fields->symbols), status);
- fields->exportedProperties.adoptInsteadAndCheckErrorCode(new DecimalFormatProperties(), status);
// In order to simplify error handling logic in the various getters/setters/etc, we do not allow
// any partially populated DecimalFormatFields object. We must have a fully complete fields object
// or else we set it to nullptr.
- if (fields->formatter.isNull() || fields->properties.isNull() || fields->exportedProperties.isNull() || fields->symbols.isNull()) {
+ if (U_FAILURE(status)) {
delete fields;
fields = nullptr;
return;
@@ -470,8 +460,8 @@
if (fields == nullptr || rhs.fields == nullptr) {
return *this; // unfortunately, no way to report an error.
}
- *fields->properties = *rhs.fields->properties;
- fields->exportedProperties->clear();
+ fields->properties = rhs.fields->properties;
+ fields->exportedProperties.clear();
UErrorCode status = U_ZERO_ERROR;
LocalPointer dfs(new DecimalFormatSymbols(*rhs.fields->symbols), status);
if (U_FAILURE(status)) {
@@ -495,7 +485,7 @@
delete fields;
}
-Format* DecimalFormat::clone() const {
+DecimalFormat* DecimalFormat::clone() const {
// can only clone valid objects.
if (fields == nullptr) {
return nullptr;
@@ -517,7 +507,7 @@
if (fields == nullptr || otherDF->fields == nullptr) {
return false;
}
- return *fields->properties == *otherDF->fields->properties && *fields->symbols == *otherDF->fields->symbols;
+ return fields->properties == otherDF->fields->properties && *fields->symbols == *otherDF->fields->symbols;
}
UnicodeString& DecimalFormat::format(double number, UnicodeString& appendTo, FieldPosition& pos) const {
@@ -529,7 +519,7 @@
return appendTo;
}
UErrorCode localStatus = U_ZERO_ERROR;
- FormattedNumber output = fields->formatter->formatDouble(number, localStatus);
+ FormattedNumber output = fields->formatter.formatDouble(number, localStatus);
fieldPositionHelper(output, pos, appendTo.length(), localStatus);
auto appendable = UnicodeStringAppendable(appendTo);
output.appendTo(appendable, localStatus);
@@ -550,7 +540,7 @@
if (pos.getField() == FieldPosition::DONT_CARE && fastFormatDouble(number, appendTo)) {
return appendTo;
}
- FormattedNumber output = fields->formatter->formatDouble(number, status);
+ FormattedNumber output = fields->formatter.formatDouble(number, status);
fieldPositionHelper(output, pos, appendTo.length(), status);
auto appendable = UnicodeStringAppendable(appendTo);
output.appendTo(appendable, status);
@@ -572,7 +562,7 @@
if (posIter == nullptr && fastFormatDouble(number, appendTo)) {
return appendTo;
}
- FormattedNumber output = fields->formatter->formatDouble(number, status);
+ FormattedNumber output = fields->formatter.formatDouble(number, status);
fieldPositionIteratorHelper(output, posIter, appendTo.length(), status);
auto appendable = UnicodeStringAppendable(appendTo);
output.appendTo(appendable, status);
@@ -603,7 +593,7 @@
return appendTo;
}
UErrorCode localStatus = U_ZERO_ERROR;
- FormattedNumber output = fields->formatter->formatInt(number, localStatus);
+ FormattedNumber output = fields->formatter.formatInt(number, localStatus);
fieldPositionHelper(output, pos, appendTo.length(), localStatus);
auto appendable = UnicodeStringAppendable(appendTo);
output.appendTo(appendable, localStatus);
@@ -624,7 +614,7 @@
if (pos.getField() == FieldPosition::DONT_CARE && fastFormatInt64(number, appendTo)) {
return appendTo;
}
- FormattedNumber output = fields->formatter->formatInt(number, status);
+ FormattedNumber output = fields->formatter.formatInt(number, status);
fieldPositionHelper(output, pos, appendTo.length(), status);
auto appendable = UnicodeStringAppendable(appendTo);
output.appendTo(appendable, status);
@@ -646,7 +636,7 @@
if (posIter == nullptr && fastFormatInt64(number, appendTo)) {
return appendTo;
}
- FormattedNumber output = fields->formatter->formatInt(number, status);
+ FormattedNumber output = fields->formatter.formatInt(number, status);
fieldPositionIteratorHelper(output, posIter, appendTo.length(), status);
auto appendable = UnicodeStringAppendable(appendTo);
output.appendTo(appendable, status);
@@ -665,7 +655,7 @@
appendTo.setToBogus();
return appendTo;
}
- FormattedNumber output = fields->formatter->formatDecimal(number, status);
+ FormattedNumber output = fields->formatter.formatDecimal(number, status);
fieldPositionIteratorHelper(output, posIter, appendTo.length(), status);
auto appendable = UnicodeStringAppendable(appendTo);
output.appendTo(appendable, status);
@@ -683,7 +673,7 @@
appendTo.setToBogus();
return appendTo;
}
- FormattedNumber output = fields->formatter->formatDecimalQuantity(number, status);
+ FormattedNumber output = fields->formatter.formatDecimalQuantity(number, status);
fieldPositionIteratorHelper(output, posIter, appendTo.length(), status);
auto appendable = UnicodeStringAppendable(appendTo);
output.appendTo(appendable, status);
@@ -702,7 +692,7 @@
appendTo.setToBogus();
return appendTo;
}
- FormattedNumber output = fields->formatter->formatDecimalQuantity(number, status);
+ FormattedNumber output = fields->formatter.formatDecimalQuantity(number, status);
fieldPositionHelper(output, pos, appendTo.length(), status);
auto appendable = UnicodeStringAppendable(appendTo);
output.appendTo(appendable, status);
@@ -823,7 +813,7 @@
if (fields == nullptr) {
return nullptr;
}
- return fields->properties->currencyPluralInfo.fPtr.getAlias();
+ return fields->properties.currencyPluralInfo.fPtr.getAlias();
}
void DecimalFormat::adoptCurrencyPluralInfo(CurrencyPluralInfo* toAdopt) {
@@ -833,7 +823,7 @@
if (fields == nullptr) {
return;
}
- fields->properties->currencyPluralInfo.fPtr.adoptInstead(cpi.orphan());
+ fields->properties.currencyPluralInfo.fPtr.adoptInstead(cpi.orphan());
touchNoError();
}
@@ -841,11 +831,11 @@
if (fields == nullptr) {
return;
}
- if (fields->properties->currencyPluralInfo.fPtr.isNull()) {
+ if (fields->properties.currencyPluralInfo.fPtr.isNull()) {
// Note: clone() can fail with OOM error, but we have no way to report it. :(
- fields->properties->currencyPluralInfo.fPtr.adoptInstead(info.clone());
+ fields->properties.currencyPluralInfo.fPtr.adoptInstead(info.clone());
} else {
- *fields->properties->currencyPluralInfo.fPtr = info; // copy-assignment operator
+ *fields->properties.currencyPluralInfo.fPtr = info; // copy-assignment operator
}
touchNoError();
}
@@ -856,7 +846,7 @@
return result;
}
UErrorCode status = U_ZERO_ERROR;
- fields->formatter->getAffixImpl(true, false, result, status);
+ fields->formatter.getAffixImpl(true, false, result, status);
if (U_FAILURE(status)) { result.setToBogus(); }
return result;
}
@@ -865,8 +855,8 @@
if (fields == nullptr) {
return;
}
- if (newValue == fields->properties->positivePrefix) { return; }
- fields->properties->positivePrefix = newValue;
+ if (newValue == fields->properties.positivePrefix) { return; }
+ fields->properties.positivePrefix = newValue;
touchNoError();
}
@@ -876,7 +866,7 @@
return result;
}
UErrorCode status = U_ZERO_ERROR;
- fields->formatter->getAffixImpl(true, true, result, status);
+ fields->formatter.getAffixImpl(true, true, result, status);
if (U_FAILURE(status)) { result.setToBogus(); }
return result;
}
@@ -885,8 +875,8 @@
if (fields == nullptr) {
return;
}
- if (newValue == fields->properties->negativePrefix) { return; }
- fields->properties->negativePrefix = newValue;
+ if (newValue == fields->properties.negativePrefix) { return; }
+ fields->properties.negativePrefix = newValue;
touchNoError();
}
@@ -896,7 +886,7 @@
return result;
}
UErrorCode status = U_ZERO_ERROR;
- fields->formatter->getAffixImpl(false, false, result, status);
+ fields->formatter.getAffixImpl(false, false, result, status);
if (U_FAILURE(status)) { result.setToBogus(); }
return result;
}
@@ -905,8 +895,8 @@
if (fields == nullptr) {
return;
}
- if (newValue == fields->properties->positiveSuffix) { return; }
- fields->properties->positiveSuffix = newValue;
+ if (newValue == fields->properties.positiveSuffix) { return; }
+ fields->properties.positiveSuffix = newValue;
touchNoError();
}
@@ -916,7 +906,7 @@
return result;
}
UErrorCode status = U_ZERO_ERROR;
- fields->formatter->getAffixImpl(false, true, result, status);
+ fields->formatter.getAffixImpl(false, true, result, status);
if (U_FAILURE(status)) { result.setToBogus(); }
return result;
}
@@ -925,8 +915,8 @@
if (fields == nullptr) {
return;
}
- if (newValue == fields->properties->negativeSuffix) { return; }
- fields->properties->negativeSuffix = newValue;
+ if (newValue == fields->properties.negativeSuffix) { return; }
+ fields->properties.negativeSuffix = newValue;
touchNoError();
}
@@ -935,13 +925,13 @@
if (fields == nullptr) {
return DecimalFormatProperties::getDefault().signAlwaysShown;
}
- return fields->properties->signAlwaysShown;
+ return fields->properties.signAlwaysShown;
}
void DecimalFormat::setSignAlwaysShown(UBool value) {
if (fields == nullptr) { return; }
- if (UBOOL_TO_BOOL(value) == fields->properties->signAlwaysShown) { return; }
- fields->properties->signAlwaysShown = value;
+ if (UBOOL_TO_BOOL(value) == fields->properties.signAlwaysShown) { return; }
+ fields->properties.signAlwaysShown = value;
touchNoError();
}
@@ -952,7 +942,7 @@
// Fallback to using the default instance of DecimalFormatProperties.
dfp = &(DecimalFormatProperties::getDefault());
} else {
- dfp = fields->properties.getAlias();
+ dfp = &fields->properties;
}
if (dfp->multiplier != 1) {
return dfp->multiplier;
@@ -984,11 +974,11 @@
value = temp;
}
if (delta != -1) {
- fields->properties->magnitudeMultiplier = delta;
- fields->properties->multiplier = 1;
+ fields->properties.magnitudeMultiplier = delta;
+ fields->properties.multiplier = 1;
} else {
- fields->properties->magnitudeMultiplier = 0;
- fields->properties->multiplier = multiplier;
+ fields->properties.magnitudeMultiplier = 0;
+ fields->properties.multiplier = multiplier;
}
touchNoError();
}
@@ -999,13 +989,13 @@
// Fallback to using the default instance of DecimalFormatProperties.
return DecimalFormatProperties::getDefault().multiplierScale;
}
- return fields->properties->multiplierScale;
+ return fields->properties.multiplierScale;
}
void DecimalFormat::setMultiplierScale(int32_t newValue) {
if (fields == nullptr) { return; }
- if (newValue == fields->properties->multiplierScale) { return; }
- fields->properties->multiplierScale = newValue;
+ if (newValue == fields->properties.multiplierScale) { return; }
+ fields->properties.multiplierScale = newValue;
touchNoError();
}
@@ -1015,13 +1005,13 @@
// Fallback to using the default instance of DecimalFormatProperties.
return DecimalFormatProperties::getDefault().roundingIncrement;
}
- return fields->exportedProperties->roundingIncrement;
+ return fields->exportedProperties.roundingIncrement;
}
void DecimalFormat::setRoundingIncrement(double newValue) {
if (fields == nullptr) { return; }
- if (newValue == fields->properties->roundingIncrement) { return; }
- fields->properties->roundingIncrement = newValue;
+ if (newValue == fields->properties.roundingIncrement) { return; }
+ fields->properties.roundingIncrement = newValue;
touchNoError();
}
@@ -1032,17 +1022,17 @@
return static_cast(DecimalFormatProperties::getDefault().roundingMode.getNoError());
}
// UNumberFormatRoundingMode and ERoundingMode have the same values.
- return static_cast(fields->exportedProperties->roundingMode.getNoError());
+ return static_cast(fields->exportedProperties.roundingMode.getNoError());
}
void DecimalFormat::setRoundingMode(ERoundingMode roundingMode) {
if (fields == nullptr) { return; }
auto uRoundingMode = static_cast(roundingMode);
- if (!fields->properties->roundingMode.isNull() && uRoundingMode == fields->properties->roundingMode.getNoError()) {
+ if (!fields->properties.roundingMode.isNull() && uRoundingMode == fields->properties.roundingMode.getNoError()) {
return;
}
NumberFormat::setMaximumIntegerDigits(roundingMode); // to set field for compatibility
- fields->properties->roundingMode = uRoundingMode;
+ fields->properties.roundingMode = uRoundingMode;
touchNoError();
}
@@ -1052,52 +1042,52 @@
// Fallback to using the default instance of DecimalFormatProperties.
return DecimalFormatProperties::getDefault().formatWidth;
}
- return fields->properties->formatWidth;
+ return fields->properties.formatWidth;
}
void DecimalFormat::setFormatWidth(int32_t width) {
if (fields == nullptr) { return; }
- if (width == fields->properties->formatWidth) { return; }
- fields->properties->formatWidth = width;
+ if (width == fields->properties.formatWidth) { return; }
+ fields->properties.formatWidth = width;
touchNoError();
}
UnicodeString DecimalFormat::getPadCharacterString() const {
- if (fields == nullptr || fields->properties->padString.isBogus()) {
+ if (fields == nullptr || fields->properties.padString.isBogus()) {
// Readonly-alias the static string kFallbackPaddingString
return {TRUE, kFallbackPaddingString, -1};
} else {
- return fields->properties->padString;
+ return fields->properties.padString;
}
}
void DecimalFormat::setPadCharacter(const UnicodeString& padChar) {
if (fields == nullptr) { return; }
- if (padChar == fields->properties->padString) { return; }
+ if (padChar == fields->properties.padString) { return; }
if (padChar.length() > 0) {
- fields->properties->padString = UnicodeString(padChar.char32At(0));
+ fields->properties.padString = UnicodeString(padChar.char32At(0));
} else {
- fields->properties->padString.setToBogus();
+ fields->properties.padString.setToBogus();
}
touchNoError();
}
EPadPosition DecimalFormat::getPadPosition(void) const {
- if (fields == nullptr || fields->properties->padPosition.isNull()) {
+ if (fields == nullptr || fields->properties.padPosition.isNull()) {
return EPadPosition::kPadBeforePrefix;
} else {
// UNumberFormatPadPosition and EPadPosition have the same values.
- return static_cast(fields->properties->padPosition.getNoError());
+ return static_cast(fields->properties.padPosition.getNoError());
}
}
void DecimalFormat::setPadPosition(EPadPosition padPos) {
if (fields == nullptr) { return; }
auto uPadPos = static_cast(padPos);
- if (!fields->properties->padPosition.isNull() && uPadPos == fields->properties->padPosition.getNoError()) {
+ if (!fields->properties.padPosition.isNull() && uPadPos == fields->properties.padPosition.getNoError()) {
return;
}
- fields->properties->padPosition = uPadPos;
+ fields->properties.padPosition = uPadPos;
touchNoError();
}
@@ -1107,17 +1097,17 @@
// Fallback to using the default instance of DecimalFormatProperties.
return (DecimalFormatProperties::getDefault().minimumExponentDigits != -1);
}
- return (fields->properties->minimumExponentDigits != -1);
+ return (fields->properties.minimumExponentDigits != -1);
}
void DecimalFormat::setScientificNotation(UBool useScientific) {
if (fields == nullptr) { return; }
int32_t minExp = useScientific ? 1 : -1;
- if (fields->properties->minimumExponentDigits == minExp) { return; }
+ if (fields->properties.minimumExponentDigits == minExp) { return; }
if (useScientific) {
- fields->properties->minimumExponentDigits = 1;
+ fields->properties.minimumExponentDigits = 1;
} else {
- fields->properties->minimumExponentDigits = -1;
+ fields->properties.minimumExponentDigits = -1;
}
touchNoError();
}
@@ -1128,13 +1118,13 @@
// Fallback to using the default instance of DecimalFormatProperties.
return static_cast(DecimalFormatProperties::getDefault().minimumExponentDigits);
}
- return static_cast(fields->properties->minimumExponentDigits);
+ return static_cast(fields->properties.minimumExponentDigits);
}
void DecimalFormat::setMinimumExponentDigits(int8_t minExpDig) {
if (fields == nullptr) { return; }
- if (minExpDig == fields->properties->minimumExponentDigits) { return; }
- fields->properties->minimumExponentDigits = minExpDig;
+ if (minExpDig == fields->properties.minimumExponentDigits) { return; }
+ fields->properties.minimumExponentDigits = minExpDig;
touchNoError();
}
@@ -1144,13 +1134,13 @@
// Fallback to using the default instance of DecimalFormatProperties.
return DecimalFormatProperties::getDefault().exponentSignAlwaysShown;
}
- return fields->properties->exponentSignAlwaysShown;
+ return fields->properties.exponentSignAlwaysShown;
}
void DecimalFormat::setExponentSignAlwaysShown(UBool expSignAlways) {
if (fields == nullptr) { return; }
- if (UBOOL_TO_BOOL(expSignAlways) == fields->properties->exponentSignAlwaysShown) { return; }
- fields->properties->exponentSignAlwaysShown = expSignAlways;
+ if (UBOOL_TO_BOOL(expSignAlways) == fields->properties.exponentSignAlwaysShown) { return; }
+ fields->properties.exponentSignAlwaysShown = expSignAlways;
touchNoError();
}
@@ -1161,7 +1151,7 @@
// Fallback to using the default instance of DecimalFormatProperties.
groupingSize = DecimalFormatProperties::getDefault().groupingSize;
} else {
- groupingSize = fields->properties->groupingSize;
+ groupingSize = fields->properties.groupingSize;
}
if (groupingSize < 0) {
return 0;
@@ -1171,8 +1161,8 @@
void DecimalFormat::setGroupingSize(int32_t newValue) {
if (fields == nullptr) { return; }
- if (newValue == fields->properties->groupingSize) { return; }
- fields->properties->groupingSize = newValue;
+ if (newValue == fields->properties.groupingSize) { return; }
+ fields->properties.groupingSize = newValue;
touchNoError();
}
@@ -1183,7 +1173,7 @@
// Fallback to using the default instance of DecimalFormatProperties.
grouping2 = DecimalFormatProperties::getDefault().secondaryGroupingSize;
} else {
- grouping2 = fields->properties->secondaryGroupingSize;
+ grouping2 = fields->properties.secondaryGroupingSize;
}
if (grouping2 < 0) {
return 0;
@@ -1193,8 +1183,8 @@
void DecimalFormat::setSecondaryGroupingSize(int32_t newValue) {
if (fields == nullptr) { return; }
- if (newValue == fields->properties->secondaryGroupingSize) { return; }
- fields->properties->secondaryGroupingSize = newValue;
+ if (newValue == fields->properties.secondaryGroupingSize) { return; }
+ fields->properties.secondaryGroupingSize = newValue;
touchNoError();
}
@@ -1204,13 +1194,13 @@
// Fallback to using the default instance of DecimalFormatProperties.
return DecimalFormatProperties::getDefault().minimumGroupingDigits;
}
- return fields->properties->minimumGroupingDigits;
+ return fields->properties.minimumGroupingDigits;
}
void DecimalFormat::setMinimumGroupingDigits(int32_t newValue) {
if (fields == nullptr) { return; }
- if (newValue == fields->properties->minimumGroupingDigits) { return; }
- fields->properties->minimumGroupingDigits = newValue;
+ if (newValue == fields->properties.minimumGroupingDigits) { return; }
+ fields->properties.minimumGroupingDigits = newValue;
touchNoError();
}
@@ -1220,13 +1210,13 @@
// Fallback to using the default instance of DecimalFormatProperties.
return DecimalFormatProperties::getDefault().decimalSeparatorAlwaysShown;
}
- return fields->properties->decimalSeparatorAlwaysShown;
+ return fields->properties.decimalSeparatorAlwaysShown;
}
void DecimalFormat::setDecimalSeparatorAlwaysShown(UBool newValue) {
if (fields == nullptr) { return; }
- if (UBOOL_TO_BOOL(newValue) == fields->properties->decimalSeparatorAlwaysShown) { return; }
- fields->properties->decimalSeparatorAlwaysShown = newValue;
+ if (UBOOL_TO_BOOL(newValue) == fields->properties.decimalSeparatorAlwaysShown) { return; }
+ fields->properties.decimalSeparatorAlwaysShown = newValue;
touchNoError();
}
@@ -1236,13 +1226,13 @@
// Fallback to using the default instance of DecimalFormatProperties.
return DecimalFormatProperties::getDefault().decimalPatternMatchRequired;
}
- return fields->properties->decimalPatternMatchRequired;
+ return fields->properties.decimalPatternMatchRequired;
}
void DecimalFormat::setDecimalPatternMatchRequired(UBool newValue) {
if (fields == nullptr) { return; }
- if (UBOOL_TO_BOOL(newValue) == fields->properties->decimalPatternMatchRequired) { return; }
- fields->properties->decimalPatternMatchRequired = newValue;
+ if (UBOOL_TO_BOOL(newValue) == fields->properties.decimalPatternMatchRequired) { return; }
+ fields->properties.decimalPatternMatchRequired = newValue;
touchNoError();
}
@@ -1252,13 +1242,13 @@
// Fallback to using the default instance of DecimalFormatProperties.
return DecimalFormatProperties::getDefault().parseNoExponent;
}
- return fields->properties->parseNoExponent;
+ return fields->properties.parseNoExponent;
}
void DecimalFormat::setParseNoExponent(UBool value) {
if (fields == nullptr) { return; }
- if (UBOOL_TO_BOOL(value) == fields->properties->parseNoExponent) { return; }
- fields->properties->parseNoExponent = value;
+ if (UBOOL_TO_BOOL(value) == fields->properties.parseNoExponent) { return; }
+ fields->properties.parseNoExponent = value;
touchNoError();
}
@@ -1268,13 +1258,13 @@
// Fallback to using the default instance of DecimalFormatProperties.
return DecimalFormatProperties::getDefault().parseCaseSensitive;
}
- return fields->properties->parseCaseSensitive;
+ return fields->properties.parseCaseSensitive;
}
void DecimalFormat::setParseCaseSensitive(UBool value) {
if (fields == nullptr) { return; }
- if (UBOOL_TO_BOOL(value) == fields->properties->parseCaseSensitive) { return; }
- fields->properties->parseCaseSensitive = value;
+ if (UBOOL_TO_BOOL(value) == fields->properties.parseCaseSensitive) { return; }
+ fields->properties.parseCaseSensitive = value;
touchNoError();
}
@@ -1284,13 +1274,13 @@
// Fallback to using the default instance of DecimalFormatProperties.
return DecimalFormatProperties::getDefault().formatFailIfMoreThanMaxDigits;
}
- return fields->properties->formatFailIfMoreThanMaxDigits;
+ return fields->properties.formatFailIfMoreThanMaxDigits;
}
void DecimalFormat::setFormatFailIfMoreThanMaxDigits(UBool value) {
if (fields == nullptr) { return; }
- if (UBOOL_TO_BOOL(value) == fields->properties->formatFailIfMoreThanMaxDigits) { return; }
- fields->properties->formatFailIfMoreThanMaxDigits = value;
+ if (UBOOL_TO_BOOL(value) == fields->properties.formatFailIfMoreThanMaxDigits) { return; }
+ fields->properties.formatFailIfMoreThanMaxDigits = value;
touchNoError();
}
@@ -1305,7 +1295,7 @@
// so that CurrencyUsage is reflected properly.
// TODO: Consider putting this logic in number_patternstring.cpp instead.
ErrorCode localStatus;
- DecimalFormatProperties tprops(*fields->properties);
+ DecimalFormatProperties tprops(fields->properties);
bool useCurrency = (
!tprops.currency.isNull() ||
!tprops.currencyPluralInfo.fPtr.isNull() ||
@@ -1315,9 +1305,9 @@
AffixUtils::hasCurrencySymbols(tprops.negativePrefixPattern, localStatus) ||
AffixUtils::hasCurrencySymbols(tprops.negativeSuffixPattern, localStatus));
if (useCurrency) {
- tprops.minimumFractionDigits = fields->exportedProperties->minimumFractionDigits;
- tprops.maximumFractionDigits = fields->exportedProperties->maximumFractionDigits;
- tprops.roundingIncrement = fields->exportedProperties->roundingIncrement;
+ tprops.minimumFractionDigits = fields->exportedProperties.minimumFractionDigits;
+ tprops.maximumFractionDigits = fields->exportedProperties.maximumFractionDigits;
+ tprops.roundingIncrement = fields->exportedProperties.roundingIncrement;
}
result = PatternStringUtils::propertiesToPatternString(tprops, localStatus);
return result;
@@ -1373,49 +1363,53 @@
void DecimalFormat::setMaximumIntegerDigits(int32_t newValue) {
if (fields == nullptr) { return; }
- if (newValue == fields->properties->maximumIntegerDigits) { return; }
+ if (newValue == fields->properties.maximumIntegerDigits) { return; }
// For backwards compatibility, conflicting min/max need to keep the most recent setting.
- int32_t min = fields->properties->minimumIntegerDigits;
+ int32_t min = fields->properties.minimumIntegerDigits;
if (min >= 0 && min > newValue) {
- fields->properties->minimumIntegerDigits = newValue;
+ fields->properties.minimumIntegerDigits = newValue;
}
- fields->properties->maximumIntegerDigits = newValue;
+ fields->properties.maximumIntegerDigits = newValue;
touchNoError();
}
void DecimalFormat::setMinimumIntegerDigits(int32_t newValue) {
if (fields == nullptr) { return; }
- if (newValue == fields->properties->minimumIntegerDigits) { return; }
+ if (newValue == fields->properties.minimumIntegerDigits) { return; }
// For backwards compatibility, conflicting min/max need to keep the most recent setting.
- int32_t max = fields->properties->maximumIntegerDigits;
+ int32_t max = fields->properties.maximumIntegerDigits;
if (max >= 0 && max < newValue) {
- fields->properties->maximumIntegerDigits = newValue;
+ fields->properties.maximumIntegerDigits = newValue;
}
- fields->properties->minimumIntegerDigits = newValue;
+ fields->properties.minimumIntegerDigits = newValue;
touchNoError();
}
void DecimalFormat::setMaximumFractionDigits(int32_t newValue) {
if (fields == nullptr) { return; }
- if (newValue == fields->properties->maximumFractionDigits) { return; }
+ if (newValue == fields->properties.maximumFractionDigits) { return; }
+ // cap for backward compatibility, formerly 340, now 999
+ if (newValue > kMaxIntFracSig) {
+ newValue = kMaxIntFracSig;
+ }
// For backwards compatibility, conflicting min/max need to keep the most recent setting.
- int32_t min = fields->properties->minimumFractionDigits;
+ int32_t min = fields->properties.minimumFractionDigits;
if (min >= 0 && min > newValue) {
- fields->properties->minimumFractionDigits = newValue;
+ fields->properties.minimumFractionDigits = newValue;
}
- fields->properties->maximumFractionDigits = newValue;
+ fields->properties.maximumFractionDigits = newValue;
touchNoError();
}
void DecimalFormat::setMinimumFractionDigits(int32_t newValue) {
if (fields == nullptr) { return; }
- if (newValue == fields->properties->minimumFractionDigits) { return; }
+ if (newValue == fields->properties.minimumFractionDigits) { return; }
// For backwards compatibility, conflicting min/max need to keep the most recent setting.
- int32_t max = fields->properties->maximumFractionDigits;
+ int32_t max = fields->properties.maximumFractionDigits;
if (max >= 0 && max < newValue) {
- fields->properties->maximumFractionDigits = newValue;
+ fields->properties.maximumFractionDigits = newValue;
}
- fields->properties->minimumFractionDigits = newValue;
+ fields->properties.minimumFractionDigits = newValue;
touchNoError();
}
@@ -1425,7 +1419,7 @@
// Fallback to using the default instance of DecimalFormatProperties.
return DecimalFormatProperties::getDefault().minimumSignificantDigits;
}
- return fields->exportedProperties->minimumSignificantDigits;
+ return fields->exportedProperties.minimumSignificantDigits;
}
int32_t DecimalFormat::getMaximumSignificantDigits() const {
@@ -1434,28 +1428,28 @@
// Fallback to using the default instance of DecimalFormatProperties.
return DecimalFormatProperties::getDefault().maximumSignificantDigits;
}
- return fields->exportedProperties->maximumSignificantDigits;
+ return fields->exportedProperties.maximumSignificantDigits;
}
void DecimalFormat::setMinimumSignificantDigits(int32_t value) {
if (fields == nullptr) { return; }
- if (value == fields->properties->minimumSignificantDigits) { return; }
- int32_t max = fields->properties->maximumSignificantDigits;
+ if (value == fields->properties.minimumSignificantDigits) { return; }
+ int32_t max = fields->properties.maximumSignificantDigits;
if (max >= 0 && max < value) {
- fields->properties->maximumSignificantDigits = value;
+ fields->properties.maximumSignificantDigits = value;
}
- fields->properties->minimumSignificantDigits = value;
+ fields->properties.minimumSignificantDigits = value;
touchNoError();
}
void DecimalFormat::setMaximumSignificantDigits(int32_t value) {
if (fields == nullptr) { return; }
- if (value == fields->properties->maximumSignificantDigits) { return; }
- int32_t min = fields->properties->minimumSignificantDigits;
+ if (value == fields->properties.maximumSignificantDigits) { return; }
+ int32_t min = fields->properties.minimumSignificantDigits;
if (min >= 0 && min > value) {
- fields->properties->minimumSignificantDigits = value;
+ fields->properties.minimumSignificantDigits = value;
}
- fields->properties->maximumSignificantDigits = value;
+ fields->properties.maximumSignificantDigits = value;
touchNoError();
}
@@ -1466,7 +1460,7 @@
// Fallback to using the default instance of DecimalFormatProperties.
dfp = &(DecimalFormatProperties::getDefault());
} else {
- dfp = fields->properties.getAlias();
+ dfp = &fields->properties;
}
return dfp->minimumSignificantDigits != -1 || dfp->maximumSignificantDigits != -1;
}
@@ -1476,20 +1470,20 @@
// These are the default values from the old implementation.
if (useSignificantDigits) {
- if (fields->properties->minimumSignificantDigits != -1 ||
- fields->properties->maximumSignificantDigits != -1) {
+ if (fields->properties.minimumSignificantDigits != -1 ||
+ fields->properties.maximumSignificantDigits != -1) {
return;
}
} else {
- if (fields->properties->minimumSignificantDigits == -1 &&
- fields->properties->maximumSignificantDigits == -1) {
+ if (fields->properties.minimumSignificantDigits == -1 &&
+ fields->properties.maximumSignificantDigits == -1) {
return;
}
}
int32_t minSig = useSignificantDigits ? 1 : -1;
int32_t maxSig = useSignificantDigits ? 6 : -1;
- fields->properties->minimumSignificantDigits = minSig;
- fields->properties->maximumSignificantDigits = maxSig;
+ fields->properties.minimumSignificantDigits = minSig;
+ fields->properties.maximumSignificantDigits = maxSig;
touchNoError();
}
@@ -1503,11 +1497,11 @@
}
CurrencyUnit currencyUnit(theCurrency, ec);
if (U_FAILURE(ec)) { return; }
- if (!fields->properties->currency.isNull() && fields->properties->currency.getNoError() == currencyUnit) {
+ if (!fields->properties.currency.isNull() && fields->properties.currency.getNoError() == currencyUnit) {
return;
}
NumberFormat::setCurrency(theCurrency, ec); // to set field for compatibility
- fields->properties->currency = currencyUnit;
+ fields->properties.currency = currencyUnit;
// TODO: Set values in fields->symbols, too?
touchNoError();
}
@@ -1525,20 +1519,20 @@
*ec = U_MEMORY_ALLOCATION_ERROR;
return;
}
- if (!fields->properties->currencyUsage.isNull() && newUsage == fields->properties->currencyUsage.getNoError()) {
+ if (!fields->properties.currencyUsage.isNull() && newUsage == fields->properties.currencyUsage.getNoError()) {
return;
}
- fields->properties->currencyUsage = newUsage;
+ fields->properties.currencyUsage = newUsage;
touch(*ec);
}
UCurrencyUsage DecimalFormat::getCurrencyUsage() const {
// CurrencyUsage is not exported, so we have to get it from the input property bag.
// TODO: Should we export CurrencyUsage instead?
- if (fields == nullptr || fields->properties->currencyUsage.isNull()) {
+ if (fields == nullptr || fields->properties.currencyUsage.isNull()) {
return UCURR_USAGE_STANDARD;
}
- return fields->properties->currencyUsage.getNoError();
+ return fields->properties.currencyUsage.getNoError();
}
void
@@ -1550,7 +1544,7 @@
status = U_MEMORY_ALLOCATION_ERROR;
return;
}
- fields->formatter->formatDouble(number, status).getDecimalQuantity(output, status);
+ fields->formatter.formatDouble(number, status).getDecimalQuantity(output, status);
}
void DecimalFormat::formatToDecimalQuantity(const Formattable& number, DecimalQuantity& output,
@@ -1564,7 +1558,7 @@
}
UFormattedNumberData obj;
number.populateDecimalQuantity(obj.quantity, status);
- fields->formatter->formatImpl(&obj, status);
+ fields->formatter.formatImpl(&obj, status);
output = std::move(obj.quantity);
}
@@ -1576,12 +1570,7 @@
status = U_MEMORY_ALLOCATION_ERROR;
return nullptr;
}
- return &*fields->formatter;
-}
-
-const number::LocalizedNumberFormatter& DecimalFormat::toNumberFormatter() const {
- UErrorCode localStatus = U_ZERO_ERROR;
- return *toNumberFormatter(localStatus);
+ return &fields->formatter;
}
/** Rebuilds the formatter object from the property bag. */
@@ -1608,9 +1597,9 @@
// Since memory has already been allocated for the formatter, we can move assign a stack-allocated object
// and don't need to call new. (Which is slower and could possibly fail).
- *fields->formatter = NumberPropertyMapper::create(
- *fields->properties, *fields->symbols, fields->warehouse, *fields->exportedProperties, status).locale(
- locale);
+ fields->formatter = NumberPropertyMapper::create(
+ fields->properties, *fields->symbols, fields->warehouse, fields->exportedProperties, status
+ ).locale(locale);
// Do this after fields->exportedProperties are set up
setupFastFormat();
@@ -1620,13 +1609,13 @@
delete fields->atomicCurrencyParser.exchange(nullptr);
// In order for the getters to work, we need to populate some fields in NumberFormat.
- NumberFormat::setCurrency(fields->exportedProperties->currency.get(status).getISOCurrency(), status);
- NumberFormat::setMaximumIntegerDigits(fields->exportedProperties->maximumIntegerDigits);
- NumberFormat::setMinimumIntegerDigits(fields->exportedProperties->minimumIntegerDigits);
- NumberFormat::setMaximumFractionDigits(fields->exportedProperties->maximumFractionDigits);
- NumberFormat::setMinimumFractionDigits(fields->exportedProperties->minimumFractionDigits);
+ NumberFormat::setCurrency(fields->exportedProperties.currency.get(status).getISOCurrency(), status);
+ NumberFormat::setMaximumIntegerDigits(fields->exportedProperties.maximumIntegerDigits);
+ NumberFormat::setMinimumIntegerDigits(fields->exportedProperties.minimumIntegerDigits);
+ NumberFormat::setMaximumFractionDigits(fields->exportedProperties.maximumFractionDigits);
+ NumberFormat::setMinimumFractionDigits(fields->exportedProperties.minimumFractionDigits);
// fImpl->properties, not fields->exportedProperties, since this information comes from the pattern:
- NumberFormat::setGroupingUsed(fields->properties->groupingUsed);
+ NumberFormat::setGroupingUsed(fields->properties.groupingUsed);
}
void DecimalFormat::touchNoError() {
@@ -1639,7 +1628,7 @@
if (U_SUCCESS(status)) {
// Cast workaround to get around putting the enum in the public header file
auto actualIgnoreRounding = static_cast(ignoreRounding);
- PatternParser::parseToExistingProperties(pattern, *fields->properties, actualIgnoreRounding, status);
+ PatternParser::parseToExistingProperties(pattern, fields->properties, actualIgnoreRounding, status);
}
}
@@ -1658,7 +1647,7 @@
}
// Try computing the parser on our own
- auto* temp = NumberParserImpl::createParserFromProperties(*fields->properties, *fields->symbols, false, status);
+ auto* temp = NumberParserImpl::createParserFromProperties(fields->properties, *fields->symbols, false, status);
if (U_FAILURE(status)) {
return nullptr;
}
@@ -1691,7 +1680,7 @@
}
// Try computing the parser on our own
- auto* temp = NumberParserImpl::createParserFromProperties(*fields->properties, *fields->symbols, true, status);
+ auto* temp = NumberParserImpl::createParserFromProperties(fields->properties, *fields->symbols, true, status);
if (temp == nullptr) {
status = U_MEMORY_ALLOCATION_ERROR;
// although we may still dereference, call sites should be guarded
@@ -1739,7 +1728,7 @@
void DecimalFormat::setupFastFormat() {
// Check the majority of properties:
- if (!fields->properties->equalsDefaultExceptFastFormat()) {
+ if (!fields->properties.equalsDefaultExceptFastFormat()) {
trace("no fast format: equality\n");
fields->canUseFastFormat = false;
return;
@@ -1747,12 +1736,12 @@
// Now check the remaining properties.
// Nontrivial affixes:
- UBool trivialPP = fields->properties->positivePrefixPattern.isEmpty();
- UBool trivialPS = fields->properties->positiveSuffixPattern.isEmpty();
- UBool trivialNP = fields->properties->negativePrefixPattern.isBogus() || (
- fields->properties->negativePrefixPattern.length() == 1 &&
- fields->properties->negativePrefixPattern.charAt(0) == u'-');
- UBool trivialNS = fields->properties->negativeSuffixPattern.isEmpty();
+ UBool trivialPP = fields->properties.positivePrefixPattern.isEmpty();
+ UBool trivialPS = fields->properties.positiveSuffixPattern.isEmpty();
+ UBool trivialNP = fields->properties.negativePrefixPattern.isBogus() || (
+ fields->properties.negativePrefixPattern.length() == 1 &&
+ fields->properties.negativePrefixPattern.charAt(0) == u'-');
+ UBool trivialNS = fields->properties.negativeSuffixPattern.isEmpty();
if (!trivialPP || !trivialPS || !trivialNP || !trivialNS) {
trace("no fast format: affixes\n");
fields->canUseFastFormat = false;
@@ -1760,8 +1749,8 @@
}
// Grouping (secondary grouping is forbidden in equalsDefaultExceptFastFormat):
- bool groupingUsed = fields->properties->groupingUsed;
- int32_t groupingSize = fields->properties->groupingSize;
+ bool groupingUsed = fields->properties.groupingUsed;
+ int32_t groupingSize = fields->properties.groupingSize;
bool unusualGroupingSize = groupingSize > 0 && groupingSize != 3;
const UnicodeString& groupingString = fields->symbols->getConstSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol);
if (groupingUsed && (unusualGroupingSize || groupingString.length() != 1)) {
@@ -1771,8 +1760,8 @@
}
// Integer length:
- int32_t minInt = fields->exportedProperties->minimumIntegerDigits;
- int32_t maxInt = fields->exportedProperties->maximumIntegerDigits;
+ int32_t minInt = fields->exportedProperties.minimumIntegerDigits;
+ int32_t maxInt = fields->exportedProperties.maximumIntegerDigits;
// Fastpath supports up to only 10 digits (length of INT32_MIN)
if (minInt > 10) {
trace("no fast format: integer\n");
@@ -1781,7 +1770,7 @@
}
// Fraction length (no fraction part allowed in fast path):
- int32_t minFrac = fields->exportedProperties->minimumFractionDigits;
+ int32_t minFrac = fields->exportedProperties.minimumFractionDigits;
if (minFrac > 0) {
trace("no fast format: fraction\n");
fields->canUseFastFormat = false;
diff -Nru icu-64.2/source/i18n/decNumberLocal.h icu-65.1/source/i18n/decNumberLocal.h
--- icu-64.2/source/i18n/decNumberLocal.h 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/i18n/decNumberLocal.h 2019-10-03 11:16:41.000000000 +0000
@@ -259,7 +259,7 @@
/* 2,000,000,000 (as is needed for negative exponents of */
/* subnormals). The unsigned integer pow is used as a temporary */
/* variable. */
- #define TODIGIT(u, cut, c, pow) { \
+ #define TODIGIT(u, cut, c, pow) UPRV_BLOCK_MACRO_BEGIN { \
*(c)='0'; \
pow=DECPOWERS[cut]*2; \
if ((u)>pow) { \
@@ -272,7 +272,7 @@
if ((u)>=pow) {(u)-=pow; *(c)+=2;} \
pow/=2; \
if ((u)>=pow) {(u)-=pow; *(c)+=1;} \
- }
+ } UPRV_BLOCK_MACRO_END
/* ---------------------------------------------------------------- */
/* Definitions for fixed-precision modules (only valid after */
diff -Nru icu-64.2/source/i18n/double-conversion-bignum.cpp icu-65.1/source/i18n/double-conversion-bignum.cpp
--- icu-64.2/source/i18n/double-conversion-bignum.cpp 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/i18n/double-conversion-bignum.cpp 2019-10-03 11:16:41.000000000 +0000
@@ -34,6 +34,9 @@
#include "unicode/utypes.h"
#if !UCONFIG_NO_FORMATTING
+#include
+#include
+
// ICU PATCH: Customize header file paths for ICU.
#include "double-conversion-bignum.h"
@@ -44,136 +47,129 @@
namespace double_conversion {
-Bignum::Bignum()
- : bigits_buffer_(), bigits_(bigits_buffer_, kBigitCapacity), used_digits_(0), exponent_(0) {
- for (int i = 0; i < kBigitCapacity; ++i) {
- bigits_[i] = 0;
- }
+Bignum::Chunk& Bignum::RawBigit(const int index) {
+ DOUBLE_CONVERSION_ASSERT(static_cast(index) < kBigitCapacity);
+ return bigits_buffer_[index];
+}
+
+
+const Bignum::Chunk& Bignum::RawBigit(const int index) const {
+ DOUBLE_CONVERSION_ASSERT(static_cast(index) < kBigitCapacity);
+ return bigits_buffer_[index];
}
template
-static int BitSize(S value) {
+static int BitSize(const 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));
+void Bignum::AssignUInt16(const uint16_t value) {
+ DOUBLE_CONVERSION_ASSERT(kBigitSize >= BitSize(value));
Zero();
- if (value == 0) return;
-
- EnsureCapacity(1);
- bigits_[0] = value;
- used_digits_ = 1;
+ if (value > 0) {
+ RawBigit(0) = value;
+ used_bigits_ = 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;
+ for(int i = 0; value > 0; ++i) {
+ RawBigit(i) = value & kBigitMask;
+ value >>= kBigitSize;
+ ++used_bigits_;
}
- 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];
+ for (int i = 0; i < other.used_bigits_; ++i) {
+ RawBigit(i) = other.RawBigit(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_;
+ used_bigits_ = other.used_bigits_;
}
-static uint64_t ReadUInt64(Vector buffer,
- int from,
- int digits_to_read) {
+static uint64_t ReadUInt64(const Vector buffer,
+ const int from,
+ const 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);
+ const int digit = buffer[i] - '0';
+ DOUBLE_CONVERSION_ASSERT(0 <= digit && digit <= 9);
result = result * 10 + digit;
}
return result;
}
-void Bignum::AssignDecimalString(Vector value) {
+void Bignum::AssignDecimalString(const Vector value) {
// 2^64 = 18446744073709551616 > 10^19
- const int kMaxUint64DecimalDigits = 19;
+ static const int kMaxUint64DecimalDigits = 19;
Zero();
int length = value.length();
- unsigned int pos = 0;
+ unsigned pos = 0;
// Let's just say that each digit needs 4 bits.
while (length >= kMaxUint64DecimalDigits) {
- uint64_t digits = ReadUInt64(value, pos, kMaxUint64DecimalDigits);
+ const uint64_t digits = ReadUInt64(value, pos, kMaxUint64DecimalDigits);
pos += kMaxUint64DecimalDigits;
length -= kMaxUint64DecimalDigits;
MultiplyByPowerOfTen(kMaxUint64DecimalDigits);
AddUInt64(digits);
}
- uint64_t digits = ReadUInt64(value, pos, length);
+ const 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');
+static uint64_t HexCharValue(const int c) {
+ if ('0' <= c && c <= '9') {
+ return c - '0';
+ }
+ if ('a' <= c && c <= 'f') {
+ return 10 + c - 'a';
+ }
+ DOUBLE_CONVERSION_ASSERT('A' <= c && c <= 'F');
return 10 + c - 'A';
}
+// Unlike AssignDecimalString(), this function is "only" used
+// for unit-tests and therefore not performance critical.
void Bignum::AssignHexString(Vector 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_++;
+ // Required capacity could be reduced by ignoring leading zeros.
+ EnsureCapacity(((value.length() * 4) + kBigitSize - 1) / kBigitSize);
+ DOUBLE_CONVERSION_ASSERT(sizeof(uint64_t) * 8 >= kBigitSize + 4); // TODO: static_assert
+ // Accumulates converted hex digits until at least kBigitSize bits.
+ // Works with non-factor-of-four kBigitSizes.
+ uint64_t tmp = 0; // Accumulates converted hex digits until at least
+ for (int cnt = 0; !value.is_empty(); value.pop_back()) {
+ tmp |= (HexCharValue(value.last()) << cnt);
+ if ((cnt += 4) >= kBigitSize) {
+ RawBigit(used_bigits_++) = (tmp & kBigitMask);
+ cnt -= kBigitSize;
+ tmp >>= kBigitSize;
+ }
+ }
+ if (tmp > 0) {
+ RawBigit(used_bigits_++) = tmp;
}
Clamp();
}
-void Bignum::AddUInt64(uint64_t operand) {
- if (operand == 0) return;
+void Bignum::AddUInt64(const uint64_t operand) {
+ if (operand == 0) {
+ return;
+ }
Bignum other;
other.AssignUInt64(operand);
AddBignum(other);
@@ -181,8 +177,8 @@
void Bignum::AddBignum(const Bignum& other) {
- ASSERT(IsClamped());
- ASSERT(other.IsClamped());
+ DOUBLE_CONVERSION_ASSERT(IsClamped());
+ DOUBLE_CONVERSION_ASSERT(other.IsClamped());
// If this has a greater exponent than other append zero-bigits to this.
// After this call exponent_ <= other.exponent_.
@@ -200,48 +196,52 @@
// cccccccccccc 0000
// In both cases we might need a carry bigit.
- EnsureCapacity(1 + Max(BigitLength(), other.BigitLength()) - exponent_);
+ EnsureCapacity(1 + (std::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;
+ DOUBLE_CONVERSION_ASSERT(bigit_pos >= 0);
+ for (int i = used_bigits_; i < bigit_pos; ++i) {
+ RawBigit(i) = 0;
+ }
+ for (int i = 0; i < other.used_bigits_; ++i) {
+ const Chunk my = (bigit_pos < used_bigits_) ? RawBigit(bigit_pos) : 0;
+ const Chunk sum = my + other.RawBigit(i) + carry;
+ RawBigit(bigit_pos) = sum & kBigitMask;
carry = sum >> kBigitSize;
- bigit_pos++;
+ ++bigit_pos;
}
-
while (carry != 0) {
- Chunk sum = bigits_[bigit_pos] + carry;
- bigits_[bigit_pos] = sum & kBigitMask;
+ const Chunk my = (bigit_pos < used_bigits_) ? RawBigit(bigit_pos) : 0;
+ const Chunk sum = my + carry;
+ RawBigit(bigit_pos) = sum & kBigitMask;
carry = sum >> kBigitSize;
- bigit_pos++;
+ ++bigit_pos;
}
- used_digits_ = Max(bigit_pos, used_digits_);
- ASSERT(IsClamped());
+ used_bigits_ = (std::max)(bigit_pos, static_cast(used_bigits_));
+ DOUBLE_CONVERSION_ASSERT(IsClamped());
}
void Bignum::SubtractBignum(const Bignum& other) {
- ASSERT(IsClamped());
- ASSERT(other.IsClamped());
+ DOUBLE_CONVERSION_ASSERT(IsClamped());
+ DOUBLE_CONVERSION_ASSERT(other.IsClamped());
// We require this to be bigger than other.
- ASSERT(LessEqual(other, *this));
+ DOUBLE_CONVERSION_ASSERT(LessEqual(other, *this));
Align(other);
- int offset = other.exponent_ - exponent_;
+ const 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;
+ for (i = 0; i < other.used_bigits_; ++i) {
+ DOUBLE_CONVERSION_ASSERT((borrow == 0) || (borrow == 1));
+ const Chunk difference = RawBigit(i + offset) - other.RawBigit(i) - borrow;
+ RawBigit(i + offset) = difference & kBigitMask;
borrow = difference >> (kChunkSize - 1);
}
while (borrow != 0) {
- Chunk difference = bigits_[i + offset] - borrow;
- bigits_[i + offset] = difference & kBigitMask;
+ const Chunk difference = RawBigit(i + offset) - borrow;
+ RawBigit(i + offset) = difference & kBigitMask;
borrow = difference >> (kChunkSize - 1);
++i;
}
@@ -249,91 +249,105 @@
}
-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);
+void Bignum::ShiftLeft(const int shift_amount) {
+ if (used_bigits_ == 0) {
+ return;
+ }
+ exponent_ += (shift_amount / kBigitSize);
+ const int local_shift = shift_amount % kBigitSize;
+ EnsureCapacity(used_bigits_ + 1);
BigitsShiftLeft(local_shift);
}
-void Bignum::MultiplyByUInt32(uint32_t factor) {
- if (factor == 1) return;
+void Bignum::MultiplyByUInt32(const uint32_t factor) {
+ if (factor == 1) {
+ return;
+ }
if (factor == 0) {
Zero();
return;
}
- if (used_digits_ == 0) return;
-
+ if (used_bigits_ == 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);
+ DOUBLE_CONVERSION_ASSERT(kDoubleChunkSize >= kBigitSize + 32 + 1);
DoubleChunk carry = 0;
- for (int i = 0; i < used_digits_; ++i) {
- DoubleChunk product = static_cast(factor) * bigits_[i] + carry;
- bigits_[i] = static_cast(product & kBigitMask);
+ for (int i = 0; i < used_bigits_; ++i) {
+ const DoubleChunk product = static_cast(factor) * RawBigit(i) + carry;
+ RawBigit(i) = static_cast(product & kBigitMask);
carry = (product >> kBigitSize);
}
while (carry != 0) {
- EnsureCapacity(used_digits_ + 1);
- bigits_[used_digits_] = carry & kBigitMask;
- used_digits_++;
+ EnsureCapacity(used_bigits_ + 1);
+ RawBigit(used_bigits_) = carry & kBigitMask;
+ used_bigits_++;
carry >>= kBigitSize;
}
}
-void Bignum::MultiplyByUInt64(uint64_t factor) {
- if (factor == 1) return;
+void Bignum::MultiplyByUInt64(const uint64_t factor) {
+ if (factor == 1) {
+ return;
+ }
if (factor == 0) {
Zero();
return;
}
- ASSERT(kBigitSize < 32);
+ if (used_bigits_ == 0) {
+ return;
+ }
+ DOUBLE_CONVERSION_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;
+ const uint64_t low = factor & 0xFFFFFFFF;
+ const uint64_t high = factor >> 32;
+ for (int i = 0; i < used_bigits_; ++i) {
+ const uint64_t product_low = low * RawBigit(i);
+ const uint64_t product_high = high * RawBigit(i);
+ const uint64_t tmp = (carry & kBigitMask) + product_low;
+ RawBigit(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_++;
+ EnsureCapacity(used_bigits_ + 1);
+ RawBigit(used_bigits_) = carry & kBigitMask;
+ used_bigits_++;
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[] =
+void Bignum::MultiplyByPowerOfTen(const int exponent) {
+ static const uint64_t kFive27 = DOUBLE_CONVERSION_UINT64_2PART_C(0x6765c793, fa10079d);
+ static const uint16_t kFive1 = 5;
+ static const uint16_t kFive2 = kFive1 * 5;
+ static const uint16_t kFive3 = kFive2 * 5;
+ static const uint16_t kFive4 = kFive3 * 5;
+ static const uint16_t kFive5 = kFive4 * 5;
+ static const uint16_t kFive6 = kFive5 * 5;
+ static const uint32_t kFive7 = kFive6 * 5;
+ static const uint32_t kFive8 = kFive7 * 5;
+ static const uint32_t kFive9 = kFive8 * 5;
+ static const uint32_t kFive10 = kFive9 * 5;
+ static const uint32_t kFive11 = kFive10 * 5;
+ static const uint32_t kFive12 = kFive11 * 5;
+ static const uint32_t kFive13 = kFive12 * 5;
+ static 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;
+ DOUBLE_CONVERSION_ASSERT(exponent >= 0);
+ if (exponent == 0) {
+ return;
+ }
+ if (used_bigits_ == 0) {
+ return;
+ }
// We shift by exponent at the end just before returning.
int remaining_exponent = exponent;
while (remaining_exponent >= 27) {
@@ -352,8 +366,8 @@
void Bignum::Square() {
- ASSERT(IsClamped());
- int product_length = 2 * used_digits_;
+ DOUBLE_CONVERSION_ASSERT(IsClamped());
+ const int product_length = 2 * used_bigits_;
EnsureCapacity(product_length);
// Comba multiplication: compute each column separately.
@@ -368,64 +382,64 @@
//
// 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();
+ if ((1 << (2 * (kChunkSize - kBigitSize))) <= used_bigits_) {
+ DOUBLE_CONVERSION_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];
+ const int copy_offset = used_bigits_;
+ for (int i = 0; i < used_bigits_; ++i) {
+ RawBigit(copy_offset + i) = RawBigit(i);
}
// We have two loops to avoid some 'if's in the loop.
- for (int i = 0; i < used_digits_; ++i) {
+ for (int i = 0; i < used_bigits_; ++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];
+ const Chunk chunk1 = RawBigit(copy_offset + bigit_index1);
+ const Chunk chunk2 = RawBigit(copy_offset + bigit_index2);
accumulator += static_cast(chunk1) * chunk2;
bigit_index1--;
bigit_index2++;
}
- bigits_[i] = static_cast(accumulator) & kBigitMask;
+ RawBigit(i) = static_cast(accumulator) & kBigitMask;
accumulator >>= kBigitSize;
}
- for (int i = used_digits_; i < product_length; ++i) {
- int bigit_index1 = used_digits_ - 1;
+ for (int i = used_bigits_; i < product_length; ++i) {
+ int bigit_index1 = used_bigits_ - 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];
+ while (bigit_index2 < used_bigits_) {
+ const Chunk chunk1 = RawBigit(copy_offset + bigit_index1);
+ const Chunk chunk2 = RawBigit(copy_offset + bigit_index2);
accumulator += static_cast(chunk1) * chunk2;
bigit_index1--;
bigit_index2++;
}
- // The overwritten bigits_[i] will never be read in further loop iterations,
+ // The overwritten RawBigit(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(accumulator) & kBigitMask;
+ // than i - used_bigits_.
+ RawBigit(i) = static_cast(accumulator) & kBigitMask;
accumulator >>= kBigitSize;
}
// Since the result was guaranteed to lie inside the number the
// accumulator must be 0 now.
- ASSERT(accumulator == 0);
+ DOUBLE_CONVERSION_ASSERT(accumulator == 0);
// Don't forget to update the used_digits and the exponent.
- used_digits_ = product_length;
+ used_bigits_ = product_length;
exponent_ *= 2;
Clamp();
}
-void Bignum::AssignPowerUInt16(uint16_t base, int power_exponent) {
- ASSERT(base != 0);
- ASSERT(power_exponent >= 0);
+void Bignum::AssignPowerUInt16(uint16_t base, const int power_exponent) {
+ DOUBLE_CONVERSION_ASSERT(base != 0);
+ DOUBLE_CONVERSION_ASSERT(power_exponent >= 0);
if (power_exponent == 0) {
AssignUInt16(1);
return;
@@ -445,7 +459,7 @@
tmp_base >>= 1;
bit_size++;
}
- int final_size = bit_size * power_exponent;
+ const int final_size = bit_size * power_exponent;
// 1 extra bigit for the shifting, and one for rounded final_size.
EnsureCapacity(final_size / kBigitSize + 2);
@@ -466,10 +480,10 @@
// 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) {
- ASSERT(bit_size > 0);
- uint64_t base_bits_mask =
- ~((static_cast(1) << (64 - bit_size)) - 1);
- bool high_bits_zero = (this_value & base_bits_mask) == 0;
+ DOUBLE_CONVERSION_ASSERT(bit_size > 0);
+ const uint64_t base_bits_mask =
+ ~((static_cast(1) << (64 - bit_size)) - 1);
+ const bool high_bits_zero = (this_value & base_bits_mask) == 0;
if (high_bits_zero) {
this_value *= base;
} else {
@@ -499,9 +513,9 @@
// Precondition: this/other < 16bit.
uint16_t Bignum::DivideModuloIntBignum(const Bignum& other) {
- ASSERT(IsClamped());
- ASSERT(other.IsClamped());
- ASSERT(other.used_digits_ > 0);
+ DOUBLE_CONVERSION_ASSERT(IsClamped());
+ DOUBLE_CONVERSION_ASSERT(other.IsClamped());
+ DOUBLE_CONVERSION_ASSERT(other.used_bigits_ > 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.
@@ -519,34 +533,34 @@
// 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);
+ DOUBLE_CONVERSION_ASSERT(other.RawBigit(other.used_bigits_ - 1) >= ((1 << kBigitSize) / 16));
+ DOUBLE_CONVERSION_ASSERT(RawBigit(used_bigits_ - 1) < 0x10000);
// Remove the multiples of the first digit.
// Example this = 23 and other equals 9. -> Remove 2 multiples.
- result += static_cast(bigits_[used_digits_ - 1]);
- SubtractTimes(other, bigits_[used_digits_ - 1]);
+ result += static_cast(RawBigit(used_bigits_ - 1));
+ SubtractTimes(other, RawBigit(used_bigits_ - 1));
}
- ASSERT(BigitLength() == other.BigitLength());
+ DOUBLE_CONVERSION_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];
+ // RawBigit(used_bigits_ - 1) is safe.
+ const Chunk this_bigit = RawBigit(used_bigits_ - 1);
+ const Chunk other_bigit = other.RawBigit(other.used_bigits_ - 1);
- if (other.used_digits_ == 1) {
+ if (other.used_bigits_ == 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);
+ RawBigit(used_bigits_ - 1) = this_bigit - other_bigit * quotient;
+ DOUBLE_CONVERSION_ASSERT(quotient < 0x10000);
result += static_cast(quotient);
Clamp();
return result;
}
- int division_estimate = this_bigit / (other_bigit + 1);
- ASSERT(division_estimate < 0x10000);
+ const int division_estimate = this_bigit / (other_bigit + 1);
+ DOUBLE_CONVERSION_ASSERT(division_estimate < 0x10000);
result += static_cast(division_estimate);
SubtractTimes(other, division_estimate);
@@ -566,7 +580,7 @@
template
static int SizeInHexChars(S number) {
- ASSERT(number > 0);
+ DOUBLE_CONVERSION_ASSERT(number > 0);
int result = 0;
while (number != 0) {
number >>= 4;
@@ -576,29 +590,35 @@
}
-static char HexCharOfValue(int value) {
- ASSERT(0 <= value && value <= 16);
- if (value < 10) return static_cast(value + '0');
+static char HexCharOfValue(const int value) {
+ DOUBLE_CONVERSION_ASSERT(0 <= value && value <= 16);
+ if (value < 10) {
+ return static_cast(value + '0');
+ }
return static_cast(value - 10 + 'A');
}
-bool Bignum::ToHexString(char* buffer, int buffer_size) const {
- ASSERT(IsClamped());
+bool Bignum::ToHexString(char* buffer, const int buffer_size) const {
+ DOUBLE_CONVERSION_ASSERT(IsClamped());
// Each bigit must be printable as separate hex-character.
- ASSERT(kBigitSize % 4 == 0);
- const int kHexCharsPerBigit = kBigitSize / 4;
+ DOUBLE_CONVERSION_ASSERT(kBigitSize % 4 == 0);
+ static const int kHexCharsPerBigit = kBigitSize / 4;
- if (used_digits_ == 0) {
- if (buffer_size < 2) return false;
+ if (used_bigits_ == 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;
+ const int needed_chars = (BigitLength() - 1) * kHexCharsPerBigit +
+ SizeInHexChars(RawBigit(used_bigits_ - 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) {
@@ -606,15 +626,15 @@
buffer[string_index--] = '0';
}
}
- for (int i = 0; i < used_digits_ - 1; ++i) {
- Chunk current_bigit = bigits_[i];
+ for (int i = 0; i < used_bigits_ - 1; ++i) {
+ Chunk current_bigit = RawBigit(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];
+ Chunk most_significant_bigit = RawBigit(used_bigits_ - 1);
while (most_significant_bigit != 0) {
buffer[string_index--] = HexCharOfValue(most_significant_bigit & 0xF);
most_significant_bigit >>= 4;
@@ -623,25 +643,37 @@
}
-Bignum::Chunk Bignum::BigitAt(int index) const {
- if (index >= BigitLength()) return 0;
- if (index < exponent_) return 0;
- return bigits_[index - exponent_];
+Bignum::Chunk Bignum::BigitOrZero(const int index) const {
+ if (index >= BigitLength()) {
+ return 0;
+ }
+ if (index < exponent_) {
+ return 0;
+ }
+ return RawBigit(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;
+ DOUBLE_CONVERSION_ASSERT(a.IsClamped());
+ DOUBLE_CONVERSION_ASSERT(b.IsClamped());
+ const int bigit_length_a = a.BigitLength();
+ const 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 >= (std::min)(a.exponent_, b.exponent_); --i) {
+ const Chunk bigit_a = a.BigitOrZero(i);
+ const Chunk bigit_b = b.BigitOrZero(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;
@@ -649,14 +681,18 @@
int Bignum::PlusCompare(const Bignum& a, const Bignum& b, const Bignum& c) {
- ASSERT(a.IsClamped());
- ASSERT(b.IsClamped());
- ASSERT(c.IsClamped());
+ DOUBLE_CONVERSION_ASSERT(a.IsClamped());
+ DOUBLE_CONVERSION_ASSERT(b.IsClamped());
+ DOUBLE_CONVERSION_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;
+ 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'.
@@ -666,92 +702,83 @@
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_);
+ const int min_exponent = (std::min)((std::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;
+ const Chunk chunk_a = a.BigitOrZero(i);
+ const Chunk chunk_b = b.BigitOrZero(i);
+ const Chunk chunk_c = c.BigitOrZero(i);
+ const Chunk sum = chunk_a + chunk_b;
if (sum > chunk_c + borrow) {
return +1;
} else {
borrow = chunk_c + borrow - sum;
- if (borrow > 1) return -1;
+ if (borrow > 1) {
+ return -1;
+ }
borrow <<= kBigitSize;
}
}
- if (borrow == 0) return 0;
+ if (borrow == 0) {
+ return 0;
+ }
return -1;
}
void Bignum::Clamp() {
- while (used_digits_ > 0 && bigits_[used_digits_ - 1] == 0) {
- used_digits_--;
+ while (used_bigits_ > 0 && RawBigit(used_bigits_ - 1) == 0) {
+ used_bigits_--;
}
- if (used_digits_ == 0) {
+ if (used_bigits_ == 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
+ // If "X" represents a "hidden" bigit (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];
+ const int zero_bigits = exponent_ - other.exponent_;
+ EnsureCapacity(used_bigits_ + zero_bigits);
+ for (int i = used_bigits_ - 1; i >= 0; --i) {
+ RawBigit(i + zero_bigits) = RawBigit(i);
}
- for (int i = 0; i < zero_digits; ++i) {
- bigits_[i] = 0;
+ for (int i = 0; i < zero_bigits; ++i) {
+ RawBigit(i) = 0;
}
- used_digits_ += zero_digits;
- exponent_ -= zero_digits;
- ASSERT(used_digits_ >= 0);
- ASSERT(exponent_ >= 0);
+ used_bigits_ += zero_bigits;
+ exponent_ -= zero_bigits;
+
+ DOUBLE_CONVERSION_ASSERT(used_bigits_ >= 0);
+ DOUBLE_CONVERSION_ASSERT(exponent_ >= 0);
}
}
-void Bignum::BigitsShiftLeft(int shift_amount) {
- ASSERT(shift_amount < kBigitSize);
- ASSERT(shift_amount >= 0);
+void Bignum::BigitsShiftLeft(const int shift_amount) {
+ DOUBLE_CONVERSION_ASSERT(shift_amount < kBigitSize);
+ DOUBLE_CONVERSION_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;
+ for (int i = 0; i < used_bigits_; ++i) {
+ const Chunk new_carry = RawBigit(i) >> (kBigitSize - shift_amount);
+ RawBigit(i) = ((RawBigit(i) << shift_amount) + carry) & kBigitMask;
carry = new_carry;
}
if (carry != 0) {
- bigits_[used_digits_] = carry;
- used_digits_++;
+ RawBigit(used_bigits_) = carry;
+ used_bigits_++;
}
}
-void Bignum::SubtractTimes(const Bignum& other, int factor) {
- ASSERT(exponent_ <= other.exponent_);
+void Bignum::SubtractTimes(const Bignum& other, const int factor) {
+ DOUBLE_CONVERSION_ASSERT(exponent_ <= other.exponent_);
if (factor < 3) {
for (int i = 0; i < factor; ++i) {
SubtractBignum(other);
@@ -759,19 +786,21 @@
return;
}
Chunk borrow = 0;
- int exponent_diff = other.exponent_ - exponent_;
- for (int i = 0; i < other.used_digits_; ++i) {
- DoubleChunk product = static_cast(factor) * other.bigits_[i];
- DoubleChunk remove = borrow + product;
- Chunk difference = bigits_[i + exponent_diff] - (remove & kBigitMask);
- bigits_[i + exponent_diff] = difference & kBigitMask;
+ const int exponent_diff = other.exponent_ - exponent_;
+ for (int i = 0; i < other.used_bigits_; ++i) {
+ const DoubleChunk product = static_cast(factor) * other.RawBigit(i);
+ const DoubleChunk remove = borrow + product;
+ const Chunk difference = RawBigit(i + exponent_diff) - (remove & kBigitMask);
+ RawBigit(i + exponent_diff) = difference & kBigitMask;
borrow = static_cast((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;
+ for (int i = other.used_bigits_ + exponent_diff; i < used_bigits_; ++i) {
+ if (borrow == 0) {
+ return;
+ }
+ const Chunk difference = RawBigit(i) - borrow;
+ RawBigit(i) = difference & kBigitMask;
borrow = difference >> (kChunkSize - 1);
}
Clamp();
diff -Nru icu-64.2/source/i18n/double-conversion-bignum-dtoa.cpp icu-65.1/source/i18n/double-conversion-bignum-dtoa.cpp
--- icu-64.2/source/i18n/double-conversion-bignum-dtoa.cpp 2019-04-17 19:42:15.000000000 +0000
+++ icu-65.1/source/i18n/double-conversion-bignum-dtoa.cpp 2019-10-03 11:16:41.000000000 +0000
@@ -49,7 +49,7 @@
namespace double_conversion {
static int NormalizedExponent(uint64_t significand, int exponent) {
- ASSERT(significand != 0);
+ DOUBLE_CONVERSION_ASSERT(significand != 0);
while ((significand & Double::kHiddenBit) == 0) {
significand = significand << 1;
exponent = exponent - 1;
@@ -90,26 +90,26 @@
// Generates 'requested_digits' after the decimal point.
static void BignumToFixed(int requested_digits, int* decimal_point,
Bignum* numerator, Bignum* denominator,
- Vector(buffer), int* length);
+ Vector 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(buffer), int* length);
+ Vector buffer, int* length);
void BignumDtoa(double v, BignumDtoaMode mode, int requested_digits,
Vector buffer, int* length, int* decimal_point) {
- ASSERT(v > 0);
- ASSERT(!Double(v).IsSpecial());
+ DOUBLE_CONVERSION_ASSERT(v > 0);
+ DOUBLE_CONVERSION_ASSERT(!Double(v).IsSpecial());
uint64_t significand;
int exponent;
bool lower_boundary_is_closer;
if (mode == BIGNUM_DTOA_SHORTEST_SINGLE) {
float f = static_cast(v);
- ASSERT(f == v);
+ DOUBLE_CONVERSION_ASSERT(f == v);
significand = Single(f).Significand();
exponent = Single(f).Exponent();
lower_boundary_is_closer = Single(f).LowerBoundaryIsCloser();
@@ -148,7 +148,7 @@
// 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);
+ DOUBLE_CONVERSION_ASSERT(Bignum::kMaxSignificantBits >= 324*4);
InitialScaledStartValues(significand, exponent, lower_boundary_is_closer,
estimated_power, need_boundary_deltas,
&numerator, &denominator,
@@ -177,7 +177,7 @@
buffer, length);
break;
default:
- UNREACHABLE();
+ DOUBLE_CONVERSION_UNREACHABLE();
}
buffer[*length] = '\0';
}
@@ -209,7 +209,7 @@
for (;;) {
uint16_t digit;
digit = numerator->DivideModuloIntBignum(*denominator);
- ASSERT(digit <= 9); // digit is a uint16_t and therefore always positive.
+ DOUBLE_CONVERSION_ASSERT(digit <= 9); // digit is a uint16_t and therefore always positive.
// digit = numerator / denominator (integer division).
// numerator = numerator % denominator.
buffer[(*length)++] = static_cast(digit + '0');
@@ -255,7 +255,7 @@
// loop would have stopped earlier.
// We still have an assert here in case the preconditions were not
// satisfied.
- ASSERT(buffer[(*length) - 1] != '9');
+ DOUBLE_CONVERSION_ASSERT(buffer[(*length) - 1] != '9');
buffer[(*length) - 1]++;
} else {
// Halfway case.
@@ -266,7 +266,7 @@
if ((buffer[(*length) - 1] - '0') % 2 == 0) {
// Round down => Do nothing.
} else {
- ASSERT(buffer[(*length) - 1] != '9');
+ DOUBLE_CONVERSION_ASSERT(buffer[(*length) - 1] != '9');
buffer[(*length) - 1]++;
}
}
@@ -278,9 +278,9 @@
// 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
+ // We still have an DOUBLE_CONVERSION_ASSERT here, in case the preconditions were not
// satisfied.
- ASSERT(buffer[(*length) -1] != '9');
+ DOUBLE_CONVERSION_ASSERT(buffer[(*length) -1] != '9');
buffer[(*length) - 1]++;
return;
}
@@ -297,11 +297,11 @@
static void GenerateCountedDigits(int count, int* decimal_point,
Bignum* numerator, Bignum* denominator,
Vector buffer, int* length) {
- ASSERT(count >= 0);
+ DOUBLE_CONVERSION_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.
+ DOUBLE_CONVERSION_ASSERT(digit <= 9); // digit is a uint16_t and therefore always positive.
// digit = numerator / denominator (integer division).
// numerator = numerator % denominator.
buffer[i] = static_cast(digit + '0');
@@ -314,7 +314,7 @@
if (Bignum::PlusCompare(*numerator, *numerator, *denominator) >= 0) {
digit++;
}
- ASSERT(digit <= 10);
+ DOUBLE_CONVERSION_ASSERT(digit <= 10);
buffer[count - 1] = static_cast