ICU-13725 Additional MSVC compatibility fixes.

X-SVN-Rev: 41272
This commit is contained in:
Shane Carr 2018-04-25 00:39:22 +00:00
parent a7bcbfc07c
commit a256316990
20 changed files with 93 additions and 53 deletions

View file

@ -440,7 +440,7 @@
<ClInclude Include="uinvchar.h" />
<ClInclude Include="ustr_cnv.h" />
<ClInclude Include="ustr_imp.h" />
<ClCompile Include="numparse_unisets.h" />
<ClInclude Include="numparse_unisets.h" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="common.rc" />

View file

@ -566,7 +566,7 @@
<ClInclude Include="uinvchar.h" />
<ClInclude Include="ustr_cnv.h" />
<ClInclude Include="ustr_imp.h" />
<ClCompile Include="numparse_unisets.h" />
<ClInclude Include="numparse_unisets.h" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="common.rc" />

View file

@ -61,12 +61,14 @@ enum Key {
COUNT
};
// Exported as U_COMMON_API for ucurr.h
const U_COMMON_API UnicodeSet* get(Key key);
// Exported as U_COMMON_API for ucurr.cpp
U_COMMON_API const UnicodeSet* get(Key key);
Key chooseFrom(UnicodeString str, Key key1);
// Exported as U_COMMON_API for numparse_decimal.cpp
U_COMMON_API Key chooseFrom(UnicodeString str, Key key1);
Key chooseFrom(UnicodeString str, Key key1, Key key2);
// Exported as U_COMMON_API for numparse_decimal.cpp
U_COMMON_API Key chooseFrom(UnicodeString str, Key key1, Key key2);
// Unused in C++:
// Key chooseCurrency(UnicodeString str);

View file

@ -30,6 +30,14 @@ using namespace icu::numparse::impl;
using ERoundingMode = icu::DecimalFormat::ERoundingMode;
using EPadPosition = icu::DecimalFormat::EPadPosition;
// MSVC warns C4805 when comparing bool with UBool
// TODO: Move this macro into a better place?
#if U_PF_WINDOWS <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN
#define UBOOL_TO_BOOL(b) static_cast<bool>(b)
#else
#define UBOOL_TO_BOOL(b) b
#endif
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(DecimalFormat)
@ -89,7 +97,10 @@ DecimalFormat::DecimalFormat(const UnicodeString& pattern, DecimalFormatSymbols*
DecimalFormat::DecimalFormat(const DecimalFormatSymbols* symbolsToAdopt, UErrorCode& status) {
fProperties.adoptInsteadAndCheckErrorCode(new DecimalFormatProperties(), status);
fExportedProperties.adoptInsteadAndCheckErrorCode(new DecimalFormatProperties(), status);
fWarehouse.adoptInsteadAndCheckErrorCode(new DecimalFormatWarehouse(), status);
fWarehouse = new DecimalFormatWarehouse();
if (fWarehouse == nullptr) {
status = U_MEMORY_ALLOCATION_ERROR;
}
if (symbolsToAdopt == nullptr) {
fSymbols.adoptInsteadAndCheckErrorCode(new DecimalFormatSymbols(status), status);
} else {
@ -331,14 +342,14 @@ int32_t DecimalFormat::getAttribute(UNumberFormatAttribute attr, UErrorCode& sta
}
void DecimalFormat::setGroupingUsed(UBool enabled) {
if (enabled == fProperties->groupingUsed) { return; }
if (UBOOL_TO_BOOL(enabled) == fProperties->groupingUsed) { return; }
NumberFormat::setGroupingUsed(enabled); // to set field for compatibility
fProperties->groupingUsed = enabled;
touchNoError();
}
void DecimalFormat::setParseIntegerOnly(UBool value) {
if (value == fProperties->parseIntegerOnly) { return; }
if (UBOOL_TO_BOOL(value) == fProperties->parseIntegerOnly) { return; }
NumberFormat::setParseIntegerOnly(value); // to set field for compatibility
fProperties->parseIntegerOnly = value;
touchNoError();
@ -374,7 +385,7 @@ DecimalFormat::DecimalFormat(const DecimalFormat& source) : NumberFormat(source)
fProperties.adoptInstead(new DecimalFormatProperties(*source.fProperties));
fSymbols.adoptInstead(new DecimalFormatSymbols(*source.fSymbols));
fExportedProperties.adoptInstead(new DecimalFormatProperties());
fWarehouse.adoptInstead(new DecimalFormatWarehouse());
fWarehouse = new DecimalFormatWarehouse();
if (fProperties == nullptr || fSymbols == nullptr || fExportedProperties == nullptr ||
fWarehouse == nullptr) {
return;
@ -391,8 +402,9 @@ DecimalFormat& DecimalFormat::operator=(const DecimalFormat& rhs) {
}
DecimalFormat::~DecimalFormat() {
delete fAtomicParser.exchange(nullptr);
delete fAtomicCurrencyParser.exchange(nullptr);
delete fWarehouse->fAtomicParser.exchange(nullptr);
delete fWarehouse->fAtomicCurrencyParser.exchange(nullptr);
delete fWarehouse;
};
Format* DecimalFormat::clone() const {
@ -665,7 +677,7 @@ UBool DecimalFormat::isSignAlwaysShown() const {
}
void DecimalFormat::setSignAlwaysShown(UBool value) {
if (value == fProperties->signAlwaysShown) { return; }
if (UBOOL_TO_BOOL(value) == fProperties->signAlwaysShown) { return; }
fProperties->signAlwaysShown = value;
touchNoError();
}
@ -819,7 +831,7 @@ UBool DecimalFormat::isExponentSignAlwaysShown(void) const {
}
void DecimalFormat::setExponentSignAlwaysShown(UBool expSignAlways) {
if (expSignAlways == fProperties->exponentSignAlwaysShown) { return; }
if (UBOOL_TO_BOOL(expSignAlways) == fProperties->exponentSignAlwaysShown) { return; }
fProperties->exponentSignAlwaysShown = expSignAlways;
touchNoError();
}
@ -866,7 +878,7 @@ UBool DecimalFormat::isDecimalSeparatorAlwaysShown(void) const {
}
void DecimalFormat::setDecimalSeparatorAlwaysShown(UBool newValue) {
if (newValue == fProperties->decimalSeparatorAlwaysShown) { return; }
if (UBOOL_TO_BOOL(newValue) == fProperties->decimalSeparatorAlwaysShown) { return; }
fProperties->decimalSeparatorAlwaysShown = newValue;
touchNoError();
}
@ -876,7 +888,7 @@ UBool DecimalFormat::isDecimalPatternMatchRequired(void) const {
}
void DecimalFormat::setDecimalPatternMatchRequired(UBool newValue) {
if (newValue == fProperties->decimalPatternMatchRequired) { return; }
if (UBOOL_TO_BOOL(newValue) == fProperties->decimalPatternMatchRequired) { return; }
fProperties->decimalPatternMatchRequired = newValue;
touchNoError();
}
@ -886,7 +898,7 @@ UBool DecimalFormat::isParseNoExponent() const {
}
void DecimalFormat::setParseNoExponent(UBool value) {
if (value == fProperties->parseNoExponent) { return; }
if (UBOOL_TO_BOOL(value) == fProperties->parseNoExponent) { return; }
fProperties->parseNoExponent = value;
touchNoError();
}
@ -896,7 +908,7 @@ UBool DecimalFormat::isParseCaseSensitive() const {
}
void DecimalFormat::setParseCaseSensitive(UBool value) {
if (value == fProperties->parseCaseSensitive) { return; }
if (UBOOL_TO_BOOL(value) == fProperties->parseCaseSensitive) { return; }
fProperties->parseCaseSensitive = value;
touchNoError();
}
@ -906,7 +918,7 @@ UBool DecimalFormat::isFormatFailIfMoreThanMaxDigits() const {
}
void DecimalFormat::setFormatFailIfMoreThanMaxDigits(UBool value) {
if (value == fProperties->formatFailIfMoreThanMaxDigits) { return; }
if (UBOOL_TO_BOOL(value) == fProperties->formatFailIfMoreThanMaxDigits) { return; }
fProperties->formatFailIfMoreThanMaxDigits = value;
touchNoError();
}
@ -1129,8 +1141,8 @@ void DecimalFormat::touch(UErrorCode& status) {
setupFastFormat();
// Delete the parsers if they were made previously
delete fAtomicParser.exchange(nullptr);
delete fAtomicCurrencyParser.exchange(nullptr);
delete fWarehouse->fAtomicParser.exchange(nullptr);
delete fWarehouse->fAtomicCurrencyParser.exchange(nullptr);
// In order for the getters to work, we need to populate some fields in NumberFormat.
NumberFormat::setCurrency(fExportedProperties->currency.get(status).getISOCurrency(), status);
@ -1158,7 +1170,7 @@ const numparse::impl::NumberParserImpl* DecimalFormat::getParser(UErrorCode& sta
if (U_FAILURE(status)) { return nullptr; }
// First try to get the pre-computed parser
auto* ptr = fAtomicParser.load();
auto* ptr = fWarehouse->fAtomicParser.load();
if (ptr != nullptr) {
return ptr;
}
@ -1173,7 +1185,7 @@ const numparse::impl::NumberParserImpl* DecimalFormat::getParser(UErrorCode& sta
// Note: ptr starts as nullptr; during compare_exchange, it is set to what is actually stored in the
// atomic if another thread beat us to computing the parser object.
auto* nonConstThis = const_cast<DecimalFormat*>(this);
if (!nonConstThis->fAtomicParser.compare_exchange_strong(ptr, temp)) {
if (!nonConstThis->fWarehouse->fAtomicParser.compare_exchange_strong(ptr, temp)) {
// Another thread beat us to computing the parser
delete temp;
return ptr;
@ -1187,7 +1199,7 @@ const numparse::impl::NumberParserImpl* DecimalFormat::getCurrencyParser(UErrorC
if (U_FAILURE(status)) { return nullptr; }
// First try to get the pre-computed parser
auto* ptr = fAtomicCurrencyParser.load();
auto* ptr = fWarehouse->fAtomicCurrencyParser.load();
if (ptr != nullptr) {
return ptr;
}
@ -1202,7 +1214,7 @@ const numparse::impl::NumberParserImpl* DecimalFormat::getCurrencyParser(UErrorC
// Note: ptr starts as nullptr; during compare_exchange, it is set to what is actually stored in the
// atomic if another thread beat us to computing the parser object.
auto* nonConstThis = const_cast<DecimalFormat*>(this);
if (!nonConstThis->fAtomicCurrencyParser.compare_exchange_strong(ptr, temp)) {
if (!nonConstThis->fWarehouse->fAtomicCurrencyParser.compare_exchange_strong(ptr, temp)) {
// Another thread beat us to computing the parser
delete temp;
return ptr;

View file

@ -15,7 +15,8 @@ U_NAMESPACE_BEGIN namespace number {
namespace impl {
class CurrencySymbols : public UMemory {
// Exported as U_I18N_API for tests
class U_I18N_API CurrencySymbols : public UMemory {
public:
CurrencySymbols() = default; // default constructor: leaves class in valid but undefined state

View file

@ -509,9 +509,9 @@ int64_t DecimalQuantity::toLong(bool truncateIfOverflow) const {
result = result * 10 + getDigitPos(magnitude - scale);
}
if (isNegative()) {
return -result;
return static_cast<int64_t>(-result);
}
return result;
return static_cast<int64_t>(result);
}
uint64_t DecimalQuantity::toFractionLong(bool includeTrailingZeros) const {

View file

@ -1,7 +1,6 @@
// © 2017 and later: Unicode, Inc. and others.
// License & terms of use: http://www.unicode.org/copyright.html
#include <unicode/numberformatter.h>
#include "unicode/utypes.h"
#if !UCONFIG_NO_FORMATTING

View file

@ -1,7 +1,6 @@
// © 2017 and later: Unicode, Inc. and others.
// License & terms of use: http://www.unicode.org/copyright.html
#include <unicode/numberformatter.h>
#include "unicode/utypes.h"
#if !UCONFIG_NO_FORMATTING

View file

@ -114,6 +114,10 @@ struct DecimalFormatWarehouse {
PropertiesAffixPatternProvider propertiesAPP;
CurrencyPluralInfoAffixProvider currencyPluralInfoAPP;
CurrencySymbols currencySymbols;
// Can't have std::atomic in public header files, so put it here in the warehouse.
std::atomic<numparse::impl::NumberParserImpl*> fAtomicParser = {};
std::atomic<numparse::impl::NumberParserImpl*> fAtomicCurrencyParser = {};
};

View file

@ -17,7 +17,8 @@ namespace impl {
/**
* Wraps a {@link Multiplier} for use in the number formatting pipeline.
*/
class MultiplierFormatHandler : public MicroPropsGenerator, public UMemory {
// Exported as U_I18N_API for tests
class U_I18N_API MultiplierFormatHandler : public MicroPropsGenerator, public UMemory {
public:
void setAndChain(const Scale& multiplier, const MicroPropsGenerator* parent);

View file

@ -116,7 +116,8 @@ getPatternForStyle(const Locale& locale, const char* nsName, CldrPatternStyle st
/** A very thin C++ wrapper around decNumber.h */
class DecNum : public UMemory {
// Exported as U_I18N_API for tests
class U_I18N_API DecNum : public UMemory {
public:
DecNum(); // leaves object in valid but undefined state

View file

@ -47,7 +47,8 @@ class CodePointMatcher : public NumberParseMatcher, public UMemory {
/**
* A warehouse to retain ownership of CodePointMatchers.
*/
class CodePointMatcherWarehouse : public UMemory {
// Exported as U_I18N_API for tests
class U_I18N_API CodePointMatcherWarehouse : public UMemory {
private:
static constexpr int32_t CODE_POINT_STACK_CAPACITY = 5; // Number of entries directly on the stack
static constexpr int32_t CODE_POINT_BATCH_SIZE = 10; // Number of entries per heap allocation
@ -92,7 +93,8 @@ struct AffixTokenMatcherSetupData {
*
* @author sffc
*/
class AffixTokenMatcherWarehouse : public UMemory {
// Exported as U_I18N_API for tests
class U_I18N_API AffixTokenMatcherWarehouse : public UMemory {
public:
AffixTokenMatcherWarehouse() = default; // WARNING: Leaves the object in an unusable state
@ -154,7 +156,8 @@ class AffixPatternMatcherBuilder : public TokenConsumer, public MutableMatcherCo
};
class AffixPatternMatcher : public ArraySeriesMatcher {
// Exported as U_I18N_API for tests
class U_I18N_API AffixPatternMatcher : public ArraySeriesMatcher {
public:
AffixPatternMatcher() = default; // WARNING: Leaves the object in an unusable state

View file

@ -61,7 +61,8 @@ class CompositionMatcher : public NumberParseMatcher {
* @author sffc
* @see AnyMatcher
*/
class SeriesMatcher : public CompositionMatcher {
// Exported as U_I18N_API for tests
class U_I18N_API SeriesMatcher : public CompositionMatcher {
public:
bool match(StringSegment& segment, ParsedNumber& result, UErrorCode& status) const override;
@ -82,7 +83,8 @@ class SeriesMatcher : public CompositionMatcher {
*
* The object adopts the array, but NOT the matchers contained inside the array.
*/
class ArraySeriesMatcher : public SeriesMatcher {
// Exported as U_I18N_API for tests
class U_I18N_API ArraySeriesMatcher : public SeriesMatcher {
public:
ArraySeriesMatcher(); // WARNING: Leaves the object in an unusable state

View file

@ -22,7 +22,8 @@
U_NAMESPACE_BEGIN namespace numparse {
namespace impl {
class NumberParserImpl : public MutableMatcherCollection {
// Exported as U_I18N_API for tests
class U_I18N_API NumberParserImpl : public MutableMatcherCollection {
public:
virtual ~NumberParserImpl();

View file

@ -72,7 +72,7 @@ double ParsedNumber::getDouble() const {
}
if (quantity.fitsInLong()) {
return quantity.toLong();
return static_cast<double>(quantity.toLong());
} else {
return quantity.toDouble();
}

View file

@ -44,7 +44,8 @@ class SymbolMatcher : public NumberParseMatcher, public UMemory {
};
class IgnorablesMatcher : public SymbolMatcher {
// Exported as U_I18N_API for tests
class U_I18N_API IgnorablesMatcher : public SymbolMatcher {
public:
IgnorablesMatcher() = default; // WARNING: Leaves the object in an unusable state
@ -74,7 +75,8 @@ class InfinityMatcher : public SymbolMatcher {
};
class MinusSignMatcher : public SymbolMatcher {
// Exported as U_I18N_API for tests
class U_I18N_API MinusSignMatcher : public SymbolMatcher {
public:
MinusSignMatcher() = default; // WARNING: Leaves the object in an unusable state
@ -118,7 +120,8 @@ class PaddingMatcher : public SymbolMatcher {
};
class PercentMatcher : public SymbolMatcher {
// Exported as U_I18N_API for tests
class U_I18N_API PercentMatcher : public SymbolMatcher {
public:
PercentMatcher() = default; // WARNING: Leaves the object in an unusable state
@ -144,7 +147,8 @@ class PermilleMatcher : public SymbolMatcher {
};
class PlusSignMatcher : public SymbolMatcher {
// Exported as U_I18N_API for tests
class U_I18N_API PlusSignMatcher : public SymbolMatcher {
public:
PlusSignMatcher() = default; // WARNING: Leaves the object in an unusable state

View file

@ -84,7 +84,8 @@ class CompactUnicodeString {
*
* @author sffc
*/
class ParsedNumber {
// Exported as U_I18N_API for tests
class U_I18N_API ParsedNumber {
public:
/**
@ -171,7 +172,8 @@ class ParsedNumber {
*
* @author sffc
*/
class StringSegment : public UMemory {
// Exported as U_I18N_API for tests
class U_I18N_API StringSegment : public UMemory {
public:
StringSegment(const UnicodeString& str, bool ignoreCase);
@ -282,7 +284,8 @@ class StringSegment : public UMemory {
*
* @author sffc
*/
class NumberParseMatcher {
// Exported as U_I18N_API for tests
class U_I18N_API NumberParseMatcher {
public:
/**
* Matchers can override this method to return true to indicate that they are optional and can be run

View file

@ -78,6 +78,14 @@ class NumberParserImpl;
// explicit template instantiation. see digitlst.h
// (When building DLLs for Windows this is required.)
#if U_PF_WINDOWS <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN
// Ignore warning 4661 as LocalPointerBase does not use operator== or operator!=
#pragma warning(suppress: 4661)
template class U_I18N_API LocalPointerBase<number::LocalizedNumberFormatter>;
template class U_I18N_API LocalPointer<number::LocalizedNumberFormatter>;
template class U_I18N_API LocalPointerBase<number::impl::DecimalFormatProperties>;
template class U_I18N_API LocalPointer<number::impl::DecimalFormatProperties>;
template class U_I18N_API LocalPointerBase<DecimalFormatSymbols>;
template class U_I18N_API LocalPointer<DecimalFormatSymbols>;
template class U_I18N_API EnumSet<UNumberFormatAttribute,
UNUM_MAX_NONBOOLEAN_ATTRIBUTE+1,
UNUM_LIMIT_BOOLEAN_ATTRIBUTE>;
@ -2144,11 +2152,11 @@ class U_I18N_API DecimalFormat : public NumberFormat {
*/
LocalPointer<number::impl::DecimalFormatProperties> fExportedProperties;
/** A field for a few additional helper object that need ownership. */
LocalPointer<number::impl::DecimalFormatWarehouse> fWarehouse;
std::atomic<numparse::impl::NumberParserImpl*> fAtomicParser = {};
std::atomic<numparse::impl::NumberParserImpl*> fAtomicCurrencyParser = {};
/**
* A field for a few additional helper object that need ownership.
* Can't be a LocalPointer because it is an internal class.
*/
number::impl::DecimalFormatWarehouse* fWarehouse;
// Data for fastpath
bool fCanUseFastFormat;

View file

@ -152,7 +152,7 @@ static void strToInt(
}
value = value * 10 - 0x30 + (int32_t) ch;
}
int32_t signedValue = neg ? -value : static_cast<int32_t>(value);
int32_t signedValue = neg ? static_cast<int32_t>(-value) : static_cast<int32_t>(value);
*static_cast<int32_t *>(intPtr) = signedValue;
}

View file

@ -367,7 +367,7 @@ void DecimalQuantityTest::testMaxDigits() {
assertEquals("Should trim, toPlainString", "76.54", dq.toPlainString());
assertEquals("Should trim, toScientificString", "7.654E+1", dq.toScientificString());
assertEquals("Should trim, toLong", 76LL, dq.toLong(true));
assertEquals("Should trim, toFractionLong", 54L, dq.toFractionLong(false));
assertEquals("Should trim, toFractionLong", 54LL, dq.toFractionLong(false));
assertEquals("Should trim, toDouble", 76.54, dq.toDouble());
// To test DecNum output, check the round-trip.
DecNum dn;